mirror of
https://github.com/zadam/trilium.git
synced 2026-02-24 15:20:52 +01:00
Compare commits
544 Commits
standalone
...
renovate/j
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7f2d8ee30 | ||
|
|
cfb56cb143 | ||
|
|
477e516473 | ||
|
|
fd601eac5b | ||
|
|
df4fa42acd | ||
|
|
b06d390df5 | ||
|
|
7f013a58f5 | ||
|
|
1fd0fb03fa | ||
|
|
7ec718218e | ||
|
|
b5300e5b86 | ||
|
|
8d233e66e1 | ||
|
|
39e0d5b629 | ||
|
|
90844d5bc2 | ||
|
|
29df06626b | ||
|
|
d28661fee3 | ||
|
|
dc8c10e531 | ||
|
|
538e1f0fdd | ||
|
|
eaf0c690e1 | ||
|
|
a4a3d6a82c | ||
|
|
a3e4044fec | ||
|
|
f380df9c01 | ||
|
|
83fc82a615 | ||
|
|
eaf3632fc9 | ||
|
|
1d947f26ff | ||
|
|
34a08be4cd | ||
|
|
f84a4c4856 | ||
|
|
47aa24d0f4 | ||
|
|
e6e132e905 | ||
|
|
ad2df957c7 | ||
|
|
818ca2c2ab | ||
|
|
72c34eb491 | ||
|
|
22341bf0b1 | ||
|
|
c735870b95 | ||
|
|
56f796bf80 | ||
|
|
225693fa79 | ||
|
|
7f760bff17 | ||
|
|
6b4da33729 | ||
|
|
82cae8ffbf | ||
|
|
31dbbb1881 | ||
|
|
31de1e007a | ||
|
|
a2d0655a75 | ||
|
|
269209dd31 | ||
|
|
32082927b2 | ||
|
|
c10d0b6349 | ||
|
|
11ff1266e5 | ||
|
|
8b5717ff7f | ||
|
|
e69f6bef2c | ||
|
|
2a17a322c2 | ||
|
|
26ddb76338 | ||
|
|
f62f156c93 | ||
|
|
f4b6c65bad | ||
|
|
0a08399d9e | ||
|
|
df1adaad3a | ||
|
|
33b1490de0 | ||
|
|
286720bdbf | ||
|
|
1441ac67ab | ||
|
|
d245fdd1b8 | ||
|
|
e9c9b456e0 | ||
|
|
d9eafff7df | ||
|
|
94eb19d879 | ||
|
|
d7b585230a | ||
|
|
16ed14f85a | ||
|
|
93e59cc3b6 | ||
|
|
c38220892b | ||
|
|
4ef72fb35b | ||
|
|
3f23ce095c | ||
|
|
0ead246ce7 | ||
|
|
0f8259fdf7 | ||
|
|
ebb180b0ab | ||
|
|
c03f50583e | ||
|
|
b8a6cf0099 | ||
|
|
ad3cdc3364 | ||
|
|
d924d3fa4f | ||
|
|
dd4a8c08c8 | ||
|
|
52f2e800e7 | ||
|
|
8d94b62db0 | ||
|
|
c3eb483224 | ||
|
|
e7b1e0a81f | ||
|
|
ca672c68a3 | ||
|
|
416e11a32b | ||
|
|
bbaa2db377 | ||
|
|
cf4e412ab8 | ||
|
|
48ac88dbfe | ||
|
|
4980e9a15b | ||
|
|
290a2ab902 | ||
|
|
6a04d8fce1 | ||
|
|
7286ac743f | ||
|
|
41b6b5f615 | ||
|
|
d0572f7691 | ||
|
|
a8210844cb | ||
|
|
c5c39cedc4 | ||
|
|
8d6ae2da82 | ||
|
|
9eea6b3645 | ||
|
|
6d9638970d | ||
|
|
ecd3638298 | ||
|
|
bbde0e4d24 | ||
|
|
299f694aa9 | ||
|
|
2675698d3a | ||
|
|
3056f3cfcf | ||
|
|
7310d8af30 | ||
|
|
b62f40f8c9 | ||
|
|
ae1aac02ae | ||
|
|
e19f344dc1 | ||
|
|
1525ecdb05 | ||
|
|
4f6a13b2c4 | ||
|
|
4747297adc | ||
|
|
f753974800 | ||
|
|
bd4002529c | ||
|
|
00588eb099 | ||
|
|
81420b6168 | ||
|
|
fe74d2aec9 | ||
|
|
6514701c6a | ||
|
|
9e206ce7ea | ||
|
|
b32ad68e4f | ||
|
|
dfb5322b1a | ||
|
|
47859d401e | ||
|
|
5da90f9e16 | ||
|
|
4b098e2008 | ||
|
|
b4cd66db50 | ||
|
|
4847f4094a | ||
|
|
3fb34e6ae1 | ||
|
|
135ed32374 | ||
|
|
9b1fc77d56 | ||
|
|
5b751fd6e2 | ||
|
|
39ece711d9 | ||
|
|
a77b5601be | ||
|
|
8b5d88bf2b | ||
|
|
1f602f9cad | ||
|
|
5588042ab6 | ||
|
|
bc89bc8270 | ||
|
|
60ae094d3b | ||
|
|
a9facc7ce2 | ||
|
|
f200ac898a | ||
|
|
56ce25b8e8 | ||
|
|
4d5d9b4b70 | ||
|
|
b97ab913bf | ||
|
|
9fe7bdf79b | ||
|
|
4ebc4ece34 | ||
|
|
0110b3c4a2 | ||
|
|
fb20d4998a | ||
|
|
bd06c530e4 | ||
|
|
cd4505bcf0 | ||
|
|
173f4a23a5 | ||
|
|
b33d4e64b9 | ||
|
|
a4c95132bb | ||
|
|
095e797a02 | ||
|
|
aaec171d94 | ||
|
|
42b28993b2 | ||
|
|
09a39379ef | ||
|
|
29f7370c72 | ||
|
|
a07dcef2c4 | ||
|
|
6e696e1123 | ||
|
|
f0b1aa914d | ||
|
|
ce1ae2c9bd | ||
|
|
29597ddb48 | ||
|
|
1c1421fe3a | ||
|
|
918a52005e | ||
|
|
a3564b879f | ||
|
|
b78f3bbaa7 | ||
|
|
4cbdb5a073 | ||
|
|
758021e10c | ||
|
|
374e3560c3 | ||
|
|
57a3524cc3 | ||
|
|
9af4773b45 | ||
|
|
6942773965 | ||
|
|
734b3ee519 | ||
|
|
1b80fa8df2 | ||
|
|
afd6a05e0f | ||
|
|
5a4bd1933d | ||
|
|
a25dfce410 | ||
|
|
fc0490bc6a | ||
|
|
29cdd1d028 | ||
|
|
419e87b0de | ||
|
|
75c7d55e01 | ||
|
|
e006550b9f | ||
|
|
2a424f8dc4 | ||
|
|
5036518458 | ||
|
|
297cbbd8b3 | ||
|
|
87a89f709a | ||
|
|
6f1991e20e | ||
|
|
700de58686 | ||
|
|
57e1208c27 | ||
|
|
b33fe2ca3a | ||
|
|
3c3e73edae | ||
|
|
ec4fd371b5 | ||
|
|
555b138a90 | ||
|
|
c139ff776c | ||
|
|
0c6b5e3b8e | ||
|
|
1138f9a0e9 | ||
|
|
4955bd782b | ||
|
|
516f0052ef | ||
|
|
f4e82acc67 | ||
|
|
a5806c0d1d | ||
|
|
bf302a84a9 | ||
|
|
fcc740d592 | ||
|
|
cee16dc3dc | ||
|
|
47601cd1da | ||
|
|
092a60fdd9 | ||
|
|
e8e7568bdc | ||
|
|
4caca56e3b | ||
|
|
e4432e6feb | ||
|
|
d8275e7ea8 | ||
|
|
952dc634b4 | ||
|
|
7dceca475d | ||
|
|
62a78bc272 | ||
|
|
6aaf277b45 | ||
|
|
a1c61768c4 | ||
|
|
8e4c88c10c | ||
|
|
b57780519c | ||
|
|
c07c4013be | ||
|
|
768211cc26 | ||
|
|
b4a31503ee | ||
|
|
6c2b3e238c | ||
|
|
f2ff834b9c | ||
|
|
86e1688358 | ||
|
|
d259eb1f9d | ||
|
|
568a668e9f | ||
|
|
0621dfbac7 | ||
|
|
827bb9a32f | ||
|
|
fd08654dd5 | ||
|
|
e5d750722e | ||
|
|
b43c4ad666 | ||
|
|
c9f93a4706 | ||
|
|
a38834f7e2 | ||
|
|
fcfc6f6476 | ||
|
|
b23a5348b5 | ||
|
|
782cd59407 | ||
|
|
7964bd3be4 | ||
|
|
3d41ce13b1 | ||
|
|
6f0881ab8a | ||
|
|
a6309715f3 | ||
|
|
5a06193e65 | ||
|
|
4912834537 | ||
|
|
d64f2c72b7 | ||
|
|
358d06a402 | ||
|
|
5deabe4260 | ||
|
|
1b1162e26e | ||
|
|
30ad5d531c | ||
|
|
99efc73e93 | ||
|
|
17c0071dd1 | ||
|
|
a26bec047f | ||
|
|
748e7cc1df | ||
|
|
f653c86965 | ||
|
|
58a41e58ee | ||
|
|
309a55f276 | ||
|
|
df96c6b9fa | ||
|
|
d779e078c7 | ||
|
|
ae224151a0 | ||
|
|
9f11717b69 | ||
|
|
ea25477e3d | ||
|
|
82576c9703 | ||
|
|
80f1fc4c7c | ||
|
|
41cd4bcef6 | ||
|
|
46a414e155 | ||
|
|
70a903f811 | ||
|
|
52db410c82 | ||
|
|
08da8d73e0 | ||
|
|
81a572af25 | ||
|
|
23c50f34fe | ||
|
|
70aa115933 | ||
|
|
0b8cba78d5 | ||
|
|
d8806eaa04 | ||
|
|
b8bc85856b | ||
|
|
cc097c5414 | ||
|
|
7551d0e044 | ||
|
|
489a88b8da | ||
|
|
48013dc264 | ||
|
|
4ee9d45dfc | ||
|
|
e00150a876 | ||
|
|
71668f8f8d | ||
|
|
b71424d239 | ||
|
|
d1a3bceaa6 | ||
|
|
483c57029a | ||
|
|
7e6daf5b36 | ||
|
|
b658253687 | ||
|
|
80b488deec | ||
|
|
10cf1a371e | ||
|
|
81445901fa | ||
|
|
f645d9d721 | ||
|
|
900bfdff9d | ||
|
|
108ca5afb5 | ||
|
|
3df03a551c | ||
|
|
6ffbe19667 | ||
|
|
e3172ebf1c | ||
|
|
9b2876a8ff | ||
|
|
3db2c910e0 | ||
|
|
2799e4392f | ||
|
|
61963fcfda | ||
|
|
b0a3d54276 | ||
|
|
2135412c84 | ||
|
|
7a534c3ea7 | ||
|
|
a6e596a5e3 | ||
|
|
8b3e3c2c3a | ||
|
|
ec8b0a3801 | ||
|
|
197b769838 | ||
|
|
1ba498c0e3 | ||
|
|
5550cb7b95 | ||
|
|
06a005acec | ||
|
|
2103be9d28 | ||
|
|
a02f3c4440 | ||
|
|
4b8d341e00 | ||
|
|
964633f426 | ||
|
|
d11fb38280 | ||
|
|
04f4530990 | ||
|
|
5a77318a9e | ||
|
|
9ed2894a0c | ||
|
|
e0766ad439 | ||
|
|
67acfaab62 | ||
|
|
10b5d29107 | ||
|
|
297dd41170 | ||
|
|
1364223599 | ||
|
|
a6b7761dfa | ||
|
|
2e6290c514 | ||
|
|
78f4928611 | ||
|
|
d044fce9c1 | ||
|
|
11fa815e13 | ||
|
|
8d917eb970 | ||
|
|
e411e5f2cf | ||
|
|
fea8de89c6 | ||
|
|
48773636ca | ||
|
|
5a3c7355c1 | ||
|
|
4afbabb977 | ||
|
|
afa9fe3063 | ||
|
|
178ac088b4 | ||
|
|
b2ebaf111f | ||
|
|
ffd5ebbe79 | ||
|
|
6b78bfecb4 | ||
|
|
9c2b01e3c9 | ||
|
|
dca201ce42 | ||
|
|
d3c0a44c00 | ||
|
|
33ea2de231 | ||
|
|
43ebbfc321 | ||
|
|
1e5b294eb3 | ||
|
|
29855112c8 | ||
|
|
8af7b3c81a | ||
|
|
b72b82ff1a | ||
|
|
1588c8103c | ||
|
|
15e569dcea | ||
|
|
3774ea3768 | ||
|
|
0a9c6a3119 | ||
|
|
a6cbde88bb | ||
|
|
4bdb407404 | ||
|
|
4568cedcd3 | ||
|
|
f290317acc | ||
|
|
645279c8fa | ||
|
|
09436f8d65 | ||
|
|
b616e0e5f9 | ||
|
|
f06a0852a1 | ||
|
|
9e688138be | ||
|
|
5d46970a38 | ||
|
|
ecc441c074 | ||
|
|
f2ce3678c4 | ||
|
|
c9ad390647 | ||
|
|
92acc7accd | ||
|
|
9c13f36ca0 | ||
|
|
fe4a11c5ad | ||
|
|
e29b238161 | ||
|
|
2ef4eb7eae | ||
|
|
7b230706cb | ||
|
|
5a2b04adba | ||
|
|
50dcd3ba44 | ||
|
|
740b02952f | ||
|
|
5d3d42ffdd | ||
|
|
866d3110da | ||
|
|
7a3e7fccec | ||
|
|
3107bc8840 | ||
|
|
2d34cdef5e | ||
|
|
bd1f0909a2 | ||
|
|
ef75de63fe | ||
|
|
a739d28563 | ||
|
|
66ff009b72 | ||
|
|
a68e82c1c8 | ||
|
|
46556c1c14 | ||
|
|
7be637798f | ||
|
|
9b3396349e | ||
|
|
ccff210b4c | ||
|
|
a2264847b6 | ||
|
|
7d103f8c50 | ||
|
|
f3dccc0aec | ||
|
|
311b1d8a64 | ||
|
|
f3094e3079 | ||
|
|
f3b37b16d5 | ||
|
|
5f16ecf02d | ||
|
|
8b75287827 | ||
|
|
bb38e806cd | ||
|
|
8cbc15f1b0 | ||
|
|
870524f9cf | ||
|
|
218343ca14 | ||
|
|
61953fd713 | ||
|
|
62ddf3a11b | ||
|
|
be12658864 | ||
|
|
b618e5a00f | ||
|
|
5da9963f31 | ||
|
|
34e885812f | ||
|
|
a9ac11452d | ||
|
|
04b91308b1 | ||
|
|
b09ef222f5 | ||
|
|
2d0ed06d50 | ||
|
|
8dd7cf6085 | ||
|
|
4999bd4f1e | ||
|
|
22f408addb | ||
|
|
9ca1dbe638 | ||
|
|
26662952e3 | ||
|
|
f0c9fa4ca3 | ||
|
|
b51aa1dd71 | ||
|
|
846253c9e3 | ||
|
|
6ab6ea97ac | ||
|
|
bf41f70b98 | ||
|
|
67ddbedd08 | ||
|
|
2573e219dc | ||
|
|
7e368678ab | ||
|
|
4a9fcf7ab6 | ||
|
|
65856c61c5 | ||
|
|
b5a97bffab | ||
|
|
e6d728715f | ||
|
|
54a52f0589 | ||
|
|
badfa23f86 | ||
|
|
4c36a9cca9 | ||
|
|
30ccd3487a | ||
|
|
75e012f2c9 | ||
|
|
5ecb1d1e2d | ||
|
|
f8c24c838a | ||
|
|
4ad9cfcdf4 | ||
|
|
a57253dd35 | ||
|
|
222e65bd45 | ||
|
|
3192ea3383 | ||
|
|
3a27f873cd | ||
|
|
e8fb279036 | ||
|
|
21ec7078d2 | ||
|
|
94937e9fa4 | ||
|
|
36401a20b8 | ||
|
|
8d1c4e4661 | ||
|
|
14362060c8 | ||
|
|
de47e94f62 | ||
|
|
c78ed78bf6 | ||
|
|
7674c95124 | ||
|
|
ec522c20b2 | ||
|
|
81f9578526 | ||
|
|
20bca751d4 | ||
|
|
49b5c49776 | ||
|
|
5d514fae61 | ||
|
|
9e17e93dd7 | ||
|
|
7f70c641dc | ||
|
|
7e3af4b7bc | ||
|
|
59ff4c0aef | ||
|
|
875e6b8e53 | ||
|
|
fafc44de7c | ||
|
|
e0d7eb10d5 | ||
|
|
ae01eb28a3 | ||
|
|
637c66c04f | ||
|
|
1c061e4428 | ||
|
|
cbe0626572 | ||
|
|
86dc98174a | ||
|
|
f0ac8ea977 | ||
|
|
35d4c2cdfc | ||
|
|
394f7c0d09 | ||
|
|
b83eee9bdc | ||
|
|
e41b2e8d31 | ||
|
|
d93cec2bfd | ||
|
|
9eb87a39cd | ||
|
|
07818ec1df | ||
|
|
d4052dbe37 | ||
|
|
656f5e0a7f | ||
|
|
f3d415a3a7 | ||
|
|
fd8ab990bd | ||
|
|
0cc5e4dac3 | ||
|
|
8bbfff3cb2 | ||
|
|
93059798b0 | ||
|
|
33fae88cad | ||
|
|
4feb23e9ca | ||
|
|
c2b6b7ba72 | ||
|
|
fb76aee258 | ||
|
|
320b1829cc | ||
|
|
601f0255a4 | ||
|
|
b6cc2b227a | ||
|
|
cc7da4b948 | ||
|
|
1ae3be2fda | ||
|
|
5b4d35ea86 | ||
|
|
00735e6c8e | ||
|
|
66a42a38c9 | ||
|
|
05af1fba80 | ||
|
|
3b2dd0f5e9 | ||
|
|
1493a66a36 | ||
|
|
b4bf103fd8 | ||
|
|
94286becfd | ||
|
|
a68aade58c | ||
|
|
014201edf4 | ||
|
|
8ae6297148 | ||
|
|
5e0300aa8e | ||
|
|
80a7e18413 | ||
|
|
5c007cdebc | ||
|
|
ef6c733f93 | ||
|
|
e7d6658c7a | ||
|
|
43be0a1a3f | ||
|
|
5eb32744c3 | ||
|
|
89d39f5f2b | ||
|
|
1f4900dd1e | ||
|
|
1c561c1483 | ||
|
|
6baaf60b67 | ||
|
|
dde73f6c2b | ||
|
|
f445a49b34 | ||
|
|
29016d1cf5 | ||
|
|
c06435046b | ||
|
|
134422802f | ||
|
|
5e00d6a305 | ||
|
|
b5f0137d8e | ||
|
|
081d041cbc | ||
|
|
95e733a67c | ||
|
|
a664057312 | ||
|
|
5b1a2d93bf | ||
|
|
0323f95828 | ||
|
|
375838449f | ||
|
|
4562de8c2c | ||
|
|
68d21669e7 | ||
|
|
625e0cf159 | ||
|
|
551ef00c61 | ||
|
|
10518f6364 | ||
|
|
3c33b5b169 | ||
|
|
639b81b228 | ||
|
|
0c552eb0c0 | ||
|
|
ae723f9557 | ||
|
|
34d691341b | ||
|
|
8574a11cf7 | ||
|
|
3742cd4a51 | ||
|
|
d7d411caf9 | ||
|
|
000c31b66c | ||
|
|
fd7780abb0 | ||
|
|
c8a981e8d6 | ||
|
|
faac45784c | ||
|
|
f6b454cb9a | ||
|
|
563463782c | ||
|
|
19781bb14c | ||
|
|
7fd2bc30cc | ||
|
|
07f273fda4 | ||
|
|
b08126ec2b | ||
|
|
e0824a5426 | ||
|
|
c4f5471e13 | ||
|
|
99215c272c | ||
|
|
51325e2f4a | ||
|
|
bd7e47d8f0 | ||
|
|
457a7a03fb | ||
|
|
6e486c64f1 | ||
|
|
4f3575d765 | ||
|
|
f5f1b27754 |
57
.vscode/launch.json
vendored
Normal file
57
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch client (Chrome)",
|
||||
"request": "launch",
|
||||
"type": "chrome",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}/apps/client"
|
||||
},
|
||||
{
|
||||
"name": "Launch server",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/apps/server/src/main.ts",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx",
|
||||
"env": {
|
||||
"NODE_ENV": "development",
|
||||
"TRILIUM_ENV": "dev",
|
||||
"TRILIUM_DATA_DIR": "${input:trilium_data_dir}",
|
||||
"TRILIUM_RESOURCE_DIR": "${workspaceFolder}/apps/server/src"
|
||||
},
|
||||
"autoAttachChildProcesses": true,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"skipFiles": ["<node_internals>/**", "${workspaceFolder}/node_modules/**"]
|
||||
},
|
||||
{
|
||||
"name": "Launch Vitest with current test file",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"autoAttachChildProcesses": true,
|
||||
"program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
|
||||
"args": ["run", "${relativeFile}"],
|
||||
"smartStep": true,
|
||||
"console": "integratedTerminal",
|
||||
"skipFiles": ["<node_internals>/**", "**/node_modules/**"],
|
||||
"cwd": "${workspaceFolder}"
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Launch client (Chrome) and server",
|
||||
"configurations": ["Launch server","Launch client (Chrome)"],
|
||||
"stopAll": true
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "trilium_data_dir",
|
||||
"type": "promptString",
|
||||
"description": "Select Trilum Notes data directory",
|
||||
"default": "${workspaceFolder}/apps/server/data"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -10,4 +10,5 @@ Description above is a general rule and may be altered on case by case basis.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
You can report low severity vulnerabilities as GitHub issues, more severe vulnerabilities should be reported to the email [contact@eliandoran.me](mailto:contact@eliandoran.me)
|
||||
* For low severity vulnerabilities, they can be reported as GitHub issues.
|
||||
* For severe vulnerabilities, please report it using [GitHub Security Advisories](https://github.com/TriliumNext/Trilium/security/advisories).
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
{
|
||||
"name": "build-docs",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"description": "Build documentation from Trilium notes",
|
||||
"main": "src/main.ts",
|
||||
"bin": {
|
||||
"trilium-build-docs": "dist/cli.js"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "tsx ."
|
||||
"start": "tsx .",
|
||||
"cli": "tsx src/cli.ts",
|
||||
"build": "tsx scripts/build.ts"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Elian Doran <contact@eliandoran.me>",
|
||||
"license": "AGPL-3.0-only",
|
||||
"packageManager": "pnpm@10.29.1",
|
||||
"packageManager": "pnpm@10.30.1",
|
||||
"devDependencies": {
|
||||
"@redocly/cli": "2.15.1",
|
||||
"@redocly/cli": "2.19.1",
|
||||
"archiver": "7.0.1",
|
||||
"fs-extra": "11.3.3",
|
||||
"js-yaml": "4.1.1",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4",
|
||||
"typedoc": "0.28.16",
|
||||
"typedoc": "0.28.17",
|
||||
"typedoc-plugin-missing-exports": "4.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
23
apps/build-docs/scripts/build.ts
Normal file
23
apps/build-docs/scripts/build.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import BuildHelper from "../../../scripts/build-utils";
|
||||
|
||||
const build = new BuildHelper("apps/build-docs");
|
||||
|
||||
async function main() {
|
||||
// Build the CLI and other TypeScript files
|
||||
await build.buildBackend([
|
||||
"src/cli.ts",
|
||||
"src/main.ts",
|
||||
"src/build-docs.ts",
|
||||
"src/swagger.ts",
|
||||
"src/script-api.ts",
|
||||
"src/context.ts"
|
||||
]);
|
||||
|
||||
// Copy HTML template
|
||||
build.copy("src/index.html", "index.html");
|
||||
|
||||
// Copy node modules dependencies if needed
|
||||
build.copyNodeModules([ "better-sqlite3", "bindings", "file-uri-to-path" ]);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -13,8 +13,12 @@
|
||||
* Make sure to keep in line with backend's `script_context.ts`.
|
||||
*/
|
||||
|
||||
export type { default as AbstractBeccaEntity } from "../../server/src/becca/entities/abstract_becca_entity.js";
|
||||
export type { default as BAttachment } from "../../server/src/becca/entities/battachment.js";
|
||||
export type {
|
||||
default as AbstractBeccaEntity
|
||||
} from "../../server/src/becca/entities/abstract_becca_entity.js";
|
||||
export type {
|
||||
default as BAttachment
|
||||
} from "../../server/src/becca/entities/battachment.js";
|
||||
export type { default as BAttribute } from "../../server/src/becca/entities/battribute.js";
|
||||
export type { default as BBranch } from "../../server/src/becca/entities/bbranch.js";
|
||||
export type { default as BEtapiToken } from "../../server/src/becca/entities/betapi_token.js";
|
||||
@@ -31,6 +35,7 @@ export type { Api };
|
||||
const fakeNote = new BNote();
|
||||
|
||||
/**
|
||||
* The `api` global variable allows access to the backend script API, which is documented in {@link Api}.
|
||||
* The `api` global variable allows access to the backend script API,
|
||||
* which is documented in {@link Api}.
|
||||
*/
|
||||
export const api: Api = new BackendScriptApi(fakeNote, {});
|
||||
|
||||
@@ -1,19 +1,90 @@
|
||||
process.env.TRILIUM_INTEGRATION_TEST = "memory-no-store";
|
||||
process.env.TRILIUM_RESOURCE_DIR = "../server/src";
|
||||
// Only set TRILIUM_RESOURCE_DIR if not already set (e.g., by Nix wrapper)
|
||||
if (!process.env.TRILIUM_RESOURCE_DIR) {
|
||||
process.env.TRILIUM_RESOURCE_DIR = "../server/src";
|
||||
}
|
||||
process.env.NODE_ENV = "development";
|
||||
|
||||
import cls from "@triliumnext/server/src/services/cls.js";
|
||||
import { dirname, join, resolve } from "path";
|
||||
import archiver from "archiver";
|
||||
import { execSync } from "child_process";
|
||||
import { WriteStream } from "fs";
|
||||
import * as fs from "fs/promises";
|
||||
import * as fsExtra from "fs-extra";
|
||||
import archiver from "archiver";
|
||||
import { WriteStream } from "fs";
|
||||
import { execSync } from "child_process";
|
||||
import yaml from "js-yaml";
|
||||
import { dirname, join, resolve } from "path";
|
||||
|
||||
import BuildContext from "./context.js";
|
||||
|
||||
interface NoteMapping {
|
||||
rootNoteId: string;
|
||||
path: string;
|
||||
format: "markdown" | "html" | "share";
|
||||
ignoredFiles?: string[];
|
||||
exportOnly?: boolean;
|
||||
}
|
||||
|
||||
interface Config {
|
||||
baseUrl: string;
|
||||
noteMappings: NoteMapping[];
|
||||
}
|
||||
|
||||
const DOCS_ROOT = "../../../docs";
|
||||
const OUTPUT_DIR = "../../site";
|
||||
|
||||
// Load configuration from edit-docs-config.yaml
|
||||
async function loadConfig(configPath?: string): Promise<Config | null> {
|
||||
const pathsToTry = configPath
|
||||
? [resolve(configPath)]
|
||||
: [
|
||||
join(process.cwd(), "edit-docs-config.yaml"),
|
||||
join(__dirname, "../../../edit-docs-config.yaml")
|
||||
];
|
||||
|
||||
for (const path of pathsToTry) {
|
||||
try {
|
||||
const configContent = await fs.readFile(path, "utf-8");
|
||||
const config = yaml.load(configContent) as Config;
|
||||
|
||||
// Resolve all paths relative to the config file's directory
|
||||
const CONFIG_DIR = dirname(path);
|
||||
config.noteMappings = config.noteMappings.map((mapping) => ({
|
||||
...mapping,
|
||||
path: resolve(CONFIG_DIR, mapping.path)
|
||||
}));
|
||||
|
||||
return config;
|
||||
} catch (error) {
|
||||
if (error.code !== "ENOENT") {
|
||||
throw error; // rethrow unexpected errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null; // No config file found
|
||||
}
|
||||
|
||||
async function exportDocs(
|
||||
noteId: string,
|
||||
format: "markdown" | "html" | "share",
|
||||
outputPath: string,
|
||||
ignoredFiles?: string[]
|
||||
) {
|
||||
const zipFilePath = `output-${noteId}.zip`;
|
||||
try {
|
||||
const { exportToZipFile } = (await import("@triliumnext/server/src/services/export/zip.js"))
|
||||
.default;
|
||||
await exportToZipFile(noteId, format, zipFilePath, {});
|
||||
|
||||
const ignoredSet = ignoredFiles ? new Set(ignoredFiles) : undefined;
|
||||
await extractZip(zipFilePath, outputPath, ignoredSet);
|
||||
} finally {
|
||||
if (await fsExtra.exists(zipFilePath)) {
|
||||
await fsExtra.rm(zipFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function importAndExportDocs(sourcePath: string, outputSubDir: string) {
|
||||
const note = await importData(sourcePath);
|
||||
|
||||
@@ -21,15 +92,18 @@ async function importAndExportDocs(sourcePath: string, outputSubDir: string) {
|
||||
const zipName = outputSubDir || "user-guide";
|
||||
const zipFilePath = `output-${zipName}.zip`;
|
||||
try {
|
||||
const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js")).default;
|
||||
const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js"))
|
||||
.default;
|
||||
const branch = note.getParentBranches()[0];
|
||||
const taskContext = new (await import("@triliumnext/server/src/services/task_context.js")).default(
|
||||
"no-progress-reporting",
|
||||
"export",
|
||||
null
|
||||
);
|
||||
const taskContext = new (await import("@triliumnext/server/src/services/task_context.js"))
|
||||
.default(
|
||||
"no-progress-reporting",
|
||||
"export",
|
||||
null
|
||||
);
|
||||
const fileOutputStream = fsExtra.createWriteStream(zipFilePath);
|
||||
await exportToZip(taskContext, branch, "share", fileOutputStream);
|
||||
const { waitForStreamToFinish } = await import("@triliumnext/server/src/services/utils.js");
|
||||
await waitForStreamToFinish(fileOutputStream);
|
||||
|
||||
// Output to root directory if outputSubDir is empty, otherwise to subdirectory
|
||||
@@ -42,7 +116,7 @@ async function importAndExportDocs(sourcePath: string, outputSubDir: string) {
|
||||
}
|
||||
}
|
||||
|
||||
async function buildDocsInner() {
|
||||
async function buildDocsInner(config?: Config) {
|
||||
const i18n = await import("@triliumnext/server/src/services/i18n.js");
|
||||
await i18n.initializeTranslations();
|
||||
|
||||
@@ -53,18 +127,49 @@ async function buildDocsInner() {
|
||||
const beccaLoader = await import("../../server/src/becca/becca_loader.js");
|
||||
await beccaLoader.beccaLoaded;
|
||||
|
||||
// Build User Guide
|
||||
console.log("Building User Guide...");
|
||||
await importAndExportDocs(join(__dirname, DOCS_ROOT, "User Guide"), "user-guide");
|
||||
if (config) {
|
||||
// Config-based build (reads from edit-docs-config.yaml)
|
||||
console.log("Building documentation from config file...");
|
||||
|
||||
// Build Developer Guide
|
||||
console.log("Building Developer Guide...");
|
||||
await importAndExportDocs(join(__dirname, DOCS_ROOT, "Developer Guide"), "developer-guide");
|
||||
// Import all non-export-only mappings
|
||||
for (const mapping of config.noteMappings) {
|
||||
if (!mapping.exportOnly) {
|
||||
console.log(`Importing from ${mapping.path}...`);
|
||||
await importData(mapping.path);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy favicon.
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "favicon.ico"));
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "user-guide", "favicon.ico"));
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "developer-guide", "favicon.ico"));
|
||||
// Export all mappings
|
||||
for (const mapping of config.noteMappings) {
|
||||
if (mapping.exportOnly) {
|
||||
console.log(`Exporting ${mapping.format} to ${mapping.path}...`);
|
||||
await exportDocs(
|
||||
mapping.rootNoteId,
|
||||
mapping.format,
|
||||
mapping.path,
|
||||
mapping.ignoredFiles
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Legacy hardcoded build (for backward compatibility)
|
||||
console.log("Building User Guide...");
|
||||
await importAndExportDocs(join(__dirname, DOCS_ROOT, "User Guide"), "user-guide");
|
||||
|
||||
console.log("Building Developer Guide...");
|
||||
await importAndExportDocs(
|
||||
join(__dirname, DOCS_ROOT, "Developer Guide"),
|
||||
"developer-guide"
|
||||
);
|
||||
|
||||
// Copy favicon.
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico",
|
||||
join(OUTPUT_DIR, "favicon.ico"));
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico",
|
||||
join(OUTPUT_DIR, "user-guide", "favicon.ico"));
|
||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico",
|
||||
join(OUTPUT_DIR, "developer-guide", "favicon.ico"));
|
||||
}
|
||||
|
||||
console.log("Documentation built successfully!");
|
||||
}
|
||||
@@ -91,12 +196,13 @@ async function createImportZip(path: string) {
|
||||
zlib: { level: 0 }
|
||||
});
|
||||
|
||||
console.log("Archive path is ", resolve(path))
|
||||
console.log("Archive path is ", resolve(path));
|
||||
archive.directory(path, "/");
|
||||
|
||||
const outputStream = fsExtra.createWriteStream(inputFile);
|
||||
archive.pipe(outputStream);
|
||||
archive.finalize();
|
||||
const { waitForStreamToFinish } = await import("@triliumnext/server/src/services/utils.js");
|
||||
await waitForStreamToFinish(outputStream);
|
||||
|
||||
try {
|
||||
@@ -106,15 +212,15 @@ async function createImportZip(path: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function waitForStreamToFinish(stream: WriteStream) {
|
||||
return new Promise<void>((res, rej) => {
|
||||
stream.on("finish", () => res());
|
||||
stream.on("error", (err) => rej(err));
|
||||
});
|
||||
}
|
||||
|
||||
export async function extractZip(zipFilePath: string, outputPath: string, ignoredFiles?: Set<string>) {
|
||||
const { readZipFile, readContent } = (await import("@triliumnext/server/src/services/import/zip.js"));
|
||||
export async function extractZip(
|
||||
zipFilePath: string,
|
||||
outputPath: string,
|
||||
ignoredFiles?: Set<string>
|
||||
) {
|
||||
const { readZipFile, readContent } = (await import(
|
||||
"@triliumnext/server/src/services/import/zip.js"
|
||||
));
|
||||
await readZipFile(await fs.readFile(zipFilePath), async (zip, entry) => {
|
||||
// We ignore directories since they can appear out of order anyway.
|
||||
if (!entry.fileName.endsWith("/") && !ignoredFiles?.has(entry.fileName)) {
|
||||
@@ -129,6 +235,27 @@ export async function extractZip(zipFilePath: string, outputPath: string, ignore
|
||||
});
|
||||
}
|
||||
|
||||
export async function buildDocsFromConfig(configPath?: string, gitRootDir?: string) {
|
||||
const config = await loadConfig(configPath);
|
||||
|
||||
if (gitRootDir) {
|
||||
// Build the share theme if we have a gitRootDir (for Trilium project)
|
||||
execSync(`pnpm run --filter share-theme build`, {
|
||||
stdio: "inherit",
|
||||
cwd: gitRootDir
|
||||
});
|
||||
}
|
||||
|
||||
// Trigger the actual build.
|
||||
await new Promise((res, rej) => {
|
||||
cls.init(() => {
|
||||
buildDocsInner(config ?? undefined)
|
||||
.catch(rej)
|
||||
.then(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default async function buildDocs({ gitRootDir }: BuildContext) {
|
||||
// Build the share theme.
|
||||
execSync(`pnpm run --filter share-theme build`, {
|
||||
|
||||
89
apps/build-docs/src/cli.ts
Normal file
89
apps/build-docs/src/cli.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import packageJson from "../package.json" with { type: "json" };
|
||||
import { buildDocsFromConfig } from "./build-docs.js";
|
||||
|
||||
// Parse command-line arguments
|
||||
function parseArgs() {
|
||||
const args = process.argv.slice(2);
|
||||
let configPath: string | undefined;
|
||||
let showHelp = false;
|
||||
let showVersion = false;
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] === "--config" || args[i] === "-c") {
|
||||
configPath = args[i + 1];
|
||||
if (!configPath) {
|
||||
console.error("Error: --config/-c requires a path argument");
|
||||
process.exit(1);
|
||||
}
|
||||
i++; // Skip the next argument as it's the value
|
||||
} else if (args[i] === "--help" || args[i] === "-h") {
|
||||
showHelp = true;
|
||||
} else if (args[i] === "--version" || args[i] === "-v") {
|
||||
showVersion = true;
|
||||
}
|
||||
}
|
||||
|
||||
return { configPath, showHelp, showVersion };
|
||||
}
|
||||
|
||||
function getVersion(): string {
|
||||
return packageJson.version;
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
const version = getVersion();
|
||||
console.log(`
|
||||
Usage: trilium-build-docs [options]
|
||||
|
||||
Options:
|
||||
-c, --config <path> Path to the configuration file
|
||||
(default: edit-docs-config.yaml in current directory)
|
||||
-h, --help Display this help message
|
||||
-v, --version Display version information
|
||||
|
||||
Description:
|
||||
Builds documentation from Trilium note structure and exports to various formats.
|
||||
Configuration file should be in YAML format with the following structure:
|
||||
|
||||
baseUrl: "https://example.com"
|
||||
noteMappings:
|
||||
- rootNoteId: "noteId123"
|
||||
path: "docs"
|
||||
format: "markdown"
|
||||
- rootNoteId: "noteId456"
|
||||
path: "public/docs"
|
||||
format: "share"
|
||||
exportOnly: true
|
||||
|
||||
Version: ${version}
|
||||
`);
|
||||
}
|
||||
|
||||
function printVersion() {
|
||||
const version = getVersion();
|
||||
console.log(version);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const { configPath, showHelp, showVersion } = parseArgs();
|
||||
|
||||
if (showHelp) {
|
||||
printHelp();
|
||||
process.exit(0);
|
||||
} else if (showVersion) {
|
||||
printVersion();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
try {
|
||||
await buildDocsFromConfig(configPath);
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error("Error building documentation:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -13,16 +13,19 @@
|
||||
* Make sure to keep in line with frontend's `script_context.ts`.
|
||||
*/
|
||||
|
||||
export type { default as BasicWidget } from "../../client/src/widgets/basic_widget.js";
|
||||
export type { default as FAttachment } from "../../client/src/entities/fattachment.js";
|
||||
export type { default as FAttribute } from "../../client/src/entities/fattribute.js";
|
||||
export type { default as FBranch } from "../../client/src/entities/fbranch.js";
|
||||
export type { default as FNote } from "../../client/src/entities/fnote.js";
|
||||
export type { Api } from "../../client/src/services/frontend_script_api.js";
|
||||
export type { default as NoteContextAwareWidget } from "../../client/src/widgets/note_context_aware_widget.js";
|
||||
export type { default as BasicWidget } from "../../client/src/widgets/basic_widget.js";
|
||||
export type {
|
||||
default as NoteContextAwareWidget
|
||||
} from "../../client/src/widgets/note_context_aware_widget.js";
|
||||
export type { default as RightPanelWidget } from "../../client/src/widgets/right_panel_widget.js";
|
||||
|
||||
import FrontendScriptApi, { type Api } from "../../client/src/services/frontend_script_api.js";
|
||||
|
||||
//@ts-expect-error
|
||||
|
||||
// @ts-expect-error - FrontendScriptApi is not directly exportable as Api without this simulation.
|
||||
export const api: Api = new FrontendScriptApi();
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { join } from "path";
|
||||
import BuildContext from "./context";
|
||||
import buildSwagger from "./swagger";
|
||||
import { cpSync, existsSync, mkdirSync, rmSync } from "fs";
|
||||
import { join } from "path";
|
||||
|
||||
import buildDocs from "./build-docs";
|
||||
import BuildContext from "./context";
|
||||
import buildScriptApi from "./script-api";
|
||||
import buildSwagger from "./swagger";
|
||||
|
||||
const context: BuildContext = {
|
||||
gitRootDir: join(__dirname, "../../../"),
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { execSync } from "child_process";
|
||||
import BuildContext from "./context";
|
||||
import { join } from "path";
|
||||
|
||||
import BuildContext from "./context";
|
||||
|
||||
export default function buildScriptApi({ baseDir, gitRootDir }: BuildContext) {
|
||||
// Generate types
|
||||
execSync(`pnpm typecheck`, { stdio: "inherit", cwd: gitRootDir });
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import BuildContext from "./context";
|
||||
import { join } from "path";
|
||||
import { execSync } from "child_process";
|
||||
import { mkdirSync } from "fs";
|
||||
import { join } from "path";
|
||||
|
||||
import BuildContext from "./context";
|
||||
|
||||
interface BuildInfo {
|
||||
specPath: string;
|
||||
@@ -27,6 +28,9 @@ export default function buildSwagger({ baseDir, gitRootDir }: BuildContext) {
|
||||
const absSpecPath = join(gitRootDir, specPath);
|
||||
const targetDir = join(baseDir, outDir);
|
||||
mkdirSync(targetDir, { recursive: true });
|
||||
execSync(`pnpm redocly build-docs ${absSpecPath} -o ${targetDir}/index.html`, { stdio: "inherit" });
|
||||
execSync(
|
||||
`pnpm redocly build-docs ${absSpecPath} -o ${targetDir}/index.html`,
|
||||
{ stdio: "inherit" }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": [],
|
||||
"include": [
|
||||
"scripts/**/*.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../server"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"entryPoints": [
|
||||
"src/backend_script_entrypoint.ts"
|
||||
],
|
||||
"tsconfig": "tsconfig.app.json",
|
||||
"plugin": [
|
||||
"typedoc-plugin-missing-exports"
|
||||
]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"entryPoints": [
|
||||
"src/frontend_script_entrypoint.ts"
|
||||
],
|
||||
"tsconfig": "tsconfig.app.json",
|
||||
"plugin": [
|
||||
"typedoc-plugin-missing-exports"
|
||||
]
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"@mermaid-js/layout-elk": "0.2.0",
|
||||
"@mind-elixir/node-menu": "5.0.1",
|
||||
"@popperjs/core": "2.11.8",
|
||||
"@preact/signals": "2.6.2",
|
||||
"@preact/signals": "2.8.1",
|
||||
"@triliumnext/ckeditor5": "workspace:*",
|
||||
"@triliumnext/codemirror": "workspace:*",
|
||||
"@triliumnext/commons": "workspace:*",
|
||||
@@ -44,24 +44,24 @@
|
||||
"draggabilly": "3.0.0",
|
||||
"force-graph": "1.51.1",
|
||||
"globals": "17.3.0",
|
||||
"i18next": "25.8.0",
|
||||
"i18next": "25.8.13",
|
||||
"i18next-http-backend": "3.0.2",
|
||||
"jquery": "4.0.0",
|
||||
"jquery.fancytree": "2.38.5",
|
||||
"jsplumb": "2.15.6",
|
||||
"katex": "0.16.28",
|
||||
"katex": "0.16.33",
|
||||
"knockout": "3.5.1",
|
||||
"leaflet": "1.9.4",
|
||||
"leaflet-gpx": "2.2.0",
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "17.0.1",
|
||||
"mermaid": "11.12.2",
|
||||
"mind-elixir": "5.8.0",
|
||||
"marked": "17.0.3",
|
||||
"mermaid": "11.12.3",
|
||||
"mind-elixir": "5.9.0",
|
||||
"normalize.css": "8.0.1",
|
||||
"panzoom": "9.4.3",
|
||||
"preact": "10.28.3",
|
||||
"preact": "10.28.4",
|
||||
"react-i18next": "16.5.4",
|
||||
"react-window": "2.2.6",
|
||||
"react-window": "2.2.7",
|
||||
"reveal.js": "5.2.1",
|
||||
"svg-pan-zoom": "3.6.2",
|
||||
"tabulator-tables": "6.3.1",
|
||||
@@ -69,16 +69,16 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ckeditor/ckeditor5-inspector": "5.0.0",
|
||||
"@prefresh/vite": "2.4.11",
|
||||
"@prefresh/vite": "2.4.12",
|
||||
"@types/bootstrap": "5.2.10",
|
||||
"@types/jquery": "3.5.33",
|
||||
"@types/jquery": "3.5.34",
|
||||
"@types/leaflet": "1.9.21",
|
||||
"@types/leaflet-gpx": "1.3.8",
|
||||
"@types/mark.js": "8.11.12",
|
||||
"@types/reveal.js": "5.2.2",
|
||||
"@types/tabulator-tables": "6.3.1",
|
||||
"copy-webpack-plugin": "13.0.1",
|
||||
"happy-dom": "20.5.0",
|
||||
"happy-dom": "20.7.0",
|
||||
"lightningcss": "1.31.1",
|
||||
"script-loader": "0.7.2",
|
||||
"vite-plugin-static-copy": "3.2.0"
|
||||
|
||||
@@ -101,8 +101,6 @@ export type CommandMappings = {
|
||||
showRevisions: CommandData & {
|
||||
noteId?: string | null;
|
||||
};
|
||||
showLlmChat: CommandData;
|
||||
createAiChat: CommandData;
|
||||
showOptions: CommandData & {
|
||||
section: string;
|
||||
};
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import dateNoteService from "../services/date_notes.js";
|
||||
import froca from "../services/froca.js";
|
||||
import noteCreateService from "../services/note_create.js";
|
||||
import openService from "../services/open.js";
|
||||
import options from "../services/options.js";
|
||||
import protectedSessionService from "../services/protected_session.js";
|
||||
import toastService from "../services/toast.js";
|
||||
import treeService from "../services/tree.js";
|
||||
import utils, { openInReusableSplit } from "../services/utils.js";
|
||||
import appContext, { type CommandListenerData } from "./app_context.js";
|
||||
@@ -248,34 +246,4 @@ export default class RootCommandExecutor extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
async createAiChatCommand() {
|
||||
try {
|
||||
// Create a new AI Chat note at the root level
|
||||
const rootNoteId = "root";
|
||||
|
||||
const result = await noteCreateService.createNote(rootNoteId, {
|
||||
title: "New AI Chat",
|
||||
type: "aiChat",
|
||||
content: JSON.stringify({
|
||||
messages: [],
|
||||
title: "New AI Chat"
|
||||
})
|
||||
});
|
||||
|
||||
if (!result.note) {
|
||||
toastService.showError("Failed to create AI Chat note");
|
||||
return;
|
||||
}
|
||||
|
||||
await appContext.tabManager.openTabWithNoteWithHoisting(result.note.noteId, {
|
||||
activate: true
|
||||
});
|
||||
|
||||
toastService.showMessage("Created new AI Chat note");
|
||||
}
|
||||
catch (e) {
|
||||
console.error("Error creating AI Chat note:", e);
|
||||
toastService.showError(`Failed to create AI Chat note: ${(e as Error).message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ const RELATION = "relation";
|
||||
* 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" | "aiChat";
|
||||
export type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code" | "mindMap";
|
||||
|
||||
export interface NotePathRecord {
|
||||
isArchived: boolean;
|
||||
@@ -700,6 +700,15 @@ export default class FNote {
|
||||
return this.hasAttribute(LABEL, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the note has a label with the given name (same as {@link hasOwnedLabel}), or it has a label with the `disabled:` prefix (for example due to a safe import).
|
||||
* @param name the name of the label to look for.
|
||||
* @returns `true` if the label exists, or its version with the `disabled:` prefix.
|
||||
*/
|
||||
hasLabelOrDisabled(name: string) {
|
||||
return this.hasLabel(name) || this.hasLabel(`disabled:${name}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name - label name
|
||||
* @returns true if label exists (including inherited) and does not have "false" value.
|
||||
|
||||
@@ -23,10 +23,7 @@ import NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import NoteWrapperWidget from "../widgets/note_wrapper.js";
|
||||
import NoteDetail from "../widgets/NoteDetail.jsx";
|
||||
import QuickSearchWidget from "../widgets/quick_search.js";
|
||||
import { useNoteContext } from "../widgets/react/hooks.jsx";
|
||||
import StandaloneRibbonAdapter from "../widgets/ribbon/components/StandaloneRibbonAdapter.jsx";
|
||||
import FilePropertiesTab from "../widgets/ribbon/FilePropertiesTab.jsx";
|
||||
import SearchDefinitionTab from "../widgets/ribbon/SearchDefinitionTab.jsx";
|
||||
import ScrollPadding from "../widgets/scroll_padding";
|
||||
import SearchResult from "../widgets/search_result.jsx";
|
||||
import MobileEditorToolbar from "../widgets/type_widgets/text/mobile_editor_toolbar.jsx";
|
||||
import { applyModals } from "./layout_commons.js";
|
||||
@@ -78,7 +75,7 @@ export default class MobileLayout {
|
||||
.child(<NoteDetail />)
|
||||
.child(<NoteList media="screen" />)
|
||||
.child(<SearchResult />)
|
||||
.child(<FilePropertiesWrapper />)
|
||||
.child(<ScrollPadding />)
|
||||
)
|
||||
.child(<MobileEditorToolbar />)
|
||||
.child(new FindWidget())
|
||||
@@ -102,13 +99,3 @@ export default class MobileLayout {
|
||||
return rootContainer;
|
||||
}
|
||||
}
|
||||
|
||||
function FilePropertiesWrapper() {
|
||||
const { note, ntxId } = useNoteContext();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{note?.type === "file" && <FilePropertiesTab note={note} ntxId={ntxId} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ export type PrintReport = {
|
||||
} | {
|
||||
type: "collection";
|
||||
ignoredNoteIds: string[];
|
||||
} | {
|
||||
type: "error";
|
||||
message: string;
|
||||
stack?: string;
|
||||
};
|
||||
|
||||
async function main() {
|
||||
|
||||
@@ -168,6 +168,49 @@ function isAffecting(attrRow: AttributeRow, affectedNote: FNote | null | undefin
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles whether a dangerous attribute is enabled or not. When an attribute is disabled, its name is prefixed with `disabled:`.
|
||||
*
|
||||
* Note that this work for non-dangerous attributes as well.
|
||||
*
|
||||
* If there are multiple attributes with the same name, all of them will be toggled at the same time.
|
||||
*
|
||||
* @param note the note whose attribute to change.
|
||||
* @param type the type of dangerous attribute (label or relation).
|
||||
* @param name the name of the dangerous attribute.
|
||||
* @param willEnable whether to enable or disable the attribute.
|
||||
* @returns a promise that will resolve when the request to the server completes.
|
||||
*/
|
||||
async function toggleDangerousAttribute(note: FNote, type: "label" | "relation", name: string, willEnable: boolean) {
|
||||
const attrs = [
|
||||
...note.getOwnedAttributes(type, name),
|
||||
...note.getOwnedAttributes(type, `disabled:${name}`)
|
||||
];
|
||||
|
||||
for (const attr of attrs) {
|
||||
const baseName = getNameWithoutDangerousPrefix(attr.name);
|
||||
const newName = willEnable ? baseName : `disabled:${baseName}`;
|
||||
if (newName === attr.name) continue;
|
||||
|
||||
// We are adding and removing afterwards to avoid a flicker (because for a moment there would be no active content attribute anymore) because the operations are done in sequence and not atomically.
|
||||
if (attr.type === "label") {
|
||||
await setLabel(note.noteId, newName, attr.value);
|
||||
} else {
|
||||
await setRelation(note.noteId, newName, attr.value);
|
||||
}
|
||||
await removeAttributeById(note.noteId, attr.attributeId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of an attribute without the `disabled:` prefix, or the same name if it's not disabled.
|
||||
* @param name the name of an attribute.
|
||||
* @returns the name without the `disabled:` prefix.
|
||||
*/
|
||||
function getNameWithoutDangerousPrefix(name: string) {
|
||||
return name.startsWith("disabled:") ? name.substring(9) : name;
|
||||
}
|
||||
|
||||
export default {
|
||||
addLabel,
|
||||
setLabel,
|
||||
@@ -177,5 +220,7 @@ export default {
|
||||
removeAttributeById,
|
||||
removeOwnedLabelByName,
|
||||
removeOwnedRelationByName,
|
||||
isAffecting
|
||||
isAffecting,
|
||||
toggleDangerousAttribute,
|
||||
getNameWithoutDangerousPrefix
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@ import { h, VNode } from "preact";
|
||||
|
||||
import BasicWidget, { ReactWrappedWidget } from "../widgets/basic_widget.js";
|
||||
import RightPanelWidget from "../widgets/right_panel_widget.js";
|
||||
import froca from "./froca.js";
|
||||
import type { Entity } from "./frontend_script_api.js";
|
||||
import { WidgetDefinitionWithType } from "./frontend_script_api_preact.js";
|
||||
import { t } from "./i18n.js";
|
||||
@@ -38,15 +37,18 @@ async function getAndExecuteBundle(noteId: string, originEntity = null, script =
|
||||
|
||||
export type ParentName = "left-pane" | "center-pane" | "note-detail-pane" | "right-pane";
|
||||
|
||||
export async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery<HTMLElement>) {
|
||||
export async function executeBundleWithoutErrorHandling(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery<HTMLElement>) {
|
||||
const apiContext = await ScriptContext(bundle.noteId, bundle.allNoteIds, originEntity, $container);
|
||||
return await function () {
|
||||
return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`);
|
||||
}.call(apiContext);
|
||||
}
|
||||
|
||||
export async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery<HTMLElement>) {
|
||||
try {
|
||||
return await function () {
|
||||
return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`);
|
||||
}.call(apiContext);
|
||||
} catch (e: any) {
|
||||
showErrorForScriptNote(bundle.noteId, t("toast.bundle-error.message", { message: e.message }));
|
||||
return await executeBundleWithoutErrorHandling(bundle, originEntity, $container);
|
||||
} catch (e: unknown) {
|
||||
showErrorForScriptNote(bundle.noteId, t("toast.bundle-error.message", { message: getErrorMessage(e) }));
|
||||
logError("Widget initialization failed: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import protectedSessionService from "./protected_session.js";
|
||||
import protectedSessionHolder from "./protected_session_holder.js";
|
||||
import renderService from "./render.js";
|
||||
import { applySingleBlockSyntaxHighlight } from "./syntax_highlight.js";
|
||||
import utils from "./utils.js";
|
||||
import utils, { getErrorMessage } from "./utils.js";
|
||||
|
||||
let idCounter = 1;
|
||||
|
||||
@@ -62,7 +62,10 @@ export async function getRenderedContent(this: {} | { ctx: string }, entity: FNo
|
||||
} else if (type === "render" && entity instanceof FNote) {
|
||||
const $content = $("<div>");
|
||||
|
||||
await renderService.render(entity, $content);
|
||||
await renderService.render(entity, $content, (e) => {
|
||||
const $error = $("<div>").addClass("admonition caution").text(typeof e === "string" ? e : getErrorMessage(e));
|
||||
$content.empty().append($error);
|
||||
});
|
||||
|
||||
$renderedContent.append($content);
|
||||
} else if (type === "doc" && "noteId" in entity) {
|
||||
@@ -189,7 +192,7 @@ function renderFile(entity: FNote | FAttachment, type: string, $renderedContent:
|
||||
throw new Error(`Can't recognize entity type of '${entity}'`);
|
||||
}
|
||||
|
||||
const $content = $('<div style="display: flex; flex-direction: column; height: 100%;">');
|
||||
const $content = $('<div style="display: flex; flex-direction: column; height: 100%; justify-content: end;">');
|
||||
|
||||
if (type === "pdf") {
|
||||
const $pdfPreview = $('<iframe class="pdf-preview" style="width: 100%; flex-grow: 100;"></iframe>');
|
||||
|
||||
@@ -120,7 +120,6 @@ async function renderChildrenList($renderedContent: JQuery<HTMLElement>, note: F
|
||||
return;
|
||||
}
|
||||
|
||||
$renderedContent.css("padding", "10px");
|
||||
$renderedContent.addClass("text-with-ellipsis");
|
||||
|
||||
// just load the first 10 child notes
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { dayjs } from "@triliumnext/commons";
|
||||
|
||||
import type { FNoteRow } from "../entities/fnote.js";
|
||||
import froca from "./froca.js";
|
||||
import server from "./server.js";
|
||||
@@ -14,8 +15,13 @@ async function getTodayNote() {
|
||||
return await getDayNote(dayjs().format("YYYY-MM-DD"));
|
||||
}
|
||||
|
||||
async function getDayNote(date: string) {
|
||||
const note = await server.get<FNoteRow>(`special-notes/days/${date}`, "date-note");
|
||||
async function getDayNote(date: string, calendarRootId?: string) {
|
||||
let url = `special-notes/days/${date}`;
|
||||
if (calendarRootId) {
|
||||
url += `?calendarRootId=${calendarRootId}`;
|
||||
}
|
||||
|
||||
const note = await server.get<FNoteRow>(url, "date-note");
|
||||
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
|
||||
@@ -24,7 +24,8 @@ export async function initLocale() {
|
||||
backend: {
|
||||
loadPath: `${window.glob.assetPath}/translations/{{lng}}/{{ns}}.json`
|
||||
},
|
||||
returnEmptyString: false
|
||||
returnEmptyString: false,
|
||||
showSupportNotice: false
|
||||
});
|
||||
|
||||
await setDayjsLocale(locale);
|
||||
|
||||
@@ -17,8 +17,7 @@ export const byNoteType: Record<Exclude<NoteType, "book">, string | null> = {
|
||||
render: null,
|
||||
search: null,
|
||||
text: null,
|
||||
webView: null,
|
||||
aiChat: null
|
||||
webView: null
|
||||
};
|
||||
|
||||
export const byBookType: Record<ViewTypeOptions, string | null> = {
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import treeService from "./tree.js";
|
||||
import linkService from "./link.js";
|
||||
import froca from "./froca.js";
|
||||
import utils from "./utils.js";
|
||||
import attributeRenderer from "./attribute_renderer.js";
|
||||
import contentRenderer from "./content_renderer.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import attributeRenderer from "./attribute_renderer.js";
|
||||
import contentRenderer from "./content_renderer.js";
|
||||
import froca from "./froca.js";
|
||||
import { t } from "./i18n.js";
|
||||
import linkService from "./link.js";
|
||||
import treeService from "./tree.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
// Track all elements that open tooltips
|
||||
let openTooltipElements: JQuery<HTMLElement>[] = [];
|
||||
let dismissTimer: ReturnType<typeof setTimeout>;
|
||||
|
||||
function setupGlobalTooltip() {
|
||||
$(document).on("mouseenter", "a:not(.no-tooltip-preview)", mouseEnterHandler);
|
||||
$(document).on("mouseenter", "[data-href]:not(.no-tooltip-preview)", mouseEnterHandler);
|
||||
$(document).on("pointerenter", "a:not(.no-tooltip-preview)", mouseEnterHandler);
|
||||
$(document).on("pointerenter", "[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) => {
|
||||
@@ -37,10 +37,12 @@ function dismissAllTooltips() {
|
||||
}
|
||||
|
||||
function setupElementTooltip($el: JQuery<HTMLElement>) {
|
||||
$el.on("mouseenter", mouseEnterHandler);
|
||||
$el.on("pointerenter", mouseEnterHandler);
|
||||
}
|
||||
|
||||
async function mouseEnterHandler(this: HTMLElement) {
|
||||
async function mouseEnterHandler<T>(this: HTMLElement, e: JQuery.TriggeredEvent<T, undefined, T, T>) {
|
||||
if (e.pointerType !== "mouse") return;
|
||||
|
||||
const $link = $(this);
|
||||
|
||||
if ($link.hasClass("no-tooltip-preview") || $link.hasClass("disabled")) {
|
||||
@@ -91,7 +93,7 @@ async function mouseEnterHandler(this: HTMLElement) {
|
||||
}
|
||||
|
||||
const html = `<div class="note-tooltip-content">${content}</div>`;
|
||||
const tooltipClass = "tooltip-" + Math.floor(Math.random() * 999_999_999);
|
||||
const tooltipClass = `tooltip-${ Math.floor(Math.random() * 999_999_999)}`;
|
||||
|
||||
// we need to check if we're still hovering over the element
|
||||
// since the operation to get tooltip content was async, it is possible that
|
||||
@@ -224,7 +226,7 @@ function renderFootnoteOrAnchor($link: JQuery<HTMLElement>, url: string) {
|
||||
}
|
||||
|
||||
let footnoteContent = $targetContent.html();
|
||||
footnoteContent = `<div class="ck-content">${footnoteContent}</div>`
|
||||
footnoteContent = `<div class="ck-content">${footnoteContent}</div>`;
|
||||
return footnoteContent || "";
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ export const NOTE_TYPES: NoteTypeMapping[] = [
|
||||
{ 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 */
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import { h, VNode } from "preact";
|
||||
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import { renderReactWidgetAtElement } from "../widgets/react/react_utils.jsx";
|
||||
import bundleService, { type Bundle } from "./bundle.js";
|
||||
import froca from "./froca.js";
|
||||
import server from "./server.js";
|
||||
|
||||
async function render(note: FNote, $el: JQuery<HTMLElement>) {
|
||||
const relations = note.getRelations("renderNote");
|
||||
const renderNoteIds = relations.map((rel) => rel.value).filter((noteId) => noteId);
|
||||
|
||||
$el.empty().toggle(renderNoteIds.length > 0);
|
||||
|
||||
for (const renderNoteId of renderNoteIds) {
|
||||
const bundle = await server.post<Bundle>(`script/bundle/${renderNoteId}`);
|
||||
|
||||
const $scriptContainer = $("<div>");
|
||||
$el.append($scriptContainer);
|
||||
|
||||
$scriptContainer.append(bundle.html);
|
||||
|
||||
// async so that scripts cannot block trilium execution
|
||||
bundleService.executeBundle(bundle, note, $scriptContainer).then(result => {
|
||||
// Render JSX
|
||||
if (bundle.html === "") {
|
||||
renderIfJsx(bundle, result, $el);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return renderNoteIds.length > 0;
|
||||
}
|
||||
|
||||
async function renderIfJsx(bundle: Bundle, result: unknown, $el: JQuery<HTMLElement>) {
|
||||
// Ensure the root script note is actually a JSX.
|
||||
const rootScriptNoteId = await froca.getNote(bundle.noteId);
|
||||
if (rootScriptNoteId?.mime !== "text/jsx") return;
|
||||
|
||||
// Ensure the output is a valid el.
|
||||
if (typeof result !== "function") return;
|
||||
|
||||
// Obtain the parent component.
|
||||
const closestComponent = glob.getComponentByEl($el.closest(".component")[0]);
|
||||
if (!closestComponent) return;
|
||||
|
||||
// Render the element.
|
||||
const el = h(result as () => VNode, {});
|
||||
renderReactWidgetAtElement(closestComponent, el, $el[0]);
|
||||
}
|
||||
|
||||
export default {
|
||||
render
|
||||
};
|
||||
86
apps/client/src/services/render.tsx
Normal file
86
apps/client/src/services/render.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import { Component, h, VNode } from "preact";
|
||||
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import { renderReactWidgetAtElement } from "../widgets/react/react_utils.jsx";
|
||||
import { type Bundle, executeBundleWithoutErrorHandling } from "./bundle.js";
|
||||
import froca from "./froca.js";
|
||||
import server from "./server.js";
|
||||
|
||||
type ErrorHandler = (e: unknown) => void;
|
||||
|
||||
async function render(note: FNote, $el: JQuery<HTMLElement>, onError?: ErrorHandler) {
|
||||
const relations = note.getRelations("renderNote");
|
||||
const renderNoteIds = relations.map((rel) => rel.value).filter((noteId) => noteId);
|
||||
|
||||
$el.empty().toggle(renderNoteIds.length > 0);
|
||||
|
||||
try {
|
||||
for (const renderNoteId of renderNoteIds) {
|
||||
const bundle = await server.postWithSilentInternalServerError<Bundle>(`script/bundle/${renderNoteId}`);
|
||||
|
||||
const $scriptContainer = $("<div>");
|
||||
$el.append($scriptContainer);
|
||||
|
||||
$scriptContainer.append(bundle.html);
|
||||
|
||||
// async so that scripts cannot block trilium execution
|
||||
executeBundleWithoutErrorHandling(bundle, note, $scriptContainer)
|
||||
.catch(onError)
|
||||
.then(result => {
|
||||
// Render JSX
|
||||
if (bundle.html === "") {
|
||||
renderIfJsx(bundle, result, $el, onError).catch(onError);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return renderNoteIds.length > 0;
|
||||
} catch (e) {
|
||||
if (typeof e === "string" && e.startsWith("{") && e.endsWith("}")) {
|
||||
try {
|
||||
onError?.(JSON.parse(e));
|
||||
} catch (e) {
|
||||
onError?.(e);
|
||||
}
|
||||
} else {
|
||||
onError?.(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function renderIfJsx(bundle: Bundle, result: unknown, $el: JQuery<HTMLElement>, onError?: ErrorHandler) {
|
||||
// Ensure the root script note is actually a JSX.
|
||||
const rootScriptNoteId = await froca.getNote(bundle.noteId);
|
||||
if (rootScriptNoteId?.mime !== "text/jsx") return;
|
||||
|
||||
// Ensure the output is a valid el.
|
||||
if (typeof result !== "function") return;
|
||||
|
||||
// Obtain the parent component.
|
||||
const closestComponent = glob.getComponentByEl($el.closest(".component")[0]);
|
||||
if (!closestComponent) return;
|
||||
|
||||
// Render the element.
|
||||
const UserErrorBoundary = class UserErrorBoundary extends Component {
|
||||
constructor(props: object) {
|
||||
super(props);
|
||||
this.state = { error: null };
|
||||
}
|
||||
|
||||
componentDidCatch(error: unknown) {
|
||||
onError?.(error);
|
||||
this.setState({ error });
|
||||
}
|
||||
|
||||
render() {
|
||||
if ("error" in this.state && this.state?.error) return null;
|
||||
return this.props.children;
|
||||
}
|
||||
};
|
||||
const el = h(UserErrorBoundary, {}, h(result as () => VNode, {}));
|
||||
renderReactWidgetAtElement(closestComponent, el, $el[0]);
|
||||
}
|
||||
|
||||
export default {
|
||||
render
|
||||
};
|
||||
@@ -73,6 +73,10 @@ async function post<T>(url: string, data?: unknown, componentId?: string) {
|
||||
return await call<T>("POST", url, componentId, { data });
|
||||
}
|
||||
|
||||
async function postWithSilentInternalServerError<T>(url: string, data?: unknown, componentId?: string) {
|
||||
return await call<T>("POST", url, componentId, { data, silentInternalServerError: true });
|
||||
}
|
||||
|
||||
async function put<T>(url: string, data?: unknown, componentId?: string) {
|
||||
return await call<T>("PUT", url, componentId, { data });
|
||||
}
|
||||
@@ -111,6 +115,7 @@ let maxKnownEntityChangeId = 0;
|
||||
interface CallOptions {
|
||||
data?: unknown;
|
||||
silentNotFound?: boolean;
|
||||
silentInternalServerError?: boolean;
|
||||
// If `true`, the value will be returned as a string instead of a JavaScript object if JSON, XMLDocument if XML, etc.
|
||||
raw?: boolean;
|
||||
}
|
||||
@@ -143,7 +148,7 @@ async function call<T>(method: string, url: string, componentId?: string, option
|
||||
});
|
||||
})) as any;
|
||||
} else {
|
||||
resp = await ajax(url, method, data, headers, !!options.silentNotFound, options.raw);
|
||||
resp = await ajax(url, method, data, headers, options);
|
||||
}
|
||||
|
||||
const maxEntityChangeIdStr = resp.headers["trilium-max-entity-change-id"];
|
||||
@@ -155,10 +160,7 @@ async function call<T>(method: string, url: string, componentId?: string, option
|
||||
return resp.body as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param raw if `true`, the value will be returned as a string instead of a JavaScript object if JSON, XMLDocument if XML, etc.
|
||||
*/
|
||||
function ajax(url: string, method: string, data: unknown, headers: Headers, silentNotFound: boolean, raw?: boolean): Promise<Response> {
|
||||
function ajax(url: string, method: string, data: unknown, headers: Headers, opts: CallOptions): Promise<Response> {
|
||||
return new Promise((res, rej) => {
|
||||
const options: JQueryAjaxSettings = {
|
||||
url: window.glob.baseApiUrl + url,
|
||||
@@ -190,7 +192,9 @@ function ajax(url: string, method: string, data: unknown, headers: Headers, sile
|
||||
// don't report requests that are rejected by the browser, usually when the user is refreshing or going to a different page.
|
||||
rej("rejected by browser");
|
||||
return;
|
||||
} else if (silentNotFound && jqXhr.status === 404) {
|
||||
} else if (opts.silentNotFound && jqXhr.status === 404) {
|
||||
// report nothing
|
||||
} else if (opts.silentInternalServerError && jqXhr.status === 500) {
|
||||
// report nothing
|
||||
} else {
|
||||
await reportError(method, url, jqXhr.status, jqXhr.responseText);
|
||||
@@ -200,7 +204,7 @@ function ajax(url: string, method: string, data: unknown, headers: Headers, sile
|
||||
}
|
||||
};
|
||||
|
||||
if (raw) {
|
||||
if (opts.raw) {
|
||||
options.dataType = "text";
|
||||
}
|
||||
|
||||
@@ -299,6 +303,7 @@ export default {
|
||||
get,
|
||||
getWithSilentNotFound,
|
||||
post,
|
||||
postWithSilentInternalServerError,
|
||||
put,
|
||||
patch,
|
||||
remove,
|
||||
|
||||
@@ -14,7 +14,9 @@ export function reloadFrontendApp(reason?: string) {
|
||||
}
|
||||
|
||||
if (isElectron()) {
|
||||
dynamicRequire("@electron/remote").BrowserWindow.getFocusedWindow()?.reload();
|
||||
for (const window of dynamicRequire("@electron/remote").BrowserWindow.getAllWindows()) {
|
||||
window.reload();
|
||||
}
|
||||
} else {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
@@ -133,49 +133,6 @@ async function handleMessage(event: MessageEvent<any>) {
|
||||
appContext.triggerEvent("apiLogMessages", { noteId: message.noteId, messages: message.messages });
|
||||
} else if (message.type === "toast") {
|
||||
toastService.showMessage(message.message);
|
||||
} else if (message.type === "llm-stream") {
|
||||
// ENHANCED LOGGING FOR DEBUGGING
|
||||
console.log(`[WS-CLIENT] >>> RECEIVED LLM STREAM MESSAGE <<<`);
|
||||
console.log(`[WS-CLIENT] Message details: sessionId=${message.sessionId}, hasContent=${!!message.content}, contentLength=${message.content ? message.content.length : 0}, hasThinking=${!!message.thinking}, hasToolExecution=${!!message.toolExecution}, isDone=${!!message.done}`);
|
||||
|
||||
if (message.content) {
|
||||
console.log(`[WS-CLIENT] CONTENT PREVIEW: "${message.content.substring(0, 50)}..."`);
|
||||
}
|
||||
|
||||
// Create the event with detailed logging
|
||||
console.log(`[WS-CLIENT] Creating CustomEvent 'llm-stream-message'`);
|
||||
const llmStreamEvent = new CustomEvent('llm-stream-message', { detail: message });
|
||||
|
||||
// Dispatch to multiple targets to ensure delivery
|
||||
try {
|
||||
console.log(`[WS-CLIENT] Dispatching event to window`);
|
||||
window.dispatchEvent(llmStreamEvent);
|
||||
console.log(`[WS-CLIENT] Event dispatched to window`);
|
||||
|
||||
// Also try document for completeness
|
||||
console.log(`[WS-CLIENT] Dispatching event to document`);
|
||||
document.dispatchEvent(new CustomEvent('llm-stream-message', { detail: message }));
|
||||
console.log(`[WS-CLIENT] Event dispatched to document`);
|
||||
} catch (err) {
|
||||
console.error(`[WS-CLIENT] Error dispatching event:`, err);
|
||||
}
|
||||
|
||||
// Debug current listeners (though we can't directly check for specific event listeners)
|
||||
console.log(`[WS-CLIENT] Active event listeners should receive this message now`);
|
||||
|
||||
// Detailed logging based on message type
|
||||
if (message.content) {
|
||||
console.log(`[WS-CLIENT] Content message: ${message.content.length} chars`);
|
||||
} else if (message.thinking) {
|
||||
console.log(`[WS-CLIENT] Thinking update: "${message.thinking}"`);
|
||||
} else if (message.toolExecution) {
|
||||
console.log(`[WS-CLIENT] Tool execution: action=${message.toolExecution.action}, tool=${message.toolExecution.tool || 'unknown'}`);
|
||||
if (message.toolExecution.result) {
|
||||
console.log(`[WS-CLIENT] Tool result preview: "${String(message.toolExecution.result).substring(0, 50)}..."`);
|
||||
}
|
||||
} else if (message.done) {
|
||||
console.log(`[WS-CLIENT] Completion signal received`);
|
||||
}
|
||||
} else if (message.type === "execute-script") {
|
||||
// TODO: Remove after porting the file
|
||||
// @ts-ignore
|
||||
|
||||
@@ -1,450 +0,0 @@
|
||||
/* LLM Chat Panel Styles */
|
||||
.note-context-chat {
|
||||
background-color: var(--main-background-color);
|
||||
}
|
||||
|
||||
/* Message Styling */
|
||||
.chat-message {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.message-avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
font-size: 1.25rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
background-color: var(--input-background-color);
|
||||
color: var(--cmd-button-icon-color);
|
||||
}
|
||||
|
||||
.assistant-avatar {
|
||||
background-color: var(--subtle-border-color, var(--main-border-color));
|
||||
color: var(--hover-item-text-color);
|
||||
}
|
||||
|
||||
.message-content {
|
||||
max-width: calc(100% - 50px);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
color: var(--main-text-color);
|
||||
}
|
||||
|
||||
.user-content {
|
||||
border-radius: 0.5rem 0.5rem 0 0.5rem !important;
|
||||
background-color: var(--input-background-color) !important;
|
||||
}
|
||||
|
||||
.assistant-content {
|
||||
border-radius: 0.5rem 0.5rem 0.5rem 0 !important;
|
||||
background-color: var(--main-background-color);
|
||||
border: 1px solid var(--subtle-border-color, var(--main-border-color));
|
||||
}
|
||||
|
||||
/* Tool Execution Styling */
|
||||
.tool-execution-info {
|
||||
margin-top: 0.75rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border: 1px solid var(--subtle-border-color);
|
||||
border-radius: 0.5rem;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
||||
background-color: var(--main-background-color);
|
||||
/* Add a subtle transition effect */
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.tool-execution-status {
|
||||
background-color: var(--accented-background-color, rgba(0, 0, 0, 0.03)) !important;
|
||||
border-radius: 0 !important;
|
||||
padding: 0.5rem !important;
|
||||
max-height: 250px !important;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tool-execution-status .d-flex {
|
||||
border-bottom: 1px solid var(--subtle-border-color);
|
||||
padding-bottom: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.tool-step {
|
||||
padding: 0.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
border-radius: 0.375rem;
|
||||
background-color: var(--main-background-color);
|
||||
border: 1px solid var(--subtle-border-color);
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.tool-step:hover {
|
||||
background-color: rgba(0, 0, 0, 0.01);
|
||||
}
|
||||
|
||||
.tool-step:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Tool step specific styling */
|
||||
.tool-step.executing {
|
||||
background-color: rgba(0, 123, 255, 0.05);
|
||||
border-color: rgba(0, 123, 255, 0.2);
|
||||
}
|
||||
|
||||
.tool-step.result {
|
||||
background-color: rgba(40, 167, 69, 0.05);
|
||||
border-color: rgba(40, 167, 69, 0.2);
|
||||
}
|
||||
|
||||
.tool-step.error {
|
||||
background-color: rgba(220, 53, 69, 0.05);
|
||||
border-color: rgba(220, 53, 69, 0.2);
|
||||
}
|
||||
|
||||
/* Tool result formatting */
|
||||
.tool-result pre {
|
||||
margin: 0.5rem 0;
|
||||
padding: 0.5rem;
|
||||
background-color: rgba(0, 0, 0, 0.03);
|
||||
border-radius: 0.25rem;
|
||||
overflow: auto;
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
.tool-result code {
|
||||
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.tool-args code {
|
||||
display: block;
|
||||
padding: 0.5rem;
|
||||
background-color: rgba(0, 0, 0, 0.03);
|
||||
border-radius: 0.25rem;
|
||||
margin-top: 0.25rem;
|
||||
font-size: 0.85em;
|
||||
color: var(--muted-text-color);
|
||||
white-space: pre-wrap;
|
||||
overflow: auto;
|
||||
max-height: 100px;
|
||||
}
|
||||
|
||||
/* Tool Execution in Chat Styling */
|
||||
.chat-tool-execution {
|
||||
padding: 0 0 0 36px; /* Aligned with message content, accounting for avatar width */
|
||||
width: 100%;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.tool-execution-container {
|
||||
background-color: var(--accented-background-color, rgba(245, 247, 250, 0.7));
|
||||
border: 1px solid var(--subtle-border-color);
|
||||
border-radius: 0.375rem;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
overflow: hidden;
|
||||
max-width: calc(100% - 20px);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.tool-execution-container.collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tool-execution-header {
|
||||
background-color: var(--main-background-color);
|
||||
border-bottom: 1px solid var(--subtle-border-color);
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--muted-text-color);
|
||||
font-weight: 500;
|
||||
padding: 0.6rem 0.8rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.tool-execution-header:hover {
|
||||
background-color: var(--hover-item-background-color, rgba(0, 0, 0, 0.03));
|
||||
}
|
||||
|
||||
.tool-execution-toggle {
|
||||
color: var(--muted-text-color) !important;
|
||||
background: transparent !important;
|
||||
padding: 0.2rem 0.4rem !important;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.tool-execution-toggle:hover {
|
||||
color: var(--main-text-color) !important;
|
||||
}
|
||||
|
||||
.tool-execution-toggle i.bx-chevron-down {
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.tool-execution-toggle i.bx-chevron-right {
|
||||
transform: rotate(-90deg);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.tool-execution-chat-steps {
|
||||
padding: 0.5rem;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Make error text more visible */
|
||||
.text-danger {
|
||||
color: #dc3545 !important;
|
||||
}
|
||||
|
||||
/* Sources Styling */
|
||||
.sources-container {
|
||||
background-color: var(--accented-background-color, var(--main-background-color));
|
||||
border-top: 1px solid var(--main-border-color);
|
||||
color: var(--main-text-color);
|
||||
}
|
||||
|
||||
.source-item {
|
||||
transition: all 0.2s ease;
|
||||
background-color: var(--main-background-color);
|
||||
border-color: var(--subtle-border-color, var(--main-border-color)) !important;
|
||||
}
|
||||
|
||||
.source-item:hover {
|
||||
background-color: var(--link-hover-background, var(--hover-item-background-color));
|
||||
}
|
||||
|
||||
.source-link {
|
||||
color: var(--link-color, var(--hover-item-text-color));
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.source-link:hover {
|
||||
color: var(--link-hover-color, var(--hover-item-text-color));
|
||||
}
|
||||
|
||||
/* Input Area Styling */
|
||||
.note-context-chat-form {
|
||||
background-color: var(--main-background-color);
|
||||
border-top: 1px solid var(--main-border-color);
|
||||
}
|
||||
|
||||
.context-option-container {
|
||||
padding: 0.5rem 0;
|
||||
border-bottom: 1px solid var(--subtle-border-color, var(--main-border-color));
|
||||
color: var(--main-text-color);
|
||||
}
|
||||
|
||||
.chat-input-container {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
.note-context-chat-input {
|
||||
border-color: var(--subtle-border-color, var(--main-border-color));
|
||||
background-color: var(--input-background-color) !important;
|
||||
color: var(--input-text-color) !important;
|
||||
resize: none;
|
||||
transition: all 0.2s ease;
|
||||
min-height: 50px;
|
||||
max-height: 150px;
|
||||
}
|
||||
|
||||
.note-context-chat-input:focus {
|
||||
border-color: var(--input-focus-outline-color, var(--main-border-color));
|
||||
box-shadow: 0 0 0 0.25rem var(--input-focus-outline-color, rgba(13, 110, 253, 0.25));
|
||||
}
|
||||
|
||||
.note-context-chat-send-button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
align-self: flex-end;
|
||||
background-color: var(--cmd-button-background-color) !important;
|
||||
color: var(--cmd-button-text-color) !important;
|
||||
}
|
||||
|
||||
/* Loading Indicator */
|
||||
.loading-indicator {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1rem;
|
||||
color: var(--muted-text-color);
|
||||
}
|
||||
|
||||
/* Thinking display styles */
|
||||
.llm-thinking-container {
|
||||
margin: 1rem 0;
|
||||
animation: fadeInUp 0.3s ease-out;
|
||||
}
|
||||
|
||||
.thinking-bubble {
|
||||
background-color: var(--accented-background-color, var(--main-background-color));
|
||||
border: 1px solid var(--subtle-border-color, var(--main-border-color));
|
||||
border-radius: 0.75rem;
|
||||
padding: 0.75rem;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.thinking-bubble:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.thinking-bubble::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, var(--hover-item-background-color, rgba(0, 0, 0, 0.03)), transparent);
|
||||
animation: shimmer 2s infinite;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.thinking-header {
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.thinking-header:hover {
|
||||
background-color: var(--hover-item-background-color, rgba(0, 0, 0, 0.03));
|
||||
padding: 0.25rem;
|
||||
margin: -0.25rem;
|
||||
}
|
||||
|
||||
.thinking-dots {
|
||||
display: flex;
|
||||
gap: 3px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.thinking-dots span {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background-color: var(--link-color, var(--hover-item-text-color));
|
||||
border-radius: 50%;
|
||||
animation: thinkingPulse 1.4s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.thinking-dots span:nth-child(1) {
|
||||
animation-delay: -0.32s;
|
||||
}
|
||||
|
||||
.thinking-dots span:nth-child(2) {
|
||||
animation-delay: -0.16s;
|
||||
}
|
||||
|
||||
.thinking-dots span:nth-child(3) {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.thinking-label {
|
||||
font-weight: 500;
|
||||
color: var(--link-color, var(--hover-item-text-color)) !important;
|
||||
}
|
||||
|
||||
.thinking-toggle {
|
||||
color: var(--muted-text-color) !important;
|
||||
transition: transform 0.2s ease;
|
||||
background: transparent !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.thinking-toggle:hover {
|
||||
color: var(--main-text-color) !important;
|
||||
}
|
||||
|
||||
.thinking-toggle.expanded {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.thinking-content {
|
||||
margin-top: 0.75rem;
|
||||
padding-top: 0.75rem;
|
||||
border-top: 1px solid var(--subtle-border-color, var(--main-border-color));
|
||||
animation: expandDown 0.3s ease-out;
|
||||
}
|
||||
|
||||
.thinking-text {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
color: var(--main-text-color);
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
background-color: var(--input-background-color);
|
||||
padding: 0.75rem;
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid var(--subtle-border-color, var(--main-border-color));
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
transition: border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.thinking-text:hover {
|
||||
border-color: var(--main-border-color);
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes thinkingPulse {
|
||||
0%, 80%, 100% {
|
||||
transform: scale(0.8);
|
||||
opacity: 0.6;
|
||||
}
|
||||
40% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% {
|
||||
inset-inline-start: -100%;
|
||||
}
|
||||
100% {
|
||||
inset-inline-start: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes expandDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
max-height: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
max-height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.thinking-bubble {
|
||||
margin: 0.5rem 0;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.thinking-text {
|
||||
font-size: 0.8rem;
|
||||
padding: 0.5rem;
|
||||
max-height: 200px;
|
||||
}
|
||||
}
|
||||
@@ -153,6 +153,11 @@ textarea,
|
||||
background: var(--input-background-color);
|
||||
}
|
||||
|
||||
.form-control:disabled {
|
||||
background-color: var(--input-background-color);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
color: var(--input-text-color);
|
||||
background: var(--input-background-color);
|
||||
@@ -942,6 +947,7 @@ table.promoted-attributes-in-tooltip th {
|
||||
color: var(--muted-text-color);
|
||||
opacity: 0.6;
|
||||
line-height: 1;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.aa-dropdown-menu .aa-suggestion p {
|
||||
@@ -1336,15 +1342,12 @@ body.desktop .dropdown-submenu > .dropdown-menu {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.dropdown-submenu.dropstart > .dropdown-menu {
|
||||
.dropdown-submenu.dropstart > .dropdown-menu,
|
||||
body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
inset-inline-start: auto;
|
||||
inset-inline-end: calc(100% - 2px);
|
||||
}
|
||||
|
||||
body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
inset-inline-start: calc(-100% + 10px);
|
||||
}
|
||||
|
||||
.right-dropdown-widget {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -1584,7 +1587,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
bottom: 0;
|
||||
height: 100dvh;
|
||||
width: 85vw;
|
||||
padding-top: env(safe-area-inset-top);
|
||||
transition: transform 250ms ease-in-out;
|
||||
@@ -1648,13 +1651,27 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
body.mobile .jump-to-note-dialog .modal-content {
|
||||
overflow-y: auto;
|
||||
}
|
||||
body.mobile .jump-to-note-dialog {
|
||||
.modal-header {
|
||||
padding-bottom: 0.75rem !important;
|
||||
}
|
||||
|
||||
body.mobile .jump-to-note-dialog .modal-dialog .aa-dropdown-menu {
|
||||
max-height: unset;
|
||||
overflow: auto;
|
||||
.modal-content {
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.aa-dropdown-menu {
|
||||
max-height: unset;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.aa-suggestion {
|
||||
padding-inline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
body.mobile .modal-dialog .dropdown-menu {
|
||||
|
||||
@@ -210,6 +210,7 @@
|
||||
--badge-share-background-color: #4d4d4d;
|
||||
--badge-clipped-note-background-color: #295773;
|
||||
--badge-execute-background-color: #604180;
|
||||
--badge-active-content-background-color: rgb(12, 68, 70);
|
||||
|
||||
--note-icon-background-color: #444444;
|
||||
--note-icon-color: #d4d4d4;
|
||||
@@ -238,9 +239,9 @@
|
||||
|
||||
--bottom-panel-background-color: #11111180;
|
||||
--bottom-panel-title-bar-background-color: #3F3F3F80;
|
||||
|
||||
|
||||
--status-bar-border-color: var(--main-border-color);
|
||||
|
||||
|
||||
--scrollbar-thumb-color: #fdfdfd5c;
|
||||
--scrollbar-thumb-hover-color: #ffffff7d;
|
||||
--scrollbar-background-color: transparent;
|
||||
@@ -290,6 +291,15 @@
|
||||
--ck-editor-toolbar-button-on-shadow: 1px 1px 2px rgba(0, 0, 0, .75);
|
||||
--ck-editor-toolbar-dropdown-button-open-background: #ffffff14;
|
||||
|
||||
--note-list-view-icon-color: var(--left-pane-icon-color);
|
||||
--note-list-view-large-icon-background: var(--note-icon-background-color);
|
||||
--note-list-view-large-icon-color: var(--note-icon-color);
|
||||
--note-list-view-search-result-highlight-background: transparent;
|
||||
--note-list-view-search-result-highlight-color: var(--quick-search-result-highlight-color);
|
||||
--note-list-view-content-background: rgba(0, 0, 0, .2);
|
||||
--note-list-view-content-search-result-highlight-background: var(--quick-search-result-highlight-color);
|
||||
--note-list-view-content-search-result-highlight-color: black;
|
||||
|
||||
--calendar-coll-event-background-saturation: 25%;
|
||||
--calendar-coll-event-background-lightness: 20%;
|
||||
--calendar-coll-event-background-color: #3c3c3c;
|
||||
@@ -303,7 +313,9 @@
|
||||
* Dark color scheme tweaks
|
||||
*/
|
||||
|
||||
#left-pane .fancytree-node.tinted {
|
||||
#left-pane .fancytree-node.tinted,
|
||||
.nested-note-list-item.use-note-color,
|
||||
.note-book-card .note-book-header.use-note-color {
|
||||
--custom-color: var(--dark-theme-custom-color);
|
||||
|
||||
/* The background color of the active item in the note tree.
|
||||
@@ -337,12 +349,25 @@ body .todo-list input[type="checkbox"]:not(:checked):before {
|
||||
--promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 13.2%, 20.8%);
|
||||
}
|
||||
|
||||
.modal.tab-bar-modal .tabs .tab-card.with-hue {
|
||||
background-color: hsl(var(--bg-hue), 8.8%, 11.2%);
|
||||
border-color: hsl(var(--bg-hue), 9.4%, 25.1%);
|
||||
}
|
||||
|
||||
.modal.tab-bar-modal .tabs .tab-card.active.with-hue {
|
||||
background-color: hsl(var(--bg-hue), 8.8%, 16.2%);
|
||||
border-color: hsl(var(--bg-hue), 9.4%, 25.1%);
|
||||
}
|
||||
|
||||
|
||||
.use-note-color {
|
||||
--custom-color: var(--dark-theme-custom-color);
|
||||
}
|
||||
|
||||
.note-split.with-hue,
|
||||
.quick-edit-dialog-wrapper.with-hue {
|
||||
.quick-edit-dialog-wrapper.with-hue,
|
||||
.nested-note-list-item.with-hue,
|
||||
.note-book-card.with-hue .note-book-header {
|
||||
--note-icon-custom-background-color: hsl(var(--custom-color-hue), 15.8%, 30.9%);
|
||||
--note-icon-custom-color: hsl(var(--custom-color-hue), 100%, 76.5%);
|
||||
--note-icon-hover-custom-background-color: hsl(var(--custom-color-hue), 28.3%, 36.7%);
|
||||
@@ -351,4 +376,9 @@ body .todo-list input[type="checkbox"]:not(:checked):before {
|
||||
.note-split.with-hue *::selection,
|
||||
.quick-edit-dialog-wrapper.with-hue *::selection {
|
||||
--selection-background-color: hsl(var(--custom-color-hue), 49.2%, 35%);
|
||||
}
|
||||
|
||||
.note-book-card.with-hue {
|
||||
--card-background-color: hsl(var(--custom-color-hue), 6%, 21%);
|
||||
--card-background-hover-color: hsl(var(--custom-color-hue), 8%, 25%);
|
||||
}
|
||||
@@ -202,6 +202,7 @@
|
||||
--badge-share-background-color: #6b6b6b;
|
||||
--badge-clipped-note-background-color: #2284c0;
|
||||
--badge-execute-background-color: #7b47af;
|
||||
--badge-active-content-background-color: rgb(27, 164, 168);
|
||||
|
||||
--note-icon-background-color: #4f4f4f;
|
||||
--note-icon-color: white;
|
||||
@@ -288,6 +289,15 @@
|
||||
--ck-editor-toolbar-button-on-shadow: none;
|
||||
--ck-editor-toolbar-dropdown-button-open-background: #0000000f;
|
||||
|
||||
--note-list-view-icon-color: var(--left-pane-icon-color);
|
||||
--note-list-view-large-icon-background: var(--note-icon-background-color);
|
||||
--note-list-view-large-icon-color: var(--note-icon-color);
|
||||
--note-list-view-search-result-highlight-background: transparent;
|
||||
--note-list-view-search-result-highlight-color: var(--quick-search-result-highlight-color);
|
||||
--note-list-view-content-background: #b1b1b133;
|
||||
--note-list-view-content-search-result-highlight-background: var(--quick-search-result-highlight-color);
|
||||
--note-list-view-content-search-result-highlight-color: white;
|
||||
|
||||
--calendar-coll-event-background-lightness: 95%;
|
||||
--calendar-coll-event-background-saturation: 80%;
|
||||
--calendar-coll-event-background-color: #eaeaea;
|
||||
@@ -297,7 +307,9 @@
|
||||
--calendar-coll-today-background-color: #00000006;
|
||||
}
|
||||
|
||||
#left-pane .fancytree-node.tinted {
|
||||
#left-pane .fancytree-node.tinted,
|
||||
.nested-note-list-item.use-note-color,
|
||||
.note-book-card .note-book-header.use-note-color {
|
||||
--custom-color: var(--light-theme-custom-color);
|
||||
|
||||
/* The background color of the active item in the note tree.
|
||||
@@ -312,8 +324,20 @@
|
||||
--promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 40%, 88%);
|
||||
}
|
||||
|
||||
.modal.tab-bar-modal .tabs .tab-card.with-hue {
|
||||
background-color: hsl(var(--bg-hue), 56%, 96%);
|
||||
border-color: hsl(var(--bg-hue), 33%, 41%);
|
||||
}
|
||||
|
||||
.modal.tab-bar-modal .tabs .tab-card.active.with-hue {
|
||||
background-color: hsl(var(--bg-hue), 86%, 96%);
|
||||
border-color: hsl(var(--bg-hue), 33%, 41%);
|
||||
}
|
||||
|
||||
.note-split.with-hue,
|
||||
.quick-edit-dialog-wrapper.with-hue {
|
||||
.quick-edit-dialog-wrapper.with-hue,
|
||||
.nested-note-list-item.with-hue,
|
||||
.note-book-card.with-hue .note-book-header {
|
||||
--note-icon-custom-background-color: hsl(var(--custom-color-hue), 44.5%, 43.1%);
|
||||
--note-icon-custom-color: hsl(var(--custom-color-hue), 91.3%, 91%);
|
||||
--note-icon-hover-custom-background-color: hsl(var(--custom-color-hue), 55.1%, 50.2%);
|
||||
@@ -322,4 +346,9 @@
|
||||
.note-split.with-hue *::selection,
|
||||
.quick-edit-dialog-wrapper.with-hue *::selection {
|
||||
--selection-background-color: hsl(var(--custom-color-hue), 60%, 90%);
|
||||
}
|
||||
|
||||
.note-book-card.with-hue {
|
||||
--card-background-color: hsl(var(--custom-color-hue), 21%, 94%);
|
||||
--card-background-hover-color: hsl(var(--custom-color-hue), 21%, 87%);
|
||||
}
|
||||
@@ -643,139 +643,6 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
|
||||
transform: translateY(4%);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE LIST
|
||||
*/
|
||||
|
||||
.note-list .note-book-card {
|
||||
--note-list-horizontal-padding: 22px;
|
||||
--note-list-vertical-padding: 15px;
|
||||
background-color: var(--card-background-color);
|
||||
border: 1px solid var(--card-border-color) !important;
|
||||
border-radius: 12px;
|
||||
user-select: none;
|
||||
padding: 0;
|
||||
margin: 5px 10px 5px 0;
|
||||
}
|
||||
|
||||
:root .note-list .note-book-card:hover {
|
||||
background-color: var(--card-background-hover-color);
|
||||
transition: background-color 200ms ease-out;
|
||||
}
|
||||
|
||||
:root .note-list.grid-view .note-book-card:active {
|
||||
transform: scale(.98);
|
||||
}
|
||||
|
||||
.note-list.list-view .note-book-card {
|
||||
box-shadow: 0 0 3px var(--card-shadow-color);
|
||||
}
|
||||
|
||||
.note-list.list-view .note-book-card .note-book-header .note-icon {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card a {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-header {
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
padding: 0.5em 1rem;
|
||||
border-bottom-color: var(--card-border-color);
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-header .note-icon {
|
||||
font-size: 17px;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-header .note-book-title {
|
||||
font-size: 1em;
|
||||
color: var(--active-item-text-color);
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-header .rendered-note-attributes {
|
||||
font-size: 0.7em;
|
||||
font-weight: normal;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-header:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content {
|
||||
padding: 0 !important;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content .rendered-content {
|
||||
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;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content h1,
|
||||
.note-list-wrapper .note-book-card .note-book-content h2,
|
||||
.note-list-wrapper .note-book-card .note-book-content h3,
|
||||
.note-list-wrapper .note-book-card .note-book-content h4,
|
||||
.note-list-wrapper .note-book-card .note-book-content h5,
|
||||
.note-list-wrapper .note-book-card .note-book-content h6 {
|
||||
font-size: 1rem;
|
||||
color: var(--active-item-text-color);
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-canvas .rendered-content,
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-mindMap .rendered-content,
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-code .rendered-content,
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-video .rendered-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-code {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .note-book-content.type-code pre {
|
||||
height: 100%;
|
||||
padding: 1em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper .note-book-card .tn-icon {
|
||||
color: var(--left-pane-icon-color) !important;
|
||||
}
|
||||
|
||||
.note-list.grid-view .note-book-card:hover {
|
||||
filter: contrast(105%);
|
||||
}
|
||||
|
||||
.note-list.grid-view .ck-content {
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.note-list.grid-view .ck-content p {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.note-list.grid-view .ck-content figure.image {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE SEARCH SUGGESTIONS
|
||||
*/
|
||||
@@ -800,3 +667,18 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
|
||||
background: var(--hover-item-background-color);
|
||||
color: var(--hover-item-text-color);
|
||||
}
|
||||
|
||||
/*
|
||||
* Alert bars
|
||||
*/
|
||||
|
||||
div.alert {
|
||||
margin-bottom: 8px;
|
||||
background: var(--alert-bar-background) !important;
|
||||
border-radius: 8px;
|
||||
font-size: .85em;
|
||||
}
|
||||
|
||||
div.alert p + p {
|
||||
margin-block: 1em 0;
|
||||
}
|
||||
@@ -84,6 +84,22 @@ button.btn.btn-success kbd {
|
||||
letter-spacing: 0.5pt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Low profile buttons
|
||||
*/
|
||||
|
||||
button.tn-low-profile {
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
button.tn-low-profile:hover {
|
||||
background-color: var(--icon-button-hover-background);
|
||||
}
|
||||
|
||||
/*
|
||||
* Icon buttons
|
||||
*/
|
||||
@@ -129,6 +145,10 @@ button.btn.btn-success kbd {
|
||||
font-size: calc(var(--icon-button-size) * var(--icon-button-icon-ratio));
|
||||
}
|
||||
|
||||
:root .icon-action.disabled::before {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
:root .icon-action:not(.global-menu-button):hover,
|
||||
:root .icon-action:not(.global-menu-button).show,
|
||||
:root .tn-tool-button:hover,
|
||||
@@ -794,3 +814,35 @@ input[type="range"] {
|
||||
scrollbar-width: unset;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Centered forms
|
||||
*/
|
||||
|
||||
.tn-centered-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 20vh;
|
||||
}
|
||||
|
||||
.tn-centered-form .form-group {
|
||||
text-align: center;
|
||||
color: var(--muted-text-color);
|
||||
}
|
||||
|
||||
.tn-centered-form .form-icon {
|
||||
font-size: 140px;
|
||||
color: var(--main-border-color);
|
||||
}
|
||||
|
||||
.tn-centered-form .protected-session-password {
|
||||
margin-inline: auto;
|
||||
max-width: 350px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tn-centered-form .input-group,
|
||||
.tn-centered-form button {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
/* LLM Chat Launcher Widget Styles */
|
||||
.note-context-chat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.note-context-chat-container {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.chat-message {
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
max-width: 85%;
|
||||
}
|
||||
|
||||
.chat-message.user-message {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
|
||||
.chat-message.assistant-message {
|
||||
margin-inline-end: auto;
|
||||
}
|
||||
|
||||
.message-avatar {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-inline-end: 8px;
|
||||
}
|
||||
|
||||
.user-message .message-avatar {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.assistant-message .message-avatar {
|
||||
background-color: var(--secondary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
background-color: var(--more-accented-background-color);
|
||||
border-radius: 12px;
|
||||
padding: 10px 15px;
|
||||
max-width: calc(100% - 40px);
|
||||
}
|
||||
|
||||
.user-message .message-content {
|
||||
background-color: var(--accented-background-color);
|
||||
}
|
||||
|
||||
.message-content pre {
|
||||
background-color: var(--code-background-color);
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
overflow-x: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.message-content code {
|
||||
background-color: var(--code-background-color);
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.loading-indicator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 10px 0;
|
||||
color: var(--muted-text-color);
|
||||
}
|
||||
|
||||
.sources-container {
|
||||
background-color: var(--accented-background-color);
|
||||
border-top: 1px solid var(--main-border-color);
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.sources-list {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.source-item {
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.source-link {
|
||||
color: var(--link-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.source-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.note-context-chat-form {
|
||||
display: flex;
|
||||
background-color: var(--main-background-color);
|
||||
border-top: 1px solid var(--main-border-color);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.note-context-chat-input {
|
||||
resize: vertical;
|
||||
min-height: 44px;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.chat-message {
|
||||
max-width: 95%;
|
||||
}
|
||||
}
|
||||
@@ -265,13 +265,6 @@ body.desktop .options-section:not(.tn-no-card) {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.options-section .alert {
|
||||
margin-bottom: 8px;
|
||||
background: var(--alert-bar-background) !important;
|
||||
border-radius: 8px;
|
||||
font-size: .85em;
|
||||
}
|
||||
|
||||
nav.options-section-tabs {
|
||||
min-width: var(--options-card-min-width);
|
||||
max-width: var(--options-card-max-width);
|
||||
|
||||
@@ -751,12 +751,14 @@ body[dir=rtl] #left-pane span.fancytree-node.protected > span.fancytree-custom-i
|
||||
}
|
||||
}
|
||||
|
||||
#left-pane .fancytree-expander {
|
||||
#left-pane .fancytree-expander,
|
||||
.nested-note-list-item .note-expander {
|
||||
opacity: 0.65;
|
||||
transition: opacity 150ms ease-in;
|
||||
}
|
||||
|
||||
#left-pane .fancytree-expander:hover {
|
||||
#left-pane .fancytree-expander:hover,
|
||||
.nested-note-list-item .note-expander:hover {
|
||||
opacity: 1;
|
||||
transition: opacity 300ms ease-out;
|
||||
}
|
||||
|
||||
@@ -566,113 +566,6 @@
|
||||
"enable-smooth-scroll": "تمكين التمرير السلس",
|
||||
"enable-motion": "تمكين الانتقالات والرسوم المتحركة"
|
||||
},
|
||||
"ai_llm": {
|
||||
"progress": "تقدم",
|
||||
"openai_tab": "OpenAI",
|
||||
"actions": "أجراءات",
|
||||
"retry": "أعد المحاولة",
|
||||
"reprocessing_index": "جار اعادة البناء...",
|
||||
"never": "ابدٱ",
|
||||
"agent": {
|
||||
"processing": "جار المعالجة...",
|
||||
"thinking": "جار التفكير...",
|
||||
"loading": "جار التحميل...",
|
||||
"generating": "جار الانشاء..."
|
||||
},
|
||||
"name": "الذكاء الأصطناعي",
|
||||
"openai": "OpenAI",
|
||||
"sources": "مصادر",
|
||||
"temperature": "درجة الحرارة",
|
||||
"model": "نموذج",
|
||||
"refreshing_models": "جار التحديث...",
|
||||
"error": "خطأ",
|
||||
"refreshing": "جار التحديث...",
|
||||
"ollama_tab": "Ollama",
|
||||
"anthropic_tab": "انتروبيك",
|
||||
"not_started": "لم يبدأ بعد",
|
||||
"title": "اعدادات AI",
|
||||
"processed_notes": "الملاحظات المعالجة",
|
||||
"total_notes": "الملاحظات الكلية",
|
||||
"queued_notes": "الملاحظات في قائمة الانتظار",
|
||||
"failed_notes": "الملاحظات الفاشلة",
|
||||
"last_processed": "اخر معالجة",
|
||||
"refresh_stats": "تحديث الاحصائيات",
|
||||
"voyage_tab": "استكشاف AI",
|
||||
"provider_precedence": "اولوية المزود",
|
||||
"system_prompt": "موجه النظام",
|
||||
"openai_configuration": "اعدادات OpenAI",
|
||||
"openai_settings": "اعدادات OpenAI",
|
||||
"api_key": "مفتاح واجهة برمجة التطبيقات",
|
||||
"url": "عنوان URL الاساسي",
|
||||
"default_model": "النموذج الافتراضي",
|
||||
"base_url": "عنوان URL الأساسي",
|
||||
"openai_url_description": "افتراضيا: https://api.openai.com/v1",
|
||||
"anthropic_settings": "اعدادات انتروبيك",
|
||||
"ollama_settings": "اعدادات Ollama",
|
||||
"anthropic_configuration": "تهيئة انتروبيك",
|
||||
"voyage_url_description": "افتراضيا: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "تهيئة Ollama",
|
||||
"enable_ollama": "تمكين Ollama",
|
||||
"last_attempt": "اخر محاولة",
|
||||
"active_providers": "المزودون النشطون",
|
||||
"disabled_providers": "المزودون المعطلون",
|
||||
"similarity_threshold": "عتبة التشابه",
|
||||
"complete": "اكتمل (100%)",
|
||||
"ai_settings": "اعدادات AI",
|
||||
"show_thinking": "عرض التفكير",
|
||||
"index_status": "حالة الفهرس",
|
||||
"indexed_notes": "الملاحظات المفهرسة",
|
||||
"indexing_stopped": "تم ايقاف الفهرسة",
|
||||
"last_indexed": "اخر فهرسة",
|
||||
"note_chat": "دردشة الملاحظة",
|
||||
"start_indexing": "بدء الفهرسة",
|
||||
"chat": {
|
||||
"root_note_title": "دردشات AI",
|
||||
"new_chat_title": "دردشة جديدة",
|
||||
"create_new_ai_chat": "انشاء دردشة AI جديدة"
|
||||
},
|
||||
"selected_provider": "المزود المحدد",
|
||||
"select_model": "اختر النموذج...",
|
||||
"select_provider": "اختر المزود...",
|
||||
"ollama_model": "نموذج Ollama",
|
||||
"refresh_models": "تحديث النماذج",
|
||||
"rebuild_index": "اعادة بناء الفهرس",
|
||||
"note_title": "عنوان الملاحظة",
|
||||
"processing": "جاري المعالجة ({{percentage}}%)",
|
||||
"incomplete": "غير مكتمل ({{percentage}}%)",
|
||||
"ollama_url": "عنوان URL الخاص ب Ollama",
|
||||
"provider_configuration": "تكوين موفر AI",
|
||||
"voyage_settings": "استكشاف اعدادات AI",
|
||||
"enable_automatic_indexing": "تمكين الفهرسة التلقائية",
|
||||
"index_rebuild_progress": "تقدم اعادة انشاء الفهرس",
|
||||
"index_rebuild_complete": "اكتملت عملية تحسين الفهرس",
|
||||
"use_enhanced_context": "استخدام السياق المحسن",
|
||||
"enter_message": "ادخل رسالتك...",
|
||||
"index_all_notes": "فهرسة جميع الملاحظات",
|
||||
"indexing_in_progress": "جار فهرسة الملاحظات...",
|
||||
"use_advanced_context": "استخدم السياق المتقدم",
|
||||
"ai_enabled": "تمكين مميزات AI",
|
||||
"ai_disabled": "الغاء تمكين مميزات AI",
|
||||
"enable_ai_features": "تمكين خصائص AI/LLM",
|
||||
"enable_ai": "تمكين خصائص AI/LLM",
|
||||
"reprocess_index": "اعادة بناء فهرس البحث",
|
||||
"index_rebuilding": "جار تحسين الفهرس {{percentage}}",
|
||||
"voyage_configuration": "اعدادت Voyage AI",
|
||||
"openai_model_description": "الامثلة: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"partial": "{{ percentage }} % مكتمل",
|
||||
"retry_queued": "تم جدولة الملاحظة لاعادة المحاولة",
|
||||
"max_notes_per_llm_query": "اكبر عدد للملاحظات لكل استعلام",
|
||||
"remove_provider": "احذف المزود من البحث",
|
||||
"restore_provider": "استعادة المزود الى البحث",
|
||||
"reprocess_index_error": "حدث خطأ اثناء اعادة بناء فهرس البحث",
|
||||
"auto_refresh_notice": "تحديث تلقائي كل {{seconds}} ثانية",
|
||||
"note_queued_for_retry": "الملاحظة جاهزة لاعادة المحاولة لاحقا",
|
||||
"failed_to_retry_note": "فشل في اعادة محاولة معالجة المحاولة",
|
||||
"failed_to_retry_all": "فشل في اعادة محاولة معالجة الملاحظة",
|
||||
"error_generating_response": "فشل في توليد استجابة من ال AI",
|
||||
"create_new_ai_chat": "انشاء دردشة AI جديدة",
|
||||
"error_fetching": "فشل في استرجاع النماذج: {{error}}"
|
||||
},
|
||||
"code_auto_read_only_size": {
|
||||
"unit": "حروف",
|
||||
"title": "الحجم التلقائي للقراءه فقط"
|
||||
@@ -910,7 +803,6 @@
|
||||
"web-view": "عرض الويب",
|
||||
"mind-map": "خريطة ذهنية",
|
||||
"geo-map": "خريطة جغرافية",
|
||||
"ai-chat": "دردشة AI",
|
||||
"task-list": "قائمة المهام"
|
||||
},
|
||||
"shared_switch": {
|
||||
@@ -1180,9 +1072,6 @@
|
||||
"note_not_found": "الملاحظة {{noteId}} غير موجودة!",
|
||||
"cannot_match_transform": "تعذر مطابقة التحويل: {{transform}}"
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "عرض الويب"
|
||||
},
|
||||
"consistency_checks": {
|
||||
"title": "فحوصات التناسق"
|
||||
},
|
||||
|
||||
@@ -1008,7 +1008,7 @@
|
||||
"no_attachments": "此笔记没有附件。"
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "此类型为书籍的笔记没有任何子笔记,因此没有内容显示。请参阅 <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> 了解详情。",
|
||||
"no_children_help": "此集合没有任何子笔记,因此没有内容显示。",
|
||||
"drag_locked_title": "锁定编辑",
|
||||
"drag_locked_message": "无法拖拽,因为集合已被锁定编辑。"
|
||||
},
|
||||
@@ -1064,15 +1064,6 @@
|
||||
"default_new_note_title": "新笔记",
|
||||
"click_on_canvas_to_place_new_note": "点击画布以放置新笔记"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "之所以显示此帮助说明,是因为这个类型为渲染 HTML 的笔记没有正常工作所需的关系。",
|
||||
"note_detail_render_help_2": "渲染 HTML 笔记类型用于<a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">编写脚本</a>。简而言之,您有一份 HTML 代码笔记(可包含一些 JavaScript),然后这个笔记会把页面渲染出来。要使其正常工作,您需要定义一个名为 \"renderNote\" 的<a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">关系</a>指向要渲染的 HTML 笔记。"
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "网页视图",
|
||||
"embed_websites": "网页视图类型的笔记允许您将网站嵌入到 Trilium 中。",
|
||||
"create_label": "首先,请创建一个带有您要嵌入的 URL 地址的标签,例如 #webViewSrc=\"https://www.bing.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "刷新"
|
||||
},
|
||||
@@ -1421,7 +1412,8 @@
|
||||
"description": "描述",
|
||||
"reload_app": "重载应用以应用更改",
|
||||
"set_all_to_default": "将所有快捷键重置为默认值",
|
||||
"confirm_reset": "您确定要将所有键盘快捷键重置为默认值吗?"
|
||||
"confirm_reset": "您确定要将所有键盘快捷键重置为默认值吗?",
|
||||
"no_results": "未找到与“{{filter}}”匹配的快捷方式"
|
||||
},
|
||||
"spellcheck": {
|
||||
"title": "拼写检查",
|
||||
@@ -1540,7 +1532,6 @@
|
||||
"geo-map": "地理地图",
|
||||
"beta-feature": "测试版",
|
||||
"task-list": "任务列表",
|
||||
"ai-chat": "AI聊天",
|
||||
"new-feature": "新建",
|
||||
"collections": "集合",
|
||||
"book": "集合"
|
||||
@@ -1622,7 +1613,9 @@
|
||||
"print_report_title": "打印报告",
|
||||
"print_report_collection_content_other": "集合中的 {{count}} 篇笔记无法打印,因为它们不受支持或受到保护。",
|
||||
"print_report_collection_details_button": "查看详情",
|
||||
"print_report_collection_details_ignored_notes": "忽略的笔记"
|
||||
"print_report_collection_details_ignored_notes": "忽略的笔记",
|
||||
"print_report_error_title": "打印失败",
|
||||
"print_report_stack_trace": "堆栈跟踪"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "请输入笔记标题...",
|
||||
@@ -1845,149 +1838,6 @@
|
||||
"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": "最后索引时间",
|
||||
"note_chat": "笔记聊天",
|
||||
"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": "编辑器"
|
||||
},
|
||||
@@ -2075,7 +1925,8 @@
|
||||
"raster": "栅格",
|
||||
"vector_light": "矢量(浅色)",
|
||||
"vector_dark": "矢量(深色)",
|
||||
"show-scale": "显示比例尺"
|
||||
"show-scale": "显示比例尺",
|
||||
"show-labels": "显示标记名称"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "删除行"
|
||||
@@ -2154,7 +2005,6 @@
|
||||
"app-restart-required": "(需重启程序以应用更改)"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "第 {{startIndex}} 页 - 第 {{endIndex}} 页",
|
||||
"total_notes": "{{count}} 篇笔记"
|
||||
},
|
||||
"collections": {
|
||||
@@ -2268,5 +2118,49 @@
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "书签"
|
||||
},
|
||||
"web_view_setup": {
|
||||
"title": "直接在 Trilium 中创建网页的实时视图",
|
||||
"url_placeholder": "输入或粘贴网站地址,例如 https://triliumnotes.org",
|
||||
"create_button": "创建网页视图",
|
||||
"invalid_url_title": "无效的地址",
|
||||
"invalid_url_message": "请输入有效的网址,例如 https://triliumnotes.org。",
|
||||
"disabled_description": "此网页视图来自外部来源。为保护您免受网络钓鱼或恶意内容侵害,该视图不会自动加载。若您信任该来源,可手动启用加载功能。",
|
||||
"disabled_button_enable": "启用网页视图"
|
||||
},
|
||||
"render": {
|
||||
"setup_title": "在此笔记中显示自定义 HTML 或 Preact JSX",
|
||||
"setup_create_sample_preact": "使用 Preact 建立范例笔记",
|
||||
"setup_create_sample_html": "使用 HTML 建立范例笔记",
|
||||
"setup_sample_created": "已建立一个范例笔记作为子笔记。",
|
||||
"disabled_description": "此渲染笔记来自外部来源。为保护您免受恶意内容侵害,该功能默认处于禁用状态。启用前请确保您信任该来源。",
|
||||
"disabled_button_enable": "启用渲染笔记"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "图标包",
|
||||
"type_backend_script": "后端脚本",
|
||||
"type_frontend_script": "前端脚本",
|
||||
"type_widget": "小部件",
|
||||
"type_app_css": "自定义 CSS",
|
||||
"type_render_note": "渲染笔记",
|
||||
"type_web_view": "网页视图",
|
||||
"type_app_theme": "自定义主题",
|
||||
"toggle_tooltip_enable_tooltip": "点击以启用此 {{type}}。",
|
||||
"toggle_tooltip_disable_tooltip": "点击以禁用此 {{type}}。",
|
||||
"menu_docs": "打开文档",
|
||||
"menu_execute_now": "立即执行脚本",
|
||||
"menu_run": "自动执行",
|
||||
"menu_run_disabled": "手动",
|
||||
"menu_run_backend_startup": "当后端启动时",
|
||||
"menu_run_hourly": "每小时",
|
||||
"menu_run_daily": "每日",
|
||||
"menu_run_frontend_startup": "当桌面前端启动时",
|
||||
"menu_run_mobile_startup": "当移动前端启动时",
|
||||
"menu_change_to_widget": "更改为小部件",
|
||||
"menu_change_to_frontend_script": "更改为前端脚本",
|
||||
"menu_theme_base": "主题基底"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "了解更多"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,9 +428,9 @@
|
||||
"run_on_note_content_change": "Wird ausgeführt, wenn der Inhalt einer Notiz geändert wird (einschließlich der Erstellung von Notizen).",
|
||||
"run_on_note_change": "Wird ausgeführt, wenn eine Notiz geändert wird (einschließlich der Erstellung von Notizen). Enthält keine Inhaltsänderungen",
|
||||
"run_on_note_deletion": "Wird ausgeführt, wenn eine Notiz gelöscht wird",
|
||||
"run_on_branch_creation": "wird ausgeführt, wenn ein Zweig erstellt wird. Der Zweig ist eine Verbindung zwischen der übergeordneten Notiz und der untergeordneten Notiz und wird z. B. erstellt. beim Klonen oder Verschieben von Notizen.",
|
||||
"run_on_branch_creation": "wird ausgeführt, wenn ein Zweig erstellt wird. Der Zweig ist eine Verbindung zwischen der übergeordneten und der untergeordneten Notiz und wird z. B. beim Klonen oder Verschieben von Notizen erstellt.",
|
||||
"run_on_branch_change": "wird ausgeführt, wenn ein Zweig aktualisiert wird.",
|
||||
"run_on_branch_deletion": "wird ausgeführt, wenn ein Zweig gelöscht wird. Der Zweig ist eine Verknüpfung zwischen der übergeordneten Notiz und der untergeordneten Notiz und wird z. B. gelöscht. beim Verschieben der Notiz (alter Zweig/Link wird gelöscht).",
|
||||
"run_on_branch_deletion": "wird ausgeführt, wenn ein Zweig gelöscht wird. Der Zweig ist eine Verknüpfung zwischen der übergeordneten und der untergeordneten Notiz und wird z. B. beim Verschieben der Notiz gelöscht (alter Zweig/Link wird gelöscht).",
|
||||
"run_on_attribute_creation": "wird ausgeführt, wenn für die Notiz ein neues Attribut erstellt wird, das diese Beziehung definiert",
|
||||
"run_on_attribute_change": " wird ausgeführt, wenn das Attribut einer Notiz geändert wird, die diese Beziehung definiert. Dies wird auch ausgelöst, wenn das Attribut gelöscht wird",
|
||||
"relation_template": "Die Attribute der Notiz werden auch ohne eine Hierarchische-Beziehung vererbt. Der Inhalt und der Zweig werden den Instanznotizen hinzugefügt, wenn sie leer sind. Einzelheiten findest du in der Dokumentation.",
|
||||
@@ -801,7 +801,7 @@
|
||||
"expand_tooltip": "Erweitert die direkten Unterelemente dieser Sammlung (eine Ebene tiefer). Für weitere Optionen auf den Pfeil rechts klicken.",
|
||||
"expand_first_level": "Direkte Unterelemente erweitern",
|
||||
"expand_nth_level": "{{depth}} Ebenen erweitern",
|
||||
"hide_child_notes": "Unternotizen im Baum ausblenden"
|
||||
"hide_child_notes": "Untergeordnete Notizen im Baum ausblenden"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "An diesem Tag wurden noch keine Notizen bearbeitet...",
|
||||
@@ -1007,7 +1007,7 @@
|
||||
"no_attachments": "Diese Notiz enthält keine Anhänge."
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "Diese Notiz mit dem Notiztyp Buch besitzt keine Unternotizen, deshalb ist nichts zum Anzeigen vorhanden. Siehe <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">Wiki</a> für mehr Details.",
|
||||
"no_children_help": "Diese Sammlung enthält keine untergeordnete Notizen, daher gibt es nichts anzuzeigen.",
|
||||
"drag_locked_title": "Für Bearbeitung gesperrt",
|
||||
"drag_locked_message": "Das Ziehen ist nicht möglich, da die Sammlung für die Bearbeitung gesperrt ist."
|
||||
},
|
||||
@@ -1063,15 +1063,6 @@
|
||||
"default_new_note_title": "neue Notiz",
|
||||
"click_on_canvas_to_place_new_note": "Klicke auf den Canvas, um eine neue Notiz zu platzieren"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Diese Hilfesnotiz wird angezeigt, da diese Notiz vom Typ „HTML rendern“ nicht über die erforderliche Beziehung verfügt, um ordnungsgemäß zu funktionieren.",
|
||||
"note_detail_render_help_2": "Render-HTML-Notiztyp wird benutzt für <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">scripting</a>. Kurzgesagt, du hast ein HTML-Code-Notiz (optional mit JavaScript) und diese Notiz rendert es. Damit es funktioniert, musst du eine a <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">Beziehung</a> namens \"renderNote\" zeigend auf die HTML-Notiz zum rendern definieren."
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Webansicht",
|
||||
"embed_websites": "Notiz vom Typ Web View ermöglicht das Einbetten von Websites in Trilium.",
|
||||
"create_label": "Um zu beginnen, erstelle bitte ein Label mit einer URL-Adresse, die eingebettet werden soll, z. B. #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Aktualisieren"
|
||||
},
|
||||
@@ -1196,7 +1187,7 @@
|
||||
"tooltip_code_note_syntax": "Code-Notizen"
|
||||
},
|
||||
"vim_key_bindings": {
|
||||
"use_vim_keybindings_in_code_notes": "Verwende VIM-Tastenkombinationen in Codenotizen (kein Ex-Modus)",
|
||||
"use_vim_keybindings_in_code_notes": "Vim Tastenbelegung",
|
||||
"enable_vim_keybindings": "Aktiviere Vim-Tastenkombinationen"
|
||||
},
|
||||
"wrap_lines": {
|
||||
@@ -1387,7 +1378,8 @@
|
||||
"description": "Beschreibung",
|
||||
"reload_app": "Lade die App neu, um die Änderungen zu übernehmen",
|
||||
"set_all_to_default": "Setze alle Verknüpfungen auf die Standardeinstellungen",
|
||||
"confirm_reset": "Möchtest du wirklich alle Tastaturkürzel auf die Standardeinstellungen zurücksetzen?"
|
||||
"confirm_reset": "Möchtest du wirklich alle Tastaturkürzel auf die Standardeinstellungen zurücksetzen?",
|
||||
"no_results": "Keine Tastenkürzel für '{{filter}}' gefunden"
|
||||
},
|
||||
"spellcheck": {
|
||||
"title": "Rechtschreibprüfung",
|
||||
@@ -1447,7 +1439,7 @@
|
||||
"open-in-a-new-tab": "In neuem Tab öffnen",
|
||||
"open-in-a-new-split": "In neuem Split öffnen",
|
||||
"insert-note-after": "Notiz dahinter einfügen",
|
||||
"insert-child-note": "Unternotiz einfügen",
|
||||
"insert-child-note": "Untergeordnete Notiz einfügen",
|
||||
"delete": "Löschen",
|
||||
"search-in-subtree": "Im Zweig suchen",
|
||||
"hoist-note": "Notiz-Fokus setzen",
|
||||
@@ -1566,7 +1558,7 @@
|
||||
"saved-search-note-refreshed": "Gespeicherte Such-Notiz wurde aktualisiert.",
|
||||
"hoist-this-note-workspace": "Diese Notiz fokussieren (Arbeitsbereich)",
|
||||
"refresh-saved-search-results": "Gespeicherte Suchergebnisse aktualisieren",
|
||||
"create-child-note": "Unternotiz anlegen",
|
||||
"create-child-note": "Untergeordnete Notiz anlegen",
|
||||
"unhoist": "Fokus verlassen",
|
||||
"toggle-sidebar": "Seitenleiste ein-/ausblenden",
|
||||
"dropping-not-allowed": "Ablegen von Notizen an dieser Stelle ist nicht zulässig.",
|
||||
@@ -1577,7 +1569,7 @@
|
||||
"subtree-hidden-tooltip_one": "{{count}} untergeordnete Notiz, die im Baum ausgeblendet ist",
|
||||
"subtree-hidden-tooltip_other": "{{count}} untergeordnete Notizen, die im Baum ausgeblendet sind",
|
||||
"subtree-hidden-moved-title": "Zu {{title}} hinzugefügt",
|
||||
"subtree-hidden-moved-description-collection": "Diese Sammlung blendet ihre Unternotizen im Baum aus.",
|
||||
"subtree-hidden-moved-description-collection": "Diese Sammlung blendet ihre untergeordneten Notizen im Baum aus.",
|
||||
"subtree-hidden-moved-description-other": "Untergeordnete Notizen sind im Baum für diese Notiz ausgeblendet."
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
@@ -1591,7 +1583,9 @@
|
||||
"print_report_collection_details_button": "Details anzeigen",
|
||||
"print_report_collection_details_ignored_notes": "Ignorierte Notizen",
|
||||
"print_report_collection_content_one": "{{count}} Notiz in der Sammlung konnte nicht gedruckt werden, weil sie nicht unterstützt oder geschützt ist.",
|
||||
"print_report_collection_content_other": "{{count}} Notizen in der Sammlung konnten nicht gedruckt werden, weil sie nicht unterstützt oder geschützt sind."
|
||||
"print_report_collection_content_other": "{{count}} Notizen in der Sammlung konnten nicht gedruckt werden, weil sie nicht unterstützt oder geschützt sind.",
|
||||
"print_report_error_title": "Druck fehlgeschlagen",
|
||||
"print_report_stack_trace": "Stapelzurückverfolgung"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "Titel der Notiz hier eingeben…",
|
||||
@@ -1606,7 +1600,8 @@
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "Es wurden keine Notizen mit den angegebenen Suchparametern gefunden.",
|
||||
"search_not_executed": "Die Suche wurde noch nicht ausgeführt. Klicke oben auf „Suchen“, um die Ergebnisse anzuzeigen."
|
||||
"search_not_executed": "Die Suche wurde noch nicht ausgeführt.",
|
||||
"search_now": "Jetzt suchen"
|
||||
},
|
||||
"spacer": {
|
||||
"configure_launchbar": "Starterleiste konfigurieren"
|
||||
@@ -1762,7 +1757,7 @@
|
||||
},
|
||||
"note_autocomplete": {
|
||||
"search-for": "Suche nach \"{{term}}\"",
|
||||
"create-note": "Erstelle und verlinke Unternotiz \"{{term}}\"",
|
||||
"create-note": "Erstelle und verlinke untergeordnete Notiz \"{{term}}\"",
|
||||
"insert-external-link": "Einfügen von Externen Link zu \"{{term}}\"",
|
||||
"clear-text-field": "Textfeldinhalt löschen",
|
||||
"show-recent-notes": "Aktuelle Notizen anzeigen",
|
||||
@@ -1773,7 +1768,7 @@
|
||||
"quick-edit": "Schnellbearbeitung"
|
||||
},
|
||||
"geo-map": {
|
||||
"create-child-note-title": "Neue Unternotiz anlegen und zur Karte hinzufügen",
|
||||
"create-child-note-title": "Neue untergeordnete Notiz anlegen und zur Karte hinzufügen",
|
||||
"create-child-note-instruction": "Auf die Karte klicken, um eine neue Notiz an der Stelle zu erstellen oder Escape drücken um abzubrechen.",
|
||||
"unable-to-load-map": "Karte konnte nicht geladen werden.",
|
||||
"create-child-note-text": "Marker hinzufügen"
|
||||
@@ -1800,149 +1795,6 @@
|
||||
"close": "Schließen",
|
||||
"help_title": "Zeige mehr Informationen zu diesem Fenster"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Nicht gestartet",
|
||||
"title": "KI Einstellungen",
|
||||
"processed_notes": "Verarbeitete Notizen",
|
||||
"total_notes": "Gesamt Notizen",
|
||||
"progress": "Fortschritt",
|
||||
"queued_notes": "Eingereihte Notizen",
|
||||
"failed_notes": "Fehlgeschlagenen Notizen",
|
||||
"last_processed": "Zuletzt verarbeitet",
|
||||
"refresh_stats": "Statistiken neu laden",
|
||||
"enable_ai_features": "Aktiviere KI/LLM Funktionen",
|
||||
"enable_ai_description": "Aktiviere KI-Funktionen wie Notizzusammenfassungen, Inhaltserzeugung und andere LLM-Funktionen",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Aktiviere KI/LLM Funktionen",
|
||||
"enable_ai_desc": "Aktiviere KI-Funktionen wie Notizzusammenfassungen, Inhaltserzeugung und andere LLM-Funktionen",
|
||||
"provider_configuration": "KI-Anbieterkonfiguration",
|
||||
"provider_precedence": "Anbieter Priorität",
|
||||
"provider_precedence_description": "Komma-getrennte Liste von Anbieter in der Reihenfolge ihrer Priorität (z.B. 'openai, anthropic,ollama')",
|
||||
"temperature": "Temperatur",
|
||||
"temperature_description": "Regelt die Zufälligkeit in Antworten (0 = deterministisch, 2 = maximale Zufälligkeit)",
|
||||
"system_prompt": "Systemaufforderung",
|
||||
"system_prompt_description": "Standard Systemaufforderung für alle KI-Interaktionen",
|
||||
"openai_configuration": "OpenAI Konfiguration",
|
||||
"openai_settings": "OpenAI Einstellungen",
|
||||
"api_key": "API Schlüssel",
|
||||
"url": "Basis-URL",
|
||||
"model": "Modell",
|
||||
"anthropic_settings": "Anthropic Einstellungen",
|
||||
"partial": "{{ percentage }}% verarbeitet",
|
||||
"anthropic_api_key_description": "Dein Anthropic API-Key für den Zugriff auf Claude Modelle",
|
||||
"anthropic_model_description": "Anthropic Claude Modell für Chat-Vervollständigung",
|
||||
"voyage_settings": "Einstellungen für Voyage AI",
|
||||
"ollama_url_description": "URL für die Ollama API (Standard: http://localhost:11434)",
|
||||
"ollama_model_description": "Ollama Modell für Chat-Vervollständigung",
|
||||
"anthropic_configuration": "Anthropic Konfiguration",
|
||||
"voyage_configuration": "Voyage AI Konfiguration",
|
||||
"voyage_url_description": "Standard: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Ollama Konfiguration",
|
||||
"enable_ollama": "Aktiviere Ollama",
|
||||
"enable_ollama_description": "Aktiviere Ollama für lokale KI Modell Nutzung",
|
||||
"ollama_url": "Ollama URL",
|
||||
"ollama_model": "Ollama Modell",
|
||||
"refresh_models": "Aktualisiere Modelle",
|
||||
"refreshing_models": "Aktualisiere...",
|
||||
"enable_automatic_indexing": "Aktiviere automatische Indizierung",
|
||||
"rebuild_index": "Index neu aufbauen",
|
||||
"rebuild_index_error": "Fehler beim Neuaufbau des Index. Prüfe Log für mehr Informationen.",
|
||||
"retry_failed": "Fehler: Notiz konnte nicht erneut eingereiht werden",
|
||||
"max_notes_per_llm_query": "Max. Notizen je Abfrage",
|
||||
"max_notes_per_llm_query_description": "Maximale Anzahl ähnlicher Notizen zum Einbinden als KI Kontext",
|
||||
"active_providers": "Aktive Anbieter",
|
||||
"disabled_providers": "Inaktive Anbieter",
|
||||
"remove_provider": "Entferne Anbieter von Suche",
|
||||
"restore_provider": "Anbieter zur Suche wiederherstellen",
|
||||
"similarity_threshold": "Ähnlichkeitsschwelle",
|
||||
"similarity_threshold_description": "Mindestähnlichkeitswert (0-1) für Notizen, die im Kontext für LLM-Abfragen berücksichtigt werden sollen",
|
||||
"reprocess_index": "Suchindex neu erstellen",
|
||||
"reprocessing_index": "Neuerstellung...",
|
||||
"reprocess_index_started": "Suchindex-Optimierung wurde im Hintergrund gestartet",
|
||||
"reprocess_index_error": "Fehler beim Wiederaufbau des Suchindex",
|
||||
"index_rebuild_progress": "Fortschritt der Index-Neuerstellung",
|
||||
"index_rebuilding": "Optimierung Index ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Index Optimierung abgeschlossen",
|
||||
"index_rebuild_status_error": "Fehler bei Überprüfung Status Index Neuerstellung",
|
||||
"never": "Niemals",
|
||||
"processing": "Verarbeitung ({{percentage}}%)",
|
||||
"refreshing": "Aktualisiere...",
|
||||
"incomplete": "Unvollständig ({{percentage}}%)",
|
||||
"complete": "Abgeschlossen (100%)",
|
||||
"auto_refresh_notice": "Auto-Aktualisierung alle {{seconds}} Sekunden",
|
||||
"note_queued_for_retry": "Notiz in Warteschlange für erneuten Versuch hinzugefügt",
|
||||
"failed_to_retry_note": "Wiederholungsversuch fehlgeschlagen für Notiz",
|
||||
"ai_settings": "KI Einstellungen",
|
||||
"agent": {
|
||||
"processing": "Verarbeite...",
|
||||
"thinking": "Nachdenken...",
|
||||
"loading": "Lade...",
|
||||
"generating": "Generiere..."
|
||||
},
|
||||
"name": "KI",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Benutze verbesserten Kontext",
|
||||
"openai_api_key_description": "Dein OpenAPI-Key für den Zugriff auf den KI-Dienst",
|
||||
"default_model": "Standardmodell",
|
||||
"openai_model_description": "Beispiele: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "Basis URL",
|
||||
"openai_url_description": "Standard: https://api.openai.com/v1",
|
||||
"anthropic_url_description": "Basis URL für Anthropic API (Standard: https://api.anthropic.com)",
|
||||
"ollama_settings": "Ollama Einstellungen",
|
||||
"note_title": "Notiz Titel",
|
||||
"error": "Fehler",
|
||||
"last_attempt": "Letzter Versuch",
|
||||
"actions": "Aktionen",
|
||||
"retry": "Erneut versuchen",
|
||||
"retry_queued": "Notiz für weiteren Versuch eingereiht",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "Anthropic API-Key ist leer. Bitte gültigen API-Key eingeben.",
|
||||
"openai": "OpenAI API-Key ist leer. Bitte gültigen API-Key eingeben.",
|
||||
"voyage": "Voyage API-Key ist leer. Bitte gültigen API-Key eingeben.",
|
||||
"ollama": "Ollama API-Key ist leer. Bitte gültigen API-Key eingeben."
|
||||
},
|
||||
"api_key_tooltip": "API-Key für den Zugriff auf den Dienst",
|
||||
"failed_to_retry_all": "Wiederholungsversuch für Notizen fehlgeschlagen",
|
||||
"all_notes_queued_for_retry": "Alle fehlgeschlagenen Notizen wurden zur Wiederholung in die Warteschlange gestellt",
|
||||
"enhanced_context_description": "Versorgt die KI mit mehr Kontext aus der Notiz und den zugehörigen Notizen, um bessere Antworten zu ermöglichen",
|
||||
"show_thinking": "Zeige Denkprozess",
|
||||
"show_thinking_description": "Zeige den Denkprozess der KI",
|
||||
"enter_message": "Geben Sie Ihre Nachricht ein...",
|
||||
"error_contacting_provider": "Fehler beim Kontaktieren des KI-Anbieters. Bitte überprüfe die Einstellungen und die Internetverbindung.",
|
||||
"error_generating_response": "Fehler beim Generieren der KI Antwort",
|
||||
"index_all_notes": "Indiziere alle Notizen",
|
||||
"index_status": "Indizierungsstatus",
|
||||
"indexed_notes": "Indizierte Notizen",
|
||||
"indexing_stopped": "Indizierung gestoppt",
|
||||
"indexing_in_progress": "Indizierung in Bearbeitung...",
|
||||
"last_indexed": "Zuletzt Indiziert",
|
||||
"note_chat": "Notizen-Chat",
|
||||
"sources": "Quellen",
|
||||
"start_indexing": "Starte Indizierung",
|
||||
"use_advanced_context": "Benutze erweiterten Kontext",
|
||||
"ollama_no_url": "Ollama ist nicht konfiguriert. Bitte trage eine gültige URL ein.",
|
||||
"chat": {
|
||||
"root_note_title": "KI Chats",
|
||||
"root_note_content": "Diese Notiz enthält gespeicherte KI-Chat-Unterhaltungen.",
|
||||
"new_chat_title": "Neuer Chat",
|
||||
"create_new_ai_chat": "Erstelle neuen KI Chat"
|
||||
},
|
||||
"create_new_ai_chat": "Erstelle neuen KI Chat",
|
||||
"configuration_warnings": "Es wurden Probleme mit der KI Konfiguration festgestellt. Bitte überprüfe die Einstellungen.",
|
||||
"experimental_warning": "Die LLM-Funktionen sind aktuell experimentell - sei an dieser Stelle gewarnt.",
|
||||
"selected_provider": "Ausgewählter Anbieter",
|
||||
"selected_provider_description": "Wähle einen KI-Anbieter für Chat- und Vervollständigungsfunktionen",
|
||||
"select_model": "Wähle Modell...",
|
||||
"select_provider": "Wähle Anbieter...",
|
||||
"ai_enabled": "KI Funktionen aktiviert",
|
||||
"ai_disabled": "KI Funktionen deaktiviert",
|
||||
"no_models_found_online": "Keine Modelle gefunden. Bitte überprüfe den API-Key und die Einstellungen.",
|
||||
"no_models_found_ollama": "Kein Ollama Modell gefunden. Bitte prüfe, ob Ollama gerade läuft.",
|
||||
"error_fetching": "Fehler beim Abrufen der Modelle: {{error}}"
|
||||
},
|
||||
"zen_mode": {
|
||||
"button_exit": "Verlasse Zen Modus"
|
||||
},
|
||||
@@ -1977,7 +1829,7 @@
|
||||
"no_totp_secret_warning": "Um TOTP zu aktivieren, muss zunächst ein TOTP Geheimnis generiert werden.",
|
||||
"totp_secret_description_warning": "Nach der Generierung des TOTP Geheimnisses ist eine Neuanmeldung mit dem TOTP Geheimnis erforderlich.",
|
||||
"totp_secret_generated": "TOTP Geheimnis generiert",
|
||||
"totp_secret_warning": "Bitte speichere das TOTP Geheimnis an einem sicheren Ort. Es wird nicht noch einmal angezeigt.",
|
||||
"totp_secret_warning": "Bitte speichere das generierte Geheimnis an einem sicheren Ort. Es wird nicht noch einmal angezeigt.",
|
||||
"totp_secret_regenerate_confirm": "Möchten Sie das TOTP-Geheimnis wirklich neu generieren? Dadurch werden das bisherige TOTP-Geheimnis und alle vorhandenen Wiederherstellungscodes ungültig.",
|
||||
"recovery_keys_title": "Einmalige Wiederherstellungsschlüssel",
|
||||
"recovery_keys_description": "Einmalige Wiederherstellungsschlüssel werden verwendet, um sich anzumelden, falls Sie keinen Zugriff auf Ihre Authentifizierungscodes haben.",
|
||||
@@ -2075,7 +1927,7 @@
|
||||
"show-hide-columns": "Zeige/verberge Spalten",
|
||||
"row-insert-above": "Zeile oberhalb einfügen",
|
||||
"row-insert-below": "Zeile unterhalb einfügen",
|
||||
"row-insert-child": "Unternotiz einfügen",
|
||||
"row-insert-child": "Untergeordnete Notiz einfügen",
|
||||
"add-column-to-the-left": "Spalte links einfügen",
|
||||
"add-column-to-the-right": "Spalte rechts einfügen",
|
||||
"edit-column": "Spalte editieren",
|
||||
@@ -2092,7 +1944,8 @@
|
||||
"raster": "Raster",
|
||||
"vector_light": "Vektor (Hell)",
|
||||
"vector_dark": "Vektor (Dunkel)",
|
||||
"show-scale": "Zeige Skalierung"
|
||||
"show-scale": "Zeige Skalierung",
|
||||
"show-labels": "Zeige Markierungsnamen"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "Zeile entfernen"
|
||||
@@ -2159,8 +2012,9 @@
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Seite {{startIndex}} von {{endIndex}}",
|
||||
"total_notes": "{{count}} Notizen"
|
||||
"total_notes": "{{count}} Notizen",
|
||||
"prev_page": "Vorherige Seite",
|
||||
"next_page": "Nächste Seite"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "Aufgrund eines Fehlers können keine Inhalte angezeigt werden."
|
||||
@@ -2206,7 +2060,7 @@
|
||||
"hoisted_badge_title": "Abgesenkt",
|
||||
"workspace_badge": "Arbeitsfläche",
|
||||
"scroll_to_top_title": "Zum Anfang der Notiz springen",
|
||||
"create_new_note": "Neue Unternotiz erstellen",
|
||||
"create_new_note": "Neue untergeordnete Notiz erstellen",
|
||||
"empty_hide_archived_notes": "Archivierte Notizen ausblenden"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
@@ -2283,5 +2137,49 @@
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Lesezeichen"
|
||||
},
|
||||
"web_view_setup": {
|
||||
"title": "Erstelle eine Live-Ansicht einer Webseite direkt in Trilium",
|
||||
"url_placeholder": "Gib oder füge die Adresse der Webseite ein, zum Beispiel https://triliumnotes.org",
|
||||
"create_button": "Erstelle Web Ansicht",
|
||||
"invalid_url_title": "Ungültige Adresse",
|
||||
"invalid_url_message": "Füge eine valide Webadresse ein, zum Beispiel https://triliumnotes.org.",
|
||||
"disabled_description": "Diese Webansicht wurde von einer externen Quelle importiert. Um Sie vor Phishing oder schädlichen Inhalten zu schützen, wird sie nicht automatisch geladen. Sie können sie aktivieren, wenn Sie der Quelle vertrauen.",
|
||||
"disabled_button_enable": "Webansicht aktivieren"
|
||||
},
|
||||
"render": {
|
||||
"setup_create_sample_html": "Eine Beispielnotiz mit HTML erstellen",
|
||||
"setup_create_sample_preact": "Eine Beispielnotiz mit Preact erstellen",
|
||||
"setup_title": "Benutzerdefiniertes HTML oder Preact JSX in dieser Notiz anzeigen",
|
||||
"setup_sample_created": "Eine Beispielnotiz wurde als untergeordnete Notiz erstellt.",
|
||||
"disabled_description": "Diese Rendering-Notizen stammen aus einer externen Quelle. Um Sie vor schädlichen Inhalten zu schützen, ist diese Funktion standardmäßig deaktiviert. Stellen Sie sicher, dass Sie der Quelle vertrauen, bevor Sie sie aktivieren.",
|
||||
"disabled_button_enable": "Rendering-Notiz aktivieren"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "Icon-Paket",
|
||||
"type_backend_script": "Backend-Skript",
|
||||
"type_frontend_script": "Frontend-Skript",
|
||||
"type_widget": "Widget",
|
||||
"type_app_css": "Benutzerdefiniertes CSS",
|
||||
"type_render_note": "Rendering-Notiz",
|
||||
"type_web_view": "Webansicht",
|
||||
"type_app_theme": "Benutzerdefiniertes Thema",
|
||||
"toggle_tooltip_enable_tooltip": "Klicken, um diesen {{type}} zu aktivieren.",
|
||||
"toggle_tooltip_disable_tooltip": "Klicken, um diesen {{type}} zu deaktivieren.",
|
||||
"menu_docs": "Dokumentation öffnen",
|
||||
"menu_execute_now": "Skript jetzt ausführen",
|
||||
"menu_run": "Automatisch ausführen",
|
||||
"menu_run_disabled": "Manuell",
|
||||
"menu_run_backend_startup": "Wenn das Backend startet",
|
||||
"menu_run_hourly": "Stündlich",
|
||||
"menu_run_daily": "Täglich",
|
||||
"menu_run_frontend_startup": "Wenn das Desktop-Frontend startet",
|
||||
"menu_run_mobile_startup": "Wenn das mobile Frontend startet",
|
||||
"menu_change_to_widget": "Zum Widget wechseln",
|
||||
"menu_change_to_frontend_script": "Zum Frontend-Skript wechseln",
|
||||
"menu_theme_base": "Themenbasis"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Mehr erfahren"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,61 @@
|
||||
"critical-error": {
|
||||
"title": "Κρίσιμο σφάλμα",
|
||||
"message": "Συνέβη κάποιο κρίσιμο σφάλμα, το οποίο δεν επιτρέπει στην εφαρμογή χρήστη να ξεκινήσει:\n\n{{message}}\n\nΤο πιθανότερο είναι να προκλήθηκε από κάποιο script που απέτυχε απρόοπτα. Δοκιμάστε να ξεκινήσετε την εφαρμογή σε ασφαλή λειτουργία για να λύσετε το πρόβλημα."
|
||||
}
|
||||
},
|
||||
"widget-error": {
|
||||
"title": "Δεν ήταν δυνατή η αρχικοποίηση του widget",
|
||||
"message-custom": "Προσαρμοσμένο widget της σημείωσης με ID \"{{id}}\", με τίτλο \"{{title}}\", δεν ήταν δυνατό να αρχικοποιηθεί λόγω:\n\n{{message}}",
|
||||
"message-unknown": "Άγνωστο widget δεν ήταν δυνατό να αρχικοποιηθεί λόγω:\n\n{{message}}"
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "Δεν ήταν δυνατή η φόρτωση προσαρμοσμένου script",
|
||||
"message": "Το script δεν ήταν δυνατό να εκτελεστεί λόγω:\n\n{{message}}"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "Δεν ήταν δυνατή η λήψη της λίστας των widgets από τον server"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "Δεν ήταν δυνατή η απόδοση προσαρμοσμένου React widget"
|
||||
},
|
||||
"widget-missing-parent": "Το προσαρμοσμένο widget δεν έχει ορισμένη την υποχρεωτική ιδιότητα '{{property}}'.\n\nΕάν το script προορίζεται για εκτέλεση χωρίς UI element, χρησιμοποιήστε '#run=frontendStartup' αντί για αυτό.",
|
||||
"open-script-note": "Άνοιγμα σημείωσης script",
|
||||
"scripting-error": "Σφάλμα προσαρμοσμένου script: {{title}}"
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Σελιδοδείκτες"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Προσθήκη συνδέσμου",
|
||||
"help_on_links": "Βοήθεια για συνδέσμους",
|
||||
"note": "Σημείωση",
|
||||
"search_note": "Αναζήτηση σημείωσης με βάση το όνομά της",
|
||||
"link_title_mirrors": "Ο τίτλος του συνδέσμου αντικατοπτρίζει τον τρέχοντα τίτλο της σημείωσης",
|
||||
"link_title_arbitrary": "Ο τίτλος του συνδέσμου μπορεί να τροποποιηθεί ελεύθερα",
|
||||
"link_title": "Τίτλος συνδέσμου",
|
||||
"button_add_link": "Προσθήκη συνδέσμου"
|
||||
},
|
||||
"branch_prefix": {
|
||||
"edit_branch_prefix": "Επεξεργασία προθέματος κλάδου",
|
||||
"edit_branch_prefix_multiple": "Επεξεργασία προθέματος κλάδου για {{count}} κλάδους",
|
||||
"help_on_tree_prefix": "Βοήθεια για πρόθεμα δέντρου",
|
||||
"prefix": "Πρόθεμα: ",
|
||||
"save": "Αποθήκευση",
|
||||
"branch_prefix_saved": "Το πρόθεμα κλάδου αποθηκεύτηκε.",
|
||||
"branch_prefix_saved_multiple": "Το πρόθεμα κλάδου αποθηκεύτηκε για {{count}} κλάδους.",
|
||||
"affected_branches": "Επηρεαζόμενοι κλάδοι ({{count}}):"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "Μαζικές ενέργειες",
|
||||
"affected_notes": "Επηρεαζόμενες σημειώσεις",
|
||||
"include_descendants": "Συμπερίληψη απογόνων των επιλεγμένων σημειώσεων",
|
||||
"available_actions": "Διαθέσιμες ενέργειες",
|
||||
"chosen_actions": "Επιλεγμένες ενέργειες",
|
||||
"execute_bulk_actions": "Εκτέλεση μαζικών ενεργειών",
|
||||
"bulk_actions_executed": "Οι μαζικές ενέργειες εκτελέστηκαν επιτυχώς.",
|
||||
"none_yet": "Καμία ακόμη… προσθέστε μια ενέργεια επιλέγοντας μία από τις διαθέσιμες παραπάνω.",
|
||||
"labels": "Ετικέτες",
|
||||
"relations": "Συσχετίσεις",
|
||||
"notes": "Σημειώσεις",
|
||||
"other": "Λοιπά"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,11 +47,6 @@
|
||||
"attachment_detail_2": {
|
||||
"unrecognized_role": "Unrecognised attachment role '{{role}}'."
|
||||
},
|
||||
"ai_llm": {
|
||||
"reprocess_index_started": "Search index optimisation started in the background",
|
||||
"index_rebuilding": "Optimising index ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Index optimisation complete"
|
||||
},
|
||||
"highlighting": {
|
||||
"color-scheme": "Colour Scheme"
|
||||
},
|
||||
|
||||
@@ -1010,7 +1010,7 @@
|
||||
"no_attachments": "This note has no attachments."
|
||||
},
|
||||
"book": {
|
||||
"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.",
|
||||
"no_children_help": "This collection doesn't have any child notes so there's nothing to display.",
|
||||
"drag_locked_title": "Locked for editing",
|
||||
"drag_locked_message": "Dragging not allowed since the collection is locked for editing."
|
||||
},
|
||||
@@ -1067,13 +1067,21 @@
|
||||
"click_on_canvas_to_place_new_note": "Click on canvas to place new note"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "This help note is shown because this note of type Render HTML doesn't have required relation to function properly.",
|
||||
"note_detail_render_help_2": "Render HTML note type is used for <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">scripting</a>. In short, you have a HTML code note (optionally with some JavaScript) and this note will render it. To make it work, you need to define a <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">relation</a> called \"renderNote\" pointing to the HTML note to render."
|
||||
"setup_title": "Display custom HTML or Preact JSX inside this note",
|
||||
"setup_create_sample_preact": "Create sample note with Preact",
|
||||
"setup_create_sample_html": "Create sample note with HTML",
|
||||
"setup_sample_created": "A sample note was created as a child note.",
|
||||
"disabled_description": "This render notes comes from an external source. To protect you from malicious content, it is not enabled by default. Make sure you trust the source before enabling it.",
|
||||
"disabled_button_enable": "Enable render note"
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Web View",
|
||||
"embed_websites": "Note of type Web View allows you to embed websites into Trilium.",
|
||||
"create_label": "To start, please create a label with a URL address you want to embed, e.g. #webViewSrc=\"https://www.google.com\""
|
||||
"web_view_setup": {
|
||||
"title": "Create a live view of a webpage directly into Trilium",
|
||||
"url_placeholder": "Enter or paste the website address, for example https://triliumnotes.org",
|
||||
"create_button": "Create Web View",
|
||||
"invalid_url_title": "Invalid address",
|
||||
"invalid_url_message": "Insert a valid web address, for example https://triliumnotes.org.",
|
||||
"disabled_description": "This web view was imported from an external source. To help protect you from phishing or malicious content, it isn’t loading automatically. You can enable it if you trust the source.",
|
||||
"disabled_button_enable": "Enable web view"
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Refresh"
|
||||
@@ -1196,149 +1204,6 @@
|
||||
"enable-smooth-scroll": "Enable smooth scrolling",
|
||||
"app-restart-required": "(a restart of the application is required for the change to take effect)"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Not started",
|
||||
"title": "AI Settings",
|
||||
"processed_notes": "Processed Notes",
|
||||
"total_notes": "Total Notes",
|
||||
"progress": "Progress",
|
||||
"queued_notes": "Queued Notes",
|
||||
"failed_notes": "Failed Notes",
|
||||
"last_processed": "Last Processed",
|
||||
"refresh_stats": "Refresh Statistics",
|
||||
"enable_ai_features": "Enable AI/LLM features",
|
||||
"enable_ai_description": "Enable AI features like note summarization, content generation, and other LLM capabilities",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Enable AI/LLM features",
|
||||
"enable_ai_desc": "Enable AI features like note summarization, content generation, and other LLM capabilities",
|
||||
"provider_configuration": "AI Provider Configuration",
|
||||
"provider_precedence": "Provider Precedence",
|
||||
"provider_precedence_description": "Comma-separated list of providers in order of precedence (e.g., 'openai,anthropic,ollama')",
|
||||
"temperature": "Temperature",
|
||||
"temperature_description": "Controls randomness in responses (0 = deterministic, 2 = maximum randomness)",
|
||||
"system_prompt": "System Prompt",
|
||||
"system_prompt_description": "Default system prompt used for all AI interactions",
|
||||
"openai_configuration": "OpenAI Configuration",
|
||||
"openai_settings": "OpenAI Settings",
|
||||
"api_key": "API Key",
|
||||
"url": "Base URL",
|
||||
"model": "Model",
|
||||
"openai_api_key_description": "Your OpenAI API key for accessing their AI services",
|
||||
"anthropic_api_key_description": "Your Anthropic API key for accessing Claude models",
|
||||
"default_model": "Default Model",
|
||||
"openai_model_description": "Examples: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "Base URL",
|
||||
"openai_url_description": "Default: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Anthropic Settings",
|
||||
"anthropic_url_description": "Base URL for the Anthropic API (default: https://api.anthropic.com)",
|
||||
"anthropic_model_description": "Anthropic Claude models for chat completion",
|
||||
"voyage_settings": "Voyage AI Settings",
|
||||
"ollama_settings": "Ollama Settings",
|
||||
"ollama_url_description": "URL for the Ollama API (default: http://localhost:11434)",
|
||||
"ollama_model_description": "Ollama model to use for chat completion",
|
||||
"anthropic_configuration": "Anthropic Configuration",
|
||||
"voyage_configuration": "Voyage AI Configuration",
|
||||
"voyage_url_description": "Default: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Ollama Configuration",
|
||||
"enable_ollama": "Enable Ollama",
|
||||
"enable_ollama_description": "Enable Ollama for local AI model usage",
|
||||
"ollama_url": "Ollama URL",
|
||||
"ollama_model": "Ollama Model",
|
||||
"refresh_models": "Refresh Models",
|
||||
"refreshing_models": "Refreshing...",
|
||||
"enable_automatic_indexing": "Enable Automatic Indexing",
|
||||
"rebuild_index": "Rebuild Index",
|
||||
"rebuild_index_error": "Error starting index rebuild. Check logs for details.",
|
||||
"note_title": "Note Title",
|
||||
"error": "Error",
|
||||
"last_attempt": "Last Attempt",
|
||||
"actions": "Actions",
|
||||
"retry": "Retry",
|
||||
"partial": "{{ percentage }}% completed",
|
||||
"retry_queued": "Note queued for retry",
|
||||
"retry_failed": "Failed to queue note for retry",
|
||||
"max_notes_per_llm_query": "Max Notes Per Query",
|
||||
"max_notes_per_llm_query_description": "Maximum number of similar notes to include in AI context",
|
||||
"active_providers": "Active Providers",
|
||||
"disabled_providers": "Disabled Providers",
|
||||
"remove_provider": "Remove provider from search",
|
||||
"restore_provider": "Restore provider to search",
|
||||
"similarity_threshold": "Similarity Threshold",
|
||||
"similarity_threshold_description": "Minimum similarity score (0-1) for notes to be included in context for LLM queries",
|
||||
"reprocess_index": "Rebuild Search Index",
|
||||
"reprocessing_index": "Rebuilding...",
|
||||
"reprocess_index_started": "Search index optimization started in the background",
|
||||
"reprocess_index_error": "Error rebuilding search index",
|
||||
"index_rebuild_progress": "Index Rebuild Progress",
|
||||
"index_rebuilding": "Optimizing index ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Index optimization complete",
|
||||
"index_rebuild_status_error": "Error checking index rebuild status",
|
||||
"never": "Never",
|
||||
"processing": "Processing ({{percentage}}%)",
|
||||
"incomplete": "Incomplete ({{percentage}}%)",
|
||||
"complete": "Complete (100%)",
|
||||
"refreshing": "Refreshing...",
|
||||
"auto_refresh_notice": "Auto-refreshes every {{seconds}} seconds",
|
||||
"note_queued_for_retry": "Note queued for retry",
|
||||
"failed_to_retry_note": "Failed to retry note",
|
||||
"all_notes_queued_for_retry": "All failed notes queued for retry",
|
||||
"failed_to_retry_all": "Failed to retry notes",
|
||||
"ai_settings": "AI Settings",
|
||||
"api_key_tooltip": "API key for accessing the service",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "Anthropic API key is empty. Please enter a valid API key.",
|
||||
"openai": "OpenAI API key is empty. Please enter a valid API key.",
|
||||
"voyage": "Voyage API key is empty. Please enter a valid API key.",
|
||||
"ollama": "Ollama API key is empty. Please enter a valid API key."
|
||||
},
|
||||
"agent": {
|
||||
"processing": "Processing...",
|
||||
"thinking": "Thinking...",
|
||||
"loading": "Loading...",
|
||||
"generating": "Generating..."
|
||||
},
|
||||
"name": "AI",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Use enhanced context",
|
||||
"enhanced_context_description": "Provides the AI with more context from the note and its related notes for better responses",
|
||||
"show_thinking": "Show thinking",
|
||||
"show_thinking_description": "Show the AI's chain of thought process",
|
||||
"enter_message": "Enter your message...",
|
||||
"error_contacting_provider": "Error contacting AI provider. Please check your settings and internet connection.",
|
||||
"error_generating_response": "Error generating AI response",
|
||||
"index_all_notes": "Index All Notes",
|
||||
"index_status": "Index Status",
|
||||
"indexed_notes": "Indexed Notes",
|
||||
"indexing_stopped": "Indexing stopped",
|
||||
"indexing_in_progress": "Indexing in progress...",
|
||||
"last_indexed": "Last Indexed",
|
||||
"note_chat": "Note Chat",
|
||||
"sources": "Sources",
|
||||
"start_indexing": "Start Indexing",
|
||||
"use_advanced_context": "Use Advanced Context",
|
||||
"ollama_no_url": "Ollama is not configured. Please enter a valid URL.",
|
||||
"chat": {
|
||||
"root_note_title": "AI Chats",
|
||||
"root_note_content": "This note contains your saved AI chat conversations.",
|
||||
"new_chat_title": "New Chat",
|
||||
"create_new_ai_chat": "Create new AI Chat"
|
||||
},
|
||||
"create_new_ai_chat": "Create new AI Chat",
|
||||
"configuration_warnings": "There are some issues with your AI configuration. Please check your settings.",
|
||||
"experimental_warning": "The LLM feature is currently experimental - you have been warned.",
|
||||
"selected_provider": "Selected Provider",
|
||||
"selected_provider_description": "Choose the AI provider for chat and completion features",
|
||||
"select_model": "Select model...",
|
||||
"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)",
|
||||
"description": "Zooming can be controlled with CTRL+- and CTRL+= shortcuts as well."
|
||||
@@ -1589,7 +1454,8 @@
|
||||
"description": "Description",
|
||||
"reload_app": "Reload app to apply changes",
|
||||
"set_all_to_default": "Set all shortcuts to the default",
|
||||
"confirm_reset": "Do you really want to reset all keyboard shortcuts to the default?"
|
||||
"confirm_reset": "Do you really want to reset all keyboard shortcuts to the default?",
|
||||
"no_results": "No shortcuts found matching '{{filter}}'"
|
||||
},
|
||||
"spellcheck": {
|
||||
"title": "Spell Check",
|
||||
@@ -1795,6 +1661,8 @@
|
||||
"printing": "Printing in progress...",
|
||||
"printing_pdf": "Exporting to PDF in progress...",
|
||||
"print_report_title": "Print report",
|
||||
"print_report_error_title": "Failed to print",
|
||||
"print_report_stack_trace": "Stack trace",
|
||||
"print_report_collection_content_one": "{{count}} note in the collection could not be printed because they are not supported or they are protected.",
|
||||
"print_report_collection_content_other": "{{count}} notes in the collection could not be printed because they are not supported or they are protected.",
|
||||
"print_report_collection_details_button": "See details",
|
||||
@@ -1813,7 +1681,8 @@
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "No notes have been found for given search parameters.",
|
||||
"search_not_executed": "Search has not been executed yet. Click on \"Search\" button above to see the results."
|
||||
"search_not_executed": "Search has not been executed yet.",
|
||||
"search_now": "Search now"
|
||||
},
|
||||
"spacer": {
|
||||
"configure_launchbar": "Configure Launchbar"
|
||||
@@ -2099,7 +1968,8 @@
|
||||
"raster": "Raster",
|
||||
"vector_light": "Vector (Light)",
|
||||
"vector_dark": "Vector (Dark)",
|
||||
"show-scale": "Show scale"
|
||||
"show-scale": "Show scale",
|
||||
"show-labels": "Show marker names"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "Delete row"
|
||||
@@ -2178,8 +2048,9 @@
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Page of {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} notes"
|
||||
"total_notes": "{{count}} notes",
|
||||
"prev_page": "Previous page",
|
||||
"next_page": "Next page"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "Unable to show content due to an error."
|
||||
@@ -2283,5 +2154,32 @@
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Bookmarks"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "Icon pack",
|
||||
"type_backend_script": "Backend script",
|
||||
"type_frontend_script": "Frontend script",
|
||||
"type_widget": "Widget",
|
||||
"type_app_css": "Custom CSS",
|
||||
"type_render_note": "Render note",
|
||||
"type_web_view": "Web view",
|
||||
"type_app_theme": "Custom theme",
|
||||
"toggle_tooltip_enable_tooltip": "Click to enable this {{type}}.",
|
||||
"toggle_tooltip_disable_tooltip": "Click to disable this {{type}}.",
|
||||
"menu_docs": "Open documentation",
|
||||
"menu_execute_now": "Execute script now",
|
||||
"menu_run": "Run automatically",
|
||||
"menu_run_disabled": "Manually",
|
||||
"menu_run_backend_startup": "When the backend starts up",
|
||||
"menu_run_hourly": "Hourly",
|
||||
"menu_run_daily": "Daily",
|
||||
"menu_run_frontend_startup": "When the desktop frontend starts up",
|
||||
"menu_run_mobile_startup": "When the mobile frontend starts up",
|
||||
"menu_change_to_widget": "Change to widget",
|
||||
"menu_change_to_frontend_script": "Change to frontend script",
|
||||
"menu_theme_base": "Theme base"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Learn more"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -669,7 +669,7 @@
|
||||
"button_exit": "Salir del modo Zen"
|
||||
},
|
||||
"sync_status": {
|
||||
"unknown": "<p>El estado de sincronización será conocido una vez que el siguiente intento de sincronización comience.</p><p>Dé clic para activar la sincronización ahora</p>",
|
||||
"unknown": "<p>El estado de sincronización será conocido una vez que el siguiente intento de sincronización comience.</p><p>Dé clic para activar la sincronización ahora.</p>",
|
||||
"connected_with_changes": "<p>Conectado al servidor de sincronización. <br>Hay cambios pendientes que aún no se han sincronizado.</p><p>Dé clic para activar la sincronización.</p>",
|
||||
"connected_no_changes": "<p>Conectado al servidor de sincronización.<br>Todos los cambios ya han sido sincronizados.</p><p>Dé clic para activar la sincronización.</p>",
|
||||
"disconnected_with_changes": "<p>El establecimiento de la conexión con el servidor de sincronización no ha tenido éxito.<br>Hay algunos cambios pendientes que aún no se han sincronizado.</p><p>Dé clic para activar la sincronización.</p>",
|
||||
@@ -760,7 +760,7 @@
|
||||
"mobile_detail_menu": {
|
||||
"insert_child_note": "Insertar subnota",
|
||||
"delete_this_note": "Eliminar esta nota",
|
||||
"error_cannot_get_branch_id": "No se puede obtener el branchID del notePath '{{notePath}}'",
|
||||
"error_cannot_get_branch_id": "No se puede obtener el branchId del notePath '{{notePath}}'",
|
||||
"error_unrecognized_command": "Comando no reconocido {{command}}",
|
||||
"note_revisions": "Revisiones de notas",
|
||||
"backlinks": "Vínculos de retroceso",
|
||||
@@ -1012,7 +1012,7 @@
|
||||
"no_attachments": "Esta nota no tiene archivos adjuntos."
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "Esta nota de tipo libro no tiene ninguna subnota así que no hay nada que mostrar. Véa la <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> para más detalles.",
|
||||
"no_children_help": "Esta colección no tiene ninguna subnota así que no hay nada que mostrar.",
|
||||
"drag_locked_title": "Bloqueado para edición",
|
||||
"drag_locked_message": "No se permite Arrastrar pues la colección está bloqueada para edición."
|
||||
},
|
||||
@@ -1068,15 +1068,6 @@
|
||||
"default_new_note_title": "nueva nota",
|
||||
"click_on_canvas_to_place_new_note": "Haga clic en el lienzo para colocar una nueva nota"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Esta nota de ayuda se muestra porque esta nota de tipo Renderizar HTML no tiene la relación requerida para funcionar correctamente.",
|
||||
"note_detail_render_help_2": "El tipo de nota Render HTML es usado para <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">scripting</a>. De forma resumida, tiene una nota con código HTML (opcionalmente con algo de JavaScript) y esta nota la renderizará. Para que funcione, es necesario definir una <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">relación</a> llamada \"renderNote\" apuntando a la nota HTML nota a renderizar."
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Vista web",
|
||||
"embed_websites": "La nota de tipo Web View le permite insertar sitios web en Trilium.",
|
||||
"create_label": "Para comenzar, por favor cree una etiqueta con una dirección URL que desee empotrar, e.g. #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Refrescar"
|
||||
},
|
||||
@@ -1184,149 +1175,6 @@
|
||||
"light_theme": "Heredado (Claro)",
|
||||
"dark_theme": "Heredado (Oscuro)"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "No iniciado",
|
||||
"title": "IA y ajustes de embeddings",
|
||||
"processed_notes": "Notas procesadas",
|
||||
"total_notes": "Notas totales",
|
||||
"progress": "Progreso",
|
||||
"queued_notes": "Notas en fila",
|
||||
"failed_notes": "Notas fallidas",
|
||||
"last_processed": "Última procesada",
|
||||
"refresh_stats": "Recargar estadísticas",
|
||||
"enable_ai_features": "Habilitar características IA/LLM",
|
||||
"enable_ai_description": "Habilitar características de IA como resumen de notas, generación de contenido y otras capacidades LLM",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Habilitar características IA/LLM",
|
||||
"enable_ai_desc": "Habilitar características de IA como resumen de notas, generación de contenido y otras capacidades LLM",
|
||||
"provider_configuration": "Configuración de proveedor de IA",
|
||||
"provider_precedence": "Precedencia de proveedor",
|
||||
"provider_precedence_description": "Lista de proveedores en orden de precedencia separada por comas (p.e., 'openai,anthropic,ollama')",
|
||||
"temperature": "Temperatura",
|
||||
"temperature_description": "Controla la aleatoriedad de las respuestas (0 = determinista, 2 = aleatoriedad máxima)",
|
||||
"system_prompt": "Mensaje de sistema",
|
||||
"system_prompt_description": "Mensaje de sistema predeterminado utilizado para todas las interacciones de IA",
|
||||
"openai_configuration": "Configuración de OpenAI",
|
||||
"openai_settings": "Ajustes de OpenAI",
|
||||
"api_key": "Clave API",
|
||||
"url": "URL base",
|
||||
"model": "Modelo",
|
||||
"openai_api_key_description": "Tu clave API de OpenAI para acceder a sus servicios de IA",
|
||||
"anthropic_api_key_description": "Tu clave API de Anthropic para acceder a los modelos Claude",
|
||||
"default_model": "Modelo por defecto",
|
||||
"openai_model_description": "Ejemplos: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "URL base",
|
||||
"openai_url_description": "Por defecto: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Ajustes de Anthropic",
|
||||
"anthropic_url_description": "URL base para la API de Anthropic (por defecto: https://api.anthropic.com)",
|
||||
"anthropic_model_description": "Modelos Claude de Anthropic para el completado de chat",
|
||||
"voyage_settings": "Ajustes de Voyage AI",
|
||||
"ollama_settings": "Ajustes de Ollama",
|
||||
"ollama_url_description": "URL para la API de Ollama (por defecto: http://localhost:11434)",
|
||||
"ollama_model_description": "Modelo de Ollama a usar para el completado de chat",
|
||||
"anthropic_configuration": "Configuración de Anthropic",
|
||||
"voyage_configuration": "Configuración de Voyage AI",
|
||||
"voyage_url_description": "Por defecto: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Configuración de Ollama",
|
||||
"enable_ollama": "Habilitar Ollama",
|
||||
"enable_ollama_description": "Habilitar Ollama para uso de modelo de IA local",
|
||||
"ollama_url": "URL de Ollama",
|
||||
"ollama_model": "Modelo de Ollama",
|
||||
"refresh_models": "Refrescar modelos",
|
||||
"refreshing_models": "Refrescando...",
|
||||
"enable_automatic_indexing": "Habilitar indexado automático",
|
||||
"rebuild_index": "Recrear índice",
|
||||
"rebuild_index_error": "Error al comenzar la reconstrucción del índice. Consulte los registros para más detalles.",
|
||||
"note_title": "Título de nota",
|
||||
"error": "Error",
|
||||
"last_attempt": "Último intento",
|
||||
"actions": "Acciones",
|
||||
"retry": "Reintentar",
|
||||
"partial": "{{ percentage }}% completado",
|
||||
"retry_queued": "Nota en la cola para reintento",
|
||||
"retry_failed": "Hubo un fallo al poner en la cola a la nota para reintento",
|
||||
"max_notes_per_llm_query": "Máximo de notas por consulta",
|
||||
"max_notes_per_llm_query_description": "Número máximo de notas similares a incluir en el contexto IA",
|
||||
"active_providers": "Proveedores activos",
|
||||
"disabled_providers": "Proveedores deshabilitados",
|
||||
"remove_provider": "Eliminar proveedor de la búsqueda",
|
||||
"restore_provider": "Restaurar proveedor a la búsqueda",
|
||||
"similarity_threshold": "Bias de similaridad",
|
||||
"similarity_threshold_description": "Puntuación de similaridad mínima (0-1) para incluir notas en el contexto para consultas LLM",
|
||||
"reprocess_index": "Reconstruir el índice de búsqueda",
|
||||
"reprocessing_index": "Reconstruyendo...",
|
||||
"reprocess_index_started": "La optimización de índice de búsqueda comenzó en segundo plano",
|
||||
"reprocess_index_error": "Error al reconstruir el índice de búsqueda",
|
||||
"index_rebuild_progress": "Progreso de reconstrucción de índice",
|
||||
"index_rebuilding": "Optimizando índice ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Optimización de índice completa",
|
||||
"index_rebuild_status_error": "Error al comprobar el estado de reconstrucción del índice",
|
||||
"never": "Nunca",
|
||||
"processing": "Procesando ({{percentage}}%)",
|
||||
"incomplete": "Incompleto ({{percentage}}%)",
|
||||
"complete": "Completo (100%)",
|
||||
"refreshing": "Refrescando...",
|
||||
"auto_refresh_notice": "Refrescar automáticamente cada {{seconds}} segundos",
|
||||
"note_queued_for_retry": "Nota en la cola para reintento",
|
||||
"failed_to_retry_note": "Hubo un fallo al reintentar nota",
|
||||
"all_notes_queued_for_retry": "Todas las notas con fallo agregadas a la cola para reintento",
|
||||
"failed_to_retry_all": "Hubo un fallo al reintentar notas",
|
||||
"ai_settings": "Ajustes de IA",
|
||||
"api_key_tooltip": "Clave API para acceder al servicio",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "La clave API de Anthropic está vacía. Por favor, ingrese una clave API válida.",
|
||||
"openai": "La clave API de OpenAI está vacía. Por favor, ingrese una clave API válida.",
|
||||
"voyage": "La clave API de Voyage está vacía. Por favor, ingrese una clave API válida.",
|
||||
"ollama": "La clave API de Ollama está vacía. Por favor, ingrese una clave API válida."
|
||||
},
|
||||
"agent": {
|
||||
"processing": "Procesando...",
|
||||
"thinking": "Pensando...",
|
||||
"loading": "Cargando...",
|
||||
"generating": "Generando..."
|
||||
},
|
||||
"name": "IA",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Utilizar contexto mejorado",
|
||||
"enhanced_context_description": "Provee a la IA con más contexto de la nota y sus notas relacionadas para obtener mejores respuestas",
|
||||
"show_thinking": "Mostrar pensamiento",
|
||||
"show_thinking_description": "Mostrar la cadena del proceso de pensamiento de la IA",
|
||||
"enter_message": "Ingrese su mensaje...",
|
||||
"error_contacting_provider": "Error al contactar con su proveedor de IA. Por favor compruebe sus ajustes y conexión a internet.",
|
||||
"error_generating_response": "Error al generar respuesta de IA",
|
||||
"index_all_notes": "Indexar todas las notas",
|
||||
"index_status": "Estado de índice",
|
||||
"indexed_notes": "Notas indexadas",
|
||||
"indexing_stopped": "Indexado detenido",
|
||||
"indexing_in_progress": "Indexado en progreso...",
|
||||
"last_indexed": "Último indexado",
|
||||
"note_chat": "Chat de nota",
|
||||
"sources": "Fuentes",
|
||||
"start_indexing": "Comenzar indexado",
|
||||
"use_advanced_context": "Usar contexto avanzado",
|
||||
"ollama_no_url": "Ollama no está configurado. Por favor ingrese una URL válida.",
|
||||
"chat": {
|
||||
"root_note_title": "Chats de IA",
|
||||
"root_note_content": "Esta nota contiene tus conversaciones de chat de IA guardadas.",
|
||||
"new_chat_title": "Nuevo chat",
|
||||
"create_new_ai_chat": "Crear nuevo chat de IA"
|
||||
},
|
||||
"create_new_ai_chat": "Crear nuevo chat de IA",
|
||||
"configuration_warnings": "Hay algunos problemas con su configuración de IA. Por favor compruebe sus ajustes.",
|
||||
"experimental_warning": "La característica de LLM aún es experimental - ha sido advertido.",
|
||||
"selected_provider": "Proveedor seleccionado",
|
||||
"selected_provider_description": "Elija el proveedor de IA para el chat y características de completado",
|
||||
"select_model": "Seleccionar modelo...",
|
||||
"select_provider": "Seleccionar proveedor...",
|
||||
"ai_enabled": "Características de IA activadas",
|
||||
"ai_disabled": "Características de IA desactivadas",
|
||||
"no_models_found_online": "No se encontraron modelos. Por favor, comprueba tu clave de API y la configuración.",
|
||||
"no_models_found_ollama": "No se encontraron modelos de Ollama. Por favor, comprueba si Ollama se está ejecutando.",
|
||||
"error_fetching": "Error al obtener los modelos: {{error}}"
|
||||
},
|
||||
"zoom_factor": {
|
||||
"title": "Factor de zoom (solo versión de escritorio)",
|
||||
"description": "El zoom también se puede controlar con los atajos CTRL+- y CTRL+=."
|
||||
@@ -1569,7 +1417,7 @@
|
||||
"shortcuts": {
|
||||
"keyboard_shortcuts": "Atajos de teclado",
|
||||
"multiple_shortcuts": "Varios atajos para la misma acción se pueden separar mediante comas.",
|
||||
"electron_documentation": "Véa la <a href=\"https://www.electronjs.org/docs/latest/api/accelerator\">documentación de Electron </a> para los modificadores y códigos de tecla disponibles.",
|
||||
"electron_documentation": "Consulte la <a href=\"https://www.electronjs.org/docs/latest/api/accelerator\">documentación de Electron</a> para los modificadores y códigos de tecla disponibles.",
|
||||
"type_text_to_filter": "Escriba texto para filtrar los accesos directos...",
|
||||
"action_name": "Nombre de la acción",
|
||||
"shortcuts": "Atajos",
|
||||
@@ -1577,7 +1425,8 @@
|
||||
"description": "Descripción",
|
||||
"reload_app": "Vuelva a cargar la aplicación para aplicar los cambios",
|
||||
"set_all_to_default": "Establecer todos los accesos directos al valor predeterminado",
|
||||
"confirm_reset": "¿Realmente desea restablecer todos los atajos de teclado a sus valores predeterminados?"
|
||||
"confirm_reset": "¿Realmente desea restablecer todos los atajos de teclado a sus valores predeterminados?",
|
||||
"no_results": "No se encontraron atajos que coincidan con '{{filter}} '"
|
||||
},
|
||||
"spellcheck": {
|
||||
"title": "Revisión ortográfica",
|
||||
@@ -1784,7 +1633,9 @@
|
||||
"print_report_collection_content_other": "{{count}} notas en la colección no se pueden imprimir porque no son compatibles o están protegidas.",
|
||||
"print_report_title": "Imprimir informe",
|
||||
"print_report_collection_details_button": "Ver detalles",
|
||||
"print_report_collection_details_ignored_notes": "Notas ignoradas"
|
||||
"print_report_collection_details_ignored_notes": "Notas ignoradas",
|
||||
"print_report_stack_trace": "Rastreo de pila",
|
||||
"print_report_error_title": "Fallo al imprimir"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "escriba el título de la nota aquí...",
|
||||
@@ -1832,7 +1683,7 @@
|
||||
"no_headings": "Sin encabezados."
|
||||
},
|
||||
"watched_file_update_status": {
|
||||
"file_last_modified": "Archivo <code class=\"file-path\"></code> ha sido modificado por última vez en<span class=\"file-last-modified\"></span>.",
|
||||
"file_last_modified": "El archivo <code class=\"file-path\"></code> ha sido modificado por última vez en <span class=\"file-last-modified\"></span>.",
|
||||
"upload_modified_file": "Subir archivo modificado",
|
||||
"ignore_this_change": "Ignorar este cambio"
|
||||
},
|
||||
@@ -2056,7 +1907,8 @@
|
||||
"max-nesting-depth": "Máxima profundidad de anidamiento:",
|
||||
"vector_light": "Vector (claro)",
|
||||
"vector_dark": "Vector (oscuro)",
|
||||
"raster": "Trama"
|
||||
"raster": "Trama",
|
||||
"show-labels": "Mostrar nombres de marcadores"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "Eliminar fila"
|
||||
@@ -2165,7 +2017,8 @@
|
||||
},
|
||||
"pagination": {
|
||||
"total_notes": "{{count}} notas",
|
||||
"page_title": "Página de {{startIndex}} - {{endIndex}}"
|
||||
"prev_page": "Página anterior",
|
||||
"next_page": "Página siguiente"
|
||||
},
|
||||
"presentation_view": {
|
||||
"edit-slide": "Editar este slide",
|
||||
@@ -2298,5 +2151,49 @@
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Marcadores"
|
||||
},
|
||||
"web_view_setup": {
|
||||
"title": "Crear una vista en vivo de una página web directamente en Trilium",
|
||||
"url_placeholder": "Ingresar o pegar la dirección del sitio web, por ejemplo https://triliumnotes.org",
|
||||
"create_button": "Crear Vista Web",
|
||||
"invalid_url_title": "Dirección inválida",
|
||||
"invalid_url_message": "Ingrese una dirección web válida, por ejemplo https://triliumnotes.org.",
|
||||
"disabled_description": "Esta vista web fue importada de una fuente externa. Para ayudarlo a protegerse del phishing o el contenido malicioso, no se está cargando automáticamente. Puede activarlo si confía en la fuente.",
|
||||
"disabled_button_enable": "Habilita vista web"
|
||||
},
|
||||
"render": {
|
||||
"setup_title": "Mostrar HTML personalizado o Preact JSX dentro de esta nota",
|
||||
"setup_create_sample_preact": "Crear nota de muestra con Preact",
|
||||
"setup_create_sample_html": "Crear nota de muestra con HTML",
|
||||
"setup_sample_created": "Se creó una nota de muestra como subnota.",
|
||||
"disabled_description": "Esta nota de renderización proviene de una fuente externa. Para protegerlo de contenido malicioso, no está habilitado por defecto. Asegúrese de confiar en la fuente antes de habilitarla.",
|
||||
"disabled_button_enable": "Habilitar nota de renderización"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "Paquete de iconos",
|
||||
"type_backend_script": "Script de backend",
|
||||
"type_frontend_script": "Script de frontend",
|
||||
"type_widget": "Widget",
|
||||
"type_app_css": "CSS personalizado",
|
||||
"type_render_note": "Nota de renderización",
|
||||
"type_web_view": "Vista web",
|
||||
"type_app_theme": "Tema personalizado",
|
||||
"toggle_tooltip_enable_tooltip": "Haga clic para habilitar este {{type}}.",
|
||||
"toggle_tooltip_disable_tooltip": "Haga clic para deshabilitar este {{type}}.",
|
||||
"menu_docs": "Abrir documentación",
|
||||
"menu_execute_now": "Ejecutar script ahora",
|
||||
"menu_run": "Ejecutar automáticamente",
|
||||
"menu_run_disabled": "Manualmente",
|
||||
"menu_run_backend_startup": "Cuando el backend inicia",
|
||||
"menu_run_hourly": "Cada hora",
|
||||
"menu_run_daily": "Diariamente",
|
||||
"menu_run_frontend_startup": "Cuando el frontend de escritorio inicia",
|
||||
"menu_run_mobile_startup": "Cuando el frontend móvil inicia",
|
||||
"menu_change_to_widget": "Cambiar a widget",
|
||||
"menu_change_to_frontend_script": "Cambiar a script de frontend",
|
||||
"menu_theme_base": "Tema base"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Para saber más"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1053,15 +1053,6 @@
|
||||
"default_new_note_title": "nouvelle note",
|
||||
"click_on_canvas_to_place_new_note": "Cliquez sur le canevas pour placer une nouvelle note"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Cette note d'aide s'affiche car cette note de type Rendu HTML n'a pas la relation requise pour fonctionner correctement.",
|
||||
"note_detail_render_help_2": "Le type de note Rendu HTML est utilisé pour les <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">scripts</a>. En résumé, vous disposez d'une note de code HTML (éventuellement contenant JavaScript) et cette note affichera le rendu. Pour que cela fonctionne, vous devez définir une <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">relation</a> appelée \"renderNote\" pointant vers la note HTML à rendre."
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Affichage Web",
|
||||
"embed_websites": "Les notes de type Affichage Web vous permet d'intégrer des sites Web dans Trilium.",
|
||||
"create_label": "Pour commencer, veuillez créer un label avec l'adresse URL que vous souhaitez intégrer, par ex. #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Rafraîchir"
|
||||
},
|
||||
@@ -1494,7 +1485,6 @@
|
||||
"beta-feature": "Beta",
|
||||
"task-list": "Liste de tâches",
|
||||
"book": "Collection",
|
||||
"ai-chat": "Chat IA",
|
||||
"new-feature": "Nouveau",
|
||||
"collections": "Collections"
|
||||
},
|
||||
@@ -1807,149 +1797,6 @@
|
||||
"close": "Fermer",
|
||||
"help_title": "Afficher plus d'informations sur cet écran"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Non démarré",
|
||||
"title": "Paramètres IA",
|
||||
"processed_notes": "Notes traitées",
|
||||
"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",
|
||||
"total_notes": "Notes totales",
|
||||
"progress": "Progrès",
|
||||
"queued_notes": "Notes dans la file d'attente",
|
||||
"refresh_stats": "Rafraîchir les statistiques",
|
||||
"enable_ai_features": "Activer les fonctionnalités IA/LLM",
|
||||
"enable_ai_description": "Activer les fonctionnalités IA telles que le résumé des notes, la génération de contenu et autres fonctionnalités LLM",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Activer les fonctionnalités IA/LLM",
|
||||
"enable_ai_desc": "Activer les fonctionnalités IA telles que le résumé des notes, la génération de contenu et autres fonctionnalités LLM",
|
||||
"provider_configuration": "Configuration du fournisseur IA",
|
||||
"provider_precedence_description": "Liste de fournisseurs séparés par virgule, par ordre de préférence (ex. 'openai,anthopic,ollama')",
|
||||
"temperature": "Température",
|
||||
"temperature_description": "Contrôle de l'aléatoirité dans les réponses (0 = déterministe, 2 = hasard maximum)",
|
||||
"system_prompt": "Prompt système",
|
||||
"system_prompt_description": "Prompt système par défaut pour toutes les intéractions IA",
|
||||
"openai_configuration": "Configuration OpenAI",
|
||||
"openai_settings": "Options OpenAI",
|
||||
"api_key": "Clef API",
|
||||
"url": "URL de base",
|
||||
"model": "Modèle",
|
||||
"openai_api_key_description": "Votre clef API OpenAI pour accéder à leurs services IA",
|
||||
"anthropic_api_key_description": "Votre clef API Anthropic pour accéder aux modèles Claude",
|
||||
"default_model": "Modèle par défaut",
|
||||
"openai_model_description": "Exemples : gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "URL de base",
|
||||
"openai_url_description": "Défaut : https://api.openai.com/v1",
|
||||
"anthropic_settings": "Réglages Anthropic",
|
||||
"enable_ollama": "Activer Ollama",
|
||||
"enable_ollama_description": "Activer Ollama comme modèle d'IA local",
|
||||
"ollama_url": "URL Ollama",
|
||||
"ollama_model": "Modèle Ollama",
|
||||
"refresh_models": "Rafraîchir les modèles",
|
||||
"refreshing_models": "Mise à jour...",
|
||||
"enable_automatic_indexing": "Activer l'indexage automatique",
|
||||
"rebuild_index": "Rafraîchir l'index",
|
||||
"rebuild_index_error": "Erreur dans le démarrage du rafraichissement de l'index. Veuillez consulter les logs pour plus de détails.",
|
||||
"note_title": "Titre de la note",
|
||||
"error": "Erreur",
|
||||
"last_attempt": "Dernier essai",
|
||||
"actions": "Actions",
|
||||
"retry": "Réessayer",
|
||||
"partial": "Complété à {{ percentage }}%",
|
||||
"retry_queued": "Note ajoutée à la file d'attente",
|
||||
"retry_failed": "Echec de l'ajout de la note à la file d'attente",
|
||||
"max_notes_per_llm_query": "Notes maximum par requête",
|
||||
"max_notes_per_llm_query_description": "Nombre maximum de notes similaires à inclure dans le contexte IA",
|
||||
"active_providers": "Fournisseurs actifs",
|
||||
"disabled_providers": "Fournisseurs désactivés",
|
||||
"remove_provider": "Retirer le fournisseur de la recherche",
|
||||
"similarity_threshold": "Seuil de similarité",
|
||||
"similarity_threshold_description": "Seuil de similarité minimum (0-1) pour que inclure les notes dans le contexte d'une requête IA",
|
||||
"reprocess_index": "Rafraîchir l'index de recherche",
|
||||
"reprocessing_index": "Mise à jour...",
|
||||
"reprocess_index_started": "L'optimisation de l'indice de recherche à commencer en arrière-plan",
|
||||
"reprocess_index_error": "Erreur dans le rafraichissement de l'indice de recherche",
|
||||
"failed_notes": "Notes en erreur",
|
||||
"last_processed": "Dernier traitement",
|
||||
"restore_provider": "Restaurer le fournisseur de recherche",
|
||||
"index_rebuild_progress": "Progression de la reconstruction de l'index",
|
||||
"index_rebuilding": "Optimisation de l'index ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Optimisation de l'index terminée",
|
||||
"index_rebuild_status_error": "Erreur lors de la vérification de l'état de reconstruction de l'index",
|
||||
"provider_precedence": "Priorité du fournisseur",
|
||||
"never": "Jamais",
|
||||
"processing": "Traitement en cours ({{percentage}}%)",
|
||||
"incomplete": "Incomplet ({{percentage}}%)",
|
||||
"complete": "Terminé (100%)",
|
||||
"refreshing": "Mise à jour...",
|
||||
"auto_refresh_notice": "Actualisation automatique toutes les {{seconds}} secondes",
|
||||
"note_queued_for_retry": "Note mise en file d'attente pour une nouvelle tentative",
|
||||
"failed_to_retry_note": "Échec de la nouvelle tentative de note",
|
||||
"all_notes_queued_for_retry": "Toutes les notes ayant échoué sont mises en file d'attente pour une nouvelle tentative",
|
||||
"failed_to_retry_all": "Échec du ré essai des notes",
|
||||
"ai_settings": "Paramètres IA",
|
||||
"api_key_tooltip": "Clé API pour accéder au service",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "La clé API Anthropic est vide. Veuillez saisir une clé API valide.",
|
||||
"openai": "La clé API OpenAI est vide. Veuillez saisir une clé API valide.",
|
||||
"voyage": "La clé API Voyage est vide. Veuillez saisir une clé API valide.",
|
||||
"ollama": "La clé API Ollama est vide. Veuillez saisir une clé API valide."
|
||||
},
|
||||
"agent": {
|
||||
"processing": "Traitement...",
|
||||
"thinking": "Réflexion...",
|
||||
"loading": "Chargement...",
|
||||
"generating": "Génération..."
|
||||
},
|
||||
"name": "IA",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Utiliser un contexte amélioré",
|
||||
"enhanced_context_description": "Fournit à l'IA plus de contexte à partir de la note et de ses notes associées pour de meilleures réponses",
|
||||
"show_thinking": "Montrer la réflexion",
|
||||
"show_thinking_description": "Montrer la chaîne de pensée de l'IA",
|
||||
"enter_message": "Entrez votre message...",
|
||||
"error_contacting_provider": "Erreur lors de la connexion au fournisseur d'IA. Veuillez vérifier vos paramètres et votre connexion Internet.",
|
||||
"error_generating_response": "Erreur lors de la génération de la réponse de l'IA",
|
||||
"index_all_notes": "Indexer toutes les notes",
|
||||
"index_status": "Statut de l'index",
|
||||
"indexed_notes": "Notes indexées",
|
||||
"indexing_stopped": "Arrêt de l'indexation",
|
||||
"indexing_in_progress": "Indexation en cours...",
|
||||
"last_indexed": "Dernière indexée",
|
||||
"note_chat": "Note discussion",
|
||||
"sources": "Sources",
|
||||
"start_indexing": "Démarrage de l'indexation",
|
||||
"use_advanced_context": "Utiliser le contexte avancé",
|
||||
"ollama_no_url": "Ollama n'est pas configuré. Veuillez saisir une URL valide.",
|
||||
"chat": {
|
||||
"root_note_title": "Discussions IA",
|
||||
"root_note_content": "Cette note contient vos conversations de chat IA enregistrées.",
|
||||
"new_chat_title": "Nouvelle discussion",
|
||||
"create_new_ai_chat": "Créer une nouvelle discussion IA"
|
||||
},
|
||||
"create_new_ai_chat": "Créer une nouvelle discussion IA",
|
||||
"configuration_warnings": "Il y a quelques problèmes avec la configuration de votre IA. Veuillez vérifier vos paramètres.",
|
||||
"experimental_warning": "La fonctionnalité LLM est actuellement expérimentale – vous êtes prévenu.",
|
||||
"selected_provider": "Fournisseur sélectionné",
|
||||
"selected_provider_description": "Choisissez le fournisseur d’IA pour les fonctionnalités de discussion et de complétion",
|
||||
"select_model": "Sélectionner le modèle...",
|
||||
"select_provider": "Sélectionnez un fournisseur...",
|
||||
"ai_enabled": "Fonctionnalités d'IA activées",
|
||||
"ai_disabled": "Fonctionnalités d'IA désactivées",
|
||||
"no_models_found_online": "Aucun modèle trouvé. Veuillez vérifier votre clé API et vos paramètres.",
|
||||
"no_models_found_ollama": "Aucun modèle Ollama trouvé. Veuillez vérifier si Ollama est en cours d'exécution.",
|
||||
"error_fetching": "Erreur lors de la récupération des modèles : {{error}}"
|
||||
},
|
||||
"ui-performance": {
|
||||
"title": "Performance",
|
||||
"enable-motion": "Activer les transitions et animations",
|
||||
@@ -2058,7 +1905,6 @@
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Page de {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} notes"
|
||||
},
|
||||
"collections": {
|
||||
|
||||
@@ -442,7 +442,7 @@
|
||||
"share_index": "liostálfaidh nóta leis an lipéad seo fréamhacha uile nótaí comhroinnte",
|
||||
"display_relations": "Ainmneacha caidrimh scartha le camóga ar cheart iad a thaispeáint. Beidh na cinn eile go léir i bhfolach.",
|
||||
"hide_relations": "Ainmneacha caidrimh scartha le camóga ar cheart iad a cheilt. Taispeánfar na cinn eile go léir.",
|
||||
"title_template": "Teideal réamhshocraithe nótaí a cruthaíodh mar leanaí den nóta seo. Déantar an luach a mheas mar theaghrán JavaScript\n agus dá bhrí sin is féidir é a shaibhriú le hábhar dinimiciúil trí na hathróga <code>now</code> agus <code>parentNote</code> insteallta. Samplaí:\n\n <ul>\n <li><code>Saothair liteartha ${parentNote.getLabelValue('authorName')}</code></li>\n <li><code>Log le haghaidh ${now.format('YYYY-MM-DD HH:mm:ss')}</code></li>\n </ul>\n\nFéach <a href=\"https://triliumnext.github.io/Docs/Wiki/default-note-title.html\">vicí le sonraí</a>, doiciméid API le haghaidh <a href=\"https://zadam.github.io/trilium/backend_api/Note.html\">parentNote</a> agus <a href=\"https://day.js.org/docs/en/display/format\">now</a> le haghaidh sonraí.",
|
||||
"title_template": "teideal réamhshocraithe nótaí a cruthaíodh mar leanaí den nóta seo. Déantar an luach a mheas mar theaghrán JavaScript \n agus dá bhrí sin is féidir é a shaibhriú le hábhar dinimiciúil trí na hathróga <code>now</code> agus <code>parentNote</code> insteallta. Samplaí:\n \n <ul>\n <li><code>Saothair liteartha ${parentNote.getLabelValue('authorName')}</code></li>\n <li><code>Log le haghaidh ${now.format('YYYY-MM-DD HH:mm:ss')}</code></li>\n </ul>\n \n Féach <a href=\"https://triliumnext.github.io/Docs/Wiki/default-note-title.html\">vicí le sonraí</a>, doiciméid API le haghaidh <a href=\"https://zadam.github.io/trilium/backend_api/Note.html\">parentNote</a> agus <a href=\"https://day.js.org/docs/en/display/format\">now</a> le haghaidh sonraí.",
|
||||
"template": "Beidh an nóta seo le feiceáil i roghnú na dteimpléad atá ar fáil agus nóta nua á chruthú",
|
||||
"toc": "Cuirfidh <code>#toc</code> nó <code>#toc=show</code> iallach ar an gClár Ábhair a bheith le feiceáil, cuirfidh <code>#toc=hide</code> iallach air é a cheilt. Mura bhfuil an lipéad ann, breathnaítear ar an socrú domhanda",
|
||||
"color": "sainmhíníonn dath an nóta sa chrann nótaí, snaisc srl. Úsáid aon luach datha CSS bailí cosúil le 'dearg' nó #a13d5f",
|
||||
@@ -1016,7 +1016,7 @@
|
||||
"no_attachments": "Níl aon cheangaltáin leis an nóta seo."
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "Níl aon nótaí faoi mhíbhuntáiste sa bhailiúchán seo mar sin níl aon rud le taispeáint. Féach ar an <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">vicí</a> le haghaidh tuilleadh sonraí.",
|
||||
"no_children_help": "Níl aon nótaí faoi mhíbhuntáiste sa bhailiúchán seo mar sin níl aon rud le taispeáint.",
|
||||
"drag_locked_title": "Glasáilte le haghaidh eagarthóireachta",
|
||||
"drag_locked_message": "Ní cheadaítear tarraingt ós rud é go bhfuil an bailiúchán faoi ghlas le haghaidh eagarthóireachta."
|
||||
},
|
||||
@@ -1072,15 +1072,6 @@
|
||||
"default_new_note_title": "nóta nua",
|
||||
"click_on_canvas_to_place_new_note": "Cliceáil ar chanbhás chun nóta nua a chur"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Taispeántar an nóta cabhrach seo mar nach bhfuil aon ghaol riachtanach ag an nóta seo den chineál Render HTML le go bhfeidhmeoidh sé i gceart.",
|
||||
"note_detail_render_help_2": "Úsáidtear cineál nóta HTML rindreála le haghaidh <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">scriptithe</a>. Go hachomair, tá nóta cóid HTML agat (le roinnt JavaScript más féidir) agus déanfaidh an nóta seo é a rindreáil. Chun go n-oibreoidh sé, ní mór duit <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">gaol</a> ar a dtugtar \"renderNote\" a shainiú ag pointeáil chuig an nóta HTML atá le rindreáil."
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Radharc Gréasáin",
|
||||
"embed_websites": "Nóta den chineál Gréasáin a ligeann duit suíomhanna gréasáin a leabú i Trilium.",
|
||||
"create_label": "Chun tús a chur leis, cruthaigh lipéad le seoladh URL ar mhaith leat a leabú, m.sh. #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Athnuachan"
|
||||
},
|
||||
@@ -1202,149 +1193,6 @@
|
||||
"enable-smooth-scroll": "Cumasaigh scrollú réidh",
|
||||
"app-restart-required": "(tá atosú an fheidhmchláir ag teastáil chun an t-athrú a chur i bhfeidhm)"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Níor tosaíodh",
|
||||
"title": "Socruithe AI",
|
||||
"processed_notes": "Nótaí Próiseáilte",
|
||||
"total_notes": "Nótaí Iomlána",
|
||||
"progress": "Dul Chun Cinn",
|
||||
"queued_notes": "Nótaí i gCiú",
|
||||
"failed_notes": "Nótaí Theipthe",
|
||||
"last_processed": "Próiseáilte Deiridh",
|
||||
"refresh_stats": "Athnuachan Staitisticí",
|
||||
"enable_ai_features": "Cumasaigh gnéithe AI/LLM",
|
||||
"enable_ai_description": "Cumasaigh gnéithe AI cosúil le achoimre nótaí, giniúint ábhair, agus cumais LLM eile",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Cumasaigh gnéithe AI/LLM",
|
||||
"enable_ai_desc": "Cumasaigh gnéithe AI cosúil le achoimre nótaí, giniúint ábhair, agus cumais LLM eile",
|
||||
"provider_configuration": "Cumraíocht Soláthraí AI",
|
||||
"provider_precedence": "Tosaíocht Soláthraí",
|
||||
"provider_precedence_description": "Liosta soláthraithe scartha le camóga in ord tosaíochta (m.sh., 'openai, anthropic, ollama')",
|
||||
"temperature": "Teocht",
|
||||
"temperature_description": "Rialaíonn randamacht i bhfreagraí (0 = cinntitheach, 2 = uasmhéid randamachta)",
|
||||
"system_prompt": "Pras Córais",
|
||||
"system_prompt_description": "Leid réamhshocraithe an chórais a úsáidtear le haghaidh gach idirghníomhaíocht AI",
|
||||
"openai_configuration": "Cumraíocht OpenAI",
|
||||
"openai_settings": "Socruithe OpenAI",
|
||||
"api_key": "Eochair API",
|
||||
"url": "Bun-URL",
|
||||
"model": "Samhail",
|
||||
"openai_api_key_description": "D'eochair API OpenAI chun rochtain a fháil ar a gcuid seirbhísí AI",
|
||||
"anthropic_api_key_description": "D'eochair API Anthropic chun rochtain a fháil ar mhúnlaí Claude",
|
||||
"default_model": "Samhail Réamhshocraithe",
|
||||
"openai_model_description": "Samplaí: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "Bun-URL",
|
||||
"openai_url_description": "Réamhshocrú: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Socruithe Anthropic",
|
||||
"anthropic_url_description": "Bun-URL don Anthropic API (réamhshocraithe: https://api.anthropic.com)",
|
||||
"anthropic_model_description": "Samhlacha Anthropic Claude le haghaidh comhlánú comhrá",
|
||||
"voyage_settings": "Socruithe Voyage AI",
|
||||
"ollama_settings": "Socruithe Ollama",
|
||||
"ollama_url_description": "URL don Ollama API (réamhshocrú: http://localhost:11434)",
|
||||
"ollama_model_description": "Samhail Ollama le húsáid le haghaidh comhrá a chríochnú",
|
||||
"anthropic_configuration": "Cumraíocht Anthropic",
|
||||
"voyage_configuration": "Cumraíocht AI Voyage",
|
||||
"voyage_url_description": "Réamhshocrú: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Cumraíocht Ollama",
|
||||
"enable_ollama": "Cumasaigh Ollama",
|
||||
"enable_ollama_description": "Cumasaigh Ollama le haghaidh úsáide áitiúla samhail AI",
|
||||
"ollama_url": "URL Ollama",
|
||||
"ollama_model": "Samhail Ollama",
|
||||
"refresh_models": "Athnuachan Samhlacha",
|
||||
"refreshing_models": "Ag athnuachan...",
|
||||
"enable_automatic_indexing": "Cumasaigh Innéacsú Uathoibríoch",
|
||||
"rebuild_index": "Innéacs Athchóirithe",
|
||||
"rebuild_index_error": "Earráid ag tosú atógáil an innéacs. Seiceáil na logaí le haghaidh sonraí.",
|
||||
"note_title": "Teideal an Nóta",
|
||||
"error": "Earráid",
|
||||
"last_attempt": "Iarracht Dheiridh",
|
||||
"actions": "Gníomhartha",
|
||||
"retry": "Déan iarracht eile",
|
||||
"partial": "{{ percentage }}% críochnaithe",
|
||||
"retry_queued": "Nóta curtha i scuaine le haghaidh athiarrachta",
|
||||
"retry_failed": "Theip ar an nóta a chur sa scuaine le haghaidh athiarrachta",
|
||||
"max_notes_per_llm_query": "Uasmhéid Nótaí In Aghaidh an Fhiosrúcháin",
|
||||
"max_notes_per_llm_query_description": "Uasmhéid nótaí comhchosúla le cur san áireamh i gcomhthéacs na hintleachta saorga",
|
||||
"active_providers": "Soláthraithe Gníomhacha",
|
||||
"disabled_providers": "Soláthraithe faoi Mhíchumas",
|
||||
"remove_provider": "Bain an soláthraí as an gcuardach",
|
||||
"restore_provider": "Athchóirigh soláthraí chuig an gcuardach",
|
||||
"similarity_threshold": "Tairseach Cosúlachta",
|
||||
"similarity_threshold_description": "Scór cosúlachta íosta (0-1) le go n-áireofar nótaí i gcomhthéacs fiosrúcháin LLM",
|
||||
"reprocess_index": "Athchruthaigh Innéacs Cuardaigh",
|
||||
"reprocessing_index": "Atógáil...",
|
||||
"reprocess_index_started": "Cuireadh tús le hoptamú innéacs cuardaigh sa chúlra",
|
||||
"reprocess_index_error": "Earráid ag atógáil innéacs cuardaigh",
|
||||
"index_rebuild_progress": "Dul Chun Cinn Athchóirithe Innéacs",
|
||||
"index_rebuilding": "Innéacs optamaithe ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Uasmhéadú innéacs críochnaithe",
|
||||
"index_rebuild_status_error": "Earráid ag seiceáil stádas athchóirithe innéacs",
|
||||
"never": "Choíche",
|
||||
"processing": "Próiseáil ({{percentage}}%)",
|
||||
"incomplete": "Neamhchríochnaithe ({{percentage}}%)",
|
||||
"complete": "Críochnaithe (100%)",
|
||||
"refreshing": "Ag athnuachan...",
|
||||
"auto_refresh_notice": "Athnuachan uathoibríoch gach {{seconds}} soicind",
|
||||
"note_queued_for_retry": "Nóta curtha i scuaine le haghaidh athiarrachta",
|
||||
"failed_to_retry_note": "Theip ar an nóta a athdhéanamh",
|
||||
"all_notes_queued_for_retry": "Gach nóta nár éirigh leo curtha i scuaine le haghaidh athiarrachta",
|
||||
"failed_to_retry_all": "Theip ar athiarracht nótaí",
|
||||
"ai_settings": "Socruithe AI",
|
||||
"api_key_tooltip": "Eochair API chun rochtain a fháil ar an tseirbhís",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "Tá eochair API Anthropic folamh. Cuir isteach eochair API bhailí le do thoil.",
|
||||
"openai": "Tá eochair API OpenAI folamh. Cuir isteach eochair API bhailí le do thoil.",
|
||||
"voyage": "Tá eochair API Voyage folamh. Cuir isteach eochair API bhailí le do thoil.",
|
||||
"ollama": "Tá eochair API Ollama folamh. Cuir isteach eochair API bhailí le do thoil."
|
||||
},
|
||||
"agent": {
|
||||
"processing": "Ag próiseáil...",
|
||||
"thinking": "Ag smaoineamh...",
|
||||
"loading": "Ag lódáil...",
|
||||
"generating": "Ag giniúint..."
|
||||
},
|
||||
"name": "Intleacht Shaorga",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Úsáid comhthéacs feabhsaithe",
|
||||
"enhanced_context_description": "Tugann sé níos mó comhthéacs don AI ón nóta agus a nótaí gaolmhara le haghaidh freagraí níos fearr",
|
||||
"show_thinking": "Taispeáin smaointeoireacht",
|
||||
"show_thinking_description": "Taispeáin slabhra phróiseas smaointeoireachta na hintleachta saorga",
|
||||
"enter_message": "Cuir isteach do theachtaireacht...",
|
||||
"error_contacting_provider": "Earráid ag teacht i dteagmháil leis an soláthraí AI. Seiceáil do shocruithe agus do nasc idirlín le do thoil.",
|
||||
"error_generating_response": "Earráid ag giniúint freagra AI",
|
||||
"index_all_notes": "Innéacs na Nótaí Uile",
|
||||
"index_status": "Stádas Innéacs",
|
||||
"indexed_notes": "Nótaí Innéacsaithe",
|
||||
"indexing_stopped": "Stopadh an innéacsú",
|
||||
"indexing_in_progress": "Innéacsú ar siúl...",
|
||||
"last_indexed": "Innéacsaithe Deiridh",
|
||||
"note_chat": "Comhrá Nótaí",
|
||||
"sources": "Foinsí",
|
||||
"start_indexing": "Tosaigh ag Innéacsú",
|
||||
"use_advanced_context": "Úsáid Comhthéacs Ardleibhéil",
|
||||
"ollama_no_url": "Níl Ollama cumraithe. Cuir isteach URL bailí le do thoil.",
|
||||
"chat": {
|
||||
"root_note_title": "Comhráite AI",
|
||||
"root_note_content": "Tá do chomhráite comhrá AI sábháilte sa nóta seo.",
|
||||
"new_chat_title": "Comhrá Nua",
|
||||
"create_new_ai_chat": "Cruthaigh Comhrá AI nua"
|
||||
},
|
||||
"create_new_ai_chat": "Cruthaigh Comhrá AI nua",
|
||||
"configuration_warnings": "Tá roinnt fadhbanna le do chumraíocht AI. Seiceáil do shocruithe le do thoil.",
|
||||
"experimental_warning": "Tá an ghné LLM turgnamhach faoi láthair - tugadh rabhadh duit.",
|
||||
"selected_provider": "Soláthraí Roghnaithe",
|
||||
"selected_provider_description": "Roghnaigh an soláthraí AI le haghaidh gnéithe comhrá agus comhlánaithe",
|
||||
"select_model": "Roghnaigh samhail...",
|
||||
"select_provider": "Roghnaigh soláthraí...",
|
||||
"ai_enabled": "Gnéithe AI cumasaithe",
|
||||
"ai_disabled": "Gnéithe AI díchumasaithe",
|
||||
"no_models_found_online": "Níor aimsíodh aon mhúnlaí. Seiceáil d’eochair API agus do shocruithe le do thoil.",
|
||||
"no_models_found_ollama": "Níor aimsíodh aon mhúnlaí Ollama. Seiceáil le do thoil an bhfuil Ollama ag rith.",
|
||||
"error_fetching": "Earráid ag fáil samhlacha: {{error}}"
|
||||
},
|
||||
"zoom_factor": {
|
||||
"title": "Fachtóir Súmáil (leagan deisce amháin)",
|
||||
"description": "Is féidir súmáil a rialú le haicearraí CTRL+- agus CTRL+= chomh maith."
|
||||
@@ -1595,7 +1443,8 @@
|
||||
"description": "Cur síos",
|
||||
"reload_app": "Athlódáil an aip chun na hathruithe a chur i bhfeidhm",
|
||||
"set_all_to_default": "Socraigh gach aicearra go dtí an réamhshocrú",
|
||||
"confirm_reset": "An bhfuil tú cinnte gur mhaith leat na haicearraí méarchláir go léir a athshocrú go dtí an rogha réamhshocraithe?"
|
||||
"confirm_reset": "An bhfuil tú cinnte gur mhaith leat na haicearraí méarchláir go léir a athshocrú go dtí an rogha réamhshocraithe?",
|
||||
"no_results": "Níor aimsíodh aon aicearraí a mheaitseálann '{{filter}}'"
|
||||
},
|
||||
"spellcheck": {
|
||||
"title": "Seiceáil Litrithe",
|
||||
@@ -1813,7 +1662,9 @@
|
||||
"print_report_collection_content_many": "Níorbh fhéidir {{count}} nótaí sa bhailiúchán a phriontáil mar nach dtacaítear leo nó mar go bhfuil siad faoi chosaint.",
|
||||
"print_report_collection_content_other": "Níorbh fhéidir {{count}} nótaí sa bhailiúchán a phriontáil mar nach dtacaítear leo nó mar go bhfuil siad faoi chosaint.",
|
||||
"print_report_collection_details_button": "Féach sonraí",
|
||||
"print_report_collection_details_ignored_notes": "Nótaí neamhairdithe"
|
||||
"print_report_collection_details_ignored_notes": "Nótaí neamhairdithe",
|
||||
"print_report_error_title": "Theip ar phriontáil",
|
||||
"print_report_stack_trace": "Rian cruachta"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "clóscríobh teideal an nóta anseo...",
|
||||
@@ -2114,7 +1965,8 @@
|
||||
"raster": "Raster",
|
||||
"vector_light": "Veicteoir (Solas)",
|
||||
"vector_dark": "Veicteoir (Dorcha)",
|
||||
"show-scale": "Taispeáin scála"
|
||||
"show-scale": "Taispeáin scála",
|
||||
"show-labels": "Taispeáin ainmneacha marcóirí"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "Scrios an tsraith"
|
||||
@@ -2193,8 +2045,9 @@
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Leathanach de {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} nótaí"
|
||||
"total_notes": "{{count}} nótaí",
|
||||
"prev_page": "Leathanach roimhe seo",
|
||||
"next_page": "An chéad leathanach eile"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "Ní féidir ábhar a thaispeáint mar gheall ar earráid."
|
||||
@@ -2328,5 +2181,49 @@
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Leabharmharcanna"
|
||||
},
|
||||
"web_view_setup": {
|
||||
"title": "Cruthaigh radharc beo de leathanach gréasáin go díreach isteach i Trilium",
|
||||
"url_placeholder": "Cuir isteach nó greamaigh seoladh an tsuímh ghréasáin, mar shampla https://triliumnotes.org",
|
||||
"create_button": "Cruthaigh Radharc Gréasáin",
|
||||
"invalid_url_title": "Seoladh neamhbhailí",
|
||||
"invalid_url_message": "Cuir isteach seoladh gréasáin bailí, mar shampla https://triliumnotes.org.",
|
||||
"disabled_description": "Iompórtáladh an radharc gréasáin seo ó fhoinse sheachtrach. Chun cabhrú leat a chosaint ar ábhar fioscaireachta nó mailíseach, níl sé ag lódáil go huathoibríoch. Is féidir leat é a chumasú má tá muinín agat as an bhfoinse.",
|
||||
"disabled_button_enable": "Cumasaigh radharc gréasáin"
|
||||
},
|
||||
"render": {
|
||||
"setup_title": "Taispeáin HTML saincheaptha nó Preact JSX taobh istigh den nóta seo",
|
||||
"setup_create_sample_preact": "Cruthaigh nóta samplach le Preact",
|
||||
"setup_create_sample_html": "Cruthaigh nóta samplach le HTML",
|
||||
"setup_sample_created": "Cruthaíodh nóta samplach mar nóta linbh.",
|
||||
"disabled_description": "Tagann na nótaí rindreála seo ó fhoinse sheachtrach. Chun tú a chosaint ar ábhar mailíseach, níl sé cumasaithe de réir réamhshocraithe. Déan cinnte go bhfuil muinín agat as an bhfoinse sula gcumasaíonn tú é.",
|
||||
"disabled_button_enable": "Cumasaigh nóta rindreála"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "Pacáiste deilbhín",
|
||||
"type_backend_script": "Script chúltaca",
|
||||
"type_frontend_script": "Script tosaigh",
|
||||
"type_widget": "Giuirléid",
|
||||
"type_app_css": "CSS saincheaptha",
|
||||
"type_render_note": "Nóta rindreála",
|
||||
"type_web_view": "Radharc gréasáin",
|
||||
"type_app_theme": "Téama saincheaptha",
|
||||
"toggle_tooltip_enable_tooltip": "Cliceáil chun an {{type}} seo a chumasú.",
|
||||
"toggle_tooltip_disable_tooltip": "Cliceáil chun an {{type}} seo a dhíchumasú.",
|
||||
"menu_docs": "Doiciméadú oscailte",
|
||||
"menu_execute_now": "Rith an script anois",
|
||||
"menu_run": "Rith go huathoibríoch",
|
||||
"menu_run_disabled": "De láimh",
|
||||
"menu_run_backend_startup": "Nuair a thosaíonn an cúltaca",
|
||||
"menu_run_hourly": "Gach uair an chloig",
|
||||
"menu_run_daily": "Laethúil",
|
||||
"menu_run_frontend_startup": "Nuair a thosaíonn tosaigh an deisce",
|
||||
"menu_run_mobile_startup": "Nuair a thosaíonn an taobhlíne soghluaiste",
|
||||
"menu_change_to_widget": "Athraigh go giuirléid",
|
||||
"menu_change_to_frontend_script": "Athraigh chuig an script tosaigh",
|
||||
"menu_theme_base": "Bunús téama"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Foghlaim níos mó"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -50,7 +50,8 @@
|
||||
"save": "Simpan",
|
||||
"branch_prefix_saved": "Prefiks cabang telah disimpan.",
|
||||
"branch_prefix_saved_multiple": "Prefix cabang telah disimpan pada {{count}} cabang.",
|
||||
"affected_branches": "Cabang terdampak ({{count}}):"
|
||||
"affected_branches": "Cabang terdampak ({{count}}):",
|
||||
"edit_branch_prefix": "Sunting awalan cabang"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "Aksi borongan",
|
||||
@@ -61,14 +62,18 @@
|
||||
"execute_bulk_actions": "Eksekusi aksi borongan",
|
||||
"bulk_actions_executed": "Aksi borongan telah di eksekusi dengan sukses.",
|
||||
"none_yet": "Belum ada... tambahkan aksi dengan memilih salah satu dari aksi di atas.",
|
||||
"labels": "Label-label"
|
||||
"labels": "Label-label",
|
||||
"relations": "Hubungan",
|
||||
"notes": "Catatan",
|
||||
"other": "Lainnya"
|
||||
},
|
||||
"confirm": {
|
||||
"cancel": "Batal",
|
||||
"ok": "Oke",
|
||||
"are_you_sure_remove_note": "Apakah anda yakin mau membuang catatan \"{{title}}\" dari peta relasi? ",
|
||||
"if_you_dont_check": "Jika Anda tidak mencentang ini, catatan hanya akan dihapus dari peta relasi.",
|
||||
"also_delete_note": "Hapus juga catatannya"
|
||||
"also_delete_note": "Hapus juga catatannya",
|
||||
"confirmation": "Konfirmasi"
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Hapus pratinjau catatan",
|
||||
@@ -77,9 +82,19 @@
|
||||
"erase_notes_description": "Penghapusan normal hanya menandai catatan sebagai dihapus dan dapat dipulihkan (melalui dialog versi revisi) dalam jangka waktu tertentu. Mencentang opsi ini akan menghapus catatan secara permanen seketika dan catatan tidak akan bisa dipulihkan kembali.",
|
||||
"erase_notes_warning": "Hapus catatan secara permanen (tidak bisa dikembalikan), termasuk semua duplikat. Aksi akan memaksa aplikasi untuk mengulang kembali.",
|
||||
"notes_to_be_deleted": "Catatan-catatan berikut akan dihapuskan ({{notesCount}})",
|
||||
"no_note_to_delete": "Tidak ada Catatan yang akan dihapus (hanya duplikat)."
|
||||
"no_note_to_delete": "Tidak ada Catatan yang akan dihapus (hanya duplikat).",
|
||||
"broken_relations_to_be_deleted": "Hubungan berikut akan diputus dan dihapus ({{ relationCount}})"
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "Duplikat catatan ke…"
|
||||
"clone_notes_to": "Duplikat catatan ke…",
|
||||
"help_on_links": "Bantuan pada tautan",
|
||||
"notes_to_clone": "Catatan untuk kloning",
|
||||
"target_parent_note": "Sasaran catatan utama",
|
||||
"search_for_note_by_its_name": "cari catatan berdasarkan namanya",
|
||||
"cloned_note_prefix_title": "Catatan yang dikloning akan ditampilkan diruntutan catatan dengan awalan yang diberikan",
|
||||
"prefix_optional": "Awalan (opsional)",
|
||||
"clone_to_selected_note": "Salin ke catatan yang dipilih",
|
||||
"no_path_to_clone_to": "Tidak ada jalur untuk digandakan.",
|
||||
"note_cloned": "Catatan \"{{clonedTitle}}\" telah digandakan ke dalam \"{{targetTitle}}\""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,8 +167,8 @@
|
||||
"desktop-application": "Applicazione Desktop",
|
||||
"native-title-bar": "Barra del titolo nativa",
|
||||
"native-title-bar-description": "Su Windows e macOS, disattivare la barra del titolo nativa rende l'applicazione più compatta. Su Linux, attivarla si integra meglio con il resto del sistema.",
|
||||
"background-effects": "Abilita effetti di sfondo (solo Windows 11)",
|
||||
"background-effects-description": "L'effetto Mica aggiunge uno sfondo sfocato ed elegante alle finestre delle app, creando profondità e un aspetto moderno. La \"Barra del titolo nativa\" deve essere disattivata.",
|
||||
"background-effects": "Abilita effetti di sfondo",
|
||||
"background-effects-description": "Aggiunge uno sfondo sfocato ed elegante alle finestre dell'app, creando profondità e un look moderno. La \"barra del titolo nativa\" deve essere disabilitata.",
|
||||
"restart-app-button": "Riavviare l'applicazione per visualizzare le modifiche"
|
||||
},
|
||||
"note_autocomplete": {
|
||||
@@ -186,7 +186,8 @@
|
||||
"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."
|
||||
"unable-to-load-map": "Impossibile caricare la mappa.",
|
||||
"create-child-note-text": "Aggiungi indicatore"
|
||||
},
|
||||
"geo-map-context": {
|
||||
"open-location": "Apri la posizione",
|
||||
@@ -368,7 +369,8 @@
|
||||
"description": "Descrizione",
|
||||
"reload_app": "Ricarica l'app per applicare le modifiche",
|
||||
"set_all_to_default": "Imposta tutte le scorciatoie sui valori predefiniti",
|
||||
"confirm_reset": "Vuoi davvero ripristinare tutte le scorciatoie da tastiera ai valori predefiniti?"
|
||||
"confirm_reset": "Vuoi davvero ripristinare tutte le scorciatoie da tastiera ai valori predefiniti?",
|
||||
"no_results": "Nessuna scorciatoia trovata corrispondente '{{filter}}'"
|
||||
},
|
||||
"shared_switch": {
|
||||
"toggle-on-title": "Condividi la nota",
|
||||
@@ -422,7 +424,8 @@
|
||||
"unknown_search_option": "Opzione di ricerca sconosciuta {{searchOptionName}}",
|
||||
"search_note_saved": "La nota di ricerca è stata salvata in {{- notePathTitle}}",
|
||||
"actions_executed": "Le azioni sono state eseguite.",
|
||||
"view_options": "Opzioni di visualizzazione:"
|
||||
"view_options": "Opzioni di visualizzazione:",
|
||||
"option": "opzione"
|
||||
},
|
||||
"modal": {
|
||||
"close": "Chiudi",
|
||||
@@ -660,149 +663,6 @@
|
||||
"thursday": "Giovedì",
|
||||
"friday": "Venerdì"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Non iniziato",
|
||||
"title": "Impostazioni AI",
|
||||
"processed_notes": "Note elaborate",
|
||||
"total_notes": "Note totali",
|
||||
"progress": "Progressi",
|
||||
"queued_notes": "Note in coda",
|
||||
"failed_notes": "Note non riuscite",
|
||||
"last_processed": "Ultimo elaborato",
|
||||
"refresh_stats": "Aggiorna statistiche",
|
||||
"enable_ai_features": "Abilita le funzionalità AI/LLM",
|
||||
"enable_ai_description": "Abilita funzionalità di intelligenza artificiale come il riepilogo delle note, la generazione di contenuti e altre funzionalità LLM",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Antropico",
|
||||
"voyage_tab": "Viaggio AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Abilita le funzionalità AI/LLM",
|
||||
"enable_ai_desc": "Abilita funzionalità di intelligenza artificiale come il riepilogo delle note, la generazione di contenuti e altre funzionalità LLM",
|
||||
"provider_configuration": "Configurazione del fornitore di intelligenza artificiale",
|
||||
"provider_precedence": "Precedenza del fornitore",
|
||||
"provider_precedence_description": "Elenco dei provider separati da virgole in ordine di precedenza (ad esempio, 'openai,anthropic,ollama')",
|
||||
"temperature": "Temperatura",
|
||||
"temperature_description": "Controlla la casualità nelle risposte (0 = deterministico, 2 = casualità massima)",
|
||||
"system_prompt": "Prompt di sistema",
|
||||
"system_prompt_description": "Prompt di sistema predefinito utilizzato per tutte le interazioni con l'IA",
|
||||
"openai_configuration": "Configurazione OpenAI",
|
||||
"openai_settings": "Impostazioni OpenAI",
|
||||
"api_key": "Chiave API",
|
||||
"url": "URL di base",
|
||||
"model": "Modello",
|
||||
"openai_api_key_description": "La tua chiave API OpenAI per accedere ai loro servizi di intelligenza artificiale",
|
||||
"anthropic_api_key_description": "La tua chiave API Anthropic per accedere ai modelli Claude",
|
||||
"default_model": "Modello predefinito",
|
||||
"openai_model_description": "Esempi: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "URL di base",
|
||||
"openai_url_description": "Predefinito: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Ambientazioni antropiche",
|
||||
"anthropic_url_description": "URL di base per l'API Anthropic (predefinito: https://api.anthropic.com)",
|
||||
"anthropic_model_description": "Modelli di Anthropic Claude per il completamento della chat",
|
||||
"voyage_settings": "Impostazioni AI di Voyage",
|
||||
"ollama_settings": "Impostazioni Ollama",
|
||||
"ollama_url_description": "URL per l'API Ollama (predefinito: http://localhost:11434)",
|
||||
"ollama_model_description": "Modello Ollama da utilizzare per il completamento della chat",
|
||||
"anthropic_configuration": "Configurazione antropica",
|
||||
"voyage_configuration": "Configurazione AI di viaggio",
|
||||
"voyage_url_description": "Predefinito: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Configurazione Ollama",
|
||||
"enable_ollama": "Abilita Ollama",
|
||||
"enable_ollama_description": "Abilita Ollama per l'utilizzo del modello AI locale",
|
||||
"ollama_url": "URL di Ollama",
|
||||
"ollama_model": "Modello Ollama",
|
||||
"refresh_models": "Aggiorna modelli",
|
||||
"refreshing_models": "Rinfrescante...",
|
||||
"enable_automatic_indexing": "Abilita l'indicizzazione automatica",
|
||||
"rebuild_index": "Ricostruisci indice",
|
||||
"rebuild_index_error": "Errore durante l'avvio della ricostruzione dell'indice. Controllare i log per i dettagli.",
|
||||
"note_title": "Titolo della nota",
|
||||
"error": "Errore",
|
||||
"last_attempt": "Ultimo tentativo",
|
||||
"actions": "Azioni",
|
||||
"retry": "Riprova",
|
||||
"partial": "{{ percentage }}% completato",
|
||||
"retry_queued": "Nota in coda per un nuovo tentativo",
|
||||
"retry_failed": "Impossibile mettere in coda la nota per un nuovo tentativo",
|
||||
"max_notes_per_llm_query": "Numero massimo di note per query",
|
||||
"max_notes_per_llm_query_description": "Numero massimo di note simili da includere nel contesto AI",
|
||||
"active_providers": "Fornitori attivi",
|
||||
"disabled_providers": "Fornitori disabili",
|
||||
"remove_provider": "Rimuovi il fornitore dalla ricerca",
|
||||
"restore_provider": "Ripristina il provider per la ricerca",
|
||||
"similarity_threshold": "Soglia di similarità",
|
||||
"similarity_threshold_description": "Punteggio minimo di similarità (0-1) per le note da includere nel contesto per le query LLM",
|
||||
"reprocess_index": "Ricostruisci l'indice di ricerca",
|
||||
"reprocessing_index": "Ricostruzione...",
|
||||
"reprocess_index_started": "Ottimizzazione dell'indice di ricerca avviata in background",
|
||||
"reprocess_index_error": "Errore durante la ricostruzione dell'indice di ricerca",
|
||||
"index_rebuild_progress": "Progresso nella ricostruzione dell'indice",
|
||||
"index_rebuilding": "Indice di ottimizzazione ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Ottimizzazione dell'indice completata",
|
||||
"index_rebuild_status_error": "Errore durante il controllo dello stato di ricostruzione dell'indice",
|
||||
"never": "Mai",
|
||||
"processing": "Elaborazione ({{percentage}}%)",
|
||||
"incomplete": "Incompleto ({{percentage}}%)",
|
||||
"complete": "Completato (100%)",
|
||||
"refreshing": "Rinfrescante...",
|
||||
"auto_refresh_notice": "Si aggiorna automaticamente ogni {{seconds}} secondi",
|
||||
"note_queued_for_retry": "Nota in coda per un nuovo tentativo",
|
||||
"failed_to_retry_note": "Impossibile riprovare nota",
|
||||
"all_notes_queued_for_retry": "Tutte le note non riuscite sono in coda per un nuovo tentativo",
|
||||
"failed_to_retry_all": "Impossibile riprovare le note",
|
||||
"ai_settings": "Impostazioni AI",
|
||||
"api_key_tooltip": "Chiave API per accedere al servizio",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "La chiave API di Anthropic è vuota. Inserisci una chiave API valida.",
|
||||
"openai": "La chiave API di OpenAI è vuota. Inserisci una chiave API valida.",
|
||||
"voyage": "La chiave API di Voyage è vuota. Inserisci una chiave API valida.",
|
||||
"ollama": "La chiave API di Ollama è vuota. Inserisci una chiave API valida."
|
||||
},
|
||||
"agent": {
|
||||
"processing": "Elaborazione in corso...",
|
||||
"thinking": "Pensiero...",
|
||||
"loading": "Caricamento...",
|
||||
"generating": "Generazione in corso..."
|
||||
},
|
||||
"name": "intelligenza artificiale",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Utilizzare il contesto avanzato",
|
||||
"enhanced_context_description": "Fornisce all'IA più contesto dalla nota e dalle note correlate per risposte migliori",
|
||||
"show_thinking": "Mostra il pensiero",
|
||||
"show_thinking_description": "Mostra la catena del processo di pensiero dell'IA",
|
||||
"enter_message": "Inserisci il tuo messaggio...",
|
||||
"error_contacting_provider": "Errore durante la connessione al fornitore dell'IA. Controlla le impostazioni e la connessione Internet.",
|
||||
"error_generating_response": "Errore durante la generazione della risposta AI",
|
||||
"index_all_notes": "Indice Tutte le note",
|
||||
"index_status": "Stato dell'indice",
|
||||
"indexed_notes": "Note indicizzate",
|
||||
"indexing_stopped": "Indicizzazione interrotta",
|
||||
"indexing_in_progress": "Indicizzazione in corso...",
|
||||
"last_indexed": "Ultimo indicizzato",
|
||||
"note_chat": "Nota Chat",
|
||||
"sources": "Fonti",
|
||||
"start_indexing": "Avvia l'indicizzazione",
|
||||
"use_advanced_context": "Usa contesto avanzato",
|
||||
"ollama_no_url": "Ollama non è configurato. Inserisci un URL valido.",
|
||||
"chat": {
|
||||
"root_note_title": "Chat AI",
|
||||
"root_note_content": "Questa nota contiene le conversazioni della chat AI salvate.",
|
||||
"new_chat_title": "Nuova chat",
|
||||
"create_new_ai_chat": "Crea una nuova chat AI"
|
||||
},
|
||||
"create_new_ai_chat": "Crea una nuova chat AI",
|
||||
"configuration_warnings": "Ci sono alcuni problemi con la configurazione dell'IA. Controlla le impostazioni.",
|
||||
"experimental_warning": "La funzionalità LLM è attualmente sperimentale: sei stato avvisato.",
|
||||
"selected_provider": "Fornitore selezionato",
|
||||
"selected_provider_description": "Scegli il fornitore di intelligenza artificiale per le funzionalità di chat e completamento",
|
||||
"select_model": "Seleziona il modello...",
|
||||
"select_provider": "Seleziona il fornitore...",
|
||||
"ai_enabled": "Funzionalità AI abilitate",
|
||||
"ai_disabled": "Funzionalità AI disabilitate",
|
||||
"no_models_found_online": "Nessun modello trovato. Controlla la tua chiave API e le impostazioni.",
|
||||
"no_models_found_ollama": "Nessun modello Ollama trovato. Controlla se Ollama è in esecuzione.",
|
||||
"error_fetching": "Errore durante il recupero dei modelli: {{error}}"
|
||||
},
|
||||
"import": {
|
||||
"importIntoNote": "Importa nella nota",
|
||||
"chooseImportFile": "Scegli file di importazione",
|
||||
@@ -1241,7 +1101,8 @@
|
||||
"show-cheatsheet": "Mostra il foglietto illustrativo",
|
||||
"toggle-zen-mode": "Modalità Zen",
|
||||
"new-version-available": "Nuovo aggiornamento disponibile",
|
||||
"download-update": "Ottieni la versione {{latestVersion}}"
|
||||
"download-update": "Ottieni la versione {{latestVersion}}",
|
||||
"search_notes": "Cerca note"
|
||||
},
|
||||
"zen_mode": {
|
||||
"button_exit": "Esci dalla modalità Zen"
|
||||
@@ -1324,7 +1185,7 @@
|
||||
"button_title": "Esporta diagramma come SVG"
|
||||
},
|
||||
"relation_map_buttons": {
|
||||
"create_child_note_title": "Crea una nuova nota secondaria e aggiungila a questa mappa delle relazioni",
|
||||
"create_child_note_title": "Crea una nota secondaria e aggiungila alla mappa",
|
||||
"reset_pan_zoom_title": "Ripristina panoramica e zoom alle coordinate e all'ingrandimento iniziali",
|
||||
"zoom_in_title": "Ingrandisci",
|
||||
"zoom_out_title": "Rimpicciolisci"
|
||||
@@ -1340,7 +1201,9 @@
|
||||
"delete_this_note": "Elimina questa nota",
|
||||
"note_revisions": "Revisioni delle note",
|
||||
"error_cannot_get_branch_id": "Impossibile ottenere branchId per notePath '{{notePath}}'",
|
||||
"error_unrecognized_command": "Comando non riconosciuto {{command}}"
|
||||
"error_unrecognized_command": "Comando non riconosciuto {{command}}",
|
||||
"backlinks": "Backlinks",
|
||||
"content_language_switcher": "Lingua dei contenuti: {{language}}"
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "Cambia icona nota",
|
||||
@@ -1521,7 +1384,7 @@
|
||||
"no_attachments": "Questa nota non ha allegati."
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "Questa raccolta non ha note secondarie, quindi non c'è nulla da visualizzare. Consulta la <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> per i dettagli.",
|
||||
"no_children_help": "Questa raccolta non ha note secondarie, quindi non c'è nulla da visualizzare.",
|
||||
"drag_locked_title": "Bloccato per la modifica",
|
||||
"drag_locked_message": "Trascinamento non consentito poiché la raccolta è bloccata per la modifica."
|
||||
},
|
||||
@@ -1577,15 +1440,6 @@
|
||||
"default_new_note_title": "nuova nota",
|
||||
"click_on_canvas_to_place_new_note": "Clicca sulla tela per inserire una nuova nota"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Questa nota di aiuto viene visualizzata perché questa nota di tipo Render HTML non ha la relazione richiesta per funzionare correttamente.",
|
||||
"note_detail_render_help_2": "Il tipo di nota HTML Render viene utilizzato per lo <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">scripting</a>. In breve, si ottiene una nota in codice HTML (opzionalmente con un po' di JavaScript) che verrà visualizzata. Per farla funzionare, è necessario definire una <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">relazione</a> denominata \"renderNote\" che punti alla nota HTML da visualizzare."
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Visualizzazione Web",
|
||||
"embed_websites": "La nota di tipo Web View consente di incorporare siti web in Trilium.",
|
||||
"create_label": "Per iniziare, crea un'etichetta con l'indirizzo URL che desideri incorporare, ad esempio #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"vacuum_database": {
|
||||
"title": "Pulizia del database",
|
||||
"description": "Questa operazione ricostruirà il database, generando in genere un file di dimensioni inferiori. In realtà, nessun dato verrà modificato.",
|
||||
@@ -1859,7 +1713,6 @@
|
||||
"confirm-change": "Si sconsiglia di cambiare tipo di nota quando il contenuto della nota non è vuoto. Vuoi continuare comunque?",
|
||||
"geo-map": "Mappa geografica",
|
||||
"beta-feature": "Beta",
|
||||
"ai-chat": "Chat AI",
|
||||
"task-list": "Elenco delle attività",
|
||||
"new-feature": "Nuovo",
|
||||
"collections": "Collezioni"
|
||||
@@ -1923,7 +1776,9 @@
|
||||
"print_report_collection_content_many": "{{count}} le note nella raccolta non possono essere stampate perché non sono supportate o sono protette.",
|
||||
"print_report_collection_content_other": "{{count}} le note nella raccolta non possono essere stampate perché non sono supportate o sono protette.",
|
||||
"print_report_collection_details_button": "Vedi dettagli",
|
||||
"print_report_collection_details_ignored_notes": "Note ignorate"
|
||||
"print_report_collection_details_ignored_notes": "Note ignorate",
|
||||
"print_report_error_title": "Impossibile stampare",
|
||||
"print_report_stack_trace": "Traccia dello stack"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "scrivi qui il titolo della nota...",
|
||||
@@ -2110,7 +1965,8 @@
|
||||
"raster": "Trama",
|
||||
"vector_light": "Vettore (Luce)",
|
||||
"vector_dark": "Vettore (scuro)",
|
||||
"show-scale": "Mostra scala"
|
||||
"show-scale": "Mostra scala",
|
||||
"show-labels": "Mostra nomi dei marcatori"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "Elimina riga"
|
||||
@@ -2143,9 +1999,9 @@
|
||||
"next_theme_message": "Al momento stai utilizzando il tema legacy. Vuoi provare il nuovo tema?",
|
||||
"next_theme_button": "Prova il nuovo tema",
|
||||
"background_effects_title": "Gli effetti di sfondo sono ora stabili",
|
||||
"background_effects_message": "Sui dispositivi Windows, gli effetti di sfondo sono ora completamente stabili. Gli effetti di sfondo aggiungono un tocco di colore all'interfaccia utente sfocando lo sfondo retrostante. Questa tecnica è utilizzata anche in altre applicazioni come Esplora risorse di Windows.",
|
||||
"background_effects_message": "Su dispositivi Windows e macOS, gli effetti di sfondo sono ora stabili. Gli effetti di sfondo aggiungono un tocco di colore all'interfaccia utente sfocando lo sfondo dietro di essa.",
|
||||
"background_effects_button": "Abilita gli effetti di sfondo",
|
||||
"dismiss": "Congedare",
|
||||
"dismiss": "Chiudi",
|
||||
"new_layout_title": "Nuovo layout",
|
||||
"new_layout_message": "Abbiamo introdotto un layout modernizzato per Trilium. La barra multifunzione è stata rimossa e integrata perfettamente nell'interfaccia principale, con una nuova barra di stato e sezioni espandibili (come gli attributi promossi) che assumono le funzioni chiave.\n\nIl nuovo layout è abilitato di default e può essere temporaneamente disabilitato tramite Opzioni → Aspetto.",
|
||||
"new_layout_button": "Maggiori informazioni"
|
||||
@@ -2164,7 +2020,6 @@
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Pagina di {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} note"
|
||||
},
|
||||
"collections": {
|
||||
@@ -2281,5 +2136,61 @@
|
||||
"pages_other": "{{count}} pagine",
|
||||
"pages_alt": "Pagina {{pageNumber}}",
|
||||
"pages_loading": "Caricamento in corso..."
|
||||
},
|
||||
"web_view_setup": {
|
||||
"title": "Crea una visualizzazione live di una pagina web direttamente in Trilium",
|
||||
"url_placeholder": "Inserisci o incolla l'indirizzo del sito web, ad esempio https://triliumnotes.org",
|
||||
"create_button": "Crea vista Web",
|
||||
"invalid_url_title": "Indirizzo non valido",
|
||||
"invalid_url_message": "Inserisci un indirizzo web valido, ad esempio https://triliumnotes.org.",
|
||||
"disabled_description": "Questa visualizzazione web è stata importata da una fonte esterna. Per proteggerti dal phishing o da contenuti dannosi, non viene caricata automaticamente. Puoi abilitarla se ritieni che la fonte sia affidabile.",
|
||||
"disabled_button_enable": "Abilita visualizzazione web"
|
||||
},
|
||||
"platform_indicator": {
|
||||
"available_on": "Disponibile su {{platform}}"
|
||||
},
|
||||
"mobile_tab_switcher": {
|
||||
"title_one": "Scheda {{count}}",
|
||||
"title_many": "Schede {{count}}",
|
||||
"title_other": "Schede {{count}}",
|
||||
"more_options": "Altre opzioni"
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Segnalibri"
|
||||
},
|
||||
"render": {
|
||||
"setup_title": "Visualizza HTML personalizzato o Preact JSX all'interno di questa nota",
|
||||
"setup_create_sample_preact": "Crea una nota di esempio con Preact",
|
||||
"setup_create_sample_html": "Crea una nota di esempio con HTML",
|
||||
"setup_sample_created": "È stata creata una nota di esempio come nota secondaria.",
|
||||
"disabled_description": "Queste note di rendering provengono da una fonte esterna. Per proteggerti da contenuti dannosi, non sono abilitate per impostazione predefinita. Assicurati di fidarti della fonte prima di abilitarle.",
|
||||
"disabled_button_enable": "Abilita nota di rendering"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "Pacchetto icone",
|
||||
"type_backend_script": "Script di backend",
|
||||
"type_frontend_script": "Script frontend",
|
||||
"type_widget": "Widget",
|
||||
"type_app_css": "CSS personalizzato",
|
||||
"type_render_note": "Nota di rendering",
|
||||
"type_web_view": "Visualizzazione web",
|
||||
"type_app_theme": "Tema personalizzato",
|
||||
"toggle_tooltip_enable_tooltip": "Clicca per abilitare questa funzione {{type}}.",
|
||||
"toggle_tooltip_disable_tooltip": "Clicca per disattivare questa funzione {{type}}.",
|
||||
"menu_docs": "Documentazione aperta",
|
||||
"menu_execute_now": "Esegui lo script ora",
|
||||
"menu_run": "Esegui automaticamente",
|
||||
"menu_run_disabled": "Manualmente",
|
||||
"menu_run_backend_startup": "Quando il backend si avvia",
|
||||
"menu_run_hourly": "Ogni ora",
|
||||
"menu_run_daily": "Giornaliero",
|
||||
"menu_run_frontend_startup": "Quando si avvia il frontend desktop",
|
||||
"menu_run_mobile_startup": "Quando si avvia il frontend mobile",
|
||||
"menu_change_to_widget": "Passa al widget",
|
||||
"menu_change_to_frontend_script": "Modifica allo script frontend",
|
||||
"menu_theme_base": "Tema base"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "Per saperne di più"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,7 +249,8 @@
|
||||
"reload_app": "リロードして変更を適用する",
|
||||
"set_all_to_default": "すべてのショートカットをデフォルトに戻す",
|
||||
"confirm_reset": "キーボードショートカットをすべてデフォルトにリセットしますか?",
|
||||
"keyboard_shortcuts": "キーボードショートカット"
|
||||
"keyboard_shortcuts": "キーボードショートカット",
|
||||
"no_results": "'{{filter}}' に一致するショートカットが見つかりません"
|
||||
},
|
||||
"confirm": {
|
||||
"confirmation": "確認",
|
||||
@@ -596,7 +597,6 @@
|
||||
"widget": "ウィジェット",
|
||||
"confirm-change": "ノートの内容が空ではない場合、ノートタイプを変更することは推奨されません。続行しますか?",
|
||||
"beta-feature": "Beta",
|
||||
"ai-chat": "AI チャット",
|
||||
"task-list": "タスクリスト",
|
||||
"new-feature": "New",
|
||||
"collections": "コレクション"
|
||||
@@ -826,11 +826,6 @@
|
||||
"error_no_path": "移動するパスがありません。",
|
||||
"move_success_message": "選択したノートは以下に移動されました "
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Web ビュー",
|
||||
"embed_websites": "Web ビュータイプでは、web サイトを Trilium に埋め込むことができます。",
|
||||
"create_label": "まず始めに、埋め込みたいURLアドレスのラベルを作成してください。例: #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "リフレッシュ"
|
||||
},
|
||||
@@ -1287,7 +1282,8 @@
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "指定された検索パラメータに該当するノートは見つかりませんでした。",
|
||||
"search_not_executed": "検索はまだ実行されていません。上の「検索」ボタンをクリックすると、検索結果が表示されます。"
|
||||
"search_not_executed": "検索はまだ実行されていません。",
|
||||
"search_now": "今すぐ検索"
|
||||
},
|
||||
"sql_result": {
|
||||
"no_rows": "このクエリでは行が返されませんでした",
|
||||
@@ -1428,149 +1424,6 @@
|
||||
"content_renderer": {
|
||||
"open_externally": "外部で開く"
|
||||
},
|
||||
"ai_llm": {
|
||||
"title": "AI 設定",
|
||||
"enable_ai_features": "AI/LLM 機能を有効化",
|
||||
"enable_ai_description": "ノートの要約、コンテンツ生成、その他のLLM機能などのAI機能を有効にする",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "AI/LLM 機能を有効化",
|
||||
"enable_ai_desc": "ノートの要約、コンテンツ生成、その他のLLM機能などのAI機能を有効にする",
|
||||
"provider_configuration": "AI プロバイダーの設定",
|
||||
"provider_precedence": "プロバイダーの優先順位",
|
||||
"provider_precedence_description": "カンマで区切られたプロバイダーの優先順位リスト(例: 'openai,anthropic,ollama')",
|
||||
"temperature_description": "応答のランダム性を制御する(0 = 決定的、2 = 最大ランダム性)",
|
||||
"system_prompt_description": "すべてのAIとの対話に使用されるデフォルトのシステムプロンプト",
|
||||
"system_prompt": "システムプロンプト",
|
||||
"openai_configuration": "OpenAIの設定",
|
||||
"openai_settings": "OpenAIの設定",
|
||||
"api_key": "APIキー",
|
||||
"model": "モデル",
|
||||
"openai_api_key_description": "OpenAIのAIサービスにアクセスするためのAPIキー",
|
||||
"anthropic_api_key_description": "AnthropicのClaudeモデルにアクセスするためのAPIキー",
|
||||
"default_model": "デフォルトモデル",
|
||||
"openai_model_description": "例: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"openai_url_description": "デフォルト: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Anthropicの設定",
|
||||
"anthropic_model_description": "チャット補完用のAnthropic Claudeモデル",
|
||||
"voyage_settings": "Voyage AIの設定",
|
||||
"ollama_settings": "Ollamaの設定",
|
||||
"ollama_url_description": "Ollama API の URL(デフォルト: http://localhost:11434)",
|
||||
"anthropic_url_description": "Anthropic APIのベースURL(デフォルト: https://api.anthropic.com)",
|
||||
"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": "ローカルAIモデルを利用するためOllamaを有効にする",
|
||||
"ollama_url": "Ollama URL",
|
||||
"ollama_model": "Ollamaモデル",
|
||||
"refresh_models": "モデルを更新",
|
||||
"refreshing_models": "更新中...",
|
||||
"error": "エラー",
|
||||
"retry": "再試行",
|
||||
"partial": "{{ percentage }}%完了",
|
||||
"processing": "処理中({{percentage}}%)",
|
||||
"complete": "完了(100%)",
|
||||
"refreshing": "更新中...",
|
||||
"auto_refresh_notice": "{{seconds}}秒ごとに自動更新",
|
||||
"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": "処理中...",
|
||||
"loading": "読み込み中...",
|
||||
"generating": "生成中...",
|
||||
"thinking": "考え中..."
|
||||
},
|
||||
"name": "AI",
|
||||
"openai": "OpenAI",
|
||||
"error_contacting_provider": "AIプロバイダーへの接続中にエラーが発生しました。設定とインターネット接続をご確認ください。",
|
||||
"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_description": "チャットおよび補完機能のAIプロバイダーを選択する",
|
||||
"selected_provider": "プロバイダーを選択",
|
||||
"select_model": "モデルを選択...",
|
||||
"select_provider": "プロバイダーを選択...",
|
||||
"not_started": "開始されていません",
|
||||
"processed_notes": "処理済みノート",
|
||||
"total_notes": "ノートの総数",
|
||||
"progress": "進行状況",
|
||||
"queued_notes": "キューに登録されたノート",
|
||||
"failed_notes": "失敗したノート",
|
||||
"last_processed": "最終処理日時",
|
||||
"refresh_stats": "統計情報を更新",
|
||||
"temperature": "Temperature(温度)",
|
||||
"url": "ベースURL",
|
||||
"base_url": "ベースURL",
|
||||
"enable_automatic_indexing": "自動インデックス作成を有効にする",
|
||||
"rebuild_index": "インデックスの再構築",
|
||||
"rebuild_index_error": "インデックスの再構築開始時にエラーが発生しました。詳細はログをご確認ください。",
|
||||
"note_title": "ノートのタイトル",
|
||||
"last_attempt": "最終試行日時",
|
||||
"actions": "アクション",
|
||||
"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": "なし",
|
||||
"incomplete": "未完了 ({{percentage}}%)",
|
||||
"note_queued_for_retry": "ノートが再試行キューに追加されました",
|
||||
"failed_to_retry_note": "ノートの再試行に失敗しました",
|
||||
"all_notes_queued_for_retry": "失敗したすべてのノートは再試行のためにキューに入れられました",
|
||||
"failed_to_retry_all": "ノートの再試行に失敗しました",
|
||||
"use_enhanced_context": "拡張されたコンテキストを使用する",
|
||||
"enhanced_context_description": "ノートとその関連ノートからより多くのコンテキストをAIに提供し、より良い応答を実現します",
|
||||
"show_thinking": "思考を表示",
|
||||
"show_thinking_description": "AIの思考プロセスをチェーン表示",
|
||||
"enter_message": "メッセージを入力...",
|
||||
"error_generating_response": "AI応答の生成中にエラーが発生しました",
|
||||
"index_all_notes": "すべてのノートをインデックスに登録",
|
||||
"index_status": "インデックスのステータス",
|
||||
"indexed_notes": "インデックス登録済みのノート",
|
||||
"indexing_stopped": "インデックス登録を停止しました",
|
||||
"indexing_in_progress": "インデックス登録中です...",
|
||||
"last_indexed": "最終インデックス作成日時",
|
||||
"note_chat": "ノートチャット",
|
||||
"sources": "ソース",
|
||||
"start_indexing": "インデックス作成を開始",
|
||||
"use_advanced_context": "高度なコンテキストを使用",
|
||||
"ai_enabled": "AI 機能が有効",
|
||||
"ai_disabled": "AI 機能が無効",
|
||||
"no_models_found_online": "モデルが見つかりません。API キーと設定を確認してください。",
|
||||
"no_models_found_ollama": "Ollama モデルが見つかりません。Ollama が実行中かどうかを確認してください。",
|
||||
"error_fetching": "モデルの取得エラー: {{error}}"
|
||||
},
|
||||
"add_label": {
|
||||
"add_label": "ラベルを追加",
|
||||
"label_name_placeholder": "ラベル名",
|
||||
@@ -1864,10 +1717,6 @@
|
||||
"protecting-title": "保護の状態",
|
||||
"unprotecting-title": "保護解除の状態"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "このヘルプノートが表示されるのは、このノートの「HTML のレンダリング」タイプには、正常に機能するために必要なリレーションがないためです。",
|
||||
"note_detail_render_help_2": "レンダリングHTMLノートタイプは、<a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">スクリプティング</a>に使用されます。簡単に言うと、HTMLコードノート(オプションでJavaScriptを含む)があり、このノートがそれをレンダリングします。これを動作させるには、レンダリングするHTMLノートを指す「renderNote」という<a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">リレーション</a>を定義する必要があります。"
|
||||
},
|
||||
"consistency_checks": {
|
||||
"find_and_fix_button": "一貫性の問題を見つけて修正する",
|
||||
"finding_and_fixing_message": "一貫性の問題を見つけて修正中…",
|
||||
@@ -1959,7 +1808,9 @@
|
||||
"print_report_title": "レポートを印刷",
|
||||
"print_report_collection_content_other": "コレクション内の {{count}} 件のノートは、サポートされていないか保護されているため、印刷できませんでした。",
|
||||
"print_report_collection_details_button": "詳細を見る",
|
||||
"print_report_collection_details_ignored_notes": "無視されたノート"
|
||||
"print_report_collection_details_ignored_notes": "無視されたノート",
|
||||
"print_report_error_title": "印刷に失敗しました",
|
||||
"print_report_stack_trace": "スタックトレース"
|
||||
},
|
||||
"watched_file_update_status": {
|
||||
"ignore_this_change": "この変更を無視する",
|
||||
@@ -2042,7 +1893,8 @@
|
||||
"show-scale": "スケールを表示",
|
||||
"raster": "Raster",
|
||||
"vector_light": "Vector(ライト)",
|
||||
"vector_dark": "Vector (ダーク)"
|
||||
"vector_dark": "Vector (ダーク)",
|
||||
"show-labels": "マーカー名を表示"
|
||||
},
|
||||
"call_to_action": {
|
||||
"next_theme_title": "新しいTriliumテーマをお試しください",
|
||||
@@ -2070,8 +1922,9 @@
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "{{startIndex}} - {{endIndex}} ページ",
|
||||
"total_notes": "{{count}} ノート"
|
||||
"total_notes": "{{count}} ノート",
|
||||
"prev_page": "前のページ",
|
||||
"next_page": "次のページ"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "エラーのためコンテンツを表示できません。"
|
||||
@@ -2099,7 +1952,7 @@
|
||||
"no_attachments": "このノートには添付ファイルはありません。"
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "このコレクションには子ノートがないため、表示するものがありません。詳細は<a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a>をご覧ください。",
|
||||
"no_children_help": "このコレクションには子ノートがないため、表示するものがありません。",
|
||||
"drag_locked_title": "編集をロック中",
|
||||
"drag_locked_message": "コレクションは編集がロックされているため、ドラッグは許可されていません。"
|
||||
},
|
||||
@@ -2268,5 +2121,49 @@
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "ブックマーク"
|
||||
},
|
||||
"web_view_setup": {
|
||||
"title": "Trilium に直接 Web ページのライブビューを作成",
|
||||
"url_placeholder": "Web サイトのアドレスを入力または貼り付けて下さい。 例: https://triliumnotes.org",
|
||||
"create_button": "Web ビューを作成",
|
||||
"invalid_url_title": "無効なアドレス",
|
||||
"invalid_url_message": "有効な Web アドレスを入力してください。 例: https://triliumnotes.org",
|
||||
"disabled_description": "この Web ビューは外部ソースからインポートされました。フィッシングや悪意のあるコンテンツから保護するため、自動的には読み込まれません。ソースを信頼できる場合は、有効にすることができます。",
|
||||
"disabled_button_enable": "Web ビューを有効"
|
||||
},
|
||||
"render": {
|
||||
"setup_title": "このノート内にカスタム HTML または Preact JSX を表示",
|
||||
"setup_create_sample_preact": "Preact でサンプルノートを作成",
|
||||
"setup_create_sample_html": "HTML でサンプルノートを作成",
|
||||
"setup_sample_created": "子ノートとしてサンプルノートが作成されました。",
|
||||
"disabled_description": "このレンダリングノートは外部ソースから提供されています。悪意のあるコンテンツからユーザーを保護するため、デフォルトでは有効になっていません。有効にする前に、ソースが信頼できるかどうかをご確認ください。",
|
||||
"disabled_button_enable": "レンダリングノートを有効"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "アイコンパック",
|
||||
"type_backend_script": "バックエンドスクリプト",
|
||||
"type_frontend_script": "フロントエンドスクリプト",
|
||||
"type_widget": "ウィジェット",
|
||||
"type_app_css": "カスタム CSS",
|
||||
"type_render_note": "レンダリングノート",
|
||||
"type_web_view": "Web ビュー",
|
||||
"type_app_theme": "カスタムテーマ",
|
||||
"toggle_tooltip_enable_tooltip": "この {{type}} を有効にするにはクリックしてください。",
|
||||
"toggle_tooltip_disable_tooltip": "この {{type}} を無効にするにはクリックしてください。",
|
||||
"menu_docs": "ドキュメントを開く",
|
||||
"menu_execute_now": "今すぐスクリプトを実行",
|
||||
"menu_run": "自動で実行",
|
||||
"menu_run_disabled": "手動で実行",
|
||||
"menu_run_backend_startup": "バックエンドの起動時",
|
||||
"menu_run_hourly": "毎時",
|
||||
"menu_run_daily": "毎日",
|
||||
"menu_run_frontend_startup": "デスクトップ フロントエンドの起動時",
|
||||
"menu_run_mobile_startup": "モバイル フロントエンドの起動時",
|
||||
"menu_change_to_widget": "ウィジェットの変更",
|
||||
"menu_change_to_frontend_script": "フロントエンドスクリプトの変更",
|
||||
"menu_theme_base": "テーマベース"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "さらに詳しく"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,17 @@
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "사용자 정의 스크립트를 불러오는데 실패했습니다",
|
||||
"message": "ID가 \"{{id}}\"고, 제목이 \"{{title}}\"인 노트에서 스크립트가 실행되지 못했습니다:\n\n{{message}}"
|
||||
}
|
||||
"message": "다음 이유로 인해 스크립트가 실행되지 못했습니다:\n\n{{message}}"
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "서버에서 위젯 목록을 가져오는 데 실패했습니다"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "사용자 정의 React 위젯을 렌더링하는 데 실패했습니다"
|
||||
},
|
||||
"widget-missing-parent": "사용자 정의 위젯에 필수 속성 '{{property}}'가 정의되어 있지 않습니다.\n\n이 스크립트를 UI 요소 없이 실행하려면 '#run=frontendStartup'을 대신 사용하십시오.",
|
||||
"open-script-note": "스크립트 노트 열기",
|
||||
"scripting-error": "사용자 지정 스크립트 오류: {{title}}"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "링크 추가",
|
||||
@@ -41,7 +50,8 @@
|
||||
"prefix": "접두사: ",
|
||||
"branch_prefix_saved": "브랜치 접두사가 저장되었습니다.",
|
||||
"edit_branch_prefix_multiple": "{{count}}개의 지점 접두사 편집",
|
||||
"branch_prefix_saved_multiple": "{{count}}개의 지점에 대해 지점 접두사가 저장되었습니다."
|
||||
"branch_prefix_saved_multiple": "{{count}}개의 지점에 대해 지점 접두사가 저장되었습니다.",
|
||||
"affected_branches": "영향을 받는 브랜치 수 ({{count}}):"
|
||||
},
|
||||
"bulk_actions": {
|
||||
"bulk_actions": "대량 작업",
|
||||
@@ -64,10 +74,66 @@
|
||||
"first-week-contains-first-day": "첫 번째 주에는 올해의 첫날이 포함됩니다"
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "~로 노트 복제",
|
||||
"clone_notes_to": "노트 클론하기...",
|
||||
"help_on_links": "링크에 대한 도움말",
|
||||
"notes_to_clone": "노트 클론 생성",
|
||||
"target_parent_note": "부모 노트 타겟",
|
||||
"search_for_note_by_its_name": "이름으로 노트 검색하기"
|
||||
"search_for_note_by_its_name": "이름으로 노트 검색하기",
|
||||
"no_path_to_clone_to": "클론할 경로가 존재하지 않습니다.",
|
||||
"note_cloned": "노트 \"{{clonedTitle}}\"이(가) \"{{targetTitle}}\"로 클론되었습니다",
|
||||
"cloned_note_prefix_title": "클론된 노트는 지정된 접두사와 함께 노트 트리에 표시됩니다",
|
||||
"prefix_optional": "접두사 (선택 사항)",
|
||||
"clone_to_selected_note": "선택한 노트에 클론"
|
||||
},
|
||||
"confirm": {
|
||||
"confirmation": "확인",
|
||||
"cancel": "취소",
|
||||
"ok": "OK",
|
||||
"are_you_sure_remove_note": "관계 맵에서 \"{{title}}\" 노트를 정말로 제거하시겠습니까? ",
|
||||
"if_you_dont_check": "이 항목을 선택하지 않으면 해당 노트는 관계 맵에서만 제거됩니다.",
|
||||
"also_delete_note": "노트를 함께 삭제"
|
||||
},
|
||||
"delete_notes": {
|
||||
"erase_notes_description": "일반(소프트) 삭제는 메모를 삭제된 것으로 표시하는 것일 뿐이며, 일정 시간 동안 (최근 변경 내용 대화 상자에서) 복구할 수 있습니다. 이 옵션을 선택하면 메모가 즉시 삭제되며 복구할 수 없습니다.",
|
||||
"erase_notes_warning": "모든 복제본을 포함하여 메모를 영구적으로 삭제합니다(이 작업은 되돌릴 수 없습니다). 애플리케이션이 다시 시작됩니다.",
|
||||
"notes_to_be_deleted": "다음 노트가 삭제됩니다 ({{notesCount}})",
|
||||
"no_note_to_delete": "삭제되는 노트가 없습니다 (클론만 삭제됩니다).",
|
||||
"broken_relations_to_be_deleted": "다음 관계가 끊어지고 삭제됩니다({{ relationCount}})",
|
||||
"cancel": "취소",
|
||||
"ok": "OK",
|
||||
"deleted_relation_text": "삭제 예정인 노트 {{- note}} (은)는 {{- source}}에서 시작된 관계 {{- relation}}에 의해 참조되고 있습니다.",
|
||||
"delete_notes_preview": "노트 미리보기 삭제",
|
||||
"close": "닫기",
|
||||
"delete_all_clones_description": "모든 복제본 삭제(최근 변경 사항에서 되돌릴 수 있습니다)"
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "노트 내보내기",
|
||||
"export_type_single": "이 노트에만 해당(후손 노트를 포함하지 않음)",
|
||||
"export": "내보내기",
|
||||
"choose_export_type": "내보내기 타입을 선택해 주세요",
|
||||
"export_status": "상태 내보내기",
|
||||
"export_in_progress": "내보내기 진행 중: {{progressCount}}",
|
||||
"export_finished_successfully": "내보내기를 성공적으로 완료했습니다.",
|
||||
"format_pdf": "PDF - 인쇄 또는 공유용",
|
||||
"share-format": "웹 게시용 HTML - 공유 노트에 사용되는 것과 동일한 테마를 사용하지만 정적 웹사이트로 게시할 수 있습니다.",
|
||||
"close": "닫기",
|
||||
"export_type_subtree": "이 노트와 모든 후손 노트",
|
||||
"format_html": "HTML - 모든 형식 유지됨, 권장",
|
||||
"format_html_zip": "HTML(ZIP 아카이브) - 모든 서식이 유지됨, 권장.",
|
||||
"format_markdown": "마크다운 - 대부분의 서식이 유지됩니다.",
|
||||
"format_opml": "OPML은 텍스트 전용 아웃라이너 교환 형식입니다. 서식, 이미지 및 파일은 포함되지 않습니다.",
|
||||
"opml_version_1": "OPML v1.0 - 일반 텍스트만",
|
||||
"opml_version_2": "OPML v2.0 - HTML 지원"
|
||||
},
|
||||
"help": {
|
||||
"title": "치트 시트",
|
||||
"editShortcuts": "키보드 단축키 편집",
|
||||
"noteNavigation": "노트 내비게이션",
|
||||
"goUpDown": "노트 목록에서 위/아래로 이동",
|
||||
"collapseExpand": "노트 접기/펼치기",
|
||||
"notSet": "미설정",
|
||||
"goBackForwards": "히스토리에서 뒤로/앞으로 이동",
|
||||
"showJumpToNoteDialog": "<a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"노트로 이동\" 대화 상자</a> 표시",
|
||||
"scrollToActiveNote": "활성화된 노트로 스크롤 이동"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,7 +261,6 @@
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Strona {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} notatek"
|
||||
},
|
||||
"collections": {
|
||||
@@ -774,149 +773,6 @@
|
||||
"target_note": "notatka docelowa",
|
||||
"create_relation_on_all_matched_notes": "Na wszystkich dopasowanych notatkach utwórz podaną relację."
|
||||
},
|
||||
"ai_llm": {
|
||||
"actions": "Akcje",
|
||||
"retry": "Ponów",
|
||||
"partial": "{{ percentage }}% ukończono",
|
||||
"retry_queued": "Notatka zakolejkowana do ponowienia",
|
||||
"retry_failed": "Nie udało się zakolejkować notatki do ponowienia",
|
||||
"max_notes_per_llm_query": "Maks. notatek na zapytanie",
|
||||
"index_all_notes": "Indeksuj wszystkie notatki",
|
||||
"index_status": "Status indeksu",
|
||||
"indexed_notes": "Zaindeksowane notatki",
|
||||
"indexing_stopped": "Indeksowanie zatrzymane",
|
||||
"indexing_in_progress": "Indeksowanie w toku...",
|
||||
"last_indexed": "Ostatnio zaindeksowane",
|
||||
"note_chat": "Czat notatki",
|
||||
"note_title": "Tytuł notatki",
|
||||
"error": "Błąd",
|
||||
"last_attempt": "Ostatnia próba",
|
||||
"queued_notes": "Notatki w kolejce",
|
||||
"failed_notes": "Notatki nieudane",
|
||||
"last_processed": "Ostatnio przetworzone",
|
||||
"refresh_stats": "Odśwież statystyki",
|
||||
"enable_ai_features": "Włącz funkcje AI/LLM",
|
||||
"enable_ai_description": "Włącz funkcje AI, takie jak podsumowywanie notatek, generowanie treści i inne możliwości LLM",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Włącz funkcje AI/LLM",
|
||||
"enable_ai_desc": "Włącz funkcje AI, takie jak podsumowywanie notatek, generowanie treści i inne możliwości LLM",
|
||||
"provider_configuration": "Konfiguracja dostawcy AI",
|
||||
"provider_precedence": "Kolejność dostawców",
|
||||
"provider_precedence_description": "Lista dostawców oddzielona przecinkami w kolejności pierwszeństwa (np. 'openai,anthropic,ollama')",
|
||||
"temperature": "Temperatura",
|
||||
"temperature_description": "Kontroluje losowość w odpowiedziach (0 = deterministyczne, 2 = maksymalna losowość)",
|
||||
"system_prompt": "Prompt systemowy",
|
||||
"system_prompt_description": "Domyślny prompt systemowy używany dla wszystkich interakcji AI",
|
||||
"openai_configuration": "Konfiguracja OpenAI",
|
||||
"openai_settings": "Ustawienia OpenAI",
|
||||
"api_key": "Klucz API",
|
||||
"url": "Bazowy URL",
|
||||
"model": "Model",
|
||||
"openai_api_key_description": "Twój klucz API OpenAI do dostępu do ich usług AI",
|
||||
"anthropic_api_key_description": "Twój klucz API Anthropic do dostępu do modeli Claude",
|
||||
"default_model": "Domyślny model",
|
||||
"openai_model_description": "Przykłady: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "Bazowy URL",
|
||||
"openai_url_description": "Domyślnie: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Ustawienia Anthropic",
|
||||
"anthropic_url_description": "Bazowy URL dla API Anthropic (domyślnie: https://api.anthropic.com)",
|
||||
"anthropic_model_description": "Modele Anthropic Claude do czatu",
|
||||
"voyage_settings": "Ustawienia Voyage AI",
|
||||
"ollama_settings": "Ustawienia Ollama",
|
||||
"ollama_url_description": "URL dla API Ollama (domyślnie: http://localhost:11434)",
|
||||
"ollama_model_description": "Model Ollama do użycia w czacie",
|
||||
"anthropic_configuration": "Konfiguracja Anthropic",
|
||||
"voyage_configuration": "Konfiguracja Voyage AI",
|
||||
"voyage_url_description": "Domyślnie: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Konfiguracja Ollama",
|
||||
"enable_ollama": "Włącz Ollama",
|
||||
"enable_ollama_description": "Włącz Ollama do lokalnego użycia modeli AI",
|
||||
"ollama_url": "URL Ollama",
|
||||
"ollama_model": "Model Ollama",
|
||||
"refresh_models": "Odśwież modele",
|
||||
"refreshing_models": "Odświeżanie...",
|
||||
"enable_automatic_indexing": "Włącz automatyczne indeksowanie",
|
||||
"rebuild_index": "Przebuduj indeks",
|
||||
"rebuild_index_error": "Błąd podczas rozpoczynania przebudowy indeksu. Sprawdź logi po szczegóły.",
|
||||
"max_notes_per_llm_query_description": "Maksymalna liczba podobnych notatek do uwzględnienia w kontekście AI",
|
||||
"active_providers": "Aktywni dostawcy",
|
||||
"disabled_providers": "Wyłączeni dostawcy",
|
||||
"remove_provider": "Usuń dostawcę z wyszukiwania",
|
||||
"restore_provider": "Przywróć dostawcę do wyszukiwania",
|
||||
"similarity_threshold": "Próg podobieństwa",
|
||||
"not_started": "Nie rozpoczęto",
|
||||
"title": "Ustawienia AI",
|
||||
"processed_notes": "Przetworzone notatki",
|
||||
"total_notes": "Łącznie notatek",
|
||||
"progress": "Postęp",
|
||||
"similarity_threshold_description": "Minimalny wynik podobieństwa (0-1) dla notatek, które mają być uwzględnione w kontekście zapytań LLM",
|
||||
"reprocess_index": "Przebuduj indeks wyszukiwania",
|
||||
"reprocessing_index": "Przebudowywanie...",
|
||||
"reprocess_index_started": "Optymalizacja indeksu wyszukiwania rozpoczęta w tle",
|
||||
"reprocess_index_error": "Błąd podczas przebudowy indeksu wyszukiwania",
|
||||
"index_rebuild_progress": "Postęp przebudowy indeksu",
|
||||
"index_rebuilding": "Optymalizacja indeksu ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Optymalizacja indeksu zakończona",
|
||||
"index_rebuild_status_error": "Błąd podczas sprawdzania statusu przebudowy indeksu",
|
||||
"never": "Nigdy",
|
||||
"processing": "Przetwarzanie ({{percentage}}%)",
|
||||
"incomplete": "Niekompletne ({{percentage}}%)",
|
||||
"complete": "Zakończone (100%)",
|
||||
"refreshing": "Odświeżanie...",
|
||||
"auto_refresh_notice": "Automatyczne odświeżanie co {{seconds}} sekund",
|
||||
"note_queued_for_retry": "Notatka zakolejkowana do ponowienia",
|
||||
"failed_to_retry_note": "Nie udało się ponowić notatki",
|
||||
"all_notes_queued_for_retry": "Wszystkie nieudane notatki zakolejkowane do ponowienia",
|
||||
"failed_to_retry_all": "Nie udało się ponowić notatek",
|
||||
"ai_settings": "Ustawienia AI",
|
||||
"api_key_tooltip": "Klucz API do dostępu do usługi",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "Klucz API Anthropic jest pusty. Proszę wprowadzić poprawny klucz API.",
|
||||
"openai": "Klucz API OpenAI jest pusty. Proszę wprowadzić poprawny klucz API.",
|
||||
"voyage": "Klucz API Voyage jest pusty. Proszę wprowadzić poprawny klucz API.",
|
||||
"ollama": "Klucz API Ollama jest pusty. Proszę wprowadzić poprawny klucz API."
|
||||
},
|
||||
"agent": {
|
||||
"processing": "Przetwarzanie...",
|
||||
"thinking": "Myślę...",
|
||||
"loading": "Ładowanie...",
|
||||
"generating": "Generowanie..."
|
||||
},
|
||||
"name": "AI",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Użyj rozszerzonego kontekstu",
|
||||
"enhanced_context_description": "Dostarcza AI więcej kontekstu z notatki i jej powiązanych notatek dla lepszych odpowiedzi",
|
||||
"show_thinking": "Pokaż proces myślenia",
|
||||
"show_thinking_description": "Pokaż ciąg myślowy AI",
|
||||
"enter_message": "Wpisz swoją wiadomość...",
|
||||
"error_contacting_provider": "Błąd połączenia z dostawcą AI. Sprawdź swoje ustawienia i połączenie internetowe.",
|
||||
"error_generating_response": "Błąd generowania odpowiedzi AI",
|
||||
"sources": "Źródła",
|
||||
"start_indexing": "Rozpocznij indeksowanie",
|
||||
"use_advanced_context": "Użyj zaawansowanego kontekstu",
|
||||
"ollama_no_url": "Ollama nie jest skonfigurowana. Proszę wprowadzić poprawny URL.",
|
||||
"chat": {
|
||||
"root_note_title": "Czaty AI",
|
||||
"root_note_content": "Ta notatka zawiera twoje zapisane rozmowy czatu AI.",
|
||||
"new_chat_title": "Nowy czat",
|
||||
"create_new_ai_chat": "Utwórz nowy czat AI"
|
||||
},
|
||||
"create_new_ai_chat": "Utwórz nowy czat AI",
|
||||
"configuration_warnings": "Istnieją pewne problemy z twoją konfiguracją AI. Proszę sprawdzić ustawienia.",
|
||||
"experimental_warning": "Funkcja LLM jest obecnie eksperymentalna - zostałeś ostrzeżony.",
|
||||
"selected_provider": "Wybrany dostawca",
|
||||
"selected_provider_description": "Wybierz dostawcę AI dla funkcji czatu i uzupełniania",
|
||||
"select_model": "Wybierz model...",
|
||||
"select_provider": "Wybierz dostawcę...",
|
||||
"ai_enabled": "Funkcje AI włączone",
|
||||
"ai_disabled": "Funkcje AI wyłączone",
|
||||
"no_models_found_online": "Nie znaleziono modeli. Proszę sprawdzić klucz API i ustawienia.",
|
||||
"no_models_found_ollama": "Nie znaleziono modeli Ollama. Proszę sprawdzić, czy Ollama jest uruchomiona.",
|
||||
"error_fetching": "Błąd pobierania modeli: {{error}}"
|
||||
},
|
||||
"prompt": {
|
||||
"title": "Monit",
|
||||
"ok": "OK",
|
||||
@@ -1432,15 +1288,6 @@
|
||||
"default_new_note_title": "nowa notatka",
|
||||
"click_on_canvas_to_place_new_note": "Kliknij na płótnie, aby umieścić nową notatkę"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Ta notatka pomocy jest wyświetlana, ponieważ ta notatka typu Render HTML nie ma wymaganej relacji do poprawnego działania.",
|
||||
"note_detail_render_help_2": "Typ notatki Render HTML jest używany do <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">skryptowania</a>. W skrócie, masz notatkę kodu HTML (opcjonalnie z JavaScript) i ta notatka ją wyrenderuje. Aby to zadziałało, musisz zdefiniować <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">relację</a> o nazwie \"renderNote\" wskazującą na notatkę HTML do wyrenderowania."
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Widok WWW",
|
||||
"embed_websites": "Notatka typu Widok WWW pozwala na osadzanie stron internetowych w Trilium.",
|
||||
"create_label": "Aby rozpocząć, utwórz etykietę z adresem URL, który chcesz osadzić, np. #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Odśwież"
|
||||
},
|
||||
|
||||
@@ -1064,15 +1064,6 @@
|
||||
"default_new_note_title": "nova nota",
|
||||
"click_on_canvas_to_place_new_note": "Clique no quadro para incluir uma nova nota"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Esta nota de ajuda é mostrada porque esta nota do tipo Renderizar HTML não possui a relação necessária para funcionar corretamente.",
|
||||
"note_detail_render_help_2": "O tipo de nota Renderizar HTML é usado para <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">automação</a>. Em suma, tem uma nota de código HTML (opcionalmente com algum JavaScript) e esta nota irá renderizá-la. Para fazê-lo funcionar, deve definir uma <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">relação</a> chamada \"renderNote\" que aponta para a nota HTML a ser renderizada."
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Web View",
|
||||
"embed_websites": "Nota do tipo Visualização Web permite que incorpore sites no Trilium.",
|
||||
"create_label": "Para começar, crie uma etiqueta com um endereço URL que deseja incorporar, por exemplo, #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Recarregar"
|
||||
},
|
||||
@@ -1188,149 +1179,6 @@
|
||||
"enable-smooth-scroll": "Activar deslocamento suave",
|
||||
"app-restart-required": "(é necessário reiniciar a aplicação para aplicar as alterações)"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Não iniciado",
|
||||
"title": "Configurações de IA",
|
||||
"processed_notes": "Notas Processadas",
|
||||
"total_notes": "Total de Notas",
|
||||
"progress": "Andamento",
|
||||
"queued_notes": "Notas Enfileiradas",
|
||||
"failed_notes": "Notas com Falha",
|
||||
"last_processed": "Últimas Processadas",
|
||||
"refresh_stats": "Atualizar Estatísticas",
|
||||
"enable_ai_features": "Ativar recurso IA/LLM",
|
||||
"enable_ai_description": "Ativar recursos IA como sumarização de notas, geração de conteúdo e outras capacidades de LLM",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Ativar recursos IA/LLM",
|
||||
"enable_ai_desc": "Ativar recursos de IA como sumarização de notas, geração de conteúdo e outras capacidades de LLM",
|
||||
"provider_configuration": "Configuração de Provedor de IA",
|
||||
"provider_precedence": "Prioridade de provedor",
|
||||
"provider_precedence_description": "Lista de provedores em ordem de prioridade, separados por vírgula (por exemplo, 'openai, anthropic, ollama')",
|
||||
"temperature": "Temperatura",
|
||||
"temperature_description": "Controla a aleatoriedade em respostas (0 = determinística, 2 = aleatoriedade máxima)",
|
||||
"system_prompt": "Prompt de Sistema",
|
||||
"system_prompt_description": "Prompt padrão de sistema usado para todas as interações de IA",
|
||||
"openai_configuration": "Configuração OpenAI",
|
||||
"openai_settings": "Opções OpenAI",
|
||||
"api_key": "Chave de API",
|
||||
"url": "URL Base",
|
||||
"model": "Modelo",
|
||||
"openai_api_key_description": "A sua API Key da OpenAI para aceder os serviços de IA",
|
||||
"anthropic_api_key_description": "A sua API Key da Anthropic para aceder os modelos Claude",
|
||||
"default_model": "Modelo Padrão",
|
||||
"openai_model_description": "Exemplos: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "URL Base",
|
||||
"openai_url_description": "Padrão: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Configurações Anthropic",
|
||||
"anthropic_url_description": "URL Base da API Anthropic (padrão: https://api.anthropic.com)",
|
||||
"anthropic_model_description": "Modelos Claude da Anthropic para completar conversas",
|
||||
"voyage_settings": "Configurações Voyage AI",
|
||||
"ollama_settings": "Configurações do Ollama",
|
||||
"ollama_url_description": "URL para a API Ollama (padrão: http://localhost:11434)",
|
||||
"ollama_model_description": "Modelo Ollama usado para complementação de chat",
|
||||
"anthropic_configuration": "Configuração da Anthropic",
|
||||
"voyage_configuration": "Configuração da Voyage IA",
|
||||
"voyage_url_description": "Padrão: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Configuração da Ollama",
|
||||
"enable_ollama": "Ativar Ollama",
|
||||
"enable_ollama_description": "Ativar Ollama para uso do modelo local de IA",
|
||||
"ollama_url": "URL da Ollama",
|
||||
"ollama_model": "Modelo do Ollama",
|
||||
"refresh_models": "Atualizar Modelos",
|
||||
"refreshing_models": "A atualizar…",
|
||||
"enable_automatic_indexing": "Ativar indexação automática",
|
||||
"rebuild_index": "Reconstruir Índice",
|
||||
"rebuild_index_error": "Ocorreu um erro ao iniciar a reconstrução do índice. Verifique os logs para obter pormenores.",
|
||||
"note_title": "Título da nota",
|
||||
"error": "Erro",
|
||||
"last_attempt": "Última Tentativa",
|
||||
"actions": "Ações",
|
||||
"retry": "Tentar novamente",
|
||||
"partial": "{{ percentage }}% concluído",
|
||||
"retry_queued": "Nota enfileirada para nova tentativa",
|
||||
"retry_failed": "Falha ao enfileirar nota para nova tentativa",
|
||||
"max_notes_per_llm_query": "Máximo de Notas por Consulta",
|
||||
"max_notes_per_llm_query_description": "Quantidade máxima de notas similares para incluir no contexto da IA",
|
||||
"active_providers": "Provedores Ativos",
|
||||
"disabled_providers": "Provedores Desativados",
|
||||
"remove_provider": "Remover provedor da pesquisa",
|
||||
"restore_provider": "Restaurar provedor na pesquisa",
|
||||
"similarity_threshold": "Tolerância de Similaridade",
|
||||
"similarity_threshold_description": "Pontuação máxima de similaridade (0-1) para notas a serem incluídas no contexto das consultas de LLM",
|
||||
"reprocess_index": "Reconstruir Índice de Pesquisa",
|
||||
"reprocessing_index": "A reconstruir…",
|
||||
"reprocess_index_started": "Otimiação do índice de pesquisa iniciado em plano de fundo",
|
||||
"reprocess_index_error": "Erro ao reconstruir índice de pesquisa",
|
||||
"index_rebuild_progress": "Andamento da Reconstrução do Índice",
|
||||
"index_rebuilding": "A otimizar índice ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Otimização de índice finalizada",
|
||||
"index_rebuild_status_error": "Erro ao verificar o estado da reconstrução do índice",
|
||||
"never": "Nunca",
|
||||
"processing": "A processar ({{percentage}}%)",
|
||||
"incomplete": "Incompleto ({{percentage}}%)",
|
||||
"complete": "Completo (100%)",
|
||||
"refreshing": "A atualizar…",
|
||||
"auto_refresh_notice": "A atualizar automaticamente a cada {{seconds}} segundos",
|
||||
"note_queued_for_retry": "Nota enfileirada para nova tentativa",
|
||||
"failed_to_retry_note": "Falha ao retentar nota",
|
||||
"all_notes_queued_for_retry": "Todas as notas com falha enfileiradas para nova tentativa",
|
||||
"failed_to_retry_all": "Falha ao retentar notas",
|
||||
"ai_settings": "Configurações IA",
|
||||
"api_key_tooltip": "Chave de API para aceder o serviço",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "A chave de API Anthropic está vazia. Por favor, digite uma chave de API válida.",
|
||||
"openai": "A chave de API OpenAI está vazia. Por favor, digite uma chave de API válida.",
|
||||
"voyage": "A chave de API da Voyage API está vazia. Por favor, digite uma chave de API válida.",
|
||||
"ollama": "A chave de API da Ollama API está vazia. Por favor, digite uma chave de API válida."
|
||||
},
|
||||
"agent": {
|
||||
"processing": "A processar…",
|
||||
"thinking": "A pensar…",
|
||||
"loading": "A carregar…",
|
||||
"generating": "A gerir…"
|
||||
},
|
||||
"name": "IA",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Usar contexto aprimorado",
|
||||
"enhanced_context_description": "Alimentar IA com mais contexto sobre a nota e as suas notas relacionadas para melhores respostas",
|
||||
"show_thinking": "Exibir pensamento",
|
||||
"show_thinking_description": "Exibir o processo de linha de raciocínio da AI",
|
||||
"enter_message": "Digite a sua mensagem…",
|
||||
"error_contacting_provider": "Erro ao contactar o provedor de IA. Por favor, verifique as suas configurações e a sua conexão à internet.",
|
||||
"error_generating_response": "Erro ao gerar resposta da IA",
|
||||
"index_all_notes": "Indexar Todas as Notas",
|
||||
"index_status": "Estado do Índice",
|
||||
"indexed_notes": "Notas Indexadas",
|
||||
"indexing_stopped": "Indexação interrompida",
|
||||
"indexing_in_progress": "Indexação em andamento…",
|
||||
"last_indexed": "Última Indexada",
|
||||
"note_chat": "Conversa de Nota",
|
||||
"sources": "Origens",
|
||||
"start_indexing": "Iniciar Indexação",
|
||||
"use_advanced_context": "Usar Contexto Avançado",
|
||||
"ollama_no_url": "Ollama não está configurado. Por favor, digite uma URL válida.",
|
||||
"chat": {
|
||||
"root_note_title": "Conversas IA",
|
||||
"root_note_content": "Esta nota contém as suas conversas com IA gravdas.",
|
||||
"new_chat_title": "Nova Conversa",
|
||||
"create_new_ai_chat": "Criar Conversa IA"
|
||||
},
|
||||
"create_new_ai_chat": "Criar Conversa IA",
|
||||
"configuration_warnings": "Há problemas com a sua configuração de IA. Por favor, verifique as suas configurações.",
|
||||
"experimental_warning": "O recurso de LLM atualmente é experimental - você foi avisado.",
|
||||
"selected_provider": "Provedor Selecionado",
|
||||
"selected_provider_description": "Escolha o provedor de IA para conversas e recursos de completar",
|
||||
"select_model": "Selecionar modelo…",
|
||||
"select_provider": "Selecionar provedor…",
|
||||
"ai_enabled": "Recursos de IA ativados",
|
||||
"ai_disabled": "Recursos de IA desativados",
|
||||
"no_models_found_online": "Nenhum modelo encontrado. Por favor, verifique a sua chave de API e as configurações.",
|
||||
"no_models_found_ollama": "Nenhum modelo Ollama encontrado. Por favor, verifique se o Ollama está em execução.",
|
||||
"error_fetching": "Erro ao obter modelos: {{error}}"
|
||||
},
|
||||
"zoom_factor": {
|
||||
"title": "Fator do Zoom (apenas versão de área de trabalho)",
|
||||
"description": "O zoom também pode ser controlado com atalhos CTRL+- e CTRL+=."
|
||||
@@ -1700,7 +1548,6 @@
|
||||
"confirm-change": "Não é recomentado alterar o tipo da nota quando o conteúdo da nota não está vazio. Quer continuar assim mesmo?",
|
||||
"geo-map": "Mapa geográfico",
|
||||
"beta-feature": "Beta",
|
||||
"ai-chat": "Chat IA",
|
||||
"task-list": "Lista de Tarefas",
|
||||
"new-feature": "Novo",
|
||||
"collections": "Coleções"
|
||||
@@ -2174,7 +2021,6 @@
|
||||
"delete_note": "Apagar nota..."
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Página {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} notas"
|
||||
},
|
||||
"collections": {
|
||||
|
||||
@@ -85,149 +85,6 @@
|
||||
"clone_to_selected_note": "Clonar para a nota selecionada",
|
||||
"note_cloned": "A nota \"{{clonedTitle}}\" foi clonada para \"{{targetTitle}}\""
|
||||
},
|
||||
"ai_llm": {
|
||||
"temperature": "Temperatura",
|
||||
"retry_queued": "Nota enfileirada para nova tentativa",
|
||||
"queued_notes": "Notas Enfileiradas",
|
||||
"empty_key_warning": {
|
||||
"voyage": "A chave de API da Voyage API está vazia. Por favor, digite uma chave de API válida.",
|
||||
"ollama": "A chave de API da Ollama API está vazia. Por favor, digite uma chave de API válida.",
|
||||
"anthropic": "A chave de API Anthropic está vazia. Por favor, digite uma chave de API válida.",
|
||||
"openai": "A chave de API OpenAI está vazia. Por favor, digite uma chave de API válida."
|
||||
},
|
||||
"not_started": "Não iniciado",
|
||||
"title": "Configurações de IA",
|
||||
"processed_notes": "Notas Processadas",
|
||||
"total_notes": "Total de Notas",
|
||||
"progress": "Andamento",
|
||||
"failed_notes": "Notas com Falha",
|
||||
"last_processed": "Últimas Processadas",
|
||||
"refresh_stats": "Atualizar Estatísticas",
|
||||
"enable_ai_features": "Ativar recurso IA/LLM",
|
||||
"enable_ai_description": "Ativar recursos IA como sumarização de notas, geração de conteúdo, e outras capacidades de LLM",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"enable_ai": "Ativar recursos IA/LLM",
|
||||
"provider_configuration": "Configuração de Provedor de IA",
|
||||
"system_prompt": "Prompt de Sistema",
|
||||
"system_prompt_description": "Prompt padrão de sistema usado para todas as interações de IA",
|
||||
"openai_configuration": "Configuração OpenAI",
|
||||
"openai_settings": "Opções OpenAI",
|
||||
"api_key": "Chave de API",
|
||||
"url": "URL Base",
|
||||
"model": "Modelo",
|
||||
"openai_api_key_description": "Sua API Key da OpenAI para acessar os serviços de IA",
|
||||
"anthropic_api_key_description": "Sua API Key da Anthropic para acessar os modelos Claude",
|
||||
"default_model": "Modelo Padrão",
|
||||
"openai_model_description": "Exemplos: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "URL Base",
|
||||
"openai_url_description": "Padrão: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Configurações Anthropic",
|
||||
"anthropic_url_description": "URL Base da API Anthropic (padrão: https://api.anthropic.com)",
|
||||
"anthropic_model_description": "Modelos Claude da Anthropic para completar conversas",
|
||||
"voyage_settings": "Configurações Voyage AI",
|
||||
"retry": "Tentar novamente",
|
||||
"retry_failed": "Falha ao enfileirar nota para nova tentativa",
|
||||
"max_notes_per_llm_query": "Máximo de Notas por Consulta",
|
||||
"max_notes_per_llm_query_description": "Número máximo de notas similares para incluir no contexto da IA",
|
||||
"active_providers": "Provedores Ativos",
|
||||
"disabled_providers": "Provedores Desativados",
|
||||
"remove_provider": "Remover provedor da pesquisa",
|
||||
"restore_provider": "Restaurar provedor na pesquisa",
|
||||
"similarity_threshold": "Tolerância de Similaridade",
|
||||
"similarity_threshold_description": "Pontuação máxima de similaridade (0-1) para notas a serem incluídas no contexto das consultas de LLM",
|
||||
"reprocess_index": "Reconstruir Índice de Pesquisa",
|
||||
"reprocessing_index": "Reconstruindo…",
|
||||
"reprocess_index_started": "Otimiação do índice de pesquisa iniciado em plano de fundo",
|
||||
"reprocess_index_error": "Erro ao reconstruir índice de pesquisa",
|
||||
"index_rebuild_progress": "Andamento da Reconstrução do Índice",
|
||||
"index_rebuilding": "Otimizando índice ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Otimização de índice finalizada",
|
||||
"index_rebuild_status_error": "Erro ao verificar o estado da reconstrução do índice",
|
||||
"never": "Nunca",
|
||||
"processing": "Processando ({{percentage}}%)",
|
||||
"incomplete": "Incompleto ({{percentage}}%)",
|
||||
"complete": "Completo (100%)",
|
||||
"refreshing": "Atualizando…",
|
||||
"auto_refresh_notice": "Atualizando automaticamente a cada {{seconds}} segundos",
|
||||
"note_queued_for_retry": "Nota enfileirada para nova tentativa",
|
||||
"failed_to_retry_note": "Falha ao retentar nota",
|
||||
"all_notes_queued_for_retry": "Todas as notas com falha enfileiradas para nova tentativa",
|
||||
"failed_to_retry_all": "Falha ao retentar notas",
|
||||
"ai_settings": "Configurações IA",
|
||||
"api_key_tooltip": "Chave de API para acessar o serviço",
|
||||
"agent": {
|
||||
"processing": "Processando…",
|
||||
"thinking": "Pensando…",
|
||||
"loading": "Carregando…",
|
||||
"generating": "Gerando…"
|
||||
},
|
||||
"name": "IA",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Usar contexto aprimorado",
|
||||
"enhanced_context_description": "Alimentar IA com mais contexto sobre a nota e suas notas relacionadas para melhores respostas",
|
||||
"show_thinking": "Exibir pensamento",
|
||||
"enter_message": "Digite sua mensagem…",
|
||||
"error_contacting_provider": "Erro ao contatar o provedor de IA. Por favor, verifique suas configurações e sua conexão de internet.",
|
||||
"error_generating_response": "Erro ao gerar resposta da IA",
|
||||
"index_all_notes": "Indexar Todas as Notas",
|
||||
"index_status": "Estado do Índice",
|
||||
"indexed_notes": "Notas Indexadas",
|
||||
"indexing_stopped": "Indexação interrompida",
|
||||
"indexing_in_progress": "Indexação em andamento…",
|
||||
"last_indexed": "Última Indexada",
|
||||
"note_chat": "Conversa de Nota",
|
||||
"sources": "Origens",
|
||||
"start_indexing": "Iniciar Indexação",
|
||||
"use_advanced_context": "Usar Contexto Avançado",
|
||||
"ollama_no_url": "Ollama não está configurado. Por favor, digite uma URL válida.",
|
||||
"chat": {
|
||||
"root_note_title": "Conversas IA",
|
||||
"root_note_content": "Esta nota contém suas conversas com IA salvas.",
|
||||
"new_chat_title": "Nova Conversa",
|
||||
"create_new_ai_chat": "Criar nova Conversa IA"
|
||||
},
|
||||
"create_new_ai_chat": "Criar nova Conversa IA",
|
||||
"configuration_warnings": "Existem alguns problemas com sua configuração de IA. Por fovor, verifique suas configurações.",
|
||||
"experimental_warning": "O recurso de LLM atualmente é experimental - você foi avisado.",
|
||||
"selected_provider": "Provedor Selecionado",
|
||||
"selected_provider_description": "Escolha o provedor de IA para conversas e recursos de completar",
|
||||
"select_model": "Selecionar modelo…",
|
||||
"select_provider": "Selecionar provedor…",
|
||||
"ai_enabled": "Recursos de IA habilitados",
|
||||
"ai_disabled": "Recursos de IA desabilitados",
|
||||
"no_models_found_online": "Nenhum modelo encontrado. Por favor, verifique sua chave de API e as configurações.",
|
||||
"no_models_found_ollama": "Nenhum modelo Ollama encontrado. Por favor, verifique se o Ollama está em execução.",
|
||||
"error_fetching": "Erro ao obter modelos: {{error}}",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai_desc": "Habilitar recursos de IA como sumarização de notas, geração de conteúdo, e outras capacidades de LLM",
|
||||
"provider_precedence": "Prioridade de provedor",
|
||||
"provider_precedence_description": "Lista de provedores em ordem de prioridade, separados por vírgula (por exemplo, 'openai, anthropic, ollama')",
|
||||
"temperature_description": "Controla a aleatoriedade em respostas (0 = determinística, 2 = aleatoriedade máxima)",
|
||||
"ollama_settings": "Configurações do Ollama",
|
||||
"ollama_url_description": "URL para a API Ollama (padrão: http://localhost:11434)",
|
||||
"ollama_model_description": "Modelo Ollama usado para complementação de chat",
|
||||
"anthropic_configuration": "Configuração da Anthropic",
|
||||
"voyage_configuration": "Configuração da Voyage IA",
|
||||
"voyage_url_description": "Padrão: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Configuração da Ollama",
|
||||
"enable_ollama": "Habilitar Ollama",
|
||||
"enable_ollama_description": "Habilitar Ollama para uso do modelo local de IA",
|
||||
"ollama_url": "URL da Ollama",
|
||||
"ollama_model": "Modelo do Ollama",
|
||||
"refresh_models": "Atualizar Modelos",
|
||||
"refreshing_models": "Atualizando…",
|
||||
"enable_automatic_indexing": "Habilitar indexação automática",
|
||||
"rebuild_index": "Reconstruir Índice",
|
||||
"rebuild_index_error": "Ocorreu um erro ao iniciar a reconstrução do índice. Verifique os logs para obter detalhes.",
|
||||
"note_title": "Título da nota",
|
||||
"error": "Erro",
|
||||
"last_attempt": "Última Tentativa",
|
||||
"actions": "Ações",
|
||||
"partial": "{{ percentage }}% concluído",
|
||||
"show_thinking_description": "Exibir o processo de linha de raciocínio da AI"
|
||||
},
|
||||
"confirm": {
|
||||
"confirmation": "Confirmação",
|
||||
"cancel": "Cancelar",
|
||||
@@ -1271,11 +1128,6 @@
|
||||
"start_dragging_relations": "Comece arrastando as relações daqui e solte-as em outra nota.",
|
||||
"cannot_match_transform": "Não foi possível combinar a transformação: {{transform}}"
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Web View",
|
||||
"embed_websites": "Nota do tipo Visualização Web permite que você incorpore sites dentro do Trilium.",
|
||||
"create_label": "Para começar, crie uma etiqueta com um endereço URL que deseja incorporar, por exemplo, #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Recarregar"
|
||||
},
|
||||
@@ -1580,7 +1432,6 @@
|
||||
"confirm-change": "Não é recomentado alterar o tipo da nota quando o conteúdo da nota não está vazio. Quer continuar assim mesmo?",
|
||||
"geo-map": "Mapa geográfico",
|
||||
"beta-feature": "Beta",
|
||||
"ai-chat": "Chat IA",
|
||||
"task-list": "Lista de Tarefas",
|
||||
"new-feature": "Novo",
|
||||
"collections": "Coleções",
|
||||
@@ -1996,10 +1847,6 @@
|
||||
"drag_locked_title": "Bloqueado para edição",
|
||||
"drag_locked_message": "Arrastar não é permitido pois a coleção está bloqueada para edição."
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Esta nota de ajuda é mostrada porque esta nota do tipo Renderizar HTML não possui a relação necessária para funcionar corretamente.",
|
||||
"note_detail_render_help_2": "O tipo de nota Renderizar HTML é usado para <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">automação</a>. Em suma, você tem uma nota de código HTML (opcionalmente com algum JavaScript) e esta nota irá renderizá-la. Para fazê-lo funcionar, você precisa definir uma <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">relação</a> chamada \"renderNote\" apontando para a nota HTML a ser renderizada."
|
||||
},
|
||||
"etapi": {
|
||||
"title": "ETAPI",
|
||||
"description": "ETAPI é uma API REST usada para acessar a instância do Trilium programaticamente, sem interface gráfica.",
|
||||
@@ -2124,7 +1971,6 @@
|
||||
"shared_locally": "Esta nota é compartilhada localmente em {{- link}}."
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Página de {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} notas"
|
||||
},
|
||||
"collections": {
|
||||
|
||||
@@ -1094,10 +1094,6 @@
|
||||
"rename_relation_from": "Redenumește relația din",
|
||||
"to": "În"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Această notă informativă este afișată deoarece această notiță de tip „Randare HTML” nu are relația necesară pentru a funcționa corespunzător.",
|
||||
"note_detail_render_help_2": "Notița de tipul „Render HTML” este utilizată pentru <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">scriptare</a>. Pe scurt, se folosește o notiță de tip cod HTML (opțional cu niște JavaScript) și această notiță o va randa. Pentru a funcționa, trebuie definită o <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">relație</a> denumită „renderNote” ce indică notița HTML de randat."
|
||||
},
|
||||
"revisions": {
|
||||
"confirm_delete": "Doriți ștergerea acestei revizii?",
|
||||
"confirm_delete_all": "Doriți ștergerea tuturor reviziilor acestei notițe?",
|
||||
@@ -1376,11 +1372,6 @@
|
||||
"enable_vim_keybindings": "Permite utilizarea combinațiilor de taste în stil Vim pentru notițele de tip cod (fără modul ex)",
|
||||
"use_vim_keybindings_in_code_notes": "Combinații de taste Vim"
|
||||
},
|
||||
"web_view": {
|
||||
"create_label": "Pentru a începe, creați o etichetă cu adresa URL de încorporat, e.g. #webViewSrc=\"https://www.google.com\"",
|
||||
"embed_websites": "Notițele de tip „Vizualizare web” permit încorporarea site-urilor web în Trilium.",
|
||||
"web_view": "Vizualizare web"
|
||||
},
|
||||
"wrap_lines": {
|
||||
"enable_line_wrap": "Activează trecerea automată pe rândul următor (poate necesita o reîncărcare a interfeței pentru a avea efect)",
|
||||
"wrap_lines_in_code_notes": "Trecerea automată pe rândul următor în notițe de cod"
|
||||
@@ -1466,7 +1457,6 @@
|
||||
"geo-map": "Hartă geografică",
|
||||
"beta-feature": "Beta",
|
||||
"task-list": "Listă de sarcini",
|
||||
"ai-chat": "Discuție cu AI-ul",
|
||||
"new-feature": "Nou",
|
||||
"collections": "Colecții"
|
||||
},
|
||||
@@ -1844,149 +1834,6 @@
|
||||
"lock-editing": "Blochează editarea",
|
||||
"unlock-editing": "Deblochează editarea"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Nu s-a pornit",
|
||||
"title": "Setări AI",
|
||||
"processed_notes": "Notițe procesate",
|
||||
"total_notes": "Totalul de notițe",
|
||||
"progress": "Progres",
|
||||
"queued_notes": "Notițe în curs de procesare",
|
||||
"failed_notes": "Notițe ce au eșuat",
|
||||
"last_processed": "Ultima procesare",
|
||||
"refresh_stats": "Reîmprospătare statistici",
|
||||
"enable_ai_features": "Activează funcțiile AI/LLM",
|
||||
"enable_ai_description": "Activează funcțiile AI precum sumarizarea notițelor, generarea de conținut și alte capabilități ale LLM-ului",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"ollama_tab": "Ollama",
|
||||
"enable_ai": "Activează funcții AI/LLM",
|
||||
"enable_ai_desc": "Activează funcțiile AI precum sumarizarea notițelor, generarea de conținut și alte capabilități ale LLM-ului",
|
||||
"provider_configuration": "Setările furnizorului de AI",
|
||||
"provider_precedence": "Ordinea de precedență a furnizorilor",
|
||||
"provider_precedence_description": "Lista de furnizori în ordinea de precedență, separate de virgulă (ex. „openai,anthropic,ollama”)",
|
||||
"temperature": "Temperatură",
|
||||
"temperature_description": "Controlează aleatoritatea din răspunsuri (0 = deterministic, 2 = maxim aleator)",
|
||||
"system_prompt": "Prompt-ul de sistem",
|
||||
"system_prompt_description": "Prompt-ul de sistem folosit pentru toate interacțiunile cu AI-ul",
|
||||
"openai_configuration": "Configurația OpenAI",
|
||||
"openai_settings": "Setările OpenAI",
|
||||
"api_key": "Cheie API",
|
||||
"url": "URL de bază",
|
||||
"model": "Model",
|
||||
"openai_api_key_description": "Cheia de API din OpenAI pentru a putea accesa serviciile de AI",
|
||||
"anthropic_api_key_description": "Cheia de API din Anthropic pentru a accesa modelele Claude",
|
||||
"default_model": "Modelul implicit",
|
||||
"openai_model_description": "Exemple: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "URL de bază",
|
||||
"openai_url_description": "Implicit: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Setări Anthropic",
|
||||
"anthropic_url_description": "URL de bază pentru API-ul Anthropic (implicit: https://api.anthropic.com)",
|
||||
"anthropic_model_description": "Modele Anthropic Claude pentru auto-completare",
|
||||
"voyage_settings": "Setări Voyage AI",
|
||||
"ollama_settings": "Setări Ollama",
|
||||
"ollama_url_description": "URL pentru API-ul Ollama (implicit: http://localhost:11434)",
|
||||
"ollama_model_description": "Modelul Ollama pentru auto-completare",
|
||||
"anthropic_configuration": "Configurația Anthropic",
|
||||
"voyage_configuration": "Configurația Voyage AI",
|
||||
"voyage_url_description": "Implicit: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Configurația Ollama",
|
||||
"enable_ollama": "Activează Ollama",
|
||||
"enable_ollama_description": "Activează Ollama pentru a putea utiliza modele AI locale",
|
||||
"ollama_url": "URL Ollama",
|
||||
"ollama_model": "Model Ollama",
|
||||
"refresh_models": "Reîmprospătează modelele",
|
||||
"refreshing_models": "Reîmprospătare...",
|
||||
"enable_automatic_indexing": "Activează indexarea automată",
|
||||
"rebuild_index": "Reconstruire index",
|
||||
"rebuild_index_error": "Eroare la reconstruirea indexului. Verificați logurile pentru mai multe detalii.",
|
||||
"note_title": "Titlul notiței",
|
||||
"error": "Eroare",
|
||||
"last_attempt": "Ultima încercare",
|
||||
"actions": "Acțiuni",
|
||||
"retry": "Reîncercare",
|
||||
"partial": "{{ percentage }}% finalizat",
|
||||
"retry_queued": "Notiță pusă în coadă pentru reîncercare",
|
||||
"retry_failed": "Nu s-a putut pune notița în coada pentru reîncercare",
|
||||
"max_notes_per_llm_query": "Număr maximum de notițe per interogare",
|
||||
"max_notes_per_llm_query_description": "Numărul maxim de notițe similare incluse în contextul pentru AI",
|
||||
"active_providers": "Furnizori activi",
|
||||
"disabled_providers": "Furnizori dezactivați",
|
||||
"remove_provider": "Șterge furnizorul din căutare",
|
||||
"restore_provider": "Restaurează furnizorul pentru căutare",
|
||||
"similarity_threshold": "Prag de similaritate",
|
||||
"similarity_threshold_description": "Scorul minim de similaritate (0-1) pentru a include notițele în contextul interogărilor LLM",
|
||||
"reprocess_index": "Reconstruiește indexul de căutare",
|
||||
"reprocessing_index": "Reconstruire...",
|
||||
"reprocess_index_started": "S-a pornit în fundal optimizarea indexului de căutare",
|
||||
"reprocess_index_error": "Eroare la reconstruirea indexului de căutare",
|
||||
"index_rebuild_progress": "Reconstruire index în curs",
|
||||
"index_rebuilding": "Optimizare index ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Optimizarea indexului a avut loc cu succes",
|
||||
"index_rebuild_status_error": "Eroare la verificarea stării reconstruirii indexului",
|
||||
"never": "Niciodată",
|
||||
"processing": "Procesare ({{percentage}}%)",
|
||||
"incomplete": "Incomplet ({{percentage}}%)",
|
||||
"complete": "Complet (100%)",
|
||||
"refreshing": "Reîmprospătare...",
|
||||
"auto_refresh_notice": "Reîmprospătare automată la fiecare {{seconds}} secunde",
|
||||
"note_queued_for_retry": "Notiță pusă în coadă pentru reîncercare",
|
||||
"failed_to_retry_note": "Eroare la reîncercarea notiței",
|
||||
"all_notes_queued_for_retry": "Toate notițele eșuate au fost puse în coada de reîncercare",
|
||||
"failed_to_retry_all": "Eroare la reîncercarea notițelor",
|
||||
"ai_settings": "Setări AI",
|
||||
"api_key_tooltip": "Cheia API pentru accesarea serviciului",
|
||||
"empty_key_warning": {
|
||||
"anthropic": "Cheia API pentru Anthropic lipsește. Introduceți o cheie API validă.",
|
||||
"openai": "Cheia API pentru OpenAI lipsește. Introduceți o cheie API validă.",
|
||||
"voyage": "Cheia API pentru Voyage lipsește. Introduceți o cheie API validă.",
|
||||
"ollama": "Cheia API pentru Ollama lipsește. Introduceți o cheie API validă."
|
||||
},
|
||||
"agent": {
|
||||
"processing": "Procesare...",
|
||||
"thinking": "Raționalizare...",
|
||||
"loading": "Încărcare...",
|
||||
"generating": "Generare..."
|
||||
},
|
||||
"name": "AI",
|
||||
"openai": "OpenAI",
|
||||
"use_enhanced_context": "Folosește context îmbogățit",
|
||||
"enhanced_context_description": "Oferă AI-ului mai multe informații de context din notiță și notițele similare pentru răspunsuri mai bune",
|
||||
"show_thinking": "Afișează procesul de raționalizare",
|
||||
"show_thinking_description": "Afișează lanțul de acțiuni din procesul de gândire al AI-ului",
|
||||
"enter_message": "Introduceți mesajul...",
|
||||
"error_contacting_provider": "Eroare la contactarea furnizorului de AI. Verificați setările și conexiunea la internet.",
|
||||
"error_generating_response": "Eroare la generarea răspunsului AI",
|
||||
"index_all_notes": "Indexează toate notițele",
|
||||
"index_status": "Starea indexării",
|
||||
"indexed_notes": "Notițe indexate",
|
||||
"indexing_stopped": "Indexarea s-a oprit",
|
||||
"indexing_in_progress": "Indexare în curs...",
|
||||
"last_indexed": "Ultima indexare",
|
||||
"note_chat": "Discuție pe baza notițelor",
|
||||
"sources": "Surse",
|
||||
"start_indexing": "Indexează",
|
||||
"use_advanced_context": "Folosește context îmbogățit",
|
||||
"ollama_no_url": "Ollama nu este configurat. Introduceți un URL corect.",
|
||||
"chat": {
|
||||
"root_note_title": "Discuții cu AI-ul",
|
||||
"root_note_content": "Această notiță stochează conversația cu AI-ul.",
|
||||
"new_chat_title": "Discuție nouă",
|
||||
"create_new_ai_chat": "Crează o nouă discuție cu AI-ul"
|
||||
},
|
||||
"create_new_ai_chat": "Crează o nouă discuție cu AI-ul",
|
||||
"configuration_warnings": "Sunt câteva probleme la configurația AI-ului. Verificați setările.",
|
||||
"experimental_warning": "Funcția LLM este experimentală.",
|
||||
"selected_provider": "Furnizor selectat",
|
||||
"selected_provider_description": "Selectați furnizorul de AI pentru funcțiile de discuție și completare",
|
||||
"select_model": "Selectați modelul...",
|
||||
"select_provider": "Selectați furnizorul...",
|
||||
"ai_enabled": "Funcționalitățile AI au fost activate",
|
||||
"ai_disabled": "Funcționalitățile AI au fost dezactivate",
|
||||
"no_models_found_online": "Nu s-a găsit niciun model. Verificați cheia API și configurația.",
|
||||
"no_models_found_ollama": "Nu s-a găsit niciun model Ollama. Verificați dacă Ollama rulează.",
|
||||
"error_fetching": "Eroare la obținerea modelelor: {{error}}"
|
||||
},
|
||||
"custom_date_time_format": {
|
||||
"title": "Format dată/timp personalizat",
|
||||
"description": "Personalizați formatul de dată și timp inserat prin <shortcut /> sau din bara de unelte. Vedeți <doc>Documentația Day.js</doc> pentru câmpurile de formatare disponibile.",
|
||||
@@ -2160,7 +2007,6 @@
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Pagina pentru {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} notițe"
|
||||
},
|
||||
"collections": {
|
||||
|
||||
@@ -668,7 +668,8 @@
|
||||
"geo-map": {
|
||||
"unable-to-load-map": "Не удалось загрузить карту.",
|
||||
"create-child-note-instruction": "Щелкните по карте, чтобы создать новую заметку в этом месте, или нажмите Escape, чтобы закрыть ее.",
|
||||
"create-child-note-title": "Создать новую дочернюю заметку и добавить ее на карту"
|
||||
"create-child-note-title": "Создать новую дочернюю заметку и добавить ее на карту",
|
||||
"create-child-note-text": "Добавить маркер"
|
||||
},
|
||||
"note_tooltip": {
|
||||
"quick-edit": "Быстрое редактирование",
|
||||
@@ -685,8 +686,8 @@
|
||||
"electron_integration": {
|
||||
"zoom-factor": "Коэффициент масштабирования",
|
||||
"restart-app-button": "Применить изменения и перезапустить приложение",
|
||||
"background-effects-description": "Эффект Mica добавляет размытый, стильный фон окнам приложений, создавая глубину и современный вид. Опция \"Системная строка заголовка\" должна быть отключена.",
|
||||
"background-effects": "Включить фоновые эффекты (только Windows 11)",
|
||||
"background-effects-description": "Добавляет размытый, стильный фон окнам приложений, создавая глубину и современный вид. Опция \"Системная строка заголовка\" должна быть отключена.",
|
||||
"background-effects": "Включить фоновые эффекты",
|
||||
"native-title-bar-description": "В Windows и macOS отключение системной строки заголовка делает приложение более компактным. В Linux включение системной строки заголовка улучшает интеграцию с остальной частью системы.",
|
||||
"native-title-bar": "Системная панель заголовка",
|
||||
"desktop-application": "Десктопное приложение"
|
||||
@@ -776,7 +777,11 @@
|
||||
"refresh-saved-search-results": "Обновить сохраненные результаты поиска",
|
||||
"automatically-collapse-notes-title": "Заметки будут свернуты после определенного периода бездействия, чтобы навести порядок в дереве.",
|
||||
"toggle-sidebar": "Переключить боковую панель",
|
||||
"dropping-not-allowed": "Перетаскивание заметок в эту область не разрешено."
|
||||
"dropping-not-allowed": "Перетаскивание заметок в эту область не разрешено.",
|
||||
"shared-indicator-tooltip": "Эта заметка опубликована",
|
||||
"shared-indicator-tooltip-with-url": "Эта заметка доступно публично по адресу: {{- url}}",
|
||||
"subtree-hidden-moved-description-other": "В дереве, к которому относится эта заметка, скрыты дочерние заметки.",
|
||||
"subtree-hidden-moved-description-collection": "Эта коллекция скрывает свои дочерние заметки в дереве."
|
||||
},
|
||||
"quick-search": {
|
||||
"no-results": "Результаты не найдены",
|
||||
@@ -819,7 +824,6 @@
|
||||
"web-view": "Веб-страница",
|
||||
"mind-map": "Mind Map",
|
||||
"geo-map": "Географическая карта",
|
||||
"ai-chat": "ИИ Чат",
|
||||
"task-list": "Список задач",
|
||||
"confirm-change": "Не рекомендуется менять тип заметки, если её содержимое не пустое. Вы всё равно хотите продолжить?"
|
||||
},
|
||||
@@ -856,7 +860,10 @@
|
||||
"convert-to-attachment-confirm": "Вы уверены, что хотите преобразовать выбранные заметки во вложения их родительских заметок? Эта операция применяется только к заметкам в виде изображений; другие заметки будут пропущены.",
|
||||
"converted-to-attachments": "{{count}} заметок были преобразованы во вложения.",
|
||||
"archive": "Архивировать",
|
||||
"unarchive": "Разархивировать"
|
||||
"unarchive": "Разархивировать",
|
||||
"open-in-a-new-window": "Открыть в новом окне",
|
||||
"hide-subtree": "Скрыть поддерево",
|
||||
"show-subtree": "Показать поддерево"
|
||||
},
|
||||
"info": {
|
||||
"closeButton": "Закрыть",
|
||||
@@ -1000,7 +1007,8 @@
|
||||
"switch_to_mobile_version": "Перейти на мобильную версию",
|
||||
"switch_to_desktop_version": "Переключиться на версию для ПК",
|
||||
"new-version-available": "Доступно обновление",
|
||||
"download-update": "Обновить до {{latestVersion}}"
|
||||
"download-update": "Обновить до {{latestVersion}}",
|
||||
"search_notes": "Поиск заметок"
|
||||
},
|
||||
"zpetne_odkazy": {
|
||||
"relation": "отношение",
|
||||
@@ -1047,7 +1055,8 @@
|
||||
"expand_all_levels": "Развернуть все вложенные уровни",
|
||||
"expand_nth_level": "Развернуть уровни: {{depth}} шт.",
|
||||
"expand_first_level": "Развернуть прямые дочерние уровни",
|
||||
"expand_tooltip": "Разщвернуть дочерние элементы этой коллекции (на один уровень вложенности). Для получения дополнительных параметров нажмите стрелку справа."
|
||||
"expand_tooltip": "Разщвернуть дочерние элементы этой коллекции (на один уровень вложенности). Для получения дополнительных параметров нажмите стрелку справа.",
|
||||
"hide_child_notes": "Скрыть дочерние заметки в дереве"
|
||||
},
|
||||
"edited_notes": {
|
||||
"deleted": "(удалено)",
|
||||
@@ -1247,149 +1256,6 @@
|
||||
"disabled": "выключено",
|
||||
"title": "Системная панель заголовка (требует перезапуска приложения)"
|
||||
},
|
||||
"ai_llm": {
|
||||
"progress": "Прогресс",
|
||||
"openai_tab": "OpenAI",
|
||||
"anthropic_tab": "Anthropic",
|
||||
"ollama_tab": "Ollama",
|
||||
"temperature": "Температура",
|
||||
"model": "Модель",
|
||||
"refreshing_models": "Обновление...",
|
||||
"error": "Ошибка",
|
||||
"actions": "Действия",
|
||||
"retry": "Повторить",
|
||||
"never": "Никогда",
|
||||
"refreshing": "Обновление...",
|
||||
"agent": {
|
||||
"processing": "Обработка...",
|
||||
"thinking": "Думаю...",
|
||||
"loading": "Загрузка...",
|
||||
"generating": "Создание..."
|
||||
},
|
||||
"name": "AI",
|
||||
"openai": "OpenAI",
|
||||
"sources": "Источники",
|
||||
"reprocessing_index": "Перестройка индекса...",
|
||||
"processed_notes": "Обработанные заметки",
|
||||
"total_notes": "Всего заметок",
|
||||
"queued_notes": "Заметок в очереди",
|
||||
"failed_notes": "Заметки с ошибками обработки",
|
||||
"last_processed": "Последние обработанные",
|
||||
"refresh_stats": "Обновить статистику",
|
||||
"voyage_tab": "Voyage AI",
|
||||
"system_prompt": "Системный промпт",
|
||||
"openai_configuration": "Конфигурация OpenAI",
|
||||
"openai_settings": "Настройки OpenAI",
|
||||
"api_key": "Ключ API",
|
||||
"url": "Базовый URL",
|
||||
"default_model": "Модель по умолчанию",
|
||||
"base_url": "Базовый URL",
|
||||
"openai_url_description": "По умолчанию: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Настройки Anthropic",
|
||||
"ollama_settings": "Настройки Ollama",
|
||||
"anthropic_configuration": "Конфигурация Anthropic",
|
||||
"voyage_url_description": "По умолчанию: https://api.voyageai.com/v1",
|
||||
"ollama_configuration": "Конфигурация Ollama",
|
||||
"enable_ollama": "Включить Ollama",
|
||||
"ollama_url": "URL Ollama",
|
||||
"ollama_model": "Модель Ollama",
|
||||
"refresh_models": "Обновить модели",
|
||||
"rebuild_index": "Пересобрать индекс",
|
||||
"note_title": "Название заметки",
|
||||
"last_attempt": "Последняя попытка",
|
||||
"active_providers": "Активные провайдеры",
|
||||
"disabled_providers": "Отключенные провайдеры",
|
||||
"similarity_threshold": "Порок сходства",
|
||||
"processing": "Обработка ({{percentage}}%)",
|
||||
"incomplete": "Не завершено ({{percentage}}%)",
|
||||
"complete": "Завершено (100%)",
|
||||
"ai_settings": "Настройки AI",
|
||||
"show_thinking": "Отображать размышление",
|
||||
"index_status": "Статус индексирования",
|
||||
"indexed_notes": "Проиндексированные заметки",
|
||||
"indexing_stopped": "Индексирование остановлено",
|
||||
"last_indexed": "Индексировано в последний раз",
|
||||
"note_chat": "Чат по заметке",
|
||||
"start_indexing": "Начать индексирование",
|
||||
"chat": {
|
||||
"root_note_title": "Чаты с AI",
|
||||
"new_chat_title": "Новый чат",
|
||||
"create_new_ai_chat": "Создать новый чат с ИИ",
|
||||
"root_note_content": "В этой заметке содержатся сохраненные вами разговоры в чате ИИ."
|
||||
},
|
||||
"selected_provider": "Выбранный провайдер",
|
||||
"select_model": "Выбрать модель...",
|
||||
"select_provider": "Выбрать провайдера...",
|
||||
"title": "Настройки AI",
|
||||
"voyage_settings": "Настройки Voyage AI",
|
||||
"error_contacting_provider": "Ошибка подключения к провайдеру AI. Проверьте настройки и подключение к интернету.",
|
||||
"configuration_warnings": "Возникли проблемы с конфигурацией AI. Проверьте настройки.",
|
||||
"selected_provider_description": "Выберите провайдер AI для функций чата и автодополнения",
|
||||
"provider_configuration": "Конфигурация провайдера AI",
|
||||
"ollama_url_description": "URL для API Ollama (по умолчанию: http://localhost:11434)",
|
||||
"ollama_model_description": "Модель Ollama для автодополнения чата",
|
||||
"temperature_description": "Контролирует случайность ответов (0 = детерминированный, 2 = максимальная случайность)",
|
||||
"system_prompt_description": "Системный промпт по умолчанию, используемый для всех взаимодействий с ИИ",
|
||||
"empty_key_warning": {
|
||||
"openai": "Ключ API OpenAI пуст. Введите действительный ключ API.",
|
||||
"ollama": "API-ключ Ollama пуст. Введите действительный API-ключ.",
|
||||
"voyage": "Ключ API Voyage пуст. Введите действительный ключ API.",
|
||||
"anthropic": "Ключ API Anthropic пуст. Введите действительный ключ API."
|
||||
},
|
||||
"openai_api_key_description": "Ваш ключ API OpenAI для доступа к их службам ИИ",
|
||||
"provider_precedence_description": "Список провайдеров, разделенных запятыми, в порядке приоритета (например, \"openai,anthropic,ollama\")",
|
||||
"remove_provider": "Удалить провайдер из поиска",
|
||||
"not_started": "Не запущено",
|
||||
"provider_precedence": "Приоритет провайдера",
|
||||
"enable_ai_features": "Включить функции AI/LLM",
|
||||
"enable_ai": "Включить функции AI/LLM",
|
||||
"voyage_configuration": "Конфигурация Voyage AI",
|
||||
"enable_automatic_indexing": "Включить автоматическое индексирование",
|
||||
"reprocess_index": "Перестроить индекс поиска",
|
||||
"index_rebuild_progress": "Прогресс перестройки индекса",
|
||||
"index_rebuilding": "Оптимизация индекса ({{percentage}}%)",
|
||||
"index_rebuild_complete": "Оптимизация индекса завершена",
|
||||
"use_enhanced_context": "Использовать улучшенный контекст",
|
||||
"enter_message": "Введите ваше сообщение...",
|
||||
"index_all_notes": "Индексировать все заметки",
|
||||
"indexing_in_progress": "Индексация в процессе...",
|
||||
"use_advanced_context": "Использовать расширенный контекст",
|
||||
"openai_model_description": "Примеры: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"partial": "{{ percentage }}% завершено",
|
||||
"retry_queued": "Примечание поставлено в очередь на повторную попытку",
|
||||
"max_notes_per_llm_query": "Макс. количество заметок на запрос",
|
||||
"reprocess_index_error": "Ошибка перестройки поискового индекса",
|
||||
"auto_refresh_notice": "Автоматически обновляется каждые {{seconds}} секунд",
|
||||
"note_queued_for_retry": "Заметка поставлена в очередь на повторную попытку",
|
||||
"failed_to_retry_note": "Не удалось повторить попытку",
|
||||
"failed_to_retry_all": "Не удалось повторить попытку",
|
||||
"error_generating_response": "Ошибка генерации ответа ИИ",
|
||||
"create_new_ai_chat": "Создать новый чат с ИИ",
|
||||
"ai_enabled": "Возможности ИИ активны",
|
||||
"ai_disabled": "Возможности ИИ неактивны",
|
||||
"restore_provider": "Восстановить значение провайдера",
|
||||
"error_fetching": "Ошибка получения списка моделей: {{error}}",
|
||||
"index_rebuild_status_error": "Ошибка проверки статуса перестроения индекса",
|
||||
"enhanced_context_description": "Предоставляет ИИ больше контекста из заметки и связанных с ней заметок для более точных ответов",
|
||||
"no_models_found_ollama": "Модели Ollama не найдены. Проверьте, запущена ли Ollama.",
|
||||
"no_models_found_online": "Модели не найдены. Проверьте ваш ключ API и настройки.",
|
||||
"experimental_warning": "Функция LLM в настоящее время является экспериментальной — вы предупреждены.",
|
||||
"ollama_no_url": "Ollama не настроена. Введите корректный URL-адрес.",
|
||||
"show_thinking_description": "Показать цепочку мыслительного процесса ИИ",
|
||||
"api_key_tooltip": "API-ключ для доступа к сервису",
|
||||
"all_notes_queued_for_retry": "Все неудачные заметки поставлены в очередь на повторную попытку",
|
||||
"reprocess_index_started": "Оптимизация поискового индекса запущена в фоновом режиме",
|
||||
"similarity_threshold_description": "Минимальный показатель сходства (similarity score, 0–1) для заметок, которые следует включить в контекст запросов LLM",
|
||||
"max_notes_per_llm_query_description": "Максимальное количество похожих заметок для включения в контекст ИИ",
|
||||
"retry_failed": "Не удалось поставить заметку в очередь для повторной попытки",
|
||||
"rebuild_index_error": "Ошибка при запуске перестроения индекса. Подробности смотрите в логах.",
|
||||
"enable_ollama_description": "Включить Ollama для использования локальной модели ИИ",
|
||||
"anthropic_model_description": "Модели Anthropic Claude для автодополнения чата",
|
||||
"anthropic_url_description": "Базовый URL для Anthropic API (по умолчанию: https://api.anthropic.com)",
|
||||
"anthropic_api_key_description": "Ваш ключ Anthropic API для доступа к моделям Claude",
|
||||
"enable_ai_desc": "Включить функции ИИ, такие как резюмирование заметок, генерация контента и другие возможности LLM",
|
||||
"enable_ai_description": "Включить функции ИИ, такие как резюмирование заметок, генерация контента и другие возможности LLM"
|
||||
},
|
||||
"code-editor-options": {
|
||||
"title": "Редактор"
|
||||
},
|
||||
@@ -1692,7 +1558,7 @@
|
||||
"zoom_in_title": "Увеличить масштаб",
|
||||
"zoom_out_title": "Уменьшить масштаб",
|
||||
"reset_pan_zoom_title": "Сбросить панорамирование и масштабирование",
|
||||
"create_child_note_title": "Создать новую дочернюю заметку и добавить ее в эту карту связей"
|
||||
"create_child_note_title": "Создать дочернюю заметку и добавить ее в карту"
|
||||
},
|
||||
"code_auto_read_only_size": {
|
||||
"unit": "символов",
|
||||
@@ -1845,7 +1711,8 @@
|
||||
"error_cannot_get_branch_id": "Невозможно получить branchId для notePath '{{notePath}}'",
|
||||
"delete_this_note": "Удалить эту заметку",
|
||||
"insert_child_note": "Вставить дочернюю заметку",
|
||||
"note_revisions": "История изменений"
|
||||
"note_revisions": "История изменений",
|
||||
"content_language_switcher": "Язык содержимого: {{language}}"
|
||||
},
|
||||
"svg_export_button": {
|
||||
"button_title": "Экспортировать диаграмму как SVG"
|
||||
@@ -1900,7 +1767,7 @@
|
||||
"dismiss": "Отклонить",
|
||||
"background_effects_button": "Включить эффекты фона",
|
||||
"next_theme_button": "Попробовать новую тему",
|
||||
"background_effects_message": "На устройствах Windows фоновые эффекты теперь полностью стабильны. Они добавляют цвет в пользовательский интерфейс, размывая фон за ним. Этот приём также используется в других приложениях, например, в проводнике Windows.",
|
||||
"background_effects_message": "На устройствах с ОС Windows или macOS, фоновые эффекты теперь полностью стабильны. Они добавляют цвета в пользовательский интерфейс, размывая фон за ним.",
|
||||
"background_effects_title": "Фоновые эффекты теперь стабильны",
|
||||
"next_theme_title": "Попробуйте новую тему Trilium",
|
||||
"new_layout_button": "Подробнее",
|
||||
@@ -1988,11 +1855,6 @@
|
||||
"attachment_deleted": "Это вложение было удалено.",
|
||||
"you_can_also_open": ", вы также можете открыть "
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Веб-страница",
|
||||
"create_label": "Для начала создайте метку с URL-адресом, который вы хотите встроить, например, #webViewSrc=\"https://www.google.com\"",
|
||||
"embed_websites": "Заметки типа \"Веб-страница\" позволяет встраивать веб-сайты в Trilium."
|
||||
},
|
||||
"ribbon": {
|
||||
"widgets": "Виджеты ленты",
|
||||
"promoted_attributes_message": "Вкладка \"Продвигаемые атрибуты\" будет автоматически открыта, если таковые атрибуты установлены у заметки",
|
||||
@@ -2075,10 +1937,6 @@
|
||||
"help-button": {
|
||||
"title": "Открыть соответствующую страницу справки"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_2": "Тип заметки «Рендер HTML» используется для <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">скриптинга</a>. Если коротко, у вас есть заметка с HTML-кодом (возможно, с добавлением JavaScript), и эта заметка её отобразит. Для этого необходимо определить <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">отношение</a> с именем «renderNote», указывающее на HTML-заметку для отрисовки.",
|
||||
"note_detail_render_help_1": "Эта справочная заметка отображается, поскольку эта справка типа Render HTML не имеет необходимой связи для правильной работы."
|
||||
},
|
||||
"file": {
|
||||
"too_big": "В целях повышения производительности в режиме предварительного просмотра отображаются только первые {{maxNumChars}} символов файла. Загрузите файл и откройте его во внешнем браузере, чтобы увидеть всё содержимое.",
|
||||
"file_preview_not_available": "Предварительный просмотр файла недоступен для этого файла."
|
||||
@@ -2094,7 +1952,11 @@
|
||||
"ui": "Пользовательский интерфейс"
|
||||
},
|
||||
"sql_result": {
|
||||
"no_rows": "По этому запросу не возвращено ни одной строки"
|
||||
"no_rows": "По этому запросу не возвращено ни одной строки",
|
||||
"not_executed": "Запрос еще не выполнен.",
|
||||
"failed": "Выполнение SQL-запроса завершилось с ошибкой",
|
||||
"statement_result": "Результат заявления",
|
||||
"execute_now": "Выполнить сейчас"
|
||||
},
|
||||
"editable_code": {
|
||||
"placeholder": "Введите содержимое для заметки с кодом..."
|
||||
@@ -2144,8 +2006,7 @@
|
||||
"rendering_error": "Невозможно отобразить содержимое из-за ошибки."
|
||||
},
|
||||
"pagination": {
|
||||
"total_notes": "{{count}} заметок",
|
||||
"page_title": "Страница {{startIndex}} - {{endIndex}}"
|
||||
"total_notes": "{{count}} заметок"
|
||||
},
|
||||
"status_bar": {
|
||||
"attributes_one": "{{count}} атрибут",
|
||||
@@ -2189,7 +2050,14 @@
|
||||
"read_only_auto_description": "Эта заметка была автоматически переведена в режим только для чтения по соображениям производительности. Это автоматическое ограничение можно изменить в настройках.\n\nНажмите, чтобы временно отредактировать её.",
|
||||
"read_only_auto": "Автоматический режим \"только для чтения\"",
|
||||
"read_only_explicit_description": "Эта заметка была вручную установлена в режим «только для чтения».\nНажмите, чтобы временно отредактировать её.",
|
||||
"read_only_explicit": "Только для чтения"
|
||||
"read_only_explicit": "Только для чтения",
|
||||
"save_status_saving": "Сохранение...",
|
||||
"save_status_saved": "Сохранение",
|
||||
"save_status_unsaved": "Не сохранено",
|
||||
"save_status_error": "Ошибка сохранения",
|
||||
"save_status_saving_tooltip": "Изменения сохраняются.",
|
||||
"save_status_unsaved_tooltip": "Есть несохраненные изменения. Они будут сохранены автоматически через некоторое время.",
|
||||
"save_status_error_tooltip": "Произошла ошибка при сохранении заметки. Если возможно, попробуйте скопировать содержимое заметки в другое место и перезагрузить приложение."
|
||||
},
|
||||
"breadcrumb": {
|
||||
"hoisted_badge_title": "Снять фокус",
|
||||
@@ -2243,5 +2111,30 @@
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "Атрибуты заметки"
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "Закладки"
|
||||
},
|
||||
"mobile_tab_switcher": {
|
||||
"more_options": "Показать больше",
|
||||
"title_one": "{{count}} вкладка",
|
||||
"title_few": "{{count}} вкладки",
|
||||
"title_many": "{{count}} вкладок"
|
||||
},
|
||||
"pdf": {
|
||||
"pages_loading": "Загрузка...",
|
||||
"pages_alt": "Страница {{pageNumber}}",
|
||||
"pages_one": "{{count}} страница",
|
||||
"pages_few": "{{count}} страницы",
|
||||
"pages_many": "{{count}} страниц",
|
||||
"layers_one": "{{count}} слой",
|
||||
"layers_few": "{{count}} слоя",
|
||||
"layers_many": "{{count}} слоев",
|
||||
"attachments_one": "{{count}} вложение",
|
||||
"attachments_few": "{{count}} вложения",
|
||||
"attachments_many": "{{count}} вложений"
|
||||
},
|
||||
"platform_indicator": {
|
||||
"available_on": "Доступно для {{platform}}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "Podrobnosti Trilium Notes",
|
||||
"homepage": "Domača stran:",
|
||||
"app_version": "Verzija aplikacije:",
|
||||
"db_version": "Verzija DB:",
|
||||
"sync_version": "Verzija Sync:"
|
||||
}
|
||||
"about": {
|
||||
"title": "Podrobnosti Trilium Notes",
|
||||
"homepage": "Domača stran:",
|
||||
"app_version": "Verzija aplikacije:",
|
||||
"db_version": "Verzija DB:",
|
||||
"sync_version": "Verzija Sync:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,7 +662,8 @@
|
||||
"show-cheatsheet": "顯示快捷鍵說明",
|
||||
"toggle-zen-mode": "禪模式",
|
||||
"new-version-available": "發現新更新",
|
||||
"download-update": "取得版本 {{latestVersion}}"
|
||||
"download-update": "取得版本 {{latestVersion}}",
|
||||
"search_notes": "搜尋筆記"
|
||||
},
|
||||
"sync_status": {
|
||||
"unknown": "<p>同步狀態將在下一次同步嘗試開始後顯示。</p><p>點擊以立即觸發同步。</p>",
|
||||
@@ -758,7 +759,8 @@
|
||||
"error_cannot_get_branch_id": "無法獲取 notePath '{{notePath}}' 的 branchId",
|
||||
"error_unrecognized_command": "無法識別的命令 {{command}}",
|
||||
"note_revisions": "筆記歷史版本",
|
||||
"backlinks": "反向連結"
|
||||
"backlinks": "反向連結",
|
||||
"content_language_switcher": "內文語言:{{language}}"
|
||||
},
|
||||
"note_icon": {
|
||||
"change_note_icon": "更改筆記圖標",
|
||||
@@ -910,7 +912,8 @@
|
||||
"unknown_search_option": "未知的搜尋選項 {{searchOptionName}}",
|
||||
"search_note_saved": "搜尋筆記已儲存至 {{- notePathTitle}}",
|
||||
"actions_executed": "已執行操作。",
|
||||
"view_options": "查看選項:"
|
||||
"view_options": "查看選項:",
|
||||
"option": "選項"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "相似筆記",
|
||||
@@ -1004,7 +1007,7 @@
|
||||
"no_attachments": "此筆記沒有附件。"
|
||||
},
|
||||
"book": {
|
||||
"no_children_help": "此類型為書籍的筆記沒有任何子筆記,因此沒有內容可顯示。請參閱 <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> 以了解詳情。",
|
||||
"no_children_help": "此集合沒有任何子筆記,因此沒有內容可顯示。",
|
||||
"drag_locked_title": "鎖定編輯",
|
||||
"drag_locked_message": "無法拖曳,因為此集合已被鎖定編輯。"
|
||||
},
|
||||
@@ -1060,15 +1063,6 @@
|
||||
"default_new_note_title": "新筆記",
|
||||
"click_on_canvas_to_place_new_note": "點擊畫布以放置新筆記"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "之所以顯示此說明筆記,是因為該類型的渲染 HTML 沒有設定好必須的關聯。",
|
||||
"note_detail_render_help_2": "渲染筆記類型用於編寫 <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">腳本</a>。簡單說就是您可以寫HTML程式碼(或者加上一些JavaScript程式碼), 然後這個筆記會把頁面渲染出來。要使其正常工作,您需要定義一個名為 \"renderNote\" 的 <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">關聯</a> 指向要呈現的 HTML 筆記。"
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "網頁顯示",
|
||||
"embed_websites": "網頁顯示類型的筆記允許您將網站嵌入至 Trilium 中。",
|
||||
"create_label": "首先,請新增一個帶有您要嵌入的 URL 地址的標籤,例如 #webViewSrc=\"https://www.bing.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "重新整理"
|
||||
},
|
||||
@@ -1379,7 +1373,8 @@
|
||||
"description": "描述",
|
||||
"reload_app": "重新載入應用以套用更改",
|
||||
"set_all_to_default": "將所有快捷鍵重設為預設值",
|
||||
"confirm_reset": "您確定要將所有鍵盤快捷鍵重設為預設值嗎?"
|
||||
"confirm_reset": "您確定要將所有鍵盤快捷鍵重設為預設值嗎?",
|
||||
"no_results": "未找到符合 '{{filter}}' 的捷徑"
|
||||
},
|
||||
"spellcheck": {
|
||||
"title": "拼寫檢查",
|
||||
@@ -1498,7 +1493,6 @@
|
||||
"book": "集合",
|
||||
"geo-map": "地理地圖",
|
||||
"beta-feature": "Beta",
|
||||
"ai-chat": "AI 聊天",
|
||||
"task-list": "任務列表",
|
||||
"new-feature": "新增",
|
||||
"collections": "集合"
|
||||
@@ -1583,7 +1577,9 @@
|
||||
"print_report_collection_content_one": "集合中的 {{count}} 篇筆記無法列印,因為它們不被支援或受到保護。",
|
||||
"print_report_collection_content_other": "",
|
||||
"print_report_collection_details_button": "查看詳情",
|
||||
"print_report_collection_details_ignored_notes": "忽略的筆記"
|
||||
"print_report_collection_details_ignored_notes": "忽略的筆記",
|
||||
"print_report_error_title": "列印失敗",
|
||||
"print_report_stack_trace": "堆棧追蹤"
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "請輸入筆記標題...",
|
||||
@@ -1746,149 +1742,6 @@
|
||||
"zen_mode": {
|
||||
"button_exit": "退出禪模式"
|
||||
},
|
||||
"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": "最後索引時間",
|
||||
"note_chat": "筆記聊天",
|
||||
"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": "編輯器"
|
||||
},
|
||||
@@ -2077,7 +1930,8 @@
|
||||
"raster": "柵格",
|
||||
"vector_light": "向量(淺色)",
|
||||
"vector_dark": "向量(深色)",
|
||||
"show-scale": "顯示比例尺"
|
||||
"show-scale": "顯示比例尺",
|
||||
"show-labels": "顯示標記名稱"
|
||||
},
|
||||
"table_context_menu": {
|
||||
"delete_row": "刪除列"
|
||||
@@ -2156,7 +2010,6 @@
|
||||
"app-restart-required": "(需要重啟程式以套用更改)"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "第 {{startIndex}} - {{endIndex}} 頁",
|
||||
"total_notes": "{{count}} 筆記"
|
||||
},
|
||||
"collections": {
|
||||
@@ -2272,9 +2125,57 @@
|
||||
},
|
||||
"mobile_tab_switcher": {
|
||||
"more_options": "更多選項",
|
||||
"title_one": "{{count}} 個分頁"
|
||||
"title_one": "{{count}} 個分頁",
|
||||
"title_other": ""
|
||||
},
|
||||
"platform_indicator": {
|
||||
"available_on": "可於 {{platform}} 使用"
|
||||
},
|
||||
"bookmark_buttons": {
|
||||
"bookmarks": "書籤"
|
||||
},
|
||||
"render": {
|
||||
"setup_title": "在此筆記中顯示自訂 HTML 或 Preact JSX",
|
||||
"setup_create_sample_preact": "使用 Preact 建立範例筆記",
|
||||
"setup_create_sample_html": "使用 HTML 建立範例筆記",
|
||||
"setup_sample_created": "已建立一個範例筆記作為子筆記。",
|
||||
"disabled_description": "此渲染筆記來自外部來源。為保護您免受惡意內容侵害,此功能預設為停用狀態。啟用前請務必確認來源可信。",
|
||||
"disabled_button_enable": "啟用渲染筆記"
|
||||
},
|
||||
"web_view_setup": {
|
||||
"title": "將網頁直接匯入 Trilium 建立即時預覽",
|
||||
"url_placeholder": "輸入或貼上網站網址,例如 https://triliumnotes.org",
|
||||
"create_button": "建立網頁檢視",
|
||||
"invalid_url_title": "無效地址",
|
||||
"invalid_url_message": "請輸入有效的網址,例如 https://triliumnotes.org。",
|
||||
"disabled_description": "此網頁檢視來自外部來源。為協助保護您免受網路釣魚或惡意內容侵害,內容不會自動載入。若您信任來源,可手動啟用此功能。",
|
||||
"disabled_button_enable": "啟用網頁檢視"
|
||||
},
|
||||
"active_content_badges": {
|
||||
"type_icon_pack": "圖示包",
|
||||
"type_backend_script": "後端腳本",
|
||||
"type_frontend_script": "前端腳本",
|
||||
"type_widget": "元件",
|
||||
"type_app_css": "自訂 CSS",
|
||||
"type_render_note": "渲染筆記",
|
||||
"type_web_view": "網頁顯示",
|
||||
"type_app_theme": "自訂主題",
|
||||
"toggle_tooltip_enable_tooltip": "點擊以啟用此 {{type}}。",
|
||||
"toggle_tooltip_disable_tooltip": "點擊以停用此 {{type}}。",
|
||||
"menu_docs": "打開文件",
|
||||
"menu_execute_now": "立即執行腳本",
|
||||
"menu_run": "自動執行",
|
||||
"menu_run_disabled": "手動",
|
||||
"menu_run_backend_startup": "當後端啟動時",
|
||||
"menu_run_hourly": "每小時",
|
||||
"menu_run_daily": "每日",
|
||||
"menu_run_frontend_startup": "當桌面前端啟動時",
|
||||
"menu_run_mobile_startup": "當移動前端啟動時",
|
||||
"menu_change_to_widget": "更改為元件",
|
||||
"menu_change_to_frontend_script": "更改為前端腳本",
|
||||
"menu_theme_base": "主題基底"
|
||||
},
|
||||
"setup_form": {
|
||||
"more_info": "了解更多"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1130,15 +1130,6 @@
|
||||
"default_new_note_title": "нова нотатка",
|
||||
"click_on_canvas_to_place_new_note": "Натисніть на полотно, щоб розмістити нову нотатку"
|
||||
},
|
||||
"render": {
|
||||
"note_detail_render_help_1": "Ця довідка відображається, оскільки ця нотатка типу Render HTML не має необхідного зв'язку для належного функціонування.",
|
||||
"note_detail_render_help_2": "Тип нотатки Render HTML використовується для <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/scripts.html\">скриптів</a>. Коротше кажучи, у вас є нотатка з HTML-кодом (за бажанням з деяким JavaScript), і ця нотатка її відобразить. Щоб це запрацювало, вам потрібно визначити <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/attributes.html\">відношення</a> під назвою \"renderNote\", яке вказує на нотатку HTML для відображення."
|
||||
},
|
||||
"web_view": {
|
||||
"web_view": "Веб-перегляд",
|
||||
"embed_websites": "Нотатка типу Веб-перегляд дозволяє вбудовувати веб-сайти в Trilium.",
|
||||
"create_label": "Для початку створіть мітку з URL-адресою, яку ви хочете вбудувати, наприклад, #webViewSrc=\"https://www.google.com\""
|
||||
},
|
||||
"backend_log": {
|
||||
"refresh": "Оновити"
|
||||
},
|
||||
@@ -1245,149 +1236,6 @@
|
||||
"layout-vertical-description": "Панель запуску знаходиться ліворуч (за замовчуванням)",
|
||||
"layout-horizontal-description": "Панель запуску знаходиться під панеллю вкладок, панель вкладок тепер має повну ширину."
|
||||
},
|
||||
"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": "Системний Запит (Prompt)",
|
||||
"system_prompt_description": "Системний запит (prompt) за замовчуванням використовується для всіх взаємодій з AI",
|
||||
"openai_configuration": "Конфігурація OpenAI",
|
||||
"openai_settings": "Налаштування OpenAI",
|
||||
"api_key": "API Key",
|
||||
"url": "Base URL",
|
||||
"model": "Модель",
|
||||
"openai_api_key_description": "Ваш ключ OpenAI API для доступу до служб AI",
|
||||
"anthropic_api_key_description": "Ваш ключ Anthropic API для доступу до моделей Claude",
|
||||
"default_model": "Модель за замовчуванням",
|
||||
"openai_model_description": "Наприклад: gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
|
||||
"base_url": "Base URL",
|
||||
"openai_url_description": "За замовчуванням: https://api.openai.com/v1",
|
||||
"anthropic_settings": "Налаштування Anthropic",
|
||||
"anthropic_url_description": "Базова URL-адреса для Anthropic API (за замовчуванням: https://api.anthropic.com)",
|
||||
"anthropic_model_description": "Моделі Anthropic Claude для чату",
|
||||
"voyage_settings": "Налаштування Voyage AI",
|
||||
"ollama_settings": "Налаштування Ollama",
|
||||
"ollama_url_description": "URL для Ollama API (default: 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": "Помилка початку перебудови індексу. Перегляньте logs для інформації.",
|
||||
"note_title": "Заголовок нотатки",
|
||||
"error": "Помилка",
|
||||
"last_attempt": "Остання спроба",
|
||||
"actions": "Дії",
|
||||
"retry": "Повторити спробу",
|
||||
"partial": "{{ percentage }}% completed",
|
||||
"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": "Мінімальна оцінка схожості (0-1) для нотаток, що включатимуться в контекст для запитів LLM",
|
||||
"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": "Ключ API Anthropic порожній. Будь ласка, введіть дійсний ключ API.",
|
||||
"openai": "Ключ API OpenAI порожній. Будь ласка, введіть дійсний ключ API.",
|
||||
"voyage": "Ключ Voyage API подорожі порожній. Будь ласка, введіть дійсний ключ API.",
|
||||
"ollama": "Ключ API Ollama порожній. Будь ласка, введіть дійсний ключ 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": "Остання індексація",
|
||||
"note_chat": "Нотатка Чат",
|
||||
"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}}"
|
||||
},
|
||||
"backup": {
|
||||
"automatic_backup": "Автоматичне резервне копіювання",
|
||||
"automatic_backup_description": "Trilium може автоматично створювати резервні копії бази даних:",
|
||||
@@ -1966,7 +1814,6 @@
|
||||
"confirm-change": "Не рекомендується змінювати тип нотатки, якщо її вміст не порожній. Ви все одно хочете продовжити?",
|
||||
"geo-map": "Географічна карта",
|
||||
"beta-feature": "Бета",
|
||||
"ai-chat": "Чат AI",
|
||||
"task-list": "Список завдань",
|
||||
"new-feature": "Нова",
|
||||
"collections": "Колекції",
|
||||
@@ -2072,7 +1919,6 @@
|
||||
"app-restart-required": "(щоб зміни набули чинності, потрібен перезапуск програми)"
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Сторінка {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} нотаток"
|
||||
},
|
||||
"collections": {
|
||||
|
||||
10
apps/client/src/types-lib.d.ts
vendored
10
apps/client/src/types-lib.d.ts
vendored
@@ -63,11 +63,13 @@ declare global {
|
||||
|
||||
declare module "preact" {
|
||||
namespace JSX {
|
||||
interface ElectronWebViewElement extends JSX.HTMLAttributes<HTMLElement> {
|
||||
src: string;
|
||||
class: string;
|
||||
}
|
||||
|
||||
interface IntrinsicElements {
|
||||
webview: {
|
||||
src: string;
|
||||
class: string;
|
||||
}
|
||||
webview: ElectronWebViewElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
apps/client/src/types.d.ts
vendored
2
apps/client/src/types.d.ts
vendored
@@ -119,7 +119,7 @@ declare global {
|
||||
setNote(noteId: string);
|
||||
}
|
||||
|
||||
var logError: (message: string, e?: Error | string) => void;
|
||||
var logError: (message: string, e?: unknown) => void;
|
||||
var logInfo: (message: string) => void;
|
||||
var glob: CustomGlobals;
|
||||
//@ts-ignore
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import "./NoteDetail.css";
|
||||
|
||||
import clsx from "clsx";
|
||||
import { note } from "mermaid/dist/rendering-util/rendering-elements/shapes/note.js";
|
||||
import { isValidElement, VNode } from "preact";
|
||||
import { useEffect, useRef, useState } from "preact/hooks";
|
||||
|
||||
@@ -355,6 +356,14 @@ export function checkFullHeight(noteContext: NoteContext | undefined, type: Exte
|
||||
// https://github.com/zadam/trilium/issues/2522
|
||||
const isBackendNote = noteContext?.noteId === "_backendLog";
|
||||
const isFullHeightNoteType = type && TYPE_MAPPINGS[type].isFullHeight;
|
||||
|
||||
// Allow vertical centering when there are no results.
|
||||
if (type === "book" &&
|
||||
[ "grid", "list" ].includes(noteContext.note?.getLabelValue("viewType") ?? "grid") &&
|
||||
!noteContext.note?.hasChildren()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (!noteContext?.hasNoteList() && isFullHeightNoteType)
|
||||
|| noteContext?.viewScope?.viewMode === "attachments"
|
||||
|| isBackendNote;
|
||||
@@ -370,7 +379,33 @@ function showToast(type: "printing" | "exporting_pdf", progress: number = 0) {
|
||||
}
|
||||
|
||||
function handlePrintReport(printReport?: PrintReport) {
|
||||
if (printReport?.type === "collection" && printReport.ignoredNoteIds.length > 0) {
|
||||
if (!printReport) return;
|
||||
|
||||
if (printReport.type === "error") {
|
||||
toast.showPersistent({
|
||||
id: "print-error",
|
||||
icon: "bx bx-error-circle",
|
||||
title: t("note_detail.print_report_error_title"),
|
||||
message: printReport.message,
|
||||
buttons: printReport.stack ? [
|
||||
{
|
||||
text: t("note_detail.print_report_collection_details_button"),
|
||||
onClick(api) {
|
||||
api.dismissToast();
|
||||
dialog.info(<>
|
||||
<p>{printReport.message}</p>
|
||||
<details>
|
||||
<summary>{t("note_detail.print_report_stack_trace")}</summary>
|
||||
<pre style="font-size: 0.85em; overflow-x: auto;">{printReport.stack}</pre>
|
||||
</details>
|
||||
</>, {
|
||||
title: t("note_detail.print_report_error_title")
|
||||
});
|
||||
}
|
||||
}
|
||||
] : undefined
|
||||
});
|
||||
} else if (printReport.type === "collection" && printReport.ignoredNoteIds.length > 0) {
|
||||
toast.showPersistent({
|
||||
id: "print-report",
|
||||
icon: "bx bx-collection",
|
||||
|
||||
@@ -16,6 +16,10 @@ body.mobile .promoted-attributes-widget {
|
||||
display: table;
|
||||
}
|
||||
|
||||
body.experimental-feature-new-layout .promoted-attributes-container {
|
||||
max-height: unset;
|
||||
}
|
||||
|
||||
.promoted-attribute-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -94,4 +98,4 @@ body.mobile .promoted-attributes-widget {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
transform: rotate(45deg);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,13 @@ import "./PromotedAttributes.css";
|
||||
import { UpdateAttributeResponse } from "@triliumnext/commons";
|
||||
import clsx from "clsx";
|
||||
import { ComponentChild, HTMLInputTypeAttribute, InputHTMLAttributes, MouseEventHandler, TargetedEvent, TargetedInputEvent } from "preact";
|
||||
import { Dispatch, StateUpdater, useEffect, useRef, useState } from "preact/hooks";
|
||||
import { Dispatch, StateUpdater, useCallback, useEffect, useRef, useState } from "preact/hooks";
|
||||
|
||||
import NoteContext from "../components/note_context";
|
||||
import FAttribute from "../entities/fattribute";
|
||||
import FNote from "../entities/fnote";
|
||||
import { Attribute } from "../services/attribute_parser";
|
||||
import attributes from "../services/attributes";
|
||||
import debounce from "../services/debounce";
|
||||
import { t } from "../services/i18n";
|
||||
import { DefinitionObject, extractAttributeDefinitionTypeAndName, LabelType } from "../services/promoted_attribute_definition_parser";
|
||||
import server from "../services/server";
|
||||
@@ -38,7 +37,7 @@ interface CellProps {
|
||||
}
|
||||
|
||||
type OnChangeEventData = TargetedEvent<HTMLInputElement, Event> | InputEvent | JQuery.TriggeredEvent<HTMLInputElement, undefined, HTMLInputElement, HTMLInputElement>;
|
||||
type OnChangeListener = (e: OnChangeEventData) => Promise<void>;
|
||||
type OnChangeListener = (e: OnChangeEventData) => void | Promise<void>;
|
||||
|
||||
export default function PromotedAttributes() {
|
||||
const { note, componentId, noteContext } = useNoteContext();
|
||||
@@ -110,7 +109,7 @@ export function usePromotedAttributeData(note: FNote | null | undefined, compone
|
||||
valueAttrs = valueAttrs.slice(0, 1);
|
||||
}
|
||||
|
||||
for (const [ i, valueAttr ] of valueAttrs.entries()) {
|
||||
for (const valueAttr of valueAttrs) {
|
||||
const definition = definitionAttr.getDefinition();
|
||||
|
||||
// if not owned, we'll force creation of a new attribute instead of updating the inherited one
|
||||
@@ -183,19 +182,34 @@ const LABEL_MAPPINGS: Record<LabelType, HTMLInputTypeAttribute> = {
|
||||
url: "url"
|
||||
};
|
||||
|
||||
function LabelInput({ inputId, ...props }: CellProps & { inputId: string }) {
|
||||
const { valueName, valueAttr, definition, definitionAttr } = props.cell;
|
||||
const onChangeListener = buildPromotedAttributeLabelChangedListener({...props});
|
||||
function LabelInput(props: CellProps & { inputId: string }) {
|
||||
const { inputId, note, cell, componentId, setCells } = props;
|
||||
const { valueName, valueAttr, definition, definitionAttr } = cell;
|
||||
const [ valueDraft, setDraft ] = useState(valueAttr.value);
|
||||
const onChangeListener = useCallback(async (e: OnChangeEventData) => {
|
||||
const inputEl = e.target as HTMLInputElement;
|
||||
let value: string;
|
||||
|
||||
if (inputEl.type === "checkbox") {
|
||||
value = inputEl.checked ? "true" : "false";
|
||||
} else {
|
||||
value = inputEl.value;
|
||||
}
|
||||
|
||||
await updateAttribute(note, cell, componentId, value, setCells);
|
||||
}, [ cell, componentId, note, setCells ]);
|
||||
const extraInputProps: InputHTMLAttributes = {};
|
||||
|
||||
useEffect(() => {
|
||||
if (definition.labelType === "text") {
|
||||
const el = document.getElementById(inputId);
|
||||
if (el) {
|
||||
setupTextLabelAutocomplete(el as HTMLInputElement, valueAttr, onChangeListener);
|
||||
}
|
||||
useTextLabelAutocomplete(inputId, valueAttr, definition, (e) => {
|
||||
if (e.currentTarget instanceof HTMLInputElement) {
|
||||
setDraft(e.currentTarget.value);
|
||||
}
|
||||
}, [ inputId, valueAttr, onChangeListener ]);
|
||||
});
|
||||
|
||||
// React to model changes.
|
||||
useEffect(() => {
|
||||
setDraft(valueAttr.value);
|
||||
}, [ valueAttr.value ]);
|
||||
|
||||
switch (definition.labelType) {
|
||||
case "number": {
|
||||
@@ -217,13 +231,13 @@ function LabelInput({ inputId, ...props }: CellProps & { inputId: string }) {
|
||||
tabIndex={200 + definitionAttr.position}
|
||||
id={inputId}
|
||||
type={LABEL_MAPPINGS[definition.labelType ?? "text"]}
|
||||
value={valueAttr.value}
|
||||
value={valueDraft}
|
||||
checked={definition.labelType === "boolean" ? valueAttr.value === "true" : undefined}
|
||||
placeholder={t("promoted_attributes.unset-field-placeholder")}
|
||||
data-attribute-id={valueAttr.attributeId}
|
||||
data-attribute-type={valueAttr.type}
|
||||
data-attribute-name={valueAttr.name}
|
||||
onChange={onChangeListener}
|
||||
onBlur={onChangeListener}
|
||||
{...extraInputProps}
|
||||
/>;
|
||||
|
||||
@@ -399,16 +413,27 @@ function InputButton({ icon, className, title, onClick }: {
|
||||
);
|
||||
}
|
||||
|
||||
function setupTextLabelAutocomplete(el: HTMLInputElement, valueAttr: Attribute, onChangeListener: OnChangeListener) {
|
||||
// no need to await for this, can be done asynchronously
|
||||
const $input = $(el);
|
||||
server.get<string[]>(`attribute-values/${encodeURIComponent(valueAttr.name)}`).then((_attributeValues) => {
|
||||
if (_attributeValues.length === 0) {
|
||||
function useTextLabelAutocomplete(inputId: string, valueAttr: Attribute, definition: DefinitionObject, onChangeListener: OnChangeListener) {
|
||||
const [ attributeValues, setAttributeValues ] = useState<{ value: string }[] | null>(null);
|
||||
|
||||
// Obtain data.
|
||||
useEffect(() => {
|
||||
if (definition.labelType !== "text") {
|
||||
return;
|
||||
}
|
||||
|
||||
const attributeValues = _attributeValues.map((attribute) => ({ value: attribute }));
|
||||
server.get<string[]>(`attribute-values/${encodeURIComponent(valueAttr.name)}`).then((_attributesValues) => {
|
||||
setAttributeValues(_attributesValues.map((attribute) => ({ value: attribute })));
|
||||
});
|
||||
}, [ definition.labelType, valueAttr.name ]);
|
||||
|
||||
// Initialize autocomplete.
|
||||
useEffect(() => {
|
||||
if (attributeValues?.length === 0) return;
|
||||
const el = document.getElementById(inputId) as HTMLInputElement | null;
|
||||
if (!el) return;
|
||||
|
||||
const $input = $(el);
|
||||
$input.autocomplete(
|
||||
{
|
||||
appendTo: document.querySelector("body"),
|
||||
@@ -424,7 +449,7 @@ function setupTextLabelAutocomplete(el: HTMLInputElement, valueAttr: Attribute,
|
||||
source (term, cb) {
|
||||
term = term.toLowerCase();
|
||||
|
||||
const filtered = attributeValues.filter((attr) => attr.value.toLowerCase().includes(term));
|
||||
const filtered = (attributeValues ?? []).filter((attr) => attr.value.toLowerCase().includes(term));
|
||||
|
||||
cb(filtered);
|
||||
}
|
||||
@@ -434,27 +459,13 @@ function setupTextLabelAutocomplete(el: HTMLInputElement, valueAttr: Attribute,
|
||||
|
||||
$input.off("autocomplete:selected");
|
||||
$input.on("autocomplete:selected", onChangeListener);
|
||||
});
|
||||
}
|
||||
|
||||
function buildPromotedAttributeLabelChangedListener({ note, cell, componentId, setCells }: CellProps): OnChangeListener {
|
||||
async function onChange(e: OnChangeEventData) {
|
||||
const inputEl = e.target as HTMLInputElement;
|
||||
let value: string;
|
||||
|
||||
if (inputEl.type === "checkbox") {
|
||||
value = inputEl.checked ? "true" : "false";
|
||||
} else {
|
||||
value = inputEl.value;
|
||||
}
|
||||
|
||||
await updateAttribute(note, cell, componentId, value, setCells);
|
||||
}
|
||||
|
||||
return debounce(onChange, 250);
|
||||
return () => $input.autocomplete("destroy");
|
||||
}, [ inputId, attributeValues, onChangeListener ]);
|
||||
}
|
||||
|
||||
async function updateAttribute(note: FNote, cell: Cell, componentId: string, value: string | undefined, setCells: Dispatch<StateUpdater<Cell[] | undefined>>) {
|
||||
if (value === cell.valueAttr.value) return;
|
||||
const { attributeId } = await server.put<UpdateAttributeResponse>(
|
||||
`notes/${note.noteId}/attribute`,
|
||||
{
|
||||
|
||||
@@ -47,6 +47,7 @@ export default function GlobalMenu({ isHorizontalLayout }: { isHorizontalLayout:
|
||||
>
|
||||
{isMobile() && <>
|
||||
<MenuItem command="searchNotes" icon="bx bx-search" text={t("global_menu.search_notes")} />
|
||||
<MenuItem command="showRecentChanges" icon="bx bx-history" text={t("recent_changes.title")} />
|
||||
<FormDropdownDivider />
|
||||
</>}
|
||||
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
min-height: 0;
|
||||
max-width: var(--max-content-width); /* Inherited from .note-split */
|
||||
|
||||
overflow: auto;
|
||||
overflow: visible;
|
||||
contain: none !important;
|
||||
|
||||
&.full-height {
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
body.prefers-centered-content .note-list-widget:not(.full-height) {
|
||||
@@ -19,14 +23,3 @@ body.prefers-centered-content .note-list-widget:not(.full-height) {
|
||||
.note-list-widget video {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* #region Pagination */
|
||||
.note-list-pager {
|
||||
font-size: 1rem;
|
||||
|
||||
span.current-page {
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
/* #endregion */
|
||||
|
||||
88
apps/client/src/widgets/collections/Pagination.css
Normal file
88
apps/client/src/widgets/collections/Pagination.css
Normal file
@@ -0,0 +1,88 @@
|
||||
:where(.note-list-pager) {
|
||||
--note-list-pager-page-button-width: 40px;
|
||||
--note-list-pager-page-button-gap: 3px;
|
||||
--note-list-pager-ellipsis-width: 20px;
|
||||
--note-list-pager-justify-content: flex-end;
|
||||
|
||||
--note-list-pager-current-page-button-background-color: var(--button-group-active-button-background);
|
||||
--note-list-pager-current-page-button-text-color: var(--button-group-active-button-text-color);
|
||||
}
|
||||
|
||||
.note-list-pager-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
container: note-list-pager / inline-size;
|
||||
}
|
||||
|
||||
.note-list-pager {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: .8rem;
|
||||
align-self: var(--note-list-pager-justify-content);
|
||||
|
||||
.note-list-pager-nav-button {
|
||||
--icon-button-icon-ratio: .75;
|
||||
}
|
||||
|
||||
.note-list-pager-page-button-container {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-around;
|
||||
gap: var(--note-list-pager-page-button-gap);
|
||||
|
||||
&.note-list-pager-ellipsis-present {
|
||||
/* Prevent the prev/next buttons from shifting when ellipses appear or disappear */
|
||||
--_gap-max-width: calc((var(--note-list-pager-page-button-count) + 2) * var(--note-list-pager-page-button-gap));
|
||||
|
||||
min-width: calc(var(--note-list-pager-page-button-count) * var(--note-list-pager-page-button-width)
|
||||
+ (var(--note-list-pager-ellipsis-width) * 2)
|
||||
+ var(--_gap-max-width));
|
||||
}
|
||||
|
||||
.note-list-pager-page-button {
|
||||
min-width: var(--note-list-pager-page-button-width);
|
||||
padding-inline: 0;
|
||||
padding-block: 4px;
|
||||
|
||||
&.note-list-pager-page-button-current {
|
||||
background: var(--note-list-pager-current-page-button-background-color);
|
||||
color: var(--note-list-pager-current-page-button-text-color);
|
||||
font-weight: bold;
|
||||
opacity: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.note-list-pager-ellipsis {
|
||||
display: inline-block;
|
||||
width: var(--note-list-pager-ellipsis-width);
|
||||
text-align: center;
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
|
||||
.note-list-pager-narrow-counter {
|
||||
display: none;
|
||||
min-width: 60px;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.note-list-pager-total-count {
|
||||
margin-inline-start: 8px;
|
||||
opacity: .5;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@container note-list-pager (max-width: 550px) {
|
||||
.note-list-pager-page-button-container,
|
||||
.note-list-pager-total-count {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.note-list-pager-narrow-counter {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,10 @@ import FNote from "../../entities/fnote";
|
||||
import froca from "../../services/froca";
|
||||
import { useNoteLabelInt } from "../react/hooks";
|
||||
import { t } from "../../services/i18n";
|
||||
import ActionButton from "../react/ActionButton";
|
||||
import Button from "../react/Button";
|
||||
import "./Pagination.css";
|
||||
import clsx from "clsx";
|
||||
|
||||
interface PaginationContext {
|
||||
page: number;
|
||||
@@ -17,46 +21,106 @@ interface PaginationContext {
|
||||
export function Pager({ page, pageSize, setPage, pageCount, totalNotes }: Omit<PaginationContext, "pageNotes">) {
|
||||
if (pageCount < 2) return;
|
||||
|
||||
let lastPrinted = false;
|
||||
let children: ComponentChildren[] = [];
|
||||
for (let i = 1; i <= pageCount; i++) {
|
||||
if (pageCount < 20 || i <= 5 || pageCount - i <= 5 || Math.abs(page - i) <= 2) {
|
||||
lastPrinted = true;
|
||||
|
||||
const startIndex = (i - 1) * pageSize + 1;
|
||||
const endIndex = Math.min(totalNotes, i * pageSize);
|
||||
|
||||
if (i !== page) {
|
||||
children.push((
|
||||
<a
|
||||
href="javascript:"
|
||||
title={t("pagination.page_title", { startIndex, endIndex })}
|
||||
onClick={() => setPage(i)}
|
||||
>
|
||||
{i}
|
||||
</a>
|
||||
))
|
||||
} else {
|
||||
// Current page
|
||||
children.push(<span className="current-page">{i}</span>)
|
||||
}
|
||||
|
||||
children.push(<>{" "} {" "}</>);
|
||||
} else if (lastPrinted) {
|
||||
children.push(<>{"... "} {" "}</>);
|
||||
lastPrinted = false;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="note-list-pager">
|
||||
{children}
|
||||
<div className="note-list-pager-container">
|
||||
<div className="note-list-pager">
|
||||
<ActionButton
|
||||
icon="bx bx-chevron-left"
|
||||
className="note-list-pager-nav-button"
|
||||
disabled={(page === 1)}
|
||||
text={t("pagination.prev_page")}
|
||||
onClick={() => setPage(page - 1)}
|
||||
/>
|
||||
|
||||
<span className="note-list-pager-total-count">({t("pagination.total_notes", { count: totalNotes })})</span>
|
||||
<PageButtons page={page} setPage={setPage} pageCount={pageCount} />
|
||||
<div className="note-list-pager-narrow-counter">
|
||||
<strong>{page}</strong> / <strong>{pageCount}</strong>
|
||||
</div>
|
||||
|
||||
<ActionButton
|
||||
icon="bx bx-chevron-right"
|
||||
className="note-list-pager-nav-button"
|
||||
disabled={(page === pageCount)}
|
||||
text={t("pagination.next_page")}
|
||||
onClick={() => setPage(page + 1)}
|
||||
/>
|
||||
|
||||
<div className="note-list-pager-total-count">
|
||||
{t("pagination.total_notes", { count: totalNotes })}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
interface PageButtonsProps {
|
||||
page: number;
|
||||
setPage: Dispatch<StateUpdater<number>>;
|
||||
pageCount: number;
|
||||
}
|
||||
|
||||
function PageButtons(props: PageButtonsProps) {
|
||||
const maxButtonCount = 9;
|
||||
const maxLeftRightSegmentLength = 2;
|
||||
|
||||
// The left-side segment
|
||||
const leftLength = Math.min(props.pageCount, maxLeftRightSegmentLength);
|
||||
const leftStart = 1;
|
||||
|
||||
// The middle segment
|
||||
const middleMaxLength = maxButtonCount - maxLeftRightSegmentLength * 2;
|
||||
const middleLength = Math.min(props.pageCount - leftLength, middleMaxLength);
|
||||
let middleStart = props.page - Math.floor(middleLength / 2);
|
||||
middleStart = Math.max(middleStart, leftLength + 1);
|
||||
|
||||
// The right-side segment
|
||||
const rightLength = Math.min(props.pageCount - (middleLength + leftLength), maxLeftRightSegmentLength);
|
||||
const rightStart = props.pageCount - rightLength + 1;
|
||||
middleStart = Math.min(middleStart, rightStart - middleLength);
|
||||
|
||||
const totalButtonCount = leftLength + middleLength + rightLength;
|
||||
const hasLeadingEllipsis = (middleStart - leftLength > 1);
|
||||
const hasTrailingEllipsis = (rightStart - (middleStart + middleLength - 1) > 1);
|
||||
|
||||
return <div className={clsx("note-list-pager-page-button-container", {
|
||||
"note-list-pager-ellipsis-present": (totalButtonCount === maxButtonCount)
|
||||
})}
|
||||
style={{"--note-list-pager-page-button-count": totalButtonCount}}>
|
||||
{[
|
||||
...createSegment(leftStart, leftLength, props.page, props.setPage, false),
|
||||
...createSegment(middleStart, middleLength, props.page, props.setPage, hasLeadingEllipsis),
|
||||
...createSegment(rightStart, rightLength, props.page, props.setPage, hasTrailingEllipsis),
|
||||
]}
|
||||
</div>;
|
||||
}
|
||||
|
||||
function createSegment(start: number, length: number, currentPage: number, setPage: Dispatch<StateUpdater<number>>, prependEllipsis: boolean): ComponentChildren[] {
|
||||
const children: ComponentChildren[] = [];
|
||||
|
||||
if (prependEllipsis) {
|
||||
children.push(<span className="note-list-pager-ellipsis">...</span>);
|
||||
}
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
const pageNum = start + i;
|
||||
const isCurrent = (pageNum === currentPage);
|
||||
children.push((
|
||||
<Button
|
||||
text={pageNum.toString()}
|
||||
kind="lowProfile"
|
||||
className={clsx(
|
||||
"note-list-pager-page-button",
|
||||
{"note-list-pager-page-button-current": isCurrent}
|
||||
)}
|
||||
disabled={isCurrent}
|
||||
onClick={() => setPage(pageNum)}
|
||||
/>
|
||||
));
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
export function usePagination(note: FNote, noteIds: string[]): PaginationContext {
|
||||
const [ page, setPage ] = useState(1);
|
||||
const [ pageNotes, setPageNotes ] = useState<FNote[]>();
|
||||
|
||||
@@ -79,6 +79,7 @@ export const LOCALE_MAPPINGS: Record<DISPLAYABLE_LOCALE_IDS, (() => Promise<{ de
|
||||
es: () => import("@fullcalendar/core/locales/es"),
|
||||
fr: () => import("@fullcalendar/core/locales/fr"),
|
||||
it: () => import("@fullcalendar/core/locales/it"),
|
||||
hi: () => import("@fullcalendar/core/locales/hi"),
|
||||
ga: null,
|
||||
cn: () => import("@fullcalendar/core/locales/zh-cn"),
|
||||
tw: () => import("@fullcalendar/core/locales/zh-tw"),
|
||||
@@ -307,11 +308,11 @@ function useEditing(note: FNote, isEditable: boolean, isCalendarRoot: boolean, c
|
||||
|
||||
// Called upon when clicking the day number in the calendar, opens or creates the day note but only if in a calendar root.
|
||||
const onDateClick = useCallback(async (e: DateClickArg) => {
|
||||
const eventNote = await date_notes.getDayNote(e.dateStr);
|
||||
const eventNote = await date_notes.getDayNote(e.dateStr, note.noteId);
|
||||
if (eventNote) {
|
||||
appContext.triggerCommand("openInPopup", { noteIdOrPath: eventNote.noteId });
|
||||
}
|
||||
}, []);
|
||||
}, [ note ]);
|
||||
|
||||
return {
|
||||
select: onCalendarSelection,
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
|
||||
> .collection-properties {
|
||||
position: relative;
|
||||
z-index: 2000;
|
||||
}
|
||||
}
|
||||
|
||||
.geo-map-container {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.maplibregl-canvas-container {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.leaflet-pane {
|
||||
@@ -22,7 +25,7 @@
|
||||
|
||||
.leaflet-top,
|
||||
.leaflet-bottom {
|
||||
z-index: 997;
|
||||
z-index: 997 !important;
|
||||
}
|
||||
|
||||
.geo-view.placing-note .geo-map-container {
|
||||
|
||||
@@ -22,7 +22,7 @@ import { ViewModeProps } from "../interface";
|
||||
import { createNewNote, moveMarker } from "./api";
|
||||
import openContextMenu, { openMapContextMenu } from "./context_menu";
|
||||
import Map from "./map";
|
||||
import { DEFAULT_MAP_LAYER_NAME } from "./map_layer";
|
||||
import { DEFAULT_MAP_LAYER_NAME, MAP_LAYERS, MapLayer } from "./map_layer";
|
||||
import Marker, { GpxTrack } from "./marker";
|
||||
|
||||
const DEFAULT_COORDINATES: [number, number] = [3.878638227135724, 446.6630455551659];
|
||||
@@ -45,10 +45,11 @@ export default function GeoView({ note, noteIds, viewConfig, saveConfig }: ViewM
|
||||
const [ state, setState ] = useState(State.Normal);
|
||||
const [ coordinates, setCoordinates ] = useState(viewConfig?.view?.center);
|
||||
const [ zoom, setZoom ] = useState(viewConfig?.view?.zoom);
|
||||
const [ layerName ] = useNoteLabel(note, "map:style");
|
||||
const [ hasScale ] = useNoteLabelBoolean(note, "map:scale");
|
||||
const [ hideLabels ] = useNoteLabelBoolean(note, "map:hideLabels");
|
||||
const [ isReadOnly ] = useNoteLabelBoolean(note, "readOnly");
|
||||
const [ notes, setNotes ] = useState<FNote[]>([]);
|
||||
const layerData = useLayerData(note);
|
||||
const spacedUpdate = useSpacedUpdate(() => {
|
||||
if (viewConfig) {
|
||||
saveConfig(viewConfig);
|
||||
@@ -152,7 +153,7 @@ export default function GeoView({ note, noteIds, viewConfig, saveConfig }: ViewM
|
||||
apiRef={apiRef} containerRef={containerRef}
|
||||
coordinates={coordinates}
|
||||
zoom={zoom}
|
||||
layerName={layerName ?? DEFAULT_MAP_LAYER_NAME}
|
||||
layerData={layerData}
|
||||
viewportChanged={(coordinates, zoom) => {
|
||||
if (!viewConfig) viewConfig = {};
|
||||
viewConfig.view = { center: coordinates, zoom };
|
||||
@@ -162,13 +163,35 @@ export default function GeoView({ note, noteIds, viewConfig, saveConfig }: ViewM
|
||||
onContextMenu={onContextMenu}
|
||||
scale={hasScale}
|
||||
>
|
||||
{notes.map(note => <NoteWrapper note={note} isReadOnly={isReadOnly} />)}
|
||||
{notes.map(note => <NoteWrapper note={note} isReadOnly={isReadOnly} hideLabels={hideLabels} />)}
|
||||
</Map>}
|
||||
<GeoMapTouchBar state={state} map={apiRef.current} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function useLayerData(note: FNote) {
|
||||
const [ layerName ] = useNoteLabel(note, "map:style");
|
||||
// Memo is needed because it would generate unnecessary reloads due to layer change.
|
||||
const layerData = useMemo(() => {
|
||||
// Custom layers.
|
||||
if (layerName?.startsWith("http")) {
|
||||
return {
|
||||
name: "Custom",
|
||||
type: "raster",
|
||||
url: layerName,
|
||||
attribution: ""
|
||||
} satisfies MapLayer;
|
||||
}
|
||||
|
||||
// Built-in layers.
|
||||
const layerData = MAP_LAYERS[layerName ?? ""] ?? MAP_LAYERS[DEFAULT_MAP_LAYER_NAME];
|
||||
return layerData;
|
||||
}, [ layerName ]);
|
||||
|
||||
return layerData;
|
||||
}
|
||||
|
||||
function ToggleReadOnlyButton({ note }: { note: FNote }) {
|
||||
const [ isReadOnly, setReadOnly ] = useNoteLabelBoolean(note, "readOnly");
|
||||
|
||||
@@ -179,22 +202,26 @@ function ToggleReadOnlyButton({ note }: { note: FNote }) {
|
||||
/>;
|
||||
}
|
||||
|
||||
function NoteWrapper({ note, isReadOnly }: { note: FNote, isReadOnly: boolean }) {
|
||||
function NoteWrapper({ note, isReadOnly, hideLabels }: {
|
||||
note: FNote,
|
||||
isReadOnly: boolean,
|
||||
hideLabels: boolean
|
||||
}) {
|
||||
const mime = useNoteProperty(note, "mime");
|
||||
const [ location ] = useNoteLabel(note, LOCATION_ATTRIBUTE);
|
||||
|
||||
if (mime === "application/gpx+xml") {
|
||||
return <NoteGpxTrack note={note} />;
|
||||
return <NoteGpxTrack note={note} hideLabels={hideLabels} />;
|
||||
}
|
||||
|
||||
if (location) {
|
||||
const latLng = location?.split(",", 2).map((el) => parseFloat(el)) as [ number, number ] | undefined;
|
||||
if (!latLng) return;
|
||||
return <NoteMarker note={note} editable={!isReadOnly} latLng={latLng} />;
|
||||
return <NoteMarker note={note} editable={!isReadOnly} latLng={latLng} hideLabels={hideLabels} />;
|
||||
}
|
||||
}
|
||||
|
||||
function NoteMarker({ note, editable, latLng }: { note: FNote, editable: boolean, latLng: [number, number] }) {
|
||||
function NoteMarker({ note, editable, latLng, hideLabels }: { note: FNote, editable: boolean, latLng: [number, number], hideLabels: boolean }) {
|
||||
// React to changes
|
||||
const [ color ] = useNoteLabel(note, "color");
|
||||
const [ iconClass ] = useNoteLabel(note, "iconClass");
|
||||
@@ -202,8 +229,9 @@ function NoteMarker({ note, editable, latLng }: { note: FNote, editable: boolean
|
||||
|
||||
const title = useNoteProperty(note, "title");
|
||||
const icon = useMemo(() => {
|
||||
return buildIcon(note.getIcon(), note.getColorClass() ?? undefined, title, note.noteId, archived);
|
||||
}, [ iconClass, color, title, note.noteId, archived]);
|
||||
const titleOrNone = hideLabels ? undefined : title;
|
||||
return buildIcon(note.getIcon(), note.getColorClass() ?? undefined, titleOrNone, note.noteId, archived);
|
||||
}, [ iconClass, color, title, note.noteId, archived, hideLabels ]);
|
||||
|
||||
const onClick = useCallback(() => {
|
||||
appContext.triggerCommand("openInPopup", { noteIdOrPath: note.noteId });
|
||||
@@ -235,7 +263,7 @@ function NoteMarker({ note, editable, latLng }: { note: FNote, editable: boolean
|
||||
/>;
|
||||
}
|
||||
|
||||
function NoteGpxTrack({ note }: { note: FNote }) {
|
||||
function NoteGpxTrack({ note, hideLabels }: { note: FNote, hideLabels?: boolean }) {
|
||||
const [ xmlString, setXmlString ] = useState<string>();
|
||||
const blob = useNoteBlob(note);
|
||||
|
||||
@@ -256,7 +284,7 @@ function NoteGpxTrack({ note }: { note: FNote }) {
|
||||
|
||||
const options = useMemo<GPXOptions>(() => ({
|
||||
markers: {
|
||||
startIcon: buildIcon(note.getIcon(), note.getColorClass(), note.title),
|
||||
startIcon: buildIcon(note.getIcon(), note.getColorClass(), hideLabels ? undefined : note.title),
|
||||
endIcon: buildIcon("bxs-flag-checkered"),
|
||||
wptIcons: {
|
||||
"": buildIcon("bx bx-pin")
|
||||
@@ -265,7 +293,7 @@ function NoteGpxTrack({ note }: { note: FNote }) {
|
||||
polyline_options: {
|
||||
color: note.getLabelValue("color") ?? "blue"
|
||||
}
|
||||
}), [ color, iconClass ]);
|
||||
}), [ color, iconClass, hideLabels ]);
|
||||
return xmlString && <GpxTrack gpxXmlString={xmlString} options={options} />;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useImperativeHandle, useRef, useState } from "preact/hooks";
|
||||
import L, { control, LatLng, Layer, LeafletMouseEvent } from "leaflet";
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import { MAP_LAYERS } from "./map_layer";
|
||||
import { MAP_LAYERS, type MapLayer } from "./map_layer";
|
||||
import { ComponentChildren, createContext, RefObject } from "preact";
|
||||
import { useElementSize, useSyncedRef } from "../../react/hooks";
|
||||
|
||||
@@ -12,7 +12,7 @@ interface MapProps {
|
||||
containerRef?: RefObject<HTMLDivElement>;
|
||||
coordinates: LatLng | [number, number];
|
||||
zoom: number;
|
||||
layerName: string;
|
||||
layerData: MapLayer;
|
||||
viewportChanged: (coordinates: LatLng, zoom: number) => void;
|
||||
children: ComponentChildren;
|
||||
onClick?: (e: LeafletMouseEvent) => void;
|
||||
@@ -21,7 +21,7 @@ interface MapProps {
|
||||
scale: boolean;
|
||||
}
|
||||
|
||||
export default function Map({ coordinates, zoom, layerName, viewportChanged, children, onClick, onContextMenu, scale, apiRef, containerRef: _containerRef, onZoom }: MapProps) {
|
||||
export default function Map({ coordinates, zoom, layerData, viewportChanged, children, onClick, onContextMenu, scale, apiRef, containerRef: _containerRef, onZoom }: MapProps) {
|
||||
const mapRef = useRef<L.Map>(null);
|
||||
const containerRef = useSyncedRef<HTMLDivElement>(_containerRef);
|
||||
|
||||
@@ -49,8 +49,6 @@ export default function Map({ coordinates, zoom, layerName, viewportChanged, chi
|
||||
const [ layer, setLayer ] = useState<Layer>();
|
||||
useEffect(() => {
|
||||
async function load() {
|
||||
const layerData = MAP_LAYERS[layerName];
|
||||
|
||||
if (layerData.type === "vector") {
|
||||
const style = (typeof layerData.style === "string" ? layerData.style : await layerData.style());
|
||||
await import("@maplibre/maplibre-gl-leaflet");
|
||||
@@ -68,7 +66,7 @@ export default function Map({ coordinates, zoom, layerName, viewportChanged, chi
|
||||
}
|
||||
|
||||
load();
|
||||
}, [ layerName ]);
|
||||
}, [ layerData ]);
|
||||
|
||||
// Attach layer to the map.
|
||||
useEffect(() => {
|
||||
@@ -139,7 +137,7 @@ export default function Map({ coordinates, zoom, layerName, viewportChanged, chi
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={`geo-map-container ${MAP_LAYERS[layerName].isDarkTheme ? "dark" : ""}`}
|
||||
className={`geo-map-container ${layerData.isDarkTheme ? "dark" : ""}`}
|
||||
>
|
||||
<ParentMap.Provider value={mapRef.current}>
|
||||
{children}
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
export interface MapLayer {
|
||||
name: string;
|
||||
isDarkTheme?: boolean;
|
||||
}
|
||||
|
||||
interface VectorLayer extends MapLayer {
|
||||
export type MapLayer = ({
|
||||
type: "vector";
|
||||
style: string | (() => Promise<{}>)
|
||||
}
|
||||
|
||||
interface RasterLayer extends MapLayer {
|
||||
} | {
|
||||
type: "raster";
|
||||
url: string;
|
||||
attribution: string;
|
||||
}
|
||||
}) & {
|
||||
// Common properties
|
||||
name: string;
|
||||
isDarkTheme?: boolean;
|
||||
};
|
||||
|
||||
export const MAP_LAYERS: Record<string, VectorLayer | RasterLayer> = {
|
||||
export const MAP_LAYERS: Record<string, MapLayer> = {
|
||||
"openstreetmap": {
|
||||
name: "OpenStreetMap",
|
||||
type: "raster",
|
||||
|
||||
@@ -1,151 +1,398 @@
|
||||
.note-list {
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
||||
.note-list-wrapper {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
&.grid-view .note-list-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.note-book-card {
|
||||
border-radius: 10px;
|
||||
background-color: var(--accented-background-color);
|
||||
padding: 10px 15px 15px 8px;
|
||||
margin: 5px 5px 5px 5px;
|
||||
/* #region List view / Grid view common styles */
|
||||
|
||||
.nested-note-list-item h5,
|
||||
.note-book-card .note-book-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1em;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
|
||||
.tn-icon {
|
||||
font-size: 1.2em;
|
||||
margin-inline-end: 8px;
|
||||
}
|
||||
|
||||
.note-book-title {
|
||||
--link-hover-background: transparent;
|
||||
--link-hover-color: currentColor;
|
||||
color: inherit;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.note-book-item-menu {
|
||||
margin-inline-start: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.nested-note-list-item.use-note-color,
|
||||
.note-book-card.use-note-color .note-book-header {
|
||||
span.tn-icon + span,
|
||||
.tn-icon,
|
||||
.rendered-note-attributes {
|
||||
color: var(--custom-color);
|
||||
}
|
||||
}
|
||||
|
||||
/* Search result view */
|
||||
.nested-note-list.search-results .nested-note-list-item,
|
||||
.note-list-container.search-results .note-book-card .note-book-header {
|
||||
span.tn-icon + span > span {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
small {
|
||||
line-height: .85em;
|
||||
}
|
||||
|
||||
.note-path {
|
||||
opacity: 0.5;
|
||||
margin-left: 0;
|
||||
font-size: .85em;
|
||||
line-height: .85em;
|
||||
font-weight: 500;
|
||||
letter-spacing: .5pt;
|
||||
}
|
||||
|
||||
.tn-icon {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 1.75em;
|
||||
height: 1.75em;
|
||||
margin-inline-end: 12px;
|
||||
border-radius: 50%;
|
||||
background: var(--note-icon-custom-background-color, var(--note-list-view-large-icon-background));
|
||||
font-size: 1.2em;
|
||||
color: var(--note-icon-custom-color, var(--note-list-view-large-icon-color));
|
||||
}
|
||||
|
||||
.ck-find-result {
|
||||
background: var(--note-list-view-search-result-highlight-background);
|
||||
color: var(--note-list-view-search-result-highlight-color);
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes note-preview-show {
|
||||
from {
|
||||
opacity: 0;
|
||||
} to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.nested-note-list .note-book-content,
|
||||
.note-list-container .note-book-content {
|
||||
display: none;
|
||||
animation: note-preview-show .25s ease-out;
|
||||
will-change: opacity;
|
||||
|
||||
&.note-book-content-ready {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ck-find-result {
|
||||
outline: 2px solid var(--note-list-view-content-search-result-highlight-background);
|
||||
border-radius: 4px;
|
||||
background: var(--note-list-view-content-search-result-highlight-background);
|
||||
color: var(--note-list-view-content-search-result-highlight-color);
|
||||
}
|
||||
}
|
||||
|
||||
.note-book-content {
|
||||
height: 100%;
|
||||
|
||||
&.type-image, &.type-file, &.type-protectedSession {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&.type-image img, &.type-canvas svg {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.note-content-preview:has(.note-book-content:empty) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* #endregion */
|
||||
|
||||
/* #region List view */
|
||||
|
||||
.nested-note-list {
|
||||
--card-nested-section-indent: 25px;
|
||||
|
||||
&.search-results {
|
||||
--card-nested-section-indent: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
/* List item */
|
||||
.nested-note-list-item {
|
||||
|
||||
.note-expander {
|
||||
margin-inline-end: 4px;
|
||||
font-size: x-large;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tn-icon {
|
||||
color: var(--note-list-view-icon-color);
|
||||
}
|
||||
|
||||
.note-list-attributes {
|
||||
flex-grow: 1;
|
||||
margin-inline-start: 1em;
|
||||
text-align: right;
|
||||
font-size: .75em;
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
&.archived {
|
||||
span.tn-icon + span,
|
||||
.tn-icon {
|
||||
opacity: .6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nested-note-list:not(.search-results) h5,
|
||||
.note-book-card:not(.search-results) h5 {
|
||||
span.tn-icon + span,
|
||||
.note-list-attributes {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note content preview */
|
||||
.nested-note-list .note-book-content {
|
||||
outline: 1px solid var(--note-list-view-content-background);
|
||||
border-radius: 8px;
|
||||
background-color: var(--note-list-view-content-background);
|
||||
overflow: hidden;
|
||||
user-select: text;
|
||||
font-size: .85rem;
|
||||
|
||||
> .rendered-content > *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&.type-text {
|
||||
padding: 8px 24px;
|
||||
|
||||
.ck-content > *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.type-protectedSession {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
&.type-image {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.type-pdf {
|
||||
iframe {
|
||||
height: 50vh;
|
||||
}
|
||||
|
||||
.file-footer {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&.type-webView {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-height: 50vh;
|
||||
}
|
||||
}
|
||||
|
||||
/* #endregion */
|
||||
|
||||
/* #region Grid view */
|
||||
|
||||
.note-list .note-book-card {
|
||||
--note-list-horizontal-padding: 22px;
|
||||
--note-list-vertical-padding: 15px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.note-book-card.archived {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.note-book-card:not(.expanded) .note-book-content {
|
||||
padding: 10px
|
||||
}
|
||||
|
||||
.note-book-card.expanded .note-book-content {
|
||||
display: block;
|
||||
min-height: 0;
|
||||
height: 100%;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.note-book-content .rendered-content {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.note-book-header {
|
||||
border-bottom: 1px solid var(--main-border-color);
|
||||
margin-bottom: 0;
|
||||
padding-bottom: .5rem;
|
||||
word-break: break-all;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* not-expanded title is limited to one line only */
|
||||
.note-book-card:not(.expanded) .note-book-header {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.note-book-header .rendered-note-attributes {
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
.note-book-header .rendered-note-attributes:before {
|
||||
content: "\00a0\00a0";
|
||||
}
|
||||
|
||||
.note-book-header .note-icon {
|
||||
font-size: 100%;
|
||||
display: inline-block;
|
||||
padding-inline-end: 7px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.note-book-card .note-book-card {
|
||||
border: 1px solid var(--main-border-color);
|
||||
}
|
||||
|
||||
.note-book-content.type-image, .note-book-content.type-file, .note-book-content.type-protectedSession {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.note-book-content.type-image img, .note-book-content.type-canvas svg {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.note-book-card.type-image .note-book-content img,
|
||||
.note-book-card.type-text .note-book-content img,
|
||||
.note-book-card.type-canvas .note-book-content img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.note-book-header {
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.note-list-wrapper {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.note-expander {
|
||||
font-size: x-large;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.note-list-pager {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.note-list.list-view .note-path {
|
||||
margin-left: 0.5em;
|
||||
vertical-align: middle;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* #region Grid view */
|
||||
.note-list.grid-view .note-list-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.note-list.grid-view .note-book-card {
|
||||
flex-basis: 300px;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.note-list.grid-view .note-book-card {
|
||||
max-height: 300px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
|
||||
body.mobile & {
|
||||
flex-basis: 150px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--card-background-hover-color);
|
||||
filter: contrast(105%);
|
||||
transition: background-color 200ms ease-out;
|
||||
}
|
||||
|
||||
&:not(:has(:is(.note-book-item-menu:active, .btn-primary:active))):active {
|
||||
transform: scale(.98);
|
||||
}
|
||||
|
||||
&.archived {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.note-book-header {
|
||||
margin-bottom: 0;
|
||||
border-bottom: 1px solid var(--card-border-color, var(--main-border-color));
|
||||
padding-bottom: .5rem;
|
||||
word-break: break-all;
|
||||
flex-shrink: 0;
|
||||
padding: .5rem 1rem;
|
||||
padding-inline-end: 8px;
|
||||
|
||||
.tn-icon + span {
|
||||
flex-grow: 1;
|
||||
a {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& .note-book-content {
|
||||
&.type-image .note-book-content img,
|
||||
&.type-text .note-book-content img,
|
||||
&.type-canvas .note-book-content img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.rendered-content {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.rendered-content:has(.file-footer) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
max-height: 220px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.file-footer {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: space-between;
|
||||
padding: 0;
|
||||
|
||||
.btn.btn-primary {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
box-shadow: unset;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
padding: 8px;
|
||||
color: var(--main-text-color);
|
||||
|
||||
&:hover {
|
||||
background: var(--more-accented-background-color);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.note-list.grid-view .note-book-card img {
|
||||
max-height: 220px;
|
||||
object-fit: contain;
|
||||
.note-book-card .note-book-content {
|
||||
padding: 0;
|
||||
font-size: 0.8rem;
|
||||
|
||||
.ck-content p {
|
||||
margin-bottom: 0.5em;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.ck-content figure.image {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.rendered-content,
|
||||
.rendered-content.text-with-ellipsis {
|
||||
padding: .5rem 1rem 1rem 1rem;
|
||||
}
|
||||
|
||||
&.type-image .rendered-content,
|
||||
&.type-pdf .rendered-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-size: 1rem;
|
||||
color: var(--active-item-text-color);
|
||||
}
|
||||
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&.type-canvas .rendered-content,
|
||||
&.type-mindMap .rendered-content,
|
||||
&.type-code .rendered-content,
|
||||
&.type-video .rendered-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.type-code {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&.type-code pre {
|
||||
height: 100%;
|
||||
padding: 1em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.note-list.grid-view .note-book-card:hover {
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--main-border-color);
|
||||
background: var(--more-accented-background-color);
|
||||
}
|
||||
|
||||
.note-list.grid-view .note-path {
|
||||
margin-left: 0.5em;
|
||||
vertical-align: middle;
|
||||
opacity: 0.5;
|
||||
}
|
||||
/* #endregion */
|
||||
/* #endregion */
|
||||
@@ -1,6 +1,7 @@
|
||||
import "./ListOrGridView.css";
|
||||
import { Card, CardFrame, CardSection } from "../../react/Card";
|
||||
|
||||
import { useEffect, useRef, useState } from "preact/hooks";
|
||||
import { useCallback, useEffect, useRef, useState } from "preact/hooks";
|
||||
|
||||
import FNote from "../../../entities/fnote";
|
||||
import attribute_renderer from "../../../services/attribute_renderer";
|
||||
@@ -14,6 +15,11 @@ import NoteLink from "../../react/NoteLink";
|
||||
import { ViewModeProps } from "../interface";
|
||||
import { Pager, usePagination } from "../Pagination";
|
||||
import { filterChildNotes, useFilteredNoteIds } from "./utils";
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
import { clsx } from "clsx";
|
||||
import ActionButton from "../../react/ActionButton";
|
||||
import linkContextMenuService from "../../../menus/link_context_menu";
|
||||
import { TargetedMouseEvent } from "preact";
|
||||
|
||||
export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }: ViewModeProps<{}>) {
|
||||
const expandDepth = useExpansionDepth(note);
|
||||
@@ -24,16 +30,16 @@ export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
|
||||
const hasCollectionProperties = [ "book", "search" ].includes(noteType ?? "");
|
||||
|
||||
return (
|
||||
<div class="note-list list-view">
|
||||
<div className="note-list list-view">
|
||||
<CollectionProperties
|
||||
note={note}
|
||||
centerChildren={<Pager {...pagination} />}
|
||||
/>
|
||||
|
||||
{ noteIds.length > 0 && <div class="note-list-wrapper">
|
||||
{ noteIds.length > 0 && <div className="note-list-wrapper">
|
||||
{!hasCollectionProperties && <Pager {...pagination} />}
|
||||
|
||||
<div class="note-list-container use-tn-links">
|
||||
<Card className={clsx("nested-note-list", {"search-results": (noteType === "search")})}>
|
||||
{pageNotes?.map(childNote => (
|
||||
<ListNoteCard
|
||||
key={childNote.noteId}
|
||||
@@ -41,7 +47,7 @@ export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
|
||||
expandDepth={expandDepth} highlightedTokens={highlightedTokens}
|
||||
currentLevel={1} includeArchived={includeArchived} />
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Pager {...pagination} />
|
||||
</div>}
|
||||
@@ -57,18 +63,22 @@ export function GridView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
|
||||
const hasCollectionProperties = [ "book", "search" ].includes(noteType ?? "");
|
||||
|
||||
return (
|
||||
<div class="note-list grid-view">
|
||||
<div className="note-list grid-view">
|
||||
<CollectionProperties
|
||||
note={note}
|
||||
centerChildren={<Pager {...pagination} />}
|
||||
/>
|
||||
|
||||
<div class="note-list-wrapper">
|
||||
<div className="note-list-wrapper">
|
||||
{!hasCollectionProperties && <Pager {...pagination} />}
|
||||
|
||||
<div class="note-list-container use-tn-links">
|
||||
<div className={clsx("note-list-container use-tn-links", {"search-results": (noteType === "search")})}>
|
||||
{pageNotes?.map(childNote => (
|
||||
<GridNoteCard note={childNote} parentNote={note} highlightedTokens={highlightedTokens} includeArchived={includeArchived} />
|
||||
<GridNoteCard key={childNote.noteId}
|
||||
note={childNote}
|
||||
parentNote={note}
|
||||
highlightedTokens={highlightedTokens}
|
||||
includeArchived={includeArchived} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -93,54 +103,86 @@ function ListNoteCard({ note, parentNote, highlightedTokens, currentLevel, expan
|
||||
// Reset expand state if switching to another note, or if user manually toggled expansion state.
|
||||
useEffect(() => setExpanded(currentLevel <= expandDepth), [ note, currentLevel, expandDepth ]);
|
||||
|
||||
let subSections: JSX.Element | undefined = undefined;
|
||||
if (isExpanded) {
|
||||
subSections = <>
|
||||
<CardSection className="note-content-preview">
|
||||
<NoteContent note={note}
|
||||
highlightedTokens={highlightedTokens}
|
||||
noChildrenList
|
||||
includeArchivedNotes={includeArchived} />
|
||||
</CardSection>
|
||||
|
||||
<NoteChildren note={note}
|
||||
parentNote={parentNote}
|
||||
highlightedTokens={highlightedTokens}
|
||||
currentLevel={currentLevel}
|
||||
expandDepth={expandDepth}
|
||||
includeArchived={includeArchived} />
|
||||
</>
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`note-book-card no-tooltip-preview ${isExpanded ? "expanded" : ""} ${note.isArchived ? "archived" : ""}`}
|
||||
<CardSection
|
||||
className={clsx("nested-note-list-item", "no-tooltip-preview", note.getColorClass(), {
|
||||
"expanded": isExpanded,
|
||||
"archived": note.isArchived
|
||||
})}
|
||||
subSections={subSections}
|
||||
subSectionsVisible={isExpanded}
|
||||
highlightOnHover
|
||||
data-note-id={note.noteId}
|
||||
>
|
||||
<h5 className="note-book-header">
|
||||
<span
|
||||
className={`note-expander ${isExpanded ? "bx bx-chevron-down" : "bx bx-chevron-right"}`}
|
||||
onClick={() => setExpanded(!isExpanded)}
|
||||
/>
|
||||
|
||||
<h5>
|
||||
<span className={`note-expander ${isExpanded ? "bx bx-chevron-down" : "bx bx-chevron-right"}`}
|
||||
onClick={() => setExpanded(!isExpanded)}/>
|
||||
<Icon className="note-icon" icon={note.getIcon()} />
|
||||
<NoteLink className="note-book-title" notePath={notePath} noPreview showNotePath={parentNote.type === "search"} highlightedTokens={highlightedTokens} />
|
||||
<NoteLink className="note-book-title"
|
||||
notePath={notePath}
|
||||
noPreview
|
||||
showNotePath={parentNote.type === "search"}
|
||||
highlightedTokens={highlightedTokens} />
|
||||
<NoteAttributes note={note} />
|
||||
<NoteMenuButton notePath={notePath} />
|
||||
</h5>
|
||||
|
||||
{isExpanded && <>
|
||||
<NoteContent note={note} highlightedTokens={highlightedTokens} noChildrenList includeArchivedNotes={includeArchived} />
|
||||
<NoteChildren note={note} parentNote={parentNote} highlightedTokens={highlightedTokens} currentLevel={currentLevel} expandDepth={expandDepth} includeArchived={includeArchived} />
|
||||
</>}
|
||||
</div>
|
||||
</CardSection>
|
||||
);
|
||||
}
|
||||
|
||||
function GridNoteCard({ note, parentNote, highlightedTokens, includeArchived }: { note: FNote, parentNote: FNote, highlightedTokens: string[] | null | undefined, includeArchived: boolean }) {
|
||||
const titleRef = useRef<HTMLSpanElement>(null);
|
||||
const [ noteTitle, setNoteTitle ] = useState<string>();
|
||||
const notePath = getNotePath(parentNote, note);
|
||||
interface GridNoteCardProps {
|
||||
note: FNote;
|
||||
parentNote: FNote;
|
||||
highlightedTokens: string[] | null | undefined;
|
||||
includeArchived: boolean;
|
||||
}
|
||||
|
||||
function GridNoteCard(props: GridNoteCardProps) {
|
||||
const notePath = getNotePath(props.parentNote, props.note);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`note-book-card no-tooltip-preview block-link ${note.isArchived ? "archived" : ""}`}
|
||||
data-href={`#${notePath}`}
|
||||
data-note-id={note.noteId}
|
||||
onClick={(e) => link.goToLink(e)}
|
||||
<CardFrame className={clsx("note-book-card", "no-tooltip-preview", "block-link", props.note.getColorClass(), {
|
||||
"archived": props.note.isArchived
|
||||
})}
|
||||
data-href={`#${notePath}`}
|
||||
data-note-id={props.note.noteId}
|
||||
onClick={(e) => link.goToLink(e)}
|
||||
>
|
||||
<h5 className="note-book-header">
|
||||
<Icon className="note-icon" icon={note.getIcon()} />
|
||||
<NoteLink className="note-book-title" notePath={notePath} noPreview showNotePath={parentNote.type === "search"} highlightedTokens={highlightedTokens} />
|
||||
<NoteAttributes note={note} />
|
||||
<h5 className={clsx("note-book-header")}>
|
||||
<Icon className="note-icon" icon={props.note.getIcon()} />
|
||||
<NoteLink className="note-book-title"
|
||||
notePath={notePath}
|
||||
noPreview
|
||||
showNotePath={props.parentNote.type === "search"}
|
||||
highlightedTokens={props.highlightedTokens}
|
||||
/>
|
||||
<NoteMenuButton notePath={notePath} />
|
||||
</h5>
|
||||
<NoteContent
|
||||
note={note}
|
||||
trim
|
||||
highlightedTokens={highlightedTokens}
|
||||
includeArchivedNotes={includeArchived}
|
||||
<NoteContent note={props.note}
|
||||
trim
|
||||
highlightedTokens={props.highlightedTokens}
|
||||
includeArchivedNotes={props.includeArchived}
|
||||
/>
|
||||
</div>
|
||||
</CardFrame>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -165,6 +207,9 @@ export function NoteContent({ note, trim, noChildrenList, highlightedTokens, inc
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
const highlightSearch = useImperativeSearchHighlighlighting(highlightedTokens);
|
||||
|
||||
const [ready, setReady] = useState(false);
|
||||
const [noteType, setNoteType] = useState<string>("none");
|
||||
|
||||
useEffect(() => {
|
||||
content_renderer.getRenderedContent(note, {
|
||||
trim,
|
||||
@@ -179,17 +224,19 @@ export function NoteContent({ note, trim, noChildrenList, highlightedTokens, inc
|
||||
} else {
|
||||
contentRef.current.replaceChildren();
|
||||
}
|
||||
contentRef.current.classList.add(`type-${type}`);
|
||||
highlightSearch(contentRef.current);
|
||||
setNoteType(type);
|
||||
setReady(true);
|
||||
})
|
||||
.catch(e => {
|
||||
console.warn(`Caught error while rendering note '${note.noteId}' of type '${note.type}'`);
|
||||
console.error(e);
|
||||
contentRef.current?.replaceChildren(t("collections.rendering_error"));
|
||||
setReady(true);
|
||||
});
|
||||
}, [ note, highlightedTokens ]);
|
||||
|
||||
return <div ref={contentRef} className="note-book-content" />;
|
||||
return <div ref={contentRef} className={clsx("note-book-content", `type-${noteType}`, {"note-book-content-ready": ready})} />;
|
||||
}
|
||||
|
||||
function NoteChildren({ note, parentNote, highlightedTokens, currentLevel, expandDepth, includeArchived }: {
|
||||
@@ -216,6 +263,18 @@ function NoteChildren({ note, parentNote, highlightedTokens, currentLevel, expan
|
||||
/>);
|
||||
}
|
||||
|
||||
function NoteMenuButton(props: {notePath: string}) {
|
||||
const openMenu = useCallback((e: TargetedMouseEvent<HTMLElement>) => {
|
||||
linkContextMenuService.openContextMenu(props.notePath, e);
|
||||
e.stopPropagation()
|
||||
}, [props.notePath]);
|
||||
|
||||
return <ActionButton className="note-book-item-menu"
|
||||
icon="bx bx-dots-vertical-rounded" text=""
|
||||
onClick={openMenu}
|
||||
/>
|
||||
}
|
||||
|
||||
function getNotePath(parentNote: FNote, childNote: FNote) {
|
||||
if (parentNote.type === "search") {
|
||||
// for search note parent, we want to display a non-search path
|
||||
@@ -237,4 +296,4 @@ function useExpansionDepth(note: FNote) {
|
||||
}
|
||||
return parseInt(expandDepth, 10);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
body.mobile .scrolling-container {
|
||||
--content-margin-inline: 8px;
|
||||
}
|
||||
|
||||
.note-split.type-code:not(.mime-text-x-sqlite) {
|
||||
&> .scrolling-container {
|
||||
background-color: var(--code-background-color);
|
||||
|
||||
@@ -32,6 +32,12 @@ body.mobile .modal.popup-editor-dialog .modal-dialog {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-block: 0;
|
||||
|
||||
.note-icon-widget {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.modal.popup-editor-dialog .modal-header .note-title-widget {
|
||||
|
||||
@@ -67,10 +67,7 @@ export default function PopupEditor() {
|
||||
<NoteContextContext.Provider value={noteContext}>
|
||||
<DialogWrapper>
|
||||
<Modal
|
||||
title={<>
|
||||
<TitleRow />
|
||||
{isNewLayout && <NoteBadges />}
|
||||
</>}
|
||||
title={<TitleRow />}
|
||||
customTitleBarButtons={[{
|
||||
iconClassName: "bx-expand-alt",
|
||||
title: t("popup-editor.maximize"),
|
||||
@@ -123,6 +120,7 @@ export function TitleRow() {
|
||||
<div className="title-row">
|
||||
<NoteIcon />
|
||||
<NoteTitleWidget />
|
||||
{isNewLayout && <NoteBadges />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ export default function BulkActionsDialog() {
|
||||
className="bulk-actions-dialog"
|
||||
size="xl"
|
||||
title={t("bulk_actions.bulk_actions")}
|
||||
footer={<Button text={t("bulk_actions.execute_bulk_actions")} primary />}
|
||||
footer={<Button text={t("bulk_actions.execute_bulk_actions")} kind="primary" />}
|
||||
show={shown}
|
||||
onSubmit={async () => {
|
||||
await server.post("bulk-action/execute", {
|
||||
|
||||
@@ -72,7 +72,7 @@ export default function DeleteNotesDialog() {
|
||||
footer={<>
|
||||
<Button text={t("delete_notes.cancel")}
|
||||
onClick={() => setShown(false)} />
|
||||
<Button text={t("delete_notes.ok")} primary
|
||||
<Button text={t("delete_notes.ok")} kind="primary"
|
||||
buttonRef={okButtonRef}
|
||||
onClick={() => {
|
||||
opts.callback?.({ proceed: true, deleteAllClones, eraseNotes });
|
||||
|
||||
@@ -58,7 +58,7 @@ export default function ExportDialog() {
|
||||
setShown(false);
|
||||
}}
|
||||
onHidden={() => setShown(false)}
|
||||
footer={<Button className="export-button" text={t("export.export")} primary />}
|
||||
footer={<Button className="export-button" text={t("export.export")} kind="primary" />}
|
||||
show={shown}
|
||||
>
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ export default function ImportDialog() {
|
||||
setShown(false);
|
||||
setFiles(null);
|
||||
}}
|
||||
footer={<Button text={t("import.import")} primary disabled={!files} />}
|
||||
footer={<Button text={t("import.import")} kind="primary" disabled={!files} />}
|
||||
show={shown}
|
||||
>
|
||||
<FormGroup name="files" label={t("import.chooseImportFile")} description={
|
||||
|
||||
@@ -69,7 +69,7 @@ export default function PromptDialog() {
|
||||
submitValue.current = null;
|
||||
opts.current = undefined;
|
||||
}}
|
||||
footer={<Button text={t("prompt.ok")} keyboardShortcut="Enter" primary />}
|
||||
footer={<Button text={t("prompt.ok")} keyboardShortcut="Enter" kind="primary" />}
|
||||
show={shown}
|
||||
stackable
|
||||
>
|
||||
|
||||
@@ -203,7 +203,7 @@ function RevisionPreview({noteContent, revisionItem, showDiff, setShown, onRevis
|
||||
}} />
|
||||
|
||||
<Button
|
||||
primary
|
||||
kind="primary"
|
||||
icon="bx bx-download"
|
||||
text={t("revisions.download_button")}
|
||||
onClick={() => {
|
||||
|
||||
@@ -35,7 +35,7 @@ export default function UploadAttachmentsDialog() {
|
||||
className="upload-attachments-dialog"
|
||||
size="lg"
|
||||
title={t("upload_attachments.upload_attachments_to_note")}
|
||||
footer={<Button text={t("upload_attachments.upload")} primary disabled={!files || isUploading} />}
|
||||
footer={<Button text={t("upload_attachments.upload")} kind="primary" disabled={!files || isUploading} />}
|
||||
onSubmit={async () => {
|
||||
if (!files || !parentNoteId) {
|
||||
return;
|
||||
|
||||
@@ -3,7 +3,7 @@ import clsx from "clsx";
|
||||
import server from "../../services/server";
|
||||
import { TargetedMouseEvent, VNode } from "preact";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { Dayjs } from "@triliumnext/commons";
|
||||
import { Dayjs, getWeekInfo, WeekSettings } from "@triliumnext/commons";
|
||||
import { t } from "../../services/i18n";
|
||||
|
||||
interface DateNotesForMonth {
|
||||
@@ -22,6 +22,7 @@ const DAYS_OF_WEEK = [
|
||||
|
||||
interface DateRangeInfo {
|
||||
weekNumbers: number[];
|
||||
weekYears: number[];
|
||||
dates: Dayjs[];
|
||||
}
|
||||
|
||||
@@ -36,19 +37,27 @@ export interface CalendarArgs {
|
||||
|
||||
export default function Calendar(args: CalendarArgs) {
|
||||
const [ rawFirstDayOfWeek ] = useTriliumOptionInt("firstDayOfWeek");
|
||||
const [ firstWeekOfYear ] = useTriliumOptionInt("firstWeekOfYear");
|
||||
const [ minDaysInFirstWeek ] = useTriliumOptionInt("minDaysInFirstWeek");
|
||||
const firstDayOfWeekISO = (rawFirstDayOfWeek === 0 ? 7 : rawFirstDayOfWeek);
|
||||
|
||||
const weekSettings = {
|
||||
firstDayOfWeek: firstDayOfWeekISO,
|
||||
firstWeekOfYear: firstWeekOfYear ?? 0,
|
||||
minDaysInFirstWeek: minDaysInFirstWeek ?? 4
|
||||
};
|
||||
|
||||
const date = args.date;
|
||||
const firstDay = date.startOf('month');
|
||||
const firstDayISO = firstDay.isoWeekday();
|
||||
const monthInfo = getMonthInformation(date, firstDayISO, firstDayOfWeekISO);
|
||||
const monthInfo = getMonthInformation(date, firstDayISO, weekSettings);
|
||||
|
||||
return (
|
||||
<>
|
||||
<CalendarWeekHeader rawFirstDayOfWeek={rawFirstDayOfWeek} />
|
||||
<div className="calendar-body" data-calendar-area="month">
|
||||
{firstDayISO !== firstDayOfWeekISO && <PreviousMonthDays info={monthInfo.prevMonth} {...args} />}
|
||||
<CurrentMonthDays firstDayOfWeekISO={firstDayOfWeekISO} {...args} />
|
||||
{firstDayISO !== firstDayOfWeekISO && <PreviousMonthDays info={monthInfo.prevMonth} weekSettings={weekSettings} {...args} />}
|
||||
<CurrentMonthDays weekSettings={weekSettings} {...args} />
|
||||
<NextMonthDays dates={monthInfo.nextMonth.dates} {...args} />
|
||||
</div>
|
||||
</>
|
||||
@@ -67,7 +76,7 @@ function CalendarWeekHeader({ rawFirstDayOfWeek }: { rawFirstDayOfWeek: number }
|
||||
)
|
||||
}
|
||||
|
||||
function PreviousMonthDays({ date, info: { dates, weekNumbers }, ...args }: { date: Dayjs, info: DateRangeInfo } & CalendarArgs) {
|
||||
function PreviousMonthDays({ date, info: { dates, weekNumbers, weekYears }, weekSettings, ...args }: { date: Dayjs, info: DateRangeInfo, weekSettings: WeekSettings } & CalendarArgs) {
|
||||
const prevMonth = date.subtract(1, 'month').format('YYYY-MM');
|
||||
const [ dateNotesForPrevMonth, setDateNotesForPrevMonth ] = useState<DateNotesForMonth>();
|
||||
|
||||
@@ -77,27 +86,28 @@ function PreviousMonthDays({ date, info: { dates, weekNumbers }, ...args }: { da
|
||||
|
||||
return (
|
||||
<>
|
||||
<CalendarWeek date={date} weekNumber={weekNumbers[0]} {...args} />
|
||||
<CalendarWeek date={date} weekNumber={weekNumbers[0]} weekYear={weekYears[0]} {...args} />
|
||||
{dates.map(date => <CalendarDay key={date.toISOString()} date={date} dateNotesForMonth={dateNotesForPrevMonth} className="calendar-date-prev-month" {...args} />)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function CurrentMonthDays({ date, firstDayOfWeekISO, ...args }: { date: Dayjs, firstDayOfWeekISO: number } & CalendarArgs) {
|
||||
function CurrentMonthDays({ date, weekSettings, ...args }: { date: Dayjs, weekSettings: WeekSettings } & CalendarArgs) {
|
||||
let dateCursor = date;
|
||||
const currentMonth = date.month();
|
||||
const items: VNode[] = [];
|
||||
const curMonthString = date.format('YYYY-MM');
|
||||
const [ dateNotesForCurMonth, setDateNotesForCurMonth ] = useState<DateNotesForMonth>();
|
||||
const { firstDayOfWeek, firstWeekOfYear, minDaysInFirstWeek } = weekSettings;
|
||||
|
||||
useEffect(() => {
|
||||
server.get<DateNotesForMonth>(`special-notes/notes-for-month/${curMonthString}`).then(setDateNotesForCurMonth);
|
||||
}, [ date ]);
|
||||
|
||||
while (dateCursor.month() === currentMonth) {
|
||||
const weekNumber = getWeekNumber(dateCursor, firstDayOfWeekISO);
|
||||
if (dateCursor.isoWeekday() === firstDayOfWeekISO) {
|
||||
items.push(<CalendarWeek key={`${dateCursor.year()}-W${weekNumber}`} date={dateCursor} weekNumber={weekNumber} {...args}/>)
|
||||
const { weekYear, weekNumber } = getWeekInfo(dateCursor, weekSettings);
|
||||
if (dateCursor.isoWeekday() === firstDayOfWeek) {
|
||||
items.push(<CalendarWeek key={`${weekYear}-W${weekNumber}`} date={dateCursor} weekNumber={weekNumber} weekYear={weekYear} {...args}/>)
|
||||
}
|
||||
|
||||
items.push(<CalendarDay key={dateCursor.toISOString()} date={dateCursor} dateNotesForMonth={dateNotesForCurMonth} {...args} />)
|
||||
@@ -141,14 +151,8 @@ function CalendarDay({ date, dateNotesForMonth, className, activeDate, todaysDat
|
||||
);
|
||||
}
|
||||
|
||||
function CalendarWeek({ date, weekNumber, weekNotes, onWeekClicked }: { weekNumber: number, weekNotes: string[] } & Pick<CalendarArgs, "date" | "onWeekClicked">) {
|
||||
const localDate = date.local();
|
||||
|
||||
// Handle case where week is in between years.
|
||||
let year = localDate.year();
|
||||
if (localDate.month() === 11 && weekNumber === 1) year++;
|
||||
|
||||
const weekString = `${year}-W${String(weekNumber).padStart(2, '0')}`;
|
||||
function CalendarWeek({ date, weekNumber, weekYear, weekNotes, onWeekClicked }: { weekNumber: number, weekYear: number, weekNotes: string[] } & Pick<CalendarArgs, "date" | "onWeekClicked">) {
|
||||
const weekString = `${weekYear}-W${String(weekNumber).padStart(2, '0')}`;
|
||||
|
||||
if (onWeekClicked) {
|
||||
return (
|
||||
@@ -169,33 +173,33 @@ function CalendarWeek({ date, weekNumber, weekNotes, onWeekClicked }: { weekNumb
|
||||
>{weekNumber}</span>);
|
||||
}
|
||||
|
||||
export function getMonthInformation(date: Dayjs, firstDayISO: number, firstDayOfWeekISO: number) {
|
||||
export function getMonthInformation(date: Dayjs, firstDayISO: number, weekSettings: WeekSettings) {
|
||||
return {
|
||||
prevMonth: getPrevMonthDays(date, firstDayISO, firstDayOfWeekISO),
|
||||
nextMonth: getNextMonthDays(date, firstDayOfWeekISO)
|
||||
prevMonth: getPrevMonthDays(date, firstDayISO, weekSettings),
|
||||
nextMonth: getNextMonthDays(date, weekSettings.firstDayOfWeek)
|
||||
}
|
||||
}
|
||||
|
||||
function getPrevMonthDays(date: Dayjs, firstDayISO: number, firstDayOfWeekISO: number): DateRangeInfo {
|
||||
function getPrevMonthDays(date: Dayjs, firstDayISO: number, weekSettings: WeekSettings): DateRangeInfo {
|
||||
const prevMonthLastDay = date.subtract(1, 'month').endOf('month');
|
||||
const daysToAdd = (firstDayISO - firstDayOfWeekISO + 7) % 7;
|
||||
const daysToAdd = (firstDayISO - weekSettings.firstDayOfWeek + 7) % 7;
|
||||
const dates: Dayjs[] = [];
|
||||
|
||||
const firstDay = date.startOf('month');
|
||||
const weekNumber = getWeekNumber(firstDay, firstDayOfWeekISO);
|
||||
const { weekYear, weekNumber } = getWeekInfo(firstDay, weekSettings);
|
||||
|
||||
// Get dates from previous month
|
||||
for (let i = daysToAdd - 1; i >= 0; i--) {
|
||||
dates.push(prevMonthLastDay.subtract(i, 'day'));
|
||||
}
|
||||
|
||||
return { weekNumbers: [ weekNumber ], dates };
|
||||
return { weekNumbers: [ weekNumber ], weekYears: [ weekYear ], dates };
|
||||
}
|
||||
|
||||
function getNextMonthDays(date: Dayjs, firstDayOfWeekISO: number): DateRangeInfo {
|
||||
function getNextMonthDays(date: Dayjs, firstDayOfWeek: number): DateRangeInfo {
|
||||
const lastDayOfMonth = date.endOf('month');
|
||||
const lastDayISO = lastDayOfMonth.isoWeekday();
|
||||
const lastDayOfUserWeek = ((firstDayOfWeekISO + 6 - 1) % 7) + 1;
|
||||
const lastDayOfUserWeek = ((firstDayOfWeek + 6 - 1) % 7) + 1;
|
||||
const nextMonthFirstDay = date.add(1, 'month').startOf('month');
|
||||
const dates: Dayjs[] = [];
|
||||
|
||||
@@ -206,16 +210,5 @@ function getNextMonthDays(date: Dayjs, firstDayOfWeekISO: number): DateRangeInfo
|
||||
dates.push(nextMonthFirstDay.add(i, 'day'));
|
||||
}
|
||||
}
|
||||
return { weekNumbers: [], dates };
|
||||
}
|
||||
|
||||
export function getWeekNumber(date: Dayjs, firstDayOfWeekISO: number): number {
|
||||
const weekStart = getWeekStartDate(date, firstDayOfWeekISO);
|
||||
return weekStart.isoWeek();
|
||||
}
|
||||
|
||||
function getWeekStartDate(date: Dayjs, firstDayOfWeekISO: number): Dayjs {
|
||||
const currentISO = date.isoWeekday();
|
||||
const diff = (currentISO - firstDayOfWeekISO + 7) % 7;
|
||||
return date.clone().subtract(diff, "day").startOf("day");
|
||||
return { weekNumbers: [], weekYears: [], dates };
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import BookmarkButtons from "./BookmarkButtons";
|
||||
import CalendarWidget from "./CalendarWidget";
|
||||
import HistoryNavigationButton from "./HistoryNavigation";
|
||||
import { LaunchBarContext } from "./launch_bar_widgets";
|
||||
import { AiChatButton, CommandButton, CustomWidget, NoteLauncher, QuickSearchLauncherWidget, ScriptLauncher, TodayLauncher } from "./LauncherDefinitions";
|
||||
import { CommandButton, CustomWidget, NoteLauncher, QuickSearchLauncherWidget, ScriptLauncher, TodayLauncher } from "./LauncherDefinitions";
|
||||
import ProtectedSessionStatusWidget from "./ProtectedSessionStatusWidget";
|
||||
import SpacerWidget from "./SpacerWidget";
|
||||
import SyncStatus from "./SyncStatus";
|
||||
@@ -67,7 +67,7 @@ function Launcher({ note, isHorizontalLayout }: { note: FNote, isHorizontalLayou
|
||||
case "builtinWidget":
|
||||
return initBuiltinWidget(note, isHorizontalLayout);
|
||||
default:
|
||||
throw new Error(`Unrecognized launcher type '${launcherType}' for launcher '${note.noteId}' title '${note.title}'`);
|
||||
console.warn(`Unrecognized launcher type '${launcherType}' for launcher '${note.noteId}' title '${note.title}'`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,12 +96,10 @@ function initBuiltinWidget(note: FNote, isHorizontalLayout: boolean) {
|
||||
return <TodayLauncher launcherNote={note} />;
|
||||
case "quickSearch":
|
||||
return <QuickSearchLauncherWidget />;
|
||||
case "aiChatLauncher":
|
||||
return <AiChatButton launcherNote={note} />;
|
||||
case "mobileTabSwitcher":
|
||||
return <TabSwitcher />;
|
||||
default:
|
||||
throw new Error(`Unrecognized builtin widget ${builtinWidget} for launcher ${note.noteId} "${note.title}"`);
|
||||
console.warn(`Unrecognized builtin widget ${builtinWidget} for launcher ${note.noteId} "${note.title}"`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { getErrorMessage, isMobile } from "../../services/utils";
|
||||
import BasicWidget from "../basic_widget";
|
||||
import NoteContextAwareWidget from "../note_context_aware_widget";
|
||||
import QuickSearchWidget from "../quick_search";
|
||||
import { useGlobalShortcut, useLegacyWidget, useNoteLabel, useNoteRelationTarget, useTriliumOptionBool } from "../react/hooks";
|
||||
import { useGlobalShortcut, useLegacyWidget, useNoteLabel, useNoteRelationTarget } from "../react/hooks";
|
||||
import { ParentComponent } from "../react/react_utils";
|
||||
import { CustomNoteLauncher } from "./GenericButtons";
|
||||
import { LaunchBarActionButton, LaunchBarContext, LauncherNoteProps, useLauncherIconAndTitle } from "./launch_bar_widgets";
|
||||
@@ -81,19 +81,6 @@ export function ScriptLauncher({ launcherNote }: LauncherNoteProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export function AiChatButton({ launcherNote }: LauncherNoteProps) {
|
||||
const [ aiEnabled ] = useTriliumOptionBool("aiEnabled");
|
||||
const { icon, title } = useLauncherIconAndTitle(launcherNote);
|
||||
|
||||
return aiEnabled && (
|
||||
<LaunchBarActionButton
|
||||
icon={icon}
|
||||
text={title}
|
||||
triggerCommand="createAiChat"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function TodayLauncher({ launcherNote }: LauncherNoteProps) {
|
||||
return (
|
||||
<CustomNoteLauncher
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { useEffect, useRef, useState } from "preact/hooks";
|
||||
import "./SyncStatus.css";
|
||||
import { t } from "../../services/i18n";
|
||||
import clsx from "clsx";
|
||||
import { escapeQuotes } from "../../services/utils";
|
||||
import { useStaticTooltip, useTriliumOption } from "../react/hooks";
|
||||
import sync from "../../services/sync";
|
||||
import ws, { subscribeToMessages, unsubscribeToMessage } from "../../services/ws";
|
||||
|
||||
import { WebSocketMessage } from "@triliumnext/commons";
|
||||
import clsx from "clsx";
|
||||
import { useEffect, useRef, useState } from "preact/hooks";
|
||||
|
||||
import { t } from "../../services/i18n";
|
||||
import sync from "../../services/sync";
|
||||
import { escapeQuotes } from "../../services/utils";
|
||||
import ws, { subscribeToMessages, unsubscribeToMessage } from "../../services/ws";
|
||||
import { useStaticTooltip, useTriliumOption } from "../react/hooks";
|
||||
|
||||
type SyncState = "unknown" | "in-progress"
|
||||
| "connected-with-changes" | "connected-no-changes"
|
||||
@@ -53,29 +55,29 @@ export default function SyncStatus() {
|
||||
const spanRef = useRef<HTMLSpanElement>(null);
|
||||
const [ syncServerHost ] = useTriliumOption("syncServerHost");
|
||||
useStaticTooltip(spanRef, {
|
||||
html: true
|
||||
// TODO: Placement
|
||||
html: true,
|
||||
title: escapeQuotes(title)
|
||||
});
|
||||
|
||||
return (syncServerHost &&
|
||||
<div class="sync-status-widget launcher-button">
|
||||
<div class="sync-status">
|
||||
<span
|
||||
key={syncState} // Force re-render when state changes to update tooltip content.
|
||||
ref={spanRef}
|
||||
className={clsx("sync-status-icon", `sync-status-${syncState}`, icon)}
|
||||
title={escapeQuotes(title)}
|
||||
onClick={() => {
|
||||
if (syncState === "in-progress") return;
|
||||
sync.syncNow();
|
||||
}}
|
||||
>
|
||||
{hasChanges && (
|
||||
<span class="bx bxs-star sync-status-sub-icon"></span>
|
||||
<span class="bx bxs-star sync-status-sub-icon" />
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function useSyncStatus() {
|
||||
|
||||
@@ -3,11 +3,14 @@ import { createContext } from "preact";
|
||||
import { useContext } from "preact/hooks";
|
||||
|
||||
import FNote from "../../entities/fnote";
|
||||
import utils from "../../services/utils";
|
||||
import ActionButton, { ActionButtonProps } from "../react/ActionButton";
|
||||
import Dropdown, { DropdownProps } from "../react/Dropdown";
|
||||
import { useNoteLabel, useNoteProperty } from "../react/hooks";
|
||||
import Icon from "../react/Icon";
|
||||
|
||||
const cachedIsMobile = utils.isMobile();
|
||||
|
||||
export const LaunchBarContext = createContext<{
|
||||
isHorizontalLayout: boolean;
|
||||
}>({
|
||||
@@ -26,7 +29,7 @@ export function LaunchBarActionButton({ className, ...props }: Omit<ActionButton
|
||||
<ActionButton
|
||||
className={clsx("button-widget launcher-button", className)}
|
||||
noIconActionClass
|
||||
titlePosition={isHorizontalLayout ? "bottom" : "right"}
|
||||
titlePosition={getTitlePosition(isHorizontalLayout)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -34,6 +37,7 @@ export function LaunchBarActionButton({ className, ...props }: Omit<ActionButton
|
||||
|
||||
export function LaunchBarDropdownButton({ children, icon, dropdownOptions, ...props }: Pick<DropdownProps, "title" | "children" | "onShown" | "dropdownOptions" | "dropdownRef"> & { icon: string }) {
|
||||
const { isHorizontalLayout } = useContext(LaunchBarContext);
|
||||
const titlePosition = getTitlePosition(isHorizontalLayout);
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
@@ -41,12 +45,12 @@ export function LaunchBarDropdownButton({ children, icon, dropdownOptions, ...pr
|
||||
buttonClassName="right-dropdown-button launcher-button"
|
||||
hideToggleArrow
|
||||
text={<Icon icon={icon} />}
|
||||
titlePosition={isHorizontalLayout ? "bottom" : "right"}
|
||||
titlePosition={titlePosition}
|
||||
titleOptions={{ animation: false }}
|
||||
dropdownOptions={{
|
||||
...dropdownOptions,
|
||||
popperConfig: {
|
||||
placement: isHorizontalLayout ? "bottom" : "right"
|
||||
placement: titlePosition
|
||||
}
|
||||
}}
|
||||
mobileBackdrop
|
||||
@@ -67,3 +71,10 @@ export function useLauncherIconAndTitle(note: FNote) {
|
||||
title: title ?? ""
|
||||
};
|
||||
}
|
||||
|
||||
function getTitlePosition(isHorizontalLayout: boolean) {
|
||||
if (cachedIsMobile) {
|
||||
return "top";
|
||||
}
|
||||
return isHorizontalLayout ? "bottom" : "right";
|
||||
}
|
||||
|
||||
284
apps/client/src/widgets/layout/ActiveContentBadges.tsx
Normal file
284
apps/client/src/widgets/layout/ActiveContentBadges.tsx
Normal file
@@ -0,0 +1,284 @@
|
||||
import { BUILTIN_ATTRIBUTES } from "@triliumnext/commons";
|
||||
import clsx from "clsx";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
import FNote from "../../entities/fnote";
|
||||
import attributes from "../../services/attributes";
|
||||
import { t } from "../../services/i18n";
|
||||
import { openInAppHelpFromUrl } from "../../services/utils";
|
||||
import { BadgeWithDropdown } from "../react/Badge";
|
||||
import { FormDropdownDivider, FormListItem } from "../react/FormList";
|
||||
import FormToggle from "../react/FormToggle";
|
||||
import { useNoteContext, useNoteProperty, useTriliumEvent } from "../react/hooks";
|
||||
import { BookProperty, ViewProperty } from "../react/NotePropertyMenu";
|
||||
|
||||
const NON_DANGEROUS_ACTIVE_CONTENT = [ "appCss", "appTheme" ];
|
||||
const DANGEROUS_ATTRIBUTES = BUILTIN_ATTRIBUTES.filter(a => a.isDangerous || NON_DANGEROUS_ACTIVE_CONTENT.includes(a.name));
|
||||
const activeContentLabels = [ "iconPack", "widget", "appCss", "appTheme" ] as const;
|
||||
|
||||
interface ActiveContentInfo {
|
||||
type: "iconPack" | "backendScript" | "frontendScript" | "widget" | "appCss" | "renderNote" | "webView" | "appTheme";
|
||||
isEnabled: boolean;
|
||||
canToggleEnabled: boolean;
|
||||
}
|
||||
|
||||
const executeOption: BookProperty = {
|
||||
type: "button",
|
||||
icon: "bx bx-play",
|
||||
label: t("active_content_badges.menu_execute_now"),
|
||||
onClick: context => context.triggerCommand("runActiveNote")
|
||||
};
|
||||
|
||||
const typeMappings: Record<ActiveContentInfo["type"], {
|
||||
title: string;
|
||||
icon: string;
|
||||
helpPage: string;
|
||||
apiDocsPage?: string;
|
||||
isExecutable?: boolean;
|
||||
additionalOptions?: BookProperty[];
|
||||
}> = {
|
||||
iconPack: {
|
||||
title: t("active_content_badges.type_icon_pack"),
|
||||
icon: "bx bx-package",
|
||||
helpPage: "g1mlRoU8CsqC",
|
||||
},
|
||||
backendScript: {
|
||||
title: t("active_content_badges.type_backend_script"),
|
||||
icon: "bx bx-server",
|
||||
helpPage: "SPirpZypehBG",
|
||||
apiDocsPage: "MEtfsqa5VwNi",
|
||||
isExecutable: true,
|
||||
additionalOptions: [
|
||||
executeOption,
|
||||
{
|
||||
type: "combobox",
|
||||
bindToLabel: "run",
|
||||
label: t("active_content_badges.menu_run"),
|
||||
icon: "bx bx-rss",
|
||||
dropStart: true,
|
||||
options: [
|
||||
{ value: null, label: t("active_content_badges.menu_run_disabled") },
|
||||
{ value: "backendStartup", label: t("active_content_badges.menu_run_backend_startup") },
|
||||
{ value: "daily", label: t("active_content_badges.menu_run_daily") },
|
||||
{ value: "hourly", label: t("active_content_badges.menu_run_hourly") }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
frontendScript: {
|
||||
title: t("active_content_badges.type_frontend_script"),
|
||||
icon: "bx bx-window",
|
||||
helpPage: "yIhgI5H7A2Sm",
|
||||
apiDocsPage: "Q2z6av6JZVWm",
|
||||
isExecutable: true,
|
||||
additionalOptions: [
|
||||
executeOption,
|
||||
{
|
||||
type: "combobox",
|
||||
bindToLabel: "run",
|
||||
label: t("active_content_badges.menu_run"),
|
||||
icon: "bx bx-rss",
|
||||
dropStart: true,
|
||||
options: [
|
||||
{ value: null, label: t("active_content_badges.menu_run_disabled") },
|
||||
{ value: "frontendStartup", label: t("active_content_badges.menu_run_frontend_startup") },
|
||||
{ value: "mobileStartup", label: t("active_content_badges.menu_run_mobile_startup") },
|
||||
]
|
||||
},
|
||||
{ type: "separator" },
|
||||
{
|
||||
type: "button",
|
||||
label: t("active_content_badges.menu_change_to_widget"),
|
||||
icon: "bx bxs-widget",
|
||||
onClick: ({ note }) => attributes.setLabel(note.noteId, "widget")
|
||||
}
|
||||
]
|
||||
},
|
||||
widget: {
|
||||
title: t("active_content_badges.type_widget"),
|
||||
icon: "bx bxs-widget",
|
||||
helpPage: "MgibgPcfeuGz",
|
||||
additionalOptions: [
|
||||
{
|
||||
type: "button",
|
||||
label: t("active_content_badges.menu_change_to_frontend_script"),
|
||||
icon: "bx bx-window",
|
||||
onClick: ({ note }) => {
|
||||
attributes.removeOwnedLabelByName(note, "widget");
|
||||
attributes.removeOwnedLabelByName(note, "disabled:widget");
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
appCss: {
|
||||
title: t("active_content_badges.type_app_css"),
|
||||
icon: "bx bxs-file-css",
|
||||
helpPage: "AlhDUqhENtH7"
|
||||
},
|
||||
renderNote: {
|
||||
title: t("active_content_badges.type_render_note"),
|
||||
icon: "bx bx-extension",
|
||||
helpPage: "HcABDtFCkbFN"
|
||||
},
|
||||
webView: {
|
||||
title: t("active_content_badges.type_web_view"),
|
||||
icon: "bx bx-globe",
|
||||
helpPage: "1vHRoWCEjj0L"
|
||||
},
|
||||
appTheme: {
|
||||
title :t("active_content_badges.type_app_theme"),
|
||||
icon: "bx bx-palette",
|
||||
helpPage: "7NfNr5pZpVKV",
|
||||
additionalOptions: [
|
||||
{
|
||||
type: "combobox",
|
||||
bindToLabel: "appThemeBase",
|
||||
label: t("active_content_badges.menu_theme_base"),
|
||||
icon: "bx bx-layer",
|
||||
dropStart: true,
|
||||
options: [
|
||||
{ label: t("theme.auto_theme"), value: null },
|
||||
{ type: "separator" },
|
||||
{ label: t("theme.triliumnext"), value: "next" },
|
||||
{ label: t("theme.triliumnext-light"), value: "next-light" },
|
||||
{ label: t("theme.triliumnext-dark"), value: "next-dark" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
export function ActiveContentBadges() {
|
||||
const { note } = useNoteContext();
|
||||
const info = useActiveContentInfo(note);
|
||||
|
||||
return (note && info &&
|
||||
<>
|
||||
{info.canToggleEnabled && <ActiveContentToggle info={info} note={note} />}
|
||||
<ActiveContentBadge info={info} note={note} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function ActiveContentBadge({ info, note }: { note: FNote, info: ActiveContentInfo }) {
|
||||
const { title, icon, helpPage, apiDocsPage, additionalOptions } = typeMappings[info.type];
|
||||
return (
|
||||
<BadgeWithDropdown
|
||||
className={clsx("active-content-badge", info.canToggleEnabled && !info.isEnabled && "disabled")}
|
||||
icon={icon}
|
||||
text={title}
|
||||
dropdownOptions={{
|
||||
dropdownContainerClassName: "mobile-bottom-menu",
|
||||
mobileBackdrop: true
|
||||
}}
|
||||
>
|
||||
{additionalOptions?.length && (
|
||||
<>
|
||||
{additionalOptions?.map((property, i) => (
|
||||
<ViewProperty key={i} note={note} property={property} />
|
||||
))}
|
||||
<FormDropdownDivider />
|
||||
</>
|
||||
)}
|
||||
|
||||
<FormListItem
|
||||
icon="bx bx-help-circle"
|
||||
onClick={() => openInAppHelpFromUrl(helpPage)}
|
||||
>{t("active_content_badges.menu_docs")}</FormListItem>
|
||||
|
||||
{apiDocsPage && <FormListItem
|
||||
icon="bx bx-book-content"
|
||||
onClick={() => openInAppHelpFromUrl(apiDocsPage)}
|
||||
>{t("code_buttons.trilium_api_docs_button_title")}</FormListItem>}
|
||||
</BadgeWithDropdown>
|
||||
);
|
||||
}
|
||||
|
||||
function ActiveContentToggle({ note, info }: { note: FNote, info: ActiveContentInfo }) {
|
||||
const { title } = typeMappings[info.type];
|
||||
|
||||
return info && <FormToggle
|
||||
switchOnName="" switchOffName=""
|
||||
currentValue={info.isEnabled}
|
||||
switchOffTooltip={t("active_content_badges.toggle_tooltip_disable_tooltip", { type: title })}
|
||||
switchOnTooltip={t("active_content_badges.toggle_tooltip_enable_tooltip", { type: title })}
|
||||
onChange={async (willEnable) => {
|
||||
await Promise.all(note.getOwnedAttributes()
|
||||
.map(attr => ({ name: attributes.getNameWithoutDangerousPrefix(attr.name), type: attr.type }))
|
||||
.filter(({ name, type }) => DANGEROUS_ATTRIBUTES.some(item => item.name === name && item.type === type))
|
||||
.map(({ name, type }) => attributes.toggleDangerousAttribute(note, type, name, willEnable)));
|
||||
}}
|
||||
/>;
|
||||
}
|
||||
|
||||
function useActiveContentInfo(note: FNote | null | undefined) {
|
||||
const [ info, setInfo ] = useState<ActiveContentInfo | null>(null);
|
||||
const noteType = useNoteProperty(note, "type");
|
||||
const noteMime = useNoteProperty(note, "mime");
|
||||
|
||||
function refresh() {
|
||||
let type: ActiveContentInfo["type"] | null = null;
|
||||
let isEnabled = false;
|
||||
let canToggleEnabled = false;
|
||||
|
||||
if (!note) {
|
||||
setInfo(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (noteType === "render") {
|
||||
type = "renderNote";
|
||||
isEnabled = note.hasRelation("renderNote");
|
||||
} else if (noteType === "webView") {
|
||||
type = "webView";
|
||||
isEnabled = note.hasLabel("webViewSrc");
|
||||
} else if (noteType === "code" && noteMime === "application/javascript;env=backend") {
|
||||
type = "backendScript";
|
||||
for (const backendLabel of [ "run", "customRequestHandler", "customResourceProvider" ]) {
|
||||
isEnabled ||= note.hasLabel(backendLabel);
|
||||
|
||||
if (!canToggleEnabled && note.hasLabelOrDisabled(backendLabel)) {
|
||||
canToggleEnabled = true;
|
||||
}
|
||||
}
|
||||
} else if (noteType === "code" && noteMime === "application/javascript;env=frontend") {
|
||||
type = "frontendScript";
|
||||
isEnabled = note.hasLabel("widget") || note.hasLabel("run");
|
||||
canToggleEnabled = note.hasLabelOrDisabled("widget") || note.hasLabelOrDisabled("run");
|
||||
} else if (noteType === "code" && note.hasLabelOrDisabled("appTheme")) {
|
||||
isEnabled = note.hasLabel("appTheme");
|
||||
canToggleEnabled = true;
|
||||
}
|
||||
|
||||
for (const labelToCheck of activeContentLabels) {
|
||||
if (note.hasLabel(labelToCheck)) {
|
||||
type = labelToCheck;
|
||||
isEnabled = true;
|
||||
canToggleEnabled = true;
|
||||
break;
|
||||
} else if (note.hasLabel(`disabled:${labelToCheck}`)) {
|
||||
type = labelToCheck;
|
||||
isEnabled = false;
|
||||
canToggleEnabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (type) {
|
||||
setInfo({ type, isEnabled, canToggleEnabled });
|
||||
} else {
|
||||
setInfo(null);
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh on note change.
|
||||
useEffect(refresh, [ note, noteType, noteMime ]);
|
||||
|
||||
useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
|
||||
if (loadResults.getAttributeRows().some(attr => attributes.isAffecting(attr, note))) {
|
||||
refresh();
|
||||
}
|
||||
});
|
||||
|
||||
return info;
|
||||
}
|
||||
@@ -19,6 +19,9 @@
|
||||
--link-hover-background: var(--icon-button-hover-background);
|
||||
|
||||
color: var(--custom-color, inherit);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover {
|
||||
color: var(--custom-color, inherit);
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
&.active-content-badge { --color: var(--badge-active-content-background-color); }
|
||||
&.active-content-badge.disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
min-width: 0;
|
||||
|
||||
@@ -45,6 +49,11 @@
|
||||
text-overflow: ellipsis;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.switch-button {
|
||||
--switch-track-height: 8px;
|
||||
--switch-track-width: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-badge {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user