mirror of
https://github.com/zadam/trilium.git
synced 2025-10-26 07:46:30 +01:00
Compare commits
1873 Commits
v0.96.0
...
feat/add-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5332f015ef | ||
|
|
18f0f3ecac | ||
|
|
e7d745ac94 | ||
|
|
24abf7f0ed | ||
|
|
9a08f6534b | ||
|
|
c97c66ed8a | ||
|
|
b581025bbe | ||
|
|
7bc5331747 | ||
|
|
2415976475 | ||
|
|
8d0d0f0449 | ||
|
|
16b00ed160 | ||
|
|
df73a420f9 | ||
|
|
1e4d57f275 | ||
|
|
19a238c8d3 | ||
|
|
5ffd8a79eb | ||
|
|
58e58c192f | ||
|
|
5939344378 | ||
|
|
349f19fef7 | ||
|
|
d5777a024e | ||
|
|
b7f4ee6171 | ||
|
|
a83c4e3970 | ||
|
|
5a767dae34 | ||
|
|
9f93d30b99 | ||
|
|
dff525edc6 | ||
|
|
26da431320 | ||
|
|
cde4622693 | ||
|
|
a3d77421fd | ||
|
|
5ede7ecc69 | ||
|
|
4e755dc537 | ||
|
|
5351310a38 | ||
|
|
211ca43a82 | ||
|
|
e5235e7f22 | ||
|
|
e72298f0b4 | ||
|
|
3abf5c65c6 | ||
|
|
268acb0b88 | ||
|
|
196b3b873f | ||
|
|
4d9801a372 | ||
|
|
bd710ba665 | ||
|
|
afe369c876 | ||
|
|
206007bbce | ||
|
|
8ad05b92c0 | ||
|
|
735da2a855 | ||
|
|
980077f559 | ||
|
|
5daca270e4 | ||
|
|
e18813a4bf | ||
|
|
4aa7e211f3 | ||
|
|
419dc7edfb | ||
|
|
1d0503d0e4 | ||
|
|
f7f98aa9a3 | ||
|
|
575d14261a | ||
|
|
9aab606deb | ||
|
|
2e11681b52 | ||
|
|
8cca6637f7 | ||
|
|
82e076378c | ||
|
|
94ddad3c49 | ||
|
|
d35dbca18b | ||
|
|
7468d6147a | ||
|
|
7c78d749de | ||
|
|
85dd99a3c4 | ||
|
|
0a9c0234e2 | ||
|
|
fad77ba5a0 | ||
|
|
12723f3216 | ||
|
|
a43140515f | ||
|
|
3e3cc8c541 | ||
|
|
d1538508e8 | ||
|
|
9b1da8c311 | ||
|
|
e4a8258acf | ||
|
|
5e88043c7b | ||
|
|
bedf9112fb | ||
|
|
03681d23c5 | ||
|
|
aa191e110c | ||
|
|
dd09907925 | ||
|
|
35e9508bde | ||
|
|
4c8da70ef3 | ||
|
|
ed5da5cd4a | ||
|
|
dc5fccdbcd | ||
|
|
91aea333c7 | ||
|
|
a0de01cff1 | ||
|
|
a41ed34193 | ||
|
|
49e8811c18 | ||
|
|
488563a82e | ||
|
|
a1b18c7f97 | ||
|
|
9958a6e1bf | ||
|
|
1fc6d8aca7 | ||
|
|
3e9ec2d943 | ||
|
|
1420def1c3 | ||
|
|
3b4184e765 | ||
|
|
b70e25d348 | ||
|
|
772c0bbe1a | ||
|
|
144021c053 | ||
|
|
8abd3ed3f1 | ||
|
|
53ed510c92 | ||
|
|
4ec46a2ebd | ||
|
|
db6f948499 | ||
|
|
05c73011f5 | ||
|
|
3b733d01f1 | ||
|
|
ebf21296d4 | ||
|
|
6f83ac4822 | ||
|
|
d358924324 | ||
|
|
f9a3606ca2 | ||
|
|
33299ad51e | ||
|
|
8752182e7e | ||
|
|
0551ac8ead | ||
|
|
6d5a11bd4d | ||
|
|
ce19d84247 | ||
|
|
f24aa45a3b | ||
|
|
64a28a7e75 | ||
|
|
249a755312 | ||
|
|
a3d51a013c | ||
|
|
839def9959 | ||
|
|
fd432a7100 | ||
|
|
60a07ce1e7 | ||
|
|
88c5700d87 | ||
|
|
d59993abf6 | ||
|
|
0754011909 | ||
|
|
376bb66cab | ||
|
|
588e15c633 | ||
|
|
93b8ad20d7 | ||
|
|
e51b3d760d | ||
|
|
91f3bc4488 | ||
|
|
3e80a99bbf | ||
|
|
37cdb55e79 | ||
|
|
58b66c0c95 | ||
|
|
e5f9db86a1 | ||
|
|
f138f99356 | ||
|
|
c42f4b9814 | ||
|
|
0a9fb886e3 | ||
|
|
3c4577201f | ||
|
|
816421188f | ||
|
|
5b15d2c4c6 | ||
|
|
4bc7165452 | ||
|
|
82d6531e8c | ||
|
|
d6209035c3 | ||
|
|
1d7799f981 | ||
|
|
51291a61e6 | ||
|
|
0841603be0 | ||
|
|
59ba6a0b1e | ||
|
|
53eda46043 | ||
|
|
cbc9fb7d08 | ||
|
|
1f479b20be | ||
|
|
f00b8e9522 | ||
|
|
c7dd271516 | ||
|
|
a947a61d65 | ||
|
|
0122f1cc5e | ||
|
|
acb905a3e6 | ||
|
|
7422eb5598 | ||
|
|
e721166f95 | ||
|
|
5a48130fa4 | ||
|
|
b60fe1ad10 | ||
|
|
1405b0147c | ||
|
|
222a7a57bc | ||
|
|
cddf9f0242 | ||
|
|
3e17ff5e7b | ||
|
|
04973094f2 | ||
|
|
018a6cb84a | ||
|
|
44825af0c0 | ||
|
|
cfb3607052 | ||
|
|
c5ec928aac | ||
|
|
8d0183a9fb | ||
|
|
ecd4079871 | ||
|
|
3ed975f2e6 | ||
|
|
c6deb537d5 | ||
|
|
e7b3d806a7 | ||
|
|
d1a0778b48 | ||
|
|
378634567f | ||
|
|
ed56ed2be0 | ||
|
|
648aa7e3b0 | ||
|
|
73ff41f2b2 | ||
|
|
3837466cb3 | ||
|
|
b97a5ef888 | ||
|
|
2ff1276ebb | ||
|
|
227cf5de85 | ||
|
|
ccf52be431 | ||
|
|
07713e988c | ||
|
|
f934318625 | ||
|
|
6fb90abd75 | ||
|
|
27cc33888a | ||
|
|
95af901808 | ||
|
|
c5a7f84250 | ||
|
|
a71d28500d | ||
|
|
436fd16f3a | ||
|
|
ca34bf42f6 | ||
|
|
fbf2315f57 | ||
|
|
72f50dcb6b | ||
|
|
fd4c2f79a7 | ||
|
|
72f9335213 | ||
|
|
53d97047a3 | ||
|
|
2ba3666e23 | ||
|
|
4a1d379ab4 | ||
|
|
73167e1e30 | ||
|
|
ffc13f5de3 | ||
|
|
9ba23d49d8 | ||
|
|
222a6c48a7 | ||
|
|
e33208e6ec | ||
|
|
af8781eaa7 | ||
|
|
167b1a8d2e | ||
|
|
0a7aff507c | ||
|
|
103532aad9 | ||
|
|
16939e9fd5 | ||
|
|
4ef6169041 | ||
|
|
9ebee42118 | ||
|
|
234d3997b1 | ||
|
|
3ba0bcea4e | ||
|
|
701855344e | ||
|
|
71b627fbc7 | ||
|
|
5a4fc2c690 | ||
|
|
0d67db52a2 | ||
|
|
d971554201 | ||
|
|
8fd7d7176e | ||
|
|
675575eed9 | ||
|
|
2122cde293 | ||
|
|
b68a554bba | ||
|
|
33043c7133 | ||
|
|
2e0f606a7a | ||
|
|
87878dd6a7 | ||
|
|
5296e073cc | ||
|
|
7bfb7d6f6e | ||
|
|
b5069cc7c2 | ||
|
|
3b6791f51a | ||
|
|
0b0be77e02 | ||
|
|
60db10559e | ||
|
|
76b066ba4a | ||
|
|
a28db32369 | ||
|
|
2523632391 | ||
|
|
53548c356a | ||
|
|
565904ff5d | ||
|
|
e0c5545f8c | ||
|
|
bc21285289 | ||
|
|
bbf8d757cd | ||
|
|
318d504fad | ||
|
|
fd5038148c | ||
|
|
693ca9291e | ||
|
|
cfd8afc226 | ||
|
|
3e52ca7600 | ||
|
|
482522e802 | ||
|
|
8b5b6a01c6 | ||
|
|
5614891d92 | ||
|
|
b9b4961f3c | ||
|
|
7b83b20339 | ||
|
|
e4403dd316 | ||
|
|
3f267fe6c9 | ||
|
|
3229471485 | ||
|
|
62bac1adf9 | ||
|
|
82becfd52a | ||
|
|
92f035545b | ||
|
|
74d8ea7dcb | ||
|
|
ac3f087279 | ||
|
|
1cc4eb98c1 | ||
|
|
e99bdf8f24 | ||
|
|
b4f521a141 | ||
|
|
1e23bc09f1 | ||
|
|
e3ec90405d | ||
|
|
41c87794a4 | ||
|
|
e62d2d4fda | ||
|
|
93adaa0f52 | ||
|
|
263a5d2067 | ||
|
|
f0a5005794 | ||
|
|
577457c8ab | ||
|
|
c0c450c444 | ||
|
|
1e1e0b0f51 | ||
|
|
a19204a1d5 | ||
|
|
1d139bfdfe | ||
|
|
75072decec | ||
|
|
0cf2ad6901 | ||
|
|
ccbd57a0c0 | ||
|
|
92e6c8c445 | ||
|
|
1e966f1d59 | ||
|
|
6872c2194e | ||
|
|
5b6a0216db | ||
|
|
e9a7194cd6 | ||
|
|
26898b9122 | ||
|
|
3e00e490cf | ||
|
|
c02ed17ebc | ||
|
|
fb559d66fe | ||
|
|
25dce64c3b | ||
|
|
6f19fde76e | ||
|
|
33ae91f49c | ||
|
|
99c179e29a | ||
|
|
1dbcb5a027 | ||
|
|
54d613e00e | ||
|
|
1f8aa90482 | ||
|
|
c9dcbef014 | ||
|
|
68086ec3f1 | ||
|
|
f62078d02b | ||
|
|
ab1d8594ea | ||
|
|
c368ec3c38 | ||
|
|
1a15782686 | ||
|
|
3bd0aeef77 | ||
|
|
b463baedd2 | ||
|
|
ae77c41dab | ||
|
|
807d909acd | ||
|
|
fa4f5f526e | ||
|
|
edff43cdb3 | ||
|
|
46fe45528c | ||
|
|
b4b53da6a4 | ||
|
|
41fd270080 | ||
|
|
410bb3cdca | ||
|
|
bc6fc24fbd | ||
|
|
c039f06c2b | ||
|
|
520effbbb7 | ||
|
|
a42d780724 | ||
|
|
da92255dd6 | ||
|
|
cce3d3bce8 | ||
|
|
f524e99290 | ||
|
|
ba19fc7cf3 | ||
|
|
22c3de582f | ||
|
|
48896e67cb | ||
|
|
16cd91eb02 | ||
|
|
7e03774b8e | ||
|
|
a04f6e3858 | ||
|
|
96eb1be556 | ||
|
|
f8e20a1405 | ||
|
|
c67c3a6861 | ||
|
|
d04897e011 | ||
|
|
558ae1a2ea | ||
|
|
64bffb82b1 | ||
|
|
81ac390eab | ||
|
|
0db556fac2 | ||
|
|
2793df06c4 | ||
|
|
e7b448e2bc | ||
|
|
d2bc72d54f | ||
|
|
83b22b4861 | ||
|
|
d42a949602 | ||
|
|
83e1512b59 | ||
|
|
ba6a1ec584 | ||
|
|
6685e583f2 | ||
|
|
d6032c912e | ||
|
|
25527ecc21 | ||
|
|
e0e7bd42cc | ||
|
|
fbc1af56ed | ||
|
|
8ff108db9e | ||
|
|
1dfcf960d3 | ||
|
|
9bdc51a3fb | ||
|
|
dbf3bcfacf | ||
|
|
3d5b269315 | ||
|
|
48f97da9cc | ||
|
|
9c954fbd81 | ||
|
|
c6bd41654f | ||
|
|
d65a74bb23 | ||
|
|
ff08bca042 | ||
|
|
a5d3d2e3b4 | ||
|
|
496a0667ee | ||
|
|
9be688b667 | ||
|
|
f3d9008c61 | ||
|
|
649a43c978 | ||
|
|
50568704ca | ||
|
|
b66b4dec83 | ||
|
|
8d0e807435 | ||
|
|
bf05ed7caf | ||
|
|
b5080eff00 | ||
|
|
c474769dd6 | ||
|
|
a6ae01da0b | ||
|
|
2bf4c44dbf | ||
|
|
5ca0fbba13 | ||
|
|
4cd84b2019 | ||
|
|
c502a45cf5 | ||
|
|
9e66914306 | ||
|
|
d33d27ee82 | ||
|
|
e2b13573ae | ||
|
|
ec74f5f1de | ||
|
|
5dee56debc | ||
|
|
5623fc992d | ||
|
|
1d28bfc570 | ||
|
|
084327e973 | ||
|
|
b2885efdc1 | ||
|
|
b65a75f138 | ||
|
|
0ee7f50bb4 | ||
|
|
02ce21bc18 | ||
|
|
3ba487bb00 | ||
|
|
384a89b0e3 | ||
|
|
e7fd9371b6 | ||
|
|
aa83429816 | ||
|
|
221ab02c24 | ||
|
|
0c4b751e8f | ||
|
|
43fd0924a1 | ||
|
|
7a036fc777 | ||
|
|
54efa6b38c | ||
|
|
6e37c9ee5a | ||
|
|
963f4586f3 | ||
|
|
4d0edebed3 | ||
|
|
cb39e8d0f8 | ||
|
|
a336f472b8 | ||
|
|
0a097e72be | ||
|
|
077f10af7b | ||
|
|
9317658fc7 | ||
|
|
21a13f2124 | ||
|
|
db6658c05f | ||
|
|
653af0bc06 | ||
|
|
93c5281af7 | ||
|
|
ce28fbc968 | ||
|
|
eb41c45711 | ||
|
|
17ab14e098 | ||
|
|
a42f7b4ece | ||
|
|
c7d69fa66b | ||
|
|
1da5c083ee | ||
|
|
4fb911da40 | ||
|
|
881417f860 | ||
|
|
9748b8bf94 | ||
|
|
337326da2b | ||
|
|
a088134d9b | ||
|
|
e49100f3f4 | ||
|
|
3c638e1574 | ||
|
|
9131edf021 | ||
|
|
52a1318475 | ||
|
|
5a7483d7c7 | ||
|
|
41f2748829 | ||
|
|
66bd5268ca | ||
|
|
ebef134af7 | ||
|
|
1173bf22ab | ||
|
|
e8f6828168 | ||
|
|
02c9339f9c | ||
|
|
c72bf42684 | ||
|
|
f42eeb7ee8 | ||
|
|
3d876121cc | ||
|
|
f9bcd7d90a | ||
|
|
b3af14fccb | ||
|
|
d224f33913 | ||
|
|
3a5f33ba91 | ||
|
|
e1ae8701b2 | ||
|
|
aff5a4d0d5 | ||
|
|
17467a9c29 | ||
|
|
ebed661863 | ||
|
|
c2e9f4764b | ||
|
|
7e5b87f00a | ||
|
|
70182e863c | ||
|
|
f0d30c4e34 | ||
|
|
013e7a6aa4 | ||
|
|
1b25b18d9e | ||
|
|
72ff384187 | ||
|
|
bac048f60f | ||
|
|
d8d0a64134 | ||
|
|
b2db87db4e | ||
|
|
1baaee582e | ||
|
|
9212b72351 | ||
|
|
24af820477 | ||
|
|
6c4c2d22c6 | ||
|
|
2e9b20be71 | ||
|
|
3216de5d89 | ||
|
|
4bf7cb8099 | ||
|
|
4871dbd7ef | ||
|
|
e125809fe0 | ||
|
|
27b80b573f | ||
|
|
38d6ae87b6 | ||
|
|
1a7cbc13e0 | ||
|
|
8e4691d4a4 | ||
|
|
b371337ed2 | ||
|
|
4d4b76ce39 | ||
|
|
289d3e9882 | ||
|
|
a57eb8f27f | ||
|
|
27023f1fd5 | ||
|
|
20a152993f | ||
|
|
ba7636db75 | ||
|
|
e3e51a2e1f | ||
|
|
93b601fe98 | ||
|
|
203ebb0e7a | ||
|
|
041c2e5693 | ||
|
|
258c0d511e | ||
|
|
15705553c7 | ||
|
|
27f023e399 | ||
|
|
0d2242171c | ||
|
|
0c62ecda65 | ||
|
|
7cd7fec93b | ||
|
|
cfab5e6217 | ||
|
|
0c313e8b8f | ||
|
|
61366061e6 | ||
|
|
b2c0685c09 | ||
|
|
e3ee284e91 | ||
|
|
58901855af | ||
|
|
c7f8a49c47 | ||
|
|
10685fe183 | ||
|
|
9e514fe95e | ||
|
|
f28a319e26 | ||
|
|
decfb58142 | ||
|
|
415bbc3b0a | ||
|
|
5b669ca287 | ||
|
|
1700217241 | ||
|
|
f00c0d5d73 | ||
|
|
64ce0d2911 | ||
|
|
82dce7a0d3 | ||
|
|
b94f67aa72 | ||
|
|
1ff77a1464 | ||
|
|
adb0e1e844 | ||
|
|
2043a06a48 | ||
|
|
738ebb66ac | ||
|
|
abf1f6c041 | ||
|
|
7db0e90506 | ||
|
|
400f9cf911 | ||
|
|
2d3b99c959 | ||
|
|
fd1ea05c78 | ||
|
|
d7c4b8f530 | ||
|
|
238f358d6a | ||
|
|
50afdca150 | ||
|
|
b5555d94f5 | ||
|
|
3d81633214 | ||
|
|
5db7997a17 | ||
|
|
71dd428919 | ||
|
|
a20d66a6b5 | ||
|
|
3caefa5409 | ||
|
|
a6e56be55a | ||
|
|
6d582f09be | ||
|
|
40cd46cd09 | ||
|
|
3cc59149cf | ||
|
|
e659266d62 | ||
|
|
14e09f5ea0 | ||
|
|
11f6462a31 | ||
|
|
48eebbe2fe | ||
|
|
f7093c035b | ||
|
|
b25e9cdee6 | ||
|
|
5cd7e4707a | ||
|
|
861374bb87 | ||
|
|
d3519b3059 | ||
|
|
da1f18c60f | ||
|
|
b7482f2a6a | ||
|
|
fd616cafca | ||
|
|
b262a5181f | ||
|
|
adb54a9054 | ||
|
|
5eb05f5550 | ||
|
|
2950c5eaa4 | ||
|
|
16fd67c070 | ||
|
|
9e3559f97c | ||
|
|
83eea30ea0 | ||
|
|
6ceccf1c7a | ||
|
|
31e1c4c712 | ||
|
|
fa97ec6c72 | ||
|
|
cd5467bf5c | ||
|
|
899f85f4e7 | ||
|
|
7c79fbefa6 | ||
|
|
18c6fe7ebd | ||
|
|
6f6643d758 | ||
|
|
356adebbce | ||
|
|
5c8e4fd6fd | ||
|
|
5be9bb47a7 | ||
|
|
60c5dc525b | ||
|
|
abfffcec07 | ||
|
|
09b12052f0 | ||
|
|
78bb0ab016 | ||
|
|
4cd4c2f607 | ||
|
|
f95b5d6f14 | ||
|
|
4a53be1e33 | ||
|
|
cbbe845d7b | ||
|
|
b2b52e92a4 | ||
|
|
15a97a4675 | ||
|
|
a01f25ec12 | ||
|
|
2f175765ec | ||
|
|
6a7ae72b1b | ||
|
|
e396bb1641 | ||
|
|
baedac4746 | ||
|
|
268ef626ca | ||
|
|
40c7ad4b46 | ||
|
|
54f9ce87f9 | ||
|
|
12b8a70e5c | ||
|
|
acf204d0e3 | ||
|
|
ee19f9ccaa | ||
|
|
34c0cf33b9 | ||
|
|
34ec624e46 | ||
|
|
056d3f9f36 | ||
|
|
040673af0b | ||
|
|
48fb0c5e21 | ||
|
|
4c1a55708f | ||
|
|
6e1951b356 | ||
|
|
3dd6b05d2e | ||
|
|
05f1ae01f3 | ||
|
|
3975041798 | ||
|
|
3a29d65777 | ||
|
|
eeeecb3988 | ||
|
|
28ababcbb9 | ||
|
|
f382943af3 | ||
|
|
fa38332a6c | ||
|
|
5a58fcde96 | ||
|
|
62d048433b | ||
|
|
db4ba53449 | ||
|
|
da20916767 | ||
|
|
b1e12182ce | ||
|
|
80b2061935 | ||
|
|
8ce92f8c93 | ||
|
|
05cd8cb547 | ||
|
|
6e7d0bc51b | ||
|
|
b9aede23e6 | ||
|
|
1d52988826 | ||
|
|
ebe29f41f9 | ||
|
|
598591a2da | ||
|
|
32c2860b68 | ||
|
|
d975790e79 | ||
|
|
3e1f74ae93 | ||
|
|
81a8908b98 | ||
|
|
892dfe2340 | ||
|
|
fd175eb8a8 | ||
|
|
c98f6d96d5 | ||
|
|
35b628e799 | ||
|
|
49b79c016d | ||
|
|
4d28df7a89 | ||
|
|
25a9a8a724 | ||
|
|
313a61ec48 | ||
|
|
a2eab03ee2 | ||
|
|
a563b1c9a0 | ||
|
|
20018b9c21 | ||
|
|
0a9bd5f6d1 | ||
|
|
911fee0213 | ||
|
|
ffe4b53eee | ||
|
|
cd5a68d230 | ||
|
|
95a2a69e0a | ||
|
|
360b5d6de4 | ||
|
|
bf50883e40 | ||
|
|
8e04690568 | ||
|
|
bd6c690160 | ||
|
|
c0d7278827 | ||
|
|
f9eb0a20f7 | ||
|
|
8d27a5aa39 | ||
|
|
90f9416524 | ||
|
|
ae0af8b9c7 | ||
|
|
a03a0f8a75 | ||
|
|
f0f27a9065 | ||
|
|
181d5ee36a | ||
|
|
2758a230ac | ||
|
|
a46d32ed75 | ||
|
|
b2bcae8b74 | ||
|
|
49d662afba | ||
|
|
a593ce7c40 | ||
|
|
31fbf2cb57 | ||
|
|
c0d3027e65 | ||
|
|
bde270b73f | ||
|
|
edd18b53d0 | ||
|
|
2ad4b26c9e | ||
|
|
f39a5c55ba | ||
|
|
0af5feab79 | ||
|
|
68dd54a100 | ||
|
|
7a0f148d28 | ||
|
|
958b1592f8 | ||
|
|
7ac0828ae7 | ||
|
|
f7e7b38551 | ||
|
|
33e3112290 | ||
|
|
2a27666c53 | ||
|
|
f2d45cb780 | ||
|
|
c4b91c9777 | ||
|
|
fa06f56f5d | ||
|
|
519b962af3 | ||
|
|
31e6ac2349 | ||
|
|
ed3ba2745f | ||
|
|
f5b7648d6d | ||
|
|
2d537b82f6 | ||
|
|
073354fe04 | ||
|
|
165d093928 | ||
|
|
e8cf3f4a10 | ||
|
|
2a40d6bb7e | ||
|
|
f196a78728 | ||
|
|
523c7ac273 | ||
|
|
c36b00994b | ||
|
|
76b856bfe5 | ||
|
|
7b084035a3 | ||
|
|
59fbdaa879 | ||
|
|
ce324586f8 | ||
|
|
35bd210062 | ||
|
|
0cfe3351bb | ||
|
|
7202f47716 | ||
|
|
bde4545afc | ||
|
|
b3c81ce5f2 | ||
|
|
02b0d1fb5e | ||
|
|
87d9ea06f3 | ||
|
|
a4e6a964c9 | ||
|
|
79c5d479fc | ||
|
|
8f0a9f91c1 | ||
|
|
93fae9cc8c | ||
|
|
1046321117 | ||
|
|
00fc92764b | ||
|
|
dea8bc307e | ||
|
|
18a4fbaa4b | ||
|
|
3efc4b13d5 | ||
|
|
952456a69c | ||
|
|
bde8e17fe6 | ||
|
|
9023ba1d0a | ||
|
|
61f9a86685 | ||
|
|
5520cfed5d | ||
|
|
43df984732 | ||
|
|
3f398c1a00 | ||
|
|
ad35e3b48f | ||
|
|
73ee44e177 | ||
|
|
18414cd155 | ||
|
|
652d78ac68 | ||
|
|
9a3ab05d73 | ||
|
|
fe238b8afd | ||
|
|
94492c7535 | ||
|
|
47caf970a1 | ||
|
|
3e75ab39c2 | ||
|
|
72aacdbf6f | ||
|
|
5461dafe02 | ||
|
|
30f9f66b8b | ||
|
|
19de803142 | ||
|
|
11b247fe07 | ||
|
|
faa40494d8 | ||
|
|
796802aea0 | ||
|
|
06af5cf6d5 | ||
|
|
81a99c1e44 | ||
|
|
1b384f35d2 | ||
|
|
c1259f2ea2 | ||
|
|
92d9c82d97 | ||
|
|
064f0ef921 | ||
|
|
e9a9b462d4 | ||
|
|
98888d5f1d | ||
|
|
134c869b07 | ||
|
|
beb0487513 | ||
|
|
aa9ffb8f6b | ||
|
|
18eb704b81 | ||
|
|
83fb62d4df | ||
|
|
cb650b70cb | ||
|
|
d5e42318dd | ||
|
|
24ed474c8c | ||
|
|
a9c25b4edd | ||
|
|
c89737ae7b | ||
|
|
e619a6ef7c | ||
|
|
6a2a096348 | ||
|
|
bf34ef2009 | ||
|
|
583ab8dc92 | ||
|
|
db1619af31 | ||
|
|
9cddb9ac1d | ||
|
|
d72d3db2a0 | ||
|
|
22740a6c8d | ||
|
|
e9409577db | ||
|
|
9cef8c8e70 | ||
|
|
53bcec602d | ||
|
|
a62f12b427 | ||
|
|
e20816a7ce | ||
|
|
58535df676 | ||
|
|
057040af06 | ||
|
|
c603783a44 | ||
|
|
1928356ad5 | ||
|
|
e53ad2c62a | ||
|
|
bca397e3e4 | ||
|
|
14b3bea203 | ||
|
|
05c26d17d3 | ||
|
|
51360d855a | ||
|
|
ae7d03e3c7 | ||
|
|
164feaa3ec | ||
|
|
4d09fabad8 | ||
|
|
87e1ce64d1 | ||
|
|
04913394c6 | ||
|
|
f8b563704f | ||
|
|
5d9bd0f6d3 | ||
|
|
1229c26098 | ||
|
|
77818d5453 | ||
|
|
f9c7c5637b | ||
|
|
5d55b0b0a8 | ||
|
|
b2d7fbbcad | ||
|
|
fbc6734e08 | ||
|
|
a83172390f | ||
|
|
4b1fd5e4a0 | ||
|
|
51495b282f | ||
|
|
b645d21fcd | ||
|
|
8f99ce7d14 | ||
|
|
6eb650bb22 | ||
|
|
a7f5702221 | ||
|
|
efeb9b90ca | ||
|
|
3361a2e4ab | ||
|
|
425ade5212 | ||
|
|
384ab1d1f3 | ||
|
|
70b1a37285 | ||
|
|
61a878e2a0 | ||
|
|
319cb8384c | ||
|
|
2d358342c5 | ||
|
|
dd7ee05388 | ||
|
|
6c79be881d | ||
|
|
51a8937c64 | ||
|
|
c436455b32 | ||
|
|
f740edae91 | ||
|
|
18f89b979d | ||
|
|
8094259c78 | ||
|
|
b4f503b81e | ||
|
|
4db04519bd | ||
|
|
464c2bdf28 | ||
|
|
8007bac8b8 | ||
|
|
7a1ec266ad | ||
|
|
42fedaa241 | ||
|
|
4387bd4c6f | ||
|
|
51e1367b82 | ||
|
|
8bea3f4422 | ||
|
|
0eb2e405ff | ||
|
|
5dbd4a765f | ||
|
|
f6961c7e06 | ||
|
|
8d3ba90072 | ||
|
|
3772412d82 | ||
|
|
84389f467e | ||
|
|
eb41e0f96f | ||
|
|
2d44dff997 | ||
|
|
1483bf3d46 | ||
|
|
064cf6a3ee | ||
|
|
0c0d5eaa0a | ||
|
|
afecb33b5c | ||
|
|
fbb1e3a302 | ||
|
|
8704350359 | ||
|
|
d09e725d98 | ||
|
|
8be5b149c4 | ||
|
|
faeea6af18 | ||
|
|
3fa5ea1010 | ||
|
|
6aa31ae125 | ||
|
|
27f2e9c286 | ||
|
|
67cc36fdd2 | ||
|
|
ef7297e03b | ||
|
|
97a5314cdb | ||
|
|
a1195a2856 | ||
|
|
81419c6fe3 | ||
|
|
b8da793353 | ||
|
|
8140fa79cc | ||
|
|
abff4fe67d | ||
|
|
ec8f737eba | ||
|
|
cc6688ea00 | ||
|
|
c448b29be7 | ||
|
|
61bde294b3 | ||
|
|
acab81c61e | ||
|
|
1dd965973b | ||
|
|
d61981033f | ||
|
|
30197ba7ce | ||
|
|
1b6c957334 | ||
|
|
fb7a397bf9 | ||
|
|
133c9c5a7b | ||
|
|
8a587d4d21 | ||
|
|
29b813fa3b | ||
|
|
1dfe27d3df | ||
|
|
cda8fc7146 | ||
|
|
acb16f751b | ||
|
|
a1ac276be5 | ||
|
|
54e3ab5139 | ||
|
|
baf341b312 | ||
|
|
5b074c2e22 | ||
|
|
11d086ef12 | ||
|
|
0e6b10e400 | ||
|
|
0240222998 | ||
|
|
7fc739487f | ||
|
|
f6e275709f | ||
|
|
7e01dfd220 | ||
|
|
d5866a99ec | ||
|
|
5289d41b12 | ||
|
|
030178cad2 | ||
|
|
5d00630452 | ||
|
|
eb805bfa2a | ||
|
|
ee3a8e105e | ||
|
|
97fb273e7f | ||
|
|
2ef9009384 | ||
|
|
27c7888628 | ||
|
|
b4de37a9f4 | ||
|
|
1c5ebb54f8 | ||
|
|
f3e69dd6bd | ||
|
|
66364f5ce0 | ||
|
|
f25a1fb865 | ||
|
|
62c5b8b1fc | ||
|
|
2b0de37fc0 | ||
|
|
23ef73fe2f | ||
|
|
92ac3ee4ef | ||
|
|
a3ba5ca109 | ||
|
|
5b4e81cf18 | ||
|
|
772e6f5ebc | ||
|
|
60a9428b8b | ||
|
|
a7752a8421 | ||
|
|
aefa2315b7 | ||
|
|
37a79aeeab | ||
|
|
5bc4bdaeef | ||
|
|
5e28df883d | ||
|
|
0a57748075 | ||
|
|
45e3eee642 | ||
|
|
d724a80c2a | ||
|
|
5ea8c94d18 | ||
|
|
769bc760b3 | ||
|
|
f04f45ea62 | ||
|
|
a5cab6a2a2 | ||
|
|
138611beaf | ||
|
|
e1b608057a | ||
|
|
fed6d8329f | ||
|
|
9d03d52f28 | ||
|
|
055e11174d | ||
|
|
8fda2dd7f1 | ||
|
|
ea03695c75 | ||
|
|
17b206fc72 | ||
|
|
4ec8c5963a | ||
|
|
ab2d8accf5 | ||
|
|
de8b7e9ebe | ||
|
|
18d11523a6 | ||
|
|
7a0ab3c025 | ||
|
|
3575a7dc93 | ||
|
|
bb9e7b1c6e | ||
|
|
115e9e0202 | ||
|
|
e341de70c0 | ||
|
|
1d1a0ac4fd | ||
|
|
d48470ffb1 | ||
|
|
6574ca42a3 | ||
|
|
303ff35a76 | ||
|
|
e0850958b0 | ||
|
|
13115b9ed1 | ||
|
|
933a11e9db | ||
|
|
6915993a35 | ||
|
|
237a4e9a74 | ||
|
|
1565a0fd80 | ||
|
|
e8b16287e0 | ||
|
|
c09e124805 | ||
|
|
b6f55b0e1a | ||
|
|
964bc74b83 | ||
|
|
fa9b142cb7 | ||
|
|
7e3f412c84 | ||
|
|
82e16a5624 | ||
|
|
757488a95b | ||
|
|
d7f154cfd1 | ||
|
|
3517715aab | ||
|
|
d10bbdd7a7 | ||
|
|
c4ec27bb1e | ||
|
|
0b24553ace | ||
|
|
793867269b | ||
|
|
9508e92676 | ||
|
|
89378eae7b | ||
|
|
ace166a925 | ||
|
|
d59d544c0f | ||
|
|
37461d0eb3 | ||
|
|
126152ff63 | ||
|
|
60e19de0d1 | ||
|
|
3247a9facc | ||
|
|
7b114bed26 | ||
|
|
30ffbc760e | ||
|
|
4420913049 | ||
|
|
3762690c5f | ||
|
|
d684ac40d8 | ||
|
|
d217379644 | ||
|
|
d5f7fa2fe5 | ||
|
|
3e0ef10b25 | ||
|
|
28f88f2407 | ||
|
|
e525a7a0ff | ||
|
|
3415f38e0a | ||
|
|
910c0faade | ||
|
|
4ad1bb5e3a | ||
|
|
97f6f0a945 | ||
|
|
bc78c17a11 | ||
|
|
b8e813f7bd | ||
|
|
db3581eb26 | ||
|
|
d23230df68 | ||
|
|
b29781b614 | ||
|
|
7d7c3e7cdb | ||
|
|
cbd8cb80ab | ||
|
|
bfcdc34faf | ||
|
|
c728e6047d | ||
|
|
4c53a9ba8c | ||
|
|
e10a7da7e3 | ||
|
|
5cc431b1bf | ||
|
|
734aa2fcb5 | ||
|
|
5e37319d9b | ||
|
|
2e9eb6e3e9 | ||
|
|
9ce57b123a | ||
|
|
e793168afa | ||
|
|
d1513424e7 | ||
|
|
1436a01dbe | ||
|
|
b9b936b92a | ||
|
|
adf14bec31 | ||
|
|
ca1403ffea | ||
|
|
06672e439e | ||
|
|
e851701a9e | ||
|
|
9589164008 | ||
|
|
a88b067081 | ||
|
|
b3777e6900 | ||
|
|
d2646e291d | ||
|
|
99ab9ee66b | ||
|
|
08678e74e6 | ||
|
|
62de52ab17 | ||
|
|
d9820d9725 | ||
|
|
fe8a8eeac9 | ||
|
|
dfeb414aff | ||
|
|
69f12a2916 | ||
|
|
2b062e938e | ||
|
|
e0299bd1ae | ||
|
|
ac2f1b56fe | ||
|
|
06d98f6fcf | ||
|
|
bb660d15b2 | ||
|
|
4d73cdefef | ||
|
|
313ba3df80 | ||
|
|
15377c32c2 | ||
|
|
22b52f7c4a | ||
|
|
7055f77c91 | ||
|
|
051fe67176 | ||
|
|
90accfcc48 | ||
|
|
4f99db0c90 | ||
|
|
aeb356bf54 | ||
|
|
0dffa0f333 | ||
|
|
d17f5b8447 | ||
|
|
b5a57b3c66 | ||
|
|
987a3404a9 | ||
|
|
eddc30769f | ||
|
|
4d455650ba | ||
|
|
e2157aab26 | ||
|
|
b277f4bf3f | ||
|
|
4047452b0f | ||
|
|
cb37724879 | ||
|
|
8890893412 | ||
|
|
d0cbda7c0d | ||
|
|
60e7b9ffb0 | ||
|
|
45457c6f76 | ||
|
|
737f41d92b | ||
|
|
180841f364 | ||
|
|
bea40d4c2f | ||
|
|
5f9a054441 | ||
|
|
f90bf1ce7c | ||
|
|
8c4ed2d4da | ||
|
|
0e590a1bbf | ||
|
|
218a096135 | ||
|
|
8407bce370 | ||
|
|
43229f0b99 | ||
|
|
84fa0002b9 | ||
|
|
e79c705b20 | ||
|
|
894d7ce15d | ||
|
|
5830880582 | ||
|
|
caab0f70ff | ||
|
|
641966fcdd | ||
|
|
24c22e9bbf | ||
|
|
795f597bda | ||
|
|
2228663a7e | ||
|
|
0c97df357d | ||
|
|
19f63f1be0 | ||
|
|
fc000caf73 | ||
|
|
78929e0293 | ||
|
|
71e22da987 | ||
|
|
24e99d9654 | ||
|
|
98299da424 | ||
|
|
7014af66b6 | ||
|
|
659bd90027 | ||
|
|
146b0c284b | ||
|
|
4a0ac8807f | ||
|
|
d67734832e | ||
|
|
1673bf026a | ||
|
|
1f29b000a9 | ||
|
|
a6d024123e | ||
|
|
fb1a7239ce | ||
|
|
4f71d508cb | ||
|
|
2072bd61d1 | ||
|
|
6021178b7d | ||
|
|
179b0be2bb | ||
|
|
bf2b45dd4a | ||
|
|
513561234c | ||
|
|
33da990ae7 | ||
|
|
4003946e68 | ||
|
|
21f8d40789 | ||
|
|
d6c698e1d6 | ||
|
|
6c227852ae | ||
|
|
29cb22c4fd | ||
|
|
d040bc9e2d | ||
|
|
abb92f23a6 | ||
|
|
da5c86bb69 | ||
|
|
a0d428b12c | ||
|
|
e22fe20e23 | ||
|
|
1e6659aff9 | ||
|
|
60b32d5b05 | ||
|
|
e2ee9053a0 | ||
|
|
d2f0422ecc | ||
|
|
bfd97da626 | ||
|
|
1fd163f0bb | ||
|
|
d15ce575df | ||
|
|
9999ff5a89 | ||
|
|
4653941082 | ||
|
|
fa509661ab | ||
|
|
d9a289bf18 | ||
|
|
98c76b713d | ||
|
|
05ed917a56 | ||
|
|
b833806ec7 | ||
|
|
7fdef3418a | ||
|
|
49e14ec542 | ||
|
|
efd9244684 | ||
|
|
318f2d1f8c | ||
|
|
92fa1cf052 | ||
|
|
17c6eb1680 | ||
|
|
7c6af568d8 | ||
|
|
23c9c6826e | ||
|
|
b08fda5e10 | ||
|
|
5ec3a49377 | ||
|
|
1c728ae432 | ||
|
|
fd25c735c1 | ||
|
|
7de33907c5 | ||
|
|
ec021be16c | ||
|
|
8b6826ffa4 | ||
|
|
00cc1ffe74 | ||
|
|
2384fdbaad | ||
|
|
08a93d81d7 | ||
|
|
86911100df | ||
|
|
ff01656268 | ||
|
|
d0ea6d9e8d | ||
|
|
96ca3d5e38 | ||
|
|
3a569499cb | ||
|
|
545b19f978 | ||
|
|
d98be19c9a | ||
|
|
4826898c55 | ||
|
|
482b592f77 | ||
|
|
939ebfe47b | ||
|
|
c6dee1339b | ||
|
|
23f8c3ad3c | ||
|
|
81c1b88376 | ||
|
|
c4a85db698 | ||
|
|
e6eda45c04 | ||
|
|
a3014434cf | ||
|
|
3ebab2c126 | ||
|
|
954619bd36 | ||
|
|
eb76362de4 | ||
|
|
1cde14859b | ||
|
|
c752b98995 | ||
|
|
1f792ca418 | ||
|
|
b22e08b1eb | ||
|
|
2b5029cc38 | ||
|
|
9e936cb57b | ||
|
|
e8fd2c1b3c | ||
|
|
977fbf54ee | ||
|
|
3e5c91415d | ||
|
|
d60b855f74 | ||
|
|
4146192b6d | ||
|
|
26ee0ff48f | ||
|
|
6995fbfd06 | ||
|
|
1763d80d5f | ||
|
|
a594e5147c | ||
|
|
e51ea1a619 | ||
|
|
83b72eafa6 | ||
|
|
757a6777be | ||
|
|
37c9260dca | ||
|
|
e1a8f4f5db | ||
|
|
b7b0b39afc | ||
|
|
af797489e8 | ||
|
|
d003e91b89 | ||
|
|
4a35df745a | ||
|
|
b1b756b179 | ||
|
|
9e3372df72 | ||
|
|
657df7a728 | ||
|
|
944f0b694b | ||
|
|
efd409da17 | ||
|
|
08d60c554c | ||
|
|
a428ea7beb | ||
|
|
f69878b082 | ||
|
|
c5ffc2882b | ||
|
|
765691751a | ||
|
|
f19e5977c2 | ||
|
|
8f8b9af862 | ||
|
|
3e7dc71995 | ||
|
|
2a25cd8686 | ||
|
|
7664839135 | ||
|
|
47daebc65a | ||
|
|
0d18b944b6 | ||
|
|
951b5384a3 | ||
|
|
11547ecaa3 | ||
|
|
713a0f5b09 | ||
|
|
2cf9c98b43 | ||
|
|
d7af196a0c | ||
|
|
c363be57b7 | ||
|
|
10645790de | ||
|
|
8b18cf382c | ||
|
|
7a131e0bcc | ||
|
|
3d264379cc | ||
|
|
f405682ec1 | ||
|
|
3debf3ce1c | ||
|
|
5a76883969 | ||
|
|
6f51c5e0cc | ||
|
|
2c730d1f0b | ||
|
|
d487da0b2f | ||
|
|
cb8a5cbb62 | ||
|
|
ceb08593d8 | ||
|
|
9dd0eb7b9b | ||
|
|
ebff644d24 | ||
|
|
beb1c15fa5 | ||
|
|
40a5eee211 | ||
|
|
8f393d0bae | ||
|
|
94dad49e2f | ||
|
|
409638151c | ||
|
|
0d3de92890 | ||
|
|
5d619131ec | ||
|
|
e2c8443778 | ||
|
|
daa4743967 | ||
|
|
56553078ef | ||
|
|
5584a06cb3 | ||
|
|
cfeb69ace6 | ||
|
|
b0c8f110de | ||
|
|
aba1266c45 | ||
|
|
c331e0103d | ||
|
|
13978574e0 | ||
|
|
be85963558 | ||
|
|
8c19261ced | ||
|
|
7ca17fa609 | ||
|
|
3d107572df | ||
|
|
f7488655a7 | ||
|
|
876e0a29d4 | ||
|
|
af74375695 | ||
|
|
896965fec5 | ||
|
|
ba5ef93c1a | ||
|
|
ef1153d336 | ||
|
|
0d347f8823 | ||
|
|
897cdc26ae | ||
|
|
aba621c099 | ||
|
|
839813ebde | ||
|
|
545e2ddbfc | ||
|
|
1d63a5903a | ||
|
|
2b34c00a0c | ||
|
|
123068062a | ||
|
|
9a668e8709 | ||
|
|
f6f8937d64 | ||
|
|
c9f53a2880 | ||
|
|
2887e712c3 | ||
|
|
5d3a0ed1b4 | ||
|
|
334b6319de | ||
|
|
4c118c0fd4 | ||
|
|
db00d60684 | ||
|
|
25b74af363 | ||
|
|
eb57cf97ad | ||
|
|
c92e24363f | ||
|
|
8d5d00ac0f | ||
|
|
8b457384ba | ||
|
|
fab2d53ece | ||
|
|
774f27d8d2 | ||
|
|
d7f02ef1b3 | ||
|
|
97eaa6294c | ||
|
|
dc02bb0850 | ||
|
|
2c8c041e1c | ||
|
|
874b1c6654 | ||
|
|
fb982c7097 | ||
|
|
b7f5ce600e | ||
|
|
91604c9e26 | ||
|
|
c874333a37 | ||
|
|
1298b968f2 | ||
|
|
6fe5a854a7 | ||
|
|
aba3b5cb19 | ||
|
|
282aed22b5 | ||
|
|
669a3d9dcf | ||
|
|
9d7455d28a | ||
|
|
4f0c8b081c | ||
|
|
a5db5298a0 | ||
|
|
876c6e9252 | ||
|
|
aef824d262 | ||
|
|
a25ce42490 | ||
|
|
8b0fdaccf4 | ||
|
|
bd840a2421 | ||
|
|
27d515f289 | ||
|
|
df3b9faf8d | ||
|
|
0f129734ae | ||
|
|
275aacfba9 | ||
|
|
e7f47a0663 | ||
|
|
66486541fe | ||
|
|
34f1a84769 | ||
|
|
2244f0368f | ||
|
|
9d85005255 | ||
|
|
ad8629dca6 | ||
|
|
cccfe0e05a | ||
|
|
a8874257e8 | ||
|
|
f689c55f56 | ||
|
|
853c7be8b8 | ||
|
|
823df1e12d | ||
|
|
7570f818e9 | ||
|
|
03aa5aea2c | ||
|
|
a4e86ac353 | ||
|
|
cf6efc050a | ||
|
|
3e0802176b | ||
|
|
697954d4d9 | ||
|
|
741f6c1114 | ||
|
|
b2237ffa51 | ||
|
|
7b6d11bffa | ||
|
|
97565e8f36 | ||
|
|
c0dfee8439 | ||
|
|
fc98240614 | ||
|
|
169d1203c2 | ||
|
|
f3350bc8f5 | ||
|
|
504a19275c | ||
|
|
14cdc52670 | ||
|
|
cf8063f311 | ||
|
|
aa8902f5b9 | ||
|
|
7cd0e664ac | ||
|
|
a04804d3fa | ||
|
|
86f90e6685 | ||
|
|
8131a4b3d2 | ||
|
|
b91a3e13b0 | ||
|
|
5a7a0d32d1 | ||
|
|
3f5df18d6c | ||
|
|
df2cede075 | ||
|
|
4321c161ac | ||
|
|
b1f0c64ef2 | ||
|
|
c9b37dcc77 | ||
|
|
ab093ed9a0 | ||
|
|
cf31367acd | ||
|
|
e3d306cac3 | ||
|
|
960d321019 | ||
|
|
2d4ac93221 | ||
|
|
d4a4f15416 | ||
|
|
504a842d37 | ||
|
|
ded5b1f5d2 | ||
|
|
fcbbc21a80 | ||
|
|
38fce25b86 | ||
|
|
4cc2fa5300 | ||
|
|
4a82c3f65a | ||
|
|
b255d70e18 | ||
|
|
caa842cd55 | ||
|
|
cd338085fb | ||
|
|
e703ce92a8 | ||
|
|
84479a2c2a | ||
|
|
c13969217c | ||
|
|
402540f483 | ||
|
|
8c56315313 | ||
|
|
b29c3eff6e | ||
|
|
ec7dacfc9b | ||
|
|
5f9a6a9f76 | ||
|
|
28f4aea3d5 | ||
|
|
8d29c5fe1b | ||
|
|
ccd935b562 | ||
|
|
d77a49857b | ||
|
|
e30478e5d4 | ||
|
|
71863752cd | ||
|
|
e4a2a8e56d | ||
|
|
0f1c505823 | ||
|
|
1ecce11113 | ||
|
|
2287d67fb5 | ||
|
|
5b4f17ef3d | ||
|
|
3720ab6df6 | ||
|
|
3c893d69e5 | ||
|
|
b93a4a3e42 | ||
|
|
23cef0ab94 | ||
|
|
c8ffb8d694 | ||
|
|
08e08d8920 | ||
|
|
7acd300163 | ||
|
|
d8d95db4ec | ||
|
|
af97d3ef1d | ||
|
|
c65ec14943 | ||
|
|
adfdc7edb4 | ||
|
|
8cced607eb | ||
|
|
5dd5af90c2 | ||
|
|
7a48333b4f | ||
|
|
7044533398 | ||
|
|
560aad8df6 | ||
|
|
36c2099b2e | ||
|
|
6c157675d7 | ||
|
|
458d66cb21 | ||
|
|
201e8911c5 | ||
|
|
1b1ed2408f | ||
|
|
62487d21d8 | ||
|
|
bc752bdb0b | ||
|
|
9e00d421fb | ||
|
|
e7f02fe22b | ||
|
|
6d694f8e53 | ||
|
|
977befd0a7 | ||
|
|
1566ae4fbd | ||
|
|
4e97490cc6 | ||
|
|
446d5a0fcc | ||
|
|
1fd6465012 | ||
|
|
6cea8e3b87 | ||
|
|
28a63e0326 | ||
|
|
b73da46111 | ||
|
|
abafa8c2d2 | ||
|
|
4ae3272cdf | ||
|
|
6aa3b8dbd7 | ||
|
|
395e9b2228 | ||
|
|
be33f68c52 | ||
|
|
29d96381fa | ||
|
|
da8eecf774 | ||
|
|
de91326c12 | ||
|
|
ee1c3c35d7 | ||
|
|
70eece1429 | ||
|
|
b4f2be332b | ||
|
|
23fe76989b | ||
|
|
275d07659d | ||
|
|
a901e92573 | ||
|
|
6ead31b45f | ||
|
|
d4ce12dca9 | ||
|
|
bb6e22cdb7 | ||
|
|
2c9fc4812e | ||
|
|
60f4554afa | ||
|
|
3c486bfd1b | ||
|
|
26b9a95bb2 | ||
|
|
f7c9217cea | ||
|
|
e92022b73c | ||
|
|
61ff2353c8 | ||
|
|
c8cca26ca4 | ||
|
|
aa556ed4d5 | ||
|
|
5d694a7bdf | ||
|
|
c4787dae23 | ||
|
|
9f5f329c53 | ||
|
|
f82b96fcc4 | ||
|
|
d4b24fa427 | ||
|
|
c852f67c59 | ||
|
|
92c228a3c9 | ||
|
|
42f948e2b3 | ||
|
|
13e8932117 | ||
|
|
910d34bd42 | ||
|
|
b204ba29e7 | ||
|
|
d49244cbc8 | ||
|
|
ef2f2f17b4 | ||
|
|
b9f21dcf4c | ||
|
|
808fe690cc | ||
|
|
901eec04e5 | ||
|
|
9272394ada | ||
|
|
4457982fae | ||
|
|
7f67b2b461 | ||
|
|
7f3934f4c3 | ||
|
|
a3b80a2cc4 | ||
|
|
6d967e5e51 | ||
|
|
b674ca90d1 | ||
|
|
95edb60a84 | ||
|
|
40add78ccb | ||
|
|
1029c24c06 | ||
|
|
94d94fe8fb | ||
|
|
49489c0f45 | ||
|
|
215833a2c9 | ||
|
|
a7471a3d47 | ||
|
|
909aaefbd7 | ||
|
|
15c2f56bf2 | ||
|
|
84cdfec415 | ||
|
|
91572ab8b9 | ||
|
|
ed758f4c92 | ||
|
|
f1fc15e115 | ||
|
|
22300e8151 | ||
|
|
292646e14a | ||
|
|
b4921a20d8 | ||
|
|
54be79a725 | ||
|
|
4fc47370fe | ||
|
|
9e30bcf233 | ||
|
|
e5712c54e6 | ||
|
|
2a4fe21a39 | ||
|
|
b259558f0f | ||
|
|
e2f6d9e0d6 | ||
|
|
4fc2b0fa5e | ||
|
|
8dca79ecf2 | ||
|
|
c7f49f0e21 | ||
|
|
bce2094fb2 | ||
|
|
65c33e1aa0 | ||
|
|
8e108bc5e2 | ||
|
|
4e75ce7fdb | ||
|
|
1e42574d28 | ||
|
|
85ebaf6afa | ||
|
|
661c7e4056 | ||
|
|
1e8ea54dbc | ||
|
|
ddbe7e9936 | ||
|
|
cab86175ef | ||
|
|
ec7414b174 | ||
|
|
8343a5d1dd | ||
|
|
18c55784c7 | ||
|
|
39eac83d38 | ||
|
|
55bd6fb57d | ||
|
|
6fdec52332 | ||
|
|
824a3c5fcc | ||
|
|
87da644027 | ||
|
|
4f42f543d8 | ||
|
|
97ea3ac3fc | ||
|
|
f04b75fd36 | ||
|
|
f5bffc38f1 | ||
|
|
27738acefc | ||
|
|
59ce2072c5 | ||
|
|
ed68dda70b | ||
|
|
892ab02f06 | ||
|
|
7d9196d5e1 | ||
|
|
dccdb5ceb7 | ||
|
|
f961698e44 | ||
|
|
278fe3262e | ||
|
|
1fc860b052 | ||
|
|
88a8311173 | ||
|
|
63dc5697dd | ||
|
|
b595d1fade | ||
|
|
d91c59b7d0 | ||
|
|
aa2ab0da31 | ||
|
|
91f94106fb | ||
|
|
308f319138 | ||
|
|
fa0c01591a | ||
|
|
cb5a771490 | ||
|
|
0c17a13462 | ||
|
|
04593cb2d7 | ||
|
|
b6f50b6af0 | ||
|
|
fc454cba03 | ||
|
|
6f165df29e | ||
|
|
d16468071d | ||
|
|
20a492523f | ||
|
|
1216f51c78 | ||
|
|
ea3ac1041b | ||
|
|
d838e8baf0 | ||
|
|
60a7347d7d | ||
|
|
4e05e79426 | ||
|
|
aa872f47f2 | ||
|
|
fbd833ad86 | ||
|
|
bee65ed32c | ||
|
|
5adca76a9a | ||
|
|
e7467f6446 | ||
|
|
e49473fbd3 | ||
|
|
bfec44aa5a | ||
|
|
55b3bf6036 | ||
|
|
c9c07f0cb0 | ||
|
|
e25727441d | ||
|
|
51b7955ccd | ||
|
|
196bba9cda | ||
|
|
430ed78d85 | ||
|
|
2d11ed805d | ||
|
|
f55426bdb0 | ||
|
|
87b5068fec | ||
|
|
9ddd1a4ae2 | ||
|
|
736bc9c9bd | ||
|
|
5a2da62992 | ||
|
|
1a72eb91ee | ||
|
|
0d3c5b06e2 | ||
|
|
035b72a08d | ||
|
|
fc4a595725 | ||
|
|
444969bcf4 | ||
|
|
2cb6b14eca | ||
|
|
468b5022a4 | ||
|
|
c1897563ca | ||
|
|
5e533896b9 | ||
|
|
d3ceb7cfc1 | ||
|
|
731f74f421 | ||
|
|
46d82651a3 | ||
|
|
b3108c7e2b | ||
|
|
0cb988470e | ||
|
|
5a030014b0 | ||
|
|
2a43ef4dae | ||
|
|
6b5f9fc6ff | ||
|
|
b3a156c20d | ||
|
|
24340d3a8e | ||
|
|
2fac2a8c5e | ||
|
|
decb0c702d | ||
|
|
d45ff6cca5 | ||
|
|
83833e668c | ||
|
|
2cc181d1ac | ||
|
|
a946ce3534 | ||
|
|
3e9f476b37 | ||
|
|
de65c748a4 | ||
|
|
8a2bfb9d7b | ||
|
|
a1ced31fea | ||
|
|
989a9f506e | ||
|
|
59d55e2489 | ||
|
|
2b312a9234 | ||
|
|
16d9b982c2 | ||
|
|
a5600e75f5 | ||
|
|
f91dea62b6 | ||
|
|
4915ffcf2a | ||
|
|
9dbea2aa18 | ||
|
|
45f6a70fb8 | ||
|
|
96b4c611cc | ||
|
|
4e559d6594 | ||
|
|
db1a599f95 | ||
|
|
040964bbb7 | ||
|
|
dc6a303154 | ||
|
|
f88f14c983 | ||
|
|
f870649256 | ||
|
|
ed4dc30a6e | ||
|
|
ce9010ff13 | ||
|
|
994e9fa852 | ||
|
|
9df7d6227e | ||
|
|
242a576548 | ||
|
|
c1a5808f37 | ||
|
|
5c6bb99d78 | ||
|
|
63c408c45b | ||
|
|
2a665dffbc | ||
|
|
6509acd6ee | ||
|
|
4853d45609 | ||
|
|
fe78c1fee3 | ||
|
|
8102172557 | ||
|
|
a1341e6036 | ||
|
|
d31af2ddc2 | ||
|
|
a563330136 | ||
|
|
a58e5789bc | ||
|
|
68e258f23b | ||
|
|
dd18866156 | ||
|
|
1b1f1957c3 | ||
|
|
ff6b4effbd | ||
|
|
06fa59239c | ||
|
|
557bfbd1d6 | ||
|
|
f5a6dfa629 | ||
|
|
ce33dfb003 | ||
|
|
7b1c058d29 | ||
|
|
04c8f8a123 | ||
|
|
d15fccb1d8 | ||
|
|
229dd9cd18 | ||
|
|
a4faaa406b | ||
|
|
b6d2de54b2 | ||
|
|
d5e81d77a2 | ||
|
|
939e99637f | ||
|
|
579a261612 | ||
|
|
6d03304cbb | ||
|
|
b8d41b3421 | ||
|
|
6a5bb1f5c8 | ||
|
|
cd742a4617 | ||
|
|
54063b97ad | ||
|
|
7abb67e737 | ||
|
|
00fd1ba137 | ||
|
|
7ea37b9eb9 | ||
|
|
b749de8fe1 | ||
|
|
8efef6842d | ||
|
|
dc206f38d5 | ||
|
|
29a00a6c0e | ||
|
|
fe678230a8 | ||
|
|
9cdbeb061f | ||
|
|
6c308f35c1 | ||
|
|
34b89cf2e8 | ||
|
|
b566a188dc | ||
|
|
998432e236 | ||
|
|
1af8edfe4d | ||
|
|
5bf01106c5 | ||
|
|
a45289e385 | ||
|
|
4ffd005b09 | ||
|
|
e6ca89fea8 | ||
|
|
2225aea756 | ||
|
|
bfc4a84020 | ||
|
|
5390bfdcab | ||
|
|
301211ff41 | ||
|
|
64139e4e08 | ||
|
|
e6485cde92 | ||
|
|
891f6ba66f | ||
|
|
5d3c1e3fec | ||
|
|
087e755390 | ||
|
|
025dc1ce75 | ||
|
|
703200338d | ||
|
|
377c93ca0b | ||
|
|
69394ffe29 | ||
|
|
f85231d74a | ||
|
|
b93d8b0159 | ||
|
|
67b9329903 | ||
|
|
c0edd4ea4f | ||
|
|
8eaf2786e8 | ||
|
|
25622df464 | ||
|
|
a48900e178 | ||
|
|
ac8b0535d2 | ||
|
|
6ce25a825b | ||
|
|
b3f56851b8 | ||
|
|
4b86fedce1 | ||
|
|
1ebb70c4d2 | ||
|
|
3de7b81be8 | ||
|
|
d08225339c | ||
|
|
ba22d0706f | ||
|
|
ef80f104c0 | ||
|
|
af296a1e4e | ||
|
|
28a755306a | ||
|
|
461e085eff | ||
|
|
fbda049c32 | ||
|
|
4ded5e2b98 | ||
|
|
63537aff20 | ||
|
|
0f7a2adf15 | ||
|
|
60963abe2c | ||
|
|
08cf95aa38 | ||
|
|
e5b10ab16a | ||
|
|
7f5a1ee45a | ||
|
|
15c593f68e | ||
|
|
5f8ef0395b | ||
|
|
513636e1e0 | ||
|
|
ae9b2c08a9 | ||
|
|
d5327b3b4a | ||
|
|
323e3d3cac | ||
|
|
01b2257063 | ||
|
|
c69ef611a0 | ||
|
|
dcad23316d | ||
|
|
e411f9932f | ||
|
|
854969e1b8 | ||
|
|
4ac7b6e9e8 | ||
|
|
ac70908c5a | ||
|
|
45ac70b78f | ||
|
|
a4664576fe | ||
|
|
b293643398 | ||
|
|
a2e197facd | ||
|
|
8614d39ef4 | ||
|
|
6456bb34ae | ||
|
|
f5dc4de1c1 | ||
|
|
d869056910 | ||
|
|
821e4b17cb | ||
|
|
d8cb5efd2d | ||
|
|
f90e2fb484 | ||
|
|
2c9a7144da | ||
|
|
88d1af7210 | ||
|
|
300e5a5528 | ||
|
|
4418fefe4b | ||
|
|
fe5d1cac9a | ||
|
|
49d17fff9b | ||
|
|
557c6d2d8b | ||
|
|
45fc62357d | ||
|
|
840e3cc22f | ||
|
|
c158c7fc88 | ||
|
|
bc6f8fc2dd | ||
|
|
117730acb2 | ||
|
|
595a7dac83 | ||
|
|
64a4d70df4 | ||
|
|
be36199fe1 | ||
|
|
e46ad25677 | ||
|
|
d5ee663922 | ||
|
|
a7ab4be055 | ||
|
|
6bbf29e75a | ||
|
|
0a06c60cb7 | ||
|
|
03658575eb | ||
|
|
38114bddb9 | ||
|
|
0711a197db | ||
|
|
f8f818b211 | ||
|
|
988932209c | ||
|
|
2aa56cec30 | ||
|
|
93d493650c | ||
|
|
c6162ddcb4 | ||
|
|
038517eda4 | ||
|
|
30a9db73ab | ||
|
|
a50aa41bdb | ||
|
|
cbb322fdb8 | ||
|
|
026e2a020d | ||
|
|
07aab1d005 | ||
|
|
26f0f7b188 | ||
|
|
1efde3b86b | ||
|
|
8c1318f379 | ||
|
|
40e67e8e17 | ||
|
|
04466f52fd | ||
|
|
06baa5fb57 | ||
|
|
04e1657628 | ||
|
|
7816c8cab0 | ||
|
|
6636e658a4 | ||
|
|
2a06f0daef | ||
|
|
883cfa588c | ||
|
|
68011a0b5a | ||
|
|
5247d1a371 | ||
|
|
cabdd528d4 | ||
|
|
2bacbb796b | ||
|
|
aa0ed6434a | ||
|
|
5b2215d646 | ||
|
|
0e760e25f2 | ||
|
|
acbb85b409 | ||
|
|
ea1d4b97ad | ||
|
|
a81839c13f | ||
|
|
b9d4668d4d | ||
|
|
42b27f5965 | ||
|
|
9cc8222b1c | ||
|
|
e8479338df | ||
|
|
fa9e6c9fc0 | ||
|
|
5366173b52 | ||
|
|
63520c55b3 | ||
|
|
86f6d9b14a | ||
|
|
5270cf6284 | ||
|
|
4f46d81e1b | ||
|
|
294a2e6fdb | ||
|
|
b20a8bc90b | ||
|
|
68bdd1336f | ||
|
|
e62ccd932d | ||
|
|
d6c188df6e | ||
|
|
004000b5d2 | ||
|
|
633c8a3444 | ||
|
|
2f59a20b6b | ||
|
|
593c435f75 | ||
|
|
20ec45be57 | ||
|
|
d2a0e12409 | ||
|
|
33eebe117b | ||
|
|
ef0cfc2e7c | ||
|
|
b6e17ae543 | ||
|
|
8a33e2be89 | ||
|
|
5f91097987 | ||
|
|
0fd4f02951 | ||
|
|
106e78ed62 | ||
|
|
8855868b27 | ||
|
|
bfc3e8a907 | ||
|
|
154371e052 | ||
|
|
ab4a4d3d72 | ||
|
|
5a4de02db7 | ||
|
|
43cbc8c6e8 | ||
|
|
5938aa7b50 | ||
|
|
a49252b2f5 | ||
|
|
0be885d9bf | ||
|
|
ae1e8353f2 | ||
|
|
98fe88581f | ||
|
|
d66475576f | ||
|
|
65ff7be776 | ||
|
|
190b079494 | ||
|
|
b020a30bd4 | ||
|
|
81f8453c38 | ||
|
|
533e3cf42d | ||
|
|
69ee73492d | ||
|
|
4a902d04b2 | ||
|
|
2e48e316c2 | ||
|
|
bbe5dddb83 | ||
|
|
7c943fe4ac | ||
|
|
2cbb49681a | ||
|
|
84db4ed57c | ||
|
|
e155642ce4 | ||
|
|
87c4df60d3 | ||
|
|
ff412835e4 | ||
|
|
ad15828157 | ||
|
|
b2fc7f934e | ||
|
|
2fac4d91d6 | ||
|
|
125cd96354 | ||
|
|
af02e6b714 | ||
|
|
0c87b25244 | ||
|
|
e87ada6e79 | ||
|
|
282c8e58bd | ||
|
|
475b66b115 | ||
|
|
5bb971e61a | ||
|
|
ebad9ba723 | ||
|
|
6ece2a839e | ||
|
|
8d6527fb75 | ||
|
|
6bfff38182 | ||
|
|
9e446717fa | ||
|
|
408b48f606 | ||
|
|
8d077ad46d | ||
|
|
db72465e0b | ||
|
|
ba9f5e1688 | ||
|
|
caf40cd272 | ||
|
|
3edccd224a | ||
|
|
f48931a969 | ||
|
|
84f23aa997 | ||
|
|
1965da6a85 | ||
|
|
441ae3e25b | ||
|
|
7f612711a0 | ||
|
|
92eb4aa822 | ||
|
|
08ec522ae7 | ||
|
|
c5cc1fcc1e | ||
|
|
cedf91ea1a | ||
|
|
51b462f043 | ||
|
|
727eeb6c74 | ||
|
|
a114fba062 | ||
|
|
cf322b5c2a | ||
|
|
92116f1671 | ||
|
|
bc479248d7 | ||
|
|
8ee12f2950 | ||
|
|
dcea4c30ef | ||
|
|
e7ca56e061 | ||
|
|
09b800b9ad | ||
|
|
9a6a8580de | ||
|
|
a31ac17792 | ||
|
|
0e27cd0801 | ||
|
|
bc36676fa1 | ||
|
|
3d2db23f33 | ||
|
|
56d366a286 | ||
|
|
4a26f30d65 | ||
|
|
8e51469de5 | ||
|
|
50ebcd552c | ||
|
|
ada39cd3c7 | ||
|
|
b2d20af51a | ||
|
|
f528fa25d1 | ||
|
|
e09a7fb6e0 | ||
|
|
30f7939616 | ||
|
|
16b9375b9d | ||
|
|
4ef93569a1 | ||
|
|
1ce2aaeaf1 | ||
|
|
6bfe8dfcf0 | ||
|
|
8d8f4795e2 | ||
|
|
6f6d06377b | ||
|
|
f22823fcf6 | ||
|
|
93ce57ee1a | ||
|
|
97dd747252 | ||
|
|
bc8c136458 | ||
|
|
0774252dc1 | ||
|
|
ae30ae4be6 | ||
|
|
a2b8935763 | ||
|
|
703efb74d3 | ||
|
|
b2c6062e9a | ||
|
|
c9e7e461b1 | ||
|
|
6aaddfc5a4 | ||
|
|
7f2c41940d | ||
|
|
d31ba39a91 | ||
|
|
c058673e33 | ||
|
|
44ce6a5169 | ||
|
|
0fb0be4ffc | ||
|
|
e70ba00929 | ||
|
|
fe1dbb4cbf | ||
|
|
31df2341c3 | ||
|
|
9d99da14e1 | ||
|
|
f8e10f36db | ||
|
|
bb0f384a39 | ||
|
|
6a0b24f032 | ||
|
|
80d5536503 | ||
|
|
9dcd79bd94 | ||
|
|
c5020b8884 | ||
|
|
0b74de275c | ||
|
|
e66aef17df | ||
|
|
19eff5e6d6 | ||
|
|
88b4fc73de | ||
|
|
70694542eb | ||
|
|
360e5e3102 | ||
|
|
6e89a232e6 | ||
|
|
ecd3b7039f | ||
|
|
4a22e3d2d4 | ||
|
|
dcb4ebe5d9 | ||
|
|
dd379bf18d | ||
|
|
c9b556160f | ||
|
|
168e224d3e | ||
|
|
9e57c14130 | ||
|
|
9c137a1c48 | ||
|
|
ccb9b7e5fb | ||
|
|
c7b16cd043 | ||
|
|
7e20e41521 | ||
|
|
66761a69d3 | ||
|
|
fb32d26479 | ||
|
|
b6398fdb5d | ||
|
|
d9443527ee | ||
|
|
7c175da9f1 | ||
|
|
05aa087851 | ||
|
|
592e968f9f | ||
|
|
894a26cc67 | ||
|
|
1b5dd4638d | ||
|
|
a19186c508 | ||
|
|
5450bdeae9 | ||
|
|
fcd71957ff |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -2,3 +2,5 @@
|
||||
|
||||
github: [eliandoran]
|
||||
custom: ["https://paypal.me/eliandoran"]
|
||||
liberapay: ElianDoran
|
||||
buy_me_a_coffee: eliandoran
|
||||
|
||||
22
.github/actions/build-electron/action.yml
vendored
22
.github/actions/build-electron/action.yml
vendored
@@ -162,3 +162,25 @@ runs:
|
||||
echo "Found ZIP: $zip_file"
|
||||
echo "Note: ZIP files are not code signed, but their contents should be"
|
||||
fi
|
||||
|
||||
- name: Sign the RPM
|
||||
if: inputs.os == 'linux'
|
||||
shell: ${{ inputs.shell }}
|
||||
run: |
|
||||
echo -n "$GPG_SIGNING_KEY" | base64 --decode | gpg --import
|
||||
|
||||
# Import the key into RPM for verification
|
||||
gpg --export -a > pubkey
|
||||
rpm --import pubkey
|
||||
rm pubkey
|
||||
|
||||
# Sign the RPM
|
||||
rpm_file=$(find ./apps/desktop/upload -name "*.rpm" -print -quit)
|
||||
rpmsign --define "_gpg_name Trilium Notes Signing Key <triliumnotes@outlook.com>" --addsign "$rpm_file"
|
||||
rpm -Kv "$rpm_file"
|
||||
|
||||
# Validate code signing
|
||||
if ! rpm -K "$rpm_file" | grep -q "digests signatures OK"; then
|
||||
echo .rpm file not signed
|
||||
exit 1
|
||||
fi
|
||||
|
||||
2
.github/actions/report-size/action.yml
vendored
2
.github/actions/report-size/action.yml
vendored
@@ -44,7 +44,7 @@ runs:
|
||||
steps:
|
||||
# Checkout branch to compare to [required]
|
||||
- name: Checkout base branch
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
ref: ${{ inputs.branch }}
|
||||
path: br-base
|
||||
|
||||
40
.github/instructions/nx.instructions.md
vendored
Normal file
40
.github/instructions/nx.instructions.md
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
applyTo: '**'
|
||||
---
|
||||
|
||||
// This file is automatically generated by Nx Console
|
||||
|
||||
You are in an nx workspace using Nx 21.3.9 and pnpm as the package manager.
|
||||
|
||||
You have access to the Nx MCP server and the tools it provides. Use them. Follow these guidelines in order to best help the user:
|
||||
|
||||
# General Guidelines
|
||||
- When answering questions, use the nx_workspace tool first to gain an understanding of the workspace architecture
|
||||
- For questions around nx configuration, best practices or if you're unsure, use the nx_docs tool to get relevant, up-to-date docs!! Always use this instead of assuming things about nx configuration
|
||||
- If the user needs help with an Nx configuration or project graph error, use the 'nx_workspace' tool to get any errors
|
||||
- To help answer questions about the workspace structure or simply help with demonstrating how tasks depend on each other, use the 'nx_visualize_graph' tool
|
||||
|
||||
# Generation Guidelines
|
||||
If the user wants to generate something, use the following flow:
|
||||
|
||||
- learn about the nx workspace and any specifics the user needs by using the 'nx_workspace' tool and the 'nx_project_details' tool if applicable
|
||||
- get the available generators using the 'nx_generators' tool
|
||||
- decide which generator to use. If no generators seem relevant, check the 'nx_available_plugins' tool to see if the user could install a plugin to help them
|
||||
- get generator details using the 'nx_generator_schema' tool
|
||||
- you may use the 'nx_docs' tool to learn more about a specific generator or technology if you're unsure
|
||||
- decide which options to provide in order to best complete the user's request. Don't make any assumptions and keep the options minimalistic
|
||||
- open the generator UI using the 'nx_open_generate_ui' tool
|
||||
- wait for the user to finish the generator
|
||||
- read the generator log file using the 'nx_read_generator_log' tool
|
||||
- use the information provided in the log file to answer the user's question or continue with what they were doing
|
||||
|
||||
# Running Tasks Guidelines
|
||||
If the user wants help with tasks or commands (which include keywords like "test", "build", "lint", or other similar actions), use the following flow:
|
||||
- Use the 'nx_current_running_tasks_details' tool to get the list of tasks (this can include tasks that were completed, stopped or failed).
|
||||
- If there are any tasks, ask the user if they would like help with a specific task then use the 'nx_current_running_task_output' tool to get the terminal output for that task/command
|
||||
- Use the terminal output from 'nx_current_running_task_output' to see what's wrong and help the user fix their problem. Use the appropriate tools if necessary
|
||||
- If the user would like to rerun the task or command, always use `nx run <taskId>` to rerun in the terminal. This will ensure that the task will run in the nx context and will be run the same way it originally executed
|
||||
- If the task was marked as "continuous" do not offer to rerun the task. This task is already running and the user can see the output in the terminal. You can use 'nx_current_running_task_output' to get the output of the task to verify the output.
|
||||
|
||||
|
||||
|
||||
18
.github/workflows/checks.yml
vendored
Normal file
18
.github/workflows/checks.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
name: Checks
|
||||
on:
|
||||
push:
|
||||
pull_request_target:
|
||||
types: [synchronize]
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Check if PRs have conflicts
|
||||
uses: eps1lon/actions-label-merge-conflict@v3
|
||||
if: github.repository == ${{ vars.REPO_MAIN }}
|
||||
with:
|
||||
dirtyLabel: "merge-conflicts"
|
||||
repoToken: "${{ secrets.MERGE_CONFLICT_LABEL_PAT }}"
|
||||
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -57,7 +57,7 @@ jobs:
|
||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# Add any setup steps before running the `github/codeql-action/init` action.
|
||||
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
||||
|
||||
8
.github/workflows/dev.yml
vendored
8
.github/workflows/dev.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0 # needed for https://github.com/marketplace/actions/nx-set-shas
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
- check-affected
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
- test_dev
|
||||
- check-affected
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -103,7 +103,7 @@ jobs:
|
||||
- dockerfile: Dockerfile
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Install dependencies
|
||||
|
||||
6
.github/workflows/main-docker.yml
vendored
6
.github/workflows/main-docker.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
- dockerfile: Dockerfile
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set IMAGE_NAME to lowercase
|
||||
run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV
|
||||
@@ -141,7 +141,7 @@ jobs:
|
||||
run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v4
|
||||
@@ -223,7 +223,7 @@ jobs:
|
||||
- build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
|
||||
7
.github/workflows/nightly.yml
vendored
7
.github/workflows/nightly.yml
vendored
@@ -27,6 +27,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
nightly-electron:
|
||||
if: github.repository == ${{ vars.REPO_MAIN }}
|
||||
name: Deploy nightly
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -47,7 +48,7 @@ jobs:
|
||||
forge_platform: win32
|
||||
runs-on: ${{ matrix.os.image }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v4
|
||||
@@ -75,6 +76,7 @@ jobs:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
WINDOWS_SIGN_EXECUTABLE: ${{ vars.WINDOWS_SIGN_EXECUTABLE }}
|
||||
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
|
||||
|
||||
- name: Publish release
|
||||
uses: softprops/action-gh-release@v2.3.2
|
||||
@@ -96,6 +98,7 @@ jobs:
|
||||
path: apps/desktop/upload
|
||||
|
||||
nightly-server:
|
||||
if: github.repository == ${{ vars.REPO_MAIN }}
|
||||
name: Deploy server nightly
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -108,7 +111,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Run the build
|
||||
uses: ./.github/actions/build-server
|
||||
|
||||
2
.github/workflows/playwright.yml
vendored
2
.github/workflows/playwright.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
filter: tree:0
|
||||
fetch-depth: 0
|
||||
|
||||
9
.github/workflows/release.yml
vendored
9
.github/workflows/release.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
forge_platform: win32
|
||||
runs-on: ${{ matrix.os.image }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v4
|
||||
@@ -58,6 +58,7 @@ jobs:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
WINDOWS_SIGN_EXECUTABLE: ${{ vars.WINDOWS_SIGN_EXECUTABLE }}
|
||||
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
|
||||
|
||||
- name: Upload the artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -78,7 +79,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Run the build
|
||||
uses: ./.github/actions/build-server
|
||||
@@ -101,13 +102,13 @@ jobs:
|
||||
steps:
|
||||
- run: mkdir upload
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
sparse-checkout: |
|
||||
docs/Release Notes
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
merge-multiple: true
|
||||
pattern: release-*
|
||||
|
||||
11
.github/workflows/unblock_signing.yml
vendored
Normal file
11
.github/workflows/unblock_signing.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
name: Unblock signing
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
unblock-win-signing:
|
||||
runs-on: win-signing
|
||||
steps:
|
||||
- run: |
|
||||
cat ${{ vars.WINDOWS_SIGN_ERROR_LOG }}
|
||||
rm ${{ vars.WINDOWS_SIGN_ERROR_LOG }}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,6 +10,7 @@ node_modules
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
|
||||
6
.idea/.gitignore
generated
vendored
6
.idea/.gitignore
generated
vendored
@@ -1,6 +0,0 @@
|
||||
# Default ignored files
|
||||
/workspace.xml
|
||||
|
||||
# Datasource local storage ignored files
|
||||
/dataSources.local.xml
|
||||
/dataSources/
|
||||
15
.idea/codeStyles/Project.xml
generated
15
.idea/codeStyles/Project.xml
generated
@@ -1,15 +0,0 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<option name="OTHER_INDENT_OPTIONS">
|
||||
<value>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="2" />
|
||||
</value>
|
||||
</option>
|
||||
<codeStyleSettings language="JSON">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
5
.idea/codeStyles/codeStyleConfig.xml
generated
@@ -1,5 +0,0 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
12
.idea/dataSources.xml
generated
12
.idea/dataSources.xml
generated
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="document.db" uuid="2a4ac1e6-b828-4a2a-8e4a-3f59f10aff26">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/data/document.db</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
||||
4
.idea/encodings.xml
generated
4
.idea/encodings.xml
generated
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
|
||||
</project>
|
||||
15
.idea/git_toolbox_prj.xml
generated
15
.idea/git_toolbox_prj.xml
generated
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitToolBoxProjectSettings">
|
||||
<option name="commitMessageIssueKeyValidationOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
<option name="commitMessageValidationEnabledOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
11
.idea/inspectionProfiles/Project_Default.xml
generated
11
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -1,11 +0,0 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
6
.idea/jsLibraryMappings.xml
generated
6
.idea/jsLibraryMappings.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptLibraryMappings">
|
||||
<includedPredefinedLibrary name="Node.js Core" />
|
||||
</component>
|
||||
</project>
|
||||
9
.idea/jsLinters/jslint.xml
generated
9
.idea/jsLinters/jslint.xml
generated
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JSLintConfiguration">
|
||||
<option devel="true" />
|
||||
<option es6="true" />
|
||||
<option maxerr="50" />
|
||||
<option node="true" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/misc.xml
generated
8
.idea/misc.xml
generated
@@ -1,8 +0,0 @@
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" default="true" project-jdk-name="openjdk-16" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/trilium.iml" filepath="$PROJECT_DIR$/trilium.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
7
.idea/sqldialects.xml
generated
7
.idea/sqldialects.xml
generated
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="SqlDialectMappings">
|
||||
<file url="file://$PROJECT_DIR$" dialect="SQLite" />
|
||||
<file url="PROJECT" dialect="SQLite" />
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
4
.mailmap
4
.mailmap
@@ -1,2 +1,2 @@
|
||||
Adam Zivner <adam.zivner@gmail.com>
|
||||
Adam Zivner <zadam.apps@gmail.com>
|
||||
zadam <adam.zivner@gmail.com>
|
||||
zadam <zadam.apps@gmail.com>
|
||||
2
.vscode/i18n-ally-custom-framework.yml
vendored
2
.vscode/i18n-ally-custom-framework.yml
vendored
@@ -3,6 +3,7 @@
|
||||
languageIds:
|
||||
- javascript
|
||||
- typescript
|
||||
- typescriptreact
|
||||
- html
|
||||
|
||||
# An array of RegExes to find the key usage. **The key should be captured in the first match group**.
|
||||
@@ -25,6 +26,7 @@ scopeRangeRegex: "useTranslation\\(\\s*\\[?\\s*['\"`](.*?)['\"`]"
|
||||
# The "$1" will be replaced by the keypath specified.
|
||||
refactorTemplates:
|
||||
- t("$1")
|
||||
- {t("$1")}
|
||||
- ${t("$1")}
|
||||
- <%= t("$1") %>
|
||||
|
||||
|
||||
8
.vscode/mcp.json
vendored
Normal file
8
.vscode/mcp.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"servers": {
|
||||
"nx-mcp": {
|
||||
"type": "http",
|
||||
"url": "http://localhost:9461/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
10
.vscode/settings.json
vendored
10
.vscode/settings.json
vendored
@@ -28,5 +28,13 @@
|
||||
"typescript.validate.enable": true,
|
||||
"typescript.tsserver.experimental.enableProjectDiagnostics": true,
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"docs/**/*.html": true,
|
||||
"docs/**/*.png": true,
|
||||
"apps/server/src/assets/doc_notes/**": true,
|
||||
"apps/edit-docs/demo/**": true
|
||||
},
|
||||
"nxConsole.generateAiAgentRules": true
|
||||
}
|
||||
161
CLAUDE.md
Normal file
161
CLAUDE.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Overview
|
||||
|
||||
Trilium Notes is a hierarchical note-taking application with advanced features like synchronization, scripting, and rich text editing. It's built as a TypeScript monorepo using NX, with multiple applications and shared packages.
|
||||
|
||||
## Development Commands
|
||||
|
||||
### Setup
|
||||
- `pnpm install` - Install all dependencies
|
||||
- `corepack enable` - Enable pnpm if not available
|
||||
|
||||
### Running Applications
|
||||
- `pnpm run server:start` - Start development server (http://localhost:8080)
|
||||
- `pnpm nx run server:serve` - Alternative server start command
|
||||
- `pnpm nx run desktop:serve` - Run desktop Electron app
|
||||
- `pnpm run server:start-prod` - Run server in production mode
|
||||
|
||||
### Building
|
||||
- `pnpm nx build <project>` - Build specific project (server, client, desktop, etc.)
|
||||
- `pnpm run client:build` - Build client application
|
||||
- `pnpm run server:build` - Build server application
|
||||
- `pnpm run electron:build` - Build desktop application
|
||||
|
||||
### Testing
|
||||
- `pnpm test:all` - Run all tests (parallel + sequential)
|
||||
- `pnpm test:parallel` - Run tests that can run in parallel
|
||||
- `pnpm test:sequential` - Run tests that must run sequentially (server, ckeditor5-mermaid, ckeditor5-math)
|
||||
- `pnpm nx test <project>` - Run tests for specific project
|
||||
- `pnpm coverage` - Generate coverage reports
|
||||
|
||||
### Linting & Type Checking
|
||||
- `pnpm nx run <project>:lint` - Lint specific project
|
||||
- `pnpm nx run <project>:typecheck` - Type check specific project
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Monorepo Structure
|
||||
- **apps/**: Runnable applications
|
||||
- `client/` - Frontend application (shared by server and desktop)
|
||||
- `server/` - Node.js server with web interface
|
||||
- `desktop/` - Electron desktop application
|
||||
- `web-clipper/` - Browser extension for saving web content
|
||||
- Additional tools: `db-compare`, `dump-db`, `edit-docs`
|
||||
|
||||
- **packages/**: Shared libraries
|
||||
- `commons/` - Shared interfaces and utilities
|
||||
- `ckeditor5/` - Custom rich text editor with Trilium-specific plugins
|
||||
- `codemirror/` - Code editor customizations
|
||||
- `highlightjs/` - Syntax highlighting
|
||||
- Custom CKEditor plugins: `ckeditor5-admonition`, `ckeditor5-footnotes`, `ckeditor5-math`, `ckeditor5-mermaid`
|
||||
|
||||
### Core Architecture Patterns
|
||||
|
||||
#### Three-Layer Cache System
|
||||
- **Becca** (Backend Cache): Server-side entity cache (`apps/server/src/becca/`)
|
||||
- **Froca** (Frontend Cache): Client-side mirror of backend data (`apps/client/src/services/froca.ts`)
|
||||
- **Shaca** (Share Cache): Optimized cache for shared/published notes (`apps/server/src/share/`)
|
||||
|
||||
#### Entity System
|
||||
Core entities are defined in `apps/server/src/becca/entities/`:
|
||||
- `BNote` - Notes with content and metadata
|
||||
- `BBranch` - Hierarchical relationships between notes (allows multiple parents)
|
||||
- `BAttribute` - Key-value metadata attached to notes
|
||||
- `BRevision` - Note version history
|
||||
- `BOption` - Application configuration
|
||||
|
||||
#### Widget-Based UI
|
||||
Frontend uses a widget system (`apps/client/src/widgets/`):
|
||||
- `BasicWidget` - Base class for all UI components
|
||||
- `NoteContextAwareWidget` - Widgets that respond to note changes
|
||||
- `RightPanelWidget` - Widgets displayed in the right panel
|
||||
- Type-specific widgets in `type_widgets/` directory
|
||||
|
||||
#### API Architecture
|
||||
- **Internal API**: REST endpoints in `apps/server/src/routes/api/`
|
||||
- **ETAPI**: External API for third-party integrations (`apps/server/src/etapi/`)
|
||||
- **WebSocket**: Real-time synchronization (`apps/server/src/services/ws.ts`)
|
||||
|
||||
### Key Files for Understanding Architecture
|
||||
|
||||
1. **Application Entry Points**:
|
||||
- `apps/server/src/main.ts` - Server startup
|
||||
- `apps/client/src/desktop.ts` - Client initialization
|
||||
|
||||
2. **Core Services**:
|
||||
- `apps/server/src/becca/becca.ts` - Backend data management
|
||||
- `apps/client/src/services/froca.ts` - Frontend data synchronization
|
||||
- `apps/server/src/services/backend_script_api.ts` - Scripting API
|
||||
|
||||
3. **Database Schema**:
|
||||
- `apps/server/src/assets/db/schema.sql` - Core database structure
|
||||
|
||||
4. **Configuration**:
|
||||
- `nx.json` - NX workspace configuration
|
||||
- `package.json` - Project dependencies and scripts
|
||||
|
||||
## Note Types and Features
|
||||
|
||||
Trilium supports multiple note types, each with specialized widgets:
|
||||
- **Text**: Rich text with CKEditor5 (markdown import/export)
|
||||
- **Code**: Syntax-highlighted code editing with CodeMirror
|
||||
- **File**: Binary file attachments
|
||||
- **Image**: Image display with editing capabilities
|
||||
- **Canvas**: Drawing/diagramming with Excalidraw
|
||||
- **Mermaid**: Diagram generation
|
||||
- **Relation Map**: Visual note relationship mapping
|
||||
- **Web View**: Embedded web pages
|
||||
- **Doc/Book**: Hierarchical documentation structure
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
### Testing Strategy
|
||||
- Server tests run sequentially due to shared database
|
||||
- Client tests can run in parallel
|
||||
- E2E tests use Playwright for both server and desktop apps
|
||||
- Build validation tests check artifact integrity
|
||||
|
||||
### Scripting System
|
||||
Trilium provides powerful user scripting capabilities:
|
||||
- Frontend scripts run in browser context
|
||||
- Backend scripts run in Node.js context with full API access
|
||||
- Script API documentation available in `docs/Script API/`
|
||||
|
||||
### Internationalization
|
||||
- Translation files in `apps/client/src/translations/`
|
||||
- Supported languages: English, German, Spanish, French, Romanian, Chinese
|
||||
|
||||
### Security Considerations
|
||||
- Per-note encryption with granular protected sessions
|
||||
- CSRF protection for API endpoints
|
||||
- OpenID and TOTP authentication support
|
||||
- Sanitization of user-generated content
|
||||
|
||||
## Common Development Tasks
|
||||
|
||||
### Adding New Note Types
|
||||
1. Create widget in `apps/client/src/widgets/type_widgets/`
|
||||
2. Register in `apps/client/src/services/note_types.ts`
|
||||
3. Add backend handling in `apps/server/src/services/notes.ts`
|
||||
|
||||
### Extending Search
|
||||
- Search expressions handled in `apps/server/src/services/search/`
|
||||
- Add new search operators in search context files
|
||||
|
||||
### Custom CKEditor Plugins
|
||||
- Create new package in `packages/` following existing plugin structure
|
||||
- Register in `packages/ckeditor5/src/plugins.ts`
|
||||
|
||||
### Database Migrations
|
||||
- Add migration scripts in `apps/server/src/migrations/`
|
||||
- Update schema in `apps/server/src/assets/db/schema.sql`
|
||||
|
||||
## Build System Notes
|
||||
- Uses NX for monorepo management with build caching
|
||||
- Vite for fast development builds
|
||||
- ESBuild for production optimization
|
||||
- pnpm workspaces for dependency management
|
||||
- Docker support with multi-stage builds
|
||||
62
README.md
62
README.md
@@ -1,11 +1,11 @@
|
||||
# Trilium Notes
|
||||
|
||||

|
||||

|
||||

|
||||
[](https://app.relative-ci.com/projects/Di5q7dz9daNDZ9UXi0Bp)
|
||||
 
|
||||

|
||||

|
||||
[](https://app.relative-ci.com/projects/Di5q7dz9daNDZ9UXi0Bp) [](https://hosted.weblate.org/engage/trilium/)
|
||||
|
||||
[English](./README.md) | [Chinese](./docs/README-ZH_CN.md) | [Russian](./docs/README.ru.md) | [Japanese](./docs/README.ja.md) | [Italian](./docs/README.it.md) | [Spanish](./docs/README.es.md)
|
||||
[English](./README.md) | [Chinese (Simplified)](./docs/README-ZH_CN.md) | [Chinese (Traditional)](./docs/README-ZH_TW.md) | [Russian](./docs/README.ru.md) | [Japanese](./docs/README.ja.md) | [Italian](./docs/README.it.md) | [Spanish](./docs/README.es.md)
|
||||
|
||||
Trilium Notes is a free and open-source, cross-platform hierarchical note taking application with focus on building large personal knowledge bases.
|
||||
|
||||
@@ -46,15 +46,15 @@ See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for q
|
||||
- [awesome-trilium](https://github.com/Nriver/awesome-trilium) for 3rd party themes, scripts, plugins and more.
|
||||
- [TriliumRocks!](https://trilium.rocks/) for tutorials, guides, and much more.
|
||||
|
||||
## ⚠️ Why TriliumNext?
|
||||
## ❓Why TriliumNext?
|
||||
|
||||
[The original Trilium project is in maintenance mode](https://github.com/zadam/trilium/issues/4620).
|
||||
The original Trilium developer ([Zadam](https://github.com/zadam)) has graciously given the Trilium repository to the community project which resides at https://github.com/TriliumNext
|
||||
|
||||
### Migrating from Trilium?
|
||||
### ⬆️Migrating from Zadam/Trilium?
|
||||
|
||||
There are no special migration steps to migrate from a zadam/Trilium instance to a TriliumNext/Notes instance. Simply [install TriliumNext/Notes](#-installation) as usual and it will use your existing database.
|
||||
There are no special migration steps to migrate from a zadam/Trilium instance to a TriliumNext/Trilium instance. Simply [install TriliumNext/Trilium](#-installation) as usual and it will use your existing database.
|
||||
|
||||
Versions up to and including [v0.90.4](https://github.com/TriliumNext/Notes/releases/tag/v0.90.4) are compatible with the latest zadam/trilium version of [v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7). Any later versions of TriliumNext have their sync versions incremented.
|
||||
Versions up to and including [v0.90.4](https://github.com/TriliumNext/Trilium/releases/tag/v0.90.4) are compatible with the latest zadam/trilium version of [v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7). Any later versions of TriliumNext/Trilium have their sync versions incremented which prevents direct migration.
|
||||
|
||||
## 📖 Documentation
|
||||
|
||||
@@ -75,14 +75,14 @@ Feel free to join our official conversations. We would love to hear what feature
|
||||
|
||||
- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (For synchronous discussions.)
|
||||
- The `General` Matrix room is also bridged to [XMPP](xmpp:discuss@trilium.thisgreat.party?join)
|
||||
- [Github Discussions](https://github.com/TriliumNext/Notes/discussions) (For asynchronous discussions.)
|
||||
- [Github Issues](https://github.com/TriliumNext/Notes/issues) (For bug reports and feature requests.)
|
||||
- [Github Discussions](https://github.com/TriliumNext/Trilium/discussions) (For asynchronous discussions.)
|
||||
- [Github Issues](https://github.com/TriliumNext/Trilium/issues) (For bug reports and feature requests.)
|
||||
|
||||
## 🏗 Installation
|
||||
|
||||
### Windows / MacOS
|
||||
|
||||
Download the binary release for your platform from the [latest release page](https://github.com/TriliumNext/Notes/releases/latest), unzip the package and run the `trilium` executable.
|
||||
Download the binary release for your platform from the [latest release page](https://github.com/TriliumNext/Trilium/releases/latest), unzip the package and run the `trilium` executable.
|
||||
|
||||
### Linux
|
||||
|
||||
@@ -90,7 +90,7 @@ If your distribution is listed in the table below, use your distribution's packa
|
||||
|
||||
[](https://repology.org/project/triliumnext/versions)
|
||||
|
||||
You may also download the binary release for your platform from the [latest release page](https://github.com/TriliumNext/Notes/releases/latest), unzip the package and run the `trilium` executable.
|
||||
You may also download the binary release for your platform from the [latest release page](https://github.com/TriliumNext/Trilium/releases/latest), unzip the package and run the `trilium` executable.
|
||||
|
||||
TriliumNext is also provided as a Flatpak, but not yet published on FlatHub.
|
||||
|
||||
@@ -104,23 +104,33 @@ Currently only the latest versions of Chrome & Firefox are supported (and tested
|
||||
|
||||
To use TriliumNext on a mobile device, you can use a mobile web browser to access the mobile interface of a server installation (see below).
|
||||
|
||||
If you prefer a native Android app, you can use [TriliumDroid](https://apt.izzysoft.de/fdroid/index/apk/eu.fliegendewurst.triliumdroid). Report bugs and missing features at [their repository](https://github.com/FliegendeWurst/TriliumDroid).
|
||||
See issue https://github.com/TriliumNext/Trilium/issues/4962 for more information on mobile app support.
|
||||
|
||||
See issue https://github.com/TriliumNext/Notes/issues/72 for more information on mobile app support.
|
||||
If you prefer a native Android app, you can use [TriliumDroid](https://apt.izzysoft.de/fdroid/index/apk/eu.fliegendewurst.triliumdroid).
|
||||
Report bugs and missing features at [their repository](https://github.com/FliegendeWurst/TriliumDroid).
|
||||
Note: It is best to disable automatic updates on your server installation (see below) when using TriliumDroid since the sync version must match between Trilium and TriliumDroid.
|
||||
|
||||
### Server
|
||||
|
||||
To install TriliumNext on your own server (including via Docker from [Dockerhub](https://hub.docker.com/r/triliumnext/notes)) follow [the server installation docs](https://triliumnext.github.io/Docs/Wiki/server-installation).
|
||||
To install TriliumNext on your own server (including via Docker from [Dockerhub](https://hub.docker.com/r/triliumnext/trilium)) follow [the server installation docs](https://triliumnext.github.io/Docs/Wiki/server-installation).
|
||||
|
||||
|
||||
## 💻 Contribute
|
||||
|
||||
### Translations
|
||||
|
||||
If you are a native speaker, help us translate Trilium by heading over to our [Weblate page](https://hosted.weblate.org/engage/trilium/).
|
||||
|
||||
Here's the language coverage we have so far:
|
||||
|
||||
[](https://hosted.weblate.org/engage/trilium/)
|
||||
|
||||
### Code
|
||||
|
||||
Download the repository, install dependencies using `pnpm` and then run the server (available at http://localhost:8080):
|
||||
```shell
|
||||
git clone https://github.com/TriliumNext/Notes.git
|
||||
cd Notes
|
||||
git clone https://github.com/TriliumNext/Trilium.git
|
||||
cd Trilium
|
||||
pnpm install
|
||||
pnpm run server:start
|
||||
```
|
||||
@@ -129,8 +139,8 @@ pnpm run server:start
|
||||
|
||||
Download the repository, install dependencies using `pnpm` and then run the environment required to edit the documentation:
|
||||
```shell
|
||||
git clone https://github.com/TriliumNext/Notes.git
|
||||
cd Notes
|
||||
git clone https://github.com/TriliumNext/Trilium.git
|
||||
cd Trilium
|
||||
pnpm install
|
||||
pnpm nx run edit-docs:edit-docs
|
||||
```
|
||||
@@ -138,17 +148,17 @@ pnpm nx run edit-docs:edit-docs
|
||||
### Building the Executable
|
||||
Download the repository, install dependencies using `pnpm` and then build the desktop app for Windows:
|
||||
```shell
|
||||
git clone https://github.com/TriliumNext/Notes.git
|
||||
cd Notes
|
||||
git clone https://github.com/TriliumNext/Trilium.git
|
||||
cd Trilium
|
||||
pnpm install
|
||||
pnpm nx --project=desktop electron-forge:make -- --arch=x64 --platform=win32
|
||||
```
|
||||
|
||||
For more details, see the [development docs](https://github.com/TriliumNext/Notes/blob/develop/docs/Developer%20Guide/Developer%20Guide/Building%20and%20deployment/Running%20a%20development%20build.md).
|
||||
For more details, see the [development docs](https://github.com/TriliumNext/Trilium/tree/main/docs/Developer%20Guide/Developer%20Guide).
|
||||
|
||||
### Developer Documentation
|
||||
|
||||
Please view the [documentation guide](./docs/Developer%20Guide/Developer%20Guide/Environment%20Setup.md) for details. If you have more questions, feel free to reach out via the links described in the "Discuss with us" section above.
|
||||
Please view the [documentation guide](https://github.com/TriliumNext/Trilium/blob/main/docs/Developer%20Guide/Developer%20Guide/Environment%20Setup.md) for details. If you have more questions, feel free to reach out via the links described in the "Discuss with us" section above.
|
||||
|
||||
## 👏 Shoutouts
|
||||
|
||||
@@ -160,7 +170,7 @@ Please view the [documentation guide](./docs/Developer%20Guide/Developer%20Guide
|
||||
## 🤝 Support
|
||||
|
||||
Support for the TriliumNext organization will be possible in the near future. For now, you can:
|
||||
- Support continued development on TriliumNext by supporting our developers: [eliandoran](https://github.com/sponsors/eliandoran) (See the [repository insights]([developers]([url](https://github.com/TriliumNext/Notes/graphs/contributors))) for a full list)
|
||||
- Support continued development on TriliumNext by supporting our developers: [eliandoran](https://github.com/sponsors/eliandoran) (See the [repository insights]([developers]([url](https://github.com/TriliumNext/trilium/graphs/contributors))) for a full list)
|
||||
- Show a token of gratitude to the original Trilium developer ([zadam](https://github.com/sponsors/zadam)) via [PayPal](https://paypal.me/za4am) or Bitcoin (bitcoin:bc1qv3svjn40v89mnkre5vyvs2xw6y8phaltl385d2).
|
||||
|
||||
|
||||
|
||||
@@ -35,13 +35,13 @@
|
||||
"chore:generate-openapi": "tsx bin/generate-openapi.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "1.53.1",
|
||||
"@stylistic/eslint-plugin": "5.0.0",
|
||||
"@playwright/test": "1.55.0",
|
||||
"@stylistic/eslint-plugin": "5.2.3",
|
||||
"@types/express": "5.0.3",
|
||||
"@types/node": "22.15.33",
|
||||
"@types/node": "22.17.2",
|
||||
"@types/yargs": "17.0.33",
|
||||
"@vitest/coverage-v8": "3.2.4",
|
||||
"eslint": "9.29.0",
|
||||
"eslint": "9.34.0",
|
||||
"eslint-plugin-simple-import-sort": "12.1.1",
|
||||
"esm": "3.2.25",
|
||||
"jsdoc": "4.0.4",
|
||||
@@ -49,8 +49,8 @@
|
||||
"rcedit": "4.0.1",
|
||||
"rimraf": "6.0.1",
|
||||
"tslib": "2.8.1",
|
||||
"typedoc": "0.28.5",
|
||||
"typedoc-plugin-missing-exports": "4.0.0"
|
||||
"typedoc": "0.28.10",
|
||||
"typedoc-plugin-missing-exports": "4.1.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"appdmg": "0.6.6"
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
# Note: This key must only be used for the Trilium Notes project.
|
||||
# Expires on: 2025-09-13
|
||||
VITE_CKEDITOR_KEY=eyJhbGciOiJFUzI1NiJ9.eyJleHAiOjE3NTc3MjE1OTksImp0aSI6ImFiN2E0NjZmLWJlZGMtNDNiYy1iMzU4LTk0NGQ0YWJhY2I3ZiIsImRpc3RyaWJ1dGlvbkNoYW5uZWwiOlsic2giLCJkcnVwYWwiXSwid2hpdGVMYWJlbCI6dHJ1ZSwiZmVhdHVyZXMiOlsiRFJVUCIsIkNNVCIsIkRPIiwiRlAiLCJTQyIsIlRPQyIsIlRQTCIsIlBPRSIsIkNDIiwiTUYiLCJTRUUiLCJFQ0giLCJFSVMiXSwidmMiOiI1MzlkOWY5YyJ9.2rvKPql4hmukyXhEtWPZ8MLxKvzPIwzCdykO653g7IxRRZy2QJpeRszElZx9DakKYZKXekVRAwQKgHxwkgbE_w
|
||||
VITE_CKEDITOR_ENABLE_INSPECTOR=false
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@triliumnext/client",
|
||||
"version": "0.96.0",
|
||||
"version": "0.98.0",
|
||||
"description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0-only",
|
||||
@@ -10,16 +10,17 @@
|
||||
"url": "https://github.com/TriliumNext/Notes"
|
||||
},
|
||||
"dependencies": {
|
||||
"@eslint/js": "9.29.0",
|
||||
"@eslint/js": "9.34.0",
|
||||
"@excalidraw/excalidraw": "0.18.0",
|
||||
"@fullcalendar/core": "6.1.17",
|
||||
"@fullcalendar/daygrid": "6.1.17",
|
||||
"@fullcalendar/interaction": "6.1.17",
|
||||
"@fullcalendar/list": "6.1.17",
|
||||
"@fullcalendar/multimonth": "6.1.17",
|
||||
"@fullcalendar/timegrid": "6.1.17",
|
||||
"@mermaid-js/layout-elk": "0.1.8",
|
||||
"@mind-elixir/node-menu": "1.0.5",
|
||||
"@fullcalendar/core": "6.1.19",
|
||||
"@fullcalendar/daygrid": "6.1.19",
|
||||
"@fullcalendar/interaction": "6.1.19",
|
||||
"@fullcalendar/list": "6.1.19",
|
||||
"@fullcalendar/multimonth": "6.1.19",
|
||||
"@fullcalendar/timegrid": "6.1.19",
|
||||
"@maplibre/maplibre-gl-leaflet": "0.1.3",
|
||||
"@mermaid-js/layout-elk": "0.1.9",
|
||||
"@mind-elixir/node-menu": "5.0.0",
|
||||
"@popperjs/core": "2.11.8",
|
||||
"@triliumnext/ckeditor5": "workspace:*",
|
||||
"@triliumnext/codemirror": "workspace:*",
|
||||
@@ -33,12 +34,11 @@
|
||||
"dayjs-plugin-utc": "0.1.2",
|
||||
"debounce": "2.2.0",
|
||||
"draggabilly": "3.0.0",
|
||||
"force-graph": "1.49.6",
|
||||
"globals": "16.2.0",
|
||||
"i18next": "25.2.1",
|
||||
"force-graph": "1.50.1",
|
||||
"globals": "16.3.0",
|
||||
"i18next": "25.4.1",
|
||||
"i18next-http-backend": "3.0.2",
|
||||
"jquery": "3.7.1",
|
||||
"jquery-hotkeys": "0.2.2",
|
||||
"jquery.fancytree": "2.38.5",
|
||||
"jsplumb": "2.15.6",
|
||||
"katex": "0.16.22",
|
||||
@@ -46,27 +46,31 @@
|
||||
"leaflet": "1.9.4",
|
||||
"leaflet-gpx": "2.2.0",
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "15.0.12",
|
||||
"mermaid": "11.7.0",
|
||||
"mind-elixir": "4.6.1",
|
||||
"marked": "16.2.0",
|
||||
"mermaid": "11.10.1",
|
||||
"mind-elixir": "5.0.6",
|
||||
"normalize.css": "8.0.1",
|
||||
"panzoom": "9.4.3",
|
||||
"preact": "10.26.9",
|
||||
"preact": "10.27.1",
|
||||
"react-i18next": "15.7.2",
|
||||
"split.js": "1.6.5",
|
||||
"svg-pan-zoom": "3.6.2",
|
||||
"tabulator-tables": "6.3.1",
|
||||
"vanilla-js-wheel-zoom": "9.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ckeditor/ckeditor5-inspector": "4.1.0",
|
||||
"@ckeditor/ckeditor5-inspector": "5.0.0",
|
||||
"@preact/preset-vite": "2.10.2",
|
||||
"@types/bootstrap": "5.2.10",
|
||||
"@types/jquery": "3.5.32",
|
||||
"@types/leaflet": "1.9.19",
|
||||
"@types/leaflet": "1.9.20",
|
||||
"@types/leaflet-gpx": "1.3.7",
|
||||
"@types/mark.js": "8.11.12",
|
||||
"copy-webpack-plugin": "13.0.0",
|
||||
"@types/tabulator-tables": "6.2.10",
|
||||
"copy-webpack-plugin": "13.0.1",
|
||||
"happy-dom": "18.0.1",
|
||||
"script-loader": "0.7.2",
|
||||
"vite-plugin-static-copy": "3.1.0"
|
||||
"vite-plugin-static-copy": "3.1.2"
|
||||
},
|
||||
"nx": {
|
||||
"name": "client",
|
||||
|
||||
@@ -28,6 +28,9 @@ import TouchBarComponent from "./touch_bar.js";
|
||||
import type { CKTextEditor } from "@triliumnext/ckeditor5";
|
||||
import type CodeMirror from "@triliumnext/codemirror";
|
||||
import { StartupChecks } from "./startup_checks.js";
|
||||
import type { CreateNoteOpts } from "../services/note_create.js";
|
||||
import { ColumnComponent } from "tabulator-tables";
|
||||
import { ChooseNoteTypeCallback } from "../widgets/dialogs/note_type_chooser.jsx";
|
||||
|
||||
interface Layout {
|
||||
getRootWidget: (appContext: AppContext) => RootWidget;
|
||||
@@ -90,7 +93,9 @@ export type CommandMappings = {
|
||||
closeTocCommand: CommandData;
|
||||
closeHlt: CommandData;
|
||||
showLaunchBarSubtree: CommandData;
|
||||
showRevisions: CommandData;
|
||||
showRevisions: CommandData & {
|
||||
noteId?: string | null;
|
||||
};
|
||||
showLlmChat: CommandData;
|
||||
createAiChat: CommandData;
|
||||
showOptions: CommandData & {
|
||||
@@ -122,6 +127,7 @@ export type CommandMappings = {
|
||||
showImportDialog: CommandData & { noteId: string };
|
||||
openNewNoteSplit: NoteCommandData;
|
||||
openInWindow: NoteCommandData;
|
||||
openInPopup: CommandData & { noteIdOrPath: string; };
|
||||
openNoteInNewTab: CommandData;
|
||||
openNoteInNewSplit: CommandData;
|
||||
openNoteInNewWindow: CommandData;
|
||||
@@ -130,6 +136,8 @@ export type CommandMappings = {
|
||||
hideLeftPane: CommandData;
|
||||
showCpuArchWarning: CommandData;
|
||||
showLeftPane: CommandData;
|
||||
showAttachments: CommandData;
|
||||
showSearchHistory: CommandData;
|
||||
hoistNote: CommandData & { noteId: string };
|
||||
leaveProtectedSession: CommandData;
|
||||
enterProtectedSession: CommandData;
|
||||
@@ -140,6 +148,7 @@ export type CommandMappings = {
|
||||
};
|
||||
openInTab: ContextMenuCommandData;
|
||||
openNoteInSplit: ContextMenuCommandData;
|
||||
openNoteInPopup: ContextMenuCommandData;
|
||||
toggleNoteHoisting: ContextMenuCommandData;
|
||||
insertNoteAfter: ContextMenuCommandData;
|
||||
insertChildNote: ContextMenuCommandData;
|
||||
@@ -169,7 +178,7 @@ export type CommandMappings = {
|
||||
deleteNotes: ContextMenuCommandData;
|
||||
importIntoNote: ContextMenuCommandData;
|
||||
exportNote: ContextMenuCommandData;
|
||||
searchInSubtree: ContextMenuCommandData;
|
||||
searchInSubtree: CommandData & { notePath: string; };
|
||||
moveNoteUp: ContextMenuCommandData;
|
||||
moveNoteDown: ContextMenuCommandData;
|
||||
moveNoteUpInHierarchy: ContextMenuCommandData;
|
||||
@@ -258,10 +267,76 @@ export type CommandMappings = {
|
||||
closeThisNoteSplit: CommandData;
|
||||
moveThisNoteSplit: CommandData & { isMovingLeft: boolean };
|
||||
jumpToNote: CommandData;
|
||||
commandPalette: CommandData;
|
||||
|
||||
// Keyboard shortcuts
|
||||
backInNoteHistory: CommandData;
|
||||
forwardInNoteHistory: CommandData;
|
||||
forceSaveRevision: CommandData;
|
||||
scrollToActiveNote: CommandData;
|
||||
quickSearch: CommandData;
|
||||
collapseTree: CommandData;
|
||||
createNoteAfter: CommandData;
|
||||
createNoteInto: CommandData;
|
||||
addNoteAboveToSelection: CommandData;
|
||||
addNoteBelowToSelection: CommandData;
|
||||
openNewTab: CommandData;
|
||||
activateNextTab: CommandData;
|
||||
activatePreviousTab: CommandData;
|
||||
openNewWindow: CommandData;
|
||||
toggleTray: CommandData;
|
||||
firstTab: CommandData;
|
||||
secondTab: CommandData;
|
||||
thirdTab: CommandData;
|
||||
fourthTab: CommandData;
|
||||
fifthTab: CommandData;
|
||||
sixthTab: CommandData;
|
||||
seventhTab: CommandData;
|
||||
eigthTab: CommandData;
|
||||
ninthTab: CommandData;
|
||||
lastTab: CommandData;
|
||||
showNoteSource: CommandData;
|
||||
showSQLConsole: CommandData;
|
||||
showBackendLog: CommandData;
|
||||
showCheatsheet: CommandData;
|
||||
showHelp: CommandData;
|
||||
addLinkToText: CommandData;
|
||||
followLinkUnderCursor: CommandData;
|
||||
insertDateTimeToText: CommandData;
|
||||
pasteMarkdownIntoText: CommandData;
|
||||
cutIntoNote: CommandData;
|
||||
addIncludeNoteToText: CommandData;
|
||||
editReadOnlyNote: CommandData;
|
||||
toggleRibbonTabClassicEditor: CommandData;
|
||||
toggleRibbonTabBasicProperties: CommandData;
|
||||
toggleRibbonTabBookProperties: CommandData;
|
||||
toggleRibbonTabFileProperties: CommandData;
|
||||
toggleRibbonTabImageProperties: CommandData;
|
||||
toggleRibbonTabOwnedAttributes: CommandData;
|
||||
toggleRibbonTabInheritedAttributes: CommandData;
|
||||
toggleRibbonTabPromotedAttributes: CommandData;
|
||||
toggleRibbonTabNoteMap: CommandData;
|
||||
toggleRibbonTabNoteInfo: CommandData;
|
||||
toggleRibbonTabNotePaths: CommandData;
|
||||
toggleRibbonTabSimilarNotes: CommandData;
|
||||
toggleRightPane: CommandData;
|
||||
printActiveNote: CommandData;
|
||||
exportAsPdf: CommandData;
|
||||
openNoteExternally: CommandData;
|
||||
renderActiveNote: CommandData;
|
||||
unhoist: CommandData;
|
||||
reloadFrontendApp: CommandData;
|
||||
openDevTools: CommandData;
|
||||
findInText: CommandData;
|
||||
toggleLeftPane: CommandData;
|
||||
toggleFullscreen: CommandData;
|
||||
zoomOut: CommandData;
|
||||
zoomIn: CommandData;
|
||||
zoomReset: CommandData;
|
||||
copyWithoutFormatting: CommandData;
|
||||
|
||||
// Geomap
|
||||
deleteFromMap: { noteId: string };
|
||||
openGeoLocation: { noteId: string; event: JQuery.MouseDownEvent };
|
||||
|
||||
toggleZenMode: CommandData;
|
||||
|
||||
@@ -275,12 +350,30 @@ export type CommandMappings = {
|
||||
|
||||
geoMapCreateChildNote: CommandData;
|
||||
|
||||
// Table view
|
||||
addNewRow: CommandData & {
|
||||
customOpts: CreateNoteOpts;
|
||||
parentNotePath?: string;
|
||||
};
|
||||
addNewTableColumn: CommandData & {
|
||||
columnToEdit?: ColumnComponent;
|
||||
referenceColumn?: ColumnComponent;
|
||||
direction?: "before" | "after";
|
||||
type?: "label" | "relation";
|
||||
};
|
||||
deleteTableColumn: CommandData & {
|
||||
columnToDelete?: ColumnComponent;
|
||||
};
|
||||
|
||||
buildTouchBar: CommandData & {
|
||||
TouchBar: typeof TouchBar;
|
||||
buildIcon(name: string): NativeImage;
|
||||
};
|
||||
refreshTouchBar: CommandData;
|
||||
reloadTextEditor: CommandData;
|
||||
chooseNoteType: CommandData & {
|
||||
callback: ChooseNoteTypeCallback
|
||||
}
|
||||
};
|
||||
|
||||
type EventMappings = {
|
||||
|
||||
@@ -93,11 +93,7 @@ export class TypedComponent<ChildT extends TypedComponent<ChildT>> {
|
||||
|
||||
if (fun) {
|
||||
return this.callMethod(fun, data);
|
||||
} else {
|
||||
if (!this.parent) {
|
||||
throw new Error(`Component "${this.componentId}" does not have a parent attached to propagate a command.`);
|
||||
}
|
||||
|
||||
} else if (this.parent) {
|
||||
return this.parent.triggerCommand(name, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,13 +30,6 @@ interface CreateChildrenResponse {
|
||||
export default class Entrypoints extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
if (jQuery.hotkeys) {
|
||||
// hot keys are active also inside inputs and content editables
|
||||
jQuery.hotkeys.options.filterInputAcceptingElements = false;
|
||||
jQuery.hotkeys.options.filterContentEditable = false;
|
||||
jQuery.hotkeys.options.filterTextInputs = false;
|
||||
}
|
||||
}
|
||||
|
||||
openDevToolsCommand() {
|
||||
@@ -113,7 +106,9 @@ export default class Entrypoints extends Component {
|
||||
if (win.isFullScreenable()) {
|
||||
win.setFullScreen(!win.isFullScreen());
|
||||
}
|
||||
} // outside of electron this is handled by the browser
|
||||
} else {
|
||||
document.documentElement.requestFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
reloadFrontendAppCommand() {
|
||||
|
||||
@@ -315,14 +315,39 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
|
||||
}
|
||||
|
||||
hasNoteList() {
|
||||
return (
|
||||
this.note &&
|
||||
["default", "contextual-help"].includes(this.viewScope?.viewMode ?? "") &&
|
||||
(this.note.hasChildren() || this.note.getLabelValue("viewType") === "calendar") &&
|
||||
["book", "text", "code"].includes(this.note.type) &&
|
||||
this.note.mime !== "text/x-sqlite;schema=trilium" &&
|
||||
!this.note.isLabelTruthy("hideChildrenOverview")
|
||||
);
|
||||
const note = this.note;
|
||||
|
||||
if (!note) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!["default", "contextual-help"].includes(this.viewScope?.viewMode ?? "")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Collections must always display a note list, even if no children.
|
||||
const viewType = note.getLabelValue("viewType") ?? "grid";
|
||||
if (!["list", "grid"].includes(viewType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!note.hasChildren()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!["book", "text", "code"].includes(note.type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (note.mime === "text/x-sqlite;schema=trilium") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (note.isLabelTruthy("hideChildrenOverview")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async getTextEditor(callback?: GetTextEditorCallback) {
|
||||
|
||||
@@ -13,7 +13,6 @@ import type ElectronRemote from "@electron/remote";
|
||||
import type Electron from "electron";
|
||||
import "./stylesheets/bootstrap.scss";
|
||||
import "boxicons/css/boxicons.min.css";
|
||||
import "jquery-hotkeys";
|
||||
import "autocomplete.js/index_jquery.js";
|
||||
|
||||
await appContext.earlyInit();
|
||||
|
||||
@@ -27,7 +27,6 @@ const NOTE_TYPE_ICONS = {
|
||||
doc: "bx bxs-file-doc",
|
||||
contentWidget: "bx bxs-widget",
|
||||
mindMap: "bx bx-sitemap",
|
||||
geoMap: "bx bx-map-alt",
|
||||
aiChat: "bx bx-bot"
|
||||
};
|
||||
|
||||
@@ -36,7 +35,7 @@ const NOTE_TYPE_ICONS = {
|
||||
* end user. Those types should be used only for checking against, they are
|
||||
* not for direct use.
|
||||
*/
|
||||
export type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code" | "mindMap" | "geoMap" | "aiChat";
|
||||
export type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code" | "mindMap" | "aiChat";
|
||||
|
||||
export interface NotePathRecord {
|
||||
isArchived: boolean;
|
||||
@@ -257,6 +256,20 @@ class FNote {
|
||||
return this.children;
|
||||
}
|
||||
|
||||
async getSubtreeNoteIds() {
|
||||
let noteIds: (string | string[])[] = [];
|
||||
for (const child of await this.getChildNotes()) {
|
||||
noteIds.push(child.noteId);
|
||||
noteIds.push(await child.getSubtreeNoteIds());
|
||||
}
|
||||
return noteIds.flat();
|
||||
}
|
||||
|
||||
async getSubtreeNotes() {
|
||||
const noteIds = await this.getSubtreeNoteIds();
|
||||
return this.froca.getNotes(noteIds);
|
||||
}
|
||||
|
||||
async getChildNotes() {
|
||||
return await this.froca.getNotes(this.children);
|
||||
}
|
||||
|
||||
@@ -46,28 +46,7 @@ import SharedInfoWidget from "../widgets/shared_info.js";
|
||||
import FindWidget from "../widgets/find.js";
|
||||
import TocWidget from "../widgets/toc.js";
|
||||
import HighlightsListWidget from "../widgets/highlights_list.js";
|
||||
import BulkActionsDialog from "../widgets/dialogs/bulk_actions.js";
|
||||
import AboutDialog from "../widgets/dialogs/about.js";
|
||||
import HelpDialog from "../widgets/dialogs/help.js";
|
||||
import RecentChangesDialog from "../widgets/dialogs/recent_changes.js";
|
||||
import BranchPrefixDialog from "../widgets/dialogs/branch_prefix.js";
|
||||
import SortChildNotesDialog from "../widgets/dialogs/sort_child_notes.js";
|
||||
import PasswordNoteSetDialog from "../widgets/dialogs/password_not_set.js";
|
||||
import IncludeNoteDialog from "../widgets/dialogs/include_note.js";
|
||||
import NoteTypeChooserDialog from "../widgets/dialogs/note_type_chooser.js";
|
||||
import JumpToNoteDialog from "../widgets/dialogs/jump_to_note.js";
|
||||
import AddLinkDialog from "../widgets/dialogs/add_link.js";
|
||||
import CloneToDialog from "../widgets/dialogs/clone_to.js";
|
||||
import MoveToDialog from "../widgets/dialogs/move_to.js";
|
||||
import ImportDialog from "../widgets/dialogs/import.js";
|
||||
import ExportDialog from "../widgets/dialogs/export.js";
|
||||
import MarkdownImportDialog from "../widgets/dialogs/markdown_import.js";
|
||||
import ProtectedSessionPasswordDialog from "../widgets/dialogs/protected_session_password.js";
|
||||
import RevisionsDialog from "../widgets/dialogs/revisions.js";
|
||||
import DeleteNotesDialog from "../widgets/dialogs/delete_notes.js";
|
||||
import InfoDialog from "../widgets/dialogs/info.js";
|
||||
import ConfirmDialog from "../widgets/dialogs/confirm.js";
|
||||
import PromptDialog from "../widgets/dialogs/prompt.js";
|
||||
import FloatingButtons from "../widgets/floating_buttons/floating_buttons.js";
|
||||
import RelationMapButtons from "../widgets/floating_buttons/relation_map_buttons.js";
|
||||
import SvgExportButton from "../widgets/floating_buttons/svg_export_button.js";
|
||||
@@ -83,7 +62,7 @@ import CopyImageReferenceButton from "../widgets/floating_buttons/copy_image_ref
|
||||
import ScrollPaddingWidget from "../widgets/scroll_padding.js";
|
||||
import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js";
|
||||
import options from "../services/options.js";
|
||||
import utils, { hasTouchBar } from "../services/utils.js";
|
||||
import utils from "../services/utils.js";
|
||||
import GeoMapButtons from "../widgets/floating_buttons/geo_map_button.js";
|
||||
import ContextualHelpButton from "../widgets/floating_buttons/help_button.js";
|
||||
import CloseZenButton from "../widgets/close_zen_button.js";
|
||||
@@ -229,7 +208,7 @@ export default class DesktopLayout {
|
||||
.child(new PromotedAttributesWidget())
|
||||
.child(new SqlTableSchemasWidget())
|
||||
.child(new NoteDetailWidget())
|
||||
.child(new NoteListWidget())
|
||||
.child(new NoteListWidget(false))
|
||||
.child(new SearchResultWidget())
|
||||
.child(new SqlResultWidget())
|
||||
.child(new ScrollPaddingWidget())
|
||||
|
||||
@@ -22,6 +22,15 @@ import RevisionsDialog from "../widgets/dialogs/revisions.js";
|
||||
import DeleteNotesDialog from "../widgets/dialogs/delete_notes.js";
|
||||
import InfoDialog from "../widgets/dialogs/info.js";
|
||||
import IncorrectCpuArchDialog from "../widgets/dialogs/incorrect_cpu_arch.js";
|
||||
import PopupEditorDialog from "../widgets/dialogs/popup_editor.js";
|
||||
import FlexContainer from "../widgets/containers/flex_container.js";
|
||||
import NoteIconWidget from "../widgets/note_icon.js";
|
||||
import NoteTitleWidget from "../widgets/note_title.js";
|
||||
import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js";
|
||||
import PromotedAttributesWidget from "../widgets/ribbon_widgets/promoted_attributes.js";
|
||||
import NoteDetailWidget from "../widgets/note_detail.js";
|
||||
import NoteListWidget from "../widgets/note_list.js";
|
||||
import { CallToActionDialog } from "../widgets/dialogs/call_to_action.jsx";
|
||||
|
||||
export function applyModals(rootContainer: RootContainer) {
|
||||
rootContainer
|
||||
@@ -47,4 +56,16 @@ export function applyModals(rootContainer: RootContainer) {
|
||||
.child(new ConfirmDialog())
|
||||
.child(new PromptDialog())
|
||||
.child(new IncorrectCpuArchDialog())
|
||||
.child(new PopupEditorDialog()
|
||||
.child(new FlexContainer("row")
|
||||
.class("title-row")
|
||||
.css("align-items", "center")
|
||||
.cssBlock(".title-row > * { margin: 5px; }")
|
||||
.child(new NoteIconWidget())
|
||||
.child(new NoteTitleWidget()))
|
||||
.child(new ClassicEditorToolbar())
|
||||
.child(new PromotedAttributesWidget())
|
||||
.child(new NoteDetailWidget())
|
||||
.child(new NoteListWidget(true)))
|
||||
.child(new CallToActionDialog());
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import TabRowWidget from "../widgets/tab_row.js";
|
||||
import RefreshButton from "../widgets/floating_buttons/refresh_button.js";
|
||||
import MobileEditorToolbar from "../widgets/ribbon_widgets/mobile_editor_toolbar.js";
|
||||
import { applyModals } from "./layout_commons.js";
|
||||
import CloseZenButton from "../widgets/close_zen_button.js";
|
||||
|
||||
const MOBILE_CSS = `
|
||||
<style>
|
||||
@@ -162,7 +163,7 @@ export default class MobileLayout {
|
||||
.filling()
|
||||
.contentSized()
|
||||
.child(new NoteDetailWidget())
|
||||
.child(new NoteListWidget())
|
||||
.child(new NoteListWidget(false))
|
||||
.child(new FilePropertiesWidget().css("font-size", "smaller"))
|
||||
)
|
||||
.child(new MobileEditorToolbar())
|
||||
@@ -174,7 +175,8 @@ export default class MobileLayout {
|
||||
.id("mobile-bottom-bar")
|
||||
.child(new TabRowWidget().css("height", "40px"))
|
||||
.child(new FlexContainer("row").class("horizontal").css("height", "53px").child(new LauncherContainer(true)).child(new GlobalMenuWidget(true)).id("launcher-pane"))
|
||||
);
|
||||
)
|
||||
.child(new CloseZenButton());
|
||||
applyModals(rootContainer);
|
||||
return rootContainer;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import keyboardActionService from "../services/keyboard_actions.js";
|
||||
import note_tooltip from "../services/note_tooltip.js";
|
||||
import utils from "../services/utils.js";
|
||||
|
||||
interface ContextMenuOptions<T> {
|
||||
export interface ContextMenuOptions<T> {
|
||||
x: number;
|
||||
y: number;
|
||||
orientation?: "left";
|
||||
@@ -17,17 +17,30 @@ interface MenuSeparatorItem {
|
||||
title: "----";
|
||||
}
|
||||
|
||||
export interface MenuItemBadge {
|
||||
title: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export interface MenuCommandItem<T> {
|
||||
title: string;
|
||||
command?: T;
|
||||
type?: string;
|
||||
/**
|
||||
* The icon to display in the menu item.
|
||||
*
|
||||
* If not set, no icon is displayed and the item will appear shifted slightly to the left if there are other items with icons. To avoid this, use `bx bx-empty`.
|
||||
*/
|
||||
uiIcon?: string;
|
||||
badges?: MenuItemBadge[];
|
||||
templateNoteId?: string;
|
||||
enabled?: boolean;
|
||||
handler?: MenuHandler<T>;
|
||||
items?: MenuItem<T>[] | null;
|
||||
shortcut?: string;
|
||||
spellingSuggestion?: string;
|
||||
checked?: boolean;
|
||||
columns?: number;
|
||||
}
|
||||
|
||||
export type MenuItem<T> = MenuCommandItem<T> | MenuSeparatorItem;
|
||||
@@ -146,17 +159,32 @@ class ContextMenu {
|
||||
} else {
|
||||
const $icon = $("<span>");
|
||||
|
||||
if ("uiIcon" in item && item.uiIcon) {
|
||||
$icon.addClass(item.uiIcon);
|
||||
if ("uiIcon" in item || "checked" in item) {
|
||||
const icon = (item.checked ? "bx bx-check" : item.uiIcon);
|
||||
if (icon) {
|
||||
$icon.addClass(icon);
|
||||
} else {
|
||||
$icon.append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
const $link = $("<span>")
|
||||
.append($icon)
|
||||
.append(" ") // some space between icon and text
|
||||
.append(item.title);
|
||||
|
||||
if ("badges" in item && item.badges) {
|
||||
for (let badge of item.badges) {
|
||||
const badgeElement = $(`<span class="badge">`).text(badge.title);
|
||||
|
||||
if (badge.className) {
|
||||
badgeElement.addClass(badge.className);
|
||||
}
|
||||
|
||||
$link.append(badgeElement);
|
||||
}
|
||||
}
|
||||
|
||||
if ("shortcut" in item && item.shortcut) {
|
||||
$link.append($("<kbd>").text(item.shortcut));
|
||||
}
|
||||
@@ -213,6 +241,9 @@ class ContextMenu {
|
||||
$link.addClass("dropdown-toggle");
|
||||
|
||||
const $subMenu = $("<ul>").addClass("dropdown-menu");
|
||||
if (!this.isMobile && item.columns) {
|
||||
$subMenu.css("column-count", item.columns);
|
||||
}
|
||||
|
||||
this.addItems($subMenu, item.items);
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@ function getItems(): MenuItem<CommandNames>[] {
|
||||
return [
|
||||
{ title: t("link_context_menu.open_note_in_new_tab"), command: "openNoteInNewTab", uiIcon: "bx bx-link-external" },
|
||||
{ title: t("link_context_menu.open_note_in_new_split"), command: "openNoteInNewSplit", uiIcon: "bx bx-dock-right" },
|
||||
{ title: t("link_context_menu.open_note_in_new_window"), command: "openNoteInNewWindow", uiIcon: "bx bx-window-open" }
|
||||
{ title: t("link_context_menu.open_note_in_new_window"), command: "openNoteInNewWindow", uiIcon: "bx bx-window-open" },
|
||||
{ title: t("link_context_menu.open_note_in_popup"), command: "openNoteInPopup", uiIcon: "bx bx-edit" }
|
||||
];
|
||||
}
|
||||
|
||||
@@ -40,6 +41,8 @@ function handleLinkContextMenuItem(command: string | undefined, notePath: string
|
||||
appContext.triggerCommand("openNewNoteSplit", { ntxId, notePath, hoistedNoteId, viewScope });
|
||||
} else if (command === "openNoteInNewWindow") {
|
||||
appContext.triggerCommand("openInWindow", { notePath, hoistedNoteId, viewScope });
|
||||
} else if (command === "openNoteInPopup") {
|
||||
appContext.triggerCommand("openInPopup", { noteIdOrPath: notePath })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ let lastTargetNode: HTMLElement | null = null;
|
||||
|
||||
// This will include all commands that implement ContextMenuCommandData, but it will not work if it additional options are added via the `|` operator,
|
||||
// so they need to be added manually.
|
||||
export type TreeCommandNames = FilteredCommandNames<ContextMenuCommandData> | "openBulkActionsDialog";
|
||||
export type TreeCommandNames = FilteredCommandNames<ContextMenuCommandData> | "openBulkActionsDialog" | "searchInSubtree";
|
||||
|
||||
export default class TreeContextMenu implements SelectMenuItemEventListener<TreeCommandNames> {
|
||||
private treeWidget: NoteTreeWidget;
|
||||
@@ -70,8 +70,8 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
|
||||
const items: (MenuItem<TreeCommandNames> | null)[] = [
|
||||
{ title: `${t("tree-context-menu.open-in-a-new-tab")}`, command: "openInTab", uiIcon: "bx bx-link-external", enabled: noSelectedNotes },
|
||||
|
||||
{ title: t("tree-context-menu.open-in-a-new-split"), command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes },
|
||||
{ title: t("tree-context-menu.open-in-popup"), command: "openNoteInPopup", uiIcon: "bx bx-edit", enabled: noSelectedNotes },
|
||||
|
||||
isHoisted
|
||||
? null
|
||||
@@ -92,7 +92,8 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
command: "insertNoteAfter",
|
||||
uiIcon: "bx bx-plus",
|
||||
items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter") : null,
|
||||
enabled: insertNoteAfterEnabled && noSelectedNotes && notOptionsOrHelp
|
||||
enabled: insertNoteAfterEnabled && noSelectedNotes && notOptionsOrHelp,
|
||||
columns: 2
|
||||
},
|
||||
|
||||
{
|
||||
@@ -100,7 +101,8 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
command: "insertChildNote",
|
||||
uiIcon: "bx bx-plus",
|
||||
items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null,
|
||||
enabled: notSearch && noSelectedNotes && notOptionsOrHelp
|
||||
enabled: notSearch && noSelectedNotes && notOptionsOrHelp,
|
||||
columns: 2
|
||||
},
|
||||
|
||||
{ title: "----" },
|
||||
@@ -127,12 +129,6 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
enabled: isNotRoot && parentNotSearch && noSelectedNotes && notOptionsOrHelp
|
||||
},
|
||||
{ title: t("tree-context-menu.convert-to-attachment"), command: "convertNoteToAttachment", uiIcon: "bx bx-paperclip", enabled: isNotRoot && !isHoisted && notOptionsOrHelp },
|
||||
{
|
||||
title: `${t("tree-context-menu.duplicate-subtree")} <kbd data-command="duplicateSubtree">`,
|
||||
command: "duplicateSubtree",
|
||||
uiIcon: "bx bx-outline",
|
||||
enabled: parentNotSearch && isNotRoot && !isHoisted && notOptionsOrHelp
|
||||
},
|
||||
|
||||
{ title: "----" },
|
||||
|
||||
@@ -186,6 +182,13 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
|
||||
{ title: `${t("tree-context-menu.clone-to")} <kbd data-command="cloneNotesTo"></kbd>`, command: "cloneNotesTo", uiIcon: "bx bx-duplicate", enabled: isNotRoot && !isHoisted },
|
||||
|
||||
{
|
||||
title: `${t("tree-context-menu.duplicate")} <kbd data-command="duplicateSubtree">`,
|
||||
command: "duplicateSubtree",
|
||||
uiIcon: "bx bx-outline",
|
||||
enabled: parentNotSearch && isNotRoot && !isHoisted && notOptionsOrHelp
|
||||
},
|
||||
|
||||
{
|
||||
title: `${t("tree-context-menu.delete")} <kbd data-command="deleteNotes"></kbd>`,
|
||||
command: "deleteNotes",
|
||||
@@ -244,6 +247,8 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
const { ntxId } = subContexts?.[subContexts.length - 1] ?? {};
|
||||
|
||||
this.treeWidget.triggerCommand("openNewNoteSplit", { ntxId, notePath });
|
||||
} else if (command === "openNoteInPopup") {
|
||||
appContext.triggerCommand("openInPopup", { noteIdOrPath: notePath })
|
||||
} else if (command === "convertNoteToAttachment") {
|
||||
if (!(await dialogService.confirm(t("tree-context-menu.convert-to-attachment-confirm")))) {
|
||||
return;
|
||||
|
||||
@@ -79,7 +79,19 @@ async function renderAttributes(attributes: FAttribute[], renderIsInheritable: b
|
||||
return $container;
|
||||
}
|
||||
|
||||
const HIDDEN_ATTRIBUTES = ["originalFileName", "fileSize", "template", "inherit", "cssClass", "iconClass", "pageSize", "viewType", "geolocation", "docName"];
|
||||
const HIDDEN_ATTRIBUTES = [
|
||||
"originalFileName",
|
||||
"fileSize",
|
||||
"template",
|
||||
"inherit",
|
||||
"cssClass",
|
||||
"iconClass",
|
||||
"pageSize",
|
||||
"viewType",
|
||||
"geolocation",
|
||||
"docName",
|
||||
"webViewSrc"
|
||||
];
|
||||
|
||||
async function renderNormalAttributes(note: FNote) {
|
||||
const promotedDefinitionAttributes = note.getPromotedDefinitionAttributes();
|
||||
|
||||
@@ -3,19 +3,21 @@ import froca from "./froca.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import type { AttributeRow } from "./load_results.js";
|
||||
|
||||
async function addLabel(noteId: string, name: string, value: string = "") {
|
||||
async function addLabel(noteId: string, name: string, value: string = "", isInheritable = false) {
|
||||
await server.put(`notes/${noteId}/attribute`, {
|
||||
type: "label",
|
||||
name: name,
|
||||
value: value
|
||||
value: value,
|
||||
isInheritable
|
||||
});
|
||||
}
|
||||
|
||||
async function setLabel(noteId: string, name: string, value: string = "") {
|
||||
export async function setLabel(noteId: string, name: string, value: string = "", isInheritable = false) {
|
||||
await server.put(`notes/${noteId}/set-attribute`, {
|
||||
type: "label",
|
||||
name: name,
|
||||
value: value
|
||||
value: value,
|
||||
isInheritable
|
||||
});
|
||||
}
|
||||
|
||||
@@ -49,7 +51,7 @@ function removeOwnedLabelByName(note: FNote, labelName: string) {
|
||||
* @param name the name of the attribute to set.
|
||||
* @param value the value of the attribute to set.
|
||||
*/
|
||||
async function setAttribute(note: FNote, type: "label" | "relation", name: string, value: string | null | undefined) {
|
||||
export async function setAttribute(note: FNote, type: "label" | "relation", name: string, value: string | null | undefined) {
|
||||
if (value) {
|
||||
// Create or update the attribute.
|
||||
await server.put(`notes/${note.noteId}/set-attribute`, { type, name, value });
|
||||
|
||||
@@ -95,7 +95,15 @@ async function moveToParentNote(branchIdsToMove: string[], newParentBranchId: st
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteNotes(branchIdsToDelete: string[], forceDeleteAllClones = false) {
|
||||
/**
|
||||
* Shows the delete confirmation screen
|
||||
*
|
||||
* @param branchIdsToDelete the list of branch IDs to delete.
|
||||
* @param forceDeleteAllClones whether to check by default the "Delete also all clones" checkbox.
|
||||
* @param moveToParent whether to automatically go to the parent note path after a succesful delete. Usually makes sense if deleting the active note(s).
|
||||
* @returns promise that returns false if the operation was cancelled or there was nothing to delete, true if the operation succeeded.
|
||||
*/
|
||||
async function deleteNotes(branchIdsToDelete: string[], forceDeleteAllClones = false, moveToParent = true) {
|
||||
branchIdsToDelete = filterRootNote(branchIdsToDelete);
|
||||
|
||||
if (branchIdsToDelete.length === 0) {
|
||||
@@ -110,11 +118,13 @@ async function deleteNotes(branchIdsToDelete: string[], forceDeleteAllClones = f
|
||||
return false;
|
||||
}
|
||||
|
||||
if (moveToParent) {
|
||||
try {
|
||||
await activateParentNotePath();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
const taskId = utils.randomString(10);
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ import AddRelationBulkAction from "../widgets/bulk_actions/relation/add_relation
|
||||
import RenameNoteBulkAction from "../widgets/bulk_actions/note/rename_note.js";
|
||||
import { t } from "./i18n.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import toast from "./toast.js";
|
||||
import { BulkAction } from "@triliumnext/commons";
|
||||
|
||||
const ACTION_GROUPS = [
|
||||
{
|
||||
@@ -89,6 +91,17 @@ function parseActions(note: FNote) {
|
||||
.filter((action) => !!action);
|
||||
}
|
||||
|
||||
export async function executeBulkActions(targetNoteIds: string[], actions: BulkAction[], includeDescendants = false) {
|
||||
await server.post("bulk-action/execute", {
|
||||
noteIds: targetNoteIds,
|
||||
includeDescendants,
|
||||
actions
|
||||
});
|
||||
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
toast.showMessage(t("bulk_actions.bulk_actions_executed"), 3000);
|
||||
}
|
||||
|
||||
export default {
|
||||
addAction,
|
||||
parseActions,
|
||||
|
||||
223
apps/client/src/services/ckeditor_plugin_config.ts
Normal file
223
apps/client/src/services/ckeditor_plugin_config.ts
Normal file
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
* @module CKEditor Plugin Configuration Service
|
||||
*
|
||||
* This service manages the dynamic configuration of CKEditor plugins based on user preferences.
|
||||
* It handles plugin enablement, dependency resolution, and toolbar configuration.
|
||||
*/
|
||||
|
||||
import server from "./server.js";
|
||||
import type {
|
||||
PluginConfiguration,
|
||||
PluginMetadata,
|
||||
PluginRegistry,
|
||||
PluginValidationResult
|
||||
} from "@triliumnext/commons";
|
||||
|
||||
/**
|
||||
* Cache for plugin registry and user configuration
|
||||
*/
|
||||
let pluginRegistryCache: PluginRegistry | null = null;
|
||||
let userConfigCache: PluginConfiguration[] | null = null;
|
||||
let cacheTimestamp = 0;
|
||||
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
/**
|
||||
* Get the plugin registry from server
|
||||
*/
|
||||
export async function getPluginRegistry(): Promise<PluginRegistry> {
|
||||
const now = Date.now();
|
||||
if (pluginRegistryCache && (now - cacheTimestamp) < CACHE_DURATION) {
|
||||
return pluginRegistryCache;
|
||||
}
|
||||
|
||||
try {
|
||||
pluginRegistryCache = await server.get<PluginRegistry>('ckeditor-plugins/registry');
|
||||
cacheTimestamp = now;
|
||||
return pluginRegistryCache;
|
||||
} catch (error) {
|
||||
console.error('Failed to load CKEditor plugin registry:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's plugin configuration from server
|
||||
*/
|
||||
export async function getUserPluginConfig(): Promise<PluginConfiguration[]> {
|
||||
const now = Date.now();
|
||||
if (userConfigCache && (now - cacheTimestamp) < CACHE_DURATION) {
|
||||
return userConfigCache;
|
||||
}
|
||||
|
||||
try {
|
||||
userConfigCache = await server.get<PluginConfiguration[]>('ckeditor-plugins/config');
|
||||
cacheTimestamp = now;
|
||||
return userConfigCache;
|
||||
} catch (error) {
|
||||
console.error('Failed to load user plugin configuration:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cache (call when configuration is updated)
|
||||
*/
|
||||
export function clearCache(): void {
|
||||
pluginRegistryCache = null;
|
||||
userConfigCache = null;
|
||||
cacheTimestamp = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the enabled plugins for the current user
|
||||
*/
|
||||
export async function getEnabledPlugins(): Promise<Set<string>> {
|
||||
const userConfig = await getUserPluginConfig();
|
||||
const enabledPlugins = new Set<string>();
|
||||
|
||||
// Add all enabled user plugins
|
||||
userConfig.forEach(config => {
|
||||
if (config.enabled) {
|
||||
enabledPlugins.add(config.id);
|
||||
}
|
||||
});
|
||||
|
||||
// Always include core plugins
|
||||
const registry = await getPluginRegistry();
|
||||
Object.values(registry.plugins).forEach(plugin => {
|
||||
if (plugin.isCore) {
|
||||
enabledPlugins.add(plugin.id);
|
||||
}
|
||||
});
|
||||
|
||||
return enabledPlugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get disabled plugin names for CKEditor config
|
||||
*/
|
||||
export async function getDisabledPlugins(): Promise<string[]> {
|
||||
try {
|
||||
const registry = await getPluginRegistry();
|
||||
const enabledPlugins = await getEnabledPlugins();
|
||||
const disabledPlugins: string[] = [];
|
||||
|
||||
// Find plugins that are disabled
|
||||
Object.values(registry.plugins).forEach(plugin => {
|
||||
if (!plugin.isCore && !enabledPlugins.has(plugin.id)) {
|
||||
// Map plugin ID to actual CKEditor plugin names if needed
|
||||
const pluginNames = getPluginNames(plugin.id);
|
||||
disabledPlugins.push(...pluginNames);
|
||||
}
|
||||
});
|
||||
|
||||
return disabledPlugins;
|
||||
} catch (error) {
|
||||
console.warn("Failed to get disabled plugins, returning empty list:", error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map plugin ID to actual CKEditor plugin names
|
||||
* Some plugins might have multiple names or different names than their ID
|
||||
*/
|
||||
function getPluginNames(pluginId: string): string[] {
|
||||
const nameMap: Record<string, string[]> = {
|
||||
"emoji": ["EmojiMention", "EmojiPicker"],
|
||||
"math": ["Math", "AutoformatMath"],
|
||||
"image": ["Image", "ImageCaption", "ImageInline", "ImageResize", "ImageStyle", "ImageToolbar", "ImageUpload"],
|
||||
"table": ["Table", "TableToolbar", "TableProperties", "TableCellProperties", "TableSelection", "TableCaption", "TableColumnResize"],
|
||||
"font": ["Font", "FontColor", "FontBackgroundColor"],
|
||||
"list": ["List", "ListProperties"],
|
||||
"specialcharacters": ["SpecialCharacters", "SpecialCharactersEssentials"],
|
||||
"findandreplace": ["FindAndReplace"],
|
||||
"horizontalline": ["HorizontalLine"],
|
||||
"pagebreak": ["PageBreak"],
|
||||
"removeformat": ["RemoveFormat"],
|
||||
"alignment": ["Alignment"],
|
||||
"indent": ["Indent", "IndentBlock"],
|
||||
"codeblock": ["CodeBlock"],
|
||||
"blockquote": ["BlockQuote"],
|
||||
"todolist": ["TodoList"],
|
||||
"heading": ["Heading", "HeadingButtonsUI"],
|
||||
"paragraph": ["ParagraphButtonUI"],
|
||||
// Add more mappings as needed
|
||||
};
|
||||
|
||||
return nameMap[pluginId] || [pluginId.charAt(0).toUpperCase() + pluginId.slice(1)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the current plugin configuration
|
||||
*/
|
||||
export async function validatePluginConfiguration(): Promise<PluginValidationResult> {
|
||||
try {
|
||||
const userConfig = await getUserPluginConfig();
|
||||
return await server.post<PluginValidationResult>('ckeditor-plugins/validate', {
|
||||
plugins: userConfig
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to validate plugin configuration:', error);
|
||||
return {
|
||||
valid: false,
|
||||
errors: [{
|
||||
type: "missing_dependency",
|
||||
pluginId: "unknown",
|
||||
message: `Validation failed: ${error}`
|
||||
}],
|
||||
warnings: [],
|
||||
resolvedPlugins: []
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get toolbar items that should be hidden based on disabled plugins
|
||||
*/
|
||||
export async function getHiddenToolbarItems(): Promise<string[]> {
|
||||
const registry = await getPluginRegistry();
|
||||
const enabledPlugins = await getEnabledPlugins();
|
||||
const hiddenItems: string[] = [];
|
||||
|
||||
Object.values(registry.plugins).forEach(plugin => {
|
||||
if (!enabledPlugins.has(plugin.id) && plugin.toolbarItems) {
|
||||
hiddenItems.push(...plugin.toolbarItems);
|
||||
}
|
||||
});
|
||||
|
||||
return hiddenItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user plugin configuration
|
||||
*/
|
||||
export async function updatePluginConfiguration(plugins: PluginConfiguration[]): Promise<void> {
|
||||
try {
|
||||
const response = await server.put('ckeditor-plugins/config', {
|
||||
plugins,
|
||||
validate: true
|
||||
});
|
||||
|
||||
if (!response.success) {
|
||||
throw new Error(response.errors?.join(", ") || "Update failed");
|
||||
}
|
||||
|
||||
// Clear cache so next requests fetch fresh data
|
||||
clearCache();
|
||||
} catch (error) {
|
||||
console.error('Failed to update plugin configuration:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getPluginRegistry,
|
||||
getUserPluginConfig,
|
||||
getEnabledPlugins,
|
||||
getDisabledPlugins,
|
||||
getHiddenToolbarItems,
|
||||
validatePluginConfiguration,
|
||||
updatePluginConfiguration,
|
||||
clearCache
|
||||
};
|
||||
295
apps/client/src/services/command_registry.ts
Normal file
295
apps/client/src/services/command_registry.ts
Normal file
@@ -0,0 +1,295 @@
|
||||
import { ActionKeyboardShortcut } from "@triliumnext/commons";
|
||||
import appContext, { type CommandNames } from "../components/app_context.js";
|
||||
import type NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import { t, translationsInitializedPromise } from "./i18n.js";
|
||||
import keyboardActions from "./keyboard_actions.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
export interface CommandDefinition {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
shortcut?: string;
|
||||
commandName?: CommandNames;
|
||||
handler?: () => Promise<unknown> | null | undefined | void;
|
||||
aliases?: string[];
|
||||
source?: "manual" | "keyboard-action";
|
||||
/** Reference to the original keyboard action for scope checking. */
|
||||
keyboardAction?: ActionKeyboardShortcut;
|
||||
}
|
||||
|
||||
class CommandRegistry {
|
||||
private commands: Map<string, CommandDefinition> = new Map();
|
||||
private aliases: Map<string, string> = new Map();
|
||||
|
||||
constructor() {
|
||||
this.loadCommands();
|
||||
}
|
||||
|
||||
private async loadCommands() {
|
||||
await translationsInitializedPromise;
|
||||
this.registerDefaultCommands();
|
||||
await this.loadKeyboardActionsAsync();
|
||||
}
|
||||
|
||||
private registerDefaultCommands() {
|
||||
this.register({
|
||||
id: "export-note",
|
||||
name: t("command_palette.export_note_title"),
|
||||
description: t("command_palette.export_note_description"),
|
||||
icon: "bx bx-export",
|
||||
handler: () => {
|
||||
const notePath = appContext.tabManager.getActiveContextNotePath();
|
||||
if (notePath) {
|
||||
appContext.triggerCommand("showExportDialog", {
|
||||
notePath,
|
||||
defaultType: "single"
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.register({
|
||||
id: "show-attachments",
|
||||
name: t("command_palette.show_attachments_title"),
|
||||
description: t("command_palette.show_attachments_description"),
|
||||
icon: "bx bx-paperclip",
|
||||
handler: () => appContext.triggerCommand("showAttachments")
|
||||
});
|
||||
|
||||
// Special search commands with custom logic
|
||||
this.register({
|
||||
id: "search-notes",
|
||||
name: t("command_palette.search_notes_title"),
|
||||
description: t("command_palette.search_notes_description"),
|
||||
icon: "bx bx-search",
|
||||
handler: () => appContext.triggerCommand("searchNotes", {})
|
||||
});
|
||||
|
||||
this.register({
|
||||
id: "search-in-subtree",
|
||||
name: t("command_palette.search_subtree_title"),
|
||||
description: t("command_palette.search_subtree_description"),
|
||||
icon: "bx bx-search-alt",
|
||||
handler: () => {
|
||||
const notePath = appContext.tabManager.getActiveContextNotePath();
|
||||
if (notePath) {
|
||||
appContext.triggerCommand("searchInSubtree", { notePath });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.register({
|
||||
id: "show-search-history",
|
||||
name: t("command_palette.search_history_title"),
|
||||
description: t("command_palette.search_history_description"),
|
||||
icon: "bx bx-history",
|
||||
handler: () => appContext.triggerCommand("showSearchHistory")
|
||||
});
|
||||
|
||||
this.register({
|
||||
id: "show-launch-bar",
|
||||
name: t("command_palette.configure_launch_bar_title"),
|
||||
description: t("command_palette.configure_launch_bar_description"),
|
||||
icon: "bx bx-sidebar",
|
||||
handler: () => appContext.triggerCommand("showLaunchBarSubtree")
|
||||
});
|
||||
}
|
||||
|
||||
private async loadKeyboardActionsAsync() {
|
||||
try {
|
||||
const actions = await keyboardActions.getActions();
|
||||
this.registerKeyboardActions(actions);
|
||||
} catch (error) {
|
||||
console.error("Failed to load keyboard actions:", error);
|
||||
}
|
||||
}
|
||||
|
||||
private registerKeyboardActions(actions: ActionKeyboardShortcut[]) {
|
||||
for (const action of actions) {
|
||||
// Skip actions that we've already manually registered
|
||||
if (this.commands.has(action.actionName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip actions that don't have a description (likely separators)
|
||||
if (!action.description) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip Electron-only actions if not in Electron environment
|
||||
if (action.isElectronOnly && !utils.isElectron()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip actions that should not appear in the command palette
|
||||
if (action.ignoreFromCommandPalette) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the primary shortcut (first one in the list)
|
||||
const primaryShortcut = action.effectiveShortcuts?.[0];
|
||||
|
||||
let name = action.friendlyName;
|
||||
if (action.scope === "note-tree") {
|
||||
name = t("command_palette.tree-action-name", { name: action.friendlyName });
|
||||
}
|
||||
|
||||
// Create a command definition from the keyboard action
|
||||
const commandDef: CommandDefinition = {
|
||||
id: action.actionName,
|
||||
name,
|
||||
description: action.description,
|
||||
icon: action.iconClass,
|
||||
shortcut: primaryShortcut ? this.formatShortcut(primaryShortcut) : undefined,
|
||||
commandName: action.actionName as CommandNames,
|
||||
source: "keyboard-action",
|
||||
keyboardAction: action
|
||||
};
|
||||
|
||||
this.register(commandDef);
|
||||
}
|
||||
}
|
||||
|
||||
private formatShortcut(shortcut: string): string {
|
||||
// Convert electron accelerator format to display format
|
||||
return shortcut
|
||||
.replace(/CommandOrControl/g, 'Ctrl')
|
||||
.replace(/\+/g, ' + ');
|
||||
}
|
||||
|
||||
register(command: CommandDefinition) {
|
||||
this.commands.set(command.id, command);
|
||||
|
||||
// Register aliases
|
||||
if (command.aliases) {
|
||||
for (const alias of command.aliases) {
|
||||
this.aliases.set(alias.toLowerCase(), command.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getCommand(id: string): CommandDefinition | undefined {
|
||||
return this.commands.get(id);
|
||||
}
|
||||
|
||||
getAllCommands(): CommandDefinition[] {
|
||||
const commands = Array.from(this.commands.values());
|
||||
|
||||
// Sort commands by name
|
||||
commands.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
return commands;
|
||||
}
|
||||
|
||||
searchCommands(query: string): CommandDefinition[] {
|
||||
const normalizedQuery = query.toLowerCase();
|
||||
const results: { command: CommandDefinition; score: number }[] = [];
|
||||
|
||||
for (const command of this.commands.values()) {
|
||||
let score = 0;
|
||||
|
||||
// Exact match on name
|
||||
if (command.name.toLowerCase() === normalizedQuery) {
|
||||
score = 100;
|
||||
}
|
||||
// Name starts with query
|
||||
else if (command.name.toLowerCase().startsWith(normalizedQuery)) {
|
||||
score = 80;
|
||||
}
|
||||
// Name contains query
|
||||
else if (command.name.toLowerCase().includes(normalizedQuery)) {
|
||||
score = 60;
|
||||
}
|
||||
// Description contains query
|
||||
else if (command.description?.toLowerCase().includes(normalizedQuery)) {
|
||||
score = 40;
|
||||
}
|
||||
// Check aliases
|
||||
else if (command.aliases?.some(alias => alias.toLowerCase().includes(normalizedQuery))) {
|
||||
score = 50;
|
||||
}
|
||||
|
||||
if (score > 0) {
|
||||
results.push({ command, score });
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by score (highest first) and then by name
|
||||
results.sort((a, b) => {
|
||||
if (a.score !== b.score) {
|
||||
return b.score - a.score;
|
||||
}
|
||||
return a.command.name.localeCompare(b.command.name);
|
||||
});
|
||||
|
||||
return results.map(r => r.command);
|
||||
}
|
||||
|
||||
async executeCommand(commandId: string) {
|
||||
const command = this.getCommand(commandId);
|
||||
if (!command) {
|
||||
console.error(`Command not found: ${commandId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute custom handler if provided
|
||||
if (command.handler) {
|
||||
await command.handler();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle keyboard action with scope-aware execution
|
||||
if (command.keyboardAction && command.commandName) {
|
||||
if (command.keyboardAction.scope === "note-tree") {
|
||||
this.executeWithNoteTreeFocus(command.commandName);
|
||||
} else if (command.keyboardAction.scope === "text-detail") {
|
||||
this.executeWithTextDetail(command.commandName);
|
||||
} else {
|
||||
appContext.triggerCommand(command.commandName, {
|
||||
ntxId: appContext.tabManager.activeNtxId
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback for commands without keyboard action reference
|
||||
if (command.commandName) {
|
||||
appContext.triggerCommand(command.commandName, {
|
||||
ntxId: appContext.tabManager.activeNtxId
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
console.error(`Command ${commandId} has no handler or commandName`);
|
||||
}
|
||||
|
||||
private executeWithNoteTreeFocus(actionName: CommandNames) {
|
||||
const tree = document.querySelector(".tree-wrapper") as HTMLElement;
|
||||
if (!tree) {
|
||||
return;
|
||||
}
|
||||
|
||||
const treeComponent = appContext.getComponentByEl(tree) as NoteTreeWidget;
|
||||
const activeNode = treeComponent.getActiveNode();
|
||||
treeComponent.triggerCommand(actionName, {
|
||||
ntxId: appContext.tabManager.activeNtxId,
|
||||
node: activeNode
|
||||
});
|
||||
}
|
||||
|
||||
private async executeWithTextDetail(actionName: CommandNames) {
|
||||
const typeWidget = await appContext.tabManager.getActiveContext()?.getTypeWidget();
|
||||
if (!typeWidget) {
|
||||
return;
|
||||
}
|
||||
|
||||
typeWidget.triggerCommand(actionName, {
|
||||
ntxId: appContext.tabManager.activeNtxId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const commandRegistry = new CommandRegistry();
|
||||
export default commandRegistry;
|
||||
@@ -65,6 +65,9 @@ async function getRenderedContent(this: {} | { ctx: string }, entity: FNote | FA
|
||||
|
||||
$renderedContent.append($("<div>").append("<div>This note is protected and to access it you need to enter password.</div>").append("<br/>").append($button));
|
||||
} else if (entity instanceof FNote) {
|
||||
$renderedContent
|
||||
.css("display", "flex")
|
||||
.css("flex-direction", "column");
|
||||
$renderedContent.append(
|
||||
$("<div>")
|
||||
.css("display", "flex")
|
||||
@@ -72,8 +75,33 @@ async function getRenderedContent(this: {} | { ctx: string }, entity: FNote | FA
|
||||
.css("align-items", "center")
|
||||
.css("height", "100%")
|
||||
.css("font-size", "500%")
|
||||
.css("flex-grow", "1")
|
||||
.append($("<span>").addClass(entity.getIcon()))
|
||||
);
|
||||
|
||||
if (entity.type === "webView" && entity.hasLabel("webViewSrc")) {
|
||||
const $footer = $("<footer>")
|
||||
.addClass("webview-footer");
|
||||
const $openButton = $(`
|
||||
<button class="file-open btn btn-primary" type="button">
|
||||
<span class="bx bx-link-external"></span>
|
||||
${t("content_renderer.open_externally")}
|
||||
</button>
|
||||
`)
|
||||
.appendTo($footer)
|
||||
.on("click", () => {
|
||||
const webViewSrc = entity.getLabelValue("webViewSrc");
|
||||
if (webViewSrc) {
|
||||
if (utils.isElectron()) {
|
||||
const electron = utils.dynamicRequire("electron");
|
||||
electron.shell.openExternal(webViewSrc);
|
||||
} else {
|
||||
window.open(webViewSrc, '_blank', 'noopener,noreferrer');
|
||||
}
|
||||
}
|
||||
});
|
||||
$footer.appendTo($renderedContent);
|
||||
}
|
||||
}
|
||||
|
||||
if (entity instanceof FNote) {
|
||||
@@ -118,8 +146,17 @@ async function renderText(note: FNote | FAttachment, $renderedContent: JQuery<HT
|
||||
async function renderCode(note: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>) {
|
||||
const blob = await note.getBlob();
|
||||
|
||||
let content = blob?.content || "";
|
||||
if (note.mime === "application/json") {
|
||||
try {
|
||||
content = JSON.stringify(JSON.parse(content), null, 4);
|
||||
} catch (e) {
|
||||
// Ignore JSON parsing errors.
|
||||
}
|
||||
}
|
||||
|
||||
const $codeBlock = $("<code>");
|
||||
$codeBlock.text(blob?.content || "");
|
||||
$codeBlock.text(content);
|
||||
$renderedContent.append($("<pre>").append($codeBlock));
|
||||
await applySingleBlockSyntaxHighlight($codeBlock, normalizeMimeTypeForCKEditor(note.mime));
|
||||
}
|
||||
@@ -301,7 +338,7 @@ function getRenderingType(entity: FNote | FAttachment) {
|
||||
|
||||
if (type === "file" && mime === "application/pdf") {
|
||||
type = "pdf";
|
||||
} else if (type === "file" && mime && CODE_MIME_TYPES.has(mime)) {
|
||||
} else if ((type === "file" || type === "viewConfig") && mime && CODE_MIME_TYPES.has(mime)) {
|
||||
type = "code";
|
||||
} else if (type === "file" && mime && mime.startsWith("audio/")) {
|
||||
type = "audio";
|
||||
|
||||
@@ -4,14 +4,14 @@ import type { ConfirmDialogOptions, ConfirmDialogResult, ConfirmWithMessageOptio
|
||||
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
|
||||
import { focusSavedElement, saveFocusedElement } from "./focus.js";
|
||||
|
||||
export async function openDialog($dialog: JQuery<HTMLElement>, closeActDialog = true) {
|
||||
export async function openDialog($dialog: JQuery<HTMLElement>, closeActDialog = true, config?: Partial<Modal.Options>) {
|
||||
if (closeActDialog) {
|
||||
closeActiveDialog();
|
||||
glob.activeDialog = $dialog;
|
||||
}
|
||||
|
||||
saveFocusedElement();
|
||||
Modal.getOrCreateInstance($dialog[0]).show();
|
||||
Modal.getOrCreateInstance($dialog[0], config).show();
|
||||
|
||||
$dialog.on("hidden.bs.modal", () => {
|
||||
const $autocompleteEl = $(".aa-input");
|
||||
@@ -41,8 +41,14 @@ async function info(message: string) {
|
||||
return new Promise((res) => appContext.triggerCommand("showInfoDialog", { message, callback: res }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a confirmation dialog with the given message.
|
||||
*
|
||||
* @param message the message to display in the dialog.
|
||||
* @returns A promise that resolves to true if the user confirmed, false otherwise.
|
||||
*/
|
||||
async function confirm(message: string) {
|
||||
return new Promise((res) =>
|
||||
return new Promise<boolean>((res) =>
|
||||
appContext.triggerCommand("showConfirmDialog", <ConfirmWithMessageOptions>{
|
||||
message,
|
||||
callback: (x: false | ConfirmDialogOptions) => res(x && x.confirmed)
|
||||
|
||||
@@ -35,8 +35,10 @@ async function processEntityChanges(entityChanges: EntityChange[]) {
|
||||
loadResults.addOption(attributeEntity.name);
|
||||
} else if (ec.entityName === "attachments") {
|
||||
processAttachment(loadResults, ec);
|
||||
} else if (ec.entityName === "blobs" || ec.entityName === "etapi_tokens") {
|
||||
} else if (ec.entityName === "blobs") {
|
||||
// NOOP - these entities are handled at the backend level and don't require frontend processing
|
||||
} else if (ec.entityName === "etapi_tokens") {
|
||||
loadResults.hasEtapiTokenChanges = true;
|
||||
} else {
|
||||
throw new Error(`Unknown entityName '${ec.entityName}'`);
|
||||
}
|
||||
@@ -77,9 +79,7 @@ async function processEntityChanges(entityChanges: EntityChange[]) {
|
||||
noteAttributeCache.invalidate();
|
||||
}
|
||||
|
||||
// TODO: Remove after porting the file
|
||||
// @ts-ignore
|
||||
const appContext = (await import("../components/app_context.js")).default as any;
|
||||
const appContext = (await import("../components/app_context.js")).default;
|
||||
await appContext.triggerEvent("entitiesReloaded", { loadResults });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,13 @@ function setupGlobs() {
|
||||
const string = e?.reason?.message?.toLowerCase();
|
||||
|
||||
let message = "Uncaught error: ";
|
||||
let errorObjectString;
|
||||
|
||||
try {
|
||||
errorObjectString = JSON.stringify(e.reason)
|
||||
} catch (error: any) {
|
||||
errorObjectString = error.toString();
|
||||
}
|
||||
|
||||
if (string?.includes("script error")) {
|
||||
message += "No details available";
|
||||
@@ -57,7 +64,7 @@ function setupGlobs() {
|
||||
`Message: ${e.reason.message}`,
|
||||
`Line: ${e.reason.lineNumber}`,
|
||||
`Column: ${e.reason.columnNumber}`,
|
||||
`Error object: ${JSON.stringify(e.reason)}`,
|
||||
`Error object: ${errorObjectString}`,
|
||||
`Stack: ${e.reason && e.reason.stack}`
|
||||
].join(", ");
|
||||
}
|
||||
|
||||
@@ -3,14 +3,21 @@ import i18next from "i18next";
|
||||
import i18nextHttpBackend from "i18next-http-backend";
|
||||
import server from "./server.js";
|
||||
import type { Locale } from "@triliumnext/commons";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
|
||||
let locales: Locale[] | null;
|
||||
|
||||
/**
|
||||
* A deferred promise that resolves when translations are initialized.
|
||||
*/
|
||||
export let translationsInitializedPromise = $.Deferred();
|
||||
|
||||
export async function initLocale() {
|
||||
const locale = (options.get("locale") as string) || "en";
|
||||
|
||||
locales = await server.get<Locale[]>("options/locales");
|
||||
|
||||
i18next.use(initReactI18next);
|
||||
await i18next.use(i18nextHttpBackend).init({
|
||||
lng: locale,
|
||||
fallbackLng: "en",
|
||||
@@ -19,6 +26,8 @@ export async function initLocale() {
|
||||
},
|
||||
returnEmptyString: false
|
||||
});
|
||||
|
||||
translationsInitializedPromise.resolve();
|
||||
}
|
||||
|
||||
export function getAvailableLocales() {
|
||||
|
||||
@@ -2,21 +2,15 @@ import server from "./server.js";
|
||||
import appContext, { type CommandNames } from "../components/app_context.js";
|
||||
import shortcutService from "./shortcuts.js";
|
||||
import type Component from "../components/component.js";
|
||||
import type { ActionKeyboardShortcut } from "@triliumnext/commons";
|
||||
|
||||
const keyboardActionRepo: Record<string, Action> = {};
|
||||
const keyboardActionRepo: Record<string, ActionKeyboardShortcut> = {};
|
||||
|
||||
// TODO: Deduplicate with server.
|
||||
export interface Action {
|
||||
actionName: CommandNames;
|
||||
effectiveShortcuts: string[];
|
||||
scope: string;
|
||||
}
|
||||
|
||||
const keyboardActionsLoaded = server.get<Action[]>("keyboard-actions").then((actions) => {
|
||||
const keyboardActionsLoaded = server.get<ActionKeyboardShortcut[]>("keyboard-actions").then((actions) => {
|
||||
actions = actions.filter((a) => !!a.actionName); // filter out separators
|
||||
|
||||
for (const action of actions) {
|
||||
action.effectiveShortcuts = action.effectiveShortcuts.filter((shortcut) => !shortcut.startsWith("global:"));
|
||||
action.effectiveShortcuts = (action.effectiveShortcuts ?? []).filter((shortcut) => !shortcut.startsWith("global:"));
|
||||
|
||||
keyboardActionRepo[action.actionName] = action;
|
||||
}
|
||||
@@ -38,7 +32,7 @@ async function setupActionsForElement(scope: string, $el: JQuery<HTMLElement>, c
|
||||
const actions = await getActionsForScope(scope);
|
||||
|
||||
for (const action of actions) {
|
||||
for (const shortcut of action.effectiveShortcuts) {
|
||||
for (const shortcut of action.effectiveShortcuts ?? []) {
|
||||
shortcutService.bindElShortcut($el, shortcut, () => component.triggerCommand(action.actionName, { ntxId: appContext.tabManager.activeNtxId }));
|
||||
}
|
||||
}
|
||||
@@ -46,7 +40,7 @@ async function setupActionsForElement(scope: string, $el: JQuery<HTMLElement>, c
|
||||
|
||||
getActionsForScope("window").then((actions) => {
|
||||
for (const action of actions) {
|
||||
for (const shortcut of action.effectiveShortcuts) {
|
||||
for (const shortcut of action.effectiveShortcuts ?? []) {
|
||||
shortcutService.bindGlobalShortcut(shortcut, () => appContext.triggerCommand(action.actionName, { ntxId: appContext.tabManager.activeNtxId }));
|
||||
}
|
||||
}
|
||||
@@ -80,7 +74,7 @@ function updateDisplayedShortcuts($container: JQuery<HTMLElement>) {
|
||||
const action = await getAction(actionName, true);
|
||||
|
||||
if (action) {
|
||||
const keyboardActions = action.effectiveShortcuts.join(", ");
|
||||
const keyboardActions = (action.effectiveShortcuts ?? []).join(", ");
|
||||
|
||||
if (keyboardActions || $(el).text() !== "not set") {
|
||||
$(el).text(keyboardActions);
|
||||
@@ -99,7 +93,7 @@ function updateDisplayedShortcuts($container: JQuery<HTMLElement>) {
|
||||
|
||||
if (action) {
|
||||
const title = $(el).attr("title");
|
||||
const shortcuts = action.effectiveShortcuts.join(", ");
|
||||
const shortcuts = (action.effectiveShortcuts ?? []).join(", ");
|
||||
|
||||
if (title?.includes(shortcuts)) {
|
||||
return;
|
||||
|
||||
@@ -231,6 +231,7 @@ export function parseNavigationStateFromUrl(url: string | undefined) {
|
||||
let ntxId: string | null = null;
|
||||
let hoistedNoteId: string | null = null;
|
||||
let searchString: string | null = null;
|
||||
let openInPopup = false;
|
||||
|
||||
if (paramString) {
|
||||
for (const pair of paramString.split("&")) {
|
||||
@@ -246,6 +247,8 @@ export function parseNavigationStateFromUrl(url: string | undefined) {
|
||||
searchString = value; // supports triggering search from URL, e.g. #?searchString=blabla
|
||||
} else if (["viewMode", "attachmentId"].includes(name)) {
|
||||
(viewScope as any)[name] = value;
|
||||
} else if (name === "popup") {
|
||||
openInPopup = true;
|
||||
} else {
|
||||
console.warn(`Unrecognized hash parameter '${name}'.`);
|
||||
}
|
||||
@@ -266,7 +269,8 @@ export function parseNavigationStateFromUrl(url: string | undefined) {
|
||||
ntxId,
|
||||
hoistedNoteId,
|
||||
viewScope,
|
||||
searchString
|
||||
searchString,
|
||||
openInPopup
|
||||
};
|
||||
}
|
||||
|
||||
@@ -277,13 +281,21 @@ function goToLink(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent) {
|
||||
return goToLinkExt(evt, hrefLink, $link);
|
||||
}
|
||||
|
||||
function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent | React.PointerEvent<HTMLCanvasElement>, hrefLink: string | undefined, $link?: JQuery<HTMLElement> | null) {
|
||||
/**
|
||||
* Handles navigation to a link, which can be an internal note path (e.g., `#root/1234`) or an external URL (e.g., `https://example.com`).
|
||||
*
|
||||
* @param evt the event that triggered the link navigation, or `null` if the link was clicked programmatically. Used to determine if the link should be opened in a new tab/window, based on the button presses.
|
||||
* @param hrefLink the link to navigate to, which can be a note path (e.g., `#root/1234`) or an external URL with any supported protocol (e.g., `https://example.com`).
|
||||
* @param $link the jQuery element of the link that was clicked, used to determine if the link is an anchor link (e.g., `#fn1` or `#fnref1`) and to handle it accordingly.
|
||||
* @returns `true` if the link was handled (i.e., the element was found and scrolled to), or a falsy value otherwise.
|
||||
*/
|
||||
function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent | React.PointerEvent<HTMLCanvasElement> | null, hrefLink: string | undefined, $link?: JQuery<HTMLElement> | null) {
|
||||
if (hrefLink?.startsWith("data:")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
evt?.preventDefault();
|
||||
evt?.stopPropagation();
|
||||
|
||||
if (hrefLink && hrefLink.startsWith("#") && !hrefLink.startsWith("#root/") && $link) {
|
||||
if (handleAnchor(hrefLink, $link)) {
|
||||
@@ -291,19 +303,22 @@ function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent
|
||||
}
|
||||
}
|
||||
|
||||
const { notePath, viewScope } = parseNavigationStateFromUrl(hrefLink);
|
||||
const { notePath, viewScope, openInPopup } = parseNavigationStateFromUrl(hrefLink);
|
||||
|
||||
const ctrlKey = utils.isCtrlKey(evt);
|
||||
const shiftKey = evt.shiftKey;
|
||||
const isLeftClick = "which" in evt && evt.which === 1;
|
||||
const isMiddleClick = "which" in evt && evt.which === 2;
|
||||
const ctrlKey = evt && utils.isCtrlKey(evt);
|
||||
const shiftKey = evt?.shiftKey;
|
||||
const isLeftClick = !evt || ("which" in evt && evt.which === 1);
|
||||
// Right click is handled separately.
|
||||
const isMiddleClick = evt && "which" in evt && evt.which === 2;
|
||||
const targetIsBlank = ($link?.attr("target") === "_blank");
|
||||
const openInNewTab = (isLeftClick && ctrlKey) || isMiddleClick || targetIsBlank;
|
||||
const activate = (isLeftClick && ctrlKey && shiftKey) || (isMiddleClick && shiftKey);
|
||||
const openInNewWindow = isLeftClick && evt.shiftKey && !ctrlKey;
|
||||
const openInNewWindow = isLeftClick && evt?.shiftKey && !ctrlKey;
|
||||
|
||||
if (notePath) {
|
||||
if (openInNewWindow) {
|
||||
if (isLeftClick && openInPopup) {
|
||||
appContext.triggerCommand("openInPopup", { noteIdOrPath: notePath });
|
||||
} else if (openInNewWindow) {
|
||||
appContext.triggerCommand("openInWindow", { notePath, viewScope });
|
||||
} else if (openInNewTab) {
|
||||
appContext.tabManager.openTabWithNoteWithHoisting(notePath, {
|
||||
@@ -311,7 +326,7 @@ function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent
|
||||
viewScope
|
||||
});
|
||||
} else if (isLeftClick) {
|
||||
const ntxId = $(evt.target as any)
|
||||
const ntxId = $(evt?.target as any)
|
||||
.closest("[data-ntx-id]")
|
||||
.attr("data-ntx-id");
|
||||
|
||||
@@ -379,6 +394,12 @@ function linkContextMenu(e: PointerEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (utils.isCtrlKey(e) && e.button === 2) {
|
||||
appContext.triggerCommand("openInPopup", { noteIdOrPath: notePath });
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
linkContextMenuService.openContextMenu(notePath, e, viewScope, null);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AttachmentRow } from "@triliumnext/commons";
|
||||
import type { AttachmentRow, EtapiTokenRow } from "@triliumnext/commons";
|
||||
import type { AttributeType } from "../entities/fattribute.js";
|
||||
import type { EntityChange } from "../server_types.js";
|
||||
|
||||
@@ -53,6 +53,7 @@ type EntityRowMappings = {
|
||||
options: OptionRow;
|
||||
revisions: RevisionRow;
|
||||
note_reordering: NoteReorderingRow;
|
||||
etapi_tokens: EtapiTokenRow;
|
||||
};
|
||||
|
||||
export type EntityRowNames = keyof EntityRowMappings;
|
||||
@@ -68,6 +69,7 @@ export default class LoadResults {
|
||||
private contentNoteIdToComponentId: ContentNoteIdToComponentIdRow[];
|
||||
private optionNames: string[];
|
||||
private attachmentRows: AttachmentRow[];
|
||||
public hasEtapiTokenChanges: boolean = false;
|
||||
|
||||
constructor(entityChanges: EntityChange[]) {
|
||||
const entities: Record<string, Record<string, any>> = {};
|
||||
@@ -215,7 +217,8 @@ export default class LoadResults {
|
||||
this.revisionRows.length === 0 &&
|
||||
this.contentNoteIdToComponentId.length === 0 &&
|
||||
this.optionNames.length === 0 &&
|
||||
this.attachmentRows.length === 0
|
||||
this.attachmentRows.length === 0 &&
|
||||
!this.hasEtapiTokenChanges
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import appContext from "../components/app_context.js";
|
||||
import noteCreateService from "./note_create.js";
|
||||
import froca from "./froca.js";
|
||||
import { t } from "./i18n.js";
|
||||
import commandRegistry from "./command_registry.js";
|
||||
import type { MentionFeedObjectItem } from "@triliumnext/ckeditor5";
|
||||
|
||||
// this key needs to have this value, so it's hit by the tooltip
|
||||
@@ -29,18 +30,26 @@ export interface Suggestion {
|
||||
notePathTitle?: string;
|
||||
notePath?: string;
|
||||
highlightedNotePathTitle?: string;
|
||||
action?: string | "create-note" | "search-notes" | "external-link";
|
||||
action?: string | "create-note" | "search-notes" | "external-link" | "command";
|
||||
parentNoteId?: string;
|
||||
icon?: string;
|
||||
commandId?: string;
|
||||
commandDescription?: string;
|
||||
commandShortcut?: string;
|
||||
}
|
||||
|
||||
interface Options {
|
||||
container?: HTMLElement;
|
||||
export interface Options {
|
||||
container?: HTMLElement | null;
|
||||
fastSearch?: boolean;
|
||||
allowCreatingNotes?: boolean;
|
||||
allowJumpToSearchNotes?: boolean;
|
||||
allowExternalLinks?: boolean;
|
||||
/** If set, hides the right-side button corresponding to go to selected note. */
|
||||
hideGoToSelectedNoteButton?: boolean;
|
||||
/** If set, hides all right-side buttons in the autocomplete dropdown */
|
||||
hideAllButtons?: boolean;
|
||||
/** If set, enables command palette mode */
|
||||
isCommandPalette?: boolean;
|
||||
}
|
||||
|
||||
async function autocompleteSourceForCKEditor(queryText: string) {
|
||||
@@ -70,6 +79,31 @@ async function autocompleteSourceForCKEditor(queryText: string) {
|
||||
}
|
||||
|
||||
async function autocompleteSource(term: string, cb: (rows: Suggestion[]) => void, options: Options = {}) {
|
||||
// Check if we're in command mode
|
||||
if (options.isCommandPalette && term.startsWith(">")) {
|
||||
const commandQuery = term.substring(1).trim();
|
||||
|
||||
// Get commands (all if no query, filtered if query provided)
|
||||
const commands = commandQuery.length === 0
|
||||
? commandRegistry.getAllCommands()
|
||||
: commandRegistry.searchCommands(commandQuery);
|
||||
|
||||
// Convert commands to suggestions
|
||||
const commandSuggestions: Suggestion[] = commands.map(cmd => ({
|
||||
action: "command",
|
||||
commandId: cmd.id,
|
||||
noteTitle: cmd.name,
|
||||
notePathTitle: `>${cmd.name}`,
|
||||
highlightedNotePathTitle: cmd.name,
|
||||
commandDescription: cmd.description,
|
||||
commandShortcut: cmd.shortcut,
|
||||
icon: cmd.icon
|
||||
}));
|
||||
|
||||
cb(commandSuggestions);
|
||||
return;
|
||||
}
|
||||
|
||||
const fastSearch = options.fastSearch === false ? false : true;
|
||||
if (fastSearch === false) {
|
||||
if (term.trim().length === 0) {
|
||||
@@ -143,6 +177,12 @@ function showRecentNotes($el: JQuery<HTMLElement>) {
|
||||
$el.trigger("focus");
|
||||
}
|
||||
|
||||
function showAllCommands($el: JQuery<HTMLElement>) {
|
||||
searchDelay = 0;
|
||||
$el.setSelectedNotePath("");
|
||||
$el.autocomplete("val", ">").autocomplete("open");
|
||||
}
|
||||
|
||||
function fullTextSearch($el: JQuery<HTMLElement>, options: Options) {
|
||||
const searchString = $el.autocomplete("val") as unknown as string;
|
||||
if (options.fastSearch === false || searchString?.trim().length === 0) {
|
||||
@@ -190,9 +230,11 @@ function initNoteAutocomplete($el: JQuery<HTMLElement>, options?: Options) {
|
||||
|
||||
const $goToSelectedNoteButton = $("<a>").addClass("input-group-text go-to-selected-note-button bx bx-arrow-to-right");
|
||||
|
||||
if (!options.hideAllButtons) {
|
||||
$el.after($clearTextButton).after($showRecentNotesButton).after($fullTextSearchButton);
|
||||
}
|
||||
|
||||
if (!options.hideGoToSelectedNoteButton) {
|
||||
if (!options.hideGoToSelectedNoteButton && !options.hideAllButtons) {
|
||||
$el.after($goToSelectedNoteButton);
|
||||
}
|
||||
|
||||
@@ -265,7 +307,24 @@ function initNoteAutocomplete($el: JQuery<HTMLElement>, options?: Options) {
|
||||
},
|
||||
displayKey: "notePathTitle",
|
||||
templates: {
|
||||
suggestion: (suggestion) => `<span class="${suggestion.icon ?? "bx bx-note"}"></span> ${suggestion.highlightedNotePathTitle}`
|
||||
suggestion: (suggestion) => {
|
||||
if (suggestion.action === "command") {
|
||||
let html = `<div class="command-suggestion">`;
|
||||
html += `<span class="command-icon ${suggestion.icon || "bx bx-terminal"}"></span>`;
|
||||
html += `<div class="command-content">`;
|
||||
html += `<div class="command-name">${suggestion.highlightedNotePathTitle}</div>`;
|
||||
if (suggestion.commandDescription) {
|
||||
html += `<div class="command-description">${suggestion.commandDescription}</div>`;
|
||||
}
|
||||
html += `</div>`;
|
||||
if (suggestion.commandShortcut) {
|
||||
html += `<kbd class="command-shortcut">${suggestion.commandShortcut}</kbd>`;
|
||||
}
|
||||
html += '</div>';
|
||||
return html;
|
||||
}
|
||||
return `<span class="${suggestion.icon ?? "bx bx-note"}"></span> ${suggestion.highlightedNotePathTitle}`;
|
||||
}
|
||||
},
|
||||
// we can't cache identical searches because notes can be created / renamed, new recent notes can be added
|
||||
cache: false
|
||||
@@ -275,6 +334,12 @@ function initNoteAutocomplete($el: JQuery<HTMLElement>, options?: Options) {
|
||||
|
||||
// TODO: Types fail due to "autocomplete:selected" not being registered in type definitions.
|
||||
($el as any).on("autocomplete:selected", async (event: Event, suggestion: Suggestion) => {
|
||||
if (suggestion.action === "command") {
|
||||
$el.autocomplete("close");
|
||||
$el.trigger("autocomplete:commandselected", [suggestion]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (suggestion.action === "external-link") {
|
||||
$el.setSelectedNotePath(null);
|
||||
$el.setSelectedExternalLink(suggestion.externalLink);
|
||||
@@ -387,10 +452,26 @@ function init() {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function which triggers the display of recent notes in the autocomplete input and focuses it.
|
||||
*
|
||||
* @param inputElement - The input element to trigger recent notes on.
|
||||
*/
|
||||
export function triggerRecentNotes(inputElement: HTMLInputElement | null | undefined) {
|
||||
if (!inputElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const $el = $(inputElement);
|
||||
showRecentNotes($el);
|
||||
$el.trigger("focus").trigger("select");
|
||||
}
|
||||
|
||||
export default {
|
||||
autocompleteSourceForCKEditor,
|
||||
initNoteAutocomplete,
|
||||
showRecentNotes,
|
||||
showAllCommands,
|
||||
setText,
|
||||
init
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ import type FBranch from "../entities/fbranch.js";
|
||||
import type { ChooseNoteTypeResponse } from "../widgets/dialogs/note_type_chooser.js";
|
||||
import type { CKTextEditor } from "@triliumnext/ckeditor5";
|
||||
|
||||
interface CreateNoteOpts {
|
||||
export interface CreateNoteOpts {
|
||||
isProtected?: boolean;
|
||||
saveSelection?: boolean;
|
||||
title?: string | null;
|
||||
@@ -109,8 +109,6 @@ async function createNote(parentNotePath: string | undefined, options: CreateNot
|
||||
|
||||
async function chooseNoteType() {
|
||||
return new Promise<ChooseNoteTypeResponse>((res) => {
|
||||
// TODO: Remove ignore after callback for chooseNoteType is defined in app_context.ts
|
||||
//@ts-ignore
|
||||
appContext.triggerCommand("chooseNoteType", { callback: res });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,38 +1,31 @@
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import BoardView from "../widgets/view_widgets/board_view/index.js";
|
||||
import CalendarView from "../widgets/view_widgets/calendar_view.js";
|
||||
import GeoView from "../widgets/view_widgets/geo_view/index.js";
|
||||
import ListOrGridView from "../widgets/view_widgets/list_or_grid_view.js";
|
||||
import TableView from "../widgets/view_widgets/table_view/index.js";
|
||||
import type { ViewModeArgs } from "../widgets/view_widgets/view_mode.js";
|
||||
import type ViewMode from "../widgets/view_widgets/view_mode.js";
|
||||
|
||||
export type ViewTypeOptions = "list" | "grid" | "calendar";
|
||||
const allViewTypes = ["list", "grid", "calendar", "table", "geoMap", "board"] as const;
|
||||
export type ArgsWithoutNoteId = Omit<ViewModeArgs, "noteIds">;
|
||||
export type ViewTypeOptions = typeof allViewTypes[number];
|
||||
|
||||
export default class NoteListRenderer {
|
||||
|
||||
private viewType: ViewTypeOptions;
|
||||
public viewMode: ViewMode | null;
|
||||
private args: ArgsWithoutNoteId;
|
||||
public viewMode?: ViewMode<any>;
|
||||
|
||||
constructor($parent: JQuery<HTMLElement>, parentNote: FNote, noteIds: string[], showNotePath: boolean = false) {
|
||||
this.viewType = this.#getViewType(parentNote);
|
||||
const args: ViewModeArgs = {
|
||||
$parent,
|
||||
parentNote,
|
||||
noteIds,
|
||||
showNotePath
|
||||
};
|
||||
|
||||
if (this.viewType === "list" || this.viewType === "grid") {
|
||||
this.viewMode = new ListOrGridView(this.viewType, args);
|
||||
} else if (this.viewType === "calendar") {
|
||||
this.viewMode = new CalendarView(args);
|
||||
} else {
|
||||
this.viewMode = null;
|
||||
}
|
||||
constructor(args: ArgsWithoutNoteId) {
|
||||
this.args = args;
|
||||
this.viewType = this.#getViewType(args.parentNote);
|
||||
}
|
||||
|
||||
#getViewType(parentNote: FNote): ViewTypeOptions {
|
||||
const viewType = parentNote.getLabelValue("viewType");
|
||||
|
||||
if (!["list", "grid", "calendar"].includes(viewType || "")) {
|
||||
if (!(allViewTypes as readonly string[]).includes(viewType || "")) {
|
||||
// when not explicitly set, decide based on the note type
|
||||
return parentNote.type === "search" ? "list" : "grid";
|
||||
} else {
|
||||
@@ -41,15 +34,38 @@ export default class NoteListRenderer {
|
||||
}
|
||||
|
||||
get isFullHeight() {
|
||||
return this.viewMode?.isFullHeight;
|
||||
switch (this.viewType) {
|
||||
case "list":
|
||||
case "grid":
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
async renderList() {
|
||||
if (!this.viewMode) {
|
||||
return null;
|
||||
const args = this.args;
|
||||
const viewMode = this.#buildViewMode(args);
|
||||
this.viewMode = viewMode;
|
||||
await viewMode.beforeRender();
|
||||
return await viewMode.renderList();
|
||||
}
|
||||
|
||||
return await this.viewMode.renderList();
|
||||
#buildViewMode(args: ViewModeArgs) {
|
||||
switch (this.viewType) {
|
||||
case "calendar":
|
||||
return new CalendarView(args);
|
||||
case "table":
|
||||
return new TableView(args);
|
||||
case "geoMap":
|
||||
return new GeoView(args);
|
||||
case "board":
|
||||
return new BoardView(args);
|
||||
case "list":
|
||||
case "grid":
|
||||
default:
|
||||
return new ListOrGridView(this.viewType, args);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ let openTooltipElements: JQuery<HTMLElement>[] = [];
|
||||
let dismissTimer: ReturnType<typeof setTimeout>;
|
||||
|
||||
function setupGlobalTooltip() {
|
||||
$(document).on("mouseenter", "a", mouseEnterHandler);
|
||||
$(document).on("mouseenter", "a:not(.no-tooltip-preview)", mouseEnterHandler);
|
||||
$(document).on("mouseenter", "[data-href]:not(.no-tooltip-preview)", mouseEnterHandler);
|
||||
|
||||
// close any note tooltip after click, this fixes the problem that sometimes tooltips remained on the screen
|
||||
$(document).on("click", (e) => {
|
||||
@@ -167,7 +168,10 @@ async function renderTooltip(note: FNote | null) {
|
||||
if (isContentEmpty) {
|
||||
classes.push("note-no-content");
|
||||
}
|
||||
content = `<h5 class="${classes.join(" ")}"><a href="#${note.noteId}" data-no-context-menu="true">${noteTitleWithPathAsSuffix.prop("outerHTML")}</a></h5>`;
|
||||
content = `\
|
||||
<h5 class="${classes.join(" ")}">
|
||||
<a href="#${note.noteId}" data-no-context-menu="true">${noteTitleWithPathAsSuffix.prop("outerHTML")}</a>
|
||||
</h5>`;
|
||||
}
|
||||
|
||||
content = `${content}<div class="note-tooltip-attributes">${$renderedAttributes[0].outerHTML}</div>`;
|
||||
@@ -175,6 +179,7 @@ async function renderTooltip(note: FNote | null) {
|
||||
content += $renderedContent[0].outerHTML;
|
||||
}
|
||||
|
||||
content += `<a class="open-popup-button" title="${t("note_tooltip.quick-edit")}" href="#${note.noteId}?popup"><span class="bx bx-edit" /></a>`;
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,32 +1,118 @@
|
||||
import server from "./server.js";
|
||||
import froca from "./froca.js";
|
||||
import { t } from "./i18n.js";
|
||||
import type { MenuItem } from "../menus/context_menu.js";
|
||||
import froca from "./froca.js";
|
||||
import server from "./server.js";
|
||||
import type { MenuCommandItem, MenuItem, MenuItemBadge } from "../menus/context_menu.js";
|
||||
import type { NoteType } from "../entities/fnote.js";
|
||||
import type { TreeCommandNames } from "../menus/tree_context_menu.js";
|
||||
|
||||
export interface NoteTypeMapping {
|
||||
type: NoteType;
|
||||
mime?: string;
|
||||
title: string;
|
||||
icon?: string;
|
||||
/** Indicates whether this type should be marked as a newly introduced feature. */
|
||||
isNew?: boolean;
|
||||
/** Indicates that this note type is part of a beta feature. */
|
||||
isBeta?: boolean;
|
||||
/** Indicates that this note type cannot be created by the user. */
|
||||
reserved?: boolean;
|
||||
/** Indicates that once a note of this type is created, its type can no longer be changed. */
|
||||
static?: boolean;
|
||||
}
|
||||
|
||||
export const NOTE_TYPES: NoteTypeMapping[] = [
|
||||
// The suggested note type ordering method: insert the item into the corresponding group,
|
||||
// then ensure the items within the group are ordered alphabetically.
|
||||
|
||||
// The default note type (always the first item)
|
||||
{ type: "text", mime: "text/html", title: t("note_types.text"), icon: "bx-note" },
|
||||
|
||||
// Text notes group
|
||||
{ type: "book", mime: "", title: t("note_types.book"), icon: "bx-book" },
|
||||
|
||||
// Graphic notes
|
||||
{ type: "canvas", mime: "application/json", title: t("note_types.canvas"), icon: "bx-pen" },
|
||||
{ type: "mermaid", mime: "text/mermaid", title: t("note_types.mermaid-diagram"), icon: "bx-selection" },
|
||||
|
||||
// Map notes
|
||||
{ type: "mindMap", mime: "application/json", title: t("note_types.mind-map"), icon: "bx-sitemap" },
|
||||
{ type: "noteMap", mime: "", title: t("note_types.note-map"), icon: "bxs-network-chart", static: true },
|
||||
{ type: "relationMap", mime: "application/json", title: t("note_types.relation-map"), icon: "bxs-network-chart" },
|
||||
|
||||
// Misc note types
|
||||
{ type: "render", mime: "", title: t("note_types.render-note"), icon: "bx-extension" },
|
||||
{ type: "search", title: t("note_types.saved-search"), icon: "bx-file-find", static: true },
|
||||
{ type: "webView", mime: "", title: t("note_types.web-view"), icon: "bx-globe-alt" },
|
||||
|
||||
// Code notes
|
||||
{ type: "code", mime: "text/plain", title: t("note_types.code"), icon: "bx-code" },
|
||||
|
||||
// Reserved types (cannot be created by the user)
|
||||
{ type: "contentWidget", mime: "", title: t("note_types.widget"), reserved: true },
|
||||
{ type: "doc", mime: "", title: t("note_types.doc"), reserved: true },
|
||||
{ type: "file", title: t("note_types.file"), reserved: true },
|
||||
{ type: "image", title: t("note_types.image"), reserved: true },
|
||||
{ type: "launcher", mime: "", title: t("note_types.launcher"), reserved: true },
|
||||
{ type: "aiChat", mime: "application/json", title: t("note_types.ai-chat"), reserved: true }
|
||||
];
|
||||
|
||||
/** The maximum age in days for a template to be marked with the "New" badge */
|
||||
const NEW_TEMPLATE_MAX_AGE = 3;
|
||||
|
||||
/** The length of a day in milliseconds. */
|
||||
const DAY_LENGTH = 1000 * 60 * 60 * 24;
|
||||
|
||||
/** The menu item badge used to mark new note types and templates */
|
||||
const NEW_BADGE: MenuItemBadge = {
|
||||
title: t("note_types.new-feature"),
|
||||
className: "new-note-type-badge"
|
||||
};
|
||||
|
||||
/** The menu item badge used to mark note types that are part of a beta feature */
|
||||
const BETA_BADGE = {
|
||||
title: t("note_types.beta-feature")
|
||||
};
|
||||
|
||||
const SEPARATOR = { title: "----" };
|
||||
|
||||
const creationDateCache = new Map<string, Date>();
|
||||
let rootCreationDate: Date | undefined;
|
||||
|
||||
async function getNoteTypeItems(command?: TreeCommandNames) {
|
||||
const items: MenuItem<TreeCommandNames>[] = [
|
||||
{ title: t("note_types.text"), command, type: "text", uiIcon: "bx bx-note" },
|
||||
{ title: t("note_types.code"), command, type: "code", uiIcon: "bx bx-code" },
|
||||
{ title: t("note_types.saved-search"), command, type: "search", uiIcon: "bx bx-file-find" },
|
||||
{ title: t("note_types.relation-map"), command, type: "relationMap", uiIcon: "bx bxs-network-chart" },
|
||||
{ title: t("note_types.note-map"), command, type: "noteMap", uiIcon: "bx bxs-network-chart" },
|
||||
{ title: t("note_types.render-note"), command, type: "render", uiIcon: "bx bx-extension" },
|
||||
{ title: t("note_types.book"), command, type: "book", uiIcon: "bx bx-book" },
|
||||
{ title: t("note_types.mermaid-diagram"), command, type: "mermaid", uiIcon: "bx bx-selection" },
|
||||
{ title: t("note_types.canvas"), command, type: "canvas", uiIcon: "bx bx-pen" },
|
||||
{ title: t("note_types.web-view"), command, type: "webView", uiIcon: "bx bx-globe-alt" },
|
||||
{ title: t("note_types.mind-map"), command, type: "mindMap", uiIcon: "bx bx-sitemap" },
|
||||
{ title: t("note_types.geo-map"), command, type: "geoMap", uiIcon: "bx bx-map-alt" },
|
||||
...await getBuiltInTemplates(command),
|
||||
...getBlankNoteTypes(command),
|
||||
...await getBuiltInTemplates(t("note_types.collections"), command, true),
|
||||
...await getBuiltInTemplates(null, command, false),
|
||||
...await getUserTemplates(command)
|
||||
];
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
function getBlankNoteTypes(command?: TreeCommandNames): MenuItem<TreeCommandNames>[] {
|
||||
return NOTE_TYPES
|
||||
.filter((nt) => !nt.reserved && nt.type !== "book")
|
||||
.map((nt) => {
|
||||
const menuItem: MenuCommandItem<TreeCommandNames> = {
|
||||
title: nt.title,
|
||||
command,
|
||||
type: nt.type,
|
||||
uiIcon: "bx " + nt.icon,
|
||||
badges: []
|
||||
}
|
||||
|
||||
if (nt.isNew) {
|
||||
menuItem.badges?.push(NEW_BADGE);
|
||||
}
|
||||
|
||||
if (nt.isBeta) {
|
||||
menuItem.badges?.push(BETA_BADGE);
|
||||
}
|
||||
|
||||
return menuItem;
|
||||
});
|
||||
}
|
||||
|
||||
async function getUserTemplates(command?: TreeCommandNames) {
|
||||
const templateNoteIds = await server.get<string[]>("search-templates");
|
||||
const templateNotes = await froca.getNotes(templateNoteIds);
|
||||
@@ -37,19 +123,26 @@ async function getUserTemplates(command?: TreeCommandNames) {
|
||||
const items: MenuItem<TreeCommandNames>[] = [
|
||||
SEPARATOR
|
||||
];
|
||||
|
||||
for (const templateNote of templateNotes) {
|
||||
items.push({
|
||||
const item: MenuItem<TreeCommandNames> = {
|
||||
title: templateNote.title,
|
||||
uiIcon: templateNote.getIcon(),
|
||||
command: command,
|
||||
type: templateNote.type,
|
||||
templateNoteId: templateNote.noteId
|
||||
});
|
||||
};
|
||||
|
||||
if (await isNewTemplate(templateNote.noteId)) {
|
||||
item.badges = [NEW_BADGE];
|
||||
}
|
||||
|
||||
items.push(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
async function getBuiltInTemplates(command?: TreeCommandNames) {
|
||||
async function getBuiltInTemplates(title: string | null, command: TreeCommandNames | undefined, filterCollections: boolean) {
|
||||
const templatesRoot = await froca.getNote("_templates");
|
||||
if (!templatesRoot) {
|
||||
console.warn("Unable to find template root.");
|
||||
@@ -61,21 +154,85 @@ async function getBuiltInTemplates(command?: TreeCommandNames) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const items: MenuItem<TreeCommandNames>[] = [
|
||||
SEPARATOR
|
||||
];
|
||||
for (const templateNote of childNotes) {
|
||||
const items: MenuItem<TreeCommandNames>[] = [];
|
||||
if (title) {
|
||||
items.push({
|
||||
title: title,
|
||||
enabled: false,
|
||||
uiIcon: "bx bx-empty"
|
||||
});
|
||||
} else {
|
||||
items.push(SEPARATOR);
|
||||
}
|
||||
|
||||
for (const templateNote of childNotes) {
|
||||
if (templateNote.hasLabel("collection") !== filterCollections) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const item: MenuItem<TreeCommandNames> = {
|
||||
title: templateNote.title,
|
||||
uiIcon: templateNote.getIcon(),
|
||||
command: command,
|
||||
type: templateNote.type,
|
||||
templateNoteId: templateNote.noteId
|
||||
});
|
||||
};
|
||||
|
||||
if (await isNewTemplate(templateNote.noteId)) {
|
||||
item.badges = [NEW_BADGE];
|
||||
}
|
||||
|
||||
items.push(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
async function isNewTemplate(templateNoteId) {
|
||||
if (rootCreationDate === undefined) {
|
||||
// Retrieve the root note creation date
|
||||
try {
|
||||
let rootNoteInfo: any = await server.get("notes/root");
|
||||
if ("dateCreated" in rootNoteInfo) {
|
||||
rootCreationDate = new Date(rootNoteInfo.dateCreated);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Try to retrieve the template's creation date from the cache
|
||||
let creationDate: Date | undefined = creationDateCache.get(templateNoteId);
|
||||
|
||||
if (creationDate === undefined) {
|
||||
// The creation date isn't available in the cache, try to retrieve it from the server
|
||||
try {
|
||||
const noteInfo: any = await server.get("notes/" + templateNoteId);
|
||||
if ("dateCreated" in noteInfo) {
|
||||
creationDate = new Date(noteInfo.dateCreated);
|
||||
creationDateCache.set(templateNoteId, creationDate);
|
||||
}
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (creationDate) {
|
||||
if (rootCreationDate && creationDate.getTime() - rootCreationDate.getTime() < 30000) {
|
||||
// Ignore templates created within 30 seconds after the root note is created.
|
||||
// This is useful to prevent predefined templates from being marked
|
||||
// as 'New' after setting up a new database.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine the difference in days between now and the template's creation date
|
||||
const age = (new Date().getTime() - creationDate.getTime()) / DAY_LENGTH;
|
||||
// Return true if the template is at most NEW_TEMPLATE_MAX_AGE days old
|
||||
return (age <= NEW_TEMPLATE_MAX_AGE);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getNoteTypeItems
|
||||
};
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { OptionNames } from "@triliumnext/commons";
|
||||
import server from "./server.js";
|
||||
import { isShare } from "./utils.js";
|
||||
|
||||
type OptionValue = number | string;
|
||||
export type OptionValue = number | string;
|
||||
|
||||
class Options {
|
||||
initializedPromise: Promise<void>;
|
||||
@@ -76,6 +77,14 @@ class Options {
|
||||
await server.put(`options`, payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves multiple options at once, by supplying a record where the keys are the option names and the values represent the stringified value to set.
|
||||
* @param newValues the record of keys and values.
|
||||
*/
|
||||
async saveMany<T extends OptionNames>(newValues: Record<T, OptionValue>) {
|
||||
await server.put<void>("options", newValues);
|
||||
}
|
||||
|
||||
async toggle(key: string) {
|
||||
await this.save(key, (!this.is(key)).toString());
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
type LabelType = "text" | "number" | "boolean" | "date" | "datetime" | "time" | "url";
|
||||
export type LabelType = "text" | "number" | "boolean" | "date" | "datetime" | "time" | "url" | "color";
|
||||
type Multiplicity = "single" | "multi";
|
||||
|
||||
export interface DefinitionObject {
|
||||
@@ -17,7 +17,7 @@ function parse(value: string) {
|
||||
for (const token of tokens) {
|
||||
if (token === "promoted") {
|
||||
defObj.isPromoted = true;
|
||||
} else if (["text", "number", "boolean", "date", "datetime", "time", "url"].includes(token)) {
|
||||
} else if (["text", "number", "boolean", "date", "datetime", "time", "url", "color"].includes(token)) {
|
||||
defObj.labelType = token as LabelType;
|
||||
} else if (["single", "multi"].includes(token)) {
|
||||
defObj.multiplicity = token as Multiplicity;
|
||||
|
||||
323
apps/client/src/services/shortcuts.spec.ts
Normal file
323
apps/client/src/services/shortcuts.spec.ts
Normal file
@@ -0,0 +1,323 @@
|
||||
import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
|
||||
import shortcuts, { keyMatches, matchesShortcut } from "./shortcuts.js";
|
||||
|
||||
// Mock utils module
|
||||
vi.mock("./utils.js", () => ({
|
||||
default: {
|
||||
isDesktop: () => true
|
||||
}
|
||||
}));
|
||||
|
||||
// Mock jQuery globally since it's used in the shortcuts module
|
||||
const mockElement = {
|
||||
addEventListener: vi.fn(),
|
||||
removeEventListener: vi.fn()
|
||||
};
|
||||
|
||||
const mockJQuery = vi.fn(() => [mockElement]);
|
||||
(mockJQuery as any).length = 1;
|
||||
mockJQuery[0] = mockElement;
|
||||
|
||||
(global as any).$ = mockJQuery as any;
|
||||
global.document = mockElement as any;
|
||||
|
||||
describe("shortcuts", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Clean up any active bindings after each test
|
||||
shortcuts.removeGlobalShortcut("test-namespace");
|
||||
});
|
||||
|
||||
describe("normalizeShortcut", () => {
|
||||
it("should normalize shortcut to lowercase and remove whitespace", () => {
|
||||
expect(shortcuts.normalizeShortcut("Ctrl + A")).toBe("ctrl+a");
|
||||
expect(shortcuts.normalizeShortcut(" SHIFT + F1 ")).toBe("shift+f1");
|
||||
expect(shortcuts.normalizeShortcut("Alt+Space")).toBe("alt+space");
|
||||
});
|
||||
|
||||
it("should handle empty or null shortcuts", () => {
|
||||
expect(shortcuts.normalizeShortcut("")).toBe("");
|
||||
expect(shortcuts.normalizeShortcut(null as any)).toBe(null);
|
||||
expect(shortcuts.normalizeShortcut(undefined as any)).toBe(undefined);
|
||||
});
|
||||
|
||||
it("should handle shortcuts with multiple spaces", () => {
|
||||
expect(shortcuts.normalizeShortcut("Ctrl + Shift + A")).toBe("ctrl+shift+a");
|
||||
});
|
||||
|
||||
it("should warn about malformed shortcuts", () => {
|
||||
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
|
||||
shortcuts.normalizeShortcut("ctrl+");
|
||||
shortcuts.normalizeShortcut("+a");
|
||||
shortcuts.normalizeShortcut("ctrl++a");
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledTimes(3);
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
describe("keyMatches", () => {
|
||||
const createKeyboardEvent = (key: string, code?: string) => ({
|
||||
key,
|
||||
code: code || `Key${key.toUpperCase()}`
|
||||
} as KeyboardEvent);
|
||||
|
||||
it("should match regular letter keys using key code", () => {
|
||||
const event = createKeyboardEvent("a", "KeyA");
|
||||
expect(keyMatches(event, "a")).toBe(true);
|
||||
expect(keyMatches(event, "A")).toBe(true);
|
||||
});
|
||||
|
||||
it("should match number keys using digit codes", () => {
|
||||
const event = createKeyboardEvent("1", "Digit1");
|
||||
expect(keyMatches(event, "1")).toBe(true);
|
||||
});
|
||||
|
||||
it("should match special keys using key mapping", () => {
|
||||
expect(keyMatches({ key: "Enter" } as KeyboardEvent, "return")).toBe(true);
|
||||
expect(keyMatches({ key: "Enter" } as KeyboardEvent, "enter")).toBe(true);
|
||||
expect(keyMatches({ key: "Delete" } as KeyboardEvent, "del")).toBe(true);
|
||||
expect(keyMatches({ key: "Escape" } as KeyboardEvent, "esc")).toBe(true);
|
||||
expect(keyMatches({ key: " " } as KeyboardEvent, "space")).toBe(true);
|
||||
expect(keyMatches({ key: "ArrowUp" } as KeyboardEvent, "up")).toBe(true);
|
||||
});
|
||||
|
||||
it("should match function keys", () => {
|
||||
expect(keyMatches({ key: "F1" } as KeyboardEvent, "f1")).toBe(true);
|
||||
expect(keyMatches({ key: "F12" } as KeyboardEvent, "f12")).toBe(true);
|
||||
});
|
||||
|
||||
it("should handle undefined or null keys", () => {
|
||||
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
|
||||
expect(keyMatches({} as KeyboardEvent, null as any)).toBe(false);
|
||||
expect(keyMatches({} as KeyboardEvent, undefined as any)).toBe(false);
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
describe("matchesShortcut", () => {
|
||||
const createKeyboardEvent = (options: {
|
||||
key: string;
|
||||
code?: string;
|
||||
ctrlKey?: boolean;
|
||||
altKey?: boolean;
|
||||
shiftKey?: boolean;
|
||||
metaKey?: boolean;
|
||||
}) => ({
|
||||
key: options.key,
|
||||
code: options.code || `Key${options.key.toUpperCase()}`,
|
||||
ctrlKey: options.ctrlKey || false,
|
||||
altKey: options.altKey || false,
|
||||
shiftKey: options.shiftKey || false,
|
||||
metaKey: options.metaKey || false
|
||||
} as KeyboardEvent);
|
||||
|
||||
it("should match simple key shortcuts", () => {
|
||||
const event = createKeyboardEvent({ key: "a", code: "KeyA" });
|
||||
expect(matchesShortcut(event, "a")).toBe(true);
|
||||
});
|
||||
|
||||
it("should match shortcuts with modifiers", () => {
|
||||
const event = createKeyboardEvent({ key: "a", code: "KeyA", ctrlKey: true });
|
||||
expect(matchesShortcut(event, "ctrl+a")).toBe(true);
|
||||
|
||||
const shiftEvent = createKeyboardEvent({ key: "a", code: "KeyA", shiftKey: true });
|
||||
expect(matchesShortcut(shiftEvent, "shift+a")).toBe(true);
|
||||
});
|
||||
|
||||
it("should match complex modifier combinations", () => {
|
||||
const event = createKeyboardEvent({
|
||||
key: "a",
|
||||
code: "KeyA",
|
||||
ctrlKey: true,
|
||||
shiftKey: true
|
||||
});
|
||||
expect(matchesShortcut(event, "ctrl+shift+a")).toBe(true);
|
||||
});
|
||||
|
||||
it("should not match when modifiers don't match", () => {
|
||||
const event = createKeyboardEvent({ key: "a", code: "KeyA", ctrlKey: true });
|
||||
expect(matchesShortcut(event, "alt+a")).toBe(false);
|
||||
expect(matchesShortcut(event, "a")).toBe(false);
|
||||
});
|
||||
|
||||
it("should handle alternative modifier names", () => {
|
||||
const ctrlEvent = createKeyboardEvent({ key: "a", code: "KeyA", ctrlKey: true });
|
||||
expect(matchesShortcut(ctrlEvent, "control+a")).toBe(true);
|
||||
|
||||
const metaEvent = createKeyboardEvent({ key: "a", code: "KeyA", metaKey: true });
|
||||
expect(matchesShortcut(metaEvent, "cmd+a")).toBe(true);
|
||||
expect(matchesShortcut(metaEvent, "command+a")).toBe(true);
|
||||
});
|
||||
|
||||
it("should handle empty or invalid shortcuts", () => {
|
||||
const event = createKeyboardEvent({ key: "a", code: "KeyA" });
|
||||
expect(matchesShortcut(event, "")).toBe(false);
|
||||
expect(matchesShortcut(event, null as any)).toBe(false);
|
||||
});
|
||||
|
||||
it("should handle invalid events", () => {
|
||||
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
|
||||
expect(matchesShortcut(null as any, "a")).toBe(false);
|
||||
expect(matchesShortcut({} as KeyboardEvent, "a")).toBe(false);
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("should warn about invalid shortcut formats", () => {
|
||||
const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
const event = createKeyboardEvent({ key: "a", code: "KeyA" });
|
||||
|
||||
matchesShortcut(event, "ctrl+");
|
||||
matchesShortcut(event, "+");
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
describe("bindGlobalShortcut", () => {
|
||||
it("should bind a global shortcut", () => {
|
||||
const handler = vi.fn();
|
||||
shortcuts.bindGlobalShortcut("ctrl+a", handler, "test-namespace");
|
||||
|
||||
expect(mockElement.addEventListener).toHaveBeenCalledWith("keydown", expect.any(Function));
|
||||
});
|
||||
|
||||
it("should not bind shortcuts when handler is null", () => {
|
||||
shortcuts.bindGlobalShortcut("ctrl+a", null, "test-namespace");
|
||||
|
||||
expect(mockElement.addEventListener).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should remove previous bindings when namespace is reused", () => {
|
||||
const handler1 = vi.fn();
|
||||
const handler2 = vi.fn();
|
||||
|
||||
shortcuts.bindGlobalShortcut("ctrl+a", handler1, "test-namespace");
|
||||
expect(mockElement.addEventListener).toHaveBeenCalledTimes(1);
|
||||
|
||||
shortcuts.bindGlobalShortcut("ctrl+b", handler2, "test-namespace");
|
||||
expect(mockElement.removeEventListener).toHaveBeenCalledTimes(1);
|
||||
expect(mockElement.addEventListener).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("bindElShortcut", () => {
|
||||
it("should bind shortcut to specific element", () => {
|
||||
const mockEl = { addEventListener: vi.fn(), removeEventListener: vi.fn() };
|
||||
const mockJQueryEl = [mockEl] as any;
|
||||
mockJQueryEl.length = 1;
|
||||
|
||||
const handler = vi.fn();
|
||||
shortcuts.bindElShortcut(mockJQueryEl, "ctrl+a", handler, "test-namespace");
|
||||
|
||||
expect(mockEl.addEventListener).toHaveBeenCalledWith("keydown", expect.any(Function));
|
||||
});
|
||||
|
||||
it("should fall back to document when element is empty", () => {
|
||||
const emptyJQuery = [] as any;
|
||||
emptyJQuery.length = 0;
|
||||
|
||||
const handler = vi.fn();
|
||||
shortcuts.bindElShortcut(emptyJQuery, "ctrl+a", handler, "test-namespace");
|
||||
|
||||
expect(mockElement.addEventListener).toHaveBeenCalledWith("keydown", expect.any(Function));
|
||||
});
|
||||
});
|
||||
|
||||
describe("removeGlobalShortcut", () => {
|
||||
it("should remove shortcuts for a specific namespace", () => {
|
||||
const handler = vi.fn();
|
||||
shortcuts.bindGlobalShortcut("ctrl+a", handler, "test-namespace");
|
||||
|
||||
shortcuts.removeGlobalShortcut("test-namespace");
|
||||
|
||||
expect(mockElement.removeEventListener).toHaveBeenCalledWith("keydown", expect.any(Function));
|
||||
});
|
||||
});
|
||||
|
||||
describe("event handling", () => {
|
||||
it.skip("should call handler when shortcut matches", () => {
|
||||
const handler = vi.fn();
|
||||
shortcuts.bindGlobalShortcut("ctrl+a", handler, "test-namespace");
|
||||
|
||||
// Get the listener that was registered
|
||||
expect(mockElement.addEventListener.mock.calls).toHaveLength(1);
|
||||
const [, listener] = mockElement.addEventListener.mock.calls[0];
|
||||
|
||||
// First verify that matchesShortcut works directly
|
||||
const testEvent = {
|
||||
type: "keydown",
|
||||
key: "a",
|
||||
code: "KeyA",
|
||||
ctrlKey: true,
|
||||
altKey: false,
|
||||
shiftKey: false,
|
||||
metaKey: false,
|
||||
preventDefault: vi.fn(),
|
||||
stopPropagation: vi.fn()
|
||||
} as any;
|
||||
|
||||
// Test matchesShortcut directly first
|
||||
expect(matchesShortcut(testEvent, "ctrl+a")).toBe(true);
|
||||
|
||||
// Now test the actual listener
|
||||
listener(testEvent);
|
||||
|
||||
expect(handler).toHaveBeenCalled();
|
||||
expect(testEvent.preventDefault).toHaveBeenCalled();
|
||||
expect(testEvent.stopPropagation).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should not call handler for non-keyboard events", () => {
|
||||
const handler = vi.fn();
|
||||
shortcuts.bindGlobalShortcut("ctrl+a", handler, "test-namespace");
|
||||
|
||||
const [, listener] = mockElement.addEventListener.mock.calls[0];
|
||||
|
||||
// Simulate a non-keyboard event
|
||||
const event = {
|
||||
type: "click"
|
||||
} as any;
|
||||
|
||||
listener(event);
|
||||
|
||||
expect(handler).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should not call handler when shortcut doesn't match", () => {
|
||||
const handler = vi.fn();
|
||||
shortcuts.bindGlobalShortcut("ctrl+a", handler, "test-namespace");
|
||||
|
||||
const [, listener] = mockElement.addEventListener.mock.calls[0];
|
||||
|
||||
// Simulate a non-matching keydown event
|
||||
const event = {
|
||||
type: "keydown",
|
||||
key: "b",
|
||||
code: "KeyB",
|
||||
ctrlKey: true,
|
||||
altKey: false,
|
||||
shiftKey: false,
|
||||
metaKey: false,
|
||||
preventDefault: vi.fn(),
|
||||
stopPropagation: vi.fn()
|
||||
} as any;
|
||||
|
||||
listener(event);
|
||||
|
||||
expect(handler).not.toHaveBeenCalled();
|
||||
expect(event.preventDefault).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,44 @@
|
||||
import utils from "./utils.js";
|
||||
|
||||
type ElementType = HTMLElement | Document;
|
||||
type Handler = (e: JQuery.TriggeredEvent<ElementType | Element, string, ElementType | Element, ElementType | Element>) => void;
|
||||
type Handler = (e: KeyboardEvent) => void;
|
||||
|
||||
interface ShortcutBinding {
|
||||
element: HTMLElement | Document;
|
||||
shortcut: string;
|
||||
handler: Handler;
|
||||
namespace: string | null;
|
||||
listener: (evt: Event) => void;
|
||||
}
|
||||
|
||||
// Store all active shortcut bindings for management
|
||||
const activeBindings: Map<string, ShortcutBinding[]> = new Map();
|
||||
|
||||
// Handle special key mappings and aliases
|
||||
const keyMap: { [key: string]: string[] } = {
|
||||
'return': ['Enter'],
|
||||
'enter': ['Enter'], // alias for return
|
||||
'del': ['Delete'],
|
||||
'delete': ['Delete'], // alias for del
|
||||
'esc': ['Escape'],
|
||||
'escape': ['Escape'], // alias for esc
|
||||
'space': [' ', 'Space'],
|
||||
'tab': ['Tab'],
|
||||
'backspace': ['Backspace'],
|
||||
'home': ['Home'],
|
||||
'end': ['End'],
|
||||
'pageup': ['PageUp'],
|
||||
'pagedown': ['PageDown'],
|
||||
'up': ['ArrowUp'],
|
||||
'down': ['ArrowDown'],
|
||||
'left': ['ArrowLeft'],
|
||||
'right': ['ArrowRight']
|
||||
};
|
||||
|
||||
// Function keys
|
||||
for (let i = 1; i <= 19; i++) {
|
||||
keyMap[`f${i}`] = [`F${i}`];
|
||||
}
|
||||
|
||||
function removeGlobalShortcut(namespace: string) {
|
||||
bindGlobalShortcut("", null, namespace);
|
||||
@@ -15,38 +52,141 @@ function bindElShortcut($el: JQuery<ElementType | Element>, keyboardShortcut: st
|
||||
if (utils.isDesktop()) {
|
||||
keyboardShortcut = normalizeShortcut(keyboardShortcut);
|
||||
|
||||
let eventName = "keydown";
|
||||
|
||||
// If namespace is provided, remove all previous bindings for this namespace
|
||||
if (namespace) {
|
||||
eventName += `.${namespace}`;
|
||||
|
||||
// if there's a namespace, then we replace the existing event handler with the new one
|
||||
$el.off(eventName);
|
||||
removeNamespaceBindings(namespace);
|
||||
}
|
||||
|
||||
// method can be called to remove the shortcut (e.g. when keyboardShortcut label is deleted)
|
||||
if (keyboardShortcut) {
|
||||
$el.bind(eventName, keyboardShortcut, (e) => {
|
||||
if (handler) {
|
||||
handler(e);
|
||||
// Method can be called to remove the shortcut (e.g. when keyboardShortcut label is deleted)
|
||||
if (keyboardShortcut && handler) {
|
||||
const element = $el.length > 0 ? $el[0] as (HTMLElement | Document) : document;
|
||||
|
||||
const listener = (evt: Event) => {
|
||||
// Only handle keyboard events
|
||||
if (evt.type !== 'keydown' || !(evt instanceof KeyboardEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const e = evt as KeyboardEvent;
|
||||
if (matchesShortcut(e, keyboardShortcut)) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
handler(e);
|
||||
}
|
||||
};
|
||||
|
||||
// Add the event listener
|
||||
element.addEventListener('keydown', listener);
|
||||
|
||||
// Store the binding for later cleanup
|
||||
const binding: ShortcutBinding = {
|
||||
element,
|
||||
shortcut: keyboardShortcut,
|
||||
handler,
|
||||
namespace,
|
||||
listener
|
||||
};
|
||||
|
||||
const key = namespace || 'global';
|
||||
if (!activeBindings.has(key)) {
|
||||
activeBindings.set(key, []);
|
||||
}
|
||||
activeBindings.get(key)!.push(binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeNamespaceBindings(namespace: string) {
|
||||
const bindings = activeBindings.get(namespace);
|
||||
if (bindings) {
|
||||
// Remove all event listeners for this namespace
|
||||
bindings.forEach(binding => {
|
||||
binding.element.removeEventListener('keydown', binding.listener);
|
||||
});
|
||||
activeBindings.delete(namespace);
|
||||
}
|
||||
}
|
||||
|
||||
export function matchesShortcut(e: KeyboardEvent, shortcut: string): boolean {
|
||||
if (!shortcut) return false;
|
||||
|
||||
// Ensure we have a proper KeyboardEvent with key property
|
||||
if (!e || typeof e.key !== 'string') {
|
||||
console.warn('matchesShortcut called with invalid event:', e);
|
||||
return false;
|
||||
}
|
||||
|
||||
const parts = shortcut.toLowerCase().split('+');
|
||||
const key = parts[parts.length - 1]; // Last part is the actual key
|
||||
const modifiers = parts.slice(0, -1); // Everything before is modifiers
|
||||
|
||||
// Defensive check - ensure we have a valid key
|
||||
if (!key || key.trim() === '') {
|
||||
console.warn('Invalid shortcut format:', shortcut);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the main key matches
|
||||
if (!keyMatches(e, key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check modifiers
|
||||
const expectedCtrl = modifiers.includes('ctrl') || modifiers.includes('control');
|
||||
const expectedAlt = modifiers.includes('alt');
|
||||
const expectedShift = modifiers.includes('shift');
|
||||
const expectedMeta = modifiers.includes('meta') || modifiers.includes('cmd') || modifiers.includes('command');
|
||||
|
||||
return e.ctrlKey === expectedCtrl &&
|
||||
e.altKey === expectedAlt &&
|
||||
e.shiftKey === expectedShift &&
|
||||
e.metaKey === expectedMeta;
|
||||
}
|
||||
|
||||
export function keyMatches(e: KeyboardEvent, key: string): boolean {
|
||||
// Defensive check for undefined/null key
|
||||
if (!key) {
|
||||
console.warn('keyMatches called with undefined/null key');
|
||||
return false;
|
||||
}
|
||||
|
||||
const mappedKeys = keyMap[key.toLowerCase()];
|
||||
if (mappedKeys) {
|
||||
return mappedKeys.includes(e.key) || mappedKeys.includes(e.code);
|
||||
}
|
||||
|
||||
// For number keys, use the physical key code regardless of modifiers
|
||||
// This works across all keyboard layouts
|
||||
if (key >= '0' && key <= '9') {
|
||||
return e.code === `Digit${key}`;
|
||||
}
|
||||
|
||||
// For letter keys, use the physical key code for consistency
|
||||
if (key.length === 1 && key >= 'a' && key <= 'z') {
|
||||
return e.key.toLowerCase() === key.toLowerCase();
|
||||
}
|
||||
|
||||
// For regular keys, check both key and code as fallback
|
||||
return e.key.toLowerCase() === key.toLowerCase() ||
|
||||
e.code.toLowerCase() === key.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize to the form expected by the jquery.hotkeys.js
|
||||
* Simple normalization - just lowercase and trim whitespace
|
||||
*/
|
||||
function normalizeShortcut(shortcut: string): string {
|
||||
if (!shortcut) {
|
||||
return shortcut;
|
||||
}
|
||||
|
||||
return shortcut.toLowerCase().replace("enter", "return").replace("delete", "del").replace("ctrl+alt", "alt+ctrl").replace("meta+alt", "alt+meta"); // alt needs to be first;
|
||||
const normalized = shortcut.toLowerCase().trim().replace(/\s+/g, '');
|
||||
|
||||
// Warn about potentially problematic shortcuts
|
||||
if (normalized.endsWith('+') || normalized.startsWith('+') || normalized.includes('++')) {
|
||||
console.warn('Potentially malformed shortcut:', shortcut, '-> normalized to:', normalized);
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -51,6 +51,14 @@ export default class SpacedUpdate {
|
||||
this.lastUpdated = Date.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the update interval for the spaced update.
|
||||
* @param interval The update interval in milliseconds.
|
||||
*/
|
||||
setUpdateInterval(interval: number) {
|
||||
this.updateInterval = interval;
|
||||
}
|
||||
|
||||
triggerUpdate() {
|
||||
if (!this.changed) {
|
||||
return;
|
||||
|
||||
@@ -36,7 +36,9 @@ export function applyCopyToClipboardButton($codeBlock: JQuery<HTMLElement>) {
|
||||
const $copyButton = $("<button>")
|
||||
.addClass("bx component icon-action tn-tool-button bx-copy copy-button")
|
||||
.attr("title", t("code_block.copy_title"))
|
||||
.on("click", () => {
|
||||
.on("click", (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
if (!isShare) {
|
||||
copyTextWithToast($codeBlock.text());
|
||||
} else {
|
||||
|
||||
@@ -5,7 +5,7 @@ const SVG_MIME = "image/svg+xml";
|
||||
|
||||
export const isShare = !window.glob;
|
||||
|
||||
function reloadFrontendApp(reason?: string) {
|
||||
export function reloadFrontendApp(reason?: string) {
|
||||
if (reason) {
|
||||
logInfo(`Frontend app reload: ${reason}`);
|
||||
}
|
||||
@@ -13,7 +13,7 @@ function reloadFrontendApp(reason?: string) {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
function restartDesktopApp() {
|
||||
export function restartDesktopApp() {
|
||||
if (!isElectron()) {
|
||||
reloadFrontendApp();
|
||||
return;
|
||||
@@ -125,7 +125,7 @@ function formatDateISO(date: Date) {
|
||||
return `${date.getFullYear()}-${padNum(date.getMonth() + 1)}-${padNum(date.getDate())}`;
|
||||
}
|
||||
|
||||
function formatDateTime(date: Date, userSuppliedFormat?: string): string {
|
||||
export function formatDateTime(date: Date, userSuppliedFormat?: string): string {
|
||||
if (userSuppliedFormat?.trim()) {
|
||||
return dayjs(date).format(userSuppliedFormat);
|
||||
} else {
|
||||
@@ -144,7 +144,7 @@ function now() {
|
||||
/**
|
||||
* Returns `true` if the client is currently running under Electron, or `false` if running in a web browser.
|
||||
*/
|
||||
function isElectron() {
|
||||
export function isElectron() {
|
||||
return !!(window && window.process && window.process.type);
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ function randomString(len: number) {
|
||||
return text;
|
||||
}
|
||||
|
||||
function isMobile() {
|
||||
export function isMobile() {
|
||||
return (
|
||||
window.glob?.device === "mobile" ||
|
||||
// window.glob.device is not available in setup
|
||||
@@ -306,7 +306,7 @@ function copySelectionToClipboard() {
|
||||
}
|
||||
}
|
||||
|
||||
function dynamicRequire(moduleName: string) {
|
||||
export function dynamicRequire(moduleName: string) {
|
||||
if (typeof __non_webpack_require__ !== "undefined") {
|
||||
return __non_webpack_require__(moduleName);
|
||||
} else {
|
||||
@@ -374,6 +374,17 @@ async function openInAppHelp($button: JQuery<HTMLElement>) {
|
||||
|
||||
const inAppHelpPage = $button.attr("data-in-app-help");
|
||||
if (inAppHelpPage) {
|
||||
openInAppHelpFromUrl(inAppHelpPage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the in-app help at the given page in a split note. If there already is a split note open with a help page, it will be replaced by this one.
|
||||
*
|
||||
* @param inAppHelpPage the ID of the help note (excluding the `_help_` prefix).
|
||||
* @returns a promise that resolves once the help has been opened.
|
||||
*/
|
||||
export async function openInAppHelpFromUrl(inAppHelpPage: string) {
|
||||
// Dynamic import to avoid import issues in tests.
|
||||
const appContext = (await import("../components/app_context.js")).default;
|
||||
const activeContext = appContext.tabManager.getActiveContext();
|
||||
@@ -399,8 +410,6 @@ async function openInAppHelp($button: JQuery<HTMLElement>) {
|
||||
// There is already a help window open, make sure it opens on the right note.
|
||||
helpSubcontext.setNote(targetNote, { viewScope });
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function initHelpButtons($el: JQuery<HTMLElement> | JQuery<Window>) {
|
||||
@@ -735,6 +744,50 @@ function isLaunchBarConfig(noteId: string) {
|
||||
return ["_lbRoot", "_lbAvailableLaunchers", "_lbVisibleLaunchers", "_lbMobileRoot", "_lbMobileAvailableLaunchers", "_lbMobileVisibleLaunchers"].includes(noteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a class to the <body> of the page, where the class name is formed via a prefix and a value.
|
||||
* Useful for configurable options such as `heading-style-markdown`, where `heading-style` is the prefix and `markdown` is the dynamic value.
|
||||
* There is no separator between the prefix and the value, if needed it has to be supplied manually to the prefix.
|
||||
*
|
||||
* @param prefix the prefix.
|
||||
* @param value the value to be appended to the prefix.
|
||||
*/
|
||||
export function toggleBodyClass(prefix: string, value: string) {
|
||||
const $body = $("body");
|
||||
for (const clazz of Array.from($body[0].classList)) {
|
||||
// create copy to safely iterate over while removing classes
|
||||
if (clazz.startsWith(prefix)) {
|
||||
$body.removeClass(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
$body.addClass(prefix + value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic comparison for equality between the two arrays. The values are strictly checked via `===`.
|
||||
*
|
||||
* @param a the first array to compare.
|
||||
* @param b the second array to compare.
|
||||
* @returns `true` if both arrays are equals, `false` otherwise.
|
||||
*/
|
||||
export function arrayEqual<T>(a: T[], b: T[]) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i=0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export default {
|
||||
reloadFrontendApp,
|
||||
restartDesktopApp,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import "jquery";
|
||||
import "jquery-hotkeys";
|
||||
import utils from "./services/utils.js";
|
||||
import ko from "knockout";
|
||||
import "./stylesheets/bootstrap.scss";
|
||||
|
||||
@@ -29,6 +29,14 @@ async function formatCodeBlocks() {
|
||||
await formatCodeBlocks($("#content"));
|
||||
}
|
||||
|
||||
async function setupTextNote() {
|
||||
formatCodeBlocks();
|
||||
applyMath();
|
||||
|
||||
const setupMermaid = (await import("./share/mermaid.js")).default;
|
||||
setupMermaid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch note with given ID from backend
|
||||
*
|
||||
@@ -47,8 +55,11 @@ async function fetchNote(noteId: string | null = null) {
|
||||
document.addEventListener(
|
||||
"DOMContentLoaded",
|
||||
() => {
|
||||
formatCodeBlocks();
|
||||
applyMath();
|
||||
const noteType = determineNoteType();
|
||||
|
||||
if (noteType === "text") {
|
||||
setupTextNote();
|
||||
}
|
||||
|
||||
const toggleMenuButton = document.getElementById("toggleMenuButton");
|
||||
const layout = document.getElementById("layout");
|
||||
@@ -60,6 +71,12 @@ document.addEventListener(
|
||||
false
|
||||
);
|
||||
|
||||
function determineNoteType() {
|
||||
const bodyClass = document.body.className;
|
||||
const match = bodyClass.match(/type-([^\s]+)/);
|
||||
return match ? match[1] : null;
|
||||
}
|
||||
|
||||
// workaround to prevent webpack from removing "fetchNote" as dead code:
|
||||
// add fetchNote as property to the window object
|
||||
Object.defineProperty(window, "fetchNote", {
|
||||
|
||||
17
apps/client/src/share/mermaid.ts
Normal file
17
apps/client/src/share/mermaid.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import mermaid from "mermaid";
|
||||
|
||||
export default function setupMermaid() {
|
||||
for (const codeBlock of document.querySelectorAll("#content pre code.language-mermaid")) {
|
||||
const parentPre = codeBlock.parentElement;
|
||||
if (!parentPre) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const mermaidDiv = document.createElement("div");
|
||||
mermaidDiv.classList.add("mermaid");
|
||||
mermaidDiv.innerHTML = codeBlock.innerHTML;
|
||||
parentPre.replaceWith(mermaidDiv);
|
||||
}
|
||||
|
||||
mermaid.init();
|
||||
}
|
||||
@@ -81,8 +81,8 @@ body {
|
||||
|
||||
/* -- Overrides the default colors used by the ckeditor5-image package. --------------------- */
|
||||
|
||||
--ck-color-image-caption-background: var(--main-background-color);
|
||||
--ck-color-image-caption-text: var(--main-text-color);
|
||||
--ck-content-color-image-caption-background: var(--main-background-color);
|
||||
--ck-content-color-image-caption-text: var(--main-text-color);
|
||||
|
||||
/* -- Overrides the default colors used by the ckeditor5-widget package. -------------------- */
|
||||
|
||||
|
||||
@@ -28,6 +28,28 @@
|
||||
--ck-mention-list-max-height: 500px;
|
||||
}
|
||||
|
||||
body#trilium-app.motion-disabled *,
|
||||
body#trilium-app.motion-disabled *::before,
|
||||
body#trilium-app.motion-disabled *::after {
|
||||
/* Disable transitions and animations */
|
||||
transition: none !important;
|
||||
animation: none !important;
|
||||
}
|
||||
|
||||
body#trilium-app.shadows-disabled *,
|
||||
body#trilium-app.shadows-disabled *::before,
|
||||
body#trilium-app.shadows-disabled *::after {
|
||||
/* Disable shadows */
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
body#trilium-app.backdrop-effects-disabled *,
|
||||
body#trilium-app.backdrop-effects-disabled *::before,
|
||||
body#trilium-app.backdrop-effects-disabled *::after {
|
||||
/* Disable backdrop effects */
|
||||
backdrop-filter: none !important;
|
||||
}
|
||||
|
||||
.table {
|
||||
--bs-table-bg: transparent !important;
|
||||
}
|
||||
@@ -139,10 +161,13 @@ textarea,
|
||||
color: var(--muted-text-color);
|
||||
}
|
||||
|
||||
/* Restore default apperance */
|
||||
input[type="number"],
|
||||
input[type="checkbox"] {
|
||||
appearance: auto !important;
|
||||
.form-group.disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
/* Add a gap between consecutive radios / check boxes */
|
||||
@@ -192,6 +217,13 @@ samp {
|
||||
font-family: var(--monospace-font-family) !important;
|
||||
}
|
||||
|
||||
.badge {
|
||||
--bs-badge-color: var(--muted-text-color);
|
||||
|
||||
margin-left: 8px;
|
||||
background: var(--accented-background-color);
|
||||
}
|
||||
|
||||
.input-group-text {
|
||||
background-color: var(--accented-background-color) !important;
|
||||
color: var(--muted-text-color) !important;
|
||||
@@ -320,7 +352,8 @@ button kbd {
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
.dropdown-menu,
|
||||
.tabulator-popup-container {
|
||||
color: var(--menu-text-color) !important;
|
||||
font-size: inherit;
|
||||
background-color: var(--menu-background-color) !important;
|
||||
@@ -330,7 +363,13 @@ button kbd {
|
||||
--bs-dropdown-link-active-bg: var(--active-item-background-color) !important;
|
||||
}
|
||||
|
||||
body.desktop .dropdown-menu {
|
||||
.dropdown-menu .dropdown-divider {
|
||||
break-before: avoid;
|
||||
break-after: avoid;
|
||||
}
|
||||
|
||||
body.desktop .dropdown-menu,
|
||||
body.desktop .tabulator-popup-container {
|
||||
border: 1px solid var(--dropdown-border-color);
|
||||
box-shadow: 0px 10px 20px rgba(0, 0, 0, var(--dropdown-shadow-opacity));
|
||||
animation: dropdown-menu-opening 100ms ease-in;
|
||||
@@ -338,7 +377,7 @@ body.desktop .dropdown-menu {
|
||||
|
||||
@supports (animation-fill-mode: forwards) {
|
||||
/* Delay the opening of submenus */
|
||||
body.desktop .dropdown-submenu .dropdown-menu {
|
||||
body.desktop:not(.motion-disabled) .dropdown-submenu .dropdown-menu {
|
||||
opacity: 0;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: var(--submenu-opening-delay);
|
||||
@@ -373,7 +412,8 @@ body.desktop .dropdown-menu {
|
||||
}
|
||||
|
||||
.dropdown-menu a:hover:not(.disabled),
|
||||
.dropdown-item:hover:not(.disabled, .dropdown-item-container) {
|
||||
.dropdown-item:hover:not(.disabled, .dropdown-item-container),
|
||||
.tabulator-menu-item:hover {
|
||||
color: var(--hover-item-text-color) !important;
|
||||
background-color: var(--hover-item-background-color) !important;
|
||||
border-color: var(--hover-item-border-color) !important;
|
||||
@@ -528,6 +568,7 @@ button.btn-sm {
|
||||
/* Making this narrower because https://github.com/zadam/trilium/issues/502 (problem only in smaller font sizes) */
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
pre:not(.hljs) {
|
||||
@@ -632,6 +673,10 @@ table.promoted-attributes-in-tooltip th {
|
||||
z-index: calc(var(--ck-z-panel) - 1) !important;
|
||||
}
|
||||
|
||||
.tooltip.tooltip-top {
|
||||
z-index: 32767 !important;
|
||||
}
|
||||
|
||||
.tooltip-trigger {
|
||||
background: transparent;
|
||||
pointer-events: none;
|
||||
@@ -759,6 +804,14 @@ table.promoted-attributes-in-tooltip th {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.note-tooltip-content .open-popup-button {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
bottom: 8px;
|
||||
font-size: 1.2em;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.note-tooltip-attributes {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
@@ -900,6 +953,13 @@ div[data-notify="container"] {
|
||||
font-family: var(--monospace-font-family);
|
||||
}
|
||||
|
||||
.ck-content {
|
||||
--ck-content-font-family: var(--detail-font-family);
|
||||
--ck-content-font-size: 1.1em;
|
||||
--ck-content-font-color: var(--main-text-color);
|
||||
--ck-content-line-height: var(--bs-body-line-height);
|
||||
}
|
||||
|
||||
.ck-content .table table th {
|
||||
background-color: var(--accented-background-color);
|
||||
}
|
||||
@@ -1186,12 +1246,14 @@ body.mobile .dropdown-submenu > .dropdown-menu {
|
||||
}
|
||||
|
||||
#context-menu-container,
|
||||
#context-menu-container .dropdown-menu {
|
||||
padding: 3px 0 0;
|
||||
#context-menu-container .dropdown-menu,
|
||||
.tabulator-popup-container {
|
||||
padding: 3px 0;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
#context-menu-container .dropdown-item {
|
||||
#context-menu-container .dropdown-item,
|
||||
.tabulator-menu .tabulator-menu-item {
|
||||
padding: 0 7px 0 10px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
@@ -1707,16 +1769,12 @@ button.close:hover {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.options-number-input {
|
||||
.options-section input[type="number"] {
|
||||
/* overriding settings from .form-control */
|
||||
width: 10em !important;
|
||||
flex-grow: 0 !important;
|
||||
}
|
||||
|
||||
.options-mime-types {
|
||||
column-width: 250px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
cursor: auto;
|
||||
}
|
||||
@@ -1753,6 +1811,54 @@ textarea {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
/* Command palette styling */
|
||||
.jump-to-note-dialog .command-suggestion {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .aa-suggestion .command-suggestion,
|
||||
.jump-to-note-dialog .aa-suggestion .command-suggestion div {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .aa-cursor .command-suggestion,
|
||||
.jump-to-note-dialog .aa-suggestion:hover .command-suggestion {
|
||||
border-left-color: var(--link-color);
|
||||
background-color: var(--hover-background-color);
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .command-icon {
|
||||
color: var(--muted-text-color);
|
||||
font-size: 1.125rem;
|
||||
flex-shrink: 0;
|
||||
margin-top: 0.125rem;
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .command-content {
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .command-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .command-description {
|
||||
font-size: 0.8em;
|
||||
line-height: 1.3;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.jump-to-note-dialog kbd.command-shortcut {
|
||||
background-color: transparent;
|
||||
color: inherit;
|
||||
opacity: 0.75;
|
||||
font-family: inherit !important;
|
||||
}
|
||||
|
||||
.empty-table-placeholder {
|
||||
text-align: center;
|
||||
color: var(--muted-text-color);
|
||||
@@ -1811,6 +1917,7 @@ body.zen #launcher-container,
|
||||
body.zen #launcher-pane,
|
||||
body.zen #left-pane,
|
||||
body.zen #right-pane,
|
||||
body.zen #mobile-sidebar-wrapper,
|
||||
body.zen .tab-row-container,
|
||||
body.zen .tab-row-widget,
|
||||
body.zen .ribbon-container:not(:has(.classic-toolbar-widget.visible)),
|
||||
@@ -1818,7 +1925,8 @@ body.zen .ribbon-container:has(.classic-toolbar-widget.visible) .ribbon-top-row,
|
||||
body.zen .ribbon-container .ribbon-body:not(:has(.classic-toolbar-widget.visible)),
|
||||
body.zen .note-icon-widget,
|
||||
body.zen .title-row .button-widget,
|
||||
body.zen .floating-buttons-children > *:not(.bx-edit-alt) {
|
||||
body.zen .floating-buttons-children > *:not(.bx-edit-alt),
|
||||
body.zen .action-button {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@@ -1860,14 +1968,20 @@ body.zen .note-title-widget input {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
body.zen #detail-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Content renderer */
|
||||
|
||||
footer.file-footer {
|
||||
footer.file-footer,
|
||||
footer.webview-footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
footer.file-footer button {
|
||||
footer.file-footer button,
|
||||
footer.webview-footer button {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
@@ -2168,6 +2282,13 @@ footer.file-footer button {
|
||||
padding: 1px 10px 1px 10px;
|
||||
}
|
||||
|
||||
/* Search result highlighting */
|
||||
.search-result-title b,
|
||||
.search-result-content b {
|
||||
font-weight: 900;
|
||||
color: var(--admonition-warning-accent-color);
|
||||
}
|
||||
|
||||
/* Customized icons */
|
||||
|
||||
.bx-tn-toc::before {
|
||||
|
||||
199
apps/client/src/stylesheets/table.css
Normal file
199
apps/client/src/stylesheets/table.css
Normal file
@@ -0,0 +1,199 @@
|
||||
.tabulator {
|
||||
--table-background-color: var(--main-background-color);
|
||||
|
||||
--col-header-background-color: var(--main-background-color);
|
||||
--col-header-hover-background-color: var(--accented-background-color);
|
||||
--col-header-text-color: var(--main-text-color);
|
||||
--col-header-arrow-active-color: var(--main-text-color);
|
||||
--col-header-arrow-inactive-color: var(--more-accented-background-color);
|
||||
--col-header-separator-border: none;
|
||||
--col-header-bottom-border: 2px solid var(--main-border-color);
|
||||
|
||||
--row-background-color: var(--main-background-color);
|
||||
--row-alternate-background-color: var(--main-background-color);
|
||||
--row-moving-background-color: var(--accented-background-color);
|
||||
--row-text-color: var(--main-text-color);
|
||||
--row-delimiter-color: var(--more-accented-background-color);
|
||||
|
||||
--cell-horiz-padding-size: 8px;
|
||||
--cell-vert-padding-size: 8px;
|
||||
|
||||
--cell-editable-hover-outline-color: var(--main-border-color);
|
||||
--cell-read-only-text-color: var(--muted-text-color);
|
||||
|
||||
--cell-editing-border-color: var(--main-border-color);
|
||||
--cell-editing-border-width: 2px;
|
||||
--cell-editing-background-color: var(--ck-color-selector-focused-cell-background);
|
||||
--cell-editing-text-color: initial;
|
||||
|
||||
background: unset;
|
||||
border: unset;
|
||||
}
|
||||
|
||||
.tabulator .tabulator-tableholder .tabulator-table {
|
||||
background: var(--table-background-color);
|
||||
}
|
||||
|
||||
/* Column headers */
|
||||
|
||||
.tabulator div.tabulator-header {
|
||||
border-bottom: var(--col-header-bottom-border);
|
||||
background: var(--col-header-background-color);
|
||||
color: var(--col-header-text-color);
|
||||
}
|
||||
|
||||
.tabulator .tabulator-col-content {
|
||||
padding: 8px 4px !important;
|
||||
}
|
||||
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
.tabulator .tabulator-header .tabulator-col.tabulator-sortable.tabulator-col-sorter-element:hover {
|
||||
background-color: var(--col-header-hover-background-color);
|
||||
}
|
||||
}
|
||||
|
||||
.tabulator div.tabulator-header .tabulator-col.tabulator-moving {
|
||||
border: none;
|
||||
background: var(--col-header-hover-background-color);
|
||||
}
|
||||
|
||||
.tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort] .tabulator-col-content .tabulator-col-sorter .tabulator-arrow {
|
||||
border-bottom-color: var(--col-header-arrow-active-color);
|
||||
border-top-color: var(--col-header-arrow-active-color);
|
||||
}
|
||||
|
||||
.tabulator .tabulator-header .tabulator-col.tabulator-sortable[aria-sort="none"] .tabulator-col-content .tabulator-col-sorter .tabulator-arrow {
|
||||
border-bottom-color: var(--col-header-arrow-inactive-color);
|
||||
}
|
||||
|
||||
.tabulator div.tabulator-header .tabulator-frozen.tabulator-frozen-left {
|
||||
margin-left: var(--cell-editing-border-width);
|
||||
}
|
||||
|
||||
.tabulator div.tabulator-header .tabulator-col,
|
||||
.tabulator div.tabulator-header .tabulator-frozen.tabulator-frozen-left {
|
||||
background: var(--col-header-background-color);
|
||||
border-right: var(--col-header-separator-border);
|
||||
}
|
||||
|
||||
/* Table body */
|
||||
|
||||
.tabulator-tableholder {
|
||||
padding-top: 10px;
|
||||
height: unset !important; /* Don't extend on the full height */
|
||||
}
|
||||
|
||||
/* Rows */
|
||||
|
||||
.tabulator-row .tabulator-cell {
|
||||
padding: var(--cell-vert-padding-size) var(--cell-horiz-padding-size);
|
||||
}
|
||||
|
||||
.tabulator-row .tabulator-cell input {
|
||||
padding-left: var(--cell-horiz-padding-size) !important;
|
||||
padding-right: var(--cell-horiz-padding-size) !important;
|
||||
}
|
||||
|
||||
.tabulator-row {
|
||||
background: transparent;
|
||||
border-top: none;
|
||||
border-bottom: 1px solid var(--row-delimiter-color);
|
||||
color: var(--row-text-color);
|
||||
}
|
||||
|
||||
.tabulator-row.tabulator-row-odd {
|
||||
background: var(--row-background-color);
|
||||
}
|
||||
|
||||
.tabulator-row.tabulator-row-even {
|
||||
background: var(--row-alternate-background-color);
|
||||
}
|
||||
|
||||
.tabulator-row.tabulator-moving {
|
||||
border-color: transparent;
|
||||
background-color: var(--row-moving-background-color);
|
||||
}
|
||||
|
||||
/* Cell */
|
||||
|
||||
.tabulator-row .tabulator-cell.tabulator-frozen.tabulator-frozen-left {
|
||||
margin-right: var(--cell-editing-border-width);
|
||||
}
|
||||
|
||||
.tabulator-row .tabulator-cell.tabulator-frozen.tabulator-frozen-left,
|
||||
.tabulator-row .tabulator-cell {
|
||||
border-right-color: transparent;
|
||||
}
|
||||
|
||||
.tabulator-row .tabulator-cell:not(.tabulator-editable) {
|
||||
color: var(--cell-read-only-text-color);
|
||||
}
|
||||
|
||||
.tabulator:not(.tabulator-editing) .tabulator-row .tabulator-cell.tabulator-editable:hover {
|
||||
outline: 2px solid var(--cell-editable-hover-outline-color);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
.tabulator-row .tabulator-cell.tabulator-editing {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.tabulator-row:not(.tabulator-moving) .tabulator-cell.tabulator-editing {
|
||||
outline: calc(var(--cell-editing-border-width) - 1px) solid var(--cell-editing-border-color);
|
||||
border-color: var(--cell-editing-border-color);
|
||||
background: var(--cell-editing-background-color);
|
||||
}
|
||||
|
||||
.tabulator-row:not(.tabulator-moving) .tabulator-cell.tabulator-editing > * {
|
||||
color: var(--cell-editing-text-color);
|
||||
}
|
||||
|
||||
.tabulator .tree-collapse,
|
||||
.tabulator .tree-expand {
|
||||
color: var(--row-text-color);
|
||||
}
|
||||
|
||||
/* Align items without children/expander to the ones with. */
|
||||
.tabulator-cell[tabulator-field="title"] > span:first-child, /* 1st level */
|
||||
.tabulator-cell[tabulator-field="title"] > div:first-child + span { /* sub-level */
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
/* Checkbox cells */
|
||||
|
||||
.tabulator .tabulator-cell:has(svg),
|
||||
.tabulator .tabulator-cell:has(input[type="checkbox"]) {
|
||||
padding-left: 8px;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.tabulator .tabulator-cell input[type="checkbox"] {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tabulator .tabulator-footer {
|
||||
color: var(--main-text-color);
|
||||
}
|
||||
|
||||
/* Context menus */
|
||||
|
||||
.tabulator-popup-container {
|
||||
min-width: 10em;
|
||||
border-radius: var(--bs-border-radius);
|
||||
}
|
||||
|
||||
.tabulator-menu .tabulator-menu-item {
|
||||
border: 1px solid transparent;
|
||||
color: var(--menu-text-color);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
|
||||
:root .tabulator .tabulator-footer {
|
||||
border-top: unset;
|
||||
padding: 10px 0;
|
||||
}
|
||||
@@ -89,6 +89,7 @@
|
||||
|
||||
--menu-text-color: #e3e3e3;
|
||||
--menu-background-color: #222222d9;
|
||||
--menu-background-color-no-backdrop: #1b1b1b;
|
||||
--menu-item-icon-color: #8c8c8c;
|
||||
--menu-item-disabled-opacity: 0.5;
|
||||
--menu-item-keyboard-shortcut-color: #ffffff8f;
|
||||
@@ -178,6 +179,9 @@
|
||||
|
||||
--alert-bar-background: #6b6b6b3b;
|
||||
|
||||
--badge-background-color: #ffffff1a;
|
||||
--badge-text-color: var(--muted-text-color);
|
||||
|
||||
--promoted-attribute-card-background-color: var(--card-background-color);
|
||||
--promoted-attribute-card-shadow-color: #000000b3;
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
|
||||
--menu-text-color: #272727;
|
||||
--menu-background-color: #ffffffd9;
|
||||
--menu-background-color-no-backdrop: #fdfdfd;
|
||||
--menu-item-icon-color: #727272;
|
||||
--menu-item-disabled-opacity: 0.6;
|
||||
--menu-item-keyboard-shortcut-color: #666666a8;
|
||||
@@ -171,6 +172,9 @@
|
||||
|
||||
--alert-bar-background: #32637b29;
|
||||
|
||||
--badge-background-color: #00000011;
|
||||
--badge-text-color: var(--muted-text-color);
|
||||
|
||||
--promoted-attribute-card-background-color: var(--card-background-color);
|
||||
--promoted-attribute-card-shadow-color: #00000033;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
@import url(./pages.css);
|
||||
@import url(./ribbon.css);
|
||||
@import url(./notes/text.css);
|
||||
@import url(./notes/collections/table.css);
|
||||
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
@@ -82,6 +83,12 @@
|
||||
--tab-note-icons: true;
|
||||
}
|
||||
|
||||
body.backdrop-effects-disabled {
|
||||
/* Backdrop effects are disabled, replace the menu background color with the
|
||||
* no-backdrop fallback color */
|
||||
--menu-background-color: var(--menu-background-color-no-backdrop);
|
||||
}
|
||||
|
||||
/*
|
||||
* MENUS
|
||||
*
|
||||
@@ -171,9 +178,19 @@ html body .dropdown-item[disabled] {
|
||||
opacity: var(--menu-item-disabled-opacity);
|
||||
}
|
||||
|
||||
/* Badges */
|
||||
:root .badge {
|
||||
--bs-badge-color: var(--badge-text-color);
|
||||
--bs-badge-font-weight: 500;
|
||||
|
||||
background: var(--badge-background-color);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .2pt;
|
||||
}
|
||||
|
||||
/* Menu item icon */
|
||||
.dropdown-item .bx {
|
||||
transform: translateY(var(--menu-item-icon-vert-offset));
|
||||
translate: 0 var(--menu-item-icon-vert-offset);
|
||||
color: var(--menu-item-icon-color) !important;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
@@ -447,6 +464,11 @@ body.mobile .dropdown-menu .dropdown-item.submenu-open .dropdown-toggle::after {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-image .rendered-content,
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-pdf .rendered-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content .rendered-content.text-with-ellipsis {
|
||||
padding: 1rem !important;
|
||||
}
|
||||
|
||||
@@ -128,10 +128,15 @@ div.tn-tool-dialog {
|
||||
|
||||
.jump-to-note-dialog .modal-header {
|
||||
padding: unset !important;
|
||||
padding-bottom: 26px !important;
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .modal-body {
|
||||
padding: 26px 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .modal-footer {
|
||||
padding-top: 26px;
|
||||
}
|
||||
|
||||
/* Search box wrapper */
|
||||
@@ -228,16 +233,16 @@ div.tn-tool-dialog {
|
||||
|
||||
/* Item title link */
|
||||
|
||||
.recent-changes-content ul li .note-title a {
|
||||
.recent-changes-content ul li a {
|
||||
color: currentColor;
|
||||
}
|
||||
|
||||
.recent-changes-content ul li .note-title a:hover {
|
||||
.recent-changes-content ul li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Item title for deleted notes */
|
||||
.recent-changes-content ul li.deleted-note .note-title > .note-title {
|
||||
.recent-changes-content ul li.deleted-note .note-title {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
@@ -382,6 +387,10 @@ div.tn-tool-dialog {
|
||||
|
||||
/* DELETE NOTE PREVIEW DIALOG */
|
||||
|
||||
.delete-notes-dialog .modal-dialog {
|
||||
--bs-modal-width: fit-content;
|
||||
}
|
||||
|
||||
.delete-notes-list .note-path {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
:root .tabulator {
|
||||
--col-header-hover-background-color: var(--hover-item-background-color);
|
||||
--col-header-arrow-active-color: var(--active-item-text-color);
|
||||
--col-header-arrow-inactive-color: var(--main-border-color);
|
||||
|
||||
--row-moving-background-color: var(--more-accented-background-color);
|
||||
|
||||
--cell-editable-hover-outline-color: var(--input-focus-outline-color);
|
||||
|
||||
--cell-editing-border-color: var(--input-focus-outline-color);
|
||||
--cell-editing-background-color: var(--input-background-color);
|
||||
--cell-editing-text-color: var(--input-text-color);
|
||||
}
|
||||
@@ -182,8 +182,6 @@ div.note-detail-empty {
|
||||
|
||||
.options-section:not(.tn-no-card) {
|
||||
margin: auto;
|
||||
min-width: var(--options-card-min-width);
|
||||
max-width: var(--options-card-max-width);
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--card-border-color) !important;
|
||||
box-shadow: var(--card-box-shadow);
|
||||
@@ -192,6 +190,11 @@ div.note-detail-empty {
|
||||
margin-bottom: calc(var(--options-title-offset) + 26px) !important;
|
||||
}
|
||||
|
||||
body.desktop .option-section:not(.tn-no-card) {
|
||||
min-width: var(--options-card-min-width);
|
||||
max-width: var(--options-card-max-width);
|
||||
}
|
||||
|
||||
.note-detail-content-widget-content.options {
|
||||
--default-padding: 15px;
|
||||
padding-top: calc(var(--default-padding) + var(--options-title-offset) + var(--options-title-font-size));
|
||||
@@ -233,11 +236,6 @@ div.note-detail-empty {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.options-section .options-mime-types {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.options-section .form-group {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,12 @@ div.promoted-attributes-container {
|
||||
.image-properties > div:first-child > span > strong {
|
||||
opacity: 0.65;
|
||||
font-weight: 500;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.note-info-widget-table td,
|
||||
.file-properties-widget .file-table td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.file-properties-widget {
|
||||
|
||||
@@ -71,12 +71,13 @@ body.background-effects.platform-win32.layout-vertical #vertical-main-container
|
||||
/* #endregion */
|
||||
|
||||
/* Matches when the left pane is collapsed */
|
||||
:has(.layout-vertical #left-pane.hidden-int) {
|
||||
#horizontal-main-container.left-pane-hidden {
|
||||
--center-pane-border-radius: 0;
|
||||
--tab-first-item-horiz-offset: 5px;
|
||||
}
|
||||
|
||||
:has(#left-pane.hidden-int) #launcher-pane.vertical {
|
||||
/* Add a border to the vertical launch bar if collapsed. */
|
||||
body.layout-vertical #horizontal-main-container.left-pane-hidden #launcher-pane.vertical {
|
||||
border-right: 2px solid var(--left-pane-collapsed-border-color);
|
||||
}
|
||||
|
||||
@@ -1300,9 +1301,9 @@ div.promoted-attribute-cell .tn-checkbox {
|
||||
height: 1cap;
|
||||
}
|
||||
|
||||
/* The <div> containing the checkbox for a promoted boolean attribute */
|
||||
div.promoted-attribute-cell div:has(input[type="checkbox"]) {
|
||||
order: -1; /* Relocate the checkbox before the label */
|
||||
/* Relocate the checkbox before the label */
|
||||
div.promoted-attribute-cell.promoted-attribute-label-boolean > div:first-of-type {
|
||||
order: -1;
|
||||
margin-right: 1.5em;
|
||||
}
|
||||
|
||||
@@ -1678,3 +1679,41 @@ div.find-replace-widget div.find-widget-found-wrapper > span {
|
||||
background: transparent;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
/** Canvas **/
|
||||
|
||||
.excalidraw {
|
||||
--border-radius-lg: 6px;
|
||||
}
|
||||
|
||||
.excalidraw .Island {
|
||||
backdrop-filter: var(--dropdown-backdrop-filter);
|
||||
}
|
||||
|
||||
.excalidraw .Island.App-toolbar {
|
||||
--island-bg-color: var(--floating-button-background-color);
|
||||
--shadow-island: 1px 1px 1px var(--floating-button-shadow-color);
|
||||
}
|
||||
|
||||
.excalidraw .dropdown-menu {
|
||||
border: unset !important;
|
||||
box-shadow: unset !important;
|
||||
background-color: transparent !important;
|
||||
--island-bg-color: var(--menu-background-color);
|
||||
--shadow-island: 0px 10px 20px rgba(0, 0, 0, var(--dropdown-shadow-opacity));
|
||||
--default-border-color: var(--bs-dropdown-divider-bg);
|
||||
--button-hover-bg: var(--hover-item-background-color);
|
||||
}
|
||||
|
||||
.excalidraw .dropdown-menu .dropdown-menu-container {
|
||||
border-radius: var(--dropdown-border-radius);
|
||||
}
|
||||
|
||||
.excalidraw .dropdown-menu .dropdown-menu-container > div:not([class]):not(:last-child) {
|
||||
margin-left: calc(var(--padding) * var(--space-factor) * -1) !important;
|
||||
margin-right: calc(var(--padding) * var(--space-factor) * -1) !important;
|
||||
}
|
||||
|
||||
.excalidraw .dropdown-menu:before {
|
||||
content: unset !important;
|
||||
}
|
||||
185
apps/client/src/translations/ca/translation.json
Normal file
185
apps/client/src/translations/ca/translation.json
Normal file
@@ -0,0 +1,185 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "Sobre Trilium Notes",
|
||||
"homepage": "Pàgina principal:"
|
||||
},
|
||||
"add_link": {
|
||||
"note": "Nota"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"prefix": "Prefix: ",
|
||||
"save": "Desa"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"labels": "Etiquetes",
|
||||
"relations": "Relacions",
|
||||
"notes": "Notes",
|
||||
"other": "Altres"
|
||||
},
|
||||
"confirm": {
|
||||
"confirmation": "Confirmació",
|
||||
"cancel": "Cancel·la",
|
||||
"ok": "OK"
|
||||
},
|
||||
"delete_notes": {
|
||||
"close": "Tanca",
|
||||
"cancel": "Cancel·la",
|
||||
"ok": "OK"
|
||||
},
|
||||
"export": {
|
||||
"close": "Tanca",
|
||||
"export": "Exporta"
|
||||
},
|
||||
"help": {
|
||||
"troubleshooting": "Solució de problemes",
|
||||
"other": "Altres"
|
||||
},
|
||||
"import": {
|
||||
"options": "Opcions",
|
||||
"import": "Importa"
|
||||
},
|
||||
"include_note": {
|
||||
"label_note": "Nota"
|
||||
},
|
||||
"info": {
|
||||
"closeButton": "Tanca",
|
||||
"okButton": "OK"
|
||||
},
|
||||
"note_type_chooser": {
|
||||
"templates": "Plantilles:"
|
||||
},
|
||||
"prompt": {
|
||||
"title": "Sol·licitud",
|
||||
"defaultTitle": "Sol·licitud"
|
||||
},
|
||||
"protected_session_password": {
|
||||
"close_label": "Tanca"
|
||||
},
|
||||
"recent_changes": {
|
||||
"undelete_link": "recuperar"
|
||||
},
|
||||
"revisions": {
|
||||
"restore_button": "Restaura",
|
||||
"delete_button": "Suprimeix",
|
||||
"download_button": "Descarrega",
|
||||
"mime": "MIME: ",
|
||||
"preview": "Vista prèvia:"
|
||||
},
|
||||
"sort_child_notes": {
|
||||
"title": "títol",
|
||||
"ascending": "ascendent",
|
||||
"descending": "descendent",
|
||||
"folders": "Carpetes"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"options": "Opcions",
|
||||
"upload": "Puja"
|
||||
},
|
||||
"attribute_detail": {
|
||||
"name": "Nom",
|
||||
"value": "Valor",
|
||||
"promoted": "Destacat",
|
||||
"promoted_alias": "Àlies",
|
||||
"multiplicity": "Multiplicitat",
|
||||
"label_type": "Tipus",
|
||||
"text": "Text",
|
||||
"number": "Número",
|
||||
"boolean": "Booleà",
|
||||
"date": "Data",
|
||||
"time": "Hora",
|
||||
"url": "URL",
|
||||
"precision": "Precisió",
|
||||
"digits": "dígits",
|
||||
"inheritable": "Heretable",
|
||||
"delete": "Suprimeix",
|
||||
"color_type": "Color"
|
||||
},
|
||||
"rename_label": {
|
||||
"to": "Per"
|
||||
},
|
||||
"move_note": {
|
||||
"to": "a"
|
||||
},
|
||||
"add_relation": {
|
||||
"to": "a"
|
||||
},
|
||||
"rename_relation": {
|
||||
"to": "Per"
|
||||
},
|
||||
"update_relation_target": {
|
||||
"to": "a"
|
||||
},
|
||||
"attachments_actions": {
|
||||
"download": "Descarrega"
|
||||
},
|
||||
"calendar": {
|
||||
"mon": "Dl",
|
||||
"tue": "Dt",
|
||||
"wed": "dc",
|
||||
"thu": "Dj",
|
||||
"fri": "Dv",
|
||||
"sat": "Ds",
|
||||
"sun": "Dg",
|
||||
"january": "Gener",
|
||||
"febuary": "Febrer",
|
||||
"march": "Març",
|
||||
"april": "Abril",
|
||||
"may": "Maig",
|
||||
"june": "Juny",
|
||||
"july": "Juliol",
|
||||
"august": "Agost",
|
||||
"september": "Setembre",
|
||||
"october": "Octubre",
|
||||
"november": "Novembre",
|
||||
"december": "Desembre"
|
||||
},
|
||||
"global_menu": {
|
||||
"menu": "Menú",
|
||||
"options": "Opcions",
|
||||
"zoom": "Zoom",
|
||||
"advanced": "Avançat",
|
||||
"logout": "Tanca la sessió"
|
||||
},
|
||||
"zpetne_odkazy": {
|
||||
"relation": "relació"
|
||||
},
|
||||
"note_icon": {
|
||||
"category": "Categoria:",
|
||||
"search": "Cerca:"
|
||||
},
|
||||
"basic_properties": {
|
||||
"editable": "Editable",
|
||||
"language": "Llengua"
|
||||
},
|
||||
"book_properties": {
|
||||
"grid": "Graella",
|
||||
"list": "Llista",
|
||||
"collapse": "Replega",
|
||||
"expand": "Desplega",
|
||||
"calendar": "Calendari",
|
||||
"table": "Taula",
|
||||
"board": "Tauler"
|
||||
},
|
||||
"edited_notes": {
|
||||
"deleted": "(suprimit)"
|
||||
},
|
||||
"file_properties": {
|
||||
"download": "Descarrega",
|
||||
"open": "Obre",
|
||||
"title": "Fitxer"
|
||||
},
|
||||
"image_properties": {
|
||||
"download": "Descarrega",
|
||||
"open": "Obre",
|
||||
"title": "Imatge"
|
||||
},
|
||||
"note_info_widget": {
|
||||
"created": "Creat",
|
||||
"modified": "Modificat",
|
||||
"type": "Tipus",
|
||||
"calculate": "calcula"
|
||||
},
|
||||
"note_paths": {
|
||||
"archived": "Arxivat"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "关于 Trilium Notes",
|
||||
"close": "关闭",
|
||||
"homepage": "项目主页:",
|
||||
"app_version": "应用版本:",
|
||||
"db_version": "数据库版本:",
|
||||
@@ -28,25 +27,22 @@
|
||||
"add_link": {
|
||||
"add_link": "添加链接",
|
||||
"help_on_links": "链接帮助",
|
||||
"close": "关闭",
|
||||
"note": "笔记",
|
||||
"search_note": "按名称搜索笔记",
|
||||
"link_title_mirrors": "链接标题跟随笔记标题变化",
|
||||
"link_title_arbitrary": "链接标题可随意修改",
|
||||
"link_title": "链接标题",
|
||||
"button_add_link": "添加链接 <kbd>回车</kbd>"
|
||||
"button_add_link": "添加链接"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"edit_branch_prefix": "编辑分支前缀",
|
||||
"help_on_tree_prefix": "有关树前缀的帮助",
|
||||
"close": "关闭",
|
||||
"prefix": "前缀:",
|
||||
"prefix": "前缀: ",
|
||||
"save": "保存",
|
||||
"branch_prefix_saved": "分支前缀已保存。"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "批量操作",
|
||||
"close": "关闭",
|
||||
"affected_notes": "受影响的笔记",
|
||||
"include_descendants": "包括所选笔记的子笔记",
|
||||
"available_actions": "可用操作",
|
||||
@@ -61,23 +57,21 @@
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "克隆笔记到...",
|
||||
"close": "关闭",
|
||||
"help_on_links": "链接帮助",
|
||||
"notes_to_clone": "要克隆的笔记",
|
||||
"target_parent_note": "目标父笔记",
|
||||
"search_for_note_by_its_name": "按名称搜索笔记",
|
||||
"cloned_note_prefix_title": "克隆的笔记将在笔记树中显示给定的前缀",
|
||||
"prefix_optional": "前缀(可选)",
|
||||
"clone_to_selected_note": "克隆到选定的笔记 <kbd>回车</kbd>",
|
||||
"clone_to_selected_note": "克隆到选定的笔记",
|
||||
"no_path_to_clone_to": "没有克隆路径。",
|
||||
"note_cloned": "笔记 \"{{clonedTitle}}\" 已克隆到 \"{{targetTitle}}\""
|
||||
},
|
||||
"confirm": {
|
||||
"confirmation": "确认",
|
||||
"close": "关闭",
|
||||
"cancel": "取消",
|
||||
"ok": "确定",
|
||||
"are_you_sure_remove_note": "确定要从关系图中移除笔记 \"{{title}}\" ?",
|
||||
"are_you_sure_remove_note": "确定要从关系图中移除笔记 \"{{title}}\" ? ",
|
||||
"if_you_dont_check": "如果不选中此项,笔记将仅从关系图中移除。",
|
||||
"also_delete_note": "同时删除笔记"
|
||||
},
|
||||
@@ -87,9 +81,9 @@
|
||||
"delete_all_clones_description": "同时删除所有克隆(可以在最近修改中撤消)",
|
||||
"erase_notes_description": "通常(软)删除仅标记笔记为已删除,可以在一段时间内通过最近修改对话框撤消。选中此选项将立即擦除笔记,不可撤销。",
|
||||
"erase_notes_warning": "永久擦除笔记(无法撤销),包括所有克隆。这将强制应用程序重载。",
|
||||
"notes_to_be_deleted": "将删除以下笔记 ({{- noteCount}})",
|
||||
"notes_to_be_deleted": "将删除以下笔记 ({{notesCount}})",
|
||||
"no_note_to_delete": "没有笔记将被删除(仅克隆)。",
|
||||
"broken_relations_to_be_deleted": "将删除以下关系并断开连接 ({{- relationCount}})",
|
||||
"broken_relations_to_be_deleted": "将删除以下关系并断开连接 ({{ relationCount}})",
|
||||
"cancel": "取消",
|
||||
"ok": "确定",
|
||||
"deleted_relation_text": "笔记 {{- note}} (将被删除的笔记) 被以下关系 {{- relation}} 引用, 来自 {{- source}}。"
|
||||
@@ -113,20 +107,17 @@
|
||||
"format_pdf": "PDF - 用于打印或共享目的。"
|
||||
},
|
||||
"help": {
|
||||
"fullDocumentation": "帮助(完整<a class=\"external\" href=\"https://triliumnext.github.io/Docs/\">在线文档</a>)",
|
||||
"close": "关闭",
|
||||
"noteNavigation": "笔记导航",
|
||||
"goUpDown": "<kbd>UP</kbd>, <kbd>DOWN</kbd> - 在笔记列表中向上/向下移动",
|
||||
"collapseExpand": "<kbd>LEFT</kbd>, <kbd>RIGHT</kbd> - 折叠/展开节点",
|
||||
"goUpDown": "在笔记列表中向上/向下移动",
|
||||
"collapseExpand": "折叠/展开节点",
|
||||
"notSet": "未设置",
|
||||
"goBackForwards": "在历史记录中前后移动",
|
||||
"showJumpToNoteDialog": "显示<a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"跳转到\" 对话框</a>",
|
||||
"scrollToActiveNote": "滚动到活跃笔记",
|
||||
"jumpToParentNote": "<kbd>Backspace</kbd> - 跳转到父笔记",
|
||||
"jumpToParentNote": "跳转到父笔记",
|
||||
"collapseWholeTree": "折叠整个笔记树",
|
||||
"collapseSubTree": "折叠子树",
|
||||
"tabShortcuts": "标签页快捷键",
|
||||
"newTabNoteLink": "<kbd>CTRL+click</kbd> - 在笔记链接上使用CTRL+点击(或中键点击)在新标签页中打开笔记",
|
||||
"onlyInDesktop": "仅在桌面版(电子构建)中",
|
||||
"openEmptyTab": "打开空白标签页",
|
||||
"closeActiveTab": "关闭活跃标签页",
|
||||
@@ -141,14 +132,14 @@
|
||||
"moveNoteUpHierarchy": "在层级结构中向上移动笔记",
|
||||
"multiSelectNote": "多选上/下笔记",
|
||||
"selectAllNotes": "选择当前级别的所有笔记",
|
||||
"selectNote": "<kbd>Shift+click</kbd> - 选择笔记",
|
||||
"selectNote": "选择笔记",
|
||||
"copyNotes": "将活跃笔记(或当前选择)复制到剪贴板(用于<a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/cloning-notes.html#cloning-notes\">克隆</a>)",
|
||||
"cutNotes": "将当前笔记(或当前选择)剪切到剪贴板(用于移动笔记)",
|
||||
"pasteNotes": "将笔记粘贴为活跃笔记的子笔记(根据是复制还是剪切到剪贴板来决定是移动还是克隆)",
|
||||
"deleteNotes": "删除笔记/子树",
|
||||
"editingNotes": "编辑笔记",
|
||||
"editNoteTitle": "在树形笔记树中,焦点会从笔记树切换到笔记标题。按下 Enter 键会将焦点从笔记标题切换到文本编辑器。按下 <kbd>Ctrl+.</kbd> 会将焦点从编辑器切换回笔记树。",
|
||||
"createEditLink": "<kbd>Ctrl+K</kbd> - 创建/编辑外部链接",
|
||||
"createEditLink": "创建/编辑外部链接",
|
||||
"createInternalLink": "创建内部链接",
|
||||
"followLink": "跟随光标下的链接",
|
||||
"insertDateTime": "在插入点插入当前日期和时间",
|
||||
@@ -164,11 +155,13 @@
|
||||
"showSQLConsole": "显示 SQL 控制台",
|
||||
"other": "其他",
|
||||
"quickSearch": "定位到快速搜索框",
|
||||
"inPageSearch": "页面内搜索"
|
||||
"inPageSearch": "页面内搜索",
|
||||
"newTabWithActivationNoteLink": "在新标签页打开笔记链接并激活该标签页",
|
||||
"title": "资料表",
|
||||
"newTabNoteLink": "在新标签页开启链接"
|
||||
},
|
||||
"import": {
|
||||
"importIntoNote": "导入到笔记",
|
||||
"close": "关闭",
|
||||
"chooseImportFile": "选择导入文件",
|
||||
"importDescription": "所选文件的内容将作为子笔记导入到",
|
||||
"options": "选项",
|
||||
@@ -195,14 +188,13 @@
|
||||
},
|
||||
"include_note": {
|
||||
"dialog_title": "包含笔记",
|
||||
"close": "关闭",
|
||||
"label_note": "笔记",
|
||||
"placeholder_search": "按名称搜索笔记",
|
||||
"box_size_prompt": "包含笔记的框大小:",
|
||||
"box_size_small": "小型 (显示大约10行)",
|
||||
"box_size_medium": "中型 (显示大约30行)",
|
||||
"box_size_full": "完整显示(完整文本框)",
|
||||
"button_include": "包含笔记 <kbd>回车</kbd>"
|
||||
"button_include": "包含笔记"
|
||||
},
|
||||
"info": {
|
||||
"modalTitle": "信息消息",
|
||||
@@ -210,43 +202,41 @@
|
||||
"okButton": "确定"
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_placeholder": "按笔记名称搜索",
|
||||
"close": "关闭",
|
||||
"search_button": "全文搜索 <kbd>Ctrl+回车</kbd>"
|
||||
"search_button": "全文搜索",
|
||||
"search_placeholder": "按名称或类型搜索笔记 > 查看命令..."
|
||||
},
|
||||
"markdown_import": {
|
||||
"dialog_title": "Markdown 导入",
|
||||
"close": "关闭",
|
||||
"modal_body_text": "由于浏览器沙箱的限制,无法直接从 JavaScript 读取剪贴板内容。请将要导入的 Markdown 文本粘贴到下面的文本框中,然后点击导入按钮",
|
||||
"import_button": "导入 Ctrl+回车",
|
||||
"import_button": "导入",
|
||||
"import_success": "Markdown 内容已成功导入文档。"
|
||||
},
|
||||
"move_to": {
|
||||
"dialog_title": "移动笔记到...",
|
||||
"close": "关闭",
|
||||
"notes_to_move": "需要移动的笔记",
|
||||
"target_parent_note": "目标父笔记",
|
||||
"search_placeholder": "通过名称搜索笔记",
|
||||
"move_button": "移动到选定的笔记 <kbd>回车</kbd>",
|
||||
"move_button": "移动到选定的笔记",
|
||||
"error_no_path": "没有可以移动到的路径。",
|
||||
"move_success_message": "所选笔记已移动到"
|
||||
"move_success_message": "所选笔记已移动到 "
|
||||
},
|
||||
"note_type_chooser": {
|
||||
"modal_title": "选择笔记类型",
|
||||
"close": "关闭",
|
||||
"modal_body": "选择新笔记的类型或模板:",
|
||||
"templates": "模板:"
|
||||
"templates": "模板",
|
||||
"change_path_prompt": "更改创建新笔记的位置:",
|
||||
"search_placeholder": "按名称搜索路径(默认为空)",
|
||||
"builtin_templates": "内置模板"
|
||||
},
|
||||
"password_not_set": {
|
||||
"title": "密码未设置",
|
||||
"close": "关闭",
|
||||
"body1": "受保护的笔记使用用户密码加密,但密码尚未设置。",
|
||||
"body2": "点击<a class=\"open-password-options-button\" href=\"javascript:\">这里</a>打开选项对话框并设置您的密码。"
|
||||
"body2": "若要保护笔记,请按一下下方按钮开启「选项」对话框并设置密码。",
|
||||
"go_to_password_options": "移动至密码选项"
|
||||
},
|
||||
"prompt": {
|
||||
"title": "提示",
|
||||
"close": "关闭",
|
||||
"ok": "确定 <kbd>回车</kbd>",
|
||||
"ok": "确定",
|
||||
"defaultTitle": "提示"
|
||||
},
|
||||
"protected_session_password": {
|
||||
@@ -254,12 +244,11 @@
|
||||
"help_title": "关于保护笔记的帮助",
|
||||
"close_label": "关闭",
|
||||
"form_label": "输入密码进入保护会话以继续:",
|
||||
"start_button": "开始保护会话 <kbd>回车</kbd>"
|
||||
"start_button": "开始保护会话"
|
||||
},
|
||||
"recent_changes": {
|
||||
"title": "最近修改",
|
||||
"erase_notes_button": "立即清理已删除的笔记",
|
||||
"close": "关闭",
|
||||
"deleted_notes_message": "已删除的笔记已清理。",
|
||||
"no_changes_message": "暂无修改...",
|
||||
"undelete_link": "恢复删除",
|
||||
@@ -270,7 +259,6 @@
|
||||
"delete_all_revisions": "删除此笔记的所有修订版本",
|
||||
"delete_all_button": "删除所有修订版本",
|
||||
"help_title": "关于笔记修订版本的帮助",
|
||||
"close": "关闭",
|
||||
"revision_last_edited": "此修订版本上次编辑于 {{date}}",
|
||||
"confirm_delete_all": "您是否要删除此笔记的所有修订版本?",
|
||||
"no_revisions": "此笔记暂无修订版本...",
|
||||
@@ -285,14 +273,13 @@
|
||||
"maximum_revisions": "当前笔记的最大历史数量: {{number}}。",
|
||||
"settings": "笔记修订设置",
|
||||
"download_button": "下载",
|
||||
"mime": "MIME 类型:",
|
||||
"mime": "MIME 类型: ",
|
||||
"file_size": "文件大小:",
|
||||
"preview": "预览:",
|
||||
"preview_not_available": "无法预览此类型的笔记。"
|
||||
},
|
||||
"sort_child_notes": {
|
||||
"sort_children_by": "按...排序子笔记",
|
||||
"close": "关闭",
|
||||
"sorting_criteria": "排序条件",
|
||||
"title": "标题",
|
||||
"date_created": "创建日期",
|
||||
@@ -306,13 +293,12 @@
|
||||
"sort_with_respect_to_different_character_sorting": "根据不同语言或地区的字符排序和排序规则排序。",
|
||||
"natural_sort_language": "自然排序语言",
|
||||
"the_language_code_for_natural_sort": "自然排序的语言代码,例如中文的 \"zh-CN\"。",
|
||||
"sort": "排序 <kbd>Enter</kbd>"
|
||||
"sort": "排序"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "上传附件到笔记",
|
||||
"close": "关闭",
|
||||
"choose_files": "选择文件",
|
||||
"files_will_be_uploaded": "文件将作为附件上传到",
|
||||
"files_will_be_uploaded": "文件将作为附件上传到 {{noteTitle}}",
|
||||
"options": "选项",
|
||||
"shrink_images": "缩小图片",
|
||||
"upload": "上传",
|
||||
@@ -427,7 +413,7 @@
|
||||
"run_on_branch_change": "在分支更新时执行。",
|
||||
"run_on_branch_deletion": "在删除分支时执行。分支是父笔记和子笔记之间的链接,例如在移动笔记时删除(删除旧的分支/链接)。",
|
||||
"run_on_attribute_creation": "在为定义此关系的笔记创建新属性时执行",
|
||||
"run_on_attribute_change": "当修改定义此关系的笔记的属性时执行。删除属性时也会触发此操作。",
|
||||
"run_on_attribute_change": " 当修改定义此关系的笔记的属性时执行。删除属性时也会触发此操作。",
|
||||
"relation_template": "即使没有父子关系,笔记的属性也将继承。如果空,则笔记的内容和子树将添加到实例笔记中。有关详细信息,请参见文档。",
|
||||
"inherit": "即使没有父子关系,笔记的属性也将继承。有关类似概念的模板关系,请参见模板关系。请参阅文档中的属性继承。",
|
||||
"render_note": "“渲染 HTML 笔记”类型的笔记将使用代码笔记(HTML 或脚本)进行呈现,因此需要指定要渲染的笔记",
|
||||
@@ -438,14 +424,15 @@
|
||||
"share_favicon": "在分享页面中设置的 favicon 笔记。一般需要将它设置为分享和可继承。Favicon 笔记也必须位于分享子树中。可以考虑一并使用 'share_hidden_from_tree'。",
|
||||
"is_owned_by_note": "由此笔记所有",
|
||||
"other_notes_with_name": "其它含有 {{attributeType}} 名为 \"{{attributeName}}\" 的的笔记",
|
||||
"and_more": "... 以及另外 {{count}} 个",
|
||||
"and_more": "... 以及另外 {{count}} 个。",
|
||||
"print_landscape": "导出为 PDF 时,将页面方向更改为横向而不是纵向。",
|
||||
"print_page_size": "导出为 PDF 时,更改页面大小。支持的值:<code>A0</code>、<code>A1</code>、<code>A2</code>、<code>A3</code>、<code>A4</code>、<code>A5</code>、<code>A6</code>、<code>Legal</code>、<code>Letter</code>、<code>Tabloid</code>、<code>Ledger</code>。"
|
||||
"print_page_size": "导出为 PDF 时,更改页面大小。支持的值:<code>A0</code>、<code>A1</code>、<code>A2</code>、<code>A3</code>、<code>A4</code>、<code>A5</code>、<code>A6</code>、<code>Legal</code>、<code>Letter</code>、<code>Tabloid</code>、<code>Ledger</code>。",
|
||||
"color_type": "颜色"
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "要添加标签,只需输入例如 <code>#rock</code> 或者如果您还想添加值,则例如 <code>#year = 2020</code>",
|
||||
"help_text_body2": "对于关系,请输入 <code>~author = @</code>,这将显示一个自动完成列表,您可以查找所需的笔记。",
|
||||
"help_text_body3": "您也可以使用右侧的 <code>+</code> 按钮添加标签和关系。</p>",
|
||||
"help_text_body3": "您也可以使用右侧的 <code>+</code> 按钮添加标签和关系。",
|
||||
"save_attributes": "保存属性 <enter>",
|
||||
"add_a_new_attribute": "添加新属性",
|
||||
"add_new_label": "添加新标签 <kbd data-command=\"addNewLabel\"></kbd>",
|
||||
@@ -744,7 +731,8 @@
|
||||
"basic_properties": {
|
||||
"note_type": "笔记类型",
|
||||
"editable": "可编辑",
|
||||
"basic_properties": "基本属性"
|
||||
"basic_properties": "基本属性",
|
||||
"language": "语言"
|
||||
},
|
||||
"book_properties": {
|
||||
"view_type": "视图类型",
|
||||
@@ -754,9 +742,12 @@
|
||||
"expand_all_children": "展开所有子项",
|
||||
"collapse": "折叠",
|
||||
"expand": "展开",
|
||||
"book_properties": "书籍属性",
|
||||
"invalid_view_type": "无效的查看类型 '{{type}}'",
|
||||
"calendar": "日历"
|
||||
"calendar": "日历",
|
||||
"book_properties": "集合属性",
|
||||
"table": "表格",
|
||||
"geo-map": "地理地图",
|
||||
"board": "看板"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "今天还没有编辑过的笔记...",
|
||||
@@ -833,7 +824,8 @@
|
||||
"unknown_label_type": "未知的标签类型 '{{type}}'",
|
||||
"unknown_attribute_type": "未知的属性类型 '{{type}}'",
|
||||
"add_new_attribute": "添加新属性",
|
||||
"remove_this_attribute": "移除此属性"
|
||||
"remove_this_attribute": "移除此属性",
|
||||
"remove_color": "移除此颜色标签"
|
||||
},
|
||||
"script_executor": {
|
||||
"query": "查询",
|
||||
@@ -944,19 +936,19 @@
|
||||
},
|
||||
"attachment_detail": {
|
||||
"open_help_page": "打开附件帮助页面",
|
||||
"owning_note": "所属笔记:",
|
||||
"you_can_also_open": ",您还可以打开",
|
||||
"owning_note": "所属笔记: ",
|
||||
"you_can_also_open": ",您还可以打开 ",
|
||||
"list_of_all_attachments": "所有附件列表",
|
||||
"attachment_deleted": "该附件已被删除。"
|
||||
},
|
||||
"attachment_list": {
|
||||
"open_help_page": "打开附件帮助页面",
|
||||
"owning_note": "所属笔记:",
|
||||
"owning_note": "所属笔记: ",
|
||||
"upload_attachments": "上传附件",
|
||||
"no_attachments": "此笔记没有附件。"
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "此类型为书籍的笔记没有任何子笔记,因此没有内容显示。请参阅 <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> 了解详情"
|
||||
"no_children_help": "此类型为书籍的笔记没有任何子笔记,因此没有内容显示。请参阅 <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> 了解详情。"
|
||||
},
|
||||
"editable_code": {
|
||||
"placeholder": "在这里输入您的代码笔记内容..."
|
||||
@@ -975,7 +967,7 @@
|
||||
},
|
||||
"protected_session": {
|
||||
"enter_password_instruction": "显示受保护的笔记需要输入您的密码:",
|
||||
"start_session_button": "开始受保护的会话",
|
||||
"start_session_button": "开始受保护的会话 <kbd>Enter</kbd>",
|
||||
"started": "受保护的会话已启动。",
|
||||
"wrong_password": "密码错误。",
|
||||
"protecting-finished-successfully": "保护操作已成功完成。",
|
||||
@@ -1036,7 +1028,7 @@
|
||||
"error_creating_anonymized_database": "无法创建匿名化数据库,请检查后端日志以获取详细信息",
|
||||
"successfully_created_fully_anonymized_database": "成功创建完全匿名化的数据库,路径为 {{anonymizedFilePath}}",
|
||||
"successfully_created_lightly_anonymized_database": "成功创建轻度匿名化的数据库,路径为 {{anonymizedFilePath}}",
|
||||
"no_anonymized_database_yet": "尚无匿名化数据库"
|
||||
"no_anonymized_database_yet": "尚无匿名化数据库。"
|
||||
},
|
||||
"database_integrity_check": {
|
||||
"title": "数据库完整性检查",
|
||||
@@ -1092,7 +1084,8 @@
|
||||
"max_width_label": "内容最大宽度(像素)",
|
||||
"apply_changes_description": "要应用内容宽度更改,请点击",
|
||||
"reload_button": "重载前端",
|
||||
"reload_description": "来自外观选项的更改"
|
||||
"reload_description": "来自外观选项的更改",
|
||||
"max_width_unit": "像素"
|
||||
},
|
||||
"native_title_bar": {
|
||||
"title": "原生标题栏(需要重新启动应用)",
|
||||
@@ -1108,17 +1101,17 @@
|
||||
"title": "主题",
|
||||
"theme_label": "主题",
|
||||
"override_theme_fonts_label": "覆盖主题字体",
|
||||
"auto_theme": "自动",
|
||||
"light_theme": "浅色",
|
||||
"dark_theme": "深色",
|
||||
"triliumnext": "TriliumNext Beta(跟随系统颜色方案)",
|
||||
"triliumnext-light": "TriliumNext Beta(浅色)",
|
||||
"triliumnext-dark": "TriliumNext Beta(深色)",
|
||||
"triliumnext": "Trilium(跟随系统颜色方案)",
|
||||
"triliumnext-light": "Trilium(浅色)",
|
||||
"triliumnext-dark": "Trilium(深色)",
|
||||
"layout": "布局",
|
||||
"layout-vertical-title": "垂直",
|
||||
"layout-horizontal-title": "水平",
|
||||
"layout-vertical-description": "启动栏位于左侧(默认)",
|
||||
"layout-horizontal-description": "启动栏位于标签页栏下方,标签页栏现在是全宽的。"
|
||||
"layout-horizontal-description": "启动栏位于标签页栏下方,标签页栏现在是全宽的。",
|
||||
"auto_theme": "传统(跟随系统配色方案)",
|
||||
"light_theme": "传统(浅色)",
|
||||
"dark_theme": "传统(深色)"
|
||||
},
|
||||
"zoom_factor": {
|
||||
"title": "缩放系数(仅桌面客户端有效)",
|
||||
@@ -1127,7 +1120,8 @@
|
||||
"code_auto_read_only_size": {
|
||||
"title": "自动只读大小",
|
||||
"description": "自动只读大小是指笔记超过设置的大小后自动设置为只读模式(为性能考虑)。",
|
||||
"label": "自动只读大小(代码笔记)"
|
||||
"label": "自动只读大小(代码笔记)",
|
||||
"unit": "字符"
|
||||
},
|
||||
"code_mime_types": {
|
||||
"title": "下拉菜单可用的MIME文件类型"
|
||||
@@ -1146,7 +1140,8 @@
|
||||
"download_images_description": "粘贴的 HTML 可能包含在线图片的引用,Trilium 会找到这些引用并下载图片,以便它们可以离线使用。",
|
||||
"enable_image_compression": "启用图片压缩",
|
||||
"max_image_dimensions": "图片的最大宽度/高度(超过此限制的图像将会被缩放)。",
|
||||
"jpeg_quality_description": "JPEG 质量(10 - 最差质量,100 最佳质量,建议为 50 - 85)"
|
||||
"jpeg_quality_description": "JPEG 质量(10 - 最差质量,100 最佳质量,建议为 50 - 85)",
|
||||
"max_image_dimensions_unit": "像素"
|
||||
},
|
||||
"attachment_erasure_timeout": {
|
||||
"attachment_erasure_timeout": "附件清理超时",
|
||||
@@ -1170,7 +1165,7 @@
|
||||
},
|
||||
"revisions_snapshot_interval": {
|
||||
"note_revisions_snapshot_interval_title": "笔记修订快照间隔",
|
||||
"note_revisions_snapshot_description": "笔记修订快照间隔是创建新笔记修订的时间。有关更多信息,请参见 <a href=\"https://triliumnext.github.io/Docs/Wiki/note-revisions.html\" class=\"external\">wiki</a>。",
|
||||
"note_revisions_snapshot_description": "笔记修订快照间隔是创建新笔记修订的时间。有关更多信息,请参见 <doc>wiki</doc>。",
|
||||
"snapshot_time_interval_label": "笔记修订快照时间间隔:"
|
||||
},
|
||||
"revisions_snapshot_limit": {
|
||||
@@ -1178,7 +1173,8 @@
|
||||
"note_revisions_snapshot_limit_description": "笔记修订快照数限制指的是每个笔记可以保存的最大历史记录数量。其中 -1 表示没有限制,0 表示删除所有历史记录。您可以通过 #versioningLimit 标签设置单个笔记的最大修订记录数量。",
|
||||
"snapshot_number_limit_label": "笔记修订快照数量限制:",
|
||||
"erase_excess_revision_snapshots": "立即删除多余的修订快照",
|
||||
"erase_excess_revision_snapshots_prompt": "多余的修订快照已被删除。"
|
||||
"erase_excess_revision_snapshots_prompt": "多余的修订快照已被删除。",
|
||||
"snapshot_number_limit_unit": "快照"
|
||||
},
|
||||
"search_engine": {
|
||||
"title": "搜索引擎",
|
||||
@@ -1220,12 +1216,14 @@
|
||||
"title": "目录",
|
||||
"description": "当笔记中有超过一定数量的标题时,显示目录。您可以自定义此数量:",
|
||||
"disable_info": "您可以设置一个非常大的数来禁用目录。",
|
||||
"shortcut_info": "您可以在 “选项” -> “快捷键” 中配置一个键盘快捷键,以便快速切换右侧面板(包括目录)(名称为 'toggleRightPane')。"
|
||||
"shortcut_info": "您可以在 “选项” -> “快捷键” 中配置一个键盘快捷键,以便快速切换右侧面板(包括目录)(名称为 'toggleRightPane')。",
|
||||
"unit": "标题"
|
||||
},
|
||||
"text_auto_read_only_size": {
|
||||
"title": "自动只读大小",
|
||||
"description": "自动只读笔记大小是超过该大小后,笔记将以只读模式显示(出于性能考虑)。",
|
||||
"label": "自动只读大小(文本笔记)"
|
||||
"label": "自动只读大小(文本笔记)",
|
||||
"unit": "字符"
|
||||
},
|
||||
"i18n": {
|
||||
"title": "本地化",
|
||||
@@ -1335,9 +1333,9 @@
|
||||
"oauth_title": "OAuth/OpenID 认证",
|
||||
"oauth_description": "OpenID 是一种标准化方式,允许您使用其他服务(如 Google)的账号登录网站来验证您的身份。默认的身份提供者是 Google,但您可以更改为任何其他 OpenID 提供者。点击<a href=\"#root/_hidden/_help/_help_Otzi9La2YAUX/_help_WOcw2SLH6tbX/_help_7DAiwaf8Z7Rz\">这里</a>了解更多信息。请参阅这些 <a href=\"https://developers.google.com/identity/openid-connect/openid-connect\">指南</a> 通过 Google 设置 OpenID 服务。",
|
||||
"oauth_description_warning": "要启用 OAuth/OpenID,您需要设置 config.ini 文件中的 OAuth/OpenID 基础 URL、客户端 ID 和客户端密钥,并重新启动应用程序。如果要从环境变量设置,请设置 TRILIUM_OAUTH_BASE_URL、TRILIUM_OAUTH_CLIENT_ID 和 TRILIUM_OAUTH_CLIENT_SECRET 环境变量。",
|
||||
"oauth_missing_vars": "缺少以下设置项: {{missingVars}}",
|
||||
"oauth_user_account": "用户账号:",
|
||||
"oauth_user_email": "用户邮箱:",
|
||||
"oauth_missing_vars": "缺少以下设置项:{{variables}}",
|
||||
"oauth_user_account": "用户账号: ",
|
||||
"oauth_user_email": "用户邮箱: ",
|
||||
"oauth_user_not_logged_in": "未登录!"
|
||||
},
|
||||
"shortcuts": {
|
||||
@@ -1359,7 +1357,7 @@
|
||||
"enable": "启用拼写检查",
|
||||
"language_code_label": "语言代码",
|
||||
"language_code_placeholder": "例如 \"en-US\", \"de-AT\"",
|
||||
"multiple_languages_info": "多种语言可以用逗号分隔,例如 \"en-US, de-DE, cs\"。",
|
||||
"multiple_languages_info": "多种语言可以用逗号分隔,例如 \"en-US, de-DE, cs\"。 ",
|
||||
"available_language_codes_label": "可用的语言代码:",
|
||||
"restart-required": "拼写检查选项的更改将在应用重启后生效。"
|
||||
},
|
||||
@@ -1376,7 +1374,8 @@
|
||||
"test_title": "同步测试",
|
||||
"test_description": "测试和同步服务器之间的连接。如果同步服务器没有初始化,会将本地文档同步到同步服务器上。",
|
||||
"test_button": "测试同步",
|
||||
"handshake_failed": "同步服务器握手失败,错误:{{message}}"
|
||||
"handshake_failed": "同步服务器握手失败,错误:{{message}}",
|
||||
"timeout_unit": "毫秒"
|
||||
},
|
||||
"api_log": {
|
||||
"close": "关闭"
|
||||
@@ -1431,12 +1430,13 @@
|
||||
"move-to": "移动到...",
|
||||
"paste-into": "粘贴到里面",
|
||||
"paste-after": "粘贴到后面",
|
||||
"duplicate-subtree": "复制子树",
|
||||
"export": "导出",
|
||||
"import-into-note": "导入到笔记",
|
||||
"apply-bulk-actions": "应用批量操作",
|
||||
"converted-to-attachments": "{{count}} 个笔记已被转换为附件。",
|
||||
"convert-to-attachment-confirm": "确定要将选中的笔记转换为其父笔记的附件吗?"
|
||||
"convert-to-attachment-confirm": "确定要将选中的笔记转换为其父笔记的附件吗?",
|
||||
"duplicate": "复制",
|
||||
"open-in-popup": "快速编辑"
|
||||
},
|
||||
"shared_info": {
|
||||
"shared_publicly": "此笔记已公开分享于",
|
||||
@@ -1450,7 +1450,6 @@
|
||||
"relation-map": "关系图",
|
||||
"note-map": "笔记地图",
|
||||
"render-note": "渲染笔记",
|
||||
"book": "书",
|
||||
"mermaid-diagram": "Mermaid 图",
|
||||
"canvas": "画布",
|
||||
"web-view": "网页视图",
|
||||
@@ -1463,7 +1462,11 @@
|
||||
"confirm-change": "当笔记内容不为空时,不建议更改笔记类型。您仍然要继续吗?",
|
||||
"geo-map": "地理地图",
|
||||
"beta-feature": "测试版",
|
||||
"task-list": "待办事项列表"
|
||||
"task-list": "任务列表",
|
||||
"ai-chat": "AI聊天",
|
||||
"new-feature": "新建",
|
||||
"collections": "集合",
|
||||
"book": "集合"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "保护笔记",
|
||||
@@ -1573,7 +1576,9 @@
|
||||
},
|
||||
"clipboard": {
|
||||
"cut": "笔记已剪切到剪贴板。",
|
||||
"copied": "笔记已复制到剪贴板。"
|
||||
"copied": "笔记已复制到剪贴板。",
|
||||
"copy_failed": "由于权限问题,无法复制到剪贴板。",
|
||||
"copy_success": "已复制到剪贴板。"
|
||||
},
|
||||
"entrypoints": {
|
||||
"note-revision-created": "笔记修订已创建。",
|
||||
@@ -1624,7 +1629,8 @@
|
||||
"word_wrapping": "自动换行",
|
||||
"theme_none": "无语法高亮",
|
||||
"theme_group_light": "浅色主题",
|
||||
"theme_group_dark": "深色主题"
|
||||
"theme_group_dark": "深色主题",
|
||||
"copy_title": "复制到剪贴板"
|
||||
},
|
||||
"classic_editor_toolbar": {
|
||||
"title": "格式"
|
||||
@@ -1662,7 +1668,8 @@
|
||||
"link_context_menu": {
|
||||
"open_note_in_new_tab": "在新标签页中打开笔记",
|
||||
"open_note_in_new_split": "在新分屏中打开笔记",
|
||||
"open_note_in_new_window": "在新窗口中打开笔记"
|
||||
"open_note_in_new_window": "在新窗口中打开笔记",
|
||||
"open_note_in_popup": "快速编辑"
|
||||
},
|
||||
"electron_integration": {
|
||||
"desktop-application": "桌面应用程序",
|
||||
@@ -1682,7 +1689,8 @@
|
||||
"full-text-search": "全文搜索"
|
||||
},
|
||||
"note_tooltip": {
|
||||
"note-has-been-deleted": "笔记已被删除。"
|
||||
"note-has-been-deleted": "笔记已被删除。",
|
||||
"quick-edit": "快速编辑"
|
||||
},
|
||||
"geo-map": {
|
||||
"create-child-note-title": "创建一个新的子笔记并将其添加到地图中",
|
||||
@@ -1691,7 +1699,8 @@
|
||||
},
|
||||
"geo-map-context": {
|
||||
"open-location": "打开位置",
|
||||
"remove-from-map": "从地图中移除"
|
||||
"remove-from-map": "从地图中移除",
|
||||
"add-note": "在这个位置添加一个标记"
|
||||
},
|
||||
"help-button": {
|
||||
"title": "打开相关帮助页面"
|
||||
@@ -1723,5 +1732,293 @@
|
||||
"tomorrow": "明天",
|
||||
"yesterday": "昨天"
|
||||
}
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "未开始",
|
||||
"title": "AI设置",
|
||||
"processed_notes": "已处理笔记",
|
||||
"total_notes": "笔记总数",
|
||||
"progress": "进度",
|
||||
"queued_notes": "排队中笔记",
|
||||
"failed_notes": "失败笔记",
|
||||
"last_processed": "最后处理时间",
|
||||
"refresh_stats": "刷新统计数据",
|
||||
"enable_ai_features": "启用AI/LLM功能",
|
||||
"enable_ai_description": "启用笔记摘要、内容生成等AI功能及其他LLM能力",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "启用AI/LLM功能",
|
||||
"enable_ai_desc": "启用笔记摘要、内容生成等AI功能及其他LLM能力",
|
||||
"provider_configuration": "AI提供商配置",
|
||||
"provider_precedence": "提供商优先级",
|
||||
"provider_precedence_description": "按优先级排序的提供商列表(用逗号分隔,例如:'openai,anthropic,ollama')",
|
||||
"temperature": "温度参数",
|
||||
"temperature_description": "控制响应的随机性(0 = 确定性输出,2 = 最大随机性)",
|
||||
"system_prompt": "系统提示词",
|
||||
"system_prompt_description": "所有AI交互使用的默认系统提示词",
|
||||
"openai_configuration": "OpenAI配置",
|
||||
"openai_settings": "OpenAI设置",
|
||||
"api_key": "API密钥",
|
||||
"url": "基础URL",
|
||||
"model": "模型",
|
||||
"openai_api_key_description": "用于访问OpenAI服务的API密钥",
|
||||
"anthropic_api_key_description": "用于访问Claude模型的Anthropic API密钥",
|
||||
"default_model": "默认模型",
|
||||
"openai_model_description": "示例:gpt-4o、gpt-4-turbo、gpt-3.5-turbo",
|
||||
"base_url": "基础URL",
|
||||
"openai_url_description": "默认:https://api.openai.com/v1",
|
||||
"anthropic_settings": "Anthropic设置",
|
||||
"anthropic_url_description": "Anthropic API的基础URL(默认:https://api.anthropic.com)",
|
||||
"anthropic_model_description": "用于聊天补全的Anthropic Claude模型",
|
||||
"voyage_settings": "Voyage AI设置",
|
||||
"ollama_settings": "Ollama设置",
|
||||
"ollama_url_description": "Ollama API的URL(默认:http://localhost:11434)",
|
||||
"ollama_model_description": "用于聊天补全的 Ollama 模型",
|
||||
"anthropic_configuration": "Anthropic配置",
|
||||
"voyage_configuration": "Voyage AI配置",
|
||||
"voyage_url_description": "默认:https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Ollama配置",
|
||||
"enable_ollama": "启用Ollama",
|
||||
"enable_ollama_description": "启用Ollama以使用本地AI模型",
|
||||
"ollama_url": "Ollama URL",
|
||||
"ollama_model": "Ollama模型",
|
||||
"refresh_models": "刷新模型",
|
||||
"refreshing_models": "刷新中...",
|
||||
"enable_automatic_indexing": "启用自动索引",
|
||||
"rebuild_index": "重建索引",
|
||||
"rebuild_index_error": "启动索引重建失败。请查看日志了解详情。",
|
||||
"note_title": "笔记标题",
|
||||
"error": "错误",
|
||||
"last_attempt": "最后尝试时间",
|
||||
"actions": "操作",
|
||||
"retry": "重试",
|
||||
"partial": "{{ percentage }}% 已完成",
|
||||
"retry_queued": "笔记已加入重试队列",
|
||||
"retry_failed": "笔记加入重试队列失败",
|
||||
"max_notes_per_llm_query": "每次查询的最大笔记数",
|
||||
"max_notes_per_llm_query_description": "AI上下文包含的最大相似笔记数量",
|
||||
"active_providers": "活跃提供商",
|
||||
"disabled_providers": "已禁用提供商",
|
||||
"remove_provider": "从搜索中移除提供商",
|
||||
"restore_provider": "将提供商恢复到搜索中",
|
||||
"similarity_threshold": "相似度阈值",
|
||||
"similarity_threshold_description": "纳入LLM查询上下文的笔记最低相似度分数(0-1)",
|
||||
"reprocess_index": "重建搜索索引",
|
||||
"reprocessing_index": "重建中...",
|
||||
"reprocess_index_started": "搜索索引优化已在后台启动",
|
||||
"reprocess_index_error": "重建搜索索引失败",
|
||||
"index_rebuild_progress": "索引重建进度",
|
||||
"index_rebuilding": "正在优化索引({{percentage}}%)",
|
||||
"index_rebuild_complete": "索引优化完成",
|
||||
"index_rebuild_status_error": "检查索引重建状态失败",
|
||||
"never": "从未",
|
||||
"processing": "处理中({{percentage}}%)",
|
||||
"incomplete": "未完成({{percentage}}%)",
|
||||
"complete": "已完成(100%)",
|
||||
"refreshing": "刷新中...",
|
||||
"auto_refresh_notice": "每 {{seconds}} 秒自动刷新",
|
||||
"note_queued_for_retry": "笔记已加入重试队列",
|
||||
"failed_to_retry_note": "重试笔记失败",
|
||||
"all_notes_queued_for_retry": "所有失败笔记已加入重试队列",
|
||||
"failed_to_retry_all": "重试笔记失败",
|
||||
"ai_settings": "AI设置",
|
||||
"api_key_tooltip": "用于访问服务的API密钥",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "Anthropic API密钥为空。请输入有效的API密钥。",
|
||||
"openai": "OpenAI API密钥为空。请输入有效的API密钥。",
|
||||
"voyage": "Voyage API密钥为空。请输入有效的API密钥。",
|
||||
"ollama": "Ollama API密钥为空。请输入有效的API密钥。"
|
||||
},
|
||||
"agent": {
|
||||
"processing": "处理中...",
|
||||
"thinking": "思考中...",
|
||||
"loading": "加载中...",
|
||||
"generating": "生成中..."
|
||||
},
|
||||
"name": "AI",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "使用增强上下文",
|
||||
"enhanced_context_description": "为AI提供来自笔记及其相关笔记的更多上下文,以获得更好的响应",
|
||||
"show_thinking": "显示思考过程",
|
||||
"show_thinking_description": "显示AI的思维链过程",
|
||||
"enter_message": "输入你的消息...",
|
||||
"error_contacting_provider": "联系AI提供商失败。请检查你的设置和网络连接。",
|
||||
"error_generating_response": "生成AI响应失败",
|
||||
"index_all_notes": "为所有笔记建立索引",
|
||||
"index_status": "索引状态",
|
||||
"indexed_notes": "已索引笔记",
|
||||
"indexing_stopped": "索引已停止",
|
||||
"indexing_in_progress": "索引进行中...",
|
||||
"last_indexed": "最后索引时间",
|
||||
"n_notes_queued_0": "{{ count }} 条笔记已加入索引队列",
|
||||
"note_chat": "笔记聊天",
|
||||
"notes_indexed_0": "{{ count }} 条笔记已索引",
|
||||
"sources": "来源",
|
||||
"start_indexing": "开始索引",
|
||||
"use_advanced_context": "使用高级上下文",
|
||||
"ollama_no_url": "Ollama 未配置。请输入有效的URL。",
|
||||
"chat": {
|
||||
"root_note_title": "AI聊天记录",
|
||||
"root_note_content": "此笔记包含你保存的AI聊天对话。",
|
||||
"new_chat_title": "新聊天",
|
||||
"create_new_ai_chat": "创建新的AI聊天"
|
||||
},
|
||||
"create_new_ai_chat": "创建新的AI聊天",
|
||||
"configuration_warnings": "你的AI配置存在一些问题。请检查你的设置。",
|
||||
"experimental_warning": "LLM功能目前处于实验阶段 - 特此提醒。",
|
||||
"selected_provider": "已选提供商",
|
||||
"selected_provider_description": "选择用于聊天和补全功能的AI提供商",
|
||||
"select_model": "选择模型...",
|
||||
"select_provider": "选择提供商...",
|
||||
"ai_enabled": "已启用 AI 功能",
|
||||
"ai_disabled": "已禁用 AI 功能",
|
||||
"no_models_found_online": "找不到模型。请检查您的 API 密钥及设置。",
|
||||
"no_models_found_ollama": "找不到 Ollama 模型。请确认 Ollama 是否正在运行。",
|
||||
"error_fetching": "获取模型失败:{{error}}"
|
||||
},
|
||||
"code-editor-options": {
|
||||
"title": "编辑器"
|
||||
},
|
||||
"custom_date_time_format": {
|
||||
"title": "自定义日期/时间格式",
|
||||
"description": "通过<shortcut />或工具栏的方式可自定义日期和时间格式,有关日期/时间格式字符串中各个字符的含义,请参阅<doc>Day.js docs</doc>。",
|
||||
"format_string": "日期/时间格式字符串:",
|
||||
"formatted_time": "格式化后日期/时间:"
|
||||
},
|
||||
"content_widget": {
|
||||
"unknown_widget": "未知组件:\"{{id}}\"."
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "不设置",
|
||||
"configure-languages": "设置语言..."
|
||||
},
|
||||
"content_language": {
|
||||
"title": "内容语言",
|
||||
"description": "选择一种或多种语言出现在只读或可编辑文本注释的基本属性,这将支持拼写检查或从右向左之类的功能。"
|
||||
},
|
||||
"switch_layout_button": {
|
||||
"title_vertical": "将编辑面板移至底部",
|
||||
"title_horizontal": "将编辑面板移至左侧"
|
||||
},
|
||||
"toggle_read_only_button": {
|
||||
"unlock-editing": "解锁编辑",
|
||||
"lock-editing": "锁定编辑"
|
||||
},
|
||||
"png_export_button": {
|
||||
"button_title": "将图表导出为PNG"
|
||||
},
|
||||
"svg": {
|
||||
"export_to_png": "无法将图表导出为PNG。"
|
||||
},
|
||||
"code_theme": {
|
||||
"title": "外观",
|
||||
"word_wrapping": "自动换行",
|
||||
"color-scheme": "配色方案"
|
||||
},
|
||||
"cpu_arch_warning": {
|
||||
"title": "请下载ARM64版本",
|
||||
"message_macos": "TriliumNext当前正在通过Rosetta 2转译运行,这意味着您在Apple Silicon芯片的Mac上使用的是Intel(x64)版本。这将显著影响性能和电池续航。",
|
||||
"message_windows": "TriliumNext当前正在模拟环境中运行,这意味着您在ARM架构的Windows设备上使用的是Intel(x64)版本。这将显著影响性能和电池续航。",
|
||||
"recommendation": "为获得最佳体验,请从我们的发布页面下载TriliumNext的原生ARM64版本。",
|
||||
"download_link": "下载原生版本",
|
||||
"continue_anyway": "仍然继续",
|
||||
"dont_show_again": "不再显示此警告"
|
||||
},
|
||||
"editorfeatures": {
|
||||
"title": "功能",
|
||||
"emoji_completion_enabled": "启用表情自动补全",
|
||||
"note_completion_enabled": "启用笔记自动补全"
|
||||
},
|
||||
"table_view": {
|
||||
"new-row": "新增行",
|
||||
"new-column": "新增列",
|
||||
"sort-column-by": "按\"{{title}}\"排序",
|
||||
"sort-column-ascending": "升序",
|
||||
"sort-column-descending": "降序",
|
||||
"sort-column-clear": "清除排序",
|
||||
"hide-column": "隐藏\"{{title}}\"列",
|
||||
"show-hide-columns": "显示/隐藏列",
|
||||
"row-insert-above": "在上方插入行",
|
||||
"row-insert-below": "在下方插入行",
|
||||
"row-insert-child": "插入子笔记",
|
||||
"add-column-to-the-left": "在左侧添加列",
|
||||
"add-column-to-the-right": "在右侧添加列",
|
||||
"edit-column": "编辑列",
|
||||
"delete_column_confirmation": "确定要删除此列吗?所有笔记中对应的属性都将被移除。",
|
||||
"delete-column": "删除列",
|
||||
"new-column-label": "标签",
|
||||
"new-column-relation": "关联"
|
||||
},
|
||||
"book_properties_config": {
|
||||
"hide-weekends": "隐藏周末",
|
||||
"display-week-numbers": "显示周数",
|
||||
"map-style": "地图样式:",
|
||||
"max-nesting-depth": "最大嵌套深度:",
|
||||
"raster": "栅格",
|
||||
"vector_light": "矢量(浅色)",
|
||||
"vector_dark": "矢量(深色)",
|
||||
"show-scale": "显示比例尺"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "删除行"
|
||||
},
|
||||
"board_view": {
|
||||
"delete-note": "删除笔记",
|
||||
"move-to": "移动到",
|
||||
"insert-above": "在上方插入",
|
||||
"insert-below": "在下方插入",
|
||||
"delete-column": "删除列",
|
||||
"delete-column-confirmation": "确定要删除此列吗?此列下所有笔记中对应的属性也将被删除。",
|
||||
"new-item": "新增项目",
|
||||
"add-column": "添加列"
|
||||
},
|
||||
"command_palette": {
|
||||
"tree-action-name": "树形:{{name}}",
|
||||
"export_note_title": "导出笔记",
|
||||
"export_note_description": "导出当前笔记",
|
||||
"show_attachments_title": "显示附件",
|
||||
"show_attachments_description": "查看笔记附件",
|
||||
"search_notes_title": "搜索笔记",
|
||||
"search_notes_description": "打开高级搜索",
|
||||
"search_subtree_title": "在子树中搜索",
|
||||
"search_subtree_description": "在当前子树范围内搜索",
|
||||
"search_history_title": "显示搜索历史",
|
||||
"search_history_description": "查看之前的搜索记录",
|
||||
"configure_launch_bar_title": "配置启动栏",
|
||||
"configure_launch_bar_description": "打开启动栏配置,添加或移除项目。"
|
||||
},
|
||||
"content_renderer": {
|
||||
"open_externally": "在外部打开"
|
||||
},
|
||||
"modal": {
|
||||
"close": "关闭",
|
||||
"help_title": "显示关于此画面的更多信息"
|
||||
},
|
||||
"call_to_action": {
|
||||
"background_effects_title": "背景效果现已推出稳定版本",
|
||||
"background_effects_message": "在 Windows 装置上,背景效果现在已完全稳定。背景效果通过模糊背后的背景,为使用者界面增添一抹色彩。此技术也用于其他应用程序,例如 Windows 资源管理器。",
|
||||
"background_effects_button": "启用背景效果",
|
||||
"next_theme_title": "试用新 Trilium 主题",
|
||||
"next_theme_message": "当前使用旧版主题,要试用新主题吗?",
|
||||
"next_theme_button": "试用新主题",
|
||||
"dismiss": "关闭"
|
||||
},
|
||||
"settings": {
|
||||
"related_settings": "相关设置"
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "文本笔记中代码块的色彩方案",
|
||||
"related_code_notes": "代码笔记的色彩方案"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
},
|
||||
"ui-performance": {
|
||||
"title": "性能",
|
||||
"enable-motion": "启用过渡和动画",
|
||||
"enable-shadows": "启用阴影",
|
||||
"enable-backdrop-effects": "启用菜单、弹窗和面板的背景效果"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "Über Trilium Notes",
|
||||
"close": "Schließen",
|
||||
"homepage": "Startseite:",
|
||||
"app_version": "App-Version:",
|
||||
"db_version": "DB-Version:",
|
||||
@@ -28,25 +27,22 @@
|
||||
"add_link": {
|
||||
"add_link": "Link hinzufügen",
|
||||
"help_on_links": "Hilfe zu Links",
|
||||
"close": "Schließen",
|
||||
"note": "Notiz",
|
||||
"search_note": "Suche nach einer Notiz anhand ihres Namens",
|
||||
"link_title_mirrors": "Der Linktitel spiegelt den aktuellen Titel der Notiz wider",
|
||||
"link_title_arbitrary": "Der Linktitel kann beliebig geändert werden",
|
||||
"link_title": "Linktitel",
|
||||
"button_add_link": "Link hinzufügen <kbd>Eingabetaste</kbd>"
|
||||
"button_add_link": "Link hinzufügen"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"edit_branch_prefix": "Zweigpräfix bearbeiten",
|
||||
"help_on_tree_prefix": "Hilfe zum Baumpräfix",
|
||||
"close": "Schließen",
|
||||
"prefix": "Präfix: ",
|
||||
"save": "Speichern",
|
||||
"branch_prefix_saved": "Zweigpräfix wurde gespeichert."
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "Massenaktionen",
|
||||
"close": "Schließen",
|
||||
"affected_notes": "Betroffene Notizen",
|
||||
"include_descendants": "Unternotizen der ausgewählten Notizen einbeziehen",
|
||||
"available_actions": "Verfügbare Aktionen",
|
||||
@@ -61,20 +57,18 @@
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "Notizen klonen nach...",
|
||||
"close": "Schließen",
|
||||
"help_on_links": "Hilfe zu Links",
|
||||
"notes_to_clone": "Notizen zum Klonen",
|
||||
"target_parent_note": "Ziel-Übergeordnetenotiz",
|
||||
"search_for_note_by_its_name": "Suche nach einer Notiz anhand ihres Namens",
|
||||
"cloned_note_prefix_title": "Die geklonte Notiz wird im Notizbaum mit dem angegebenen Präfix angezeigt",
|
||||
"prefix_optional": "Präfix (optional)",
|
||||
"clone_to_selected_note": "Auf ausgewählte Notiz klonen <kbd>Eingabe</kbd>",
|
||||
"clone_to_selected_note": "Auf ausgewählte Notiz klonen",
|
||||
"no_path_to_clone_to": "Kein Pfad zum Klonen.",
|
||||
"note_cloned": "Die Notiz \"{{clonedTitle}}\" wurde in \"{{targetTitle}}\" hinein geklont"
|
||||
},
|
||||
"confirm": {
|
||||
"confirmation": "Bestätigung",
|
||||
"close": "Schließen",
|
||||
"cancel": "Abbrechen",
|
||||
"ok": "OK",
|
||||
"are_you_sure_remove_note": "Bist du sicher, dass du \"{{title}}\" von der Beziehungskarte entfernen möchten? ",
|
||||
@@ -87,9 +81,9 @@
|
||||
"delete_all_clones_description": "auch alle Klone löschen (kann bei letzte Änderungen rückgängig gemacht werden)",
|
||||
"erase_notes_description": "Beim normalen (vorläufigen) Löschen werden die Notizen nur als gelöscht markiert und sie können innerhalb eines bestimmten Zeitraums (im Dialogfeld „Letzte Änderungen“) wiederhergestellt werden. Wenn du diese Option aktivierst, werden die Notizen sofort gelöscht und es ist nicht möglich, die Notizen wiederherzustellen.",
|
||||
"erase_notes_warning": "Notizen dauerhaft löschen (kann nicht rückgängig gemacht werden), einschließlich aller Klone. Dadurch wird ein Neuladen der Anwendung erzwungen.",
|
||||
"notes_to_be_deleted": "Folgende Notizen werden gelöscht (<span class=\"deleted-notes-count\"></span>)",
|
||||
"notes_to_be_deleted": "Folgende Notizen werden gelöscht ({{notesCount}})",
|
||||
"no_note_to_delete": "Es werden keine Notizen gelöscht (nur Klone).",
|
||||
"broken_relations_to_be_deleted": "Folgende Beziehungen werden gelöst und gelöscht (<span class=\"broke-relations-count\"></span>)",
|
||||
"broken_relations_to_be_deleted": "Folgende Beziehungen werden gelöst und gelöscht ({{ relationCount}})",
|
||||
"cancel": "Abbrechen",
|
||||
"ok": "OK",
|
||||
"deleted_relation_text": "Notiz {{- note}} (soll gelöscht werden) wird von Beziehung {{- relation}} ausgehend von {{- source}} referenziert."
|
||||
@@ -113,20 +107,18 @@
|
||||
"format_pdf": "PDF - für Ausdrucke oder Teilen."
|
||||
},
|
||||
"help": {
|
||||
"fullDocumentation": "Hilfe (gesamte Dokumentation ist <a class=\"external\" href=\"https://triliumnext.github.io/Docs/\">online</a> verfügbar)",
|
||||
"close": "Schließen",
|
||||
"noteNavigation": "Notiz Navigation",
|
||||
"goUpDown": "<kbd>Pfeil Hoch</kbd>, <kbd>Pfeil Runter</kbd> - In der Liste der Notizen nach oben/unten gehen",
|
||||
"collapseExpand": "<kbd>LEFT</kbd>, <kbd>RIGHT</kbd> - Knoten reduzieren/erweitern",
|
||||
"goUpDown": "In der Liste der Notizen nach oben/unten gehen",
|
||||
"collapseExpand": "Knoten reduzieren/erweitern",
|
||||
"notSet": "nicht eingestellt",
|
||||
"goBackForwards": "in der Historie zurück/vorwärts gehen",
|
||||
"showJumpToNoteDialog": "zeige <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"Springe zu\" dialog</a>",
|
||||
"scrollToActiveNote": "Scrolle zur aktiven Notiz",
|
||||
"jumpToParentNote": "<kbd>Backspace</kbd> - Zur übergeordneten Notiz springen",
|
||||
"jumpToParentNote": "Zur übergeordneten Notiz springen",
|
||||
"collapseWholeTree": "Reduziere den gesamten Notizbaum",
|
||||
"collapseSubTree": "Teilbaum einklappen",
|
||||
"tabShortcuts": "Tab-Tastenkürzel",
|
||||
"newTabNoteLink": "<kbd>Strg+Klick</kbd> - (oder mittlerer Mausklick) auf den Notizlink öffnet die Notiz in einem neuen Tab",
|
||||
"newTabNoteLink": "auf den Notizlink öffnet die Notiz in einem neuen Tab",
|
||||
"onlyInDesktop": "Nur im Desktop (Electron Build)",
|
||||
"openEmptyTab": "Leeren Tab öffnen",
|
||||
"closeActiveTab": "Aktiven Tab schließen",
|
||||
@@ -141,14 +133,14 @@
|
||||
"moveNoteUpHierarchy": "Verschiebe die Notiz in der Hierarchie nach oben",
|
||||
"multiSelectNote": "Mehrfachauswahl von Notizen oben/unten",
|
||||
"selectAllNotes": "Wähle alle Notizen in der aktuellen Ebene aus",
|
||||
"selectNote": "<kbd>Umschalt+Klick</kbd> - Notiz auswählen",
|
||||
"selectNote": "Notiz auswählen",
|
||||
"copyNotes": "Kopiere aktive Notiz (oder aktuelle Auswahl) in den Zwischenspeicher (wird genutzt für <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/cloning-notes.html#cloning-notes\">Klonen</a>)",
|
||||
"cutNotes": "Aktuelle Notiz (oder aktuelle Auswahl) in die Zwischenablage ausschneiden (wird zum Verschieben von Notizen verwendet)",
|
||||
"pasteNotes": "Notiz(en) als Unternotiz in die aktive Notiz einfügen (entweder verschieben oder klonen, je nachdem, ob sie kopiert oder in die Zwischenablag e ausgeschnitten wurde)",
|
||||
"deleteNotes": "Notiz / Unterbaum löschen",
|
||||
"editingNotes": "Notizen bearbeiten",
|
||||
"editNoteTitle": "Im Baumbereich wird vom Baumbereich zum Notiztitel gewechselt. Beim Druck auf Eingabe im Notiztitel, wechselt der Fokus zum Texteditor. <kbd>Strg+.</kbd> wechselt vom Editor zurück zum Baumbereich.",
|
||||
"createEditLink": "<kbd>Strg+K</kbd> - Externen Link erstellen/bearbeiten",
|
||||
"createEditLink": "Externen Link erstellen/bearbeiten",
|
||||
"createInternalLink": "Internen Link erstellen",
|
||||
"followLink": "Folge dem Link unter dem Cursor",
|
||||
"insertDateTime": "Gebe das aktuelle Datum und die aktuelle Uhrzeit an der Einfügemarke ein",
|
||||
@@ -164,11 +156,12 @@
|
||||
"showSQLConsole": "SQL-Konsole anzeigen",
|
||||
"other": "Andere",
|
||||
"quickSearch": "Fokus auf schnelle Sucheingabe",
|
||||
"inPageSearch": "Auf-der-Seite-Suche"
|
||||
"inPageSearch": "Auf-der-Seite-Suche",
|
||||
"newTabWithActivationNoteLink": "auf einen Notiz-Link öffnet und aktiviert die Notiz in einem neuen Tab",
|
||||
"title": "Spickzettel"
|
||||
},
|
||||
"import": {
|
||||
"importIntoNote": "In Notiz importieren",
|
||||
"close": "Schließen",
|
||||
"chooseImportFile": "Wähle Importdatei aus",
|
||||
"importDescription": "Der Inhalt der ausgewählten Datei(en) wird als untergeordnete Notiz(en) importiert",
|
||||
"options": "Optionen",
|
||||
@@ -195,14 +188,13 @@
|
||||
},
|
||||
"include_note": {
|
||||
"dialog_title": "Notiz beifügen",
|
||||
"close": "Schließen",
|
||||
"label_note": "Notiz",
|
||||
"placeholder_search": "Suche nach einer Notiz anhand ihres Namens",
|
||||
"box_size_prompt": "Kartongröße des beigelegten Zettels:",
|
||||
"box_size_small": "klein (~ 10 Zeilen)",
|
||||
"box_size_medium": "mittel (~ 30 Zeilen)",
|
||||
"box_size_full": "vollständig (Feld zeigt vollständigen Text)",
|
||||
"button_include": "Notiz beifügen <kbd>Eingabetaste</kbd>"
|
||||
"button_include": "Notiz beifügen"
|
||||
},
|
||||
"info": {
|
||||
"modalTitle": "Infonachricht",
|
||||
@@ -210,43 +202,35 @@
|
||||
"okButton": "OK"
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_placeholder": "Suche nach einer Notiz anhand ihres Namens",
|
||||
"close": "Schließen",
|
||||
"search_button": "Suche im Volltext: <kbd>Strg+Eingabetaste</kbd>"
|
||||
"search_button": "Suche im Volltext"
|
||||
},
|
||||
"markdown_import": {
|
||||
"dialog_title": "Markdown-Import",
|
||||
"close": "Schließen",
|
||||
"modal_body_text": "Aufgrund der Browser-Sandbox ist es nicht möglich, die Zwischenablage direkt aus JavaScript zu lesen. Bitte füge den zu importierenden Markdown in den Textbereich unten ein und klicke auf die Schaltfläche „Importieren“.",
|
||||
"import_button": "Importieren Strg+Eingabe",
|
||||
"import_button": "Importieren",
|
||||
"import_success": "Markdown-Inhalt wurde in das Dokument importiert."
|
||||
},
|
||||
"move_to": {
|
||||
"dialog_title": "Notizen verschieben nach ...",
|
||||
"close": "Schließen",
|
||||
"notes_to_move": "Notizen zum Verschieben",
|
||||
"target_parent_note": "Ziel-Elternnotiz",
|
||||
"search_placeholder": "Suche nach einer Notiz anhand ihres Namens",
|
||||
"move_button": "Zur ausgewählten Notiz wechseln <kbd>Eingabetaste</kbd>",
|
||||
"move_button": "Zur ausgewählten Notiz wechseln",
|
||||
"error_no_path": "Kein Weg, auf den man sich bewegen kann.",
|
||||
"move_success_message": "Ausgewählte Notizen wurden verschoben"
|
||||
},
|
||||
"note_type_chooser": {
|
||||
"modal_title": "Wähle den Notiztyp aus",
|
||||
"close": "Schließen",
|
||||
"modal_body": "Wähle den Notiztyp / die Vorlage der neuen Notiz:",
|
||||
"templates": "Vorlagen:"
|
||||
"templates": "Vorlagen"
|
||||
},
|
||||
"password_not_set": {
|
||||
"title": "Das Passwort ist nicht festgelegt",
|
||||
"close": "Schließen",
|
||||
"body1": "Geschützte Notizen werden mit einem Benutzerpasswort verschlüsselt, es wurde jedoch noch kein Passwort festgelegt.",
|
||||
"body2": "Um Notizen verschlüsseln zu können, klicke <a class=\"open-password-options-button\" href=\"javascript:\">hier</a> um das Optionsmenu zu öffnen und ein Passwort zu setzen."
|
||||
"body1": "Geschützte Notizen werden mit einem Benutzerpasswort verschlüsselt, es wurde jedoch noch kein Passwort festgelegt."
|
||||
},
|
||||
"prompt": {
|
||||
"title": "Prompt",
|
||||
"close": "Schließen",
|
||||
"ok": "OK <kbd>Eingabe</kbd>",
|
||||
"ok": "OK",
|
||||
"defaultTitle": "Prompt"
|
||||
},
|
||||
"protected_session_password": {
|
||||
@@ -254,12 +238,11 @@
|
||||
"help_title": "Hilfe zu geschützten Notizen",
|
||||
"close_label": "Schließen",
|
||||
"form_label": "Um mit der angeforderten Aktion fortzufahren, musst du eine geschützte Sitzung starten, indem du ein Passwort eingibst:",
|
||||
"start_button": "Geschützte Sitzung starten <kbd>enter</kbd>"
|
||||
"start_button": "Geschützte Sitzung starten"
|
||||
},
|
||||
"recent_changes": {
|
||||
"title": "Aktuelle Änderungen",
|
||||
"erase_notes_button": "Jetzt gelöschte Notizen löschen",
|
||||
"close": "Schließen",
|
||||
"deleted_notes_message": "Gelöschte Notizen wurden gelöscht.",
|
||||
"no_changes_message": "Noch keine Änderungen...",
|
||||
"undelete_link": "Wiederherstellen",
|
||||
@@ -270,13 +253,10 @@
|
||||
"delete_all_revisions": "Lösche alle Revisionen dieser Notiz",
|
||||
"delete_all_button": "Alle Revisionen löschen",
|
||||
"help_title": "Hilfe zu Notizrevisionen",
|
||||
"close": "Schließen",
|
||||
"revision_last_edited": "Diese Revision wurde zuletzt am {{date}} bearbeitet",
|
||||
"confirm_delete_all": "Möchtest du alle Revisionen dieser Notiz löschen?",
|
||||
"no_revisions": "Für diese Notiz gibt es noch keine Revisionen...",
|
||||
"restore_button": "",
|
||||
"confirm_restore": "Möchtest du diese Revision wiederherstellen? Dadurch werden der aktuelle Titel und Inhalt der Notiz mit dieser Revision überschrieben.",
|
||||
"delete_button": "",
|
||||
"confirm_delete": "Möchtest du diese Revision löschen?",
|
||||
"revisions_deleted": "Notizrevisionen wurden gelöscht.",
|
||||
"revision_restored": "Die Notizrevision wurde wiederhergestellt.",
|
||||
@@ -292,7 +272,6 @@
|
||||
},
|
||||
"sort_child_notes": {
|
||||
"sort_children_by": "Unternotizen sortieren nach...",
|
||||
"close": "Schließen",
|
||||
"sorting_criteria": "Sortierkriterien",
|
||||
"title": "Titel",
|
||||
"date_created": "Erstellungsdatum",
|
||||
@@ -306,13 +285,12 @@
|
||||
"sort_with_respect_to_different_character_sorting": "Sortierung im Hinblick auf unterschiedliche Sortier- und Sortierregeln für Zeichen in verschiedenen Sprachen oder Regionen.",
|
||||
"natural_sort_language": "Natürliche Sortiersprache",
|
||||
"the_language_code_for_natural_sort": "Der Sprachcode für die natürliche Sortierung, z. B. \"de-DE\" für Deutsch.",
|
||||
"sort": "Sortieren <kbd>Eingabetaste</kbd>"
|
||||
"sort": "Sortieren"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "Lade Anhänge zur Notiz hoch",
|
||||
"close": "Schließen",
|
||||
"choose_files": "Wähle Dateien aus",
|
||||
"files_will_be_uploaded": "Dateien werden als Anhänge in hochgeladen",
|
||||
"files_will_be_uploaded": "Dateien werden als Anhänge in hochgeladen {{noteTitle}}",
|
||||
"options": "Optionen",
|
||||
"shrink_images": "Bilder verkleinern",
|
||||
"upload": "Hochladen",
|
||||
@@ -750,7 +728,6 @@
|
||||
"expand_all_children": "Unternotizen ausklappen",
|
||||
"collapse": "Einklappen",
|
||||
"expand": "Ausklappen",
|
||||
"book_properties": "Bucheigenschaften",
|
||||
"invalid_view_type": "Ungültiger Ansichtstyp „{{type}}“",
|
||||
"calendar": "Kalender"
|
||||
},
|
||||
@@ -1102,12 +1079,9 @@
|
||||
"title": "Thema",
|
||||
"theme_label": "Thema",
|
||||
"override_theme_fonts_label": "Theme-Schriftarten überschreiben",
|
||||
"auto_theme": "Auto",
|
||||
"light_theme": "Hell",
|
||||
"dark_theme": "Dunkel",
|
||||
"triliumnext": "TriliumNext Beta (Systemfarbschema folgend)",
|
||||
"triliumnext-light": "TriliumNext Beta (Hell)",
|
||||
"triliumnext-dark": "TriliumNext Beta (Dunkel)",
|
||||
"triliumnext": "Trilium (Systemfarbschema folgend)",
|
||||
"triliumnext-light": "Trilium (Hell)",
|
||||
"triliumnext-dark": "Trilium (Dunkel)",
|
||||
"layout": "Layout",
|
||||
"layout-vertical-title": "Vertikal",
|
||||
"layout-horizontal-title": "Horizontal",
|
||||
@@ -1164,7 +1138,7 @@
|
||||
},
|
||||
"revisions_snapshot_interval": {
|
||||
"note_revisions_snapshot_interval_title": "Snapshot-Intervall für Notizrevisionen",
|
||||
"note_revisions_snapshot_description": "Das Snapshot-Zeitintervall für Notizrevisionen ist die Zeit, nach der eine neue Notizrevision erstellt wird. Weitere Informationen findest du im <a href=\"https://triliumnext.github.io/Docs/Wiki/note-revisions.html\" class=\"external\">Wiki</a>.",
|
||||
"note_revisions_snapshot_description": "Das Snapshot-Zeitintervall für Notizrevisionen ist die Zeit, nach der eine neue Notizrevision erstellt wird. Weitere Informationen findest du im <doc>Wiki</doc>.",
|
||||
"snapshot_time_interval_label": "Zeitintervall für Notiz-Revisions-Snapshot:"
|
||||
},
|
||||
"revisions_snapshot_limit": {
|
||||
@@ -1384,7 +1358,7 @@
|
||||
"move-to": "Verschieben nach...",
|
||||
"paste-into": "Als Unternotiz einfügen",
|
||||
"paste-after": "Danach einfügen",
|
||||
"duplicate-subtree": "Notizbaum duplizieren",
|
||||
"duplicate": "Duplizieren",
|
||||
"export": "Exportieren",
|
||||
"import-into-note": "In Notiz importieren",
|
||||
"apply-bulk-actions": "Massenaktionen ausführen",
|
||||
@@ -1403,7 +1377,6 @@
|
||||
"relation-map": "Beziehungskarte",
|
||||
"note-map": "Notizkarte",
|
||||
"render-note": "Render Notiz",
|
||||
"book": "Buch",
|
||||
"mermaid-diagram": "Mermaid Diagram",
|
||||
"canvas": "Canvas",
|
||||
"web-view": "Webansicht",
|
||||
@@ -1568,7 +1541,6 @@
|
||||
"auto-detect-language": "Automatisch erkannt"
|
||||
},
|
||||
"highlighting": {
|
||||
"title": "",
|
||||
"description": "Steuert die Syntaxhervorhebung für Codeblöcke in Textnotizen, Code-Notizen sind nicht betroffen.",
|
||||
"color-scheme": "Farbschema"
|
||||
},
|
||||
@@ -1656,5 +1628,8 @@
|
||||
},
|
||||
"time_selector": {
|
||||
"invalid_input": "Die eingegebene Zeit ist keine valide Zahl."
|
||||
},
|
||||
"modal": {
|
||||
"close": "Schließen"
|
||||
}
|
||||
}
|
||||
|
||||
18
apps/client/src/translations/el/translation.json
Normal file
18
apps/client/src/translations/el/translation.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "Πληροφορίες για το Trilium Notes",
|
||||
"homepage": "Αρχική Σελίδα:",
|
||||
"app_version": "Έκδοση εφαρμογής:",
|
||||
"db_version": "Έκδοση βάσης δεδομένων:",
|
||||
"sync_version": "Έκδοση πρωτοκόλου συγχρονισμού:",
|
||||
"build_date": "Ημερομηνία χτισίματος εφαρμογής:",
|
||||
"build_revision": "Αριθμός αναθεώρησης χτισίματος:",
|
||||
"data_directory": "Φάκελος δεδομένων:"
|
||||
},
|
||||
"toast": {
|
||||
"critical-error": {
|
||||
"title": "Κρίσιμο σφάλμα",
|
||||
"message": "Συνέβη κάποιο κρίσιμο σφάλμα, το οποίο δεν επιτρέπει στην εφαρμογή χρήστη να ξεκινήσει:\n\n{{message}}\n\nΤο πιθανότερο είναι να προκλήθηκε από κάποιο script που απέτυχε απρόοπτα. Δοκιμάστε να ξεκινήσετε την εφαρμογή σε ασφαλή λειτουργία για να λύσετε το πρόβλημα."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "About Trilium Notes",
|
||||
"close": "Close",
|
||||
"homepage": "Homepage:",
|
||||
"app_version": "App version:",
|
||||
"db_version": "DB version:",
|
||||
@@ -28,25 +27,22 @@
|
||||
"add_link": {
|
||||
"add_link": "Add link",
|
||||
"help_on_links": "Help on links",
|
||||
"close": "Close",
|
||||
"note": "Note",
|
||||
"search_note": "search for note by its name",
|
||||
"link_title_mirrors": "link title mirrors the note's current title",
|
||||
"link_title_arbitrary": "link title can be changed arbitrarily",
|
||||
"link_title": "Link title",
|
||||
"button_add_link": "Add link <kbd>enter</kbd>"
|
||||
"button_add_link": "Add link"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"edit_branch_prefix": "Edit branch prefix",
|
||||
"help_on_tree_prefix": "Help on Tree prefix",
|
||||
"close": "Close",
|
||||
"prefix": "Prefix: ",
|
||||
"save": "Save",
|
||||
"branch_prefix_saved": "Branch prefix has been saved."
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "Bulk actions",
|
||||
"close": "Close",
|
||||
"affected_notes": "Affected notes",
|
||||
"include_descendants": "Include descendants of the selected notes",
|
||||
"available_actions": "Available actions",
|
||||
@@ -61,20 +57,18 @@
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "Clone notes to...",
|
||||
"close": "Close",
|
||||
"help_on_links": "Help on links",
|
||||
"notes_to_clone": "Notes to clone",
|
||||
"target_parent_note": "Target parent note",
|
||||
"search_for_note_by_its_name": "search for note by its name",
|
||||
"cloned_note_prefix_title": "Cloned note will be shown in note tree with given prefix",
|
||||
"prefix_optional": "Prefix (optional)",
|
||||
"clone_to_selected_note": "Clone to selected note <kbd>enter</kbd>",
|
||||
"clone_to_selected_note": "Clone to selected note",
|
||||
"no_path_to_clone_to": "No path to clone to.",
|
||||
"note_cloned": "Note \"{{clonedTitle}}\" has been cloned into \"{{targetTitle}}\""
|
||||
},
|
||||
"confirm": {
|
||||
"confirmation": "Confirmation",
|
||||
"close": "Close",
|
||||
"cancel": "Cancel",
|
||||
"ok": "OK",
|
||||
"are_you_sure_remove_note": "Are you sure you want to remove the note \"{{title}}\" from relation map? ",
|
||||
@@ -87,9 +81,9 @@
|
||||
"delete_all_clones_description": "Delete also all clones (can be undone in recent changes)",
|
||||
"erase_notes_description": "Normal (soft) deletion only marks the notes as deleted and they can be undeleted (in recent changes dialog) within a period of time. Checking this option will erase the notes immediately and it won't be possible to undelete the notes.",
|
||||
"erase_notes_warning": "Erase notes permanently (can't be undone), including all clones. This will force application reload.",
|
||||
"notes_to_be_deleted": "Following notes will be deleted ({{- noteCount}})",
|
||||
"notes_to_be_deleted": "Following notes will be deleted ({{notesCount}})",
|
||||
"no_note_to_delete": "No note will be deleted (only clones).",
|
||||
"broken_relations_to_be_deleted": "Following relations will be broken and deleted ({{- relationCount}})",
|
||||
"broken_relations_to_be_deleted": "Following relations will be broken and deleted ({{ relationCount}})",
|
||||
"cancel": "Cancel",
|
||||
"ok": "OK",
|
||||
"deleted_relation_text": "Note {{- note}} (to be deleted) is referenced by relation {{- relation}} originating from {{- source}}."
|
||||
@@ -113,21 +107,20 @@
|
||||
"format_pdf": "PDF - for printing or sharing purposes."
|
||||
},
|
||||
"help": {
|
||||
"fullDocumentation": "Help (full documentation is available <a class=\"external\" href=\"https://triliumnext.github.io/Docs/\">online</a>)",
|
||||
"close": "Close",
|
||||
"title": "Cheatsheet",
|
||||
"noteNavigation": "Note navigation",
|
||||
"goUpDown": "<kbd>UP</kbd>, <kbd>DOWN</kbd> - go up/down in the list of notes",
|
||||
"collapseExpand": "<kbd>LEFT</kbd>, <kbd>RIGHT</kbd> - collapse/expand node",
|
||||
"goUpDown": "go up/down in the list of notes",
|
||||
"collapseExpand": "collapse/expand node",
|
||||
"notSet": "not set",
|
||||
"goBackForwards": "go back / forwards in the history",
|
||||
"showJumpToNoteDialog": "show <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"Jump to\" dialog</a>",
|
||||
"scrollToActiveNote": "scroll to active note",
|
||||
"jumpToParentNote": "<kbd>Backspace</kbd> - jump to parent note",
|
||||
"jumpToParentNote": "jump to parent note",
|
||||
"collapseWholeTree": "collapse whole note tree",
|
||||
"collapseSubTree": "collapse sub-tree",
|
||||
"tabShortcuts": "Tab shortcuts",
|
||||
"newTabNoteLink": "<kbd>Ctrl+click</kbd> - (or <kbd>middle mouse click</kbd>) on note link opens note in a new tab",
|
||||
"newTabWithActivationNoteLink": "<kbd>Ctrl+Shift+click</kbd> - (or <kbd>Shift+middle mouse click</kbd>) on note link opens and activates the note in a new tab",
|
||||
"newTabNoteLink": "on note link opens note in a new tab",
|
||||
"newTabWithActivationNoteLink": "on note link opens and activates the note in a new tab",
|
||||
"onlyInDesktop": "Only in desktop (Electron build)",
|
||||
"openEmptyTab": "open empty tab",
|
||||
"closeActiveTab": "close active tab",
|
||||
@@ -142,14 +135,14 @@
|
||||
"moveNoteUpHierarchy": "move note up in the hierarchy",
|
||||
"multiSelectNote": "multi-select note above/below",
|
||||
"selectAllNotes": "select all notes in the current level",
|
||||
"selectNote": "<kbd>Shift+click</kbd> - select note",
|
||||
"selectNote": "select note",
|
||||
"copyNotes": "copy active note (or current selection) into clipboard (used for <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/cloning-notes.html#cloning-notes\">cloning</a>)",
|
||||
"cutNotes": "cut current note (or current selection) into clipboard (used for moving notes)",
|
||||
"pasteNotes": "paste note(s) as sub-note into active note (which is either move or clone depending on whether it was copied or cut into clipboard)",
|
||||
"deleteNotes": "delete note / sub-tree",
|
||||
"editingNotes": "Editing notes",
|
||||
"editNoteTitle": "in tree pane will switch from tree pane into note title. Enter from note title will switch focus to text editor. <kbd>Ctrl+.</kbd> will switch back from editor to tree pane.",
|
||||
"createEditLink": "<kbd>Ctrl+K</kbd> - create / edit external link",
|
||||
"createEditLink": "create / edit external link",
|
||||
"createInternalLink": "create internal link",
|
||||
"followLink": "follow link under cursor",
|
||||
"insertDateTime": "insert current date and time at caret position",
|
||||
@@ -169,7 +162,6 @@
|
||||
},
|
||||
"import": {
|
||||
"importIntoNote": "Import into note",
|
||||
"close": "Close",
|
||||
"chooseImportFile": "Choose import file",
|
||||
"importDescription": "Content of the selected file(s) will be imported as child note(s) into",
|
||||
"options": "Options",
|
||||
@@ -196,14 +188,13 @@
|
||||
},
|
||||
"include_note": {
|
||||
"dialog_title": "Include note",
|
||||
"close": "Close",
|
||||
"label_note": "Note",
|
||||
"placeholder_search": "search for note by its name",
|
||||
"box_size_prompt": "Box size of the included note:",
|
||||
"box_size_small": "small (~ 10 lines)",
|
||||
"box_size_medium": "medium (~ 30 lines)",
|
||||
"box_size_full": "full (box shows complete text)",
|
||||
"button_include": "Include note <kbd>enter</kbd>"
|
||||
"button_include": "Include note"
|
||||
},
|
||||
"info": {
|
||||
"modalTitle": "Info message",
|
||||
@@ -211,24 +202,21 @@
|
||||
"okButton": "OK"
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_placeholder": "search for note by its name",
|
||||
"close": "Close",
|
||||
"search_button": "Search in full text <kbd>Ctrl+Enter</kbd>"
|
||||
"search_placeholder": "Search for note by its name or type > for commands...",
|
||||
"search_button": "Search in full text"
|
||||
},
|
||||
"markdown_import": {
|
||||
"dialog_title": "Markdown import",
|
||||
"close": "Close",
|
||||
"modal_body_text": "Because of browser sandbox it's not possible to directly read clipboard from JavaScript. Please paste the Markdown to import to textarea below and click on Import button",
|
||||
"import_button": "Import Ctrl+Enter",
|
||||
"import_button": "Import",
|
||||
"import_success": "Markdown content has been imported into the document."
|
||||
},
|
||||
"move_to": {
|
||||
"dialog_title": "Move notes to ...",
|
||||
"close": "Close",
|
||||
"notes_to_move": "Notes to move",
|
||||
"target_parent_note": "Target parent note",
|
||||
"search_placeholder": "search for note by its name",
|
||||
"move_button": "Move to selected note <kbd>enter</kbd>",
|
||||
"move_button": "Move to selected note",
|
||||
"error_no_path": "No path to move to.",
|
||||
"move_success_message": "Selected notes have been moved into "
|
||||
},
|
||||
@@ -236,20 +224,19 @@
|
||||
"change_path_prompt": "Change where to create the new note:",
|
||||
"search_placeholder": "search path by name (default if empty)",
|
||||
"modal_title": "Choose note type",
|
||||
"close": "Close",
|
||||
"modal_body": "Choose note type / template of the new note:",
|
||||
"templates": "Templates:"
|
||||
"templates": "Templates",
|
||||
"builtin_templates": "Built-in Templates"
|
||||
},
|
||||
"password_not_set": {
|
||||
"title": "Password is not set",
|
||||
"close": "Close",
|
||||
"body1": "Protected notes are encrypted using a user password, but password has not been set yet.",
|
||||
"body2": "To be able to protect notes, click <a class=\"open-password-options-button\" href=\"javascript:\">here</a> to open the Options dialog and set your password."
|
||||
"body2": "To be able to protect notes, click the button below to open the Options dialog and set your password.",
|
||||
"go_to_password_options": "Go to Password options"
|
||||
},
|
||||
"prompt": {
|
||||
"title": "Prompt",
|
||||
"close": "Close",
|
||||
"ok": "OK <kbd>enter</kbd>",
|
||||
"ok": "OK",
|
||||
"defaultTitle": "Prompt"
|
||||
},
|
||||
"protected_session_password": {
|
||||
@@ -257,12 +244,11 @@
|
||||
"help_title": "Help on Protected notes",
|
||||
"close_label": "Close",
|
||||
"form_label": "To proceed with requested action you need to start protected session by entering password:",
|
||||
"start_button": "Start protected session <kbd>enter</kbd>"
|
||||
"start_button": "Start protected session"
|
||||
},
|
||||
"recent_changes": {
|
||||
"title": "Recent changes",
|
||||
"erase_notes_button": "Erase deleted notes now",
|
||||
"close": "Close",
|
||||
"deleted_notes_message": "Deleted notes have been erased.",
|
||||
"no_changes_message": "No changes yet...",
|
||||
"undelete_link": "undelete",
|
||||
@@ -273,7 +259,6 @@
|
||||
"delete_all_revisions": "Delete all revisions of this note",
|
||||
"delete_all_button": "Delete all revisions",
|
||||
"help_title": "Help on Note Revisions",
|
||||
"close": "Close",
|
||||
"revision_last_edited": "This revision was last edited on {{date}}",
|
||||
"confirm_delete_all": "Do you want to delete all revisions of this note?",
|
||||
"no_revisions": "No revisions for this note yet...",
|
||||
@@ -295,7 +280,6 @@
|
||||
},
|
||||
"sort_child_notes": {
|
||||
"sort_children_by": "Sort children by...",
|
||||
"close": "Close",
|
||||
"sorting_criteria": "Sorting criteria",
|
||||
"title": "title",
|
||||
"date_created": "date created",
|
||||
@@ -309,13 +293,12 @@
|
||||
"sort_with_respect_to_different_character_sorting": "sort with respect to different character sorting and collation rules in different languages or regions.",
|
||||
"natural_sort_language": "Natural sort language",
|
||||
"the_language_code_for_natural_sort": "The language code for natural sort, e.g. \"zh-CN\" for Chinese.",
|
||||
"sort": "Sort <kbd>enter</kbd>"
|
||||
"sort": "Sort"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "Upload attachments to note",
|
||||
"close": "Close",
|
||||
"choose_files": "Choose files",
|
||||
"files_will_be_uploaded": "Files will be uploaded as attachments into",
|
||||
"files_will_be_uploaded": "Files will be uploaded as attachments into {{noteTitle}}",
|
||||
"options": "Options",
|
||||
"shrink_images": "Shrink images",
|
||||
"upload": "Upload",
|
||||
@@ -443,7 +426,8 @@
|
||||
"other_notes_with_name": "Other notes with {{attributeType}} name \"{{attributeName}}\"",
|
||||
"and_more": "... and {{count}} more.",
|
||||
"print_landscape": "When exporting to PDF, changes the orientation of the page to landscape instead of portrait.",
|
||||
"print_page_size": "When exporting to PDF, changes the size of the page. Supported values: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>."
|
||||
"print_page_size": "When exporting to PDF, changes the size of the page. Supported values: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
|
||||
"color_type": "Color"
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "To add label, just type e.g. <code>#rock</code> or if you want to add also value then e.g. <code>#year = 2020</code>",
|
||||
@@ -758,9 +742,12 @@
|
||||
"expand_all_children": "Expand all children",
|
||||
"collapse": "Collapse",
|
||||
"expand": "Expand",
|
||||
"book_properties": "Book Properties",
|
||||
"book_properties": "Collection Properties",
|
||||
"invalid_view_type": "Invalid view type '{{type}}'",
|
||||
"calendar": "Calendar"
|
||||
"calendar": "Calendar",
|
||||
"table": "Table",
|
||||
"geo-map": "Geo Map",
|
||||
"board": "Board"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "No edited notes on this day yet...",
|
||||
@@ -837,7 +824,8 @@
|
||||
"unknown_label_type": "Unknown label type '{{type}}'",
|
||||
"unknown_attribute_type": "Unknown attribute type '{{type}}'",
|
||||
"add_new_attribute": "Add new attribute",
|
||||
"remove_this_attribute": "Remove this attribute"
|
||||
"remove_this_attribute": "Remove this attribute",
|
||||
"remove_color": "Remove the color label"
|
||||
},
|
||||
"script_executor": {
|
||||
"query": "Query",
|
||||
@@ -960,7 +948,7 @@
|
||||
"no_attachments": "This note has no attachments."
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "This note of type Book doesn't have any child notes so there's nothing to display. See <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> for details."
|
||||
"no_children_help": "This collection doesn't have any child notes so there's nothing to display. See <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> for details."
|
||||
},
|
||||
"editable_code": {
|
||||
"placeholder": "Type the content of your code note here..."
|
||||
@@ -1023,7 +1011,7 @@
|
||||
"title": "Consistency Checks",
|
||||
"find_and_fix_button": "Find and fix consistency issues",
|
||||
"finding_and_fixing_message": "Finding and fixing consistency issues...",
|
||||
"issues_fixed_message": "Consistency issues should be fixed."
|
||||
"issues_fixed_message": "Any consistency issue which may have been found is now fixed."
|
||||
},
|
||||
"database_anonymization": {
|
||||
"title": "Database Anonymization",
|
||||
@@ -1113,18 +1101,24 @@
|
||||
"title": "Application Theme",
|
||||
"theme_label": "Theme",
|
||||
"override_theme_fonts_label": "Override theme fonts",
|
||||
"auto_theme": "Auto",
|
||||
"light_theme": "Light",
|
||||
"dark_theme": "Dark",
|
||||
"triliumnext": "TriliumNext Beta (Follow system color scheme)",
|
||||
"triliumnext-light": "TriliumNext Beta (Light)",
|
||||
"triliumnext-dark": "TriliumNext Beta (Dark)",
|
||||
"auto_theme": "Legacy (Follow system color scheme)",
|
||||
"light_theme": "Legacy (Light)",
|
||||
"dark_theme": "Legacy (Dark)",
|
||||
"triliumnext": "Trilium (Follow system color scheme)",
|
||||
"triliumnext-light": "Trilium (Light)",
|
||||
"triliumnext-dark": "Trilium (Dark)",
|
||||
"layout": "Layout",
|
||||
"layout-vertical-title": "Vertical",
|
||||
"layout-horizontal-title": "Horizontal",
|
||||
"layout-vertical-description": "launcher bar is on the left (default)",
|
||||
"layout-horizontal-description": "launcher bar is underneath the tab bar, the tab bar is now full width."
|
||||
},
|
||||
"ui-performance": {
|
||||
"title": "Performance",
|
||||
"enable-motion": "Enable transitions and animations",
|
||||
"enable-shadows": "Enable shadows",
|
||||
"enable-backdrop-effects": "Enable background effects for menus, popups and panels"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Not started",
|
||||
"title": "AI Settings",
|
||||
@@ -1265,7 +1259,12 @@
|
||||
"selected_provider": "Selected Provider",
|
||||
"selected_provider_description": "Choose the AI provider for chat and completion features",
|
||||
"select_model": "Select model...",
|
||||
"select_provider": "Select provider..."
|
||||
"select_provider": "Select provider...",
|
||||
"ai_enabled": "AI features enabled",
|
||||
"ai_disabled": "AI features disabled",
|
||||
"no_models_found_online": "No models found. Please check your API key and settings.",
|
||||
"no_models_found_ollama": "No Ollama models found. Please check if Ollama is running.",
|
||||
"error_fetching": "Error fetching models: {{error}}"
|
||||
},
|
||||
"zoom_factor": {
|
||||
"title": "Zoom Factor (desktop build only)",
|
||||
@@ -1322,7 +1321,7 @@
|
||||
},
|
||||
"revisions_snapshot_interval": {
|
||||
"note_revisions_snapshot_interval_title": "Note Revision Snapshot Interval",
|
||||
"note_revisions_snapshot_description": "The Note revision snapshot interval is the time after which a new note revision will be created for the note. See <a href=\"https://triliumnext.github.io/Docs/Wiki/note-revisions.html\" class=\"external\">wiki</a> for more info.",
|
||||
"note_revisions_snapshot_description": "The Note revision snapshot interval is the time after which a new note revision will be created for the note. See <doc>wiki</doc> for more info.",
|
||||
"snapshot_time_interval_label": "Note revision snapshot time interval:"
|
||||
},
|
||||
"revisions_snapshot_limit": {
|
||||
@@ -1384,7 +1383,7 @@
|
||||
},
|
||||
"custom_date_time_format": {
|
||||
"title": "Custom Date/Time Format",
|
||||
"description": "Customize the format of the date and time inserted via <kbd></kbd> or the toolbar. See <a href=\"https://day.js.org/docs/en/display/format\" target=\"_blank\" rel=\"noopener noreferrer\">Day.js docs</a> for available format tokens.",
|
||||
"description": "Customize the format of the date and time inserted via <shortcut /> or the toolbar. See <doc>Day.js docs</doc> for available format tokens.",
|
||||
"format_string": "Format string:",
|
||||
"formatted_time": "Formatted date/time:"
|
||||
},
|
||||
@@ -1593,12 +1592,13 @@
|
||||
"move-to": "Move to...",
|
||||
"paste-into": "Paste into",
|
||||
"paste-after": "Paste after",
|
||||
"duplicate-subtree": "Duplicate subtree",
|
||||
"duplicate": "Duplicate",
|
||||
"export": "Export",
|
||||
"import-into-note": "Import into note",
|
||||
"apply-bulk-actions": "Apply bulk actions",
|
||||
"converted-to-attachments": "{{count}} notes have been converted to attachments.",
|
||||
"convert-to-attachment-confirm": "Are you sure you want to convert note selected notes into attachments of their parent notes?"
|
||||
"convert-to-attachment-confirm": "Are you sure you want to convert note selected notes into attachments of their parent notes?",
|
||||
"open-in-popup": "Quick edit"
|
||||
},
|
||||
"shared_info": {
|
||||
"shared_publicly": "This note is shared publicly on",
|
||||
@@ -1612,7 +1612,7 @@
|
||||
"relation-map": "Relation Map",
|
||||
"note-map": "Note Map",
|
||||
"render-note": "Render Note",
|
||||
"book": "Book",
|
||||
"book": "Collection",
|
||||
"mermaid-diagram": "Mermaid Diagram",
|
||||
"canvas": "Canvas",
|
||||
"web-view": "Web View",
|
||||
@@ -1626,7 +1626,9 @@
|
||||
"geo-map": "Geo Map",
|
||||
"beta-feature": "Beta",
|
||||
"ai-chat": "AI Chat",
|
||||
"task-list": "Task List"
|
||||
"task-list": "Task List",
|
||||
"new-feature": "New",
|
||||
"collections": "Collections"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "Protect the note",
|
||||
@@ -1812,6 +1814,43 @@
|
||||
"multiline-toolbar": "Display the toolbar on multiple lines if it doesn't fit."
|
||||
}
|
||||
},
|
||||
"ckeditor_plugins": {
|
||||
"title": "Editor Plugins",
|
||||
"description": "Configure which CKEditor plugins are enabled. Changes take effect when the editor is reloaded.",
|
||||
"loading": "Loading plugin configuration...",
|
||||
"load_failed": "Failed to load plugin configuration.",
|
||||
"load_error": "Error loading plugins",
|
||||
"retry": "Retry",
|
||||
"category_formatting": "Text Formatting",
|
||||
"category_structure": "Document Structure",
|
||||
"category_media": "Media & Files",
|
||||
"category_tables": "Tables",
|
||||
"category_advanced": "Advanced Features",
|
||||
"category_trilium": "Trilium Features",
|
||||
"category_external": "External Plugins",
|
||||
"stats_enabled": "Enabled",
|
||||
"stats_total": "Total",
|
||||
"stats_core": "Core",
|
||||
"stats_premium": "Premium",
|
||||
"no_license": "no license",
|
||||
"premium": "Premium",
|
||||
"premium_required": "Requires premium CKEditor license",
|
||||
"has_dependencies": "Dependencies",
|
||||
"depends_on": "Depends on",
|
||||
"toolbar_items": "Toolbar items",
|
||||
"validate": "Validate",
|
||||
"validation_error": "Validation failed",
|
||||
"validation_errors": "Configuration Errors:",
|
||||
"validation_warnings": "Configuration Warnings:",
|
||||
"save": "Save Changes",
|
||||
"save_success": "Plugin configuration saved successfully",
|
||||
"save_error": "Failed to save configuration",
|
||||
"reload_editor_notice": "Please reload any open text notes to apply changes",
|
||||
"reset_defaults": "Reset to Defaults",
|
||||
"reset_confirm": "Are you sure you want to reset all plugin settings to their default values?",
|
||||
"reset_success": "Plugin configuration reset to defaults",
|
||||
"reset_error": "Failed to reset configuration"
|
||||
},
|
||||
"electron_context_menu": {
|
||||
"add-term-to-dictionary": "Add \"{{term}}\" to dictionary",
|
||||
"cut": "Cut",
|
||||
@@ -1828,7 +1867,8 @@
|
||||
"link_context_menu": {
|
||||
"open_note_in_new_tab": "Open note in a new tab",
|
||||
"open_note_in_new_split": "Open note in a new split",
|
||||
"open_note_in_new_window": "Open note in a new window"
|
||||
"open_note_in_new_window": "Open note in a new window",
|
||||
"open_note_in_popup": "Quick edit"
|
||||
},
|
||||
"electron_integration": {
|
||||
"desktop-application": "Desktop Application",
|
||||
@@ -1848,7 +1888,8 @@
|
||||
"full-text-search": "Full text search"
|
||||
},
|
||||
"note_tooltip": {
|
||||
"note-has-been-deleted": "Note has been deleted."
|
||||
"note-has-been-deleted": "Note has been deleted.",
|
||||
"quick-edit": "Quick edit"
|
||||
},
|
||||
"geo-map": {
|
||||
"create-child-note-title": "Create a new child note and add it to the map",
|
||||
@@ -1857,7 +1898,8 @@
|
||||
},
|
||||
"geo-map-context": {
|
||||
"open-location": "Open location",
|
||||
"remove-from-map": "Remove from map"
|
||||
"remove-from-map": "Remove from map",
|
||||
"add-note": "Add a marker at this location"
|
||||
},
|
||||
"help-button": {
|
||||
"title": "Open the relevant help page"
|
||||
@@ -1933,5 +1975,89 @@
|
||||
"title": "Features",
|
||||
"emoji_completion_enabled": "Enable Emoji auto-completion",
|
||||
"note_completion_enabled": "Enable note auto-completion"
|
||||
},
|
||||
"table_view": {
|
||||
"new-row": "New row",
|
||||
"new-column": "New column",
|
||||
"sort-column-by": "Sort by \"{{title}}\"",
|
||||
"sort-column-ascending": "Ascending",
|
||||
"sort-column-descending": "Descending",
|
||||
"sort-column-clear": "Clear sorting",
|
||||
"hide-column": "Hide column \"{{title}}\"",
|
||||
"show-hide-columns": "Show/hide columns",
|
||||
"row-insert-above": "Insert row above",
|
||||
"row-insert-below": "Insert row below",
|
||||
"row-insert-child": "Insert child note",
|
||||
"add-column-to-the-left": "Add column to the left",
|
||||
"add-column-to-the-right": "Add column to the right",
|
||||
"edit-column": "Edit column",
|
||||
"delete_column_confirmation": "Are you sure you want to delete this column? The corresponding attribute will be removed from all notes.",
|
||||
"delete-column": "Delete column",
|
||||
"new-column-label": "Label",
|
||||
"new-column-relation": "Relation"
|
||||
},
|
||||
"book_properties_config": {
|
||||
"hide-weekends": "Hide weekends",
|
||||
"display-week-numbers": "Display week numbers",
|
||||
"map-style": "Map style:",
|
||||
"max-nesting-depth": "Max nesting depth:",
|
||||
"raster": "Raster",
|
||||
"vector_light": "Vector (Light)",
|
||||
"vector_dark": "Vector (Dark)",
|
||||
"show-scale": "Show scale"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "Delete row"
|
||||
},
|
||||
"board_view": {
|
||||
"delete-note": "Delete Note",
|
||||
"move-to": "Move to",
|
||||
"insert-above": "Insert above",
|
||||
"insert-below": "Insert below",
|
||||
"delete-column": "Delete column",
|
||||
"delete-column-confirmation": "Are you sure you want to delete this column? The corresponding attribute will be deleted in the notes under this column as well.",
|
||||
"new-item": "New item",
|
||||
"add-column": "Add Column"
|
||||
},
|
||||
"command_palette": {
|
||||
"tree-action-name": "Tree: {{name}}",
|
||||
"export_note_title": "Export Note",
|
||||
"export_note_description": "Export current note",
|
||||
"show_attachments_title": "Show Attachments",
|
||||
"show_attachments_description": "View note attachments",
|
||||
"search_notes_title": "Search Notes",
|
||||
"search_notes_description": "Open advanced search",
|
||||
"search_subtree_title": "Search in Subtree",
|
||||
"search_subtree_description": "Search within current subtree",
|
||||
"search_history_title": "Show Search History",
|
||||
"search_history_description": "View previous searches",
|
||||
"configure_launch_bar_title": "Configure Launch Bar",
|
||||
"configure_launch_bar_description": "Open the launch bar configuration, to add or remove items."
|
||||
},
|
||||
"content_renderer": {
|
||||
"open_externally": "Open externally"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Close",
|
||||
"help_title": "Display more information about this screen"
|
||||
},
|
||||
"call_to_action": {
|
||||
"next_theme_title": "Try the new Trilium theme",
|
||||
"next_theme_message": "You are currently using the legacy theme, would you like to try the new theme?",
|
||||
"next_theme_button": "Try the new theme",
|
||||
"background_effects_title": "Background effects are now stable",
|
||||
"background_effects_message": "On Windows devices, background effects are now fully stable. The background effects adds a touch of color to the user interface by blurring the background behind it. This technique is also used in other applications such as Windows Explorer.",
|
||||
"background_effects_button": "Enable background effects",
|
||||
"dismiss": "Dismiss"
|
||||
},
|
||||
"settings": {
|
||||
"related_settings": "Related settings"
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "Color scheme for code blocks in text notes",
|
||||
"related_code_notes": "Color scheme for code notes"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "Acerca de Trilium Notes",
|
||||
"close": "Cerrar",
|
||||
"homepage": "Página principal:",
|
||||
"app_version": "Versión de la aplicación:",
|
||||
"db_version": "Versión de base de datos:",
|
||||
@@ -28,25 +27,22 @@
|
||||
"add_link": {
|
||||
"add_link": "Agregar enlace",
|
||||
"help_on_links": "Ayuda sobre enlaces",
|
||||
"close": "Cerrar",
|
||||
"note": "Nota",
|
||||
"search_note": "buscar nota por su nombre",
|
||||
"link_title_mirrors": "el título del enlace replica el título actual de la nota",
|
||||
"link_title_arbitrary": "el título del enlace se puede cambiar arbitrariamente",
|
||||
"link_title": "Título del enlace",
|
||||
"button_add_link": "Agregar enlace <kbd>Enter</kbd>"
|
||||
"button_add_link": "Agregar enlace"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"edit_branch_prefix": "Editar prefijo de rama",
|
||||
"help_on_tree_prefix": "Ayuda sobre el prefijo del árbol",
|
||||
"close": "Cerrar",
|
||||
"prefix": "Prefijo: ",
|
||||
"save": "Guardar",
|
||||
"branch_prefix_saved": "Se ha guardado el prefijo de rama."
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "Acciones en bloque",
|
||||
"close": "Cerrar",
|
||||
"affected_notes": "Notas afectadas",
|
||||
"include_descendants": "Incluir descendientes de las notas seleccionadas",
|
||||
"available_actions": "Acciones disponibles",
|
||||
@@ -61,20 +57,18 @@
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "Clonar notas a...",
|
||||
"close": "Cerrar",
|
||||
"help_on_links": "Ayuda sobre enlaces",
|
||||
"notes_to_clone": "Notas a clonar",
|
||||
"target_parent_note": "Nota padre de destino",
|
||||
"search_for_note_by_its_name": "buscar nota por su nombre",
|
||||
"cloned_note_prefix_title": "La nota clonada se mostrará en el árbol de notas con el prefijo dado",
|
||||
"prefix_optional": "Prefijo (opcional)",
|
||||
"clone_to_selected_note": "Clonar a nota seleccionada <kbd>enter</kbd>",
|
||||
"clone_to_selected_note": "Clonar a nota seleccionada",
|
||||
"no_path_to_clone_to": "No hay ruta para clonar.",
|
||||
"note_cloned": "La nota \"{{clonedTitle}}\" a sido clonada en \"{{targetTitle}}\""
|
||||
},
|
||||
"confirm": {
|
||||
"confirmation": "Confirmación",
|
||||
"close": "Cerrar",
|
||||
"cancel": "Cancelar",
|
||||
"ok": "Aceptar",
|
||||
"are_you_sure_remove_note": "¿Está seguro que desea eliminar la nota \"{{title}}\" del mapa de relaciones? ",
|
||||
@@ -87,9 +81,9 @@
|
||||
"delete_all_clones_description": "Eliminar también todos los clones (se puede deshacer en cambios recientes)",
|
||||
"erase_notes_description": "La eliminación normal (suave) solo marca las notas como eliminadas y se pueden recuperar (en el cuadro de diálogo de cambios recientes) dentro de un periodo de tiempo. Al marcar esta opción se borrarán las notas inmediatamente y no será posible recuperarlas.",
|
||||
"erase_notes_warning": "Eliminar notas permanentemente (no se puede deshacer), incluidos todos los clones. Esto forzará la recarga de la aplicación.",
|
||||
"notes_to_be_deleted": "Las siguientes notas serán eliminadas ({{- noteCount}})",
|
||||
"notes_to_be_deleted": "Las siguientes notas serán eliminadas ({{notesCount}})",
|
||||
"no_note_to_delete": "No se eliminará ninguna nota (solo clones).",
|
||||
"broken_relations_to_be_deleted": "Las siguientes relaciones se romperán y serán eliminadas ({{- relationCount}})",
|
||||
"broken_relations_to_be_deleted": "Las siguientes relaciones se romperán y serán eliminadas ({{ relationCount}})",
|
||||
"cancel": "Cancelar",
|
||||
"ok": "Aceptar",
|
||||
"deleted_relation_text": "Nota {{- note}} (para ser eliminada) está referenciado por la relación {{- relation}} que se origina en {{- source}}."
|
||||
@@ -113,21 +107,19 @@
|
||||
"format_pdf": "PDF - para propósitos de impresión o compartición."
|
||||
},
|
||||
"help": {
|
||||
"fullDocumentation": "Ayuda (la documentación completa está disponible <a class=\"external\" href=\"https://triliumnext.github.io/Docs/\">online</a>)",
|
||||
"close": "Cerrar",
|
||||
"noteNavigation": "Navegación de notas",
|
||||
"goUpDown": "<kbd>UP</kbd>, <kbd>DOWN</kbd> - subir/bajar en la lista de notas",
|
||||
"collapseExpand": "<kbd>LEFT</kbd>, <kbd>RIGHT</kbd> - colapsar/expandir nodo",
|
||||
"goUpDown": "subir/bajar en la lista de notas",
|
||||
"collapseExpand": "colapsar/expandir nodo",
|
||||
"notSet": "no establecido",
|
||||
"goBackForwards": "retroceder / avanzar en la historia",
|
||||
"showJumpToNoteDialog": "mostrar <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"Saltar a\" diálogo</a>",
|
||||
"scrollToActiveNote": "desplazarse hasta la nota activa",
|
||||
"jumpToParentNote": "<kbd>Backspace</kbd> - saltar a la nota padre",
|
||||
"jumpToParentNote": "saltar a la nota padre",
|
||||
"collapseWholeTree": "colapsar todo el árbol de notas",
|
||||
"collapseSubTree": "colapsar subárbol",
|
||||
"tabShortcuts": "Atajos de pestañas",
|
||||
"newTabNoteLink": "<kbd>CTRL+clic</kbd> - (o clic central del mouse) en el enlace de la nota abre la nota en una nueva pestaña",
|
||||
"newTabWithActivationNoteLink": "<kbd>Ctrl+Shift+clic</kbd> - (o <kbd>Shift+clic de rueda de ratón</kbd>) en el enlace de la nota abre y activa la nota en una nueva pestaña",
|
||||
"newTabNoteLink": "en el enlace de la nota abre la nota en una nueva pestaña",
|
||||
"newTabWithActivationNoteLink": "en el enlace de la nota abre y activa la nota en una nueva pestaña",
|
||||
"onlyInDesktop": "Solo en escritorio (compilación con Electron)",
|
||||
"openEmptyTab": "abrir pestaña vacía",
|
||||
"closeActiveTab": "cerrar pestaña activa",
|
||||
@@ -142,14 +134,14 @@
|
||||
"moveNoteUpHierarchy": "mover nota hacia arriba en la jerarquía",
|
||||
"multiSelectNote": "selección múltiple de nota hacia arriba/abajo",
|
||||
"selectAllNotes": "seleccionar todas las notas en el nivel actual",
|
||||
"selectNote": "<kbd>Shift+click</kbd> - seleccionar nota",
|
||||
"selectNote": "seleccionar nota",
|
||||
"copyNotes": "copiar nota activa (o selección actual) al portapapeles (usado para <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/cloning-notes.html#cloning-notes\">clonar</a>)",
|
||||
"cutNotes": "cortar la nota actual (o la selección actual) en el portapapeles (usado para mover notas)",
|
||||
"pasteNotes": "pegar notas como subnotas en la nota activa (que se puede mover o clonar dependiendo de si se copió o cortó en el portapapeles)",
|
||||
"deleteNotes": "eliminar nota/subárbol",
|
||||
"editingNotes": "Editando notas",
|
||||
"editNoteTitle": "en el panel de árbol cambiará del panel de árbol al título de la nota. Ingresar desde el título de la nota cambiará el foco al editor de texto. <kbd>Ctrl+.</kbd> cambiará de nuevo del editor al panel de árbol.",
|
||||
"createEditLink": "<kbd>Ctrl+K</kbd> - crear/editar enlace externo",
|
||||
"createEditLink": "crear/editar enlace externo",
|
||||
"createInternalLink": "crear enlace interno",
|
||||
"followLink": "siga el enlace debajo del cursor",
|
||||
"insertDateTime": "insertar la fecha y hora actuales en la posición del cursor",
|
||||
@@ -165,11 +157,11 @@
|
||||
"showSQLConsole": "mostrar consola SQL",
|
||||
"other": "Otro",
|
||||
"quickSearch": "centrarse en la entrada de búsqueda rápida",
|
||||
"inPageSearch": "búsqueda en la página"
|
||||
"inPageSearch": "búsqueda en la página",
|
||||
"title": "Hoja de ayuda"
|
||||
},
|
||||
"import": {
|
||||
"importIntoNote": "Importar a nota",
|
||||
"close": "Cerrar",
|
||||
"chooseImportFile": "Elija el archivo de importación",
|
||||
"importDescription": "El contenido de los archivos seleccionados se importará como notas secundarias en",
|
||||
"options": "Opciones",
|
||||
@@ -196,14 +188,13 @@
|
||||
},
|
||||
"include_note": {
|
||||
"dialog_title": "Incluir nota",
|
||||
"close": "Cerrar",
|
||||
"label_note": "Nota",
|
||||
"placeholder_search": "buscar nota por su nombre",
|
||||
"box_size_prompt": "Tamaño de caja de la nota incluida:",
|
||||
"box_size_small": "pequeño (~ 10 líneas)",
|
||||
"box_size_medium": "medio (~ 30 líneas)",
|
||||
"box_size_full": "completo (el cuadro muestra el texto completo)",
|
||||
"button_include": "Incluir nota <kbd>Enter</kbd>"
|
||||
"button_include": "Incluir nota"
|
||||
},
|
||||
"info": {
|
||||
"modalTitle": "Mensaje informativo",
|
||||
@@ -211,24 +202,21 @@
|
||||
"okButton": "Aceptar"
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_placeholder": "buscar nota por su nombre",
|
||||
"close": "Cerrar",
|
||||
"search_button": "Buscar en texto completo <kbd>Ctrl+Enter</kbd>"
|
||||
"search_button": "Buscar en texto completo",
|
||||
"search_placeholder": "Busque nota por su nombre o escriba > para comandos..."
|
||||
},
|
||||
"markdown_import": {
|
||||
"dialog_title": "Importación de Markdown",
|
||||
"close": "Cerrar",
|
||||
"modal_body_text": "Debido al entorno limitado del navegador, no es posible leer directamente el portapapeles desde JavaScript. Por favor, pegue el código Markdown para importar en el área de texto a continuación y haga clic en el botón Importar",
|
||||
"import_button": "Importar Ctrl+Enter",
|
||||
"import_button": "Importar",
|
||||
"import_success": "El contenido de Markdown se ha importado al documento."
|
||||
},
|
||||
"move_to": {
|
||||
"dialog_title": "Mover notas a...",
|
||||
"close": "Cerrar",
|
||||
"notes_to_move": "Notas a mover",
|
||||
"target_parent_note": "Nota padre de destino",
|
||||
"search_placeholder": "buscar nota por su nombre",
|
||||
"move_button": "Mover a la nota seleccionada <kbd>enter</kbd>",
|
||||
"move_button": "Mover a la nota seleccionada",
|
||||
"error_no_path": "No hay ruta a donde mover.",
|
||||
"move_success_message": "Las notas seleccionadas se han movido a "
|
||||
},
|
||||
@@ -236,20 +224,19 @@
|
||||
"change_path_prompt": "Cambiar donde se creará la nueva nota:",
|
||||
"search_placeholder": "ruta de búsqueda por nombre (por defecto si está vacío)",
|
||||
"modal_title": "Elija el tipo de nota",
|
||||
"close": "Cerrar",
|
||||
"modal_body": "Elija el tipo de nota/plantilla de la nueva nota:",
|
||||
"templates": "Plantillas:"
|
||||
"templates": "Plantillas",
|
||||
"builtin_templates": "Plantillas incluidas"
|
||||
},
|
||||
"password_not_set": {
|
||||
"title": "La contraseña no está establecida",
|
||||
"close": "Cerrar",
|
||||
"body1": "Las notas protegidas se cifran mediante una contraseña de usuario, pero la contraseña aún no se ha establecido.",
|
||||
"body2": "Para poder proteger notas, dé clic <a class=\"open-password-options-button\" href=\"javascript:\">aquí</a> para abrir el diálogo de Opciones y establecer tu contraseña."
|
||||
"go_to_password_options": "Ir a opciones de contraseña",
|
||||
"body2": "Para poder proteger las notas, haz click en el botón inferior para abrir la pantalla de Opciones y establecer tu contraseña."
|
||||
},
|
||||
"prompt": {
|
||||
"title": "Aviso",
|
||||
"close": "Cerrar",
|
||||
"ok": "Aceptar <kbd>enter</kbd>",
|
||||
"ok": "Aceptar",
|
||||
"defaultTitle": "Aviso"
|
||||
},
|
||||
"protected_session_password": {
|
||||
@@ -257,12 +244,11 @@
|
||||
"help_title": "Ayuda sobre notas protegidas",
|
||||
"close_label": "Cerrar",
|
||||
"form_label": "Para continuar con la acción solicitada, debe iniciar en la sesión protegida ingresando la contraseña:",
|
||||
"start_button": "Iniciar sesión protegida <kbd>entrar</kbd>"
|
||||
"start_button": "Iniciar sesión protegida"
|
||||
},
|
||||
"recent_changes": {
|
||||
"title": "Cambios recientes",
|
||||
"erase_notes_button": "Borrar notas eliminadas ahora",
|
||||
"close": "Cerrar",
|
||||
"deleted_notes_message": "Las notas eliminadas han sido borradas.",
|
||||
"no_changes_message": "Aún no hay cambios...",
|
||||
"undelete_link": "recuperar",
|
||||
@@ -273,7 +259,6 @@
|
||||
"delete_all_revisions": "Eliminar todas las revisiones de esta nota",
|
||||
"delete_all_button": "Eliminar todas las revisiones",
|
||||
"help_title": "Ayuda sobre revisiones de notas",
|
||||
"close": "Cerrar",
|
||||
"revision_last_edited": "Esta revisión se editó por última vez en {{date}}",
|
||||
"confirm_delete_all": "¿Quiere eliminar todas las revisiones de esta nota?",
|
||||
"no_revisions": "Aún no hay revisiones para esta nota...",
|
||||
@@ -295,7 +280,6 @@
|
||||
},
|
||||
"sort_child_notes": {
|
||||
"sort_children_by": "Ordenar hijos por...",
|
||||
"close": "Cerrar",
|
||||
"sorting_criteria": "Criterios de ordenamiento",
|
||||
"title": "título",
|
||||
"date_created": "fecha de creación",
|
||||
@@ -309,13 +293,12 @@
|
||||
"sort_with_respect_to_different_character_sorting": "ordenar con respecto a diferentes reglas de ordenamiento y clasificación de caracteres en diferentes idiomas o regiones.",
|
||||
"natural_sort_language": "Idioma de clasificación natural",
|
||||
"the_language_code_for_natural_sort": "El código del idioma para el ordenamiento natural, ej. \"zh-CN\" para Chino.",
|
||||
"sort": "Ordenar <kbd>Enter</kbd>"
|
||||
"sort": "Ordenar"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "Cargar archivos adjuntos a nota",
|
||||
"close": "Cerrar",
|
||||
"choose_files": "Elija los archivos",
|
||||
"files_will_be_uploaded": "Los archivos se cargarán como archivos adjuntos en",
|
||||
"files_will_be_uploaded": "Los archivos se cargarán como archivos adjuntos en {{noteTitle}}",
|
||||
"options": "Opciones",
|
||||
"shrink_images": "Reducir imágenes",
|
||||
"upload": "Subir",
|
||||
@@ -443,7 +426,8 @@
|
||||
"other_notes_with_name": "Otras notas con nombre de {{attributeType}} \"{{attributeName}}\"",
|
||||
"and_more": "... y {{count}} más.",
|
||||
"print_landscape": "Al exportar a PDF, cambia la orientación de la página a paisaje en lugar de retrato.",
|
||||
"print_page_size": "Al exportar a PDF, cambia el tamaño de la página. Valores soportados: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>."
|
||||
"print_page_size": "Al exportar a PDF, cambia el tamaño de la página. Valores soportados: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
|
||||
"color_type": "Color"
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "Para agregar una etiqueta, simplemente escriba, por ejemplo. <code>#rock</code> o si desea agregar también valor, p.e. <code>#año = 2020</code>",
|
||||
@@ -758,9 +742,12 @@
|
||||
"expand_all_children": "Ampliar todas las subnotas",
|
||||
"collapse": "Colapsar",
|
||||
"expand": "Expandir",
|
||||
"book_properties": "Propiedades del libro",
|
||||
"invalid_view_type": "Tipo de vista inválida '{{type}}'",
|
||||
"calendar": "Calendario"
|
||||
"calendar": "Calendario",
|
||||
"book_properties": "Propiedades de colección",
|
||||
"table": "Tabla",
|
||||
"geo-map": "Mapa Geo",
|
||||
"board": "Tablero"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "Aún no hay notas editadas en este día...",
|
||||
@@ -837,7 +824,8 @@
|
||||
"unknown_label_type": "Tipo de etiqueta desconocido '{{type}}'",
|
||||
"unknown_attribute_type": "Tipo de atributo desconocido '{{type}}'",
|
||||
"add_new_attribute": "Agregar nuevo atributo",
|
||||
"remove_this_attribute": "Eliminar este atributo"
|
||||
"remove_this_attribute": "Eliminar este atributo",
|
||||
"remove_color": "Eliminar la etiqueta del color"
|
||||
},
|
||||
"script_executor": {
|
||||
"query": "Consulta",
|
||||
@@ -1113,17 +1101,17 @@
|
||||
"title": "Tema",
|
||||
"theme_label": "Tema",
|
||||
"override_theme_fonts_label": "Sobreescribir fuentes de tema",
|
||||
"auto_theme": "Automático",
|
||||
"light_theme": "Claro",
|
||||
"dark_theme": "Oscuro",
|
||||
"triliumnext": "TriliumNext Beta (Sigue el esquema de color del sistema)",
|
||||
"triliumnext-light": "TriliumNext Beta (Claro)",
|
||||
"triliumnext-dark": "TriliumNext Beta (Oscuro)",
|
||||
"triliumnext": "Trilium (Sigue el esquema de color del sistema)",
|
||||
"triliumnext-light": "Trilium (Claro)",
|
||||
"triliumnext-dark": "Trilium (Oscuro)",
|
||||
"layout": "Disposición",
|
||||
"layout-vertical-title": "Vertical",
|
||||
"layout-horizontal-title": "Horizontal",
|
||||
"layout-vertical-description": "la barra del lanzador está en la izquierda (por defecto)",
|
||||
"layout-horizontal-description": "la barra de lanzamiento está debajo de la barra de pestañas, la barra de pestañas ahora tiene ancho completo."
|
||||
"layout-horizontal-description": "la barra de lanzamiento está debajo de la barra de pestañas, la barra de pestañas ahora tiene ancho completo.",
|
||||
"auto_theme": "Heredado (Sigue el esquema de colores del sistema)",
|
||||
"light_theme": "Heredado (Claro)",
|
||||
"dark_theme": "Heredado (Oscuro)"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "No iniciado",
|
||||
@@ -1322,7 +1310,7 @@
|
||||
},
|
||||
"revisions_snapshot_interval": {
|
||||
"note_revisions_snapshot_interval_title": "Intervalo de instantáneas de revisiones de notas",
|
||||
"note_revisions_snapshot_description": "El intervalo de tiempo de la instantánea de revisión de nota es el tiempo después de lo cual se creará una nueva revisión para la nota. Ver <a href=\"https://triliumnext.github.io/docs/wiki/note-revisions.html\" class=\"external\"> wiki </a> para obtener más información.",
|
||||
"note_revisions_snapshot_description": "El intervalo de tiempo de la instantánea de revisión de nota es el tiempo después de lo cual se creará una nueva revisión para la nota. Ver <doc>wiki</doc> para obtener más información.",
|
||||
"snapshot_time_interval_label": "Intervalo de tiempo de la instantánea de revisión de notas:"
|
||||
},
|
||||
"revisions_snapshot_limit": {
|
||||
@@ -1384,7 +1372,7 @@
|
||||
},
|
||||
"custom_date_time_format": {
|
||||
"title": "Formato de fecha/hora personalizada",
|
||||
"description": "Personalizar el formado de fecha y la hora insertada vía <kbd></kbd> o la barra de herramientas. Véa la <a href=\"https://day.js.org/docs/en/display/format\" target=\"_blank\" rel=\"noopener noreferrer\">documentación de Day.js</a> para más tokens de formato disponibles.",
|
||||
"description": "Personalizar el formado de fecha y la hora insertada vía <shortcut /> o la barra de herramientas. Véa la <doc>documentación de Day.js</doc> para más tokens de formato disponibles.",
|
||||
"format_string": "Cadena de formato:",
|
||||
"formatted_time": "Fecha/hora personalizada:"
|
||||
},
|
||||
@@ -1593,12 +1581,13 @@
|
||||
"move-to": "Mover a...",
|
||||
"paste-into": "Pegar en",
|
||||
"paste-after": "Pegar después de",
|
||||
"duplicate-subtree": "Duplicar subárbol",
|
||||
"duplicate": "Duplicar",
|
||||
"export": "Exportar",
|
||||
"import-into-note": "Importar a nota",
|
||||
"apply-bulk-actions": "Aplicar acciones en lote",
|
||||
"converted-to-attachments": "{{count}} notas han sido convertidas en archivos adjuntos.",
|
||||
"convert-to-attachment-confirm": "¿Está seguro que desea convertir las notas seleccionadas en archivos adjuntos de sus notas padres?"
|
||||
"convert-to-attachment-confirm": "¿Está seguro que desea convertir las notas seleccionadas en archivos adjuntos de sus notas padres?",
|
||||
"open-in-popup": "Edición rápida"
|
||||
},
|
||||
"shared_info": {
|
||||
"shared_publicly": "Esta nota está compartida públicamente en",
|
||||
@@ -1612,7 +1601,6 @@
|
||||
"relation-map": "Mapa de Relaciones",
|
||||
"note-map": "Mapa de Notas",
|
||||
"render-note": "Nota de Renderizado",
|
||||
"book": "Libro",
|
||||
"mermaid-diagram": "Diagrama Mermaid",
|
||||
"canvas": "Lienzo",
|
||||
"web-view": "Vista Web",
|
||||
@@ -1626,7 +1614,10 @@
|
||||
"geo-map": "Mapa Geo",
|
||||
"beta-feature": "Beta",
|
||||
"ai-chat": "Chat de IA",
|
||||
"task-list": "Lista de tareas"
|
||||
"task-list": "Lista de tareas",
|
||||
"book": "Colección",
|
||||
"new-feature": "Nuevo",
|
||||
"collections": "Colecciones"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "Proteger la nota",
|
||||
@@ -1828,7 +1819,8 @@
|
||||
"link_context_menu": {
|
||||
"open_note_in_new_tab": "Abrir nota en una pestaña nueva",
|
||||
"open_note_in_new_split": "Abrir nota en una nueva división",
|
||||
"open_note_in_new_window": "Abrir nota en una nueva ventana"
|
||||
"open_note_in_new_window": "Abrir nota en una nueva ventana",
|
||||
"open_note_in_popup": "Edición rápida"
|
||||
},
|
||||
"electron_integration": {
|
||||
"desktop-application": "Aplicación de escritorio",
|
||||
@@ -1848,7 +1840,8 @@
|
||||
"full-text-search": "Búsqueda de texto completo"
|
||||
},
|
||||
"note_tooltip": {
|
||||
"note-has-been-deleted": "La nota ha sido eliminada."
|
||||
"note-has-been-deleted": "La nota ha sido eliminada.",
|
||||
"quick-edit": "Edición rápida"
|
||||
},
|
||||
"geo-map": {
|
||||
"create-child-note-title": "Crear una nueva subnota y agregarla al mapa",
|
||||
@@ -1857,7 +1850,8 @@
|
||||
},
|
||||
"geo-map-context": {
|
||||
"open-location": "Abrir ubicación",
|
||||
"remove-from-map": "Eliminar del mapa"
|
||||
"remove-from-map": "Eliminar del mapa",
|
||||
"add-note": "Agregar un marcador en esta ubicación"
|
||||
},
|
||||
"help-button": {
|
||||
"title": "Abrir la página de ayuda relevante"
|
||||
@@ -1928,5 +1922,84 @@
|
||||
"download_link": "Descargar versión nativa",
|
||||
"continue_anyway": "Continuar de todas maneras",
|
||||
"dont_show_again": "No mostrar esta advertencia otra vez"
|
||||
},
|
||||
"book_properties_config": {
|
||||
"hide-weekends": "Ocultar fines de semana",
|
||||
"show-scale": "Mostrar escala",
|
||||
"display-week-numbers": "Mostrar números de semana",
|
||||
"map-style": "Estilo de mapa:",
|
||||
"max-nesting-depth": "Máxima profundidad de anidamiento:",
|
||||
"vector_light": "Vector (claro)",
|
||||
"vector_dark": "Vector (oscuro)",
|
||||
"raster": "Trama"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "Eliminar fila"
|
||||
},
|
||||
"board_view": {
|
||||
"delete-note": "Eliminar nota",
|
||||
"move-to": "Mover a",
|
||||
"insert-above": "Insertar arriba",
|
||||
"insert-below": "Insertar abajo",
|
||||
"delete-column": "Eliminar columna",
|
||||
"delete-column-confirmation": "¿Seguro que desea eliminar esta columna? El atributo correspondiente también se eliminará de las notas de esta columna.",
|
||||
"add-column": "Añadir columna",
|
||||
"new-item": "Nuevo elemento"
|
||||
},
|
||||
"content_renderer": {
|
||||
"open_externally": "Abrir externamente"
|
||||
},
|
||||
"table_view": {
|
||||
"new-column": "Nueva columna",
|
||||
"new-row": "Nueva fila",
|
||||
"show-hide-columns": "Mostrar/ocultar columnas",
|
||||
"row-insert-above": "Insertar fila arriba",
|
||||
"row-insert-below": "Insertar fila debajo",
|
||||
"sort-column-by": "Ordenar por \"{{title}}\"",
|
||||
"sort-column-ascending": "Ascendiente",
|
||||
"sort-column-descending": "Descendiente",
|
||||
"sort-column-clear": "Quitar ordenación",
|
||||
"hide-column": "Ocultar columna \"{{title}}\"",
|
||||
"add-column-to-the-left": "Añadir columna a la izquierda",
|
||||
"add-column-to-the-right": "Añadir columna a la derecha",
|
||||
"edit-column": "Editar columna",
|
||||
"delete_column_confirmation": "¿Seguro que desea eliminar esta columna? Se eliminará el atributo asociado de todas las notas.",
|
||||
"new-column-label": "Etiqueta",
|
||||
"new-column-relation": "Relación",
|
||||
"delete-column": "Eliminar columna",
|
||||
"row-insert-child": "Insertar subnota"
|
||||
},
|
||||
"editorfeatures": {
|
||||
"note_completion_enabled": "Activar autocompletado de notas",
|
||||
"emoji_completion_enabled": "Activar autocompletado de emojis",
|
||||
"title": "Funciones"
|
||||
},
|
||||
"command_palette": {
|
||||
"tree-action-name": "Árbol:{{name}}",
|
||||
"export_note_title": "Exportar nota",
|
||||
"export_note_description": "Exportar nota actual",
|
||||
"show_attachments_title": "Mostrar adjuntos",
|
||||
"show_attachments_description": "Ver adjuntos de la nota",
|
||||
"search_notes_title": "Buscar notas",
|
||||
"search_notes_description": "Abrir búsqueda avanzada",
|
||||
"search_subtree_title": "Buscar en subárbol",
|
||||
"search_subtree_description": "Buscar dentro del subárbol actual",
|
||||
"search_history_title": "Mostrar historial de búsqueda",
|
||||
"search_history_description": "Ver búsquedas previas",
|
||||
"configure_launch_bar_title": "Configurar barra de inicio",
|
||||
"configure_launch_bar_description": "Abrir la configuración de la barra de inicio, para agregar o quitar elementos."
|
||||
},
|
||||
"modal": {
|
||||
"close": "Cerrar",
|
||||
"help_title": "Mostrar más información sobre esta pantalla"
|
||||
},
|
||||
"call_to_action": {
|
||||
"next_theme_title": "Prueba el nuevo tema de Trilium",
|
||||
"next_theme_message": "Estas usando actualmente el tema heredado, ¿Te gustaría probar el nuevo tema?",
|
||||
"next_theme_button": "Prueba el nuevo tema",
|
||||
"background_effects_title": "Los efectos de fondo son ahora estables",
|
||||
"background_effects_message": "En los dispositivos Windows, los efectos de fondo ya son totalmente estables. Los efectos de fondo añaden un toque de color a la interfaz de usuario difuminando el fondo que hay detrás. Esta técnica también se utiliza en otras aplicaciones como el Explorador de Windows.",
|
||||
"background_effects_button": "Activar efectos de fondo",
|
||||
"dismiss": "Desestimar"
|
||||
}
|
||||
}
|
||||
|
||||
22
apps/client/src/translations/fa/translation.json
Normal file
22
apps/client/src/translations/fa/translation.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "درباره Trilium Notes",
|
||||
"homepage": "صفحه اصلی:",
|
||||
"app_version": "نسخه برنامه:",
|
||||
"db_version": "نسخه پایگاه داده:",
|
||||
"sync_version": "نسخه منطبق:",
|
||||
"build_date": "تاریخ ساخت:",
|
||||
"build_revision": "نسخه بازنگری شده:",
|
||||
"data_directory": "دایرکتوری داده:"
|
||||
},
|
||||
"toast": {
|
||||
"critical-error": {
|
||||
"title": "خطای بحرانی",
|
||||
"message": "خطای بحرانی رخ داده که مانع از اجرای برنامه می شود\n\n {{message}}\n\nبه احتمال زیاد ناشی از خطای غیرمنتظره در اجرای ناموفق یک اسکریپت است. برنامه را در مد ایمن اجرا کنید و خطا را بررسی نمایید."
|
||||
}
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "افزودن لینک",
|
||||
"note": "یادداشت"
|
||||
}
|
||||
}
|
||||
147
apps/client/src/translations/fi/translation.json
Normal file
147
apps/client/src/translations/fi/translation.json
Normal file
@@ -0,0 +1,147 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "Lisätietoja Trilium Notes:ista",
|
||||
"homepage": "Kotisivu:",
|
||||
"app_version": "Sovelluksen versio:",
|
||||
"db_version": "Tietokannan versio:",
|
||||
"build_date": "Koontipäivämäärä:",
|
||||
"data_directory": "Datakansio:",
|
||||
"sync_version": "Synkronoinnin versio:",
|
||||
"build_revision": "Sovelluksen versio:"
|
||||
},
|
||||
"toast": {
|
||||
"critical-error": {
|
||||
"title": "Kriittinen virhe"
|
||||
},
|
||||
"widget-error": {
|
||||
"title": "Widgetin luonti epäonnistui"
|
||||
}
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Lisää linkki",
|
||||
"link_title": "Linkin otsikko",
|
||||
"button_add_link": "Lisää linkki",
|
||||
"note": "Muistio",
|
||||
"search_note": "etsi muistiota sen nimellä"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"prefix": "Etuliite: ",
|
||||
"save": "Tallenna"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "Massatoiminnot",
|
||||
"available_actions": "Saatavilla olevat toiminnot",
|
||||
"chosen_actions": "Valitut toiminnot",
|
||||
"execute_bulk_actions": "Toteuta massatoiminnot",
|
||||
"bulk_actions_executed": "Massatoiminnot on toteutettu onnistuneesti.",
|
||||
"none_yet": "Ei vielä... lisää toiminto klikkaamalla jotiain yllä saatavilla olevaa yltä.",
|
||||
"labels": "Merkit",
|
||||
"relations": "Suhteet",
|
||||
"notes": "Muistiot",
|
||||
"other": "Muut",
|
||||
"affected_notes": "Vaikuttaa muistioihin"
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "Kopioi muistiot...",
|
||||
"help_on_links": "Apua linkkeihin",
|
||||
"notes_to_clone": "Kopioitavat muistiot",
|
||||
"target_parent_note": "Kohteen päämuistio",
|
||||
"search_for_note_by_its_name": "ensi muistiota sen nimellä",
|
||||
"cloned_note_prefix_title": "Kopioitu muistia näytetään puussa annetulla etuliitteellä",
|
||||
"prefix_optional": "Etuliite (valinnainen)",
|
||||
"clone_to_selected_note": "Kopioi valittuun muistioon",
|
||||
"note_cloned": "Muistio \"{{clonedTitle}}\" on kopioitu \"{{targetTitle}}\""
|
||||
},
|
||||
"confirm": {
|
||||
"confirmation": "Vahvistus",
|
||||
"cancel": "Peruuta",
|
||||
"ok": "OK",
|
||||
"also_delete_note": "Poista myös muistio"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Poista muistion esikatselu",
|
||||
"close": "Sulje",
|
||||
"notes_to_be_deleted": "Seuraavat muistiot tullaan poistamaan ({{notesCount}})",
|
||||
"no_note_to_delete": "Muistioita ei poisteta (vain kopiot).",
|
||||
"cancel": "Peruuta",
|
||||
"ok": "OK"
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Vie muistio",
|
||||
"close": "Sulje",
|
||||
"format_html": "HTML - suositeltu, sillä se säilyttää kaikki formatoinnit",
|
||||
"format_markdown": "Markdown - tämä säilyttää suurimman osan formatoinneista.",
|
||||
"opml_version_1": "OPML v1.0 - pelkkä teksti",
|
||||
"opml_version_2": "OPML v2.0 - sallii myös HTML:n",
|
||||
"export": "Vie",
|
||||
"choose_export_type": "Valitse ensin viennin tyyppi",
|
||||
"export_status": "Viennin tila",
|
||||
"export_in_progress": "Vienti käynnissä: {{progressCount}}",
|
||||
"export_finished_successfully": "Vienti valmistui onnistuneesti.",
|
||||
"format_pdf": "PDF - tulostukseen ja jakamiseen."
|
||||
},
|
||||
"help": {
|
||||
"title": "Lunttilappu",
|
||||
"noteNavigation": "Muistion navigointi",
|
||||
"goUpDown": "mene ylös/alas muistioiden listassa",
|
||||
"collapseExpand": "pienennä/suurenna solmu",
|
||||
"notSet": "ei asetettu",
|
||||
"goBackForwards": "mene taaksepäin/eteenpäin historiassa",
|
||||
"jumpToParentNote": "Hyppää ylempään muistioon",
|
||||
"collapseWholeTree": "pienennä koko muistio puu",
|
||||
"onlyInDesktop": "Vain työpöytänäkymässä (Electron build)",
|
||||
"openEmptyTab": "Avaa tyhjä välilehti",
|
||||
"closeActiveTab": "sulje aktiivinen välilehti",
|
||||
"activateNextTab": "aktivoi seuraava välilehti",
|
||||
"activatePreviousTab": "aktivoi edellinen välilehti",
|
||||
"creatingNotes": "Luo muistiota",
|
||||
"movingCloningNotes": "Siirrä / kopioi muistioita",
|
||||
"moveNoteUpHierarchy": "siirrä muistio ylöspäin listassa",
|
||||
"selectNote": "valitse muistio",
|
||||
"editingNotes": "Muokkaa solmua",
|
||||
"createEditLink": "luo / muokkaa ulkoista linkkiä",
|
||||
"createInternalLink": "luo sisäinen linkki",
|
||||
"insertDateTime": "lisää nykyinen päivämäärä ja aika hiiren kohdalle",
|
||||
"troubleshooting": "Vianmääritys",
|
||||
"reloadFrontend": "lataa Trilium:in käyttöliittymä",
|
||||
"showDevTools": "näytä kehittäjätyökalut",
|
||||
"showSQLConsole": "näytä SQL konsoli",
|
||||
"other": "Muut"
|
||||
},
|
||||
"import": {
|
||||
"importIntoNote": "Tuo muistioon",
|
||||
"chooseImportFile": "Valitse tuonnin tiedosto",
|
||||
"options": "Valinnat",
|
||||
"safeImport": "Turvallinen tuonti",
|
||||
"shrinkImages": "Kutista kuvat",
|
||||
"replaceUnderscoresWithSpaces": "Korvaa alaviivat väleillä tuotujen muistioiden tiedostonimissä",
|
||||
"import": "Tuo",
|
||||
"failed": "Tuonti epäonnistui: {{message}}.",
|
||||
"html_import_tags": {
|
||||
"title": "HTML Tuonnin Tunnisteet",
|
||||
"placeholder": "Lisää HTML tunnisteet, yksi per rivi"
|
||||
},
|
||||
"import-status": "Tuonnin tila",
|
||||
"in-progress": "Tuonti vaiheessa: {{progress}}",
|
||||
"successful": "Tuonti valmistui onnistuneesti."
|
||||
},
|
||||
"include_note": {
|
||||
"dialog_title": "Sisällytä muistio",
|
||||
"label_note": "Muistio",
|
||||
"placeholder_search": "etsi muistiota sen nimellä",
|
||||
"box_size_small": "pieni (~ 10 riviä)",
|
||||
"box_size_medium": "keskisuuri (~ 30 riviä)",
|
||||
"button_include": "Sisällytä muistio"
|
||||
},
|
||||
"info": {
|
||||
"modalTitle": "Info viesti",
|
||||
"closeButton": "Sulje",
|
||||
"okButton": "OK"
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_button": "Etsi koko tekstistä"
|
||||
},
|
||||
"call_to_action": {
|
||||
"dismiss": "Hylkää"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "À propos de Trilium Notes",
|
||||
"close": "Fermer",
|
||||
"homepage": "Page d'accueil :",
|
||||
"app_version": "Version de l'application :",
|
||||
"db_version": "Version de la base de données :",
|
||||
@@ -28,25 +27,22 @@
|
||||
"add_link": {
|
||||
"add_link": "Ajouter un lien",
|
||||
"help_on_links": "Aide sur les liens",
|
||||
"close": "Fermer",
|
||||
"note": "Note",
|
||||
"search_note": "rechercher une note par son nom",
|
||||
"link_title_mirrors": "le titre du lien reflète le titre actuel de la note",
|
||||
"link_title_arbitrary": "le titre du lien peut être modifié arbitrairement",
|
||||
"link_title": "Titre du lien",
|
||||
"button_add_link": "Ajouter un lien <kbd>Entrée</kbd>"
|
||||
"button_add_link": "Ajouter un lien"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"edit_branch_prefix": "Modifier le préfixe de branche",
|
||||
"help_on_tree_prefix": "Aide sur le préfixe de l'arbre",
|
||||
"close": "Fermer",
|
||||
"prefix": "Préfixe : ",
|
||||
"save": "Sauvegarder",
|
||||
"branch_prefix_saved": "Le préfixe de la branche a été enregistré."
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "Actions groupées",
|
||||
"close": "Fermer",
|
||||
"affected_notes": "Notes concernées",
|
||||
"include_descendants": "Inclure les descendants des notes sélectionnées",
|
||||
"available_actions": "Actions disponibles",
|
||||
@@ -61,20 +57,18 @@
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "Cloner les notes dans...",
|
||||
"close": "Fermer",
|
||||
"help_on_links": "Aide sur les liens",
|
||||
"notes_to_clone": "Notes à cloner",
|
||||
"target_parent_note": "Note parent cible",
|
||||
"search_for_note_by_its_name": "rechercher une note par son nom",
|
||||
"cloned_note_prefix_title": "La note clonée sera affichée dans l'arbre des notes avec le préfixe donné",
|
||||
"prefix_optional": "Préfixe (facultatif)",
|
||||
"clone_to_selected_note": "Cloner vers la note sélectionnée <kbd>entrer</kbd>",
|
||||
"clone_to_selected_note": "Cloner vers la note sélectionnée",
|
||||
"no_path_to_clone_to": "Aucun chemin vers lequel cloner.",
|
||||
"note_cloned": "La note \"{{clonedTitle}}\" a été clonée dans \"{{targetTitle}}\""
|
||||
},
|
||||
"confirm": {
|
||||
"confirmation": "Confirmation",
|
||||
"close": "Fermer",
|
||||
"cancel": "Annuler",
|
||||
"ok": "OK",
|
||||
"are_you_sure_remove_note": "Voulez-vous vraiment supprimer la note « {{title}} » de la carte des relations ? ",
|
||||
@@ -87,9 +81,9 @@
|
||||
"delete_all_clones_description": "Supprimer aussi les clones (peut être annulé dans des modifications récentes)",
|
||||
"erase_notes_description": "La suppression normale (douce) marque uniquement les notes comme supprimées et elles peuvent être restaurées (dans la boîte de dialogue des Modifications récentes) dans un délai donné. Cocher cette option effacera les notes immédiatement et il ne sera pas possible de les restaurer.",
|
||||
"erase_notes_warning": "Efface les notes de manière permanente (ne peut pas être annulée), y compris les clones. L'application va être rechargée.",
|
||||
"notes_to_be_deleted": "Les notes suivantes seront supprimées ({{- noteCount}})",
|
||||
"notes_to_be_deleted": "Les notes suivantes seront supprimées ({{notesCount}})",
|
||||
"no_note_to_delete": "Aucune note ne sera supprimée (uniquement les clones).",
|
||||
"broken_relations_to_be_deleted": "Les relations suivantes seront rompues et supprimées ({{- relationCount}})",
|
||||
"broken_relations_to_be_deleted": "Les relations suivantes seront rompues et supprimées ({{ relationCount}})",
|
||||
"cancel": "Annuler",
|
||||
"ok": "OK",
|
||||
"deleted_relation_text": "Note {{- note}} (à supprimer) est référencée dans la relation {{- relation}} provenant de {{- source}}."
|
||||
@@ -113,20 +107,18 @@
|
||||
"format_pdf": "PDF - pour l'impression ou le partage de documents."
|
||||
},
|
||||
"help": {
|
||||
"fullDocumentation": "Aide (la documentation complète est disponible <a class=\"external\" href=\"https://triliumnext.github.io/Docs/\">en ligne</a>)",
|
||||
"close": "Fermer",
|
||||
"noteNavigation": "Navigation dans les notes",
|
||||
"goUpDown": "<kbd>HAUT</kbd>, <kbd>BAS</kbd> - aller vers le haut/bas dans la liste des notes",
|
||||
"collapseExpand": "<kbd>GAUCHE</kbd>, <kbd>DROITE</kbd> - réduire/développer le nœud",
|
||||
"goUpDown": "aller vers le haut/bas dans la liste des notes",
|
||||
"collapseExpand": "réduire/développer le nœud",
|
||||
"notSet": "non défini",
|
||||
"goBackForwards": "reculer/avancer dans l'historique",
|
||||
"showJumpToNoteDialog": "afficher la <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">boîte de dialogue \"Aller à la note\"</a>",
|
||||
"scrollToActiveNote": "faire défiler jusqu'à la note active",
|
||||
"jumpToParentNote": "<kbd>Retour arrière</kbd> - aller à la note parent",
|
||||
"jumpToParentNote": "aller à la note parent",
|
||||
"collapseWholeTree": "réduire tout l'arbre des notes",
|
||||
"collapseSubTree": "réduire le sous-arbre",
|
||||
"tabShortcuts": "Raccourcis des onglets",
|
||||
"newTabNoteLink": "<kbd>CTRL+clic</kbd> - (ou clic central de la souris) sur le lien de la note ouvre la note dans un nouvel onglet",
|
||||
"newTabNoteLink": "sur le lien de la note ouvre la note dans un nouvel onglet",
|
||||
"onlyInDesktop": "Uniquement sur ordinateur (version Electron)",
|
||||
"openEmptyTab": "ouvrir un onglet vide",
|
||||
"closeActiveTab": "fermer l'onglet actif",
|
||||
@@ -141,14 +133,14 @@
|
||||
"moveNoteUpHierarchy": "déplacer la note vers le haut dans la hiérarchie",
|
||||
"multiSelectNote": "sélectionner plusieurs notes au-dessus/au-dessous",
|
||||
"selectAllNotes": "sélectionner toutes les notes du niveau actuel",
|
||||
"selectNote": "<kbd>Shift+clic</kbd> - sélectionner une note",
|
||||
"selectNote": "sélectionner une note",
|
||||
"copyNotes": "copier la note active (ou la sélection actuelle) dans le presse-papiers (utilisé pour le <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/cloning-notes.html#cloning-notes\">clonage</a>)",
|
||||
"cutNotes": "couper la note actuelle (ou la sélection actuelle) dans le presse-papiers (utilisé pour déplacer les notes)",
|
||||
"pasteNotes": "coller la ou les notes en tant que sous-note dans la note active (qui est soit déplacée, soit clonée selon qu'elle a été copiée ou coupée dans le presse-papiers)",
|
||||
"deleteNotes": "supprimer une note / un sous-arbre",
|
||||
"editingNotes": "Édition des notes",
|
||||
"editNoteTitle": "dans le volet de l'arborescence, basculera du volet au titre de la note. Presser Entrer à partir du titre de la note basculera vers l’éditeur de texte. <kbd>Ctrl+.</kbd> bascule de l'éditeur au volet arborescent.",
|
||||
"createEditLink": "<kbd>Ctrl+K</kbd> - créer/éditer un lien externe",
|
||||
"createEditLink": "créer/éditer un lien externe",
|
||||
"createInternalLink": "créer un lien interne",
|
||||
"followLink": "suivre le lien sous le curseur",
|
||||
"insertDateTime": "insérer la date et l'heure courante à la position du curseur",
|
||||
@@ -164,11 +156,12 @@
|
||||
"showSQLConsole": "afficher la console SQL",
|
||||
"other": "Autre",
|
||||
"quickSearch": "aller à la recherche rapide",
|
||||
"inPageSearch": "recherche sur la page"
|
||||
"inPageSearch": "recherche sur la page",
|
||||
"title": "Aide-mémoire",
|
||||
"newTabWithActivationNoteLink": "Lorsqu’on clique sur un lien de note, celle-ci s’ouvre et devient active dans un nouvel onglet"
|
||||
},
|
||||
"import": {
|
||||
"importIntoNote": "Importer dans la note",
|
||||
"close": "Fermer",
|
||||
"chooseImportFile": "Choisissez le fichier à importer",
|
||||
"importDescription": "Le contenu du ou des fichiers sélectionnés sera importé en tant que note(s) enfant dans",
|
||||
"options": "Options",
|
||||
@@ -195,14 +188,13 @@
|
||||
},
|
||||
"include_note": {
|
||||
"dialog_title": "Inclure une note",
|
||||
"close": "Fermer",
|
||||
"label_note": "Note",
|
||||
"placeholder_search": "rechercher une note par son nom",
|
||||
"box_size_prompt": "Taille de la boîte de la note incluse :",
|
||||
"box_size_small": "petit (~ 10 lignes)",
|
||||
"box_size_medium": "moyen (~ 30 lignes)",
|
||||
"box_size_full": "complet (la boîte affiche le texte complet)",
|
||||
"button_include": "Inclure une note <kbd>Entrée</kbd>"
|
||||
"button_include": "Inclure une note"
|
||||
},
|
||||
"info": {
|
||||
"modalTitle": "Message d'information",
|
||||
@@ -210,43 +202,41 @@
|
||||
"okButton": "OK"
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_placeholder": "rechercher une note par son nom",
|
||||
"close": "Fermer",
|
||||
"search_button": "Rechercher dans le texte intégral <kbd>Ctrl+Entrée</kbd>"
|
||||
"search_button": "Rechercher dans le texte intégral",
|
||||
"search_placeholder": "Rechercher une note par son nom ou saisir ‘>’ pour les commandes…"
|
||||
},
|
||||
"markdown_import": {
|
||||
"dialog_title": "Importation Markdown",
|
||||
"close": "Fermer",
|
||||
"modal_body_text": "En raison du bac à sable du navigateur, il n'est pas possible de lire directement le presse-papiers à partir de JavaScript. Veuillez coller le Markdown à importer dans la zone de texte ci-dessous et cliquez sur le bouton Importer",
|
||||
"import_button": "Importer Ctrl+Entrée",
|
||||
"import_button": "Importer",
|
||||
"import_success": "Le contenu Markdown a été importé dans le document."
|
||||
},
|
||||
"move_to": {
|
||||
"dialog_title": "Déplacer les notes vers...",
|
||||
"close": "Fermer",
|
||||
"notes_to_move": "Notes à déplacer",
|
||||
"target_parent_note": "Note parent cible",
|
||||
"search_placeholder": "rechercher une note par son nom",
|
||||
"move_button": "Déplacer vers la note sélectionnée <kbd>entrer</kbd>",
|
||||
"move_button": "Déplacer vers la note sélectionnée",
|
||||
"error_no_path": "Aucun chemin vers lequel déplacer.",
|
||||
"move_success_message": "Les notes sélectionnées ont été déplacées dans "
|
||||
},
|
||||
"note_type_chooser": {
|
||||
"modal_title": "Choisissez le type de note",
|
||||
"close": "Fermer",
|
||||
"modal_body": "Choisissez le type de note/le modèle de la nouvelle note :",
|
||||
"templates": "Modèles :"
|
||||
"templates": "Modèles",
|
||||
"change_path_prompt": "Modifier l’emplacement de création de la nouvelle note :",
|
||||
"search_placeholder": "Rechercher le chemin par nom (par défaut si vide)",
|
||||
"builtin_templates": "Modèles intégrés"
|
||||
},
|
||||
"password_not_set": {
|
||||
"title": "Le mot de passe n'est pas défini",
|
||||
"close": "Fermer",
|
||||
"body1": "Les notes protégées sont cryptées à l'aide d'un mot de passe utilisateur, mais le mot de passe n'a pas encore été défini.",
|
||||
"body2": "Pour pouvoir protéger les notes, cliquez <a class=\"open-password-options-button\" href=\"javascript:\">ici</a> pour ouvrir les Options et définir votre mot de passe."
|
||||
"body2": "Pour pouvoir protéger les notes, cliquez sur le bouton ci-dessous pour ouvrir la boîte de dialogue Options et définir votre mot de passe.",
|
||||
"go_to_password_options": "Accéder aux options de mot de passe"
|
||||
},
|
||||
"prompt": {
|
||||
"title": "Prompt",
|
||||
"close": "Fermer",
|
||||
"ok": "OK <kbd>entrer</kbd>",
|
||||
"ok": "OK",
|
||||
"defaultTitle": "Prompt"
|
||||
},
|
||||
"protected_session_password": {
|
||||
@@ -254,12 +244,11 @@
|
||||
"help_title": "Aide sur les notes protégées",
|
||||
"close_label": "Fermer",
|
||||
"form_label": "Pour procéder à l'action demandée, vous devez démarrer une session protégée en saisissant le mot de passe :",
|
||||
"start_button": "Démarrer une session protégée <kbd>entrer</kbd>"
|
||||
"start_button": "Démarrer une session protégée"
|
||||
},
|
||||
"recent_changes": {
|
||||
"title": "Modifications récentes",
|
||||
"erase_notes_button": "Effacer les notes supprimées maintenant",
|
||||
"close": "Fermer",
|
||||
"deleted_notes_message": "Les notes supprimées ont été effacées.",
|
||||
"no_changes_message": "Aucun changement pour l'instant...",
|
||||
"undelete_link": "annuler la suppression",
|
||||
@@ -270,13 +259,10 @@
|
||||
"delete_all_revisions": "Supprimer toutes les versions de cette note",
|
||||
"delete_all_button": "Supprimer toutes les versions",
|
||||
"help_title": "Aide sur les versions de notes",
|
||||
"close": "Fermer",
|
||||
"revision_last_edited": "Cette version a été modifiée pour la dernière fois le {{date}}",
|
||||
"confirm_delete_all": "Voulez-vous supprimer toutes les versions de cette note ?",
|
||||
"no_revisions": "Aucune version pour cette note pour l'instant...",
|
||||
"restore_button": "",
|
||||
"confirm_restore": "Voulez-vous restaurer cette version ? Le titre et le contenu actuels de la note seront écrasés par cette version.",
|
||||
"delete_button": "",
|
||||
"confirm_delete": "Voulez-vous supprimer cette version ?",
|
||||
"revisions_deleted": "Les versions de notes ont été supprimées.",
|
||||
"revision_restored": "La version de la note a été restaurée.",
|
||||
@@ -288,11 +274,12 @@
|
||||
"mime": "MIME : ",
|
||||
"file_size": "Taille du fichier :",
|
||||
"preview": "Aperçu :",
|
||||
"preview_not_available": "L'aperçu n'est pas disponible pour ce type de note."
|
||||
"preview_not_available": "L'aperçu n'est pas disponible pour ce type de note.",
|
||||
"restore_button": "Restaurer",
|
||||
"delete_button": "Supprimer"
|
||||
},
|
||||
"sort_child_notes": {
|
||||
"sort_children_by": "Trier les enfants par...",
|
||||
"close": "Fermer",
|
||||
"sorting_criteria": "Critères de tri",
|
||||
"title": "titre",
|
||||
"date_created": "date de création",
|
||||
@@ -306,13 +293,12 @@
|
||||
"sort_with_respect_to_different_character_sorting": "trier en fonction de différentes règles de tri et de classement des caractères dans différentes langues ou régions.",
|
||||
"natural_sort_language": "Langage de tri naturel",
|
||||
"the_language_code_for_natural_sort": "Le code de langue pour le tri naturel, par ex. \"zh-CN\" pour le chinois.",
|
||||
"sort": "Trier <kbd>Entrée</kbd>"
|
||||
"sort": "Trier"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "Téléverser des pièces jointes à la note",
|
||||
"close": "Fermer",
|
||||
"choose_files": "Choisir des fichiers",
|
||||
"files_will_be_uploaded": "Les fichiers seront téléversés sous forme de pièces jointes dans",
|
||||
"files_will_be_uploaded": "Les fichiers seront téléversés sous forme de pièces jointes dans {{noteTitle}}",
|
||||
"options": "Options",
|
||||
"shrink_images": "Réduire les images",
|
||||
"upload": "Téléverser",
|
||||
@@ -401,12 +387,12 @@
|
||||
"share_root": "partage cette note à l'adresse racine /share.",
|
||||
"share_description": "définir le texte à ajouter à la balise méta HTML pour la description",
|
||||
"share_raw": "la note sera servie dans son format brut, sans wrapper HTML",
|
||||
"share_disallow_robot_indexing": "interdira l'indexation par robot de cette note via l'en-tête <code>X-Robots-Tag: noindex</code>",
|
||||
"share_disallow_robot_indexing": "Interdira l'indexation par robot de cette note via l'en-tête <code>X-Robots-Tag: noindex</code>",
|
||||
"share_credentials": "exiger des informations d’identification pour accéder à cette note partagée. La valeur devrait être au format « nom d'utilisateur : mot de passe ». N'oubliez pas de rendre cela héritable pour l'appliquer aux notes/images enfants.",
|
||||
"share_index": "la note avec ce label listera toutes les racines des notes partagées",
|
||||
"display_relations": "noms des relations délimités par des virgules qui doivent être affichés. Tous les autres seront masqués.",
|
||||
"hide_relations": "noms de relations délimités par des virgules qui doivent être masqués. Tous les autres seront affichés.",
|
||||
"title_template": "titre par défaut des notes créées en tant qu'enfants de cette note. La valeur est évaluée sous forme de chaîne JavaScript \n et peut ainsi être enrichi de contenu dynamique via les variables injectées <code>now</code> et <code>parentNote</code>. Exemples :\n \n <ul>\n <li><code>Œuvres littéraires de ${parentNote.getLabelValue('authorName')}</code></li>\n <li><code>Connectez-vous pour ${now.format('YYYY-MM-DD HH:mm:ss')}</code></li>\n </ul>\n \n Consultez le <a href=\"https://triliumnext.github.io/Docs/Wiki/default-note-title.html\">wiki avec plus de détails</a>, la documentation sur l'API pour <a href=\"https://zadam.github.io/trilium/backend_api/Note.html\">parentNote</a> et <a href=\"https://day.js.org/docs/en/display/format\">maintenant< /a> pour plus de détails.",
|
||||
"title_template": "titre par défaut des notes créées en tant qu'enfants de cette note. La valeur est évaluée sous forme de chaîne JavaScript \n et peut ainsi être enrichi de contenu dynamique via les variables injectées <code>now</code> et <code>parentNote</code>. Exemples :\n \n <ul>\n <li><code>Œuvres littéraires de ${parentNote.getLabelValue('authorName')}</code></li>\n <li><code>Connectez-vous pour ${now.format('YYYY-MM-DD HH:mm:ss')}</code></li>\n </ul>\n \n Consultez le <a href=\"https://triliumnext.github.io/Docs/Wiki/default-note-title.html\">wiki avec plus de détails</a>, la documentation sur l'API pour <a href=\"https://zadam.github.io/trilium/backend_api/Note.html\">parentNote</a> et <a href=\"https://day.js.org/docs/en/display/format\">maintenant</a> pour plus de détails.",
|
||||
"template": "Cette note apparaîtra parmi les modèles disponibles lors de la création d'une nouvelle note",
|
||||
"toc": "<code>#toc</code> ou <code>#toc=show</code> forcera l'affichage de la table des matières, <code>#toc=hide</code> force qu'elle soit masquée. Si le label n'existe pas, le paramètre global est utilisé",
|
||||
"color": "définit la couleur de la note dans l'arborescence des notes, les liens, etc. Utilisez n'importe quelle valeur de couleur CSS valide comme « rouge » ou #a13d5f",
|
||||
@@ -440,7 +426,8 @@
|
||||
"other_notes_with_name": "Autres notes portant le nom {{attributeType}} \"{{attributeName}}\"",
|
||||
"and_more": "... et {{count}} plus.",
|
||||
"print_landscape": "Lors de l'exportation en PDF, change l'orientation de la page en paysage au lieu de portrait.",
|
||||
"print_page_size": "Lors de l'exportation en PDF, change la taille de la page. Valeurs supportées : <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>."
|
||||
"print_page_size": "Lors de l'exportation en PDF, change la taille de la page. Valeurs supportées : <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
|
||||
"color_type": "Couleur"
|
||||
},
|
||||
"attribute_editor": {
|
||||
"help_text_body1": "Pour ajouter un label, tapez simplement par ex. <code>#rock</code>, ou si vous souhaitez également ajouter une valeur, tapez par ex. <code>#année = 2020</code>",
|
||||
@@ -560,7 +547,7 @@
|
||||
},
|
||||
"attachments_actions": {
|
||||
"open_externally": "Ouverture externe",
|
||||
"open_externally_title": "Le fichier sera ouvert dans une application externe et les modifications apportées seront surveillées. \nVous pourrez ensuite téléverser la version modifiée dans Trilium.",
|
||||
"open_externally_title": "Le fichier sera ouvert dans une application externe et surveillé pour détecter les modifications. Vous pourrez ensuite téléverser la version modifiée dans Trilium.",
|
||||
"open_custom": "Ouvrir avec",
|
||||
"open_custom_title": "Le fichier sera ouvert dans une application externe et surveillé pour les modifications. Vous pourrez ensuite téléverser la version modifiée sur Trilium.",
|
||||
"download": "Télécharger",
|
||||
@@ -599,7 +586,8 @@
|
||||
"september": "Septembre",
|
||||
"october": "Octobre",
|
||||
"november": "Novembre",
|
||||
"december": "Décembre"
|
||||
"december": "Décembre",
|
||||
"cannot_find_week_note": "Impossible de trouver la note de la semaine"
|
||||
},
|
||||
"close_pane_button": {
|
||||
"close_this_pane": "Fermer ce volet"
|
||||
@@ -743,7 +731,8 @@
|
||||
"basic_properties": {
|
||||
"note_type": "Type de note",
|
||||
"editable": "Modifiable",
|
||||
"basic_properties": "Propriétés de base"
|
||||
"basic_properties": "Propriétés de base",
|
||||
"language": "Langage"
|
||||
},
|
||||
"book_properties": {
|
||||
"view_type": "Type d'affichage",
|
||||
@@ -753,9 +742,12 @@
|
||||
"expand_all_children": "Développer tous les enfants",
|
||||
"collapse": "Réduire",
|
||||
"expand": "Développer",
|
||||
"book_properties": "Propriétés du livre",
|
||||
"invalid_view_type": "Type de vue non valide '{{type}}'",
|
||||
"calendar": "Calendrier"
|
||||
"calendar": "Calendrier",
|
||||
"book_properties": "Propriétés de la collection",
|
||||
"table": "Tableau",
|
||||
"geo-map": "Carte géographique",
|
||||
"board": "Tableau de bord"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "Aucune note modifiée ce jour-là...",
|
||||
@@ -832,7 +824,8 @@
|
||||
"unknown_label_type": "Type de label inconnu '{{type}}'",
|
||||
"unknown_attribute_type": "Type d'attribut inconnu '{{type}}'",
|
||||
"add_new_attribute": "Ajouter un nouvel attribut",
|
||||
"remove_this_attribute": "Supprimer cet attribut"
|
||||
"remove_this_attribute": "Supprimer cet attribut",
|
||||
"remove_color": "Supprimer l’étiquette de couleur"
|
||||
},
|
||||
"script_executor": {
|
||||
"query": "Requête",
|
||||
@@ -922,7 +915,7 @@
|
||||
"description1": "Le script de recherche permet de définir les résultats de la recherche en exécutant un script. Cela offre une flexibilité maximale lorsque la recherche standard ne suffit pas.",
|
||||
"description2": "Le script de recherche doit être de type \"code\" et sous-type \"backend JavaScript\". Le script doit retourner un tableau de noteIds ou de notes.",
|
||||
"example_title": "Voir cet exemple :",
|
||||
"example_code": "// 1. préfiltrage à l'aide de la recherche standard\nconst candidateNotes = api.searchForNotes(\"#journal\"); \n\n// 2. application de critères de recherche personnalisés\nconst matchedNotes = candidateNotes\n .filter(note => note.title.match(/[0-9]{1,2}\\. ?[0-9]{1,2}\\. ?[0-9]{4}/));\n\nreturn matchedNotes;",
|
||||
"example_code": "// 1. préfiltrage à l'aide de la recherche standard\nconst candidateNotes = api.searchForNotes(\"#journal\"); \n\n// 2. application de critères de recherche personnalisés\nconst matchedNotes = candidateNotes\n .filter(note => note.title.match(/[0-9]{1,2}\\. ?[0-9]{1,2}\\. ?[0-9]{4}/));\n\nreturn matchedNotes;",
|
||||
"note": "Notez que le script de recherche et la l'expression à rechercher standard ne peuvent pas être combinés."
|
||||
},
|
||||
"search_string": {
|
||||
@@ -1091,7 +1084,8 @@
|
||||
"max_width_label": "Largeur maximale du contenu en pixels",
|
||||
"apply_changes_description": "Pour appliquer les modifications de largeur du contenu, cliquez sur",
|
||||
"reload_button": "recharger l'interface",
|
||||
"reload_description": "changements par rapport aux options d'apparence"
|
||||
"reload_description": "changements par rapport aux options d'apparence",
|
||||
"max_width_unit": "Pixels"
|
||||
},
|
||||
"native_title_bar": {
|
||||
"title": "Barre de titre native (nécessite le redémarrage de l'application)",
|
||||
@@ -1107,17 +1101,17 @@
|
||||
"title": "Thème de l'application",
|
||||
"theme_label": "Thème",
|
||||
"override_theme_fonts_label": "Remplacer les polices du thème",
|
||||
"auto_theme": "Auto",
|
||||
"light_theme": "Lumière",
|
||||
"dark_theme": "Sombre",
|
||||
"triliumnext": "TriliumNext Beta (Suit le thème du système)",
|
||||
"triliumnext-light": "TriliumNext Beta (Clair)",
|
||||
"triliumnext-dark": "TriliumNext Beta (sombre)",
|
||||
"triliumnext": "Trilium (Suit le thème du système)",
|
||||
"triliumnext-light": "Trilium (Clair)",
|
||||
"triliumnext-dark": "Trilium (sombre)",
|
||||
"layout": "Disposition",
|
||||
"layout-vertical-title": "Vertical",
|
||||
"layout-horizontal-title": "Horizontal",
|
||||
"layout-vertical-description": "la barre de raccourcis est à gauche (défaut)",
|
||||
"layout-horizontal-description": "la barre de raccourcis est sous la barre des onglets, cette-dernière est s'affiche en pleine largeur."
|
||||
"layout-horizontal-description": "la barre de raccourcis est sous la barre des onglets, cette-dernière est s'affiche en pleine largeur.",
|
||||
"auto_theme": "Hérité (suivre le schéma de couleurs du système)",
|
||||
"light_theme": "Hérité (clair)",
|
||||
"dark_theme": "Hérité (foncé)"
|
||||
},
|
||||
"zoom_factor": {
|
||||
"title": "Facteur de zoom (version bureau uniquement)",
|
||||
@@ -1162,14 +1156,14 @@
|
||||
"note_erasure_timeout": {
|
||||
"note_erasure_timeout_title": "Délai d'effacement des notes",
|
||||
"note_erasure_description": "Les notes supprimées (et les attributs, versions...) sont seulement marquées comme supprimées et il est possible de les récupérer à partir de la boîte de dialogue Notes récentes. Après un certain temps, les notes supprimées sont « effacées », ce qui signifie que leur contenu n'est plus récupérable. Ce paramètre vous permet de configurer la durée entre la suppression et l'effacement de la note.",
|
||||
"erase_notes_after": "Effacer les notes après",
|
||||
"erase_notes_after": "Effacer les notes après :",
|
||||
"manual_erasing_description": "Vous pouvez également déclencher l'effacement manuellement (sans tenir compte de la durée définie ci-dessus) :",
|
||||
"erase_deleted_notes_now": "Effacer les notes supprimées maintenant",
|
||||
"deleted_notes_erased": "Les notes supprimées ont été effacées."
|
||||
},
|
||||
"revisions_snapshot_interval": {
|
||||
"note_revisions_snapshot_interval_title": "Délai d'enregistrement automatique d'une version de note",
|
||||
"note_revisions_snapshot_description": "Le délai d'enregistrement automatique des versions de note définit le temps avant la création automatique d'une nouvelle version de note. Consultez le <a href=\"https://triliumnext.github.io/Docs/Wiki/note-revisions.html\" class=\"external\">wiki</a> pour plus d'informations.",
|
||||
"note_revisions_snapshot_description": "Le délai d'enregistrement automatique des versions de note définit le temps avant la création automatique d'une nouvelle version de note. Consultez le <doc>wiki</doc> pour plus d'informations.",
|
||||
"snapshot_time_interval_label": "Délai d'enregistrement automatique de version de note :"
|
||||
},
|
||||
"revisions_snapshot_limit": {
|
||||
@@ -1251,10 +1245,8 @@
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI est une API REST utilisée pour accéder à l'instance Trilium par programme, sans interface utilisateur.",
|
||||
"see_more": "",
|
||||
"wiki": "wiki",
|
||||
"openapi_spec": "Spec ETAPI OpenAPI",
|
||||
"swagger_ui": "",
|
||||
"create_token": "Créer un nouveau jeton ETAPI",
|
||||
"existing_tokens": "Jetons existants",
|
||||
"no_tokens_yet": "Il n'y a pas encore de jetons. Cliquez sur le bouton ci-dessus pour en créer un.",
|
||||
@@ -1389,7 +1381,7 @@
|
||||
"move-to": "Déplacer vers...",
|
||||
"paste-into": "Coller dans",
|
||||
"paste-after": "Coller après",
|
||||
"duplicate-subtree": "Dupliquer le sous-arbre",
|
||||
"duplicate": "Dupliquer",
|
||||
"export": "Exporter",
|
||||
"import-into-note": "Importer dans la note",
|
||||
"apply-bulk-actions": "Appliquer des Actions groupées",
|
||||
@@ -1408,7 +1400,6 @@
|
||||
"relation-map": "Carte des relations",
|
||||
"note-map": "Carte de notes",
|
||||
"render-note": "Rendu Html",
|
||||
"book": "Livre",
|
||||
"mermaid-diagram": "Diagramme Mermaid",
|
||||
"canvas": "Canevas",
|
||||
"web-view": "Affichage Web",
|
||||
@@ -1574,7 +1565,6 @@
|
||||
"auto-detect-language": "Détecté automatiquement"
|
||||
},
|
||||
"highlighting": {
|
||||
"title": "",
|
||||
"description": "Contrôle la coloration syntaxique des blocs de code à l'intérieur des notes texte, les notes de code ne seront pas affectées.",
|
||||
"color-scheme": "Jeu de couleurs"
|
||||
},
|
||||
@@ -1674,5 +1664,32 @@
|
||||
"time_selector": {
|
||||
"invalid_input": "La valeur de l'heure saisie n'est pas un nombre valide.",
|
||||
"minimum_input": "La valeur de temps saisie doit être d'au moins {{minimumSeconds}} secondes."
|
||||
},
|
||||
"multi_factor_authentication": {
|
||||
"oauth_user_email": "Courriel de l'utilisateur : "
|
||||
},
|
||||
"modal": {
|
||||
"close": "Fermer"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Non démarré",
|
||||
"title": "Paramètres IA",
|
||||
"processed_notes": "Notes traitées",
|
||||
"n_notes_queued_0": "{{ count }} note en attente d’indexation",
|
||||
"n_notes_queued_1": "{{ count }} notes en attente d’indexation",
|
||||
"n_notes_queued_2": "",
|
||||
"notes_indexed_0": "{{ count }} note indexée",
|
||||
"notes_indexed_1": "{{ count }} notes indexées",
|
||||
"notes_indexed_2": "",
|
||||
"anthropic_url_description": "URL de base pour l'API Anthropic (par défaut : https ://api.anthropic.com)",
|
||||
"anthropic_model_description": "Modèles Anthropic Claude pour la complétion",
|
||||
"voyage_settings": "Réglages d'IA Voyage",
|
||||
"ollama_settings": "Réglages Ollama",
|
||||
"ollama_url_description": "URL pour l'API Ollama (par défaut: http://localhost:11434)",
|
||||
"ollama_model_description": "Model Ollama utilisé pour la complétion",
|
||||
"anthropic_configuration": "Configuration Anthropic",
|
||||
"voyage_configuration": "Configuration IA Voyage",
|
||||
"voyage_url_description": "Défaut: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Configuration Ollama"
|
||||
}
|
||||
}
|
||||
|
||||
1
apps/client/src/translations/hu/translation.json
Normal file
1
apps/client/src/translations/hu/translation.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
345
apps/client/src/translations/it/translation.json
Normal file
345
apps/client/src/translations/it/translation.json
Normal file
@@ -0,0 +1,345 @@
|
||||
{
|
||||
"about": {
|
||||
"app_version": "Versione dell'app:",
|
||||
"db_version": "Versione DB:",
|
||||
"sync_version": "Versione Sync:",
|
||||
"data_directory": "Cartella dati:",
|
||||
"title": "Informazioni su Trilium Notes",
|
||||
"build_date": "Data della build:",
|
||||
"build_revision": "Revisione della build:",
|
||||
"homepage": "Homepage:"
|
||||
},
|
||||
"toast": {
|
||||
"critical-error": {
|
||||
"title": "Errore critico",
|
||||
"message": "Si è verificato un errore critico che impedisce l'avvio dell'applicazione client:\n\n{{message}}\n\nQuesto è probabilmente causato da un errore di script inaspettato. Prova a avviare l'applicazione in modo sicuro e controlla il problema."
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "Non si è riusciti a caricare uno script personalizzato",
|
||||
"message": "Lo script della nota con ID \"{{id}}\", dal titolo \"{{title}}\" non è stato inizializzato a causa di:\n\n{{message}}"
|
||||
},
|
||||
"widget-error": {
|
||||
"title": "Impossibile inizializzare un widget",
|
||||
"message-custom": "Il widget personalizzato della nota con ID \"{{id}}\", dal titolo \"{{title}}\" non è stato inizializzato a causa di:\n\n{{message}}",
|
||||
"message-unknown": "Un widget sconosciuto non è stato inizializzato a causa di:\n\n{{message}}"
|
||||
}
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Aggiungi un collegamento",
|
||||
"note": "Nota",
|
||||
"search_note": "cerca una nota per nome",
|
||||
"link_title_mirrors": "il titolo del collegamento rispecchia il titolo della nota corrente",
|
||||
"link_title_arbitrary": "il titolo del collegamento può essere modificato arbitrariamente",
|
||||
"link_title": "Titolo del collegamento",
|
||||
"button_add_link": "Aggiungi il collegamento <kbd>invio</kbd>",
|
||||
"help_on_links": "Aiuto sui collegamenti"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"edit_branch_prefix": "Modifica il prefisso del ramo",
|
||||
"help_on_tree_prefix": "Aiuto sui prefissi dell'Albero",
|
||||
"prefix": "Prefisso: ",
|
||||
"save": "Salva",
|
||||
"branch_prefix_saved": "Il prefisso del ramo è stato salvato."
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "Azioni massive",
|
||||
"affected_notes": "Note influenzate",
|
||||
"include_descendants": "Includi i discendenti della nota selezionata",
|
||||
"available_actions": "Azioni disponibili",
|
||||
"chosen_actions": "Azioni scelte",
|
||||
"execute_bulk_actions": "Esegui le azioni massive",
|
||||
"bulk_actions_executed": "Le azioni massive sono state eseguite con successo.",
|
||||
"none_yet": "Ancora nessuna... aggiungi una azione cliccando su una di quelle disponibili sopra.",
|
||||
"labels": "Etichette",
|
||||
"relations": "Relazioni",
|
||||
"notes": "Note",
|
||||
"other": "Altro"
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "Clona note in...",
|
||||
"help_on_links": "Aiuto sui collegamenti",
|
||||
"notes_to_clone": "Note da clonare",
|
||||
"target_parent_note": "Nodo padre obiettivo",
|
||||
"search_for_note_by_its_name": "cerca una nota per nome",
|
||||
"cloned_note_prefix_title": "Le note clonate saranno mostrate nell'albero delle note con il dato prefisso",
|
||||
"prefix_optional": "Prefisso (opzionale)",
|
||||
"clone_to_selected_note": "Clona sotto la nota selezionata <kbd>invio</kbd>",
|
||||
"no_path_to_clone_to": "Nessun percorso per clonare dentro.",
|
||||
"note_cloned": "La nota \"{{clonedTitle}}\" è stata clonata in \"{{targetTitle}}\""
|
||||
},
|
||||
"confirm": {
|
||||
"cancel": "Annulla",
|
||||
"ok": "OK",
|
||||
"confirmation": "Conferma",
|
||||
"are_you_sure_remove_note": "Sei sicuro di voler rimuovere la nota \"{{title}}\" dalla mappa delle relazioni? ",
|
||||
"if_you_dont_check": "Se non lo selezioni, la nota sarà rimossa solamente dalla mappa delle relazioni.",
|
||||
"also_delete_note": "Rimuove anche la nota"
|
||||
},
|
||||
"delete_notes": {
|
||||
"ok": "OK",
|
||||
"close": "Chiudi",
|
||||
"delete_notes_preview": "Anteprima di eliminazione delle note",
|
||||
"delete_all_clones_description": "Elimina anche tutti i cloni (può essere disfatto tramite i cambiamenti recenti)",
|
||||
"erase_notes_description": "L'eliminazione normale (soft) marca le note come eliminate e potranno essere recuperate entro un certo lasso di tempo (dalla finestra dei cambiamenti recenti). Selezionando questa opzione le note si elimineranno immediatamente e non sarà possibile recuperarle.",
|
||||
"erase_notes_warning": "Elimina le note in modo permanente (non potrà essere disfatto), compresi tutti i cloni. Ciò forzerà un nuovo caricamento dell'applicazione.",
|
||||
"cancel": "Annulla",
|
||||
"notes_to_be_deleted": "Le seguenti note saranno eliminate ({{- noteCount}})",
|
||||
"no_note_to_delete": "Nessuna nota sarà eliminata (solo i cloni).",
|
||||
"broken_relations_to_be_deleted": "Le seguenti relazioni saranno interrotte ed eliminate ({{- relationCount}})",
|
||||
"deleted_relation_text": "La nota {{- note}} (da eliminare) è referenziata dalla relazione {{- relation}} originata da {{- source}}."
|
||||
},
|
||||
"info": {
|
||||
"okButton": "OK",
|
||||
"closeButton": "Chiudi"
|
||||
},
|
||||
"export": {
|
||||
"close": "Chiudi",
|
||||
"export_note_title": "Esporta la nota",
|
||||
"export_status": "Stato dell'esportazione",
|
||||
"export": "Esporta",
|
||||
"choose_export_type": "Scegli prima il tipo di esportazione, per favore",
|
||||
"export_in_progress": "Esportazione in corso: {{progressCount}}",
|
||||
"export_finished_successfully": "Esportazione terminata con successo.",
|
||||
"format_pdf": "PDF- allo scopo di stampa o esportazione.",
|
||||
"export_type_subtree": "Questa nota e tutti i suoi discendenti",
|
||||
"format_html": "HTML - raccomandato in quanto mantiene tutti i formati",
|
||||
"format_html_zip": "HTML in archivio ZIP - questo è raccomandato in quanto conserva tutta la formattazione.",
|
||||
"format_markdown": "MArkdown - questo conserva la maggior parte della formattazione."
|
||||
},
|
||||
"password_not_set": {
|
||||
"body1": "Le note protette sono crittografate utilizzando una password utente, ma la password non è stata ancora impostata.",
|
||||
"body2": "Per proteggere le note, fare clic su <a class=\"open-password-options-button\" href=\"javascript:\">qui</a> per aprire la finestra di dialogo Opzioni e impostare la password."
|
||||
},
|
||||
"protected_session_password": {
|
||||
"close_label": "Chiudi"
|
||||
},
|
||||
"abstract_bulk_action": {
|
||||
"remove_this_search_action": "Rimuovi questa azione di ricerca"
|
||||
},
|
||||
"etapi": {
|
||||
"new_token_title": "Nuovo token ETAPI",
|
||||
"new_token_message": "Inserire il nuovo nome del token"
|
||||
},
|
||||
"electron_integration": {
|
||||
"zoom-factor": "Fattore di ingrandimento",
|
||||
"desktop-application": "Applicazione Desktop"
|
||||
},
|
||||
"note_autocomplete": {
|
||||
"search-for": "Cerca \"{{term}}\"",
|
||||
"create-note": "Crea e collega la nota figlia \"{{term}}\"",
|
||||
"insert-external-link": "Inserisci il collegamento esterno a \"{{term}}\"",
|
||||
"clear-text-field": "Pulisci il campo di testo",
|
||||
"show-recent-notes": "Mostra le note recenti",
|
||||
"full-text-search": "Ricerca full text"
|
||||
},
|
||||
"note_tooltip": {
|
||||
"note-has-been-deleted": "La nota è stata eliminata.",
|
||||
"quick-edit": "Modifica veloce"
|
||||
},
|
||||
"geo-map": {
|
||||
"create-child-note-title": "Crea una nota figlia e aggiungila alla mappa",
|
||||
"create-child-note-instruction": "Clicca sulla mappa per creare una nuova nota qui o premi Escape per uscire.",
|
||||
"unable-to-load-map": "Impossibile caricare la mappa."
|
||||
},
|
||||
"geo-map-context": {
|
||||
"open-location": "Apri la posizione",
|
||||
"remove-from-map": "Rimuovi dalla mappa",
|
||||
"add-note": "Aggiungi un marcatore in questa posizione"
|
||||
},
|
||||
"debug": {
|
||||
"debug": "Debug"
|
||||
},
|
||||
"database_anonymization": {
|
||||
"light_anonymization": "Anonimizzazione parziale",
|
||||
"title": "Anonimizzazione del Database",
|
||||
"full_anonymization": "Anonimizzazione completa",
|
||||
"full_anonymization_description": "Questa azione creerà una nuova copia del database e lo anonimizzerà (rimuove tutti i contenuti delle note, lasciando solo la struttura e qualche metadato non sensibile) per condividerlo online allo scopo di debugging, senza paura di far trapelare i tuoi dati personali.",
|
||||
"save_fully_anonymized_database": "Salva il database completamente anonimizzato",
|
||||
"light_anonymization_description": "Questa azione creerà una nuova copia del database e lo anonimizzerà in parzialmente — in particolare, solo il contenuto delle note sarà rimosso, ma i titoli e gli attributi rimarranno. Inoltre, note con script personalizzati JS di frontend/backend e widget personalizzati lasciando rimarranno. Ciò mette a disposizione più contesto per il debug dei problemi.",
|
||||
"choose_anonymization": "Puoi decidere da solo se fornire un database completamente o parzialmente anonimizzato. Anche un database completamente anonimizzato è molto utile, sebbene in alcuni casi i database parzialmente anonimizzati possono accelerare il processo di identificazione dei bug e la loro correzione.",
|
||||
"no_anonymized_database_yet": "Nessun database ancora anonimizzato.",
|
||||
"save_lightly_anonymized_database": "Salva il database parzialmente anonimizzato",
|
||||
"successfully_created_fully_anonymized_database": "Database completamente anonimizzato creato in {{anonymizedFilePath}}",
|
||||
"successfully_created_lightly_anonymized_database": "Database parzialmente anonimizzato creato in {{anonymizedFilePath}}"
|
||||
},
|
||||
"cpu_arch_warning": {
|
||||
"title": "Per favore scarica la versione ARM64",
|
||||
"continue_anyway": "Continua Comunque",
|
||||
"dont_show_again": "Non mostrare più questo avviso",
|
||||
"download_link": "Scarica la Versione Nativa"
|
||||
},
|
||||
"editorfeatures": {
|
||||
"title": "Caratteristiche",
|
||||
"emoji_completion_enabled": "Abilita il completamento automatico delle Emoji",
|
||||
"note_completion_enabled": "Abilita il completamento automatico delle note"
|
||||
},
|
||||
"table_view": {
|
||||
"new-row": "Nuova riga",
|
||||
"new-column": "Nuova colonna",
|
||||
"sort-column-by": "Ordina per \"{{title}}\"",
|
||||
"sort-column-ascending": "Ascendente",
|
||||
"sort-column-descending": "Discendente",
|
||||
"sort-column-clear": "Cancella l'ordinamento",
|
||||
"hide-column": "Nascondi la colonna \"{{title}}\"",
|
||||
"show-hide-columns": "Mostra/nascondi le colonne",
|
||||
"row-insert-above": "Inserisci una riga sopra",
|
||||
"row-insert-below": "Inserisci una riga sotto"
|
||||
},
|
||||
"abstract_search_option": {
|
||||
"remove_this_search_option": "Rimuovi questa opzione di ricerca",
|
||||
"failed_rendering": "Opzione di ricerca di rendering non riuscita: {{dto}} con errore: {{error}} {{stack}}"
|
||||
},
|
||||
"ancestor": {
|
||||
"label": "Antenato"
|
||||
},
|
||||
"add_label": {
|
||||
"add_label": "Aggiungi etichetta",
|
||||
"label_name_placeholder": "nome dell'etichetta",
|
||||
"new_value_placeholder": "nuovo valore",
|
||||
"to_value": "al valore"
|
||||
},
|
||||
"update_label_value": {
|
||||
"to_value": "al valore",
|
||||
"label_name_placeholder": "nome dell'etichetta"
|
||||
},
|
||||
"delete_label": {
|
||||
"delete_label": "Elimina etichetta",
|
||||
"label_name_placeholder": "nome dell'etichetta",
|
||||
"label_name_title": "Sono ammessi i caratteri alfanumerici, il carattere di sottolineato e i due punti."
|
||||
},
|
||||
"tree-context-menu": {
|
||||
"move-to": "Muovi in...",
|
||||
"cut": "Taglia"
|
||||
},
|
||||
"electron_context_menu": {
|
||||
"cut": "Taglia",
|
||||
"copy": "Copia",
|
||||
"paste": "Incolla",
|
||||
"copy-link": "Copia collegamento",
|
||||
"paste-as-plain-text": "Incolla come testo semplice"
|
||||
},
|
||||
"editing": {
|
||||
"editor_type": {
|
||||
"multiline-toolbar": "Mostra la barra degli strumenti su più linee se non entra."
|
||||
}
|
||||
},
|
||||
"edit_button": {
|
||||
"edit_this_note": "Modifica questa nota"
|
||||
},
|
||||
"shortcuts": {
|
||||
"shortcuts": "Scorciatoie"
|
||||
},
|
||||
"shared_switch": {
|
||||
"toggle-on-title": "Condividi la nota",
|
||||
"toggle-off-title": "Non condividere la nota"
|
||||
},
|
||||
"search_string": {
|
||||
"search_prefix": "Cerca:"
|
||||
},
|
||||
"attachment_detail": {
|
||||
"open_help_page": "Apri la pagina di aiuto sugli allegati"
|
||||
},
|
||||
"search_definition": {
|
||||
"ancestor": "antenato",
|
||||
"debug": "debug",
|
||||
"action": "azione",
|
||||
"add_search_option": "Aggiungi un opzione di ricerca:",
|
||||
"search_string": "cerca la stringa",
|
||||
"limit": "limite"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Chiudi"
|
||||
},
|
||||
"board_view": {
|
||||
"insert-below": "Inserisci sotto",
|
||||
"delete-column": "Elimina la colonna",
|
||||
"delete-column-confirmation": "Sei sicuro di vole eliminare questa colonna? Il corrispondente attributo sarà eliminato anche nelle note sotto questa colonna."
|
||||
},
|
||||
"backup": {
|
||||
"enable_weekly_backup": "Abilita le archiviazioni settimanali",
|
||||
"enable_monthly_backup": "Abilita le archiviazioni mensili",
|
||||
"backup_recommendation": "Si raccomanda di mantenere attive le archiviazioni, sebbene ciò possa rendere l'avvio dell'applicazione lento con database grandi e/o dispositivi di archiviazione lenti.",
|
||||
"backup_now": "Archivia adesso",
|
||||
"backup_database_now": "Archivia il database adesso",
|
||||
"existing_backups": "Backup esistenti",
|
||||
"date-and-time": "Data e ora",
|
||||
"path": "Percorso",
|
||||
"database_backed_up_to": "Il database è stato archiviato in {{backupFilePath}}",
|
||||
"enable_daily_backup": "Abilita le archiviazioni giornaliere",
|
||||
"no_backup_yet": "Ancora nessuna archiviazione"
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Aggiorna"
|
||||
},
|
||||
"consistency_checks": {
|
||||
"find_and_fix_button": "Trova e correggi i problemi di coerenza",
|
||||
"finding_and_fixing_message": "In cerca e correzione dei problemi di coerenza...",
|
||||
"issues_fixed_message": "Qualsiasi problema di coerenza che possa essere stato trovato ora è corretto."
|
||||
},
|
||||
"database_integrity_check": {
|
||||
"check_button": "Controllo dell'integrità del database",
|
||||
"checking_integrity": "Controllo dell'integrità del database in corso...",
|
||||
"title": "Controllo di Integrità del database",
|
||||
"description": "Controllerà che il database non sia corrotto a livello SQLite. Può durare un po' di tempo, a seconda della grandezza del DB.",
|
||||
"integrity_check_failed": "Controllo di integrità fallito: {{results}}"
|
||||
},
|
||||
"sync": {
|
||||
"title": "Sincronizza",
|
||||
"force_full_sync_button": "Forza una sincronizzazione completa",
|
||||
"failed": "Sincronizzazione fallita: {{message}}"
|
||||
},
|
||||
"sync_2": {
|
||||
"config_title": "Configurazione per la Sincronizzazione",
|
||||
"proxy_label": "Server Proxy per la sincronizzazione (opzionale)",
|
||||
"test_title": "Test di sincronizzazione",
|
||||
"timeout": "Timeout per la sincronizzazione",
|
||||
"timeout_unit": "millisecondi",
|
||||
"save": "Salva",
|
||||
"help": "Aiuto"
|
||||
},
|
||||
"search_engine": {
|
||||
"save_button": "Salva"
|
||||
},
|
||||
"sql_table_schemas": {
|
||||
"tables": "Tabelle"
|
||||
},
|
||||
"tab_row": {
|
||||
"close_tab": "Chiudi la scheda",
|
||||
"add_new_tab": "Aggiungi una nuova scheda",
|
||||
"close": "Chiudi",
|
||||
"close_other_tabs": "Chiudi le altre schede",
|
||||
"close_right_tabs": "Chiudi le schede a destra",
|
||||
"close_all_tabs": "Chiudi tutte le schede",
|
||||
"reopen_last_tab": "Riapri l'ultima scheda chiusa",
|
||||
"move_tab_to_new_window": "Sposta questa scheda in una nuova finestra",
|
||||
"copy_tab_to_new_window": "Copia questa scheda in una nuova finestra",
|
||||
"new_tab": "Nuova scheda"
|
||||
},
|
||||
"toc": {
|
||||
"table_of_contents": "Sommario"
|
||||
},
|
||||
"table_of_contents": {
|
||||
"title": "Sommario"
|
||||
},
|
||||
"tray": {
|
||||
"title": "Vassoio di Sistema",
|
||||
"enable_tray": "Abilita il vassoio (Trilium necessita di essere riavviato affinché la modifica abbia effetto)"
|
||||
},
|
||||
"heading_style": {
|
||||
"title": "Stile dell'Intestazione",
|
||||
"plain": "Normale",
|
||||
"underline": "Sottolineato",
|
||||
"markdown": "Stile Markdown"
|
||||
},
|
||||
"highlights_list": {
|
||||
"title": "Punti salienti"
|
||||
},
|
||||
"highlights_list_2": {
|
||||
"title": "Punti salienti",
|
||||
"options": "Opzioni"
|
||||
},
|
||||
"quick-search": {
|
||||
"placeholder": "Ricerca rapida",
|
||||
"searching": "Ricerca in corso..."
|
||||
}
|
||||
}
|
||||
1398
apps/client/src/translations/ja/translation.json
Normal file
1398
apps/client/src/translations/ja/translation.json
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user