mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-06-16 18:14:57 +02:00
Compare commits
1046 Commits
chat-feder
...
2026.5.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bc0ccb108 | ||
|
|
fc6c45d175 | ||
|
|
99081be9fd | ||
|
|
9410bc5194 | ||
|
|
baad1c51d8 | ||
|
|
e6375fb756 | ||
|
|
92c1dc06f2 | ||
|
|
1684dc9c05 | ||
|
|
08c6efb044 | ||
|
|
62b323b58b | ||
|
|
a3227c99ed | ||
|
|
f4bca4641c | ||
|
|
e233556700 | ||
|
|
6665c398d6 | ||
|
|
bf3c1f6686 | ||
|
|
f6ea52b1be | ||
|
|
b950f905e5 | ||
|
|
a19da1258d | ||
|
|
408d05654c | ||
|
|
3074784d4d | ||
|
|
a09a2c2eee | ||
|
|
717931cfcb | ||
|
|
9027129b58 | ||
|
|
b73ac26612 | ||
|
|
b528ff9c59 | ||
|
|
a82ba0d775 | ||
|
|
b78e0168b0 | ||
|
|
33f59b3469 | ||
|
|
5b478dda9d | ||
|
|
90725d6a8c | ||
|
|
86542f07d3 | ||
|
|
45022bc766 | ||
|
|
35711fc8e1 | ||
|
|
45f140aa86 | ||
|
|
22ce7b58ca | ||
|
|
37107c9818 | ||
|
|
a5a43c8c06 | ||
|
|
723d8add2f | ||
|
|
9d20152e05 | ||
|
|
37412f0e1b | ||
|
|
712b51c142 | ||
|
|
2b4bdbfde7 | ||
|
|
39032c4b1b | ||
|
|
f5a3d8996d | ||
|
|
d55e936653 | ||
|
|
6229ac365e | ||
|
|
6d9412b338 | ||
|
|
a23a72b015 | ||
|
|
93bd9d551d | ||
|
|
35d6c20828 | ||
|
|
7c9942f014 | ||
|
|
665adfccb7 | ||
|
|
973b5b50a9 | ||
|
|
985de915b3 | ||
|
|
0227148c89 | ||
|
|
7bfd85cdba | ||
|
|
21f51be5b7 | ||
|
|
b45f18cd14 | ||
|
|
6176cca0a4 | ||
|
|
9569310adb | ||
|
|
b28338c812 | ||
|
|
0f5da63328 | ||
|
|
23715c649c | ||
|
|
1dc5c60b2b | ||
|
|
3a3057a1b1 | ||
|
|
8a85ee1d45 | ||
|
|
c1b73f947c | ||
|
|
bda98ba1d9 | ||
|
|
351fe2f70a | ||
|
|
6d15fe32d0 | ||
|
|
1391269a67 | ||
|
|
86092f2faf | ||
|
|
c640aeb27a | ||
|
|
0be3142d54 | ||
|
|
37bfcb604f | ||
|
|
024f8bb102 | ||
|
|
277a1ef31f | ||
|
|
8e536eb4b9 | ||
|
|
360e805638 | ||
|
|
c95aef7535 | ||
|
|
758a085812 | ||
|
|
a6de986f83 | ||
|
|
12e590a63f | ||
|
|
a5b1f839ac | ||
|
|
d7ceaa9c88 | ||
|
|
55b0fbd172 | ||
|
|
6532cb85e7 | ||
|
|
5dc508346c | ||
|
|
c9c6ef2772 | ||
|
|
4d6256e91d | ||
|
|
cdf0438154 | ||
|
|
29cecd750f | ||
|
|
68e3476a16 | ||
|
|
3cb003366f | ||
|
|
787de92c2f | ||
|
|
22577e2134 | ||
|
|
0355420c81 | ||
|
|
4750980cef | ||
|
|
92e0e8edf7 | ||
|
|
5cb3a91b15 | ||
|
|
60018d16da | ||
|
|
b63984893e | ||
|
|
d4a5048aae | ||
|
|
b9923d0a23 | ||
|
|
38be94b2a3 | ||
|
|
ae34578c6f | ||
|
|
367766d864 | ||
|
|
a18c909ba3 | ||
|
|
0b7b59f1e2 | ||
|
|
8169c57bd1 | ||
|
|
e601fcb729 | ||
|
|
5361a3819b | ||
|
|
dbc5fe2454 | ||
|
|
7bd7e5c4db | ||
|
|
b97683cdb2 | ||
|
|
ece9679cc4 | ||
|
|
c5fd36094d | ||
|
|
b5a6e12439 | ||
|
|
1d171aeb96 | ||
|
|
b826a16231 | ||
|
|
9e38288da5 | ||
|
|
57ed2914d1 | ||
|
|
54e94263a8 | ||
|
|
0e4732180f | ||
|
|
df1fa8b90a | ||
|
|
45df44899a | ||
|
|
2904b5a342 | ||
|
|
f16ef2ef56 | ||
|
|
a3b0dc91e8 | ||
|
|
07bbc5ab33 | ||
|
|
bbffa563d9 | ||
|
|
1eefd8d3f0 | ||
|
|
589a3e229b | ||
|
|
9377e94072 | ||
|
|
bc19359876 | ||
|
|
47db963d8d | ||
|
|
277716bc49 | ||
|
|
db5cc6c058 | ||
|
|
06f8dd39ca | ||
|
|
307e90427a | ||
|
|
d083855f7f | ||
|
|
4ec56ba9f6 | ||
|
|
5e62ad160e | ||
|
|
e554e72b55 | ||
|
|
25783425e1 | ||
|
|
582ebe422c | ||
|
|
06e74508a2 | ||
|
|
b361a10c48 | ||
|
|
a07dc589e7 | ||
|
|
b5d399674a | ||
|
|
e074a91189 | ||
|
|
29c357a988 | ||
|
|
ac45781ef9 | ||
|
|
5d78b320de | ||
|
|
a025209602 | ||
|
|
d5b86a8b49 | ||
|
|
1a62318bcc | ||
|
|
9c30c0915a | ||
|
|
53b9abd098 | ||
|
|
3980b2ca55 | ||
|
|
810faa8e5d | ||
|
|
ae1304d645 | ||
|
|
676e164634 | ||
|
|
71f50d3280 | ||
|
|
d4cd47f455 | ||
|
|
22a6935468 | ||
|
|
264068c58b | ||
|
|
97f7659bac | ||
|
|
41620600cc | ||
|
|
b5121dc70e | ||
|
|
bd992661f4 | ||
|
|
799f5ab504 | ||
|
|
d4bc753e72 | ||
|
|
af40eb4d31 | ||
|
|
a22b82c414 | ||
|
|
28f5b2f173 | ||
|
|
c86cbfcfba | ||
|
|
00cbd1e6db | ||
|
|
65e51463c8 | ||
|
|
39362f78a6 | ||
|
|
d2154214ba | ||
|
|
97312b97f8 | ||
|
|
5e2b041f84 | ||
|
|
ec97f49919 | ||
|
|
4910fff7fb | ||
|
|
fc7655c808 | ||
|
|
ae2ac9d50f | ||
|
|
8932492fd3 | ||
|
|
a168e7b648 | ||
|
|
1adcb03b93 | ||
|
|
b6e737dc76 | ||
|
|
2fa6ecc7ef | ||
|
|
f744b5711f | ||
|
|
2b3d72bb73 | ||
|
|
3205eb6925 | ||
|
|
d4fcc694a6 | ||
|
|
389861f1da | ||
|
|
ec683f04d1 | ||
|
|
bd81a6c8ad | ||
|
|
d8318c02a1 | ||
|
|
b941c896aa | ||
|
|
153ebd4392 | ||
|
|
bc5aef846b | ||
|
|
4a0edf348a | ||
|
|
f3aa5081ed | ||
|
|
c0d5c0df69 | ||
|
|
0b383efa5a | ||
|
|
abe745ec87 | ||
|
|
2168395b71 | ||
|
|
7a9c4591c2 | ||
|
|
4bc0026900 | ||
|
|
faf2399e31 | ||
|
|
106fffdcfe | ||
|
|
141964e57c | ||
|
|
41592eafb3 | ||
|
|
2a14025c29 | ||
|
|
75b5dc1cd8 | ||
|
|
ee0eeb052f | ||
|
|
ece4efcefe | ||
|
|
cd973b252a | ||
|
|
666f78e676 | ||
|
|
cf89c4e363 | ||
|
|
bf41e9edd1 | ||
|
|
f92c187e2b | ||
|
|
8c5572dd3b | ||
|
|
e18b92823f | ||
|
|
2d709ceeb4 | ||
|
|
38b3eecc8c | ||
|
|
f6fc78f578 | ||
|
|
6e99acf7a7 | ||
|
|
553a147396 | ||
|
|
7bcfeba7e5 | ||
|
|
4f65c1529b | ||
|
|
589ae8d4c6 | ||
|
|
0be4405a79 | ||
|
|
2fba2e7049 | ||
|
|
96b03a7179 | ||
|
|
cdb958cdf0 | ||
|
|
245775ea87 | ||
|
|
40d55fc6a3 | ||
|
|
9c22538454 | ||
|
|
a1ba403f9a | ||
|
|
443e1ed29e | ||
|
|
b5454cb2c4 | ||
|
|
8577f10456 | ||
|
|
16ffd88ecc | ||
|
|
866e675134 | ||
|
|
01aa56c602 | ||
|
|
ff7d2c1083 | ||
|
|
404fca6c2d | ||
|
|
3fe0477cac | ||
|
|
97d485bdd2 | ||
|
|
4285303c81 | ||
|
|
14f58255ee | ||
|
|
b69b0acf59 | ||
|
|
7a5430199f | ||
|
|
c32307dca4 | ||
|
|
bc78bb9b8e | ||
|
|
a33b003282 | ||
|
|
74e847a04d | ||
|
|
06657c81d3 | ||
|
|
5c5e965151 | ||
|
|
b07a1e692f | ||
|
|
78348007ed | ||
|
|
92f1e599db | ||
|
|
26b5979c76 | ||
|
|
b1048525d2 | ||
|
|
4c31eb409c | ||
|
|
f739cb6270 | ||
|
|
81bacb6203 | ||
|
|
ee8dccea2f | ||
|
|
6d00645bc7 | ||
|
|
baeed4bc80 | ||
|
|
dba44daf9c | ||
|
|
46e6dd99d1 | ||
|
|
f48af7f73b | ||
|
|
834e8b4c24 | ||
|
|
7ef0c96758 | ||
|
|
b10074e939 | ||
|
|
260dbd150b | ||
|
|
79cbbcfe0f | ||
|
|
c893f85864 | ||
|
|
24d4ffa2ec | ||
|
|
0b931daefd | ||
|
|
cc05d93194 | ||
|
|
90345591bb | ||
|
|
730227f353 | ||
|
|
4acb37ee9d | ||
|
|
7025769c69 | ||
|
|
1a4ef8769f | ||
|
|
055cd0c250 | ||
|
|
d35ddc77d2 | ||
|
|
8d871a58e3 | ||
|
|
99b0b436e0 | ||
|
|
e3d5b95672 | ||
|
|
0d52145b2b | ||
|
|
467404d5bb | ||
|
|
99e25784ad | ||
|
|
9e1e40d35a | ||
|
|
8eb6e29d2c | ||
|
|
2d198a711b | ||
|
|
e0b872dc09 | ||
|
|
711b86ab7d | ||
|
|
e8b4dae553 | ||
|
|
36d404818d | ||
|
|
cb03f3f013 | ||
|
|
c109bec013 | ||
|
|
6fa4eb8c4f | ||
|
|
5fb4caa14b | ||
|
|
bc1f83664f | ||
|
|
78435dc8d4 | ||
|
|
d74aded35f | ||
|
|
d605680524 | ||
|
|
1096ce8e4a | ||
|
|
8e6fffee68 | ||
|
|
2cffd9f0fb | ||
|
|
988f5ab69f | ||
|
|
3afe7c5348 | ||
|
|
73cc30f50f | ||
|
|
da3b3af984 | ||
|
|
3273ca7512 | ||
|
|
b67bfe0763 | ||
|
|
63d2870755 | ||
|
|
61f9c148f0 | ||
|
|
8927a9e98a | ||
|
|
dc77d59f87 | ||
|
|
2d0dae236f | ||
|
|
a1f0ca4b8f | ||
|
|
2a996287e3 | ||
|
|
65dd917bfb | ||
|
|
b0bffd3842 | ||
|
|
4ee6f90ab2 | ||
|
|
50379e52db | ||
|
|
6bb29ab5c3 | ||
|
|
fc1e2229e5 | ||
|
|
daf2a57b3c | ||
|
|
6716950d7f | ||
|
|
29a0750eef | ||
|
|
24bd150967 | ||
|
|
a3c3052d0f | ||
|
|
a6f57d99f9 | ||
|
|
55ef4c5faa | ||
|
|
6293a57de8 | ||
|
|
5512898463 | ||
|
|
0b77dc8c48 | ||
|
|
9900b3492a | ||
|
|
d9c9b95fc0 | ||
|
|
613900598a | ||
|
|
1facca1ac5 | ||
|
|
8d66cc006a | ||
|
|
72cdaff810 | ||
|
|
7b9e83a6b8 | ||
|
|
483483bc44 | ||
|
|
f222d7e24d | ||
|
|
e1b6e9d4b6 | ||
|
|
128fe6d644 | ||
|
|
aa905a74cf | ||
|
|
5e2a6021ae | ||
|
|
dfd479bec5 | ||
|
|
0933aa4d92 | ||
|
|
fbd11c1eec | ||
|
|
768e1dd016 | ||
|
|
d55f51a69b | ||
|
|
fe01a5a28f | ||
|
|
32b5583432 | ||
|
|
5fbe801d35 | ||
|
|
3c11797c6d | ||
|
|
10242d5f14 | ||
|
|
0455187a68 | ||
|
|
1ae8e7900d | ||
|
|
81635d9f1c | ||
|
|
4bdbe794a6 | ||
|
|
cad93071da | ||
|
|
2effd9da6e | ||
|
|
2732034447 | ||
|
|
17a4d4fad9 | ||
|
|
f01ceb0b7c | ||
|
|
0b3efa47a2 | ||
|
|
e44f14115e | ||
|
|
bcd9e106e3 | ||
|
|
82b577a2f4 | ||
|
|
8d8504103c | ||
|
|
7a8c4817a8 | ||
|
|
825dcf7e3e | ||
|
|
53e2be747d | ||
|
|
f10496645c | ||
|
|
666e046399 | ||
|
|
f13a34bda4 | ||
|
|
643fd0f22a | ||
|
|
d3aba01db2 | ||
|
|
8fec44d0e9 | ||
|
|
105cc4b50a | ||
|
|
1590a73d3d | ||
|
|
18caa20969 | ||
|
|
1bb8447c73 | ||
|
|
df54bd92d0 | ||
|
|
8cb37792c9 | ||
|
|
3f539916d9 | ||
|
|
415339b30b | ||
|
|
de7cbb376e | ||
|
|
6cb6f794e5 | ||
|
|
236c235115 | ||
|
|
71808d3cc0 | ||
|
|
989c1b351a | ||
|
|
0c5f61721a | ||
|
|
e0e17a78f1 | ||
|
|
2ad393ea45 | ||
|
|
cdf059cc11 | ||
|
|
0fdd88f38e | ||
|
|
4679b2b34d | ||
|
|
052b1a6c76 | ||
|
|
fd15a7fc23 | ||
|
|
b895088546 | ||
|
|
1e5592a5bd | ||
|
|
c3ad46ad6f | ||
|
|
8c7e1bd287 | ||
|
|
043b9b3d26 | ||
|
|
91dafc26a7 | ||
|
|
4edd6a68e6 | ||
|
|
f801d1cf0b | ||
|
|
42706970f2 | ||
|
|
14730e429a | ||
|
|
2ee04860fb | ||
|
|
25afb5d279 | ||
|
|
c4f53aba3f | ||
|
|
86e4f15e95 | ||
|
|
6c190e7a5d | ||
|
|
1b46813e7a | ||
|
|
0ea0e05e61 | ||
|
|
015e680133 | ||
|
|
ea40a0756f | ||
|
|
70fa621e22 | ||
|
|
c741aa5d7d | ||
|
|
7afe0d44d1 | ||
|
|
e588615ea9 | ||
|
|
7e56fed164 | ||
|
|
9f810d701d | ||
|
|
2f3421645a | ||
|
|
4c0f215fc5 | ||
|
|
449b00c934 | ||
|
|
cdcff3ede8 | ||
|
|
9d1c3f053c | ||
|
|
8c5d571975 | ||
|
|
c5e9f7add4 | ||
|
|
e15fdd05b7 | ||
|
|
41e945b0ef | ||
|
|
f89faae0ab | ||
|
|
67ca3d7e71 | ||
|
|
2ac2e9e849 | ||
|
|
746269c4b1 | ||
|
|
c059256bd6 | ||
|
|
2e17979abc | ||
|
|
c2d95ebdcb | ||
|
|
cb5de83bad | ||
|
|
30d87d5532 | ||
|
|
5c212c996a | ||
|
|
39e01b1dfe | ||
|
|
fd2fe34270 | ||
|
|
73bcd330f7 | ||
|
|
23d2d191a0 | ||
|
|
ca1bf21dcf | ||
|
|
1ffc53f596 | ||
|
|
4e38f218ec | ||
|
|
a0d34940ff | ||
|
|
bdddd623b6 | ||
|
|
29bfc9a91a | ||
|
|
2e596607f8 | ||
|
|
cf89280fc5 | ||
|
|
c0f4c47c53 | ||
|
|
58995e6b97 | ||
|
|
d00ca499a3 | ||
|
|
ec1120bdaa | ||
|
|
3a65728fb4 | ||
|
|
e4c03b9f4e | ||
|
|
b82533c4b8 | ||
|
|
ef1cdca6f9 | ||
|
|
46d30f454b | ||
|
|
b300b5b94a | ||
|
|
39d6aecc57 | ||
|
|
edbe30a3df | ||
|
|
ad4751918b | ||
|
|
bd9041bd8f | ||
|
|
4dcff123df | ||
|
|
990be44d98 | ||
|
|
78d65ef3dd | ||
|
|
0a67d6f1a0 | ||
|
|
e312283ea0 | ||
|
|
e8c78e12d5 | ||
|
|
37fe7a9634 | ||
|
|
729abbef62 | ||
|
|
e74ab35de3 | ||
|
|
4ba18690d7 | ||
|
|
26c8914a26 | ||
|
|
119423e3ae | ||
|
|
3de1ce63cd | ||
|
|
18fbc9bb05 | ||
|
|
37a21cf54e | ||
|
|
290fd8c7cc | ||
|
|
0edb0133fc | ||
|
|
0abe021640 | ||
|
|
344f50d538 | ||
|
|
1cebad0ddb | ||
|
|
3e34e87a59 | ||
|
|
b9713259a7 | ||
|
|
e15b8b7fa3 | ||
|
|
ca89c86426 | ||
|
|
6bce19655b | ||
|
|
78ed024b0b | ||
|
|
6f76b598a1 | ||
|
|
a888f2863b | ||
|
|
a892bbcce5 | ||
|
|
6571c87e14 | ||
|
|
9e0f18a705 | ||
|
|
3dfca2d61f | ||
|
|
f1578c282e | ||
|
|
231a6877be | ||
|
|
d0a5ccc1ec | ||
|
|
4e16e23acd | ||
|
|
17da44078b | ||
|
|
1f29fb4e40 | ||
|
|
0343b4e689 | ||
|
|
a76a1a6305 | ||
|
|
1f934ada5d | ||
|
|
cd77404006 | ||
|
|
351386c8ff | ||
|
|
298f8802d4 | ||
|
|
6e614ff061 | ||
|
|
ca76ba1871 | ||
|
|
9f768b8022 | ||
|
|
4ff826eb3d | ||
|
|
60bcb9c6a9 | ||
|
|
0c85bfd56f | ||
|
|
9d37f696b4 | ||
|
|
2734ff6af7 | ||
|
|
456504cf82 | ||
|
|
81cea6aed5 | ||
|
|
2d1b7c957a | ||
|
|
5b6aa1496a | ||
|
|
259dd34b26 | ||
|
|
cf81406fae | ||
|
|
42f230f223 | ||
|
|
2e07e50bb4 | ||
|
|
d203e1a446 | ||
|
|
4988719a2e | ||
|
|
f0380f2d1c | ||
|
|
130d065d0c | ||
|
|
7b41fddf54 | ||
|
|
aafd8b6bf7 | ||
|
|
7a82c1a912 | ||
|
|
3c97c12e7f | ||
|
|
5b5a1f08e1 | ||
|
|
c4ee95a40a | ||
|
|
8ea7fe0ba1 | ||
|
|
187b6477da | ||
|
|
09896fdc12 | ||
|
|
d4cda989a2 | ||
|
|
f93043e170 | ||
|
|
1c2e57d60c | ||
|
|
67c853104c | ||
|
|
986d783940 | ||
|
|
61cfccff37 | ||
|
|
b161fe7adc | ||
|
|
c3b1c8a8ff | ||
|
|
bc2b512be6 | ||
|
|
7fe9574897 | ||
|
|
8549f71656 | ||
|
|
ae4487fa69 | ||
|
|
0a75d6fcf1 | ||
|
|
d3bb24d851 | ||
|
|
9aea7363ce | ||
|
|
f0889f4b3c | ||
|
|
b8433b2413 | ||
|
|
4e9070a4c5 | ||
|
|
bff194f648 | ||
|
|
8714945ec9 | ||
|
|
aadc7bf61a | ||
|
|
acd35ef96c | ||
|
|
43919a3fe3 | ||
|
|
8a21202281 | ||
|
|
579499a7df | ||
|
|
b48233eb4c | ||
|
|
d98bf012b5 | ||
|
|
44930342a8 | ||
|
|
29892d2a01 | ||
|
|
b6bf3cfcb7 | ||
|
|
a132a1d3e1 | ||
|
|
8cfd147555 | ||
|
|
a405575cd6 | ||
|
|
56885cceed | ||
|
|
3c64281696 | ||
|
|
45b3afa70d | ||
|
|
beabe84354 | ||
|
|
42008d1377 | ||
|
|
3df81931ec | ||
|
|
4c536630d4 | ||
|
|
92cc55f0f1 | ||
|
|
f8c6273acc | ||
|
|
edf7beff23 | ||
|
|
3804028b6e | ||
|
|
70473c66e9 | ||
|
|
a87a3c6693 | ||
|
|
72a5daeb9a | ||
|
|
54efe1b4c5 | ||
|
|
24129efe97 | ||
|
|
41aa0c8efe | ||
|
|
37526de323 | ||
|
|
21ed2e3002 | ||
|
|
917def4e13 | ||
|
|
d1eb1cad42 | ||
|
|
994690eebf | ||
|
|
b25810e091 | ||
|
|
03544dfd9d | ||
|
|
d4df749f4f | ||
|
|
04e2d44d28 | ||
|
|
6d2e582eaf | ||
|
|
9eb975e71d | ||
|
|
ced687117f | ||
|
|
7cc0483b47 | ||
|
|
a8a0c1c1b6 | ||
|
|
6b438f2ce0 | ||
|
|
188b37b33f | ||
|
|
0b642cf446 | ||
|
|
fe38115883 | ||
|
|
6fba73ca13 | ||
|
|
0d33e1f839 | ||
|
|
74f33157a3 | ||
|
|
ae10cad9a7 | ||
|
|
ba9924abdb | ||
|
|
99686801a0 | ||
|
|
f3e0713501 | ||
|
|
7fcbf57a9d | ||
|
|
7cd55c31da | ||
|
|
d03cf4d7f9 | ||
|
|
a8fcdb79ab | ||
|
|
eae9af73c2 | ||
|
|
c0dc156df7 | ||
|
|
720c6519cd | ||
|
|
f89b4cdc12 | ||
|
|
46b0e8115a | ||
|
|
7796fce779 | ||
|
|
3954837cfa | ||
|
|
7ea4cad12e | ||
|
|
d864e9a269 | ||
|
|
4e0434c275 | ||
|
|
e2f939080a | ||
|
|
6956f44d1f | ||
|
|
a393d5a87e | ||
|
|
6c634de482 | ||
|
|
fc02e0d34d | ||
|
|
cb1a90ddad | ||
|
|
f0fb3a56a8 | ||
|
|
b8ae7edcec | ||
|
|
e24233c1c7 | ||
|
|
225154d76d | ||
|
|
c5f9c0ce5c | ||
|
|
cce302ae4f | ||
|
|
e0d210e15b | ||
|
|
0b7634b126 | ||
|
|
d1446d195a | ||
|
|
218070eb13 | ||
|
|
0f8c068e84 | ||
|
|
69d66b89f2 | ||
|
|
211365de64 | ||
|
|
966127c63e | ||
|
|
54800971eb | ||
|
|
13d5c6d2b2 | ||
|
|
2cff00eedd | ||
|
|
3fc2261041 | ||
|
|
18d66c0233 | ||
|
|
2f52c20150 | ||
|
|
9d70c9ad78 | ||
|
|
42b2aea533 | ||
|
|
97adf6f2cc | ||
|
|
93ff209c51 | ||
|
|
5fe08d0bbb | ||
|
|
8c413d01e6 | ||
|
|
b231da7c7c | ||
|
|
df3e44f62e | ||
|
|
e504560477 | ||
|
|
bcb2073715 | ||
|
|
6a80c23a50 | ||
|
|
2621f468ff | ||
|
|
d4654dd7bd | ||
|
|
b7da6cad87 | ||
|
|
5b4115e21a | ||
|
|
c174c5c144 | ||
|
|
aebc3f781e | ||
|
|
f60b6291d7 | ||
|
|
7673874675 | ||
|
|
6e3354f95d | ||
|
|
b9df928097 | ||
|
|
0754678144 | ||
|
|
a8cc51dc77 | ||
|
|
690edcef16 | ||
|
|
2ea784f345 | ||
|
|
20d257b562 | ||
|
|
c215415613 | ||
|
|
726c03d96a | ||
|
|
e65ddb546c | ||
|
|
85aea9077f | ||
|
|
f3fffce6a9 | ||
|
|
eb7db5a3aa | ||
|
|
e33eb26863 | ||
|
|
430310f306 | ||
|
|
1e1eea521e | ||
|
|
86ad771221 | ||
|
|
057acf471e | ||
|
|
2bfe257879 | ||
|
|
6d75624aa8 | ||
|
|
369f0ec88a | ||
|
|
788c5660ba | ||
|
|
6cf1f86636 | ||
|
|
5b994b3e03 | ||
|
|
7b2abb7577 | ||
|
|
b681788315 | ||
|
|
279af1d72f | ||
|
|
9e188ca3fa | ||
|
|
de1b2223ff | ||
|
|
9b565728e7 | ||
|
|
a92fd8856a | ||
|
|
047773341d | ||
|
|
842670e100 | ||
|
|
ffc481a994 | ||
|
|
2ccf4f94cb | ||
|
|
3566bc207f | ||
|
|
4a0e968662 | ||
|
|
b1479ab1d8 | ||
|
|
18a9ccf7af | ||
|
|
959e72b2b3 | ||
|
|
a3d78b2f08 | ||
|
|
3c998e1f48 | ||
|
|
782c9f9852 | ||
|
|
d27c740ab0 | ||
|
|
08ecf7ca79 | ||
|
|
bdec4bf87a | ||
|
|
7000095b44 | ||
|
|
18e42cc83d | ||
|
|
11204eeb43 | ||
|
|
c95092903a | ||
|
|
21b2b9e5f8 | ||
|
|
665ec2c43c | ||
|
|
34bd840525 | ||
|
|
3d1cbcf094 | ||
|
|
5f5d88036f | ||
|
|
24739cd040 | ||
|
|
b491432daa | ||
|
|
ebe029458e | ||
|
|
d127d82c5b | ||
|
|
aabda5a956 | ||
|
|
bd5b38c9d9 | ||
|
|
647e03bf34 | ||
|
|
d16db7f311 | ||
|
|
ec4731dee4 | ||
|
|
65a4d77a7f | ||
|
|
328301ffc2 | ||
|
|
def148d7a6 | ||
|
|
aa85d701b9 | ||
|
|
f0833cffe9 | ||
|
|
9cd918f12b | ||
|
|
195a80622b | ||
|
|
8b347e23e3 | ||
|
|
bca3602da2 | ||
|
|
cfd4d7c57b | ||
|
|
084ccf5c9a | ||
|
|
fc1693f768 | ||
|
|
ff6f115976 | ||
|
|
8c2b96ad37 | ||
|
|
3e24419981 | ||
|
|
25c2007f59 | ||
|
|
2e4c4dd555 | ||
|
|
653cb116ea | ||
|
|
c9f363b215 | ||
|
|
e72da587e4 | ||
|
|
439337a108 | ||
|
|
5fef2332f4 | ||
|
|
40a325cbe7 | ||
|
|
5eff31383f | ||
|
|
575379a683 | ||
|
|
bf82b49633 | ||
|
|
87d09f255d | ||
|
|
98e07c3bd1 | ||
|
|
c5bb881438 | ||
|
|
ee96f77ef2 | ||
|
|
55eb18f5a6 | ||
|
|
aa8daca914 | ||
|
|
3e9118af3d | ||
|
|
25df56dfd0 | ||
|
|
231ccae006 | ||
|
|
2e0a34300a | ||
|
|
d2fd7460ed | ||
|
|
5e3d8fc9b8 | ||
|
|
b186c67767 | ||
|
|
ac7c60d102 | ||
|
|
b9dbd58a1c | ||
|
|
69bbac013a | ||
|
|
203296b9cb | ||
|
|
689d70ffae | ||
|
|
d5475d1ff6 | ||
|
|
05cc8047fa | ||
|
|
d6a1046361 | ||
|
|
eb9915baf8 | ||
|
|
dbb6c71c5c | ||
|
|
9e5c8d94bf | ||
|
|
120af977a9 | ||
|
|
506c8a259b | ||
|
|
0c8545ec1c | ||
|
|
7e7dc03796 | ||
|
|
a874def344 | ||
|
|
44ac51f64f | ||
|
|
3b65be8b91 | ||
|
|
76beac41d2 | ||
|
|
69cdc73f5a | ||
|
|
1c966db324 | ||
|
|
692284886b | ||
|
|
0121d19645 | ||
|
|
bf8636e516 | ||
|
|
d336a1fb1c | ||
|
|
7c761e7017 | ||
|
|
7924daf7f8 | ||
|
|
2b9706a68b | ||
|
|
f2d15f9240 | ||
|
|
caf6a3ab81 | ||
|
|
f4baa973bf | ||
|
|
3741fa4b49 | ||
|
|
27df7f643e | ||
|
|
30987b6f1f | ||
|
|
41b5677f01 | ||
|
|
47d83e8930 | ||
|
|
61ff1f313b | ||
|
|
637ad3d479 | ||
|
|
2dd8c2a355 | ||
|
|
857a87d4b6 | ||
|
|
8b4cea5c86 | ||
|
|
9f25d96ec3 | ||
|
|
bd0730e5e8 | ||
|
|
07ccb82691 | ||
|
|
16030c6381 | ||
|
|
1f6716d69b | ||
|
|
ade603ff7a | ||
|
|
4d215bde10 | ||
|
|
20d81696e1 | ||
|
|
8cbbb80e3f | ||
|
|
1eabb21d69 | ||
|
|
7f6ba2e501 | ||
|
|
8c433d2706 | ||
|
|
3a856b785d | ||
|
|
b07bf838e3 | ||
|
|
bdfe709319 | ||
|
|
4190c6cb8e | ||
|
|
44a2d531b3 | ||
|
|
a17271a5c4 | ||
|
|
3980172243 | ||
|
|
3b4879133c | ||
|
|
a1232cbae3 | ||
|
|
ebb014da4c | ||
|
|
7786761d76 | ||
|
|
ff334fe9d7 | ||
|
|
ba40cb750b | ||
|
|
fcde6789ff | ||
|
|
14cc42e305 | ||
|
|
e481205342 | ||
|
|
fea9f27fd6 | ||
|
|
9ea7340da6 | ||
|
|
60f7278aff | ||
|
|
bae92a944d | ||
|
|
7d30768769 | ||
|
|
e444942c4e | ||
|
|
90b9609341 | ||
|
|
c25a922928 | ||
|
|
d26169ea32 | ||
|
|
8839d8d679 | ||
|
|
ad6af74eef | ||
|
|
7bb43329bb | ||
|
|
4c41930554 | ||
|
|
295f42b986 | ||
|
|
299f9e3115 | ||
|
|
1d8e183883 | ||
|
|
f242892382 | ||
|
|
ecc033f101 | ||
|
|
684dbfd626 | ||
|
|
aa5c42997f | ||
|
|
e7b666f567 | ||
|
|
0f7c0ed053 | ||
|
|
1e92bb4a0a | ||
|
|
b5b7914073 | ||
|
|
7595bff43b | ||
|
|
72864fcbd0 | ||
|
|
1b0de39f92 | ||
|
|
d8a137cb6c | ||
|
|
ddac2fb7a1 | ||
|
|
b1b335d55a | ||
|
|
0586dd98cb | ||
|
|
504f886065 | ||
|
|
2931eb0aad | ||
|
|
103d5a4b44 | ||
|
|
785b85ee46 | ||
|
|
8bd84a0ec4 | ||
|
|
9539995458 | ||
|
|
e67ff36e57 | ||
|
|
96a165d729 | ||
|
|
215725a3ac | ||
|
|
3da04fcae4 | ||
|
|
85e3e49688 | ||
|
|
076a83466e | ||
|
|
aaf3f343ea | ||
|
|
4a5751416a | ||
|
|
adb3ad6b7f | ||
|
|
8598f3912e | ||
|
|
f86239ab2f | ||
|
|
ee9dc94063 | ||
|
|
998beeae59 | ||
|
|
9931fff35b | ||
|
|
b4a0fdfaa1 | ||
|
|
d979cd2c07 | ||
|
|
bb56b3b4f1 | ||
|
|
2f13f923a8 | ||
|
|
93fefc58c7 | ||
|
|
bd7339c397 | ||
|
|
941625fd08 | ||
|
|
b6765edffe | ||
|
|
9273b21516 | ||
|
|
aa10e537a5 | ||
|
|
c79fe6dc33 | ||
|
|
fbf8db618c | ||
|
|
6f3cc2cdf7 | ||
|
|
7c1f4c9037 | ||
|
|
2da20bf3e8 | ||
|
|
6d54370f01 | ||
|
|
905d3c87f1 | ||
|
|
fc244067e0 | ||
|
|
8449354887 | ||
|
|
57e0f1b4ef | ||
|
|
a1e170e065 | ||
|
|
73de40b81e | ||
|
|
2c836e3c24 | ||
|
|
c2c5898221 | ||
|
|
99adf12355 | ||
|
|
7df0a6c55f | ||
|
|
e092008dc5 | ||
|
|
0cfc910cdc | ||
|
|
62f68de800 | ||
|
|
5bf13c4cc2 | ||
|
|
16f47adcc6 | ||
|
|
8eba8c7218 | ||
|
|
b214a19d5f | ||
|
|
1082145c74 | ||
|
|
2a836047e3 | ||
|
|
b2b07e5f21 | ||
|
|
da06f75455 | ||
|
|
d624da9c1a | ||
|
|
4c520fa693 | ||
|
|
a7d1c94f48 | ||
|
|
4f5d3f6f7d | ||
|
|
4be0045826 | ||
|
|
18daf43f70 | ||
|
|
862a6fae79 | ||
|
|
a45e89c300 | ||
|
|
35888eb8f4 | ||
|
|
f2a23fb55e | ||
|
|
414d5958c1 | ||
|
|
8c65d8d020 | ||
|
|
927aa9dc3d | ||
|
|
1dec8b2329 | ||
|
|
b0493abe93 | ||
|
|
4f653f2fbc | ||
|
|
b660769288 | ||
|
|
48246bd166 | ||
|
|
73419e8a61 | ||
|
|
9852196ddc | ||
|
|
598641de48 | ||
|
|
4d643c77c5 | ||
|
|
a686592734 | ||
|
|
0619dba04d | ||
|
|
fbd6b67f1f | ||
|
|
e5c2be15f7 | ||
|
|
1b791258ce | ||
|
|
49cac2f72b | ||
|
|
5d5aa09459 | ||
|
|
e1834beae8 | ||
|
|
6f6fdfe28e | ||
|
|
ad7bf096e1 | ||
|
|
08cc5a99bb | ||
|
|
f954b1e276 | ||
|
|
5ecaf5095e | ||
|
|
d2c4f79886 | ||
|
|
e26369ed48 | ||
|
|
c165749a29 | ||
|
|
c4fdf5a47c | ||
|
|
288f0abeac | ||
|
|
89ed8be8ff | ||
|
|
a8abb03d17 | ||
|
|
c2a01551a7 | ||
|
|
553ccff77c | ||
|
|
9dddc84750 | ||
|
|
004cfd5e4b | ||
|
|
40a35968f0 | ||
|
|
e6ec15e397 | ||
|
|
8430256f22 | ||
|
|
abde15979b | ||
|
|
f128682200 | ||
|
|
cc4cdd1ec0 | ||
|
|
075df75afa | ||
|
|
64eb338d65 | ||
|
|
d986da745b | ||
|
|
50f5b29290 | ||
|
|
a460bb7913 | ||
|
|
7cf1eccd04 | ||
|
|
73397e1b7e | ||
|
|
bf17092b41 | ||
|
|
6d1018f42b | ||
|
|
7667011266 | ||
|
|
a45ccc18b4 | ||
|
|
c29a4d9503 | ||
|
|
5caf2b27cf | ||
|
|
dd87d26bdc | ||
|
|
b7a6301c2e | ||
|
|
73e8d950df | ||
|
|
45033974f7 | ||
|
|
7acfbc23d6 | ||
|
|
a9a746edce | ||
|
|
179d990c39 | ||
|
|
7c44881ca8 | ||
|
|
ccbc4cffaa | ||
|
|
706244925d | ||
|
|
09a5e4b10a | ||
|
|
c48acad04b | ||
|
|
5d3bb02f4b | ||
|
|
933e252687 | ||
|
|
f1deb89e34 | ||
|
|
8bc822d829 | ||
|
|
c215cccf1d | ||
|
|
0685bdf05c | ||
|
|
3394ed2122 | ||
|
|
c5a440cf22 | ||
|
|
3c6f07fc8c | ||
|
|
3c5ed0ffbb | ||
|
|
b8e8f3ad25 | ||
|
|
012b2a9764 | ||
|
|
dfbc40f868 | ||
|
|
32ddaa0cf8 | ||
|
|
bf6e218355 | ||
|
|
19ef6c0b14 | ||
|
|
535b86f05e | ||
|
|
01a94eaecb | ||
|
|
9a28fa0534 | ||
|
|
899273554a |
2
.claude/.gitignore
vendored
Normal file
2
.claude/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/settings.local.json
|
||||
/.credentials.json
|
||||
76
.claude/THIRD_PARTY_LICENSES.md
Normal file
76
.claude/THIRD_PARTY_LICENSES.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Third-Party Licenses (`.claude/`)
|
||||
|
||||
`.claude/` 配下に取り込まれているサードパーティ由来コンポーネントのライセンス・出典情報をまとめる。Misskey 本体は AGPL-3.0-only だが、本ディレクトリ内には MIT ライセンスのファイルが含まれている。各ファイル冒頭にも `SPDX-License-Identifier` と出典コメントを併記している。
|
||||
|
||||
最終更新: 2026-05-11
|
||||
|
||||
---
|
||||
|
||||
## 1. everything-claude-code (ECC)
|
||||
|
||||
- 上流リポジトリ: <https://github.com/affaan-m/everything-claude-code>
|
||||
- 取り込んだバージョン: v2.0.0-rc.1
|
||||
- ライセンス: **MIT**
|
||||
- Copyright: Copyright (c) 2026 Affaan Mustafa
|
||||
|
||||
### 取り込んだファイル
|
||||
|
||||
| `.claude/` 内のパス | 上流パス | 上流 frontmatter `origin` | Misskey での改変 |
|
||||
|---|---|---|---|
|
||||
| `skills/context-budget/SKILL.md` | `skills/context-budget/SKILL.md` | ECC | description を日本語化、Misskey 固有メモを追記 |
|
||||
| `commands/harness-audit.md` | `commands/harness-audit.md` | ECC | scripts 依存の自動採点を、Claude が `pnpm`/`git`/`grep` で手動採点する版に書き換え。Misskey 固有の評価軸 (SPDX / endpoint-list / migration / locales) を組み込み |
|
||||
| `commands/quality-gate.md` | `commands/quality-gate.md` | ECC | 言語自動判定を排除し Misskey 固定 pipeline (`pnpm` + tsgo + ESLint + Vitest) に。Prettier/Biome フェーズを削除 |
|
||||
|
||||
### MIT License (full text)
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Affaan Mustafa
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
### 上流 LICENSE ファイル
|
||||
|
||||
<https://github.com/affaan-m/everything-claude-code/blob/main/LICENSE>
|
||||
|
||||
---
|
||||
|
||||
## 2. AGPL コードベースとの互換性
|
||||
|
||||
Misskey 本体は **AGPL-3.0-only** で配布されているが、`.claude/` 配下の MIT ライセンスファイルはそのまま MIT として残している。
|
||||
|
||||
- MIT は permissive ライセンスで、AGPL を含む copyleft ライセンスのプロジェクトに **取り込み・再配布が許される**
|
||||
- MIT が要求する条件 (copyright notice + license text の保持) を本ファイル + 各ファイル冒頭の SPDX/出典コメントで満たしている
|
||||
- Misskey 全体の配布物としては AGPL-3.0-only で扱われるが、`.claude/` 配下の MIT ファイルは個別に MIT として識別可能
|
||||
|
||||
`.ts` / `.js` / `.vue` / `.scss` の SPDX 義務化 ([AGENTS.md §1](../AGENTS.md#1-spdx-ヘッダー必須)) は Misskey 本体コード向けで、`.claude/` 配下の `.md` / `.sh` には適用されない。
|
||||
|
||||
---
|
||||
|
||||
## 3. 新規追加時の手順
|
||||
|
||||
`.claude/` に新たにサードパーティ由来のファイルを取り込む際は:
|
||||
|
||||
1. ライセンスを確認 (互換性: MIT / Apache-2.0 / BSD は OK、GPL/AGPL は要相談)
|
||||
2. 各ファイル冒頭に SPDX ヘッダ + 出典コメントを追加
|
||||
3. 本ファイル §1 のテーブルに 1 行追記
|
||||
4. 必要なら新しいセクションでライセンス全文を同梱
|
||||
5. AGENTS.md からの参照を確認 (現状の [AGENTS.md §ツール固有の補助ファイル](../AGENTS.md) で `THIRD_PARTY_LICENSES.md` を案内済。CLAUDE.md は `@AGENTS.md` 経由で読み込むので個別の追記は不要)
|
||||
23
.claude/agents/README.md
Normal file
23
.claude/agents/README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# `.claude/agents/` — プロジェクト固有のサブエージェント
|
||||
|
||||
Misskey の特定領域に特化したレビュー / 調査エージェントを `.claude/agents/<name>.md` 形式で配置する。
|
||||
|
||||
frontmatter (`name` + `description` + `tools`) は、Claude が **自動でエージェントを呼び出すか判断する** 唯一の手がかりになる。`description` には用途を具体的かつ網羅的に書くこと (動詞 + 対象 + トリガー条件)。
|
||||
|
||||
## 実装済サブエージェント
|
||||
|
||||
| エージェント名 | 役割 | 優先度 |
|
||||
|---|---|---|
|
||||
| [misskey-api-reviewer](misskey-api-reviewer.md) | NestJS DI + meta/paramDef + UUID 重複 + endpoint-list.ts 登録 + ApiError throw + misskey-js 再生成 + e2e + CHANGELOG をチェック | 高 (登録漏れで 404 / autogen CI 落ち頻発) |
|
||||
| [vue-component-reviewer](vue-component-reviewer.md) | Mk\* 命名 / `<script lang="ts" setup>` / type-only defineProps / SCSS module / CSS 変数 / i18n.ts と i18n.tsx の使い分け / os.\* 経由 / a11y / `*.stories.impl.ts` 併設をチェック | 中 (CI 直撃は SPDX / locales 編集違反のみ。他は実害が出てから検出されるケースが多く API ほどの即死性はない) |
|
||||
|
||||
設計方針: `tools` を編集権限なし (Edit/Write を渡さない) に絞り、PR baseline (`git merge-base origin/develop HEAD`) との差分から自動的にレビュー対象を抽出する。
|
||||
|
||||
## 新規エージェントを追加する場合
|
||||
|
||||
- `.claude/agents/<name>.md` に YAML frontmatter (`name` / `description` / `tools`) と本文 Markdown を書く。
|
||||
- `description` は呼び出し判断に使われるため、対象ドメイン・主要チェック項目・トリガー条件を **具体的に** 列挙する。
|
||||
- レビュー専門なら `tools: Read, Grep, Glob, Bash` に絞る (Edit/Write を渡さない)。**`Bash` は任意のシェルコマンドを実行できる強力な権限である点に注意**: レビュー用途では `git diff` / `git ls-files` / `grep` / `sed` 等の **読み取り系コマンドに限定して使う** こと。書き込み・削除・ネットワーク送信を伴う操作は本文中の例示・指示に含めないこと (エージェント本文がガードレールになる)。
|
||||
- 主要参照ファイルへのリンクは、リポジトリルートからの相対パス (例: `../../packages/backend/...`) で貼る。絶対パスは contributor のホームディレクトリ依存になるので使わない。
|
||||
- 差分抽出は `git merge-base origin/develop HEAD` を baseline にする (PR / ブランチ全体を見るため)。`git diff HEAD` 単体は **未コミット差分しか取れず、コミット済の PR では空になって誤判定する** ので使わない。
|
||||
- 完成したらこの README の表にも 1 行追加する。
|
||||
167
.claude/agents/misskey-api-reviewer.md
Normal file
167
.claude/agents/misskey-api-reviewer.md
Normal file
@@ -0,0 +1,167 @@
|
||||
---
|
||||
name: misskey-api-reviewer
|
||||
description: Misskey の API エンドポイント (packages/backend/src/server/api/endpoints/) の追加・変更を専門レビューする。SPDX / meta / paramDef / UUID 重複 / endpoint-list.ts 登録 / ApiError throw / misskey-js 再生成 / e2e / CHANGELOG を機械的にチェック。バックエンド API を追加・変更した PR レビューで呼び出す。
|
||||
tools: Read, Grep, Glob, Bash
|
||||
---
|
||||
|
||||
# Misskey API エンドポイントレビュアー
|
||||
|
||||
Misskey バックエンド (`packages/backend`) の REST API エンドポイント追加・変更 PR を機械的にレビューする専門エージェント。規約の根拠は [.claude/skills/add-api-endpoint/SKILL.md](../skills/add-api-endpoint/SKILL.md)。
|
||||
|
||||
## 役割
|
||||
|
||||
`packages/backend/src/server/api/endpoints/` 配下の `.ts` 変更を対象に、規約逸脱・登録漏れ・型自動生成漏れ・テスト不足を抽出する。良い点には触れず、改善が必要な箇所のみ報告する。
|
||||
|
||||
## レビュー対象の特定
|
||||
|
||||
呼び出し元から明示的にファイルが渡されたらそれを優先する。渡されなかった場合は **PR / ブランチ全体の差分** を取得する (未コミット差分のみではないことに注意)。
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
{ git diff --name-only "$BASE"...HEAD; git diff --name-only HEAD; git ls-files --others --exclude-standard; } \
|
||||
| sort -u \
|
||||
| grep -E '^packages/backend/src/server/api/endpoints/.*\.ts$'
|
||||
```
|
||||
|
||||
`origin/develop` が無い環境では `develop` または `master` にフォールバックする。
|
||||
|
||||
加えて以下も同じ baseline で差分対象に含める:
|
||||
|
||||
- `packages/backend/src/server/api/endpoint-list.ts`
|
||||
- `packages/backend/test/e2e/**` (とくに `endpoints.ts` と `<area>.ts`)
|
||||
- `packages/misskey-js/src/autogen/**`
|
||||
- `CHANGELOG.md`
|
||||
|
||||
差分対象が空なら「レビュー対象の API エンドポイント変更なし」と短く報告して終了。
|
||||
|
||||
## チェックリスト
|
||||
|
||||
### 1. SPDX ヘッダー (Critical)
|
||||
|
||||
新規 `.ts` ファイル冒頭に以下があるか:
|
||||
|
||||
```
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
```
|
||||
|
||||
欠落すると CI の `spdx` ジョブが落ちる。
|
||||
|
||||
### 2. `meta` の必須・推奨フィールド (Major)
|
||||
|
||||
[endpoints.ts の型定義](../../packages/backend/src/server/api/endpoints.ts) を真とする。
|
||||
|
||||
- `tags`: OpenAPI タグ (機能領域)。
|
||||
- `requireCredential`: 明示必須 (boolean)。
|
||||
- `kind`: OAuth scope。`requireCredential: true` のとき必須 (`read:account` / `write:notes` 等)。
|
||||
- `requireModerator` / `requireAdmin`: 権限制限が要るか。
|
||||
- `prohibitMoved`: 移行済アカウントを拒否するか (write 系で要検討)。
|
||||
- `limit`: レート制限 `{ duration, max, key?, minInterval? }`。書き込み系 / コスト高い処理で未指定なら指摘。
|
||||
- `errors`: エラー定義。各要素に `message` / `code` / `id` (UUID v4) が揃っているか。
|
||||
- `res`: JSON Schema または `ref: '<EntityName>'`。各プロパティに `optional` / `nullable` が **明示** されているか。
|
||||
- `requireFile` / `secure` / `allowGet` / `cacheSec` / `description`: 該当するエンドポイントで使い分けているか。
|
||||
|
||||
### 3. `meta.errors` の UUID 検証 (Critical)
|
||||
|
||||
各 `errors[*].id` が:
|
||||
|
||||
1. UUID v4 形式 (`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`) か
|
||||
2. 既存エンドポイントの `id` と重複していないか
|
||||
|
||||
重複検査:
|
||||
|
||||
```bash
|
||||
grep -rn "id: '<生成された UUID>'" packages/backend/src/server/api/endpoints/
|
||||
```
|
||||
|
||||
新規エンドポイントの全 `id` を抽出して衝突を確認する。
|
||||
|
||||
### 4. `paramDef` (Major)
|
||||
|
||||
- JSON Schema 形式 (`type: 'object'`, `properties`, `required`)
|
||||
- ID 文字列は `format: 'misskey:id'`
|
||||
- `required` 配列で必須プロパティを明示
|
||||
- `as const` または `as const satisfies Schema` で型推論を効かせる (既存実装は前者多数。`as const` 自体が無く `Schema` 型注釈もない場合のみ指摘)
|
||||
|
||||
### 5. エンドポイント実装本体 (Major)
|
||||
|
||||
- `Endpoint<typeof meta, typeof paramDef>` を継承しているか。
|
||||
- `@Injectable()` デコレータ + `export default class` 形式か (`// eslint-disable-line import/no-default-export` が必要)。
|
||||
- DI は `@Inject(DI.xxx)` 形式か。
|
||||
- **クライアントに返すべき API エラーは `throw new ApiError(meta.errors.<key>)`** ([error.ts](../../packages/backend/src/server/api/error.ts) 参照)。`meta.errors` で定義したエラーケースを `throw new Error(...)` で投げているなら指摘する。
|
||||
- 防御的アサーション・「起きるはずがない」内部不整合・テスト用 ENV ガード等の **想定外フェイルファスト** は `throw new Error('...')` で構わない。既存実装でも `admin/reset-password.ts` などが採用しているパターン (例: `cannot reset password of root`)。`meta.errors` に対応がない `throw new Error` を一律で指摘しない。
|
||||
- 同期 `throw` は許容。非同期処理での例外伝搬を確認する。
|
||||
|
||||
### 6. ★ `endpoint-list.ts` への登録 (Critical)
|
||||
|
||||
最も忘れやすい。**忘れると 404**。[endpoint-list.ts](../../packages/backend/src/server/api/endpoint-list.ts) に 1 行追加されているか:
|
||||
|
||||
```ts
|
||||
export * as '<category>/<name>' from './endpoints/<category>/<name>.js';
|
||||
```
|
||||
|
||||
新規エンドポイントを抽出し、各々が `endpoint-list.ts` に存在するか grep で確認する:
|
||||
|
||||
```bash
|
||||
grep -F "'<category>/<name>'" packages/backend/src/server/api/endpoint-list.ts
|
||||
```
|
||||
|
||||
**並び順の補足**: ファイル全体は厳密なアルファベット順では並んでおらず、同カテゴリ内 (`admin/queue/*` など) でも追加された経緯どおりの順になっている箇所が多い。**順序逸脱は指摘根拠にしない** (誤検知の元)。「行が存在するか」のみを Critical 観点として扱う。
|
||||
|
||||
### 7. `misskey-js` 再生成 (Critical)
|
||||
|
||||
`meta` / `paramDef` / `res` を変更したら、PR / ブランチに `packages/misskey-js/src/autogen/` 配下の差分が含まれているか確認する:
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
git diff --name-only "$BASE"...HEAD -- packages/misskey-js/src/autogen/
|
||||
```
|
||||
|
||||
差分ゼロなら `pnpm build-misskey-js-with-types` の実行漏れ。CI の `check-misskey-js-autogen` ジョブで必ず落ちるため Critical 扱い。
|
||||
|
||||
### 8. e2e テスト (Major)
|
||||
|
||||
[test/e2e/endpoints.ts](../../packages/backend/test/e2e/endpoints.ts) または `test/e2e/<area>.ts` (`note.ts`, `users.ts` 等) 配下に、対応する `api('<category>/<name>', ...)` 呼び出しを含む `test(...)` ケースが追加されているか確認する。複雑な分岐 (権限チェック・エラーケース) の網羅も確認する。
|
||||
|
||||
**describe ラベルの形式は問わない**: 既存テストは `describe('Note', () => { test('投稿できる', ...) })` のように人間可読ラベルで構造化されており、`<category>/<name>` 形式の describe は使われていない。describe 名の規約違反としては指摘しない。
|
||||
|
||||
### 9. CHANGELOG エントリ (Minor)
|
||||
|
||||
ユーザー影響がある (新エンドポイント / 既存挙動変更) 場合、`CHANGELOG.md` の `## Unreleased` → `### Server` に 1 行追加されているか確認する。
|
||||
|
||||
```
|
||||
- Feat: /api/<category>/<name> を追加
|
||||
```
|
||||
|
||||
純粋な内部リファクタなら不要。
|
||||
|
||||
## 出力形式
|
||||
|
||||
優先度別に以下のフォーマットで出力する。
|
||||
|
||||
```
|
||||
## 🔴 Critical
|
||||
- packages/backend/src/server/api/endpoints/foo/bar.ts:23
|
||||
meta.errors.fooError.id が UUID v4 形式ではない (実値: 'xxx-xxx')。
|
||||
`node -e "console.log(crypto.randomUUID())"` で再生成すること。
|
||||
|
||||
## 🟡 Major
|
||||
- ...
|
||||
|
||||
## 🔵 Minor
|
||||
- ...
|
||||
```
|
||||
|
||||
問題のないチェック項目には触れない。全項目クリアなら `✅ レビュー観点上の指摘なし` と短く返す。
|
||||
|
||||
## 参照
|
||||
|
||||
- [.claude/skills/add-api-endpoint/SKILL.md](../skills/add-api-endpoint/SKILL.md) — 実装側の規約 (本エージェントの根拠)
|
||||
- [endpoints.ts (meta/paramDef 型定義)](../../packages/backend/src/server/api/endpoints.ts)
|
||||
- [endpoint-list.ts (★ 登録先)](../../packages/backend/src/server/api/endpoint-list.ts)
|
||||
- [endpoint-base.ts (Endpoint 基底クラス)](../../packages/backend/src/server/api/endpoint-base.ts)
|
||||
- [error.ts (ApiError)](../../packages/backend/src/server/api/error.ts)
|
||||
- [test/e2e/endpoints.ts](../../packages/backend/test/e2e/endpoints.ts)
|
||||
- [AGENTS.md](../../AGENTS.md) — SPDX / マイグレーション履歴 / CHANGELOG 書式などの最低限ルール (Codex / Copilot と共通)
|
||||
176
.claude/agents/vue-component-reviewer.md
Normal file
176
.claude/agents/vue-component-reviewer.md
Normal file
@@ -0,0 +1,176 @@
|
||||
---
|
||||
name: vue-component-reviewer
|
||||
description: Misskey フロントエンド (packages/frontend/src/components/ / pages/) の Vue 3 SFC 変更を専門レビューする。SPDX (HTML コメント) / Mk* 命名 / <script lang="ts" setup> / type-only defineProps / <style lang="scss" module> / CSS 変数 / i18n.ts と i18n.tsx の使い分け / os.* 経由 / a11y / Storybook (*.stories.impl.ts) を機械的にチェック。フロントエンドの .vue 変更を含む PR レビューで呼び出す。
|
||||
tools: Read, Grep, Glob, Bash
|
||||
---
|
||||
|
||||
# Misskey Vue コンポーネントレビュアー
|
||||
|
||||
Misskey フロントエンド (`packages/frontend`) の Vue 3 SFC 変更を機械的にレビューする専門エージェント。規約の根拠は [.claude/skills/add-mk-component/SKILL.md](../skills/add-mk-component/SKILL.md)。
|
||||
|
||||
## 役割
|
||||
|
||||
`packages/frontend/src/components/` および `packages/frontend/src/pages/` 配下の `.vue` 変更を対象に、命名・i18n・スタイル・アクセシビリティ・Storybook 併設の規約逸脱を抽出する。良い点には触れず、改善が必要な箇所のみ報告する。
|
||||
|
||||
## レビュー対象の特定
|
||||
|
||||
呼び出し元から明示的にファイルが渡されたらそれを優先する。渡されなかった場合は **PR / ブランチ全体の差分** を取得する (未コミット差分のみではないことに注意)。
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
{ git diff --name-only "$BASE"...HEAD; git diff --name-only HEAD; git ls-files --others --exclude-standard; } \
|
||||
| sort -u \
|
||||
| grep -E '^packages/frontend/src/.*\.vue$'
|
||||
```
|
||||
|
||||
`origin/develop` が無い環境では `develop` または `master` にフォールバックする。
|
||||
|
||||
`.ts` を一律で含めると本エージェントの守備範囲外 (composable / store / service 層) まで巻き込んで誤検知が増えるため、対象は `.vue` のみとし、Storybook 併設チェックのために以下を **別リスト** として追加する:
|
||||
|
||||
- `locales/*.yml` (とくに `ja-JP.yml` 以外の変更は即 Critical)
|
||||
- `packages/frontend/src/components/**/*.stories.impl.ts`
|
||||
- `CHANGELOG.md`
|
||||
|
||||
差分対象が空なら「レビュー対象の Vue コンポーネント変更なし」と短く報告して終了。
|
||||
|
||||
## チェックリスト
|
||||
|
||||
### 1. SPDX ヘッダー (Critical)
|
||||
|
||||
`.vue` ファイル冒頭は **HTML コメント形式** で必須:
|
||||
|
||||
```html
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
```
|
||||
|
||||
`/* ... */` (TS 形式) は禁止。既存 SFC の慣習・SFC 先頭として自然な形式に統一するため (CI の `spdx` ジョブはコメント形式ではなく SPDX 文字列の有無のみを検査するため、形式が違っても CI は通るが、規約違反として指摘する)。
|
||||
|
||||
### 2. 命名規約 (Major)
|
||||
|
||||
- 共有 / 再利用コンポーネント (`packages/frontend/src/components/` 配下、サブディレクトリ含む) は `Mk` プレフィックス必須 (例: `MkButton.vue`, `global/MkAvatar.vue`, `grid/MkGrid.vue`)。
|
||||
- ページ固有のものは `pages/` 配下に置き、`Mk` プレフィックスは不要。
|
||||
|
||||
> `<script setup>` SFC は named export を持たないため、「ファイル名と export 名の一致」を機械的に検査することはできない。SFC のデフォルトエクスポートはコンパイラ生成なので、ファイル名規約のみを基準にする。
|
||||
|
||||
### 3. `<script>` タグ (Major)
|
||||
|
||||
- `<script lang="ts" setup>` または `<script setup lang="ts">` のどちらでもよい (既存コードは多数派が前者だが、後者も `MkThemePreview.vue` 等で使われている)。属性順は指摘しない。`lang="ts"` が **無い** ものは指摘する。
|
||||
- 型ジェネリックが必要なら `generic="T extends ..."` 属性を加える (順序問わず)。
|
||||
- `defineProps<{ ... }>()` / `defineEmits<{ ... }>()` は **type-only** 形式。runtime の object 形式 (`defineProps({ ... })`) は使わない。
|
||||
- Options API (`export default { data() { ... } }`) は禁止。
|
||||
|
||||
### 4. i18n の使い分け (Critical)
|
||||
|
||||
- 文字列リテラルの直書き禁止 (テンプレート / JS 両方)。
|
||||
- 引数なし: `i18n.ts.<path>` (例: `i18n.ts.deleted`)。
|
||||
- 引数あり: `i18n.tsx.<path>(...)` (関数呼び出し、例: `i18n.tsx.takeOverConfirm({ name })`)。
|
||||
- 新規 i18n キーは `locales/ja-JP.yml` **のみ** に追加。
|
||||
- **`locales/ja-JP.yml` 以外の `.yml` 変更があれば即 Critical** (`en-US.yml` 等は Crowdin 自動配信先で、手動編集すると上書き喪失する)。
|
||||
|
||||
差分検出:
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
git diff --name-only "$BASE"...HEAD -- 'locales/*.yml' | grep -v 'ja-JP.yml'
|
||||
```
|
||||
|
||||
### 5. スタイル (Major)
|
||||
|
||||
- `<style lang="scss" module>` を既定とし、`:class="$style.foo"` で参照する。
|
||||
- 新規で `<style scoped>` (module なし) は使わない (legacy)。
|
||||
- **CSS 変数の使用必須** (色・余白・角丸など):
|
||||
- テーマ色: `var(--MI_THEME-*)` (例: `var(--MI_THEME-panel)`)
|
||||
- UI 共通: `var(--MI-*)` (例: `var(--MI-radius)`)
|
||||
- 直接の `#fff` / `rgb(...)` / `rgba(...)` ハードコードは禁止
|
||||
|
||||
ハードコード検出:
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
git diff "$BASE"...HEAD -- 'packages/frontend/src/**/*.vue' \
|
||||
| grep -E '^\+' | grep -E '#[0-9a-fA-F]{3,8}\b|rgba?\('
|
||||
```
|
||||
|
||||
### 6. UI 操作は `os.*` 経由 (Critical)
|
||||
|
||||
- 直接の `alert()` / `confirm()` / `window.prompt()` / `window.alert()` は禁止。
|
||||
- `os.alert` / `os.confirm` / `os.popup` / `os.toast` / `os.popupMenu` / `os.contextMenu` / `os.form` / `os.apiWithDialog` を使う ([os.ts](../../packages/frontend/src/os.ts) 参照)。
|
||||
|
||||
検出:
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
git diff "$BASE"...HEAD -- 'packages/frontend/src/**/*.vue' \
|
||||
| grep -E '^\+' | grep -E '\b(alert|confirm|prompt)\s*\('
|
||||
```
|
||||
|
||||
### 7. アクセシビリティ (Major)
|
||||
|
||||
- クリック可能要素は `<button>` か、`role="button"` + `tabindex="0"` + キーボードハンドラ (`@keydown.enter` 等) を実装する。
|
||||
- 装飾以外の `<div @click>` で a11y 配慮がないものは指摘する。
|
||||
- フォーム要素には対応する `<label>` または `aria-label` を付ける。
|
||||
- `:disabled` バインドや `aria-disabled` の整合性を確認する。
|
||||
|
||||
### 8. Storybook 併設 (Major)
|
||||
|
||||
- 共有 `Mk*` コンポーネントを新規追加した場合、`Mk<Name>.stories.impl.ts` が同階層に併設されているか (サブディレクトリ含む。例: `components/global/MkAvatar.stories.impl.ts`, `components/grid/MkGrid.stories.impl.ts`)。
|
||||
- **ファイル名は `.stories.impl.ts` 固定** (`.stories.ts` は誤り)。
|
||||
- 既存 [MkButton.stories.impl.ts](../../packages/frontend/src/components/MkButton.stories.impl.ts) を雛形例として参照する。
|
||||
|
||||
検出 (新規追加された `Mk*.vue` をサブディレクトリ含めて拾う):
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
git diff --name-only --diff-filter=A "$BASE"...HEAD -- \
|
||||
'packages/frontend/src/components/**/Mk*.vue' \
|
||||
| sed 's/\.vue$/.stories.impl.ts/' \
|
||||
| xargs -I {} sh -c 'test -f {} || echo "missing: {}"'
|
||||
```
|
||||
|
||||
### 9. アイコン (Minor)
|
||||
|
||||
- アイコンは Tabler icons クラス (`<i class="ti ti-info-circle">` 等) を使う。
|
||||
- インライン SVG や別アイコンセットは原則使わない (既存パターンに合わせる)。
|
||||
|
||||
### 10. CHANGELOG エントリ (Minor)
|
||||
|
||||
ユーザー影響がある変更なら、`CHANGELOG.md` の `## Unreleased` → `### Client` に 1 行追加されているか確認する。
|
||||
|
||||
```
|
||||
- Enhance: <component> の <挙動> を改善
|
||||
- Fix: <component> の <不具合> を修正
|
||||
```
|
||||
|
||||
純粋な内部リファクタなら不要。
|
||||
|
||||
## 出力形式
|
||||
|
||||
優先度別に以下のフォーマットで出力する。
|
||||
|
||||
```
|
||||
## 🔴 Critical
|
||||
- packages/frontend/src/components/MkFoo.vue:1
|
||||
SPDX ヘッダーが HTML コメント形式ではなく TS 形式になっている。
|
||||
`<!-- ... -->` で書き直すこと。
|
||||
|
||||
## 🟡 Major
|
||||
- ...
|
||||
|
||||
## 🔵 Minor
|
||||
- ...
|
||||
```
|
||||
|
||||
問題のないチェック項目には触れない。全項目クリアなら `✅ レビュー観点上の指摘なし` と短く返す。
|
||||
|
||||
## 参照
|
||||
|
||||
- [.claude/skills/add-mk-component/SKILL.md](../skills/add-mk-component/SKILL.md) — 実装側の規約 (本エージェントの根拠)
|
||||
- [.claude/skills/add-i18n-key/SKILL.md](../skills/add-i18n-key/SKILL.md) — i18n キー追加のルール
|
||||
- [os.ts](../../packages/frontend/src/os.ts) — UI 操作 API
|
||||
- [MkButton.vue](../../packages/frontend/src/components/MkButton.vue)
|
||||
- [MkInput.vue](../../packages/frontend/src/components/MkInput.vue) — generic SFC 例
|
||||
- [MkButton.stories.impl.ts](../../packages/frontend/src/components/MkButton.stories.impl.ts) — Storybook 雛形
|
||||
- [AGENTS.md](../../AGENTS.md) — SPDX / locales 編集制限 / CHANGELOG 書式などの最低限ルール (Codex / Copilot と共通)
|
||||
38
.claude/commands/README.md
Normal file
38
.claude/commands/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# `.claude/commands/` — プロジェクト固有のスラッシュコマンド
|
||||
|
||||
Misskey 開発で繰り返し使うワークフローを `/command-name` で呼び出せるよう、`.claude/commands/<name>.md` 形式で配置している。
|
||||
|
||||
## 実装済みコマンド
|
||||
|
||||
### Misskey オリジナル
|
||||
|
||||
| コマンド | 用途 | 典型ユースケース |
|
||||
| --- | --- | --- |
|
||||
| [`/check-misskey-js`](./check-misskey-js.md) | `pnpm build-misskey-js-with-types` を走らせ、`packages/misskey-js/src/autogen/` の差分を報告 | backend の API endpoint を追加・変更した直後 |
|
||||
| [`/changelog-add`](./changelog-add.md) | `CHANGELOG.md` の `## Unreleased` 配下、対応するサブセクションに 1 行追記 | ユーザー影響のある変更をコミットする直前 |
|
||||
| [`/migrate-new`](./migrate-new.md) | TypeORM `migration:create` の薄いラッパー (拡張子変換 + SPDX 付与 + `check-migrations` で pending DDL 検出) | 手書き SQL / データ移行用に空雛形が欲しい時 |
|
||||
|
||||
### ECC ([everything-claude-code](https://github.com/affaan-m/everything-claude-code)) 由来 (MIT)
|
||||
|
||||
ECC の MIT ライセンスファイルを Misskey の規約に合わせて再構成したもの。出典は [.claude/THIRD_PARTY_LICENSES.md](../THIRD_PARTY_LICENSES.md) を参照。
|
||||
|
||||
| コマンド | 用途 | 典型ユースケース |
|
||||
| --- | --- | --- |
|
||||
| [`/quality-gate`](./quality-gate.md) | `pnpm lint` + 各パッケージの unit test を順次実行する軽量品質ゲート | 完了前の軽量チェック (重い E2E は CI 側に委譲) |
|
||||
| [`/harness-audit`](./harness-audit.md) | `.claude/` ハーネスを 7 カテゴリで採点し改善優先度を提示 | 設定の点検 / 新しい skill / agent / hook を入れた後 |
|
||||
|
||||
## 使い分け
|
||||
|
||||
- **`/migrate-new` vs [`create-migration` skill](../skills/create-migration/SKILL.md)**:
|
||||
- 雛形だけ素早く欲しい → `/migrate-new`
|
||||
- エンティティ差分から自動生成、または CONCURRENTLY などの注意点を含めて完全に誘導してほしい → `create-migration` skill (`migration:generate`)
|
||||
- **`/changelog-add` vs 手動編集**:
|
||||
- サブセクションの placeholder `-` 置換や、過去リリースセクションへの誤編集を避けるため、原則コマンドを使う。
|
||||
- **`/quality-gate` のスコープ**:
|
||||
- 編集途中の軽量チェック (lint + unit test) は `/quality-gate` で十分。重い e2e / federation / Cypress は CI 側で実行されるため、ローカルでは原則回さない。
|
||||
|
||||
## 新規追加時の方針
|
||||
|
||||
- 既存の `superpowers` / `pr-review-toolkit` などのプラグイン提供スラッシュコマンドで足りる場合は新規追加しない。
|
||||
- frontmatter には最低限 `description` を指定し、引数を取るなら `argument-hint`、可能なら `allowed-tools` も指定する (permission prompt を最小化するため)。
|
||||
- 長時間ビルド (2 分超) を伴うコマンドはインライン `` !`<cmd>` `` を使わず、本文で `Bash` ツール呼び出し時の `timeout` を指示する。
|
||||
49
.claude/commands/changelog-add.md
Normal file
49
.claude/commands/changelog-add.md
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
description: CHANGELOG.md の Unreleased セクションに 1 行追記する
|
||||
argument-hint: <general|client|server> <Prefix>: <description>
|
||||
allowed-tools: Bash(awk:*), Bash(git diff:*), Read, Edit
|
||||
---
|
||||
|
||||
## 引数
|
||||
|
||||
引数: `$ARGUMENTS`
|
||||
|
||||
## 現在の Unreleased セクション
|
||||
|
||||
!`awk '/^## Unreleased/,/^## [0-9]/' CHANGELOG.md`
|
||||
|
||||
## タスク
|
||||
|
||||
1. **引数の解析**
|
||||
`$ARGUMENTS` を以下の形式として解釈する:
|
||||
- 第 1 トークン: scope = `general` / `client` / `server` のいずれか (case-insensitive)
|
||||
- 残り: エントリ本文。`Enhance:` / `Fix:` / `Feat:` のいずれかで始まる前提
|
||||
- 不正な scope や、Prefix が見当たらない場合はエラー終了し、ユーザーに `argument-hint` の書式を提示する
|
||||
|
||||
scope は次のように見出しに変換する: `general` → `### General` / `client` → `### Client` / `server` → `### Server`。
|
||||
|
||||
2. **対象サブセクションの状態判定**
|
||||
上の context (現在の Unreleased セクション) を見て、対象サブセクションが以下のどちらかを判定する:
|
||||
- **空 (placeholder のみ)**: 見出し直下に `-` 単独行のみがある状態
|
||||
- **既存エントリあり**: `- Enhance: ...` / `- Fix: ...` / `- Feat: ...` の行が 1 つ以上ある状態
|
||||
|
||||
3. **CHANGELOG.md の編集**
|
||||
`Read` で CHANGELOG.md 全体を確認した後、`Edit` ツールで以下のように更新する:
|
||||
|
||||
- **空の場合**: 該当サブセクションの placeholder `-` 行を `- <整形済みエントリ>` で置換する。例: `### General\n-\n` → `### General\n- Enhance: 新しい機能\n`
|
||||
- **既存ありの場合**: 既存エントリ群の **末尾** (次の空行直前) に新エントリを **append** する。順序入れ替えはしない。
|
||||
|
||||
`Edit` の `old_string` には、置換対象のサブセクション付近のユニークな文脈 (見出し + 直後の数行) を含め、誤マッチを防ぐ。
|
||||
|
||||
4. **不可侵の徹底**
|
||||
- `## Unreleased` 以下の対象サブセクションのみ編集する。
|
||||
- `## 2026.x.x` 以下の過去リリースセクションは絶対に変更しない ([AGENTS.md §CHANGELOG](../../AGENTS.md#changelog) 参照)。
|
||||
|
||||
5. **結果確認**
|
||||
`git diff CHANGELOG.md` を実行し、想定通り 1 行のみ追加されていることを表示して、ユーザーに確認させる。
|
||||
|
||||
## 例
|
||||
|
||||
- `/changelog-add server Fix: 通知が遅延する問題を修正` → `### Server` 末尾に追記
|
||||
- `/changelog-add client Enhance: ノートの表示を改善` → `### Client` 末尾に追記
|
||||
- `/changelog-add general Feat: 新機能の追加` → `### General` 末尾に追記 (placeholder 置換)
|
||||
42
.claude/commands/check-misskey-js.md
Normal file
42
.claude/commands/check-misskey-js.md
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
description: backend の API 変更後に misskey-js を再生成し、生成物の差分を報告する
|
||||
allowed-tools: Bash(pnpm build-misskey-js-with-types:*), Bash(git status:*), Bash(git diff:*), Bash(git branch:*)
|
||||
---
|
||||
|
||||
## 概要
|
||||
|
||||
backend の API endpoint やスキーマを変更した後、`packages/misskey-js/src/autogen/` の自動生成型を最新化するためのコマンド。内部で `pnpm build-misskey-js-with-types` (backend build → `api.json` 生成 → misskey-js 型生成 → ビルド → API extractor) を一括実行する。
|
||||
|
||||
## 現在の状態 (再生成前)
|
||||
|
||||
- 現ブランチ: !`git branch --show-current`
|
||||
- 既存の misskey-js 関連変更: !`git status --short -- packages/misskey-js/`
|
||||
|
||||
## タスク
|
||||
|
||||
以下の手順を順番に実行してください。
|
||||
|
||||
1. **再生成の実行**
|
||||
`Bash` ツールで以下のコマンドを `timeout: 600000` (10 分) を指定して実行する。内部で backend ビルドと型再生成を行うため、デフォルトの 2 分タイムアウトでは不足する。
|
||||
|
||||
```bash
|
||||
pnpm build-misskey-js-with-types
|
||||
```
|
||||
|
||||
2. **差分の確認**
|
||||
完了後、以下を実行して `packages/misskey-js/src/autogen/` の差分を確認する (`built/` は `.gitignore` 対象なので追跡対象外):
|
||||
|
||||
```bash
|
||||
git status --short -- packages/misskey-js/
|
||||
git diff --stat -- packages/misskey-js/src/autogen/
|
||||
```
|
||||
|
||||
3. **結果報告**
|
||||
- **差分なし** → 「backend の変更は misskey-js の公開型に影響していません」と報告する。追加コミットは不要。
|
||||
- **差分あり** → 変更ファイル一覧をユーザーに示し、`git add packages/misskey-js/src/autogen/` で再生成物もコミット対象に含めるよう案内する。`api.json` の差分が大きい場合は、API endpoint 側の `meta` / `paramDef` / `res` 定義を確認するよう促す。
|
||||
|
||||
## 注意
|
||||
|
||||
- このコマンドは **backend 編集後の確認** が目的。backend を変更していないのに走らせると、ビルドキャッシュ次第で no-op になる。
|
||||
- 実行中は `packages/backend/built/` や `packages/misskey-js/built/` などの中間生成物が更新されるが、これらは `.gitignore` 対象。
|
||||
- 生成物以外 (`packages/misskey-js/src/` のうち `autogen/` 以外) に予期せぬ差分が出た場合は、ローカルの編集が混入している可能性があるため、一旦中止して原因を調査する。
|
||||
146
.claude/commands/harness-audit.md
Normal file
146
.claude/commands/harness-audit.md
Normal file
@@ -0,0 +1,146 @@
|
||||
---
|
||||
description: Misskey の .claude/ ハーネス (skills/agents/commands) を 7 カテゴリで採点する確定的な監査。
|
||||
argument-hint: "[repo|skills|commands|agents]"
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: MIT
|
||||
SPDX-FileCopyrightText: 2026 Affaan Mustafa and everything-claude-code contributors
|
||||
|
||||
出典 (upstream): https://github.com/affaan-m/everything-claude-code (v2.0.0-rc.1)
|
||||
upstream path: commands/harness-audit.md
|
||||
upstream license: MIT — https://github.com/affaan-m/everything-claude-code/blob/main/LICENSE
|
||||
project-level notice: see .claude/THIRD_PARTY_LICENSES.md (Misskey 内サードパーティ一覧 + MIT 全文)
|
||||
|
||||
Imported into Misskey .claude/ on 2026-05-10. The 7-category rubric and output contract are derived from the upstream ECC version (MIT). The runtime layer was substantially reimplemented for Misskey: the upstream relies on scripts/harness-audit.js to mechanically score, while this version asks Claude to score directly with pnpm/git/grep, and adds Misskey-specific evaluation axes (SPDX coverage / endpoint-list 登録漏れ / migration 順序 / ja-JP.yml 整合).
|
||||
|
||||
note: 元 ECC 版は scripts/harness-audit.js (専用 Node スクリプト) で機械採点していたが、Misskey は ECC plugin runtime に依存しない方針なので、Claude が直接ファイルを読んで採点する手動運用版に書き換えた。Misskey 固有の重要観点 (SPDX 適用率 / endpoint-list 登録漏れ / migration 順序 / ja-JP.yml 整合) を評価軸として明示的に組み込んでいる。
|
||||
-->
|
||||
|
||||
# /harness-audit — Misskey ハーネス監査
|
||||
|
||||
Misskey リポジトリの `.claude/` 構成を 7 カテゴリで採点し、改善優先度を提示する。
|
||||
|
||||
## Usage
|
||||
|
||||
`/harness-audit [scope]`
|
||||
|
||||
- `scope` (任意): `repo` (default) / `skills` / `commands` / `agents`
|
||||
|
||||
## 評価カテゴリ (各 0-10)
|
||||
|
||||
| # | カテゴリ | 評価軸 |
|
||||
| --- | --- | --- |
|
||||
| 1 | Tool Coverage | skill / agent / command の数、欠けているワークフロー段、重複なし |
|
||||
| 2 | Context Efficiency | frontmatter description の冗長度、SKILL.md の長さ分布、重複情報、CLAUDE.md の肥大化 |
|
||||
| 3 | Quality Gates | Stop / PreToolUse / PostToolUse hook の整備、`/quality-gate` 等の完了前ゲートの有無、自動 lint/typecheck |
|
||||
| 4 | Memory Persistence | docs/* の同期状態を評価。プロジェクト側 `.claude/memory/` は未採用方針 (auto-memory はユーザーホーム側で自動運用) のため、ここを採点起点にせず既定 5/10 から開始する |
|
||||
| 5 | Eval Coverage | testing.md の網羅、Misskey 固有の e2e/fed/Storybook/Cypress 適用ガイド |
|
||||
| 6 | Security Guardrails | SPDX 規約適用、migration 不変性ルール、ja-JP.yml 限定編集ルール、secrets 検出 |
|
||||
| 7 | Cost Efficiency | enabledPlugins の重複・過剰、context-budget の整備、MCP 過剰登録なし |
|
||||
|
||||
## Misskey 固有の確認項目 (採点根拠コマンド)
|
||||
|
||||
採点時に以下を実コマンドで確認する。各項目の **属するカテゴリ** は項目内に明記する (#1-#3 は Security Guardrails、#4 は Tool Coverage、#5 は Quality Gates):
|
||||
|
||||
```bash
|
||||
# 1. [Security Guardrails] SPDX 適用率 (新規ファイル想定の汎用チェック)
|
||||
# - node_modules を prune で除外
|
||||
# - packages/misskey-js は MIT サブパッケージなので AGPL ヘッダーを持たない (AGENTS.md §1) → 除外
|
||||
# - built/ なども除外
|
||||
# 候補にはなお *.config.{ts,js} / *eslint* / *.d.ts のような CI 上 SPDX 対象外
|
||||
# (.github/workflows/check-spdx-license-id.yml の exclude 参照) も混ざるため、
|
||||
# 上位に出たファイルが「新規追加した実コード」かどうかは目視判定する。
|
||||
find packages \
|
||||
\( -type d \( -name node_modules -o -name built -o -name dist -o -path 'packages/misskey-js' \) -prune \) \
|
||||
-o -type f \( -name '*.ts' -o -name '*.js' -o -name '*.vue' -o -name '*.scss' \) -print \
|
||||
| xargs -r grep -L 'SPDX-License-Identifier: AGPL-3.0-only' | head -20
|
||||
# → 上位に新規実コードが無ければ満点
|
||||
|
||||
# 2. [Security Guardrails] ja-JP.yml 以外の locales が直近で手動編集されていないか
|
||||
# --pretty=format: でコミットヘッダ行を抑止し、ファイル名行のみを残してから grep する。
|
||||
# Crowdin の自動同期 commit でも他言語 yml は更新されるため、出力が 0 行になることは少ない。
|
||||
# 出力があった場合は、author / commit message を確認し Crowdin 由来か手動編集かを判定する:
|
||||
# git log --since='30 days ago' --pretty=format:'%h %an %s' -- locales/<file>.yml
|
||||
git log --since='30 days ago' --pretty=format: --name-only -- 'locales/*.yml' \
|
||||
| grep -v '^$' | grep -v 'ja-JP.yml' | sort -u
|
||||
# → 出力が無い、または全て Crowdin 由来 commit なら満点
|
||||
|
||||
# 3. [Security Guardrails] migration の pending DDL 検査 (TypeORM schema builder)
|
||||
pnpm --filter backend check-migrations
|
||||
# → 0 errors (= "All migrations are clean.") なら満点
|
||||
|
||||
# 4. [Tool Coverage] endpoint-list.ts 登録漏れ (新規 endpoint がリストにない場合)
|
||||
# endpoints/ は再帰構造 (notes/create.ts, admin/announcements/create.ts 等) で 400+ ファイルあるため、
|
||||
# endpoint-list.ts も `export * as '<category>/<name>' from './endpoints/<category>/<name>.js';` 形式で
|
||||
# 1 ファイル 1 行登録される。両者の行数を「再帰 .ts 数」と「export * as 行数」で比較する。
|
||||
# e2e / 単体テストは endpoint ではないので *.test.ts を除外する。
|
||||
endpoint_files=$(find packages/backend/src/server/api/endpoints -type f -name '*.ts' ! -name '*.test.ts' | wc -l)
|
||||
list_entries=$(grep -cE "^export \* as " packages/backend/src/server/api/endpoint-list.ts)
|
||||
echo "endpoints (recursive): $endpoint_files / endpoint-list.ts entries: $list_entries"
|
||||
# 差分が 0 なら満点。差分が出たら、登録漏れの具体特定:
|
||||
comm -23 \
|
||||
<(find packages/backend/src/server/api/endpoints -type f -name '*.ts' ! -name '*.test.ts' \
|
||||
| sed -E 's|.*/endpoints/||;s|\.ts$||' | sort -u) \
|
||||
<(grep -oE "^export \* as '[^']+'" packages/backend/src/server/api/endpoint-list.ts \
|
||||
| sed -E "s/^export \* as '([^']+)'/\1/" | sort -u)
|
||||
# 出力された行が登録漏れの endpoint。0 行なら満点。
|
||||
|
||||
# 5. [Quality Gates] console.log の混入
|
||||
grep -rn 'console\.\(log\|debug\)' packages/backend/src packages/frontend/src 2>/dev/null \
|
||||
| grep -v 'node_modules\|test\|.spec\.\|.test\.' | wc -l
|
||||
# → 0 が理想
|
||||
```
|
||||
|
||||
## 出力契約
|
||||
|
||||
以下を返す:
|
||||
|
||||
1. `overall_score` / `max_score` (repo は 70 点満点)
|
||||
2. カテゴリごとのスコア + 具体的な根拠
|
||||
3. 失敗チェック項目と該当ファイルパス
|
||||
4. Top 3 改善アクション
|
||||
5. 次に適用を推奨する skill / 手順
|
||||
|
||||
## サンプル出力
|
||||
|
||||
```text
|
||||
Harness Audit (repo): 55/70
|
||||
|
||||
Tool Coverage: 9/10 (skills 5, agents 2, commands 5 — 偏りなし)
|
||||
Context Efficiency: 8/10 (description 平均 3-5 行、肥大なし)
|
||||
Quality Gates: 5/10 (Stop hook 共有設定に未登録 / `/quality-gate` あり)
|
||||
Memory Persistence: 5/10 (プロジェクト側 memory/ 未採用方針 = 既定値)
|
||||
Eval Coverage: 7/10 (testing.md 網羅、Storybook 一部抜け)
|
||||
Security Guardrails: 10/10 (SPDX 100%, locales OK, migrations clean)
|
||||
Cost Efficiency: 8/10 (context-budget 導入済 / MCP 0)
|
||||
|
||||
Failed Checks:
|
||||
- packages/frontend/src/.../X.vue で SPDX 欠落 (Security Guardrails)
|
||||
- console.log が backend に 3 件 (Quality Gates)
|
||||
- 共有 Stop hook なし (Quality Gates) — 各 contributor が `.claude/settings.local.json` で opt-in する方針なら減点しなくて良い
|
||||
|
||||
Top 3 Actions:
|
||||
1) [Security Guardrails] SPDX 欠落 1 ファイルを修正:
|
||||
packages/frontend/src/.../X.vue
|
||||
2) [Quality Gates] backend の console.log 3 件を logger に置換。
|
||||
git grep "console\.log" packages/backend/src
|
||||
3) [Cost Efficiency] enabledPlugins から未使用のものを外す。
|
||||
.claude/docs/plugins.md と照合。
|
||||
|
||||
Suggested next skills to apply:
|
||||
- /quality-gate で完了前に lint + unit test を回す
|
||||
- context-budget で plugin 由来の overhead を確認
|
||||
```
|
||||
|
||||
## 採点の信頼性
|
||||
|
||||
- 確定的: 同じ commit / 同じ `.claude/` 構成なら同じスコア
|
||||
- ヒューリスティクス: 「description の冗長度」のような主観項目は同一基準で機械的に判定
|
||||
- スクリプト不要: `pnpm` と `git`、`grep`/`find` 等の標準ツールのみ
|
||||
|
||||
## 参考: ECC オリジナルとの差分
|
||||
|
||||
- ECC 版は `node scripts/harness-audit.js` を直叩きする運用で、ECC リポジトリ全体に閉じた採点だった。
|
||||
- Misskey 版は **Misskey の規約 (SPDX/migration/locales/endpoint-list)** を Security 採点に組み込み、`pnpm` ベースの実コマンドで根拠を取る方式に再設計。
|
||||
- 結果として ECC への依存はゼロ。
|
||||
81
.claude/commands/migrate-new.md
Normal file
81
.claude/commands/migrate-new.md
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
description: TypeORM migration の空雛形を生成する。スキーマ差分から自動生成したい時は create-migration skill を使うこと
|
||||
argument-hint: <PascalCaseName>
|
||||
allowed-tools: Bash(pnpm:*), Bash(ls:*), Bash(test:*), Bash(head:*), Read, Edit
|
||||
---
|
||||
|
||||
## 引数
|
||||
|
||||
引数: `$ARGUMENTS`
|
||||
|
||||
## タスク
|
||||
|
||||
1. **PascalCaseName の検証**
|
||||
`$ARGUMENTS` が `^[A-Z][A-Za-z0-9]+$` に一致するか確認する。一致しない場合はエラー終了し、`AddFooBar` / `BirthdayIndex` のような形式を案内する。
|
||||
|
||||
2. **既存ファイルの存在確認**
|
||||
|
||||
```bash
|
||||
ls packages/backend/migration/*$ARGUMENTS.{js,ts} 2>/dev/null
|
||||
```
|
||||
|
||||
既に同名 (タイムスタンプ違い) のファイルが存在する場合、上書きせずユーザーに別名を促す。
|
||||
|
||||
3. **TypeORM 公式 CLI で空雛形を生成 (`-o --esm` 必須)**
|
||||
`create-migration` skill の方針に従い、`Date.now()` を手書きするのではなく TypeORM CLI を使う。`-o --esm` で **最初から JS(ESM) を生成** させ、後続の `.ts → .js` 変換や `import { MigrationInterface }` 削除といった TS 固有構文の除去を不要にする (`-o --esm` を付けないと `.ts` + CommonJS / `implements MigrationInterface` 付きで生成され、Misskey の `ormconfig.js` (`migration/*.js` のみロード) と既存 migration スタイルに合わない):
|
||||
|
||||
```bash
|
||||
pnpm --filter backend exec typeorm migration:create -o --esm migration/$ARGUMENTS
|
||||
```
|
||||
|
||||
出力: `packages/backend/migration/<UnixMs>-<PascalCaseName>.js`
|
||||
|
||||
4. **生成ファイルパスの取得**
|
||||
後続ステップで使うパスを変数に受ける (`<ms>` を手書きしない):
|
||||
|
||||
```bash
|
||||
dst=$(ls -t packages/backend/migration/*$ARGUMENTS.js | head -1)
|
||||
```
|
||||
|
||||
以降のステップでは `$dst` を編集対象として扱う。完成後の典型的な形は次のようになる (参考: [packages/backend/migration/1767169026317-birthday-index.js](../../packages/backend/migration/1767169026317-birthday-index.js)):
|
||||
|
||||
```js
|
||||
export class <PascalCaseName><ms> {
|
||||
name = '<PascalCaseName><ms>'
|
||||
|
||||
async up(queryRunner) {
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
5. **SPDX ヘッダーの追加**
|
||||
`Edit` ツールで、ファイル冒頭に以下を挿入する。CI の `spdx` ジョブが失敗するため必須:
|
||||
|
||||
```js
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
```
|
||||
|
||||
6. **migration の pending DDL 検査**
|
||||
|
||||
```bash
|
||||
pnpm --filter backend check-migrations
|
||||
```
|
||||
|
||||
TypeORM schema builder で pending DDL を検出する検査 ([scripts/check_migrations_clean.js](../../packages/backend/scripts/check_migrations_clean.js))。空雛形を作っただけの段階ではエンティティ差分との不整合が残る場合があるため、`up`/`down` を埋めた後にも再実行して 0 件になるか確認する。
|
||||
|
||||
7. **結果報告**
|
||||
- 生成ファイルパスを示す。
|
||||
- `up()` / `down()` の中身が空であることを伝え、SQL を書く必要があると案内する。
|
||||
- `down()` を空のまま放置すると本番ロールバック時に詰むため、必ず `up` の完全な巻き戻しを実装するよう促す。
|
||||
- 詳細な手順 (`migration:generate` を使うべきケース、CONCURRENTLY などの注意点) は `create-migration` skill を参照するよう案内する。
|
||||
|
||||
## 注意
|
||||
|
||||
- このコマンドは **空雛形を素早く出して手書きする** 用途。エンティティ (`packages/backend/src/models/*.ts`) を変更した差分から SQL を自動生成したい場合は、このコマンドではなく `create-migration` skill 経由で `migration:generate` を使うこと。
|
||||
- マージ済み migration ファイルは絶対に編集しない ([AGENTS.md §3](../../AGENTS.md#3-マージ済み-migration-を絶対に編集しない))。
|
||||
122
.claude/commands/quality-gate.md
Normal file
122
.claude/commands/quality-gate.md
Normal file
@@ -0,0 +1,122 @@
|
||||
---
|
||||
description: Misskey の lint / typecheck / 高速テストを順に実行して品質ゲートを通すコマンド。完了前の軽量検証用。
|
||||
argument-hint: "[repo|backend|frontend|<path/to/file.ts>]"
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: MIT
|
||||
SPDX-FileCopyrightText: 2026 Affaan Mustafa and everything-claude-code contributors
|
||||
|
||||
出典 (upstream): https://github.com/affaan-m/everything-claude-code (v2.0.0-rc.1)
|
||||
upstream path: commands/quality-gate.md
|
||||
upstream license: MIT — https://github.com/affaan-m/everything-claude-code/blob/main/LICENSE
|
||||
project-level notice: see .claude/THIRD_PARTY_LICENSES.md (Misskey 内サードパーティ一覧 + MIT 全文)
|
||||
|
||||
Imported into Misskey .claude/ on 2026-05-10. Pipeline 概念 (lint → typecheck → test) は upstream ECC 版から借用 (MIT)。実コマンド層は Misskey の pnpm + tsgo + ESLint + Vitest に固定し、formatter (Prettier/Biome) フェーズは削除した。
|
||||
|
||||
note: 元 ECC 版は言語自動判定 + format/lint/type のジェネリック版だったが、Misskey 専用に pnpm + tsgo + ESLint + Vitest の組み合わせに固定。重い test:e2e / test:fed は含まない (CI 側で実行される)。
|
||||
-->
|
||||
|
||||
# /quality-gate — Misskey 軽量品質ゲート
|
||||
|
||||
`/quality-gate [scope]`
|
||||
|
||||
完了前の **軽量** 品質チェック。重い E2E / 連合テスト (test:e2e / test:fed / Cypress) は CI 側で実行されるため、本コマンドには含めない。
|
||||
|
||||
## Scope
|
||||
|
||||
- `repo` (default) — 全パッケージ
|
||||
- `backend` — `packages/backend` のみ
|
||||
- `frontend` — `packages/frontend` のみ
|
||||
- `path/to/file.ts` — 単一ファイルへの ESLint --fix のみ
|
||||
|
||||
## Pipeline
|
||||
|
||||
### Repo scope (全部)
|
||||
|
||||
各パッケージの `lint` スクリプト実体は `pnpm typecheck && pnpm eslint` ([packages/backend/package.json](../../packages/backend/package.json), [packages/frontend/package.json](../../packages/frontend/package.json)) で、ルートの `pnpm lint` は `pnpm --no-bail -r lint` (= 全パッケージで lint を `--no-bail` で実行)。**typecheck は lint に含まれている**ため、通常はこの 2 コマンドで十分:
|
||||
|
||||
```bash
|
||||
# 1. Lint (= typecheck + ESLint、全パッケージ。--no-bail で最初の失敗で止まらず全結果を集める)
|
||||
pnpm lint
|
||||
|
||||
# 2. Unit test (高速、e2e は含まない)
|
||||
pnpm --filter backend test
|
||||
pnpm --filter frontend test
|
||||
```
|
||||
|
||||
#### 詳細を分けて見たい時のみ (optional)
|
||||
|
||||
lint がまとめて失敗していて typecheck の結果だけ単独で見たい場合は、以下を個別に回す。**通常は不要** (lint の出力を読めば足りる):
|
||||
|
||||
```bash
|
||||
pnpm --filter backend typecheck # tsgo 単体
|
||||
pnpm --filter frontend typecheck # vue-tsc 単体 (Vue SFC の型を見るため)
|
||||
```
|
||||
|
||||
### Backend scope
|
||||
|
||||
`pnpm --filter backend lint` は内部で `pnpm typecheck && pnpm eslint` を実行する ([packages/backend/package.json](../../packages/backend/package.json)) ので、`lint` を回せば typecheck も終わる。軽量ゲートでは typecheck の二重実行を避けるため `lint` + `test` のみ:
|
||||
|
||||
```bash
|
||||
pnpm --filter backend lint
|
||||
pnpm --filter backend test
|
||||
```
|
||||
|
||||
`tsgo` の出力を単独で見たい時のみ optional で `pnpm --filter backend typecheck` を別途回す。
|
||||
|
||||
### Frontend scope
|
||||
|
||||
`pnpm --filter frontend lint` も内部で `pnpm typecheck && pnpm eslint` を実行する ([packages/frontend/package.json](../../packages/frontend/package.json)) ため、軽量ゲートでは Backend 同様に `lint` + `test` のみ:
|
||||
|
||||
```bash
|
||||
pnpm --filter frontend lint
|
||||
pnpm --filter frontend test
|
||||
```
|
||||
|
||||
`vue-tsc` の出力を単独で見たい時のみ optional で `pnpm --filter frontend typecheck` を別途回す。
|
||||
|
||||
### Single file scope
|
||||
|
||||
```bash
|
||||
pnpm exec eslint --fix <path>
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
実行したフェーズの pass/fail と件数を集計する。標準パイプラインは `pnpm lint` (typecheck 内包) と unit test のみなので、デフォルトの出力は以下のようになる:
|
||||
|
||||
```text
|
||||
Quality Gate (repo):
|
||||
|
||||
Lint: PASS (0 errors, 2 warnings)
|
||||
Backend ut: PASS (412/412)
|
||||
Frontend ut: PASS (87/87)
|
||||
|
||||
→ 完了前の軽量チェック OK。重い e2e / 連合テストは CI 側で実行される。
|
||||
```
|
||||
|
||||
`#### 詳細を分けて見たい時のみ (optional)` で個別 typecheck (`pnpm --filter backend typecheck` / `pnpm --filter frontend typecheck`) も回した場合のみ、その結果を追加行として表示する:
|
||||
|
||||
```text
|
||||
Quality Gate (repo):
|
||||
|
||||
Lint: PASS (0 errors, 2 warnings)
|
||||
Backend tc: PASS (0 errors) # optional 実行時のみ
|
||||
Frontend tc: PASS (0 errors) # optional 実行時のみ
|
||||
Backend ut: PASS (412/412)
|
||||
Frontend ut: PASS (87/87)
|
||||
```
|
||||
|
||||
失敗時は最初に落ちたフェーズで停止して詳細を見せる。
|
||||
|
||||
## 関連 skill / コマンド
|
||||
|
||||
- `/check-misskey-js` コマンド — API 変更時の misskey-js 再生成
|
||||
- [AGENTS.md §必須コマンド](../../AGENTS.md#必須コマンド) — pnpm コマンド一覧の正典
|
||||
|
||||
## 元 ECC 版との差分
|
||||
|
||||
- ジェネリックな言語自動判定を排除し、Misskey 固定 pipeline に。
|
||||
- formatter フェーズなし (Misskey は ESLint --fix のみ採用)。
|
||||
- e2e / federation / Cypress は重いため除外し CI 側に委譲。
|
||||
18
.claude/docs/README.md
Normal file
18
.claude/docs/README.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Misskey – Claude Code 補助ドキュメント
|
||||
|
||||
ルート `CLAUDE.md` には書かれていないが、開発時に参照すると便利な情報を分野別にまとめている。**Claude は必要になったタイミングで該当ファイルを Read すれば良い** (auto-load しない)。
|
||||
|
||||
## 索引
|
||||
|
||||
| ファイル | いつ読むか |
|
||||
|---|---|
|
||||
| [architecture.md](./architecture.md) | パッケージ構成・ビルド構造を把握したい時 / 新パッケージを跨ぐ変更を計画する時 |
|
||||
| [backend.md](./backend.md) | `packages/backend` を編集する時 (NestJS / TypeORM / API endpoint / migration) |
|
||||
| [frontend.md](./frontend.md) | `packages/frontend` を編集する時 (Vue 3 / Mk* / i18n / SCSS Modules / `os.ts`) |
|
||||
| [testing.md](./testing.md) | テストを書く・走らせる時 (Vitest 構成、Cypress、Storybook) |
|
||||
| [plugins.md](./plugins.md) | 有効化済の Claude Code プラグインの用途を確認したい時 |
|
||||
|
||||
## 補足: ルール vs ドキュメント
|
||||
|
||||
- 事故直結ルール (SPDX / locales / migration) と必須コマンド・CHANGELOG 書式は、リポジトリルートの [AGENTS.md](../../AGENTS.md) に集約されている。Claude Code は CLAUDE.md からの `@AGENTS.md` で常時コンテキストに乗せる。Codex / Copilot も同じファイルを読む。
|
||||
- `.claude/docs/*.md` (このディレクトリ) は **オンデマンド参照**。Claude が「知っておいた方が良いが常に持つ必要はない」内容をここに置く。
|
||||
47
.claude/docs/architecture.md
Normal file
47
.claude/docs/architecture.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# アーキテクチャ概要
|
||||
|
||||
## モノレポ構成 (pnpm workspaces)
|
||||
|
||||
pnpm workspace の正は [pnpm-workspace.yaml](../../pnpm-workspace.yaml) で、以下 11 パッケージと、`packages/misskey-js` 内の sub-workspace `packages/misskey-js/generator` (型生成用の内部ジェネレータ。直接編集しない) で構成される。`package.json` の `workspaces` 配列も併記しているが、実体は pnpm-workspace.yaml が読まれる:
|
||||
|
||||
| パッケージ | 役割 |
|
||||
|---|---|
|
||||
| `packages/backend` | NestJS 11 + Fastify 5 + TypeORM 0.3 (PostgreSQL) + Redis。HTTP/WebSocket/ActivityPub サーバー本体。 |
|
||||
| `packages/frontend` | Vue 3.5 + Vite。Web クライアント本体。 |
|
||||
| `packages/frontend-embed` | 埋め込み専用ビュー (ノート単体プレビュー等)。 |
|
||||
| `packages/frontend-shared` | frontend と frontend-embed で共有するユーティリティ・コンポーネント。 |
|
||||
| `packages/frontend-builder` | フロントエンドビルド支援 (Vite plugin など)。 |
|
||||
| `packages/sw` | Service Worker。 |
|
||||
| `packages/misskey-js` | JS/TS クライアント SDK (MIT サブパッケージ)。`src/autogen/` 配下のみ backend の OpenAPI から `pnpm build-misskey-js-with-types` で自動生成され、それ以外 (`src/index.ts` / `src/api.ts` 等) は手書き保守する。autogen 配下を直接編集しないこと。 |
|
||||
| `packages/misskey-reversi` | 内蔵リバーシゲームのロジック。 |
|
||||
| `packages/misskey-bubble-game` | 内蔵バブルゲームのロジック。 |
|
||||
| `packages/i18n` | locales 読み込み/型生成のサポート。 |
|
||||
| `packages/icons-subsetter` | アイコンのサブセット化ツール。 |
|
||||
|
||||
その他に `packages/shared` (workspaces には含まれないが共有ファイル置き場) もある。
|
||||
|
||||
## 重要な依存関係
|
||||
|
||||
```
|
||||
frontend ── misskey-js (auto-generated) ── backend (OpenAPI)
|
||||
▲
|
||||
└── frontend-embed, sw も依存
|
||||
```
|
||||
|
||||
- backend の API (meta / paramDef / response) を変更したら **必ず** `pnpm build-misskey-js-with-types` を実行し、misskey-js の生成物を更新する。忘れると CI の `check-misskey-js-autogen` ジョブが落ちる。
|
||||
|
||||
## ビルドツール
|
||||
|
||||
- **Backend**: `rolldown` (Rust 製・Rollup 互換 API のバンドラ) でバンドル。型チェックは `tsgo` (TypeScript native preview)。
|
||||
- **Frontend**: Vite。型チェックは `vue-tsc`。
|
||||
- **Lint**: ESLint 9 (Flat Config) + `@misskey-dev/eslint-plugin`。
|
||||
|
||||
## 国際化
|
||||
|
||||
- `locales/` 直下に 40 言語の YAML (ja-JP.yml + 他 39 言語)。
|
||||
- **`ja-JP.yml` のみ手動編集可** (Crowdin 経由で他言語へ自動配信)。
|
||||
- フロントエンドからの参照は引数なしか引数ありかで使い分ける。詳細は [frontend.md](./frontend.md#国際化-i18n)。
|
||||
|
||||
## ライセンス
|
||||
|
||||
リポジトリ本体は AGPL-3.0-only。**AGPL-3.0-only 管轄かつ SPDX CI 対象ディレクトリ** の新規 `.ts` / `.js` / `.cjs` / `.mjs` / `.vue` / `.scss` / `.html` ファイルには冒頭に SPDX ヘッダー必須。`packages/misskey-js` は MIT サブパッケージなので AGPL ヘッダーを一律に付けない。条件と除外の詳細は [AGENTS.md §1](../../AGENTS.md#1-spdx-ヘッダー必須) 参照。
|
||||
124
.claude/docs/backend.md
Normal file
124
.claude/docs/backend.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# Backend (`packages/backend`) 規約
|
||||
|
||||
NestJS 11 + Fastify 5 + TypeORM 0.3 (PostgreSQL) + Redis。
|
||||
|
||||
## アーキテクチャ
|
||||
|
||||
- **DI コンテナ**: NestJS の `@Injectable()` サービス + Repository (TypeORM) パターン。
|
||||
- **DI トークン**: `@/di-symbols.js` の `DI` から `@Inject(DI.xxx)` で注入。
|
||||
- **ビルド**: `rolldown -c` で `built/` にバンドル。型チェックは `tsgo`。
|
||||
|
||||
## API エンドポイント
|
||||
|
||||
### 配置
|
||||
|
||||
`packages/backend/src/server/api/endpoints/<category>/<name>.ts` (一部はトップ直下)。
|
||||
|
||||
### 三点セット (`endpoints/ping.ts` 参照)
|
||||
|
||||
各エンドポイントファイルは以下の 3 つを export する:
|
||||
|
||||
```ts
|
||||
export const meta = {
|
||||
tags: ['<tag>'],
|
||||
requireCredential: true, // または false (必ず明示)
|
||||
requireModerator: false, // 必要なら true
|
||||
kind: 'read:account', // OAuth scope
|
||||
res: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
properties: { /* ... */ },
|
||||
},
|
||||
errors: {
|
||||
sampleError: {
|
||||
message: 'Sample error message.',
|
||||
code: 'SAMPLE_ERROR',
|
||||
id: 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx', // UUID v4 (`x`=hex, `y`=8/9/a/b)。`crypto.randomUUID()` で生成し、他エンドポイントと重複させない
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: { /* JSON Schema */ },
|
||||
required: [],
|
||||
} as const;
|
||||
|
||||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||
constructor(
|
||||
// @Inject(DI.xxx) private xxxRepository: XxxRepository,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
// 実装。エラーは throw new ApiError(meta.errors.xxx);
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 注意点
|
||||
|
||||
- **公開 API エラーとしてクライアントに返したいものは `throw new ApiError(meta.errors.<key>)` を使う**。`meta.errors` に列挙して `ApiError` でラップしないと misskey-js 側の型に出ず、レスポンスも 500 になる。
|
||||
- 一方で **想定外の例外 (DB 不整合 / 下層サービスの bug 等) は握り潰さず再 throw する**。既存 endpoint も「期待される業務エラーは `ApiError` に変換し、それ以外は `throw err;` で再 throw」の二段構え (例: [`endpoints/i/pin.ts`](../../packages/backend/src/server/api/endpoints/i/pin.ts) の `catch` 節)。生 `throw` を全面禁止すると未知例外が 200 で潰れて debug 困難になる。
|
||||
- `meta.errors.<key>.id` は **UUID** 形式。新規追加時は他エンドポイントと重複しないよう確認する。
|
||||
- `requireCredential` は `true` / `false` を必ず明示する。
|
||||
- 新規エンドポイント追加後は **`pnpm build-misskey-js-with-types`** を実行する (`misskey-js` の自動生成ファイルを更新)。
|
||||
|
||||
### ルート登録
|
||||
|
||||
エンドポイントは **glob 自動収集されない**。新規ファイルを `endpoints/<category>/<name>.ts` に置いただけでは API ルーティングに乗らず、404 になる。`packages/backend/src/server/api/endpoint-list.ts` にアルファベット順で 1 行追加するのが必須:
|
||||
|
||||
```ts
|
||||
export * as '<category>/<name>' from './endpoints/<category>/<name>.js';
|
||||
```
|
||||
|
||||
`EndpointsModule.ts` がこのファイルの全エクスポートを `Object.entries()` で反復し、NestJS の provider (`provide: 'ep:<path>'`) を生成する。詳細は [.claude/skills/add-api-endpoint/SKILL.md](../skills/add-api-endpoint/SKILL.md) のステップ 4 を参照。
|
||||
|
||||
## モデル / Repository
|
||||
|
||||
- エンティティ: `packages/backend/src/models/<Name>.ts` (`@Entity` + `@Column`)。
|
||||
- DI 経由で注入される Repository を経由してアクセス。
|
||||
|
||||
## Migration
|
||||
|
||||
詳細手順 (手書き方式 = AGENTS.md §3 と整合):
|
||||
|
||||
> エンティティ差分からの自動生成や `CREATE INDEX CONCURRENTLY` 等のオプションを使いたい場合は [.claude/skills/create-migration/SKILL.md](../skills/create-migration/SKILL.md) の TypeORM CLI 手順を使う。手書き / CLI どちらでも `check-migrations` (pending DDL 検出) さえ通せば等価。
|
||||
|
||||
1. **タイムスタンプ取得**: `node -e "console.log(Date.now())"`
|
||||
2. **ファイル名**: `packages/backend/migration/{timestamp}-{PascalCaseName}.js` (拡張子は `.js`)
|
||||
3. **雛形**:
|
||||
|
||||
```js
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export class PascalCaseName1234567890123 {
|
||||
name = 'PascalCaseName1234567890123'
|
||||
|
||||
async up(queryRunner) {
|
||||
// 前進マイグレーション
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
// up を完全に巻き戻す
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
4. **検証**:
|
||||
- `pnpm --filter backend check-migrations` (TypeORM schema builder で pending DDL を検出する。エンティティと migration の不一致が残っているとここで非ゼロ終了する。実体は [scripts/check_migrations_clean.js](../../packages/backend/scripts/check_migrations_clean.js))
|
||||
- `pnpm migrate` (ローカル DB に適用)
|
||||
- `pnpm revert` (ロールバック確認)
|
||||
5. **エンティティとの整合性**: 関連する `src/models/*.ts` の `@Column` / `@Entity` も同時に更新する。
|
||||
|
||||
> マージ済み migration の編集は **絶対禁止** ([AGENTS.md §3](../../AGENTS.md#3-マージ済み-migration-を絶対に編集しない))。
|
||||
|
||||
## テスト
|
||||
|
||||
- Unit: `pnpm --filter backend test` (`vitest.config.unit.ts`)
|
||||
- E2E: `pnpm --filter backend test:e2e` (`vitest.config.e2e.ts`)
|
||||
- Federation: `pnpm --filter backend test:fed` (`vitest.config.fed.ts`)
|
||||
- 配置: `packages/backend/test/` 配下。
|
||||
76
.claude/docs/frontend.md
Normal file
76
.claude/docs/frontend.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Frontend (`packages/frontend`) 規約
|
||||
|
||||
Vue 3.5 + Vite + Storybook + Cypress E2E。
|
||||
|
||||
## コンポーネント命名
|
||||
|
||||
- 共有 / 再利用コンポーネントは **`Mk` プレフィックス** (例: `MkButton.vue`, `MkInput.vue`, `MkAbuseReport.vue`)。
|
||||
- ページ単位のものは `packages/frontend/src/pages/` 配下に置く。
|
||||
|
||||
## SFC スタイル
|
||||
|
||||
Composition API + `<script setup lang="ts">` を基本とする (Options API は新規導入しない)。型宣言や module スコープのユーティリティを置きたい時は、setup ブロックと**併用**する形で追加の `<script lang="ts">` ブロックを置いて構わない (例: [`MkInput.vue`](../../packages/frontend/src/components/MkInput.vue) は `SupportedTypes` 型を別ブロックで宣言してから setup を書いている)。SCSS は **CSS Modules** で書き、`<style lang="scss" module>` を使う:
|
||||
|
||||
```vue
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div :class="$style.root">
|
||||
<!-- ... -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
// ...
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
/* ... */
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## 国際化 (i18n)
|
||||
|
||||
- 文字列リテラルを直書きしない。
|
||||
- 引数なし: `i18n.ts.<path>` で参照する (例: `i18n.ts.deleted`)。
|
||||
- 引数あり: `i18n.tsx.<path>(...)` で関数呼び出しする (例: `i18n.tsx.takeOverConfirm({ name })`)。
|
||||
- 新規キーは **`locales/ja-JP.yml` のみ** に追加する (他言語は Crowdin で自動配信)。
|
||||
- `i18n` は `packages/frontend/src/i18n.ts` (または共有モジュール) から import する。
|
||||
|
||||
## モーダル / 通知
|
||||
|
||||
- `os.ts` (`packages/frontend/src/os.ts`) 経由で呼ぶ。
|
||||
- `os.alert(...)` / `os.confirm(...)` / `os.popup(...)` / `os.success(...)` など。
|
||||
- ブラウザ標準の `window.alert()` / `window.confirm()` を **直接呼ばない**。
|
||||
|
||||
## アクセシビリティ (PR レビューで指摘されやすい点)
|
||||
|
||||
- クリックハンドラを付けるなら `<button>` を使うか、`role="button"` + `tabindex` を付ける。
|
||||
- フォーム要素には `<label>` または `aria-label` を付ける。
|
||||
- キーボード操作可能であること。
|
||||
|
||||
## Storybook
|
||||
|
||||
新規共有コンポーネントには `<ComponentName>.stories.impl.ts` を併設するのが慣習 (`MkButton.stories.impl.ts` 等の例多数)。
|
||||
|
||||
```bash
|
||||
pnpm --filter frontend storybook-dev # localhost:6006
|
||||
```
|
||||
|
||||
## ビルド・開発
|
||||
|
||||
- 開発: `pnpm dev` (ルート) で backend + frontend が watch で立ち上がる。
|
||||
- ビルド: `pnpm --filter frontend build`
|
||||
- 型チェック: `pnpm --filter frontend typecheck` (vue-tsc)
|
||||
- ESLint: `pnpm --filter frontend eslint`
|
||||
|
||||
## テスト
|
||||
|
||||
- Unit (Vitest): `pnpm --filter frontend test`
|
||||
- Cypress E2E: `pnpm e2e` (ルートから; `start-server-and-test` で起動)
|
||||
28
.claude/docs/plugins.md
Normal file
28
.claude/docs/plugins.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# 有効化済 Claude Code プラグイン
|
||||
|
||||
`.claude/settings.json` で 14 プラグインが有効化されている。それぞれの典型的な利用シーンを 1 行で示す。
|
||||
|
||||
| プラグイン | 用途 |
|
||||
| --- | --- |
|
||||
| `frontend-design` | UI コンポーネント / ページの設計・デザイン作業 (Vue 3 編集に有効) |
|
||||
| `superpowers` | TDD・debugging・brainstorming・planning 等のメタスキル群 |
|
||||
| `context7` | OSS ドキュメントの取得 (Vue 3, NestJS, TypeORM, Vitest 等) — 訓練データの古さを補う |
|
||||
| `code-review` | コードレビュー (`/code-review`) |
|
||||
| `code-simplifier` | コード整理 (`code-simplifier:code-simplifier` サブエージェント経由) |
|
||||
| `github` | GitHub PR / Issue 操作 (gh ベースだが補助コマンドあり) |
|
||||
| `skill-creator` | 新スキルの作成・改善・評価 |
|
||||
| `feature-dev` | 機能開発ガイド (`/feature-dev:feature-dev` / 内部に `code-architect` / `code-explorer` / `code-reviewer` サブエージェント) |
|
||||
| `claude-md-management` | CLAUDE.md の作成・改善 (`/claude-md-management:revise-claude-md` / `claude-md-improver` エージェント) |
|
||||
| `typescript-lsp` | TypeScript LSP 連携 (型情報を活用) |
|
||||
| `security-guidance` | セキュリティレビュー (`/security-review`) |
|
||||
| `pr-review-toolkit` | PR レビュー一式。サブエージェント: `code-reviewer` / `code-simplifier` / `comment-analyzer` / `pr-test-analyzer` / `silent-failure-hunter` / `type-design-analyzer` |
|
||||
| `claude-code-setup` | Claude Code 自動化セットアップ提案 |
|
||||
| `playwright` | ブラウザ自動操作 (フロントエンド動作確認時に有用) |
|
||||
|
||||
## 使い分けの指針
|
||||
|
||||
- **API 関連の調査**: `context7` で対象ライブラリのドキュメントを取得 → 編集。
|
||||
- **PR 作成前**: `pr-review-toolkit` の各エージェント (code-reviewer / silent-failure-hunter 等) を並列で走らせる。
|
||||
- **新機能の設計**: `feature-dev` → brainstorming → 実装の流れ。
|
||||
- **UI 確認**: `playwright` で `pnpm dev` の画面を直接操作。
|
||||
- **将来追加検討**: PostgreSQL MCP — TypeORM + 342 migration の調査効率化。read-only ロールで登録し、接続先 (`misskey` DB) と権限分離に注意する。
|
||||
69
.claude/docs/testing.md
Normal file
69
.claude/docs/testing.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# テスト構成
|
||||
|
||||
## Backend 全般の前提: `.config/test.yml`
|
||||
|
||||
backend のテストスクリプト (`test` / `test:e2e` / `test:fed`) はすべて内部で `cross-env NODE_ENV=test pnpm compile-config` を実行し、`.config/test.yml` を読み込む ([packages/backend/package.json](../../packages/backend/package.json), [packages/backend/scripts/compile_config.js](../../packages/backend/scripts/compile_config.js))。**未作成だとテスト自体が起動しない。**
|
||||
|
||||
未作成なら以下を 1 回だけ手動コピーする (どちらでも可):
|
||||
|
||||
```bash
|
||||
ncp .github/misskey/test.yml .config/test.yml
|
||||
# または
|
||||
cp .github/misskey/test.yml .config/test.yml
|
||||
```
|
||||
|
||||
補足:
|
||||
|
||||
- ルートの `pnpm start:test` (Cypress 用にテストサーバーを起動するコマンド) を使う経路では実行時に `ncp` で自動コピーされる ([package.json](../../package.json))。それ以外で backend テストを直接走らせる時は上記の手動コピーが必要。
|
||||
- すでに `.config/test.yml` があれば各テストスクリプトの内部 `compile-config` で十分なので、追加で `pnpm --filter backend compile-config` を叩く必要はない。
|
||||
- `pnpm start:test` は backend e2e テスト (`pnpm --filter backend test:e2e`) の前提ではない (ポート競合の元になるため使わないこと)。
|
||||
|
||||
## Backend (Vitest 4, 3 設定)
|
||||
|
||||
| 種別 | 設定ファイル | 実行コマンド |
|
||||
| --- | --- | --- |
|
||||
| Unit | `packages/backend/vitest.config.unit.ts` | `pnpm --filter backend test` |
|
||||
| E2E (HTTP / DB) | `packages/backend/vitest.config.e2e.ts` | `pnpm --filter backend test:e2e` |
|
||||
| Federation | `packages/backend/vitest.config.fed.ts` | `pnpm --filter backend test:fed` |
|
||||
|
||||
- 配置: `packages/backend/test/`
|
||||
- 事前準備は [§Backend 全般の前提: `.config/test.yml`](#backend-全般の前提-configtestyml) を参照。
|
||||
- カバレッジ: `pnpm --filter backend test-and-coverage`
|
||||
|
||||
## Frontend (Vitest)
|
||||
|
||||
```bash
|
||||
pnpm --filter frontend test # 1 回実行
|
||||
pnpm --filter frontend test-and-coverage # カバレッジ付き
|
||||
```
|
||||
|
||||
- 主な配置: `packages/frontend/test/*.test.ts` (例: `i18n.test.ts`, `theme.test.ts`, `is-birthday.test.ts`)。
|
||||
- ビルドツール周りなど対象コードと隣接させた方が分かりやすいテストは、コードと同じディレクトリに `*.test.ts` として置く (例: [`packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts`](../../packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts))。
|
||||
- 共有コンポーネント (`MkX.vue`) のユニットテストは現状少なく、`*.spec.ts` / `__tests__/` 形式は採用していない (Storybook + Cypress でカバー)。
|
||||
|
||||
## E2E (Cypress)
|
||||
|
||||
ルートから実行する:
|
||||
|
||||
```bash
|
||||
pnpm e2e # start:test サーバーを立てて Cypress run
|
||||
pnpm cy:open # 対話的に開く
|
||||
```
|
||||
|
||||
- 設定: ルート `cypress.config.ts`。テスト本体は `cypress/` 配下。
|
||||
|
||||
## Storybook (frontend)
|
||||
|
||||
```bash
|
||||
pnpm --filter frontend storybook-dev # http://localhost:6006
|
||||
pnpm --filter frontend build-storybook # 静的ビルド
|
||||
```
|
||||
|
||||
- 各コンポーネント横に `*.stories.impl.ts` を併設する慣習 (例: `MkButton.stories.impl.ts`)。
|
||||
- Chromatic (`pnpm --filter frontend chromatic`) で視覚回帰チェック。
|
||||
|
||||
## ローカル DB / Redis (テスト・開発共通)
|
||||
|
||||
```bash
|
||||
docker compose -f compose.local-db.yml up -d
|
||||
```
|
||||
18
.claude/settings.json
Normal file
18
.claude/settings.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"enabledPlugins": {
|
||||
"frontend-design@claude-plugins-official": true,
|
||||
"superpowers@claude-plugins-official": true,
|
||||
"context7@claude-plugins-official": true,
|
||||
"code-review@claude-plugins-official": true,
|
||||
"code-simplifier@claude-plugins-official": true,
|
||||
"github@claude-plugins-official": true,
|
||||
"skill-creator@claude-plugins-official": true,
|
||||
"feature-dev@claude-plugins-official": true,
|
||||
"claude-md-management@claude-plugins-official": true,
|
||||
"typescript-lsp@claude-plugins-official": true,
|
||||
"security-guidance@claude-plugins-official": true,
|
||||
"pr-review-toolkit@claude-plugins-official": true,
|
||||
"claude-code-setup@claude-plugins-official": true,
|
||||
"playwright@claude-plugins-official": true
|
||||
}
|
||||
}
|
||||
33
.claude/skills/README.md
Normal file
33
.claude/skills/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# `.claude/skills/` — プロジェクト固有のカスタムスキル
|
||||
|
||||
Misskey 固有の繰り返しタスクを Claude にスムーズに実行させるための **カスタムスキル** を `.claude/skills/<name>/SKILL.md` 形式で配置する。
|
||||
|
||||
frontmatter (`name` + `description`) は、Claude が **自動でスキルを呼び出すか判断する** 唯一の手がかりになる。`description` には用途を具体的かつ網羅的に書く (動詞 + 対象 + トリガー条件)。
|
||||
|
||||
## 実装済スキル
|
||||
|
||||
### Misskey 固有 (本リポジトリ向け書き起こし)
|
||||
|
||||
| スキル名 | 役割 | 優先度 |
|
||||
| --- | --- | --- |
|
||||
| [create-migration](create-migration/SKILL.md) | TypeORM CLI (`migration:generate` / `migration:create`) でマイグレーションを生成し、SPDX / up-down / `check-migrations` まで誘導 | 高 (342 既存 / 規約厳しい) |
|
||||
| [add-api-endpoint](add-api-endpoint/SKILL.md) | NestJS DI + meta/paramDef 規約で API エンドポイント追加。`endpoint-list.ts` 登録と `misskey-js` 再生成を含む | 高 |
|
||||
| [add-i18n-key](add-i18n-key/SKILL.md) | `locales/ja-JP.yml` のみ編集する補助。型は `packages/i18n` が自動再生成 | 中 |
|
||||
| [add-mk-component](add-mk-component/SKILL.md) | `Mk*` 命名 + SPDX (HTML) + SCSS module + `*.stories.impl.ts` 併設の Vue コンポーネントを一括スキャフォールド | 中 |
|
||||
|
||||
### ECC (everything-claude-code) 由来 — MIT セレクトインポート
|
||||
|
||||
[.claude/THIRD_PARTY_LICENSES.md](../THIRD_PARTY_LICENSES.md) §1 に出典・改変メモ・MIT 全文を集約。
|
||||
|
||||
| スキル名 | 役割 | 優先度 |
|
||||
| --- | --- | --- |
|
||||
| [context-budget](context-budget/SKILL.md) | agents / skills / MCP / CLAUDE.md の token overhead を見える化し、肥大コンポーネントを検出 | 中 |
|
||||
|
||||
設計方針: `create-migration` は手動の `Date.now()` 命名ではなく TypeORM 公式 CLI (`migration:generate` / `migration:create`) を採用。Storybook ファイル名は `*.stories.impl.ts` 規約に準拠する。
|
||||
|
||||
## 新規スキルを追加する場合
|
||||
|
||||
- `.claude/skills/<name>/SKILL.md` に YAML frontmatter (`name` + `description`) と本文 Markdown を書く。
|
||||
- `disable-model-invocation: true` は付けない (auto-invoke させたいため)。
|
||||
- 主要参照ファイルへのリンクは、リポジトリルートからの相対パス (例: `../../packages/backend/...`) で貼る。絶対パスは contributor のホームディレクトリ依存になるので使わない。
|
||||
- 完成したらこの README の表にも 1 行追加する。
|
||||
253
.claude/skills/add-api-endpoint/SKILL.md
Normal file
253
.claude/skills/add-api-endpoint/SKILL.md
Normal file
@@ -0,0 +1,253 @@
|
||||
---
|
||||
name: add-api-endpoint
|
||||
description: Misskey の REST API エンドポイント (/api/<category>/<name>) を NestJS DI + meta/paramDef 規約で追加する。バックエンドに新しい API ルートを足す時に必ず使う。endpoint-list.ts への手動登録、e2e テスト、misskey-js 再生成、CHANGELOG までの一連の手順を含む。
|
||||
---
|
||||
|
||||
# Misskey API エンドポイント追加スキル
|
||||
|
||||
`packages/backend/src/server/api/endpoints/<category>/<name>.ts` に新規エンドポイントを追加するためのワークフロー。**手順 4 (endpoint-list.ts 登録) を忘れると 404 になる** 点に最大の注意を払う。
|
||||
|
||||
## 最重要事実 (見落とすと壊れる)
|
||||
|
||||
1. エンドポイントは **glob 自動収集されない**。[packages/backend/src/server/api/endpoint-list.ts](../../../packages/backend/src/server/api/endpoint-list.ts) への 1 行追加が必須。
|
||||
2. `meta` / `paramDef` を変えたら **misskey-js の再生成が必須**。`pnpm build-misskey-js-with-types` を忘れると CI の `check-misskey-js-autogen` で必ず落ちる。
|
||||
3. `meta.errors` の各 `id` は **UUID**。重複させない (既存全 UUID と衝突確認)。
|
||||
|
||||
## ステップ 1: ファイル配置と SPDX
|
||||
|
||||
`packages/backend/src/server/api/endpoints/<category>/<name>.ts` に新規作成する。`<category>` は機能領域 (例: `notes`, `users`, `admin/announcements`)。
|
||||
|
||||
冒頭に SPDX ヘッダーを必ず付ける:
|
||||
|
||||
```ts
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
```
|
||||
|
||||
## ステップ 2: 最小テンプレート (シンプル read 系)
|
||||
|
||||
[endpoints/ping.ts](../../../packages/backend/src/server/api/endpoints/ping.ts) をベースに書く。認証不要・パラメータなし・小さなレスポンスの例:
|
||||
|
||||
```ts
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['<tag>'],
|
||||
requireCredential: false,
|
||||
|
||||
res: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
properties: {
|
||||
// ...
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
required: [],
|
||||
} as const;
|
||||
|
||||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||
constructor(
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
// 実装
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## ステップ 3: 認証付き / DI / errors を含むテンプレート
|
||||
|
||||
[endpoints/notes/create.ts](../../../packages/backend/src/server/api/endpoints/notes/create.ts) を参照する。要点:
|
||||
|
||||
```ts
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
// import ms from 'ms'; // limit.duration に ms('1hour') 等を渡すとき (default import)
|
||||
|
||||
export const meta = {
|
||||
tags: ['notes'],
|
||||
requireCredential: true, // 認証必須なら true
|
||||
prohibitMoved: false, // moved user を拒否するか
|
||||
kind: 'write:notes', // OAuth scope (requireCredential 時に必須)
|
||||
limit: {
|
||||
duration: 3600000, // ms('1hour')
|
||||
max: 300,
|
||||
},
|
||||
errors: {
|
||||
noSuchNote: {
|
||||
message: 'No such note.',
|
||||
code: 'NO_SUCH_NOTE',
|
||||
id: 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx', // ★ UUID v4 を必ず生成 (`x`=hex, `y`=8/9/a/b)。下の「UUID 生成」を参照
|
||||
},
|
||||
},
|
||||
res: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
ref: 'Note', // packed entity に揃える場合
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
noteId: { type: 'string', format: 'misskey:id' },
|
||||
},
|
||||
required: ['noteId'],
|
||||
} as const;
|
||||
|
||||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||
constructor(
|
||||
@Inject(DI.notesRepository)
|
||||
private notesRepository: NotesRepository,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
const note = await this.notesRepository.findOneBy({ id: ps.noteId });
|
||||
if (note == null) throw new ApiError(meta.errors.noSuchNote);
|
||||
// 実装
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### meta フィールド早見表
|
||||
|
||||
| フィールド | 用途 |
|
||||
|---|---|
|
||||
| `tags` | OpenAPI タグ (機能領域) |
|
||||
| `requireCredential` | 認証必須か |
|
||||
| `requireModerator` / `requireAdmin` | 権限制限 |
|
||||
| `prohibitMoved` | アカウント移行済ユーザーを拒否 |
|
||||
| `kind` | OAuth scope (`read:notes` / `write:notes` 等)。`requireCredential: true` 時必須 |
|
||||
| `limit` | レート制限 (`{ duration, max, key?, minInterval? }`) |
|
||||
| `errors` | エラー定義。各要素に `message` / `code` / `id` (UUID v4) 必須 |
|
||||
| `res` | JSON Schema or `ref: '<EntityName>'` (packed entity 参照) |
|
||||
| `requireFile` | ファイルアップロード必須 |
|
||||
| `secure` | secure cookie 必要 |
|
||||
| `allowGet` | GET メソッド許可 |
|
||||
| `cacheSec` | レスポンスキャッシュ秒数 |
|
||||
| `description` | OpenAPI 説明 |
|
||||
|
||||
詳細は [endpoints.ts](../../../packages/backend/src/server/api/endpoints.ts) の型定義 (lines 11-125) を参照。
|
||||
|
||||
### paramDef の特殊フォーマット
|
||||
|
||||
JSON Schema (AJV) ベースだが、Misskey 拡張を使える:
|
||||
|
||||
- `format: 'misskey:id'` — ID 文字列バリデーション
|
||||
- `allOf` / `anyOf` / `oneOf` — 複合条件
|
||||
- `default` — デフォルト値
|
||||
|
||||
詳細は [endpoint-base.ts](../../../packages/backend/src/server/api/endpoint-base.ts) を参照。
|
||||
|
||||
### エラー throw
|
||||
|
||||
**「公開 API エラーとして API クライアントに返したいもの」は必ず `throw new ApiError(meta.errors.<key>)` を使う**。`meta.errors` に列挙した上で `ApiError` でラップしないと、misskey-js 側の型情報に出ず、レスポンスも 500 になる。第 2 引数で追加情報を渡せる:
|
||||
|
||||
```ts
|
||||
throw new ApiError(meta.errors.invalidParam, { reason: 'too short' });
|
||||
```
|
||||
|
||||
一方で、**想定外の例外 (DB 不整合 / 下層サービスの bug など) を握り潰すために `try/catch` で `ApiError` に変換するのは避ける**。既存 endpoint も「期待される業務エラーは `ApiError` に変換し、それ以外は `throw err;` で再 throw する」という二段構えになっている。`packages/backend/src/server/api/endpoints/notes/create.ts` の `catch` 節 (末尾の `throw err;`) を参照。生の `throw` を全面禁止すると未知例外も 200 で潰れて debug が困難になるので、このバランスを保つ。
|
||||
|
||||
詳細は [error.ts](../../../packages/backend/src/server/api/error.ts) の `ApiError` クラスを参照。
|
||||
|
||||
### UUID 生成
|
||||
|
||||
```bash
|
||||
node -e "console.log(crypto.randomUUID())"
|
||||
```
|
||||
|
||||
その UUID が他のエンドポイントの `id` と衝突していないか必ず確認:
|
||||
|
||||
```bash
|
||||
grep -r "id: '<生成した UUID>'" packages/backend/src/server/api/endpoints/
|
||||
```
|
||||
|
||||
## ステップ 4: ★必須 — endpoint-list.ts に登録
|
||||
|
||||
[packages/backend/src/server/api/endpoint-list.ts](../../../packages/backend/src/server/api/endpoint-list.ts) の同カテゴリ末尾に 1 行追加する(既存の並びを崩さない):
|
||||
|
||||
```ts
|
||||
export * as '<category>/<name>' from './endpoints/<category>/<name>.js';
|
||||
```
|
||||
|
||||
ファイル冒頭のコメント (`When you add new endpoint, you should add it to this file.`) の通り、このリストが API ルーティングの単一の真実。**忘れると 404**。
|
||||
|
||||
`EndpointsModule.ts` がこのファイルの全エクスポートを `Object.entries()` で反復し、NestJS provider (`provide: 'ep:<path>'`) を生成する。
|
||||
|
||||
## ステップ 5: e2e テスト追加
|
||||
|
||||
[packages/backend/test/e2e/endpoints.ts](../../../packages/backend/test/e2e/endpoints.ts) に対応する `describe` / `test` を追加する。`api()` ヘルパーで叩く:
|
||||
|
||||
```ts
|
||||
describe('<category>/<name>', () => {
|
||||
test('正常系', async () => {
|
||||
const res = await api('<category>/<name>', { /* params */ }, alice);
|
||||
assert.strictEqual(res.status, 200);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
実行: `pnpm --filter backend test:e2e`
|
||||
|
||||
## ステップ 6: misskey-js 再生成 (★必須)
|
||||
|
||||
`meta` / `paramDef` / `res` を変えたら必ず実行する:
|
||||
|
||||
```bash
|
||||
pnpm build-misskey-js-with-types
|
||||
```
|
||||
|
||||
これで以下が更新される:
|
||||
|
||||
- `packages/backend/built/api.json` (OpenAPI spec)
|
||||
- `packages/misskey-js/generator/api.json`
|
||||
- `packages/misskey-js/src/autogen/*.ts` (TypeScript 型)
|
||||
|
||||
PR に `packages/misskey-js/src/autogen/` 配下の差分が含まれていないと、CI の `check-misskey-js-autogen` で落ちる。
|
||||
|
||||
## ステップ 7: Lint と typecheck
|
||||
|
||||
```bash
|
||||
pnpm --filter backend lint
|
||||
```
|
||||
|
||||
(typecheck = `tsgo --noEmit` / ESLint = `eslint`)
|
||||
|
||||
## ステップ 8: CHANGELOG
|
||||
|
||||
ユーザー影響がある (新機能 / 既存挙動変更) なら、`CHANGELOG.md` の `## Unreleased` → `### Server` に 1 行追加する ([AGENTS.md §CHANGELOG](../../../AGENTS.md#changelog) 参照):
|
||||
|
||||
```
|
||||
- Feat: /api/<category>/<name> を追加
|
||||
```
|
||||
|
||||
純粋なリファクタや内部用なら不要。
|
||||
|
||||
## 参照ファイル
|
||||
|
||||
- [endpoints.ts (meta/paramDef 型定義)](../../../packages/backend/src/server/api/endpoints.ts)
|
||||
- [endpoint-base.ts (Endpoint 基底クラス)](../../../packages/backend/src/server/api/endpoint-base.ts)
|
||||
- [endpoint-list.ts (★ ここに登録)](../../../packages/backend/src/server/api/endpoint-list.ts)
|
||||
- [error.ts (ApiError)](../../../packages/backend/src/server/api/error.ts)
|
||||
- [endpoints/ping.ts (最小例)](../../../packages/backend/src/server/api/endpoints/ping.ts)
|
||||
- [endpoints/notes/create.ts (DI + errors の典型)](../../../packages/backend/src/server/api/endpoints/notes/create.ts)
|
||||
- [test/e2e/endpoints.ts (テスト例)](../../../packages/backend/test/e2e/endpoints.ts)
|
||||
- [scripts/generate_api_json.js (misskey-js 生成元)](../../../packages/backend/scripts/generate_api_json.js)
|
||||
117
.claude/skills/add-i18n-key/SKILL.md
Normal file
117
.claude/skills/add-i18n-key/SKILL.md
Normal file
@@ -0,0 +1,117 @@
|
||||
---
|
||||
name: add-i18n-key
|
||||
description: Misskey の i18n キーを追加・修正する。locales/ja-JP.yml のみ編集可能で、他言語ファイル (en-US.yml 等 39 言語) は Crowdin の自動配信先のため絶対に触らない。型は packages/i18n が ja-JP.yml から自動再生成する。frontend からは i18n.ts.<key> または i18n.tsx.<key>(...) で参照する。
|
||||
---
|
||||
|
||||
# Misskey i18n キー追加スキル
|
||||
|
||||
UI 文言の追加・変更を行う際の規約。**手動編集して良いのは `locales/ja-JP.yml` のみ。**
|
||||
|
||||
## 大前提 (絶対 NG)
|
||||
|
||||
- **`locales/<lang>.yml` (ja-JP.yml 以外) の編集は禁止**。これらは Crowdin の自動配信先で、手動編集すると次の同期で上書き喪失する ([locales/README.md](../../../locales/README.md), [crowdin.yml](../../../crowdin.yml))。
|
||||
- 文字列リテラルを SFC に直書きしない (`<span>こんにちは</span>` 等)。必ず `i18n.ts.<key>` を経由する。
|
||||
- 既存キーの破壊的リネームは Crowdin 翻訳資産も道連れになるので慎重に。追加・改名併用 (新キー追加 → 移行 → 旧キー削除) を検討する。
|
||||
|
||||
## ステップ 1: ja-JP.yml にキーを追加
|
||||
|
||||
[locales/ja-JP.yml](../../../locales/ja-JP.yml) を編集する。YAML の階層構造を維持し、関連するセクションに配置する:
|
||||
|
||||
```yaml
|
||||
# トップレベル単純キー
|
||||
save: "保存"
|
||||
|
||||
# ネストしたカテゴリ (アンダースコア接頭辞は内部カテゴリ)
|
||||
_settings:
|
||||
general: "全般"
|
||||
appearance: "外観"
|
||||
|
||||
# パラメータ付き (単純なプレースホルダ置換)
|
||||
# ICU MessageFormat の plural / select / number / date などは非対応
|
||||
# 使えるのは `{name}` のような単純な置換のみ
|
||||
greeting: "こんにちは、{name}さん"
|
||||
```
|
||||
|
||||
### 命名のお作法
|
||||
|
||||
- 単純キー: lowerCamelCase (例: `saveChanges`, `confirmDelete`)。
|
||||
- カテゴリ: アンダースコア接頭辞 (例: `_settings`, `_abuseUserReport`)。
|
||||
- 既存セクション内に置く場合はアルファベット順を維持する (新セクション全体を末尾に追加するのは可)。
|
||||
|
||||
## ステップ 2: 型定義の自動再生成
|
||||
|
||||
`packages/i18n/build.ts` が `ja-JP.yml` を解析し、TypeScript インターフェースを [packages/i18n/src/autogen/locale.ts](../../../packages/i18n/src/autogen/locale.ts) に出力する。
|
||||
|
||||
### 自動 (推奨)
|
||||
|
||||
`pnpm dev` 実行中なら、`packages/i18n` の watch スクリプトが yml の変更を検知して自動再生成する。
|
||||
|
||||
### 手動
|
||||
|
||||
```bash
|
||||
pnpm --filter i18n generate
|
||||
```
|
||||
|
||||
実体は `tsx scripts/generateLocaleInterface.ts`。
|
||||
|
||||
### 失敗パターン
|
||||
|
||||
これを実行せずに frontend 側で `i18n.ts.<newKey>` を参照すると、`Locale` インターフェースに追加されていないため、typecheck で「Property '<newKey>' does not exist on type 'Locale'」というエラーになる。`pnpm --filter frontend lint` で発覚する。
|
||||
|
||||
## ステップ 3: frontend での参照
|
||||
|
||||
```ts
|
||||
import { i18n } from '@/i18n.js';
|
||||
```
|
||||
|
||||
| 用途 | 書き方 |
|
||||
|---|---|
|
||||
| 単純文字列 | `i18n.ts.save` |
|
||||
| ネスト | `i18n.ts._settings.general` |
|
||||
| パラメータ付き | `i18n.tsx.greeting({ name: userName })` |
|
||||
| Vue テンプレート内 | `{{ i18n.ts.save }}` / `{{ i18n.tsx.greeting({ name }) }}` |
|
||||
|
||||
`i18n.ts` は型付き文字列、`i18n.tsx` は MessageFormat 関数。
|
||||
|
||||
## ステップ 4: 検証
|
||||
|
||||
```bash
|
||||
# i18n パッケージの型再生成 + typecheck
|
||||
pnpm --filter i18n lint
|
||||
|
||||
# frontend で新キー参照箇所の型チェック
|
||||
pnpm --filter frontend lint
|
||||
```
|
||||
|
||||
## 例: 「ノートを削除しますか?」確認ダイアログを追加する
|
||||
|
||||
1. `locales/ja-JP.yml`:
|
||||
```yaml
|
||||
_notes:
|
||||
deleteConfirm: "このノートを削除しますか?"
|
||||
```
|
||||
2. `pnpm --filter i18n generate` (または `pnpm dev` で watch 中)
|
||||
3. SFC:
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { i18n } from '@/i18n.js';
|
||||
import * as os from '@/os.js';
|
||||
|
||||
async function onDelete() {
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'warning',
|
||||
text: i18n.ts._notes.deleteConfirm,
|
||||
});
|
||||
if (canceled) return;
|
||||
// 削除処理
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## 参照ファイル
|
||||
|
||||
- [locales/README.md (★ 編集ポリシー根拠)](../../../locales/README.md)
|
||||
- [locales/ja-JP.yml](../../../locales/ja-JP.yml)
|
||||
- [packages/i18n/build.ts](../../../packages/i18n/build.ts)
|
||||
- [packages/i18n/src/autogen/locale.ts (生成物)](../../../packages/i18n/src/autogen/locale.ts)
|
||||
- [packages/frontend/src/i18n.ts](../../../packages/frontend/src/i18n.ts)
|
||||
174
.claude/skills/add-mk-component/SKILL.md
Normal file
174
.claude/skills/add-mk-component/SKILL.md
Normal file
@@ -0,0 +1,174 @@
|
||||
---
|
||||
name: add-mk-component
|
||||
description: Misskey フロントエンドの新規 Vue 3 コンポーネントを追加する。Mk* 命名 / SPDX (HTML コメント) / <script setup lang="ts"> / <style lang="scss" module> / *.stories.impl.ts 併設の規約をまとめて適用する。新しい共有 UI コンポーネントを packages/frontend/src/components/ に作る時に使う。
|
||||
---
|
||||
|
||||
# Misskey Vue コンポーネント追加スキル
|
||||
|
||||
`packages/frontend/src/components/` に新しい共有コンポーネントを追加するための規約。
|
||||
|
||||
## 大前提
|
||||
|
||||
- 共有 / 再利用コンポーネントは **必ず `Mk` プレフィックス** (例: `MkButton`, `MkInput`)。ページ固有部品など `Mk` プレフィックスでないものは原則 `pages/` 側に置く。
|
||||
- 新規では `<style lang="scss" module>` (CSS Modules) を既定とする。古い `scoped` 形式が混在しているが、新規では使わない。
|
||||
- 文字列リテラルの直書きは禁止。文言は必ず `i18n.ts.<key>` 経由で参照する (新キーは `add-i18n-key` スキルを参照)。
|
||||
- `alert()` / `confirm()` / `window.prompt()` は使わない。`os.alert` / `os.confirm` / `os.popup` などを使う。
|
||||
|
||||
## ステップ 1: ファイル配置
|
||||
|
||||
`packages/frontend/src/components/Mk<Name>.vue` に新規作成する。
|
||||
|
||||
ストーリーが必要 (= ほぼ常に必要) なら、同階層に `Mk<Name>.stories.impl.ts` も作る。Storybook の規約は `*.stories.impl.ts` であって、`*.stories.ts` ではない。
|
||||
|
||||
## ステップ 2: SPDX ヘッダー (HTML コメント形式)
|
||||
|
||||
`.vue` ファイル冒頭に必須:
|
||||
|
||||
```html
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
```
|
||||
|
||||
`/* ... */` (TS / JS 形式) ではなく **HTML コメント** で書くこと。既存の `.vue` ファイルがすべて HTML コメント形式を使っており、SFC の先頭として自然な形式に統一するため (CI の `spdx` ジョブはコメント形式ではなく SPDX 文字列の有無のみを検査する)。
|
||||
|
||||
## ステップ 3: 最小テンプレート
|
||||
|
||||
[MkInfo.vue](../../../packages/frontend/src/components/MkInfo.vue) をベースにする (シンプルな表示コンポーネント):
|
||||
|
||||
```vue
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div :class="$style.root">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const props = defineProps<{
|
||||
variant?: 'primary' | 'secondary';
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'click'): void;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
padding: 12px 14px;
|
||||
border-radius: var(--MI-radius);
|
||||
background: var(--MI_THEME-panel);
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### 規約ポイント
|
||||
|
||||
| 項目 | 規約 |
|
||||
|---|---|
|
||||
| `<script>` | `<script lang="ts" setup>`。型パラメータが必要なら `generic="T extends ..."` を付ける ([MkInput.vue 参照](../../../packages/frontend/src/components/MkInput.vue)) |
|
||||
| `defineProps` / `defineEmits` | **type-only** (`<{ ... }>`) 形式。runtime の object 形式は使わない |
|
||||
| `<style>` | `lang="scss" module` を既定。クラス参照は `:class="$style.foo"` |
|
||||
| CSS 変数 | `var(--MI_THEME-...)` (テーマ) / `var(--MI-radius)` (UI 共通) — ハードコードしない |
|
||||
| アイコン | Tabler icons のクラス (`<i class="ti ti-info-circle">`) を使う |
|
||||
|
||||
## ステップ 4: i18n と os の利用
|
||||
|
||||
```vue
|
||||
<script lang="ts" setup>
|
||||
import { i18n } from '@/i18n.js';
|
||||
import * as os from '@/os.js';
|
||||
|
||||
async function onClick() {
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'warning',
|
||||
text: i18n.ts._notes.deleteConfirm,
|
||||
});
|
||||
if (canceled) return;
|
||||
os.toast(i18n.ts.deleted);
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### `os` の主なヘルパー (詳細は [os.ts](../../../packages/frontend/src/os.ts))
|
||||
|
||||
| 関数 | 用途 |
|
||||
|---|---|
|
||||
| `os.alert({ type, title?, text })` | 単方向アラート |
|
||||
| `os.confirm({ type, title, text })` | yes/no 確認 (`{ canceled }` を返す) |
|
||||
| `os.toast(message)` | 一時通知 |
|
||||
| `os.popup(component, props, handlers)` | 任意コンポーネントの非同期ポップアップ |
|
||||
| `os.popupMenu(items, anchor?)` | コンテキストメニュー |
|
||||
| `os.form(title, fields)` | フォームダイアログ |
|
||||
| `os.apiWithDialog(endpoint, data)` | API 呼出し + エラー時ダイアログ表示 |
|
||||
|
||||
## ステップ 5: Storybook ストーリー併設
|
||||
|
||||
[MkButton.stories.impl.ts](../../../packages/frontend/src/components/MkButton.stories.impl.ts) を雛形として参考にする。`.stories.impl.ts` も `packages/frontend/src/` 配下の `.ts` ファイルなので [AGENTS.md §1 SPDX ヘッダー必須](../../../AGENTS.md#1-spdx-ヘッダー必須) の対象であり、冒頭に SPDX ヘッダーを必ず付ける (HTML コメント形式ではなく `/* */` 形式)。形式 (以下の `MkXxx` は実際のコンポーネント名に置換する):
|
||||
|
||||
```ts
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
/* eslint-disable import/no-default-export */
|
||||
import type { StoryObj } from '@storybook/vue3';
|
||||
import MkXxx from './MkXxx.vue';
|
||||
|
||||
export const Default = {
|
||||
render(args) {
|
||||
return {
|
||||
components: { MkXxx },
|
||||
setup() {
|
||||
return { args };
|
||||
},
|
||||
template: '<MkXxx v-bind="args">slot content</MkXxx>',
|
||||
};
|
||||
},
|
||||
args: {
|
||||
variant: 'primary',
|
||||
},
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
},
|
||||
} satisfies StoryObj<typeof MkXxx>;
|
||||
```
|
||||
|
||||
`Vue` SFC は default export なので、`import MkXxx from './MkXxx.vue';` のように名前付き import ではなく default import で書く。実行確認は `pnpm --filter frontend storybook-dev`。
|
||||
|
||||
## ステップ 6: Lint と typecheck
|
||||
|
||||
```bash
|
||||
pnpm --filter frontend lint
|
||||
```
|
||||
|
||||
(typecheck = vue-tsc 等、ESLint = `@misskey-dev/eslint-plugin` 含む)
|
||||
|
||||
ESLint --fix をピンポイントで:
|
||||
|
||||
```bash
|
||||
pnpm exec eslint --fix packages/frontend/src/components/Mk<Name>.vue
|
||||
```
|
||||
|
||||
## ステップ 7: 既存コンポーネントとの整合性確認
|
||||
|
||||
- 似た用途の既存 `Mk*` コンポーネントを参考に、スタイルやプロップ命名を揃える。
|
||||
- `_button` / `_panel` / `_selectable` などの **共通 utility class** (グローバルスタイルにある) を活用できるか確認する。
|
||||
- 大きな機能なら、Storybook stories で各バリエーションを網羅する。
|
||||
|
||||
## 参照ファイル
|
||||
|
||||
- [MkInfo.vue (シンプル例)](../../../packages/frontend/src/components/MkInfo.vue)
|
||||
- [MkButton.vue (汎用ボタン例)](../../../packages/frontend/src/components/MkButton.vue)
|
||||
- [MkInput.vue (generics + 多機能例)](../../../packages/frontend/src/components/MkInput.vue)
|
||||
- [MkButton.stories.impl.ts (Storybook 雛形)](../../../packages/frontend/src/components/MkButton.stories.impl.ts)
|
||||
- [packages/frontend/src/os.ts](../../../packages/frontend/src/os.ts)
|
||||
- [packages/frontend/src/i18n.ts](../../../packages/frontend/src/i18n.ts)
|
||||
148
.claude/skills/context-budget/SKILL.md
Normal file
148
.claude/skills/context-budget/SKILL.md
Normal file
@@ -0,0 +1,148 @@
|
||||
---
|
||||
name: context-budget
|
||||
description: Claude Code セッションのコンテキスト窓消費を agents/skills/MCP/rules/CLAUDE.md ごとに見える化し、肥大化と冗長コンポーネントを検出して節約候補を提示する。"コンテキスト消費を見せて"、"context budget"、"context audit"、"トークン内訳"、"これ以上 MCP 入る?" 等の発話で起動する。
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: MIT
|
||||
SPDX-FileCopyrightText: 2026 Affaan Mustafa and everything-claude-code contributors
|
||||
|
||||
出典 (upstream): https://github.com/affaan-m/everything-claude-code (v2.0.0-rc.1)
|
||||
upstream path: skills/context-budget/SKILL.md
|
||||
upstream origin frontmatter: ECC
|
||||
upstream license: MIT — https://github.com/affaan-m/everything-claude-code/blob/main/LICENSE
|
||||
project-level notice: see .claude/THIRD_PARTY_LICENSES.md (Misskey 内サードパーティ一覧 + MIT 全文)
|
||||
|
||||
Imported into Misskey .claude/ on 2026-05-10 as a standalone copy (no dependency on the ECC plugin runtime). description was rewritten in Japanese and a "Misskey 固有メモ" section was appended; body content remains MIT-licensed.
|
||||
|
||||
note: Misskey の skills/agents 数は少ないので、MCP / CLAUDE.md / プラグイン由来の overhead が支配的になりやすい点に留意。
|
||||
-->
|
||||
|
||||
# Context Budget
|
||||
|
||||
セッション内に読み込まれるコンポーネント (agents / skills / rules / MCP servers / CLAUDE.md) の token overhead を分析し、空き context を回復する具体策を提示する。
|
||||
|
||||
## 使う場面
|
||||
|
||||
- セッションが重い・出力品質が落ちてきた感覚がある
|
||||
- 直近で skills / agents / MCP server を多数追加した
|
||||
- 残りの context headroom を知りたい
|
||||
- 追加コンポーネントを入れる前に空きを確認したい
|
||||
- 「context-budget」「token 内訳」等のキーワードでユーザーが明示的に要請した時 (Misskey リポジトリにはこの名前のスラッシュコマンドは登録していない — 本 skill は名前 / description マッチで auto-invoke される想定。実装済の slash command 一覧は [.claude/commands/](../../commands/) を参照)
|
||||
|
||||
## 仕組み
|
||||
|
||||
### Phase 1: Inventory
|
||||
|
||||
各コンポーネントを走査して token を推定する。
|
||||
|
||||
**Agents** (`.claude/agents/*.md`)
|
||||
- 行数とトークン数 (`words × 1.3`) を計算
|
||||
- frontmatter `description` の長さを抽出
|
||||
- フラグ: 200 行超 (重い)、description 30 word 超 (frontmatter 肥大)
|
||||
|
||||
**Skills** (`.claude/skills/*/SKILL.md`)
|
||||
- SKILL.md ごとに token を計算
|
||||
- フラグ: 400 行超
|
||||
- `.agents/skills/` 等の重複コピーは除外
|
||||
|
||||
**Rules** (リポジトリルートの `AGENTS.md` + `.claude/` から `@-import` されるファイル)
|
||||
- ファイル単位で token 計算
|
||||
- フラグ: 100 行超
|
||||
- 同一言語モジュール内の内容重複を検出
|
||||
|
||||
**MCP Servers** (`.mcp.json` または有効 MCP 設定)
|
||||
- server 数と総 tool 数
|
||||
- schema overhead をツールあたり ~500 token で見積もる
|
||||
- フラグ: 20 tool 超のサーバー、`gh` / `git` / `npm` 等の CLI を単純ラップしただけのサーバー
|
||||
|
||||
**CLAUDE.md** (project + user-level)
|
||||
- ファイルごとに token を計算
|
||||
- フラグ: 合計 300 行超
|
||||
|
||||
### Phase 2: Classify
|
||||
|
||||
| バケット | 判定基準 | 行動 |
|
||||
|--------------------|-------------------------------------------------------------|-----------------------------------|
|
||||
| **Always needed** | CLAUDE.md から参照されている / 有効コマンドの裏 / 現プロジェクトと一致 | 維持 |
|
||||
| **Sometimes needed** | ドメイン依存 (例: 言語パターン)、CLAUDE.md 参照なし | オンデマンド有効化を検討 |
|
||||
| **Rarely needed** | コマンド参照なし、内容重複、明確な用途なし | 削除または lazy-load |
|
||||
|
||||
### Phase 3: Detect Issues
|
||||
|
||||
- **Bloated agent description** — frontmatter description が 30 word 超だと、Task ツール起動のたびに毎回ロードされる
|
||||
- **Heavy agents** — 200 行超は Task ツールの context を毎回膨らませる
|
||||
- **Redundant components** — agent ロジックを重複する skill、CLAUDE.md と重複する rule
|
||||
- **MCP over-subscription** — 10 server 超、または CLI 代用可能なサーバー
|
||||
- **CLAUDE.md bloat** — 冗長説明、古いセクション、rule に移すべき指示
|
||||
|
||||
### Phase 4: Report
|
||||
|
||||
```
|
||||
Context Budget Report
|
||||
═══════════════════════════════════════
|
||||
|
||||
Total estimated overhead: ~XX,XXX tokens
|
||||
Context model: <現在モデル名> (<window>K window) ← 例: Claude Opus 4.7 (1M), Claude Sonnet (200K)
|
||||
Effective available context: ~XXX,XXX tokens (XX%)
|
||||
|
||||
Component Breakdown:
|
||||
┌─────────────────┬────────┬───────────┐
|
||||
│ Component │ Count │ Tokens │
|
||||
├─────────────────┼────────┼───────────┤
|
||||
│ Agents │ N │ ~X,XXX │
|
||||
│ Skills │ N │ ~X,XXX │
|
||||
│ Rules │ N │ ~X,XXX │
|
||||
│ MCP tools │ N │ ~XX,XXX │
|
||||
│ CLAUDE.md │ N │ ~X,XXX │
|
||||
└─────────────────┴────────┴───────────┘
|
||||
|
||||
WARNING: Issues Found (N):
|
||||
[token 節約量の降順]
|
||||
|
||||
Top 3 Optimizations:
|
||||
1. [action] → save ~X,XXX tokens
|
||||
2. [action] → save ~X,XXX tokens
|
||||
3. [action] → save ~X,XXX tokens
|
||||
|
||||
Potential savings: ~XX,XXX tokens (XX% of current overhead)
|
||||
```
|
||||
|
||||
verbose mode ではさらにファイルごとの token 内訳、最重ファイルの行単位ブレークダウン、重複行の対比、MCP tool 一覧 + tool ごとの schema サイズ推定を出す。
|
||||
|
||||
## 例
|
||||
|
||||
**基本監査**
|
||||
```
|
||||
User: コンテキスト消費を見せて
|
||||
Skill: 16 agents (12,400 tokens), 28 skills (6,200), 87 MCP tools (43,500), 2 CLAUDE.md (1,200)
|
||||
Flags: 重い agent 3 個、CLI 代用可能な MCP 3 個
|
||||
Top saving: MCP 3 個削除 → -27,500 tokens (overhead の 47% 削減)
|
||||
```
|
||||
|
||||
**Verbose**
|
||||
```
|
||||
User: トークン内訳をファイル単位で
|
||||
Skill: 上記レポートに加えて、planner.md (213 lines, 1,840 tokens) のような
|
||||
per-file 行内訳、MCP tool ごとのサイズ、rule の重複行を side-by-side で表示
|
||||
```
|
||||
|
||||
**追加前チェック**
|
||||
```
|
||||
User: MCP server を 5 個追加したいが、空きある?
|
||||
Skill: 現状 33% → 5 server (≈ 50 tools) 追加で +25,000 tokens → 45% に到達
|
||||
推奨: CLI 代用可能な server 2 個を先に外して 40% 以下を維持
|
||||
```
|
||||
|
||||
## ベストプラクティス
|
||||
|
||||
- **トークン推定**: prose は `words × 1.3`、code 主体は `chars / 4`
|
||||
- **MCP は最大のレバー**: tool あたり ~500 token、30-tool server ひとつで全 skill より大きい
|
||||
- **agent description は常時ロード**: 呼ばれない agent でも description は毎 Task 投入
|
||||
- **verbose は debug 用**: 普段は使わない
|
||||
- **変更後は監査**: agent/skill/MCP 追加直後に走らせて creep を早期発見
|
||||
|
||||
## Misskey 固有メモ
|
||||
|
||||
- Misskey は MCP server をプロジェクトで明示登録していないため (`.mcp.json` 不在)、現状 overhead の支配項は CLAUDE.md と公式プラグイン群の skills / agents description である。
|
||||
- ECC プラグインがユーザースコープで `installed_plugins.json` に存在するため、プロジェクトで `enabledPlugins` に追加していなくても system reminder に 200+ skill が現れる。これらは description が短いので個別 overhead は小さいが、合計値の確認に本 skill を使う。
|
||||
156
.claude/skills/create-migration/SKILL.md
Normal file
156
.claude/skills/create-migration/SKILL.md
Normal file
@@ -0,0 +1,156 @@
|
||||
---
|
||||
name: create-migration
|
||||
description: Misskey の TypeORM マイグレーションを公式 CLI (migration:generate / migration:create) で正しく生成し、SPDX ヘッダー付与・up/down 整合・check-migrations 確認まで誘導する。エンティティのスキーマ変更を含むあらゆる DB 変更、または手書き SQL によるデータ移行が必要な時に使用する。
|
||||
---
|
||||
|
||||
# Misskey マイグレーション作成スキル
|
||||
|
||||
`packages/backend/migration/` に新規 TypeORM マイグレーションを追加するためのワークフロー。
|
||||
|
||||
## 大前提 (絶対 NG)
|
||||
|
||||
- **既にマージ済み (develop / master) のマイグレーションファイルを編集しない** ([AGENTS.md §3](../../../AGENTS.md#3-マージ済み-migration-を絶対に編集しない))。本番履歴の改変は深刻なデータ不整合を引き起こす。スキーマ変更は **常に新しいタイムスタンプで新規ファイル** を作る。
|
||||
- ファイル名のタイムスタンプ部分を後から書き換えない (順序が壊れる)。
|
||||
|
||||
> 作り方は AGENTS.md §3 の「`Date.now()` で UNIX ms を取得 → `{ms}-{PascalName}.js` を手書き」が最低ライン。エンティティ差分から自動生成したい (= TypeORM の `migration:generate` を使う) 場合は本 skill の手順に従う。**どちらでも構わない**が、エンティティ変更を伴う時は CLI 経由のほうが取り漏れが減るので推奨。
|
||||
|
||||
## ステップ 1: どちらの方式を使うか決める
|
||||
|
||||
| 状況 | 方式 |
|
||||
|---|---|
|
||||
| エンティティ (`packages/backend/src/models/*.ts`) を `@Column` / `@Index` / `@Entity` 等で先に変更し、差分から自動生成したい | `typeorm migration:generate` (本 skill の手順) |
|
||||
| 手書き SQL / データ移行 / `CREATE INDEX CONCURRENTLY` など、エンティティ差分では表現できない変更 | `typeorm migration:create` で空雛形を作るか、`migrate-new` command で手書き雛形を作る |
|
||||
| 列追加 1 本のような小規模変更で、既存ファイルをコピーした方が速い | AGENTS.md §3 の手順 (`Date.now()` + 手書き) でよい |
|
||||
|
||||
迷ったら **まずエンティティを変更 → `migration:generate`** が原則。既存 342 ファイルのほぼすべてが `queryRunner.query(\`SQL...\`)` の raw SQL なので、CLI 出力でも手書きでもスタイルは揃う。
|
||||
|
||||
## ステップ 2: CLI 実行
|
||||
|
||||
ルートディレクトリから以下を実行する。`<PascalName>` は変更内容を表す PascalCase (例: `AddBirthdayIndex`, `AddCategoryToAvatarDecorations`)。
|
||||
|
||||
### 2-A. エンティティ差分から生成
|
||||
|
||||
[CONTRIBUTING.md §Migration作成方法](../../../CONTRIBUTING.md#migration作成方法) に記載の基本形:
|
||||
|
||||
```bash
|
||||
# packages/backend ディレクトリで実行する場合 (CONTRIBUTING.md 記載形式)
|
||||
pnpm dlx typeorm migration:generate -d ormconfig.js -o --esm <PascalName>
|
||||
```
|
||||
|
||||
**リポジトリルートから実行する場合** (AI が使う推奨形式。`pnpm --filter backend exec` を使うと backend の TypeORM バージョンと一致するため確実):
|
||||
|
||||
```bash
|
||||
pnpm --filter backend exec typeorm migration:generate -d ormconfig.js -o --esm migration/<PascalName>
|
||||
```
|
||||
|
||||
> **`--esm` について**: `-o` / `--outputJs` は「TS ではなく JS を出力する」オプション、`--esm` は「ESM 形式 (`export class ...`) で出力する」オプション。Misskey の既存 migration はすべて ESM JS であるため **両方が必須**。`--esm` を省略すると CommonJS 形式の JS が生成されスタイルが揃わない。
|
||||
|
||||
事前準備:
|
||||
|
||||
- `pnpm build-pre` を実行して `built/meta.json` を生成する (`loadConfig()` が `built/meta.json` を必須とするため。`pnpm build` 済みであれば不要)。
|
||||
- `.config/default.yml` が存在すること (なければ `.config/example.yml` を参考に作成する)。
|
||||
- `pnpm --filter backend compile-config` を実行して `built/.config.json` を生成する (`ormconfig.js` が `loadConfig()` 経由で必須とする。未実行だと "Compiled configuration file not found." エラーになる)。
|
||||
- `pnpm --filter backend build` でエンティティを最新ビルド (CLI は `built/` を読む)。
|
||||
- ローカル DB を起動する (`docker compose -f compose.local-db.yml up -d`)。
|
||||
|
||||
### 2-B. 空の手書きマイグレーション
|
||||
|
||||
```bash
|
||||
pnpm --filter backend exec typeorm migration:create -o --esm migration/<PascalName>
|
||||
```
|
||||
|
||||
ローカル DB の起動とビルドは不要。空の `up` / `down` だけが生成される。
|
||||
|
||||
> `-o --esm` を **必ず付ける**。これが無いと `<UnixMs>-<PascalName>.ts` (CommonJS / TS 出力) が生成されるが、Misskey の `ormconfig.js` は `migration/*.js` だけを読み、既存の他 migration も全て `export class ... { async up(queryRunner) {...} }` の ESM JS 形式なので、後で手作業で `.ts → .js` リネーム + `import { MigrationInterface }` 削除 + `class ... implements MigrationInterface` 削除をしないと走らない。`-o --esm` を付ければそのまま `.js` ESM で出るので、後処理は SPDX ヘッダー付与 (ステップ 3) だけで済む。
|
||||
|
||||
## ステップ 3: SPDX ヘッダー付与
|
||||
|
||||
CLI 出力には SPDX ヘッダーが含まれない。**必ず冒頭に追加する** (CI の `spdx` ジョブが失敗するため)。
|
||||
|
||||
```js
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
```
|
||||
|
||||
## ステップ 4: up / down の整合確認
|
||||
|
||||
- `up()` の各ステートメントに対し、`down()` で完全に巻き戻せること。
|
||||
- 列追加 (`ADD COLUMN`) ↔ 列削除 (`DROP COLUMN`)、テーブル作成 ↔ テーブル削除、
|
||||
FK 追加 ↔ FK 削除、インデックス作成 ↔ インデックス削除 を必ずペアで書く。
|
||||
- `down()` を空のまま残さない。本番ロールバック時に詰む。
|
||||
|
||||
### インデックス追加時の注意 (CREATE INDEX CONCURRENTLY)
|
||||
|
||||
大規模テーブルへの `CREATE INDEX` は本番で長時間ロックする恐れがある。`CONCURRENTLY` で発行するときは **migration 側にも対応が必要**: PostgreSQL は `CREATE INDEX CONCURRENTLY` を transaction 内で実行できないため、migration class に以下を仕込んで TypeORM に「この migration は transaction を張らない」と指示する。
|
||||
|
||||
参照実装: [packages/backend/migration/1745378064470-composite-note-index.js](../../../packages/backend/migration/1745378064470-composite-note-index.js)。
|
||||
|
||||
```js
|
||||
const isConcurrentIndexMigrationEnabled = process.env.MISSKEY_MIGRATION_CREATE_INDEX_CONCURRENTLY === '1';
|
||||
|
||||
export class CompositeNoteIndex1745378064470 {
|
||||
name = 'CompositeNoteIndex1745378064470';
|
||||
transaction = isConcurrentIndexMigrationEnabled ? false : undefined;
|
||||
|
||||
async up(queryRunner) {
|
||||
const concurrently = isConcurrentIndexMigrationEnabled;
|
||||
if (concurrently) {
|
||||
// CREATE INDEX CONCURRENTLY ...
|
||||
} else {
|
||||
// CREATE INDEX ...
|
||||
}
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
// 同様に環境変数で分岐
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
要点:
|
||||
|
||||
- **`transaction = isConcurrentIndexMigrationEnabled ? false : undefined;`** が必須。これがないと `CREATE INDEX CONCURRENTLY` が transaction 内で実行されて `ERROR: CREATE INDEX CONCURRENTLY cannot run inside a transaction block` で失敗する。
|
||||
- 環境変数 `MISSKEY_MIGRATION_CREATE_INDEX_CONCURRENTLY=1` がデフォルト OFF。OFF のときは普通の `CREATE INDEX` (transaction 内) で動く必要がある。`up`/`down` 双方を環境変数で分岐させる。
|
||||
- `ormconfig.js` の `migrationsTransactionMode` は **環境変数で切り替わる**: `MISSKEY_MIGRATION_CREATE_INDEX_CONCURRENTLY=1` のときだけ `'each'` (各 migration が個別 transaction)、未設定時は `'all'` (全 migration を 1 つの transaction でラップ) ([ormconfig.js:19](../../../packages/backend/ormconfig.js#L19))。普段は `'all'` 前提なので、CONCURRENTLY を使う migration を書く時だけこのフラグの存在を意識すれば良い。
|
||||
|
||||
### 関連エンティティとの一致
|
||||
|
||||
`migration:generate` を使った場合、エンティティ側の `@Column` / `@Entity` 修正と DB スキーマが食い違うとビルド全体がズレる。生成後に該当エンティティと SQL の対応を目視確認すること。
|
||||
|
||||
## ステップ 5: 検証
|
||||
|
||||
ルートから実行:
|
||||
|
||||
```bash
|
||||
# 未反映の差分が無いか (新規 migration が生成すべき DDL を取り逃していないか)
|
||||
pnpm --filter backend check-migrations
|
||||
|
||||
# ローカル DB に適用
|
||||
pnpm migrate
|
||||
|
||||
# ロールバック (down が壊れていないか)
|
||||
pnpm revert
|
||||
|
||||
# 再適用 (順方向にもう一度通す)
|
||||
pnpm migrate
|
||||
```
|
||||
|
||||
`check-migrations` の実体は [scripts/check_migrations_clean.js](../../../packages/backend/scripts/check_migrations_clean.js)。TypeORM の `dataSource.driver.createSchemaBuilder().log()` で pending DDL を取得し、`upQueries` / `downQueries` のいずれかが残っていれば非ゼロ終了する。**順序検査ではなく**「エンティティと migration が同期しているか」の検査。
|
||||
|
||||
## ステップ 6: 既存ファイル参照テンプレ
|
||||
|
||||
新規ファイルを書くときは、変更パターンが近い既存ファイルを **必ずひとつ開いて並べて書く**。スタイルが激しくズレた PR は差し戻されやすい。
|
||||
|
||||
| パターン | 参照ファイル |
|
||||
|---|---|
|
||||
| インデックス追加 + 関数定義 | [packages/backend/migration/1767169026317-birthday-index.js](../../../packages/backend/migration/1767169026317-birthday-index.js) |
|
||||
| 列追加のみ | [packages/backend/migration/1766652173085-add-category-to-avatar-decorations.js](../../../packages/backend/migration/1766652173085-add-category-to-avatar-decorations.js) |
|
||||
| テーブル新規作成 + FK | [packages/backend/migration/1761569941833-add-channel-muting.js](../../../packages/backend/migration/1761569941833-add-channel-muting.js) |
|
||||
|
||||
クラス命名規則は **PascalCase 名 + 13 桁タイムスタンプ** (例: `class BirthdayIndex1767169026317`)。`name` プロパティもクラス名と同一文字列にする。
|
||||
|
||||
## ステップ 7: CHANGELOG (ユーザー影響がある場合)
|
||||
|
||||
スキーマ変更がユーザーに見える挙動を生む場合のみ、`CHANGELOG.md` の `## Unreleased` → `### Server` または `### General` に 1 行追加する ([AGENTS.md §CHANGELOG](../../../AGENTS.md#changelog) 参照)。内部リファクタや純粋なインデックス追加は不要。
|
||||
@@ -182,6 +182,9 @@ id: 'aidx'
|
||||
# Number of worker processes
|
||||
#clusterLimit: 1
|
||||
|
||||
# Number of threads of extra thread pool for CPU-intensive tasks (per worker)
|
||||
#threadPoolSize: 1
|
||||
|
||||
# Job concurrency per worker
|
||||
# deliverJobConcurrency: 128
|
||||
# inboxJobConcurrency: 16
|
||||
|
||||
@@ -194,6 +194,9 @@ id: 'aidx'
|
||||
# Number of worker processes
|
||||
#clusterLimit: 1
|
||||
|
||||
# Number of threads of extra thread pool for CPU-intensive tasks (per worker)
|
||||
#threadPoolSize: 1
|
||||
|
||||
# Job concurrency per worker
|
||||
# deliverJobConcurrency: 128
|
||||
# inboxJobConcurrency: 16
|
||||
|
||||
@@ -105,6 +105,54 @@ port: 3000
|
||||
# socket: /path/to/misskey.sock
|
||||
# chmodSocket: '777'
|
||||
|
||||
# Proxy trust settings
|
||||
#
|
||||
# Specifies the IP addresses that Misskey will use as trusted
|
||||
# reverse proxies (e.g., nginx, Cloudflare). This affects how
|
||||
# Misskey determines the source IP for each request and is used
|
||||
# for important rate limiting and security features. If the value
|
||||
# is not set correctly, Misskey may use the IP address of the
|
||||
# reverse proxy instead of the actual source IP, which may lead to
|
||||
# unintended rate limiting or security vulnerabilities.
|
||||
# By default, the loopback network and private network address
|
||||
# ranges shown below are trusted.
|
||||
# If you are using a single reverse proxy and it is on the same
|
||||
# machine or the same private network as Misskey, it is unlikely you
|
||||
# need to change this setting, and the default setting is fine.
|
||||
# Also, if you are using multiple reverse proxy servers and they are
|
||||
# all on the same private network as Misskey, the default setting
|
||||
# is fine.
|
||||
# However, if you are using a reverse proxy server that accesses
|
||||
# Misskey web servers and streaming servers via public IP addresses
|
||||
# (for example, Cloudflare), you must set this variable.
|
||||
# When changing this setting, you can use one of the following values:
|
||||
#
|
||||
# - true: Trust all proxies
|
||||
# - false: Do not trust any proxies
|
||||
# - IP address, IP address range, or array of them: Trust hops that
|
||||
# match the specified criteria.
|
||||
# - Integer: Trust the nth hop from the front-facing proxy server as
|
||||
# the client.
|
||||
# For more information on how to configure this setting, please refer
|
||||
# to the Fastify documentation:
|
||||
# https://fastify.dev/docs/latest/Reference/Server/#trustproxy
|
||||
#
|
||||
# Note that if this variable is set, it overrides the default range,
|
||||
# so if you have both an external reverse proxy and a proxy on the
|
||||
# local host, you must include both IPs (or IP ranges).
|
||||
#
|
||||
#trustProxy:
|
||||
# - '10.0.0.0/8'
|
||||
# - '172.16.0.0/12'
|
||||
# - '192.168.0.0/16'
|
||||
# - '127.0.0.1/32'
|
||||
# - '::1/128'
|
||||
# - 'fc00::/7'
|
||||
# # Example: If you are using some external reverse proxies like CDNs,
|
||||
# # you may need to add the CDN IP ranges here.
|
||||
# # If you're using Cloudflare, you can find IP Ranges at:
|
||||
# # https://www.cloudflare.com/ips/
|
||||
|
||||
# ┌──────────────────────────┐
|
||||
#───┘ PostgreSQL configuration └────────────────────────────────
|
||||
|
||||
@@ -273,9 +321,16 @@ id: 'aidx'
|
||||
# Whether disable HSTS
|
||||
#disableHsts: true
|
||||
|
||||
# Enable internal IP-based rate limiting (default: true)
|
||||
# To configure them in reverse proxy instead, set this to false.
|
||||
#enableIpRateLimit: true
|
||||
|
||||
# Number of worker processes
|
||||
#clusterLimit: 1
|
||||
|
||||
# Number of threads of extra thread pool for CPU-intensive tasks (per worker)
|
||||
#threadPoolSize: 1
|
||||
|
||||
# Job concurrency per worker
|
||||
#deliverJobConcurrency: 128
|
||||
#inboxJobConcurrency: 16
|
||||
|
||||
@@ -1 +1 @@
|
||||
FROM mcr.microsoft.com/devcontainers/javascript-node:0-18
|
||||
FROM mcr.microsoft.com/devcontainers/javascript-node:4.0.3-24-trixie
|
||||
|
||||
@@ -28,7 +28,7 @@ services:
|
||||
|
||||
db:
|
||||
restart: unless-stopped
|
||||
image: postgres:15-alpine
|
||||
image: postgres:18-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
environment:
|
||||
@@ -36,7 +36,7 @@ services:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: misskey
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
- postgres-data:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
||||
interval: 5s
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"Vue.volar",
|
||||
"Orta.vscode-jest",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"mrmlnc.vscode-json5"
|
||||
]
|
||||
|
||||
@@ -169,6 +169,9 @@ id: 'aidx'
|
||||
# Number of worker processes
|
||||
#clusterLimit: 1
|
||||
|
||||
# Number of threads of extra thread pool for CPU-intensive tasks (per worker)
|
||||
#threadPoolSize: 1
|
||||
|
||||
# Job concurrency per worker
|
||||
# deliverJobConcurrency: 128
|
||||
# inboxJobConcurrency: 16
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
Dockerfile
|
||||
build/
|
||||
built/
|
||||
src-js/
|
||||
db/
|
||||
.devcontainer/compose.yml
|
||||
node_modules/
|
||||
|
||||
@@ -13,3 +13,7 @@ trim_trailing_whitespace = false
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_style = space
|
||||
|
||||
[packages/backend/migration/*.js]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
6
.github/ISSUE_TEMPLATE/01_bug-report.yml
vendored
6
.github/ISSUE_TEMPLATE/01_bug-report.yml
vendored
@@ -54,7 +54,7 @@ body:
|
||||
* Model and OS of the device(s): MacBook Pro (14inch, 2021), macOS Ventura 13.4
|
||||
* Browser: Chrome 113.0.5672.126
|
||||
* Server URL: misskey.example.com
|
||||
* Misskey: 2025.x.x
|
||||
* Misskey: 2026.x.x
|
||||
value: |
|
||||
* Model and OS of the device(s):
|
||||
* Browser:
|
||||
@@ -74,9 +74,9 @@ body:
|
||||
|
||||
Examples:
|
||||
* Installation Method or Hosting Service: docker compose, k8s/docker, systemd, "Misskey install shell script", development environment
|
||||
* Misskey: 2025.x.x
|
||||
* Misskey: 2026.x.x
|
||||
* Node: 20.x.x
|
||||
* PostgreSQL: 15.x.x
|
||||
* PostgreSQL: 18.x.x
|
||||
* Redis: 7.x.x
|
||||
* OS and Architecture: Ubuntu 24.04.2 LTS aarch64
|
||||
value: |
|
||||
|
||||
54
.github/copilot-instructions.md
vendored
Normal file
54
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
# Copilot Instructions for Misskey
|
||||
|
||||
このファイルは GitHub Copilot の repository-wide instructions として使われる。Copilot code review では `AGENTS.md` が読まれない環境があるため、レビューや軽微な実装判断に必要な規約はこのファイル単体で満たすこと。
|
||||
|
||||
このリポジトリは Misskey の pnpm workspace モノレポ。主要な実装は `packages/backend` (NestJS / TypeORM) と `packages/frontend` (Vue 3) にある。より詳しいガイドはリポジトリルートの `AGENTS.md` を参照してよいが、このファイルの要件を省略してそちらへの参照だけで済ませないこと。
|
||||
|
||||
## Always follow
|
||||
|
||||
- AGPL-3.0-only 管轄かつ SPDX CI 対象ディレクトリに新規 `.ts` / `.js` / `.cjs` / `.mjs` / `.scss` ファイルを追加する場合は、必ず次の SPDX ヘッダーを付ける。詳細な対象判定は `AGENTS.md` と `.github/workflows/check-spdx-license-id.yml` を参照すること。
|
||||
|
||||
```text
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
```
|
||||
|
||||
- AGPL-3.0-only 管轄かつ SPDX CI 対象ディレクトリに新規 `.vue` / `.html` ファイルを追加する場合は、必ず次の SPDX ヘッダーを付ける。
|
||||
|
||||
```text
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
```
|
||||
|
||||
`packages/misskey-js` は MIT ライセンスのサブパッケージなので、この AGPL ヘッダーを一律に付けない。サブパッケージ固有の `package.json` / `LICENSE` / 既存ファイルのヘッダーに従う。
|
||||
|
||||
- `locales/` 配下の YAML は `ja-JP.yml` のみ手動編集してよい。他言語は Crowdin の自動配信先なので手動編集しないこと。
|
||||
- `packages/backend/migration/{timestamp}-*.js` のうち、既にマージ済みの migration は絶対に編集しない。スキーマ変更が必要な場合は新しい timestamp で migration を追加し、`up()` と `down()` の両方を実装すること。
|
||||
- ユーザー影響のある変更は `CHANGELOG.md` の `## Unreleased` 配下の `### General` / `### Client` / `### Server` のいずれかに 1 行追加する。内部リファクタのみなら不要。
|
||||
- API 変更時は `pnpm build-misskey-js-with-types` の実行が必要になる。
|
||||
|
||||
## Validation
|
||||
|
||||
- 全体ビルド: `pnpm build`
|
||||
- 全体 lint / typecheck: `pnpm lint`
|
||||
- Backend unit test: `pnpm --filter backend test`
|
||||
- Backend e2e test: `pnpm --filter backend test:e2e`
|
||||
- Backend federation test: `pnpm --filter backend test:fed`
|
||||
- Frontend test: `pnpm --filter frontend test`
|
||||
- Migration 差分検査: `pnpm --filter backend check-migrations`
|
||||
|
||||
> **backend テスト (`test` / `test:e2e` / `test:fed`) 実行前に `.config/test.yml` が必要。** 未作成の場合は `ncp .github/misskey/test.yml .config/test.yml` (または `cp .github/misskey/test.yml .config/test.yml`) を実行してから走らせる。各テストスクリプトが内部で `cross-env NODE_ENV=test pnpm compile-config` を呼ぶため、コピー済みであれば追加の compile-config は不要。
|
||||
|
||||
変更範囲に応じて最も近いコマンドから優先して検証し、必要なら全体コマンドに広げること。
|
||||
|
||||
## Editing hints
|
||||
|
||||
- Backend の API / migration / TypeORM 変更は `packages/backend` を見る。
|
||||
- Frontend の Vue コンポーネントやページ変更は `packages/frontend` を見る。
|
||||
- `AGENTS.md` 内の相対リンクはリポジトリルート起点で解決する想定。
|
||||
|
||||
> `AGENTS.md` はより詳細な正典だが、Copilot code review ではこのファイルが主な入口になる。両方が読まれる環境では `AGENTS.md` を補助情報として使ってよい。
|
||||
3
.github/dependabot.yml
vendored
3
.github/dependabot.yml
vendored
@@ -34,9 +34,6 @@ updates:
|
||||
patterns:
|
||||
- "storybook*"
|
||||
- "@storybook/*"
|
||||
swc-core:
|
||||
patterns:
|
||||
- "@swc/core*"
|
||||
typescript-eslint:
|
||||
patterns:
|
||||
- "@typescript-eslint/*"
|
||||
|
||||
2
.github/min.node-version
vendored
2
.github/min.node-version
vendored
@@ -1 +1 @@
|
||||
20.10.0
|
||||
22.15.0
|
||||
|
||||
2
.github/misskey/test.yml
vendored
2
.github/misskey/test.yml
vendored
@@ -15,3 +15,5 @@ redis:
|
||||
host: 127.0.0.1
|
||||
port: 56312
|
||||
id: aidx
|
||||
|
||||
proxyRemoteFiles: true
|
||||
|
||||
6
.github/workflows/api-misskey-js.yml
vendored
6
.github/workflows/api-misskey-js.yml
vendored
@@ -16,13 +16,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v6.0.2
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
4
.github/workflows/changelog-check.yml
vendored
4
.github/workflows/changelog-check.yml
vendored
@@ -12,9 +12,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout head
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v6.0.2
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
|
||||
|
||||
24
.github/workflows/check-misskey-js-autogen.yml
vendored
24
.github/workflows/check-misskey-js-autogen.yml
vendored
@@ -18,18 +18,18 @@ jobs:
|
||||
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
|
||||
- name: setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
uses: pnpm/action-setup@v6
|
||||
|
||||
- name: setup node
|
||||
id: setup-node
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: pnpm
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
|
||||
# packages/misskey-js/generator/built/autogen
|
||||
- name: Upload Generated
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: generated-misskey-js
|
||||
path: packages/misskey-js/generator/built/autogen
|
||||
@@ -66,14 +66,14 @@ jobs:
|
||||
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
|
||||
- name: Upload From Merged
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: actual-misskey-js
|
||||
path: packages/misskey-js/src/autogen
|
||||
@@ -86,13 +86,13 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: download generated-misskey-js
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: generated-misskey-js
|
||||
path: misskey-js-generated
|
||||
|
||||
- name: download actual-misskey-js
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: actual-misskey-js
|
||||
path: misskey-js-actual
|
||||
@@ -113,9 +113,9 @@ jobs:
|
||||
|
||||
- name: send message
|
||||
if: steps.check-changes.outputs.changes == 'true'
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
comment_tag: check-misskey-js-autogen
|
||||
comment-tag: check-misskey-js-autogen
|
||||
message: |-
|
||||
Thank you for sending us a great Pull Request! 👍
|
||||
Please regenerate misskey-js type definitions! 🙏
|
||||
@@ -127,9 +127,9 @@ jobs:
|
||||
|
||||
- name: send message
|
||||
if: steps.check-changes.outputs.changes == 'false'
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
comment_tag: check-misskey-js-autogen
|
||||
comment-tag: check-misskey-js-autogen
|
||||
mode: delete
|
||||
message: "Thank you!"
|
||||
create_if_not_exists: false
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v6.0.2
|
||||
- name: Check version
|
||||
run: |
|
||||
if [ "$(jq -r '.version' package.json)" != "$(jq -r '.version' packages/misskey-js/package.json)" ]; then
|
||||
|
||||
3
.github/workflows/check-spdx-license-id.yml
vendored
3
.github/workflows/check-spdx-license-id.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v6.0.2
|
||||
- name: Check
|
||||
run: |
|
||||
counter=0
|
||||
@@ -50,6 +50,7 @@ jobs:
|
||||
"packages/backend/test"
|
||||
"packages/frontend-shared/@types"
|
||||
"packages/frontend-shared/js"
|
||||
"packages/frontend-builder"
|
||||
"packages/frontend/.storybook"
|
||||
"packages/frontend/@types"
|
||||
"packages/frontend/lib"
|
||||
|
||||
2
.github/workflows/check_copyright_year.yml
vendored
2
.github/workflows/check_copyright_year.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
check_copyright_year:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- run: |
|
||||
if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then
|
||||
echo "Please change copyright year!"
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
wait_time: ${{ steps.get-wait-time.outputs.wait_time }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v6.0.2
|
||||
|
||||
- name: Check allowed users
|
||||
id: check-allowed-users
|
||||
|
||||
16
.github/workflows/docker-develop.yml
vendored
16
.github/workflows/docker-develop.yml
vendored
@@ -27,17 +27,17 @@ jobs:
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v6.0.2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build and push by digest
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
@@ -66,15 +66,15 @@ jobs:
|
||||
- build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
20
.github/workflows/docker.yml
vendored
20
.github/workflows/docker.yml
vendored
@@ -32,23 +32,23 @@ jobs:
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v6.0.2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
tags: ${{ env.TAGS }}
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build and Push to Docker Hub
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
@@ -77,21 +77,21 @@ jobs:
|
||||
- build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@v6
|
||||
with:
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
tags: ${{ env.TAGS }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
45
.github/workflows/dockle.yml
vendored
45
.github/workflows/dockle.yml
vendored
@@ -11,22 +11,43 @@ on:
|
||||
jobs:
|
||||
dockle:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
DOCKER_CONTENT_TRUST: 1
|
||||
DOCKLE_VERSION: 0.4.14
|
||||
DOCKLE_VERSION: 0.4.15
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
|
||||
- name: Download and install dockle v${{ env.DOCKLE_VERSION }}
|
||||
run: |
|
||||
set -eux
|
||||
curl -L -o dockle.deb "https://github.com/goodwithtech/dockle/releases/download/v${DOCKLE_VERSION}/dockle_${DOCKLE_VERSION}_Linux-64bit.deb"
|
||||
sudo dpkg -i dockle.deb
|
||||
- run: |
|
||||
cp .config/docker_example.env .config/docker.env
|
||||
cp ./compose_example.yml ./compose.yml
|
||||
- run: |
|
||||
docker compose up -d web
|
||||
docker tag "$(docker compose images web | awk 'OFS=":" {print $4}' | tail -n +2)" misskey-web:latest
|
||||
- run: |
|
||||
cmd="dockle --exit-code 1 misskey-web:latest ${image_name}"
|
||||
echo "> ${cmd}"
|
||||
eval "${cmd}"
|
||||
|
||||
- name: Build web image (docker build)
|
||||
run: |
|
||||
set -eux
|
||||
docker build -t "misskey-web:ci" .
|
||||
docker image ls
|
||||
|
||||
- name: Mount tmpfs for Dockle tar
|
||||
env:
|
||||
TMPFS_SIZE: 8G
|
||||
run: |
|
||||
set -eux
|
||||
sudo mkdir -p /mnt/dockle-tmp
|
||||
sudo mount -t tmpfs -o size=${{ env.TMPFS_SIZE }} tmpfs /mnt/dockle-tmp
|
||||
free -h
|
||||
df -h
|
||||
|
||||
- name: Save image tar into tmpfs
|
||||
run: |
|
||||
set -eux
|
||||
docker save misskey-web:ci -o /mnt/dockle-tmp/misskey-web.tar
|
||||
ls -lh /mnt/dockle-tmp/misskey-web.tar
|
||||
|
||||
- name: Run Dockle Scan (tar input)
|
||||
run: |
|
||||
set -eux
|
||||
dockle --exit-code 1 --input /mnt/dockle-tmp/misskey-web.tar
|
||||
|
||||
10
.github/workflows/get-api-diff.yml
vendored
10
.github/workflows/get-api-diff.yml
vendored
@@ -25,14 +25,14 @@ jobs:
|
||||
ref: refs/pull/${{ github.event.number }}/merge
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
ref: ${{ matrix.ref }}
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
- name: Copy API.json
|
||||
run: cp packages/backend/built/api.json ${{ matrix.api-json-name }}
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: api-artifact-${{ matrix.api-json-name }}
|
||||
path: ${{ matrix.api-json-name }}
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
PR_NUMBER: ${{ github.event.number }}
|
||||
run: |
|
||||
echo "$PR_NUMBER" > ./pr_number
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: api-artifact-pr-number
|
||||
path: pr_number
|
||||
|
||||
87
.github/workflows/get-backend-memory.yml
vendored
Normal file
87
.github/workflows/get-backend-memory.yml
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
# this name is used in report-backend-memory.yml so be careful when change name
|
||||
name: Get backend memory usage
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
paths:
|
||||
- packages/backend/**
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/get-backend-memory.yml
|
||||
|
||||
jobs:
|
||||
get-memory-usage:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
memory-json-name: [memory-base.json, memory-head.json]
|
||||
include:
|
||||
- memory-json-name: memory-base.json
|
||||
ref: ${{ github.base_ref }}
|
||||
- memory-json-name: memory-head.json
|
||||
ref: refs/pull/${{ github.event.number }}/merge
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:8
|
||||
ports:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
ref: ${{ matrix.ref }}
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Copy Configure
|
||||
run: cp .github/misskey/test.yml .config/default.yml
|
||||
- name: Compile Configure
|
||||
run: pnpm compile-config
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Run migrations
|
||||
run: pnpm --filter backend migrate
|
||||
- name: Measure memory usage
|
||||
run: |
|
||||
# Start the server and measure memory usage
|
||||
node packages/backend/scripts/measure-memory.mjs > ${{ matrix.memory-json-name }}
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: memory-artifact-${{ matrix.memory-json-name }}
|
||||
path: ${{ matrix.memory-json-name }}
|
||||
|
||||
save-pr-number:
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
steps:
|
||||
- name: Save PR number
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.number }}
|
||||
run: |
|
||||
echo "$PR_NUMBER" > ./pr_number
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: memory-artifact-pr-number
|
||||
path: pr_number
|
||||
2
.github/workflows/labeler.yml
vendored
2
.github/workflows/labeler.yml
vendored
@@ -11,6 +11,6 @@ jobs:
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v5
|
||||
- uses: actions/labeler@v6
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
29
.github/workflows/lint.yml
vendored
29
.github/workflows/lint.yml
vendored
@@ -9,6 +9,7 @@ on:
|
||||
- packages/backend/**
|
||||
- packages/frontend/**
|
||||
- packages/frontend-shared/**
|
||||
- packages/frontend-builder/**
|
||||
- packages/frontend-embed/**
|
||||
- packages/icons-subsetter/**
|
||||
- packages/sw/**
|
||||
@@ -22,6 +23,7 @@ on:
|
||||
- packages/backend/**
|
||||
- packages/frontend/**
|
||||
- packages/frontend-shared/**
|
||||
- packages/frontend-builder/**
|
||||
- packages/frontend-embed/**
|
||||
- packages/icons-subsetter/**
|
||||
- packages/sw/**
|
||||
@@ -34,13 +36,13 @@ jobs:
|
||||
pnpm_install:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- uses: actions/setup-node@v4.4.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
@@ -56,6 +58,7 @@ jobs:
|
||||
- backend
|
||||
- frontend
|
||||
- frontend-shared
|
||||
- frontend-builder
|
||||
- frontend-embed
|
||||
- icons-subsetter
|
||||
- sw
|
||||
@@ -66,19 +69,19 @@ jobs:
|
||||
eslint-cache-version: v1
|
||||
eslint-cache-path: ${{ github.workspace }}/node_modules/.cache/eslint-${{ matrix.workspace }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- uses: actions/setup-node@v4.4.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Restore eslint cache
|
||||
uses: actions/cache@v4.2.3
|
||||
uses: actions/cache@v5.0.5
|
||||
with:
|
||||
path: ${{ env.eslint-cache-path }}
|
||||
key: eslint-${{ env.eslint-cache-version }}-${{ matrix.workspace }}-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ github.ref_name }}-${{ github.sha }}
|
||||
@@ -93,22 +96,20 @@ jobs:
|
||||
matrix:
|
||||
workspace:
|
||||
- backend
|
||||
- frontend
|
||||
- sw
|
||||
- misskey-js
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- uses: actions/setup-node@v4.4.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- run: pnpm --filter misskey-js run build
|
||||
if: ${{ matrix.workspace == 'backend' || matrix.workspace == 'sw' }}
|
||||
- run: pnpm --filter misskey-reversi run build
|
||||
if: ${{ matrix.workspace == 'backend' }}
|
||||
- run: pnpm --filter "${{ matrix.workspace }}^..." run build
|
||||
- run: pnpm --filter ${{ matrix.workspace }} run typecheck
|
||||
|
||||
29
.github/workflows/locale.yml
vendored
29
.github/workflows/locale.yml
vendored
@@ -3,10 +3,12 @@ name: Lint
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- packages/i18n/**
|
||||
- locales/**
|
||||
- .github/workflows/locale.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/i18n/**
|
||||
- locales/**
|
||||
- .github/workflows/locale.yml
|
||||
jobs:
|
||||
@@ -14,15 +16,18 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- uses: actions/setup-node@v4.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- run: cd locales && node verify.js
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: ".node-version"
|
||||
cache: "pnpm"
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- run: pnpm --filter i18n build
|
||||
- name: Verify Locales
|
||||
working-directory: ./packages/i18n
|
||||
run: pnpm run verify
|
||||
|
||||
9
.github/workflows/on-release-created.yml
vendored
9
.github/workflows/on-release-created.yml
vendored
@@ -16,18 +16,21 @@ jobs:
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
# see https://docs.github.com/actions/use-cases-and-examples/publishing-packages/publishing-nodejs-packages#publishing-packages-to-the-npm-registry
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
# Ensure npm 11.5.1 or later is installed
|
||||
- name: Update npm
|
||||
run: npm install -g npm@latest
|
||||
- name: Publish package
|
||||
run: |
|
||||
pnpm i --frozen-lockfile
|
||||
|
||||
2
.github/workflows/release-edit-with-push.yml
vendored
2
.github/workflows/release-edit-with-push.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
edit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
# headが$GITHUB_REF_NAME, baseが$STABLE_BRANCHかつopenのPRを1つ取得
|
||||
- name: Get PR
|
||||
run: |
|
||||
|
||||
2
.github/workflows/release-with-dispatch.yml
vendored
2
.github/workflows/release-with-dispatch.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
outputs:
|
||||
pr_number: ${{ steps.get_pr.outputs.pr_number }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
# headが$GITHUB_REF_NAME, baseが$STABLE_BRANCHかつopenのPRを1つ取得
|
||||
- name: Get PRs
|
||||
run: |
|
||||
|
||||
24
.github/workflows/report-api-diff.yml
vendored
24
.github/workflows/report-api-diff.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
# api-artifact
|
||||
steps:
|
||||
- name: Download artifact
|
||||
uses: actions/github-script@v7.0.1
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
- name: Echo full diff
|
||||
run: cat ./api-full.json.diff
|
||||
- name: Upload full diff to Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: api-artifact
|
||||
path: |
|
||||
@@ -73,9 +73,9 @@ jobs:
|
||||
HEADER="このPRによるapi.jsonの差分"
|
||||
FOOTER="[Get diff files from Workflow Page](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})"
|
||||
DIFF_BYTES="$(stat ./api.json.diff -c '%s' | tr -d '\n')"
|
||||
|
||||
|
||||
echo "$HEADER" > ./output.md
|
||||
|
||||
|
||||
if (( "$DIFF_BYTES" <= 1 )); then
|
||||
echo '差分はありません。' >> ./output.md
|
||||
else
|
||||
@@ -87,18 +87,18 @@ jobs:
|
||||
echo '```' >> ./output.md
|
||||
echo '</details>' >> .output.md
|
||||
fi
|
||||
|
||||
|
||||
echo "$FOOTER" >> ./output.md
|
||||
- uses: thollander/actions-comment-pull-request@v2
|
||||
- uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
pr_number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment_tag: show_diff
|
||||
filePath: ./output.md
|
||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment-tag: show_diff
|
||||
file-path: ./output.md
|
||||
- name: Tell error to PR
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
if: failure() && steps.load-pr-num.outputs.pr-number
|
||||
with:
|
||||
pr_number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment_tag: show_diff_error
|
||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment-tag: show_diff_error
|
||||
message: |
|
||||
api.jsonの差分作成中にエラーが発生しました。詳細は[Workflowのログ](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})を確認してください。
|
||||
|
||||
177
.github/workflows/report-backend-memory.yml
vendored
Normal file
177
.github/workflows/report-backend-memory.yml
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
name: Report backend memory
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
types: [completed]
|
||||
workflows:
|
||||
- Get backend memory usage # get-backend-memory.yml
|
||||
|
||||
jobs:
|
||||
compare-memory:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Download artifact
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: context.payload.workflow_run.id,
|
||||
});
|
||||
let matchArtifacts = allArtifacts.data.artifacts.filter((artifact) => {
|
||||
return artifact.name.startsWith("memory-artifact-") || artifact.name == "memory-artifact"
|
||||
});
|
||||
await Promise.all(matchArtifacts.map(async (artifact) => {
|
||||
let download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: artifact.id,
|
||||
archive_format: 'zip',
|
||||
});
|
||||
await fs.promises.writeFile(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data));
|
||||
}));
|
||||
- name: Extract all artifacts
|
||||
run: |
|
||||
find . -mindepth 1 -maxdepth 1 -type f -name '*.zip' -exec unzip {} -d artifacts ';'
|
||||
ls -la artifacts/
|
||||
- name: Load PR Number
|
||||
id: load-pr-num
|
||||
run: echo "pr-number=$(cat artifacts/pr_number)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Output base
|
||||
run: cat ./artifacts/memory-base.json
|
||||
- name: Output head
|
||||
run: cat ./artifacts/memory-head.json
|
||||
- name: Compare memory usage
|
||||
id: compare
|
||||
run: |
|
||||
BASE_MEMORY=$(cat ./artifacts/memory-base.json)
|
||||
HEAD_MEMORY=$(cat ./artifacts/memory-head.json)
|
||||
|
||||
variation() {
|
||||
calc() {
|
||||
BASE=$(echo "$BASE_MEMORY" | jq -r ".${1}.${2} // 0")
|
||||
HEAD=$(echo "$HEAD_MEMORY" | jq -r ".${1}.${2} // 0")
|
||||
|
||||
DIFF=$((HEAD - BASE))
|
||||
if [ "$BASE" -gt 0 ]; then
|
||||
DIFF_PERCENT=$(echo "scale=2; ($DIFF * 100) / $BASE" | bc)
|
||||
else
|
||||
DIFF_PERCENT=0
|
||||
fi
|
||||
|
||||
# Convert KB to MB for readability
|
||||
BASE_MB=$(echo "scale=2; $BASE / 1024" | bc)
|
||||
HEAD_MB=$(echo "scale=2; $HEAD / 1024" | bc)
|
||||
DIFF_MB=$(echo "scale=2; $DIFF / 1024" | bc)
|
||||
|
||||
JSON=$(jq -c -n \
|
||||
--argjson base "$BASE_MB" \
|
||||
--argjson head "$HEAD_MB" \
|
||||
--argjson diff "$DIFF_MB" \
|
||||
--argjson diff_percent "$DIFF_PERCENT" \
|
||||
'{base: $base, head: $head, diff: $diff, diff_percent: $diff_percent}')
|
||||
|
||||
echo "$JSON"
|
||||
}
|
||||
|
||||
JSON=$(jq -c -n \
|
||||
--argjson VmRSS "$(calc $1 VmRSS)" \
|
||||
--argjson VmHWM "$(calc $1 VmHWM)" \
|
||||
--argjson VmSize "$(calc $1 VmSize)" \
|
||||
--argjson VmData "$(calc $1 VmData)" \
|
||||
'{VmRSS: $VmRSS, VmHWM: $VmHWM, VmSize: $VmSize, VmData: $VmData}')
|
||||
|
||||
echo "$JSON"
|
||||
}
|
||||
|
||||
JSON=$(jq -c -n \
|
||||
--argjson beforeGc "$(variation beforeGc)" \
|
||||
--argjson afterGc "$(variation afterGc)" \
|
||||
--argjson afterRequest "$(variation afterRequest)" \
|
||||
'{beforeGc: $beforeGc, afterGc: $afterGc, afterRequest: $afterRequest}')
|
||||
|
||||
echo "res=$JSON" >> "$GITHUB_OUTPUT"
|
||||
- id: build-comment
|
||||
name: Build memory comment
|
||||
env:
|
||||
RES: ${{ steps.compare.outputs.res }}
|
||||
run: |
|
||||
HEADER="## Backend memory usage comparison"
|
||||
FOOTER="[See workflow logs for details](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})"
|
||||
|
||||
echo "$HEADER" > ./output.md
|
||||
echo >> ./output.md
|
||||
|
||||
table() {
|
||||
echo "| Metric | base (MB) | head (MB) | Diff (MB) | Diff (%) |" >> ./output.md
|
||||
echo "|--------|------:|------:|------:|------:|" >> ./output.md
|
||||
|
||||
line() {
|
||||
METRIC=$2
|
||||
BASE=$(echo "$RES" | jq -r ".${1}.${2}.base")
|
||||
HEAD=$(echo "$RES" | jq -r ".${1}.${2}.head")
|
||||
DIFF=$(echo "$RES" | jq -r ".${1}.${2}.diff")
|
||||
DIFF_PERCENT=$(echo "$RES" | jq -r ".${1}.${2}.diff_percent")
|
||||
|
||||
if (( $(echo "$DIFF_PERCENT > 0" | bc -l) )); then
|
||||
DIFF="+$DIFF"
|
||||
DIFF_PERCENT="+$DIFF_PERCENT"
|
||||
fi
|
||||
|
||||
# highlight VmRSS
|
||||
if [ "$2" = "VmRSS" ]; then
|
||||
METRIC="**${METRIC}**"
|
||||
BASE="**${BASE}**"
|
||||
HEAD="**${HEAD}**"
|
||||
DIFF="**${DIFF}**"
|
||||
DIFF_PERCENT="**${DIFF_PERCENT}**"
|
||||
fi
|
||||
|
||||
echo "| ${METRIC} | ${BASE} MB | ${HEAD} MB | ${DIFF} MB | ${DIFF_PERCENT}% |" >> ./output.md
|
||||
}
|
||||
|
||||
line $1 VmRSS
|
||||
line $1 VmHWM
|
||||
line $1 VmSize
|
||||
line $1 VmData
|
||||
}
|
||||
|
||||
echo "### Before GC" >> ./output.md
|
||||
table beforeGc
|
||||
echo >> ./output.md
|
||||
|
||||
echo "### After GC" >> ./output.md
|
||||
table afterGc
|
||||
echo >> ./output.md
|
||||
|
||||
echo "### After Request" >> ./output.md
|
||||
table afterRequest
|
||||
echo >> ./output.md
|
||||
|
||||
# Determine if this is a significant change (more than 5% increase)
|
||||
if [ "$(echo "$RES" | jq -r '.afterGc.VmRSS.diff_percent | tonumber > 5')" = "true" ]; then
|
||||
echo "⚠️ **Warning**: Memory usage has increased by more than 5%. Please verify this is not an unintended change." >> ./output.md
|
||||
echo >> ./output.md
|
||||
fi
|
||||
|
||||
echo "$FOOTER" >> ./output.md
|
||||
- uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment-tag: show_memory_diff
|
||||
file-path: ./output.md
|
||||
- name: Tell error to PR
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
if: failure() && steps.load-pr-num.outputs.pr-number
|
||||
with:
|
||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment-tag: show_memory_diff_error
|
||||
message: |
|
||||
An error occurred while comparing backend memory usage. See [workflow logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.
|
||||
51
.github/workflows/request-release-review.yml
vendored
Normal file
51
.github/workflows/request-release-review.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Request release review
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
reply:
|
||||
if: github.event.comment.body == '/request-release-review'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Reply
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
const body = `To dev team (@misskey-dev/dev):
|
||||
|
||||
リリースが提案されています :rocket:
|
||||
|
||||
GOの場合はapprove、NO GOの場合はその旨コメントをお願いいたします。
|
||||
|
||||
判断にあたって考慮すべき観点は、
|
||||
|
||||
- やり残したことはないか?
|
||||
- CHANGELOGは過不足ないか?
|
||||
- バージョンに問題はないか?(月跨いでいるのに更新忘れているなど)
|
||||
- 再考すべき仕様・実装はないか?
|
||||
- ベータ版を検証したサーバーから不具合の報告等は上がってないか?
|
||||
- (セキュリティの修正や重要なバグ修正などのため)リリースを急いだ方が良いか?そうではないか?
|
||||
- Actionsが落ちていないか?
|
||||
|
||||
などが挙げられます。
|
||||
|
||||
ご協力ありがとうございます :sparkles:
|
||||
`
|
||||
|
||||
const issue_number = context.payload.issue ? context.payload.issue.number : (context.payload.pull_request && context.payload.pull_request.number)
|
||||
if (!issue_number) {
|
||||
console.log('No issue or PR number found in payload; skipping')
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number,
|
||||
body,
|
||||
})
|
||||
}
|
||||
12
.github/workflows/storybook.yml
vendored
12
.github/workflows/storybook.yml
vendored
@@ -22,12 +22,12 @@ jobs:
|
||||
NODE_OPTIONS: "--max_old_space_size=7168"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
if: github.event_name != 'pull_request_target'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
if: github.event_name == 'pull_request_target'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
@@ -37,9 +37,9 @@ jobs:
|
||||
if: github.event_name == 'pull_request_target'
|
||||
run: git checkout "$(git rev-list --parents -n1 HEAD | cut -d" " -f3)"
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
env:
|
||||
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||
- name: Notify that Chromatic detects changes
|
||||
uses: actions/github-script@v7.0.1
|
||||
uses: actions/github-script@v9
|
||||
if: github.event_name != 'pull_request_target' && steps.chromatic_push.outputs.success == 'false'
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -102,7 +102,7 @@ jobs:
|
||||
body: 'Chromatic detects changes. Please [review the changes on Chromatic](https://www.chromatic.com/builds?appId=6428f7d7b962f0b79f97d6e4).'
|
||||
})
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: storybook
|
||||
path: packages/frontend/storybook-static
|
||||
|
||||
99
.github/workflows/test-backend.yml
vendored
99
.github/workflows/test-backend.yml
vendored
@@ -18,6 +18,14 @@ on:
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/test-backend.yml
|
||||
- .github/misskey/test.yml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
force_ffmpeg_cache_update:
|
||||
description: 'Force update ffmpeg cache'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
unit:
|
||||
name: Unit tests (backend)
|
||||
@@ -30,24 +38,46 @@ jobs:
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15
|
||||
image: postgres:18
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:7
|
||||
image: redis:8
|
||||
ports:
|
||||
- 56312:6379
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.42.1
|
||||
ports:
|
||||
- 57712:7700
|
||||
env:
|
||||
MEILI_NO_ANALYTICS: true
|
||||
MEILI_ENV: development
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Setup and Restore ffmpeg/ffprobe Cache
|
||||
id: cache-ffmpeg
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: |
|
||||
/usr/local/bin/ffmpeg
|
||||
/usr/local/bin/ffprobe
|
||||
# daily cache
|
||||
key: ${{ runner.os }}-ffmpeg-${{ steps.current-date.outputs.today }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-ffmpeg-${{ steps.current-date.outputs.today }}
|
||||
- name: Install FFmpeg
|
||||
if: steps.cache-ffmpeg.outputs.cache-hit != 'true' || github.event.inputs.force_ffmpeg_cache_update == true
|
||||
run: |
|
||||
for i in {1..3}; do
|
||||
echo "Attempt $i: Installing FFmpeg..."
|
||||
@@ -63,7 +93,7 @@ jobs:
|
||||
fi
|
||||
done
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
@@ -77,7 +107,7 @@ jobs:
|
||||
- name: Test
|
||||
run: pnpm --filter backend test-and-coverage
|
||||
- name: Upload to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
uses: codecov/codecov-action@v6
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/backend/coverage/coverage-final.json
|
||||
@@ -86,6 +116,7 @@ jobs:
|
||||
name: E2E tests (backend)
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version-file:
|
||||
- .node-version
|
||||
@@ -93,25 +124,25 @@ jobs:
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15
|
||||
image: postgres:18
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:7
|
||||
image: redis:8
|
||||
ports:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
@@ -125,7 +156,51 @@ jobs:
|
||||
- name: Test
|
||||
run: pnpm --filter backend test-and-coverage:e2e
|
||||
- name: Upload to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
uses: codecov/codecov-action@v6
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/backend/coverage/coverage-final.json
|
||||
|
||||
migration:
|
||||
name: Migration tests (backend)
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version-file:
|
||||
- .node-version
|
||||
#- .github/min.node-version
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Copy Configure
|
||||
run: cp .github/misskey/test.yml .config
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Run migrations
|
||||
run: MISSKEY_CONFIG_YML=test.yml pnpm --filter backend migrate
|
||||
- name: Check no migrations are remaining
|
||||
run: MISSKEY_CONFIG_YML=test.yml pnpm --filter backend check-migrations
|
||||
|
||||
28
.github/workflows/test-federation.yml
vendored
28
.github/workflows/test-federation.yml
vendored
@@ -14,6 +14,13 @@ on:
|
||||
- packages/backend/**
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/test-federation.yml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
force_ffmpeg_cache_update:
|
||||
description: 'Force update ffmpeg cache'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@@ -25,12 +32,27 @@ jobs:
|
||||
- .node-version
|
||||
- .github/min.node-version
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Setup and Restore ffmpeg/ffprobe Cache
|
||||
id: cache-ffmpeg
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: |
|
||||
/usr/local/bin/ffmpeg
|
||||
/usr/local/bin/ffprobe
|
||||
# daily cache
|
||||
key: ${{ runner.os }}-ffmpeg-${{ steps.current-date.outputs.today }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-ffmpeg-${{ steps.current-date.outputs.today }}
|
||||
- name: Install FFmpeg
|
||||
if: steps.cache-ffmpeg.outputs.cache-hit != 'true' || github.event.inputs.force_ffmpeg_cache_update == true
|
||||
run: |
|
||||
for i in {1..3}; do
|
||||
echo "Attempt $i: Installing FFmpeg..."
|
||||
@@ -46,7 +68,7 @@ jobs:
|
||||
fi
|
||||
done
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
|
||||
24
.github/workflows/test-frontend.yml
vendored
24
.github/workflows/test-frontend.yml
vendored
@@ -28,13 +28,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
- name: Test
|
||||
run: pnpm --filter frontend test-and-coverage
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@v5
|
||||
uses: codecov/codecov-action@v6
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/frontend/coverage/coverage-final.json
|
||||
@@ -64,19 +64,19 @@ jobs:
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15
|
||||
image: postgres:18
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:7
|
||||
image: redis:8
|
||||
ports:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
submodules: true
|
||||
# https://github.com/cypress-io/cypress-docker-images/issues/150
|
||||
@@ -86,9 +86,9 @@ jobs:
|
||||
#- uses: browser-actions/setup-firefox@latest
|
||||
# if: ${{ matrix.browser == 'firefox' }}
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
@@ -105,7 +105,7 @@ jobs:
|
||||
- name: Cypress install
|
||||
run: pnpm exec cypress install
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v6
|
||||
uses: cypress-io/github-action@v7.1.9
|
||||
timeout-minutes: 15
|
||||
with:
|
||||
install: false
|
||||
@@ -113,12 +113,12 @@ jobs:
|
||||
wait-on: 'http://localhost:61812'
|
||||
headed: true
|
||||
browser: ${{ matrix.browser }}
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: failure()
|
||||
with:
|
||||
name: ${{ matrix.browser }}-cypress-screenshots
|
||||
path: cypress/screenshots
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: always()
|
||||
with:
|
||||
name: ${{ matrix.browser }}-cypress-videos
|
||||
|
||||
8
.github/workflows/test-misskey-js.yml
vendored
8
.github/workflows/test-misskey-js.yml
vendored
@@ -22,13 +22,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v6.0.2
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
CI: true
|
||||
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@v5
|
||||
uses: codecov/codecov-action@v6
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/misskey-js/coverage/coverage-final.json
|
||||
|
||||
6
.github/workflows/test-production.yml
vendored
6
.github/workflows/test-production.yml
vendored
@@ -16,13 +16,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
6
.github/workflows/validate-api-json.yml
vendored
6
.github/workflows/validate-api-json.yml
vendored
@@ -17,13 +17,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -46,6 +46,7 @@ docker-compose.yml
|
||||
built
|
||||
built-test
|
||||
js-built
|
||||
src-js
|
||||
/data
|
||||
/.cache-loader
|
||||
/db
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "fluent-emojis"]
|
||||
path = fluent-emojis
|
||||
url = https://github.com/misskey-dev/emojis.git
|
||||
|
||||
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@@ -3,11 +3,16 @@
|
||||
"**/node_modules": true
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"files.associations": {
|
||||
"*.test.ts": "typescript"
|
||||
},
|
||||
"jest.jestCommandLine": "pnpm run jest",
|
||||
"jest.runMode": "on-demand",
|
||||
"jest.virtualFolders": [
|
||||
{ "name": "backend unit", "jestCommandLine": "pnpm -F backend run test" },
|
||||
{ "name": "backend e2e", "jestCommandLine": "pnpm -F backend run test:e2e"},
|
||||
{ "name": "misskey-js", "jestCommandLine": "pnpm -F misskey-js run jest" }
|
||||
],
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": "explicit"
|
||||
},
|
||||
|
||||
139
AGENTS.md
Normal file
139
AGENTS.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Misskey – AI Agent Guide
|
||||
|
||||
このファイルは Misskey リポジトリで動く AI コーディングエージェント (Claude Code / OpenAI Codex / GitHub Copilot 等) が共通で参照する **最低限のルールと索引**。次の 3 経路から参照・読み込みされる:
|
||||
|
||||
- **Claude Code**: ルート `CLAUDE.md` から `@AGENTS.md` で取り込まれる
|
||||
- **OpenAI Codex**: ルート `AGENTS.md` を直接読み込む
|
||||
- **GitHub Copilot**: `.github/copilot-instructions.md` (本ファイルを参照しつつ、Copilot code review 向けに必須規約を再掲するファイル) 経由で参照する
|
||||
|
||||
人間 contributor 向けの一般規約 (Issue / PR の出し方、ActivityPub 拡張など) は [CONTRIBUTING.md](CONTRIBUTING.md) を参照。本ファイルは AI が **コードを書く・直す** 際に踏み外してはいけない事項に絞っている。
|
||||
|
||||
---
|
||||
|
||||
## 事故直結ルール (必ず守る)
|
||||
|
||||
違反すると CI 失敗または本番事故になる。順守すること。
|
||||
|
||||
### 1. SPDX ヘッダー必須
|
||||
|
||||
AGPL-3.0-only 管轄かつ SPDX CI 対象ディレクトリに新規 `.ts` / `.js` / `.cjs` / `.mjs` / `.vue` / `.scss` / `.html` ファイルを追加する場合、冒頭に以下を必ず付ける。欠落すると CI (`spdx` ジョブ) が失敗する。CI の対象判定は [.github/workflows/check-spdx-license-id.yml](.github/workflows/check-spdx-license-id.yml) の `directories` 配列を参照 (`*.config.{ts,js,cjs,mjs}` と `*eslint*` は除外)。
|
||||
|
||||
`packages/misskey-js` は MIT ライセンスのサブパッケージなので、この AGPL ヘッダーを一律に付けない。サブパッケージ固有の `package.json` / `LICENSE` / 既存ファイルのヘッダーに従う。
|
||||
|
||||
`.ts` / `.js` / `.cjs` / `.mjs` / `.scss`:
|
||||
|
||||
```text
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
```
|
||||
|
||||
`.vue` / `.html` (HTML コメント形式):
|
||||
|
||||
```text
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
```
|
||||
|
||||
### 2. locales/*.yml は `ja-JP.yml` のみ編集可
|
||||
|
||||
`locales/` 配下の YAML は **`ja-JP.yml` のみ手動編集してよい**。他言語ファイル (`en-US.yml` 等) は Crowdin の自動配信先で、手動編集すると上書きで失われる。根拠: `locales/README.md` (ja-JP.yml 以外を手動編集しない運用) と `crowdin.yml` (`ja-JP.yml` → `locales/%locale%.yml` の同期設定)。
|
||||
|
||||
### 3. マージ済み migration を絶対に編集しない
|
||||
|
||||
`packages/backend/migration/{unixMs}-{PascalName}.js` のうち、既に `develop` / `master` にマージ済みのファイルは **絶対に変更しない**。本番環境で履歴改変が起きると深刻なデータ不整合を引き起こす。
|
||||
|
||||
スキーマ変更が必要な場合は **新しいタイムスタンプで新規ファイル** を作成する:
|
||||
|
||||
- ファイル名: `node -e "console.log(Date.now())"` で UNIX ms を取得し、`{ms}-<descriptive-name>.js` として置く。命名スタイルは既存履歴で混在しており (`1716129964060-ChannelIdDenormalizedForMiPoll.js` のような PascalCase、`1721666053703-fixDriveUrl.js` のような camelCase、`1672704136584-remove-latestStatus.js` のような kebab-case)、変更を表す単一の英語名であれば良い。クラス名側は PascalCase + 13 桁タイムスタンプ (`class FixDriveUrl1721666053703 { ... }`) を必ず守ること。
|
||||
- `up()` と `down()` の両方を必ず実装する (`down` は `up` の完全な巻き戻し)。
|
||||
- `pnpm --filter backend check-migrations` を通す。これは **TypeORM schema builder で pending DDL を検出する** 検査 ([packages/backend/scripts/check_migrations_clean.js](packages/backend/scripts/check_migrations_clean.js))。エンティティの `@Column` / `@Entity` 変更が migration に取り込まれていないとここで検出される。タイムスタンプの順序自体を直接検査するわけではない (順序が壊れた場合の失敗は別経路で出る)。
|
||||
|
||||
エンティティ差分から TypeORM CLI で自動生成したい / `CREATE INDEX CONCURRENTLY` 等のオプションを使いたい場合は [.claude/skills/create-migration/SKILL.md](.claude/skills/create-migration/SKILL.md) を参照。手書き / CLI どちらの方式でも上記 3 点 (履歴改変禁止 / `up`+`down` / `check-migrations`) が満たせれば良い。
|
||||
|
||||
---
|
||||
|
||||
## 必須コマンド
|
||||
|
||||
| 用途 | コマンド |
|
||||
| --- | --- |
|
||||
| 全体ビルド | `pnpm build` |
|
||||
| 開発サーバー (backend + frontend watch) | `pnpm dev` |
|
||||
| Lint (typecheck + eslint, 全パッケージ) | `pnpm lint` (= `pnpm --no-bail -r lint`。最初の失敗で止まらず全パッケージの結果を収集する) |
|
||||
| Backend unit test (Vitest) | `pnpm --filter backend test` |
|
||||
| Backend e2e test | `pnpm --filter backend test:e2e` |
|
||||
| Backend federation test | `pnpm --filter backend test:fed` |
|
||||
| Frontend test (Vitest) | `pnpm --filter frontend test` |
|
||||
| Cypress E2E (要 `start:test`) | `pnpm e2e` |
|
||||
| Storybook dev (frontend) | `pnpm --filter frontend storybook-dev` |
|
||||
| Migration 適用 | `pnpm migrate` |
|
||||
| Migration ロールバック | `pnpm revert` |
|
||||
| Migration の pending DDL 検査 (エンティティ差分の取り込み漏れ検出) | `pnpm --filter backend check-migrations` |
|
||||
| `misskey-js` 再生成 (API 変更後必須) | `pnpm build-misskey-js-with-types` |
|
||||
|
||||
> Backend の TypeScript 型チェックは `pnpm --filter backend typecheck` (tsgo)。
|
||||
> 個別ファイルへの ESLint --fix は `pnpm exec eslint --fix <path>`。
|
||||
> **backend テスト (`test` / `test:e2e` / `test:fed`) 実行前に `.config/test.yml` が必要** (未作成だとテスト自体が起動しない)。コピー手順と詳細は [.claude/docs/testing.md §Backend 全般の前提](.claude/docs/testing.md#backend-全般の前提-configtestyml) を参照。
|
||||
|
||||
---
|
||||
|
||||
## CHANGELOG
|
||||
|
||||
ユーザー影響のある変更 (機能追加・修正・改善) は `CHANGELOG.md` の冒頭 `## Unreleased` セクションに 1 行追加する。リファクタリング等の内部変更は不要。
|
||||
|
||||
### セクション構造
|
||||
|
||||
`## Unreleased` 配下に **3 つのサブセクション** が用意されている:
|
||||
|
||||
- `### General` — 共通 / 横断的な変更
|
||||
- `### Client` — `packages/frontend` 系
|
||||
- `### Server` — `packages/backend` 系
|
||||
|
||||
### エントリ書式
|
||||
|
||||
該当サブセクションに `- <Prefix>: <概要>` の形式で追加。Prefix は先頭大文字。
|
||||
|
||||
```text
|
||||
- Enhance: ノートの詳細表示での公開範囲の表示を改善
|
||||
- Fix: 通知が約10秒遅延する問題を修正
|
||||
- Feat: 新機能の追加
|
||||
```
|
||||
|
||||
### 触ってはいけない範囲
|
||||
|
||||
- `## Unreleased` **以外** のセクション (過去リリース) は変更しない。
|
||||
- `## Unreleased` の見出しと 3 つの空サブセクション骨格自体は維持する (リリーススクリプトが期待する構造)。
|
||||
|
||||
> 参考: コミットメッセージ側は `enhance(frontend): ...` / `fix(backend): ...` の小文字 + スコープ形式 ([CONTRIBUTING.md](CONTRIBUTING.md) 参照)。CHANGELOG とは書式が異なる点に注意。
|
||||
|
||||
---
|
||||
|
||||
## オンデマンド参照 (必要時に Read すること)
|
||||
|
||||
以下は AI が **作業対象に応じて必要なときだけ** 開く詳細ドキュメント。常時コンテキストには載せない。
|
||||
|
||||
| 何をしたい時 | 参照先 |
|
||||
| --- | --- |
|
||||
| パッケージ構成・依存関係を把握したい | [.claude/docs/architecture.md](.claude/docs/architecture.md) |
|
||||
| `packages/backend` を編集する (NestJS / TypeORM / migration / API endpoint) | [.claude/docs/backend.md](.claude/docs/backend.md) |
|
||||
| `packages/frontend` を編集する (Vue 3 / Mk* / i18n / SCSS module / `os.ts`) | [.claude/docs/frontend.md](.claude/docs/frontend.md) |
|
||||
| テストを書く・走らせる (Vitest / Cypress / Storybook) | [.claude/docs/testing.md](.claude/docs/testing.md) |
|
||||
| 有効化済 Claude Code プラグインの用途を確認 | [.claude/docs/plugins.md](.claude/docs/plugins.md) |
|
||||
|
||||
---
|
||||
|
||||
## ツール固有の補助ファイル
|
||||
|
||||
`.claude/` 配下は Claude Code 固有の skills / agents / slash commands を集約している (Codex / Copilot は読み飛ばしてよい):
|
||||
|
||||
- `.claude/skills/` — 繰り返しタスク用の skill 定義 (例: `add-api-endpoint`, `create-migration`)
|
||||
- `.claude/agents/` — 専門レビューエージェント (例: `misskey-api-reviewer`, `vue-component-reviewer`)
|
||||
- `.claude/commands/` — Claude Code のスラッシュコマンド (例: `/check-misskey-js`, `/changelog-add`)
|
||||
- `.claude/docs/` — オンデマンド参照ドキュメント (上記の表で示したもの。Codex / Copilot からも内容自体は読める)
|
||||
- `.claude/settings.json` — Claude Code の有効プラグイン (`enabledPlugins`) のみを記載した共有設定。hook は意図的に登録しない (各 contributor が `.claude/settings.local.json` で opt-in する方針)
|
||||
- `.claude/settings.local.json` — 個人ローカル設定 (`.gitignore` 済)
|
||||
|
||||
サードパーティ由来 (everything-claude-code 由来の MIT ライセンスファイル等) の出典は [.claude/THIRD_PARTY_LICENSES.md](.claude/THIRD_PARTY_LICENSES.md) を参照。
|
||||
602
CHANGELOG.md
602
CHANGELOG.md
@@ -1,15 +1,471 @@
|
||||
## 2025.6.4
|
||||
## 2026.5.2
|
||||
|
||||
### Note
|
||||
- config に `threadPoolSize` オプションが追加されました。
|
||||
- デフォルトは `1` で、ワーカーごとに指定した数のスレッドが作成されます。
|
||||
- スレッドプールは CPU バウンドな処理をオフロードするために使用されるため、みだりに大きな値を指定しないでください。
|
||||
|
||||
### General
|
||||
- Enhance: Unicode 17.0 に収録されている絵文字の処理・表示に対応
|
||||
- Fluent Emojiや端末ネイティブの絵文字を利用している場合は、最新の絵文字に対応しておらず正しく表示できない可能性があります。絵文字が表示できない場合は、表示に使用する絵文字をTwemojiに切り替えてご利用ください。
|
||||
- Enhance: 投稿通知設定したユーザーをリストで見ることができるように
|
||||
- 依存関係の更新
|
||||
|
||||
### Client
|
||||
- Enhance: テーマのプレビュー時、リロードせずにもとのテーマに戻せるように
|
||||
- Enhance: Fluent Emojiを更新し、Unicode 15+相当の絵文字の表示に対応
|
||||
- Fix: テーマエディター使用時に、最初の変更のみ適用される問題を修正
|
||||
- Fix: テーマのプレビュー時、既存のテーマとIDが被っている場合にプレビューできない問題を修正
|
||||
- Fix: テーマのインストールエラーの表示を改善
|
||||
- Fix: リスト編集画面におけるユーザー追加時のユーザー選択ダイアログにおいて、自身のアカウントが検索結果の一覧に表示されない問題を修正
|
||||
- Fix: デッキのカラムから開いたアンテナ・リストの編集ウィンドウを、"ポップアウト"、"新しいタブで表示"、"リンクをコピー"した場合に誤ったリンクが与えられる問題を修正
|
||||
- Fix: チャンネルの作成ロールポリシーにて、ヘッダーにロールポリシーの値が表示されない問題を修正
|
||||
|
||||
### Server
|
||||
- Enhance: RSA 署名処理のオフロード
|
||||
|
||||
|
||||
## 2026.5.1
|
||||
|
||||
### General
|
||||
- Enhance: チャンネルの作成の可否をロールポリシーで制御できるように
|
||||
- Fix: `.devcontainer/compose.yml`のvolumeのマウントパスを修正
|
||||
|
||||
### Client
|
||||
- Enhance: ノートの詳細表示での公開範囲の表示を改善
|
||||
(Cherry-picked from https://github.com/kokonect-link/cherrypick/commit/ecc75563f4e428b66adccc379bf317b5b21ed8e6)
|
||||
- Fix: ロール設定画面でロールをアサイン/アサイン解除した際、リロードしなくても画面に反映されるよう修正
|
||||
|
||||
### Server
|
||||
- Fix: ID生成アルゴリズムにULIDを使用している場合に通知が約10秒遅延する問題を修正
|
||||
- Fix: 公開範囲がフォロワーの投稿が通知されない問題を修正
|
||||
- Fix: URLプレビューが動作しない問題を修正
|
||||
|
||||
|
||||
## 2026.5.0
|
||||
|
||||
### General
|
||||
- Enhance: アバターデコレーションにカテゴリを設定できるように
|
||||
|
||||
### Client
|
||||
- Enhance: チャンネル指定リノートでリノート先のチャンネルに移動できるように
|
||||
- Enhance: ベータ版でのアップデート時のダイアログの更新情報リンクをGitHubのReleasesページに遷移するようにし、正しく閲覧できるように
|
||||
- Fix: 一部のページ内リンクが正しく動作しない問題を修正
|
||||
- Fix: ドライブへの画像アップロード時にファイル名の変更が無視される不具合を修正
|
||||
- Fix: 連合が無効化されたサーバーで一部の設定項目が空欄で表示される問題を修正
|
||||
- Fix: オーディオ、動画の再生速度メニューが開けない問題を修正
|
||||
|
||||
### Server
|
||||
- Enhance: メモリ使用量を削減
|
||||
- Enhance: 起動の高速化
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1410)
|
||||
- Enhance: バックエンドの開発モード時の安定性向上
|
||||
- Enhance: バックエンドビルド・テスト時に使用する依存関係の整理(swc/esbuild→Rolldown, Jest→Vitest)
|
||||
- Fix: ファイルシステムを用いる処理におけるパスの取り扱いを改善
|
||||
- Fix: `/api-doc` にアクセスできない問題を修正
|
||||
- Fix: support `alsoKnownAs` from remote actors as either array or unwrapped singleton
|
||||
- Fix: ローカルに存在しないリモートアカウントに対するアカウント削除リクエストを受信した際に、そのユーザーを新規作成して削除する挙動を修正
|
||||
- Fix: Inboxでの特定のエラーによる失敗はDelayedにしない
|
||||
- Fix: ID生成アルゴリズムにULIDを使用している場合にMisskeyが正しく動作しない問題を修正
|
||||
- Fix: リレー経由で届いたノートがリノートとして表示される問題を修正
|
||||
- Fix: robots.txtの内容を調整
|
||||
- Fix: 特定のユーザーに管理者権限を持つロールが複数ついている際に、取得できるユーザーIDが重複する問題を修正
|
||||
(Cherry-picked from https://github.com/lqvp/misskey-tempura/commit/17ed4108cec4b6bd2fd989db5a9091db91fa37a7)
|
||||
- Fix: ブロックしたサーバーからのInboxジョブが蓄積し続ける問題を修正
|
||||
(Cherry-picked from https://github.com/lqvp/misskey-tempura/commit/3f0f4bfe923f2b3a7837017b54841598f421c6ef)
|
||||
- Fix: support activity with `actor` as an id string or embedded object in inbox processor and ActivityPub inbox service
|
||||
- Fix: コンフィグファイルに `meilisearch` の設定がある状態でほかの検索プロバイダを利用すると、UI上からリモートのノートの検索ができない問題を修正
|
||||
- Fix: ノートに関する通知で公開範囲が考慮されていない問題を修正
|
||||
(Cherry-picked from https://github.com/lqvp/misskey-tempura/commit/cbce96c520a138b8bcd16890ff6f2952830fa166 originally presented in https://github.com/yojo-art/cherrypick/pull/743)
|
||||
|
||||
## 2026.3.2
|
||||
|
||||
### General
|
||||
- 依存関係の更新
|
||||
|
||||
### Client
|
||||
- Enhance: アプリ内ウィンドウの初期サイズを画面サイズに応じて自動で調整するように
|
||||
- Fix: 絵文字パレットが空の状態でMisskeyについてのページが閲覧できない問題を修正
|
||||
- Fix: ウィンドウのタイトルをクリックしても最前面に出ないことがある問題を修正
|
||||
|
||||
### Server
|
||||
- Fix: 自分の行ったフォロワー限定投稿または指名投稿に自分自身でリアクションなどを行った場合のイベントが流れない問題を修正
|
||||
- Fix: 署名付きGETリクエストにおいてAcceptヘッダを署名の対象から除外(Acceptヘッダを正規化するCDNやリバースプロキシを使用している際に挙動がおかしくなる問題を修正)
|
||||
- Fix: WebSocket接続におけるノートの非表示ロジックを修正
|
||||
- Fix: チャンネルミュートを有効にしている際に、一部のタイムラインやノート一覧が空になる問題を修正
|
||||
- Fix: 初期読込時に必要なフロントエンドのアセットがすべて読み込まれていない問題を修正
|
||||
|
||||
|
||||
## 2026.3.1
|
||||
|
||||
### General
|
||||
- 依存関係の更新
|
||||
|
||||
### Server
|
||||
- Fix: セキュリティに関する修正
|
||||
|
||||
|
||||
## 2026.3.0
|
||||
|
||||
### Note
|
||||
- `users/following` の `birthday` プロパティは非推奨になりました。代わりに `users/get-following-users-by-birthday` をご利用ください。
|
||||
|
||||
### General
|
||||
- Enhance: 「もうすぐ誕生日のユーザー」ウィジェットで、誕生日が至近のユーザーも表示できるように
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey)
|
||||
- 「今日誕生日のユーザー」は「もうすぐ誕生日のユーザー」に名称変更されました
|
||||
- Fix: ユーザーハッシュタグページでユーザーの読み込みが重複する問題を修正
|
||||
- 依存関係の更新
|
||||
|
||||
### Client
|
||||
- Enhance: ドライブのファイル一覧で自動でもっと見るを利用可能に
|
||||
- Enhance: ウィジェットの表示設定をプレビューを見ながら行えるように
|
||||
- Enhance: ウィジェットの設定項目のラベルの多言語対応
|
||||
- Enhance: 画面幅が広いときにメディアを横並びで表示できるようにするオプションを追加
|
||||
- Enhance: パフォーマンスの向上
|
||||
- Fix: ドライブクリーナーでファイルを削除しても画面に反映されない問題を修正 #16061
|
||||
- Fix: 非ログイン時にログインを求めるダイアログが表示された後にダイアログのぼかしが解除されず操作不能になることがある問題を修正
|
||||
- Fix: ドライブのソートが「登録日(昇順)」の場合に正しく動作しない問題を修正
|
||||
- Fix: 高度なMFMのピッカーを使用する際の挙動を改善
|
||||
- Fix: 管理画面でアーカイブ済のお知らせを表示した際にアクティブなお知らせが多い旨の警告が出る問題を修正
|
||||
- Fix: ファイルタブのセンシティブメディアを開く際に確認ダイアログを出す設定が適用されない問題を修正
|
||||
- Fix: 2月29日を誕生日に設定している場合、閏年以外は3月1日を誕生日として扱うように修正
|
||||
- Fix: `Mk:C:container` の `borderWidth` が正しく反映されない問題を修正
|
||||
- Fix: mCaptchaが正しく動作しない問題を修正
|
||||
- Fix: 非ログイン時にリバーシの対局が表示されない問題を修正
|
||||
- Fix: ノートの詳細表示でリアクションが全件表示されない問題を修正
|
||||
- Fix: 動画埋め込みプレイヤーなどの一部ウィンドウで、ウィンドウのサイズ変更や移動が正常に行えない問題を修正
|
||||
- Fix: 画像エフェクトの修正
|
||||
- 塗りつぶし・モザイク・ぼかしエフェクトを回転させると歪む問題を修正
|
||||
- モザイクの格子のサイズが画像の縦横比によって長方形となる問題を修正
|
||||
- モザイクの色味がより自然になるように修正
|
||||
- ぼかしに不自然な縦線が入る問題を修正
|
||||
- Fix: フォロー承認通知でフォローされた際のメッセージの絵文字が表示されない問題を修正
|
||||
- Fix: HTTP環境など(Secure Contextのない環境)で、設定画面が閲覧できない問題を修正
|
||||
|
||||
### Server
|
||||
- Enhance: OAuthのクライアント情報取得(Client Information Discovery)において、IndieWeb Living Standard 11 July 2024で定義されているJSONドキュメント形式に対応しました
|
||||
- JSONによるClient Information Discoveryを行うには、レスポンスの`Content-Type`ヘッダーが`application/json`である必要があります
|
||||
- 従来の実装(12 February 2022版・HTML Microformat形式)も引き続きサポートされます
|
||||
- Enhance: メモリ使用量を削減
|
||||
- Fix: `/admin/get-user-ips` エンドポイントのアクセス権限を管理者のみに修正
|
||||
|
||||
## 2025.12.2
|
||||
|
||||
### Note
|
||||
v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`に変更」について、正しく環境に応じた設定を行わないとサインインが困難になるといった状態を緩和するために、以下の対応を行いました。
|
||||
|
||||
**正しく設定しないと、上記のような不具合の原因となったり、セキュリティリスクが高まったりする可能性があります。必ず現在のconfigをご確認の上、必要に応じて値を変更してください。**
|
||||
|
||||
- `trustProxy`について、デフォルト(configに値が設定されていない状態)ではループバックアドレスとローカルIPアドレス空間を信頼するようにしました。
|
||||
- `trustProxy`の設定方法について、より詳細に記述しました。
|
||||
- リバースプロキシやCDNなどのより上流のレイヤでレートリミットを設定したい場合や、緊急時の一時的な緩和策として、Misskey内部でのIPアドレスペースでのレートリミットを無効化できるようにしました。
|
||||
|
||||
### General
|
||||
- 依存関係の更新
|
||||
|
||||
### Client
|
||||
- Enhance: デッキのUI説明を追加
|
||||
- Enhance: 設定がブラウザによって消去されないようにするオプションを追加
|
||||
- Fix: バージョン表記のないPlayが正しく動作しない問題を修正
|
||||
バージョン表記のないものは v0.x 系として実行されます。v1.x 系で動作させたい場合は必ずバージョン表記を含めてください。
|
||||
- Fix: デッキUIでメニュー位置を下にしているとプロファイル削除ボタンが表示されないのを修正
|
||||
- Fix: 一部のUnicode絵文字のリアクションがボタンにならない問題を修正
|
||||
|
||||
### Server
|
||||
- Enhance: Misskey内部でのIPアドレスペースでのレートリミットを無効化できるように
|
||||
- リバースプロキシやCDNなど別のレイヤで別途レートリミットを設定する場合や、ローカルでのテスト用途等として利用することを想定しています。
|
||||
- デフォルトは `enableIpRateLimit: true`(Misskey内部でのIPアドレスペースでのレートリミットは有効)です。
|
||||
- Fix: コントロールパネルのジョブキューページで使用される一部APIの応答速度を改善
|
||||
|
||||
## 2025.12.1
|
||||
|
||||
### Client
|
||||
- Fix: 特定の条件下でMisskeyが起動せず空白のページが表示されることがある問題を軽減
|
||||
- Fix: 初回読み込み時などに、言語設定で不整合が発生することがある問題を修正
|
||||
- Fix: 削除されたノートのリノートが正しく動作されない問題を修正
|
||||
- Fix: チャンネルオーナーが削除済みの時にチャンネルのヘッダーメニューが表示されない不具合を修正
|
||||
- Fix: ドライブで登録日以外でソートする場合は月でグループ化して表示しないように
|
||||
- Fix: `null` を返す note_view_intrruptor プラグインが動作しない問題を修正
|
||||
|
||||
### Server
|
||||
- Fix: ジョブキューでSentryが有効にならない問題を修正
|
||||
|
||||
|
||||
## 2025.12.0
|
||||
|
||||
### Note
|
||||
- configの`trustProxy`のデフォルト値を`false`に変更しました。アップデート前に現在のconfigをご確認の上、必要に応じて値を変更してください。
|
||||
|
||||
### Client
|
||||
- Fix: stacking router viewで連続して戻る操作を行うと何も表示されなくなる問題を修正
|
||||
|
||||
### Server
|
||||
- Enhance: メモリ使用量を削減しました
|
||||
- Enhance: ActivityPubアクティビティを送信する際のパフォーマンス向上
|
||||
- Enhance: 依存関係の更新
|
||||
- Fix: セキュリティに関する修正
|
||||
|
||||
## 2025.11.1
|
||||
|
||||
### Client
|
||||
|
||||
- Enhance: リアクションの受け入れ設定にキャプションを追加 #15921
|
||||
- Fix: ページの内容がはみ出ることがある問題を修正
|
||||
- Fix: ナビゲーションバーを下に表示しているときに、項目数が多いと表示が崩れる問題を修正
|
||||
- Fix: ヘッダーメニューのチャンネルの新規作成の項目でチャンネル作成ページに飛べない問題を修正 #16816
|
||||
- Fix: ラジオボタンに空白の選択肢が表示される問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1105)
|
||||
- Fix: 一部のシチュエーションで投稿フォームのツアーが正しく表示されない問題を修正
|
||||
- Fix: 投稿フォームのリセットボタンで注釈がリセットされない問題を修正
|
||||
- Fix: PlayのAiScriptバージョン判定(v0.x系・v1.x系の判定)が正しく動作しない問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1129)
|
||||
- Fix: フォロー申請をキャンセルする際の確認ダイアログの文言が不正確な問題を修正
|
||||
- Fix: 初回読み込み時にエラーになることがある問題を修正
|
||||
- Fix: お気に入りクリップの一覧表示が正しく動作しない問題を修正
|
||||
- Fix: AiScript Misskey 拡張APIにおいて、各種関数の引数で明示的に `null` が指定されている場合のハンドリングを修正
|
||||
|
||||
### Server
|
||||
- Enhance: メモリ使用量を削減しました
|
||||
- Enhance: 依存関係の更新
|
||||
- Fix: ワードミュートの文字数計算を修正
|
||||
- Fix: チャンネルのリアルタイム更新時に、ロックダウン設定にて非ログイン時にノートを表示しない設定にしている場合でもノートが表示されてしまう問題を修正
|
||||
- Fix: DeepL APIのAPIキー指定方式変更に対応
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1096)
|
||||
- 内部実装の変更にて対応可能な更新です。Misskey側の設定方法に変更はありません。
|
||||
- Fix: DBレプリケーションを利用する環境でクエリーが失敗する問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1123)
|
||||
|
||||
## 2025.11.0
|
||||
|
||||
### General
|
||||
- Feat: チャンネルミュート機能の実装 #10649
|
||||
- チャンネルの概要画面の右上からミュートできます(リンクコピー、共有、設定と同列)
|
||||
- Enhance: Node.js 24.10.0をサポートするようになりました
|
||||
- Enhance: DockerのNode.jsが24.10.0に更新されました
|
||||
- 依存関係の更新
|
||||
|
||||
### Client
|
||||
- Feat: 画像にメタデータを含むフレームをつけられる機能
|
||||
- Enhance: プリセットを作成しなくても画像にウォーターマークを付与できるように
|
||||
- Enhance: 管理しているチャンネルの見分けがつきやすくなるように
|
||||
- Enhance: プロフィールへのリンクをユーザーポップアップのアバターに追加
|
||||
- Enhance: ユーザーのノート、フォロー、フォロワーページへのリンクをユーザーポップアップに追加
|
||||
- Enhance: プッシュ通知を行うための権限確認をより確実に行うように
|
||||
- Enhance: 投稿フォームのチュートリアルを追加
|
||||
- Enhance: 「自動でもっと見る」をほとんどの箇所で利用可能に
|
||||
- Enhance: アンテナ・リスト設定画面とタイムラインの動線を改善
|
||||
- アンテナ・リスト一覧画面の項目を選択すると、設定画面ではなくタイムラインに移動するようになりました
|
||||
- アンテナ・リストの設定画面の右上にタイムラインに移動するボタンを追加しました
|
||||
- Fix: 紙吹雪エフェクトがアニメーション設定を考慮せず常に表示される問題を修正
|
||||
- Fix: ナビゲーションバーのリアルタイムモード切替ボタンの状態をよりわかりやすく表示するように
|
||||
- Fix: ページのタイトルが長いとき、はみ出る問題を修正
|
||||
- Fix: 投稿フォームのアバターが正しく表示されない問題を修正 #16789
|
||||
- FIx: カスタム絵文字(β)画面で変更行が正しくハイライトされない問題を修正 #16626
|
||||
|
||||
### Server
|
||||
- Enhance: Remote Notes Cleaningが複雑度が高いノートの処理を中断せずに次のノートから再開するように
|
||||
- Fix: チャンネルの説明欄の最小文字数制約を除去
|
||||
|
||||
## 2025.10.2
|
||||
|
||||
### Client
|
||||
- Fix: アプリ内からキャッシュをクリアするとテーマ再適用するまでレンダリングが正しく行われない問題を修正
|
||||
- Fix: 期限が無期限のアンケートに投票できない問題を修正
|
||||
|
||||
## 2025.10.1
|
||||
|
||||
### General
|
||||
- Enhance: リモートユーザーに付与したロールバッジを表示できるように(オプトイン)
|
||||
パフォーマンス上の問題からデフォルトで無効化されています。「コントロールパネル > パフォーマンス」から有効化できます。
|
||||
- 依存関係の更新
|
||||
|
||||
### Client
|
||||
- Enhance: デッキのメインカラムのヘッダをクリックしてページ上部/下部にスクロールできるように
|
||||
- Enhance: 下書き/予約投稿一覧は投稿フォームのアカウントメニュー内に移動し、下書き保存は「...」メニュー内に移動されました
|
||||
- Fix: カスタム絵文字画面(beta)のaliasesで使用される区切り文字が一致していないのを修正 #15614
|
||||
- Fix: バナー画像の幅が表示領域と一致していない問題を修正
|
||||
- Fix: 一部のブラウザでバナー画像が上下中央に表示されない問題を修正
|
||||
- Fix: ナビゲーションバーの設定で削除した項目をその場で再追加できない問題を修正
|
||||
- Fix: ロールポリシーによりダイレクトメッセージが無効化されている際のデッキのダイレクトメッセージカラムの挙動を改善
|
||||
- Fix: 画像のマスクでタッチ操作が不安定な問題を修正
|
||||
- Fix: ウォーターマークの各種挙動修正
|
||||
- ウォーターマークを回転させると歪む問題を修正
|
||||
- ウォーターマークを敷き詰めると上下左右反転した画像/文字が表示される問題を修正
|
||||
- ウォーターマークを回転させた際に画面からはみ出た部分を考慮できるように
|
||||
- Fix: 投票が終了した後に投票結果が正しく表示されない問題を修正
|
||||
- Fix: ダークモードの同期が機能しない場合がある問題を修正
|
||||
- Fix: iOSで動画の圧縮を行うと音声トラックが失われる問題を修正
|
||||
|
||||
### Server
|
||||
- Enhance: 管理者/モデレーターはファイルのアップロード制限をバイパスするように
|
||||
- Enhance: セキュリティの向上
|
||||
|
||||
## 2025.10.0
|
||||
|
||||
### NOTE
|
||||
- pnpm 10.16.0 が必要です
|
||||
- ロールのインポート機能の利用可否ポリシーのデフォルト値が「いいえ」に変わったため、デフォルトから変更していないサーバーでは適宜設定を変更してください。
|
||||
- ロールのアップロード可能なファイル種別ポリシーのデフォルト値に「text/*」が追加されたため、デフォルトから変更していないサーバーでは適宜設定を変更してください。
|
||||
|
||||
### General
|
||||
- Feat: 予約投稿ができるようになりました
|
||||
- デフォルトで作成可能数は1になっています。適宜ロールのポリシーで設定を行ってください。
|
||||
- Enhance: 広告ごとにセンシティブフラグを設定できるようになりました
|
||||
- Enhance: 依存関係の更新
|
||||
- Enhance: 翻訳の更新
|
||||
|
||||
### Client
|
||||
- Feat: アカウントのQRコードを表示・読み取りできるようになりました
|
||||
- Feat: 動画を圧縮してアップロードできるようになりました
|
||||
- Feat: (実験的) ブラウザ上でノートの翻訳を行えるように
|
||||
- Enhance: チャットの日本語名称がダイレクトメッセージに戻るとともに、ベータ版機能ではなくなりました
|
||||
- Enhance: 画像編集にマスクエフェクト(塗りつぶし、ぼかし、モザイク)を追加
|
||||
- Enhance: 画像編集の集中線エフェクトを強化
|
||||
- Enhance: ウォーターマークにアカウントのQRコードを追加できるように
|
||||
- Enhance: テーマをドラッグ&ドロップできるように
|
||||
- Enhance: 絵文字ピッカーのサイズをより大きくできるように
|
||||
- Enhance: カスタム絵文字が多い場合にサーバーの絵文字一覧ページがフリーズしないように
|
||||
- Enhance: 時刻計算のための基準値を一か所で管理するようにし、パフォーマンスを向上
|
||||
- Enhance: 「お問い合わせ」ページから、バグの調査等に役立つ情報(OSやブラウザのバージョン等)を取得・コピーできるように
|
||||
- Fix: iOSで、デバイスがダークモードだと初回読み込み時にエラーになる問題を修正
|
||||
- Fix: アクティビティウィジェットのグラフモードが動作しない問題を修正
|
||||
- Fix: ユニコード絵文字の追加辞書をインストールするとユニコード絵文字が絵文字ピッカーで検索できなくなる絵文字があるバグを修正
|
||||
|
||||
### Server
|
||||
- Enhance: ユーザーIPを確実に取得できるために設定ファイルにFastifyOptions.trustProxyを追加しました
|
||||
|
||||
## 2025.9.0
|
||||
|
||||
### Client
|
||||
- Enhance: AiScriptAppウィジェットで構文エラーを検知してもダイアログではなくウィジェット内にエラーを表示するように
|
||||
- Enhance: /flushページでサイトキャッシュをクリアできるようになりました
|
||||
- Enhance: クリップ/リスト/アンテナ/ロール追加系メニュー項目において、表示件数を拡張
|
||||
- Enhance: 「キャッシュを削除」ボタンでブラウザの内部キャッシュの削除も行えるように
|
||||
- Enhance: Ctrlキー(Commandキー)を押下しながらリンクをクリックすると新しいタブで開くように
|
||||
- Fix: プッシュ通知を有効にできない問題を修正
|
||||
- Fix: RSSティッカーウィジェットが正しく動作しない問題を修正
|
||||
- Fix: プロファイルを復元後アカウントの切り替えができない問題を修正
|
||||
- Fix: エラー画像が横に引き伸ばされてしまう問題に対応
|
||||
|
||||
### Server
|
||||
- Fix: webpなどの画像に対してセンシティブなメディアの検出が適用されていなかった問題を修正
|
||||
|
||||
## 2025.8.0
|
||||
|
||||
### Note
|
||||
- サポートされるNode.jsの最小バージョンが**22.15.0**になりました
|
||||
|
||||
### General
|
||||
- ノートを削除した際、関連するノートが同時に削除されないようになりました
|
||||
- APIで、「replyIdが存在しているのにreplyがnull」や「renoteIdが存在しているのにrenoteがnull」であるという、今までにはなかったパターンが表れることになります
|
||||
- 定期的に古いリモートの投稿を削除する機能が実装されました
|
||||
- コントロールパネル→パフォーマンス→Remote Notes Cleaning で有効化できます
|
||||
- データベースの肥大化を防止することが可能です
|
||||
- 既存のサーバーで当機能を有効化した場合は、処理量が多くなるため、一時的にストレージ使用量が増加する可能性があります。
|
||||
- 増加量を抑えるには、最大処理継続時間をデフォルトより短くしてください。
|
||||
- データベースサイズへの効果が見られない場合はautovacuumが有効になっているか確認してください
|
||||
- サーバーの初期設定が完了するまでは連合がオンにならないようになりました
|
||||
- 日本語における公開範囲名称の「ダイレクト」が「指名」に改称されました
|
||||
- 実際の動作に即した名称になり、馴染みのない人でも理解しやすくなりました
|
||||
- 他サービスにおける「ダイレクトメッセージ」に相当するMisskeyの機能は「チャット」ですが(過去のバージョンのMisskeyでも、当該機能は「チャット」ではなく「ダイレクトメッセージ」でした)、「ダイレクト投稿」という名称の機能が存在するとそちらがダイレクトメッセージ機能であるような誤解を生んでいました
|
||||
- 今後、「チャット」の名称を「ダイレクトメッセージ」に戻す可能性があります
|
||||
- mfm.jsをアップデートしました
|
||||
- Enhance: Unicode 15.1 および 16.0 に収録されている絵文字に対応
|
||||
- Enhance: acctに `.` が入っているユーザーのメンションに対応
|
||||
- Fix: Unicode絵文字に隣接する異体字セレクタ(`U+FE0F`)が絵文字として認識される問題を修正
|
||||
- Enhance: ユーザー検索をロールポリシーで制限できるように
|
||||
|
||||
### Client
|
||||
- Feat: AiScriptが1.1.0に更新されました
|
||||
- プラグインは1.xに対応したものが必要です
|
||||
- Playはそのまま動作しますが、新規に作られるプリセットは1.xになります
|
||||
- 以前のバージョンから無効化されていた note_view_interruptor が有効になりました
|
||||
- ハンドラは同期的である必要があります
|
||||
- Feat: セーフモード
|
||||
- プラグイン・テーマ・カスタムCSSの使用でクライアントの起動に問題が発生した際に、これらを無効にして起動できます
|
||||
- 以下の方法でセーフモードを起動できます
|
||||
- `g` キーを連打する
|
||||
- URLに`?safemode=true`を付ける
|
||||
- PWAのショートカットで Safemode を選択して起動する
|
||||
- Feat: 非ログイン時に表示されるトップページのスタイルを選択できるように
|
||||
- コントロールパネル→ブランディング→エントランスページのスタイル
|
||||
- Feat: ページのタブバーを下部に表示できるように
|
||||
- Feat: (実験的)iOSでの触覚フィードバックを有効にできるように
|
||||
- Feat: コントロールパネルを検索できるように
|
||||
- Enhance: 「自動でもっと見る」オプションが有効になり、安定性が向上しました
|
||||
- Enhance: トルコ語 (tr-TR) に対応
|
||||
- Enhance: 不必要な翻訳データを読み込まなくなり、パフォーマンスが向上しました
|
||||
- Enhance: 画像エフェクトのパラメータ名の多言語対応
|
||||
- Enhance: ノートを非表示にする相対期間を1ヶ月単位で自由に指定できるように
|
||||
- Enhance: メールアドレス確認画面のUIを改善
|
||||
- Enhance: アイコンのスクロール追従を無効化する際の適用範囲を強化
|
||||
- Enhance: レンダリングパフォーマンスの向上
|
||||
- Enhance: 依存ソフトウェアの更新
|
||||
- Fix: 投稿フォームでファイルのアップロードが中止または失敗した際のハンドリングを修正
|
||||
- Fix: 一部の設定検索結果が存在しないパスになる問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1171)
|
||||
- Fix: テーマエディタが動作しない問題を修正
|
||||
- Fix: チャンネルのハイライトページにノートが表示されない問題を修正
|
||||
- Fix: カラムの名前が正しくリスト/チャンネルの名前にならない問題を修正
|
||||
- Fix: 複数のメンションを1行に記述した場合に、サジェストが正しく表示されない問題を修正
|
||||
- Fix: メンションとしての条件を満たしていても、特定の条件(`-`が含まれる場合など)で正しくサジェストされない問題を一部修正
|
||||
- Fix: ユーザーの前後ノートを閲覧する機能が動作しない問題を修正
|
||||
- Fix: 照会ダイアログでap/showでローカルユーザーを解決した際@username@nullに飛ばされる問題を修正
|
||||
- Fix: アイコンのデコレーションを付ける際にデコレーションが表示されなくなる問題を修正
|
||||
- Fix: タッチ操作時にマウスホバー時のユーザープレビューが開くことがある問題を修正
|
||||
- Fix: 管理中アカウント一覧で正しい表示が行われない問題を修正
|
||||
- Fix: lookupページでリモートURLを指定した際に正しく動作しない問題を修正
|
||||
|
||||
### Server
|
||||
- Feat: サーバー管理コマンド
|
||||
- `pnpm cli foo` の形式で実行可能です
|
||||
- 現在以下のコマンドが利用可能です
|
||||
- `reset-captcha` - CAPTCHA設定をリセットします
|
||||
- Enhance: ノートの削除処理の効率化
|
||||
- Enhance: 全体的なパフォーマンスの向上
|
||||
- Enhance: 依存ソフトウェアの更新
|
||||
- Enhance: `clips/list` APIがページネーションに対応しました
|
||||
- Fix: `notes/mentions` で場合によっては並び順が正しく返されない問題を修正
|
||||
- Fix: SystemWebhook設定でsecretを空に出来ない問題を修正
|
||||
- Fix: 削除されたユーザーがチャットメッセージにリアクションしている場合`chat/history`などでエラーになる問題を修正
|
||||
- Fix: Pageのアイキャッチ画像をドライブから消してもPageごと消えないように
|
||||
- Fix: タイムラインAPIの withRenotes: false 時のレスポンスを修正
|
||||
|
||||
|
||||
## 2025.7.0
|
||||
|
||||
### Note
|
||||
- Node.jsの最小バージョンを20.10.0から20.18.1に引き上げました
|
||||
- なお、特に必要がない限りNode.jsは推奨バージョンであるv22を使用するようにしてください
|
||||
|
||||
### General
|
||||
- Feat: ノートの下書き機能
|
||||
- Feat: クリップ内でノートを検索できるように
|
||||
- Feat: Playを検索できるように
|
||||
- Feat: モデレーションにおいて、特定のドライブファイルを添付しているチャットメッセージを一覧できるように
|
||||
- Enhance: ウォーターマーク機能をロールで制御可能に
|
||||
|
||||
### Client
|
||||
- Note: 「自動でもっと見る」オプションは無効になっています
|
||||
- Feat: モデログを検索できるように
|
||||
- Enhance: 設定の自動バックアップをオンにした直後に自動バックアップするように
|
||||
- Enhance: ファイルアップロード前にキャプション設定を行えるように
|
||||
- Enhance: ページネーションの並び順を逆にできるように
|
||||
- Enhance: ファイルアップロード時にセンシティブ設定されているか表示するように
|
||||
- Enhance: 投稿フォームにファイルをペースト/ドロップした際のUXを改善
|
||||
- Enhance: ページネーション(一覧表示)の並び順を逆にできるように
|
||||
- Enhance: ページネーション(一覧表示)の基準日時を指定できるように
|
||||
- Enhance: レンダリングパフォーマンスの向上
|
||||
- Fix: ファイルがドライブの既定アップロード先に指定したフォルダにアップロードされない問題を修正
|
||||
- Fix: プラグインをアンインストールしてもセーブデータが残る問題を修正
|
||||
- Fix: 数時間後Misskeyのタブに戻った際に、タブがスロットリングされている間の更新アニメーションを延々見せ続けられる問題を修正
|
||||
- Fix: 非ログイン時のハイライトノートの画像がCWの有無を考慮せず表示される問題を修正
|
||||
- Fix: レンジ選択・ドロップダウンにて、操作を無効にすべきところで無効にならない問題を修正
|
||||
- Fix: Pull to refreshが有効なときに横スクロールができない問題を修正
|
||||
|
||||
### Server
|
||||
- Enhance: sinceId/untilIdが指定可能なエンドポイントにおいて、sinceDate/untilDateも指定可能に
|
||||
- Enhance: メールの送信者としてサーバー名を表示するように (サーバー名が設定されている場合)
|
||||
- Fix: ジョブキューのProgressの値を正しく計算する
|
||||
|
||||
|
||||
@@ -107,7 +563,7 @@
|
||||
- Enhance: 画像の高品質なプレースホルダを無効化してパフォーマンスを向上させるオプションを追加
|
||||
- Enhance: 招待されているが参加していないルームを開いたときに、招待を承認するかどうか尋ねるように
|
||||
- Enhance: リプライ元にアンケートがあることが表示されるように
|
||||
- Enhance: ノートのサーバー情報のデザインを改善・パフォーマンス向上
|
||||
- Enhance: ノートのサーバー情報のデザインを改善・パフォーマンス向上
|
||||
(Based on https://github.com/taiyme/misskey/pull/198, https://github.com/taiyme/misskey/pull/211, https://github.com/taiyme/misskey/pull/283)
|
||||
- Enhance: ユーザー設定でURLプレビューを無効化できるように
|
||||
- Enhance: ヒントとコツを追加
|
||||
@@ -196,7 +652,7 @@
|
||||
|
||||
### Server
|
||||
- Enhance: ジョブキューの成功/失敗したジョブも一定数・一定期間保存するようにし、後から問題を調査することを容易に
|
||||
- Enhance: フォローしているユーザーならフォロワー限定投稿のノートでもアンテナで検知できるように
|
||||
- Enhance: フォローしているユーザーならフォロワー限定投稿のノートでもアンテナで検知できるように
|
||||
(Cherry-picked from https://github.com/yojo-art/cherrypick/pull/568 and https://github.com/team-shahu/misskey/pull/38)
|
||||
- Enhance: ユーザーごとにノートの表示が高速化するように
|
||||
- Fix: システムアカウントの名前がサーバー名と同期されない問題を修正
|
||||
@@ -302,7 +758,7 @@
|
||||
|
||||
### General
|
||||
- Enhance: プロキシアカウントをシステムアカウントとして作成するように
|
||||
- Enhance: OAuthで外部アプリからロゴが提供されている場合、それを表示できるように
|
||||
- Enhance: OAuthで外部アプリからロゴが提供されている場合、それを表示できるように
|
||||
書式は https://indieauth.spec.indieweb.org/20220212/#example-2 に準じます。
|
||||
- Fix: システムアカウントが削除できる問題を修正
|
||||
|
||||
@@ -316,7 +772,7 @@
|
||||
|
||||
### Server
|
||||
- Fix: 特定のケースでActivityPubの処理がデッドロックになることがあるのを修正
|
||||
- Fix: S3互換オブジェクトストレージでファイルのアップロードに失敗することがある問題を修正
|
||||
- Fix: S3互換オブジェクトストレージでファイルのアップロードに失敗することがある問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/895)
|
||||
|
||||
|
||||
@@ -337,7 +793,7 @@
|
||||
- Enhance: リアクションする際に確認ダイアログを表示できるように
|
||||
- Enhance: コントロールパネルのユーザ検索で入力された情報をページ遷移で損なわないように `#15437`
|
||||
- Enhance: CWの注釈で入力済みの文字数を表示
|
||||
- Enhance: ノート検索ページのデザイン調整
|
||||
- Enhance: ノート検索ページのデザイン調整
|
||||
(Cherry-picked from https://github.com/taiyme/misskey/pull/273)
|
||||
- Fix: ノートページで、クリップ一覧が表示されないことがある問題を修正
|
||||
- Fix: コンディショナルロールを手動で割り当てできる導線を削除 `#13529`
|
||||
@@ -354,7 +810,7 @@
|
||||
- Fix: `following/invalidate`でフォロワーを解除しようとしているユーザーの情報を返すように
|
||||
- Fix: オブジェクトストレージの設定でPrefixを設定していなかった場合nullまたは空文字になる問題を修正
|
||||
- Fix: HTTPプロキシとその除外設定を行った状態でカスタム絵文字の一括インポートをしたとき、除外設定が効かないのを修正( #8766 )
|
||||
- Fix: pgroongaでの検索時にはじめのキーワードのみが検索に使用される問題を修正
|
||||
- Fix: pgroongaでの検索時にはじめのキーワードのみが検索に使用される問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/886)
|
||||
- Fix: メールアドレスの形式が正しくなければ以降の処理を行わないように
|
||||
- Fix: `update-meta`でobjectStoragePrefixにS3_SAFEかつURL-safeでない文字列を使えないように
|
||||
@@ -364,12 +820,12 @@
|
||||
## 2025.2.0
|
||||
|
||||
### General
|
||||
- Fix: Docker のビルドに失敗する問題を修正
|
||||
- Fix: Docker のビルドに失敗する問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/883)
|
||||
|
||||
### Client
|
||||
- Fix: パスキーでパスワードレスログインが出来ない問題を修正
|
||||
- Fix: 一部環境でセンシティブなファイルを含むノートの非表示が効かない問題
|
||||
- Fix: 一部環境でセンシティブなファイルを含むノートの非表示が効かない問題
|
||||
- Fix: データセーバー有効時にもユーザーページの「ファイル」タブで画像が読み込まれてしまう問題を修正
|
||||
- Fix: MFMの `sparkle` エフェクトが正しく表示されない問題を修正
|
||||
- Fix: ページのURLにスラッシュが含まれている場合にページが正しく表示されない問題を修正
|
||||
@@ -396,14 +852,14 @@
|
||||
* β版として公開のため、旧画面も引き続き利用可能です
|
||||
|
||||
### Client
|
||||
- Enhance: PC画面でチャンネルが複数列で表示されるように
|
||||
- Enhance: PC画面でチャンネルが複数列で表示されるように
|
||||
(Cherry-picked from https://github.com/Otaku-Social/maniakey/pull/13)
|
||||
- Enhance: 照会に失敗した場合、その理由を表示するように
|
||||
- Enhance: ワードミュートで検知されたワードを表示できるように
|
||||
- Enhance: リモートのノートのリンクをコピーできるように
|
||||
- Enhance: 連合がホワイトリスト化・無効化されているサーバー向けのデザイン修正
|
||||
- Enhance: AiScriptのセーブデータを明示的に削除する関数`Mk:remove`を追加
|
||||
- Enhance: ノートの添付ファイルを一覧で遡れる「ファイル」タブを追加
|
||||
- Enhance: ノートの添付ファイルを一覧で遡れる「ファイル」タブを追加
|
||||
(Based on https://github.com/Otaku-Social/maniakey/pull/14)
|
||||
- Enhance: AiScriptの拡張API関数において引数の型チェックをより厳格に
|
||||
- Enhance: クエリパラメータでuiを一時的に変更できるように #15240
|
||||
@@ -411,26 +867,26 @@
|
||||
- Fix: 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
|
||||
- Fix: サーバー情報メニューに区切り線が不足していたのを修正
|
||||
- Fix: ノートがログインしているユーザーしか見れない場合にログインダイアログを閉じるとその後の動線がなくなる問題を修正
|
||||
- Fix: 公開範囲がホームのノートの埋め込みウィジェットが読み込まれない問題を修正
|
||||
- Fix: 公開範囲がホームのノートの埋め込みウィジェットが読み込まれない問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/803)
|
||||
- Fix: 絵文字管理画面で一部の絵文字が表示されない問題を修正
|
||||
- Fix: プラグイン `register_note_view_interruptor` でノートのサーバー情報の書き換えができない問題を修正
|
||||
- Fix: Botプロテクションの設定変更時は実際に検証を通過しないと保存できないように( #15137 )
|
||||
- Fix: ノート検索が使用できない場合でもチャンネルのノート検索欄がでていた問題を修正
|
||||
- Fix: `Ui:C:select`で値の変更が画面に反映されない問題を修正
|
||||
- Fix: MiAuth認可画面で、認可処理に失敗した場合でもコールバックURLに遷移してしまう問題を修正
|
||||
- Fix: MiAuth認可画面で、認可処理に失敗した場合でもコールバックURLに遷移してしまう問題を修正
|
||||
(Cherry-picked from https://github.com/TeamNijimiss/misskey/commit/800359623e41a662551d774de15b0437b6849bb4)
|
||||
- Fix: ノート作成画面でファイルの添付可能個数を超えてもノートボタンが押せていた問題を修正
|
||||
- Fix: 「アカウントを管理」画面で、ユーザー情報の取得に失敗したアカウント(削除されたアカウントなど)が表示されない問題を修正
|
||||
- Fix: MacOSでChrome系ブラウザを使用している場合に、Misskeyを閉じた際に他のタブのオーディオ機能と干渉する問題を修正
|
||||
- Fix: 言語データのキャッシュ状況によっては、埋め込みウィジェットが正しく起動しない問題を修正
|
||||
- Fix: 「削除して編集」でノートの引用を解除出来なかった問題を修正( #14476 )
|
||||
- Fix: RSSウィジェットが正しく表示されない問題を修正
|
||||
- Fix: RSSウィジェットが正しく表示されない問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/857)
|
||||
- Fix: ワードミュートの保存失敗時にAPIエラーが握りつぶされる事があるのを修正
|
||||
- Fix: アンケートでリモートの絵文字が正しく描画できない問題の修正
|
||||
(Cherry-picked from https://github.com/yojo-art/cherrypick/pull/153)
|
||||
- Fix: 非ログイン時のサーバー概要画面のメニューボタンが押せないことがあるのを修正
|
||||
- Fix: 非ログイン時のサーバー概要画面のメニューボタンが押せないことがあるのを修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/656)
|
||||
- Fix: URLにはじめから`#pswp`が含まれている場合に画像ビューワーがブラウザの戻るボタンで閉じられない問題を修正
|
||||
- Fix: ロール作成画面で設定できるアイコンデコレーションの最大取付個数を16に制限
|
||||
@@ -439,18 +895,18 @@
|
||||
### Server
|
||||
- Enhance: pg_bigmが利用できるよう、ノートの検索をILIKE演算子でなくLIKE演算子でLOWER()をかけたテキストに対して行うように
|
||||
- Enhance: ノート検索の選択肢としてpgroongaに対応 ( #14730 )
|
||||
- Enhance: チャート更新時にDBに同時接続しないように
|
||||
- Enhance: チャート更新時にDBに同時接続しないように
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/830)
|
||||
- Enhance: config(default.yml)からSQLログ全文を出力するか否かを設定可能に ( #15266 )
|
||||
- Fix: ユーザーのプロフィール画面をアドレス入力などで直接表示した際に概要タブの描画に失敗する問題の修正( #15032 )
|
||||
- Fix: 起動前の疎通チェックが機能しなくなっていた問題を修正
|
||||
- Fix: 起動前の疎通チェックが機能しなくなっていた問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/737)
|
||||
- Fix: ノートの閲覧にログイン必須にしてもFeedでノートが表示されてしまう問題を修正
|
||||
- Fix: 絵文字の連合でライセンス欄を相互にやり取りするように ( #10859, #14109 )
|
||||
- Fix: ロックダウンされた期間指定のノートがStreaming経由でLTLに出現するのを修正 ( #15200 )
|
||||
- Fix: disableClustering設定時の初期化ロジックを調整( #15223 )
|
||||
- Fix: URLとURIが異なるエンティティの照会に失敗する問題を修正( #15039 )
|
||||
- Fix: ActivityPubリクエストかどうかの判定が正しくない問題を修正
|
||||
- Fix: ActivityPubリクエストかどうかの判定が正しくない問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/869)
|
||||
- Fix: `/api/pages/update`にて`name`を指定せずにリクエストするとエラーが発生する問題を修正
|
||||
- Fix: AIセンシティブ判定が arm64 環境で動作しない問題を修正
|
||||
@@ -476,12 +932,12 @@
|
||||
- Fix: お知らせ作成時に画像URL入力欄を空欄に変更できないのを修正 ( #14976 )
|
||||
|
||||
### Client
|
||||
- Enhance: Bull DashboardでRelationship Queueの状態も確認できるように
|
||||
- Enhance: Bull DashboardでRelationship Queueの状態も確認できるように
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/751)
|
||||
- Enhance: ドライブでソートができるように
|
||||
- Enhance: アイコンデコレーション管理画面の改善
|
||||
- Enhance: 「単なるラッキー」の取得条件を変更
|
||||
- Enhance: 投稿フォームでEscキーを押したときIME入力中ならフォームを閉じないように( #10866 )
|
||||
- Enhance: 投稿フォームでEscキーを押したときIME入力中ならフォームを閉じないように( #10866 )
|
||||
- Enhance: MiAuth, OAuthの認可画面の改善
|
||||
- どのアカウントで認証しようとしているのかがわかるように
|
||||
- 認証するアカウントを切り替えられるように
|
||||
@@ -489,29 +945,29 @@
|
||||
- Enhance: カタルーニャ語 (ca-ES) に対応
|
||||
- Enhance: 個別お知らせページではMetaタグを出力するように
|
||||
- Enhance: ノート詳細画面にロールのバッジを表示
|
||||
- Enhance: 過去に送信したフォローリクエストを確認できるように
|
||||
- Enhance: 過去に送信したフォローリクエストを確認できるように
|
||||
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/663)
|
||||
- Enhance: サイドバーを簡単に展開・折りたたみできるように ( #14981 )
|
||||
- Enhance: リノートメニューに「リノートの詳細」を追加
|
||||
- Enhance: 非ログイン状態でMisskeyを開いた際のパフォーマンスを向上
|
||||
- Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
|
||||
- Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正
|
||||
- Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
|
||||
- Fix: デッキのタイムラインカラムで「センシティブなファイルを含むノートを表示」設定が使用できなかった問題を修正
|
||||
- Fix: Encode RSS urls with escape sequences before fetching allowing query parameters to be used
|
||||
- Fix: リンク切れを修正
|
||||
- Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正
|
||||
- Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正
|
||||
(Cherry-picked from https://github.com/taiyme/misskey/pull/305)
|
||||
- Fix: メールアドレス登録有効化時の「完了」ダイアログボックスの表示条件を修正
|
||||
- Fix: 画面幅が狭い環境でデザインが崩れる問題を修正
|
||||
- Fix: 画面幅が狭い環境でデザインが崩れる問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/815)
|
||||
- Fix: TypeScriptの型チェック対象ファイルを限定してビルドを高速化するように
|
||||
- Fix: TypeScriptの型チェック対象ファイルを限定してビルドを高速化するように
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/725)
|
||||
|
||||
### Server
|
||||
- Enhance: DockerのNode.jsを22.11.0に更新
|
||||
- Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように
|
||||
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)
|
||||
- Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように
|
||||
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/715)
|
||||
- Enhance: リモートユーザーの照会をオリジナルにリダイレクトするように
|
||||
- Fix: sharedInboxが無いActorに紐づくリモートユーザーを照会できない
|
||||
@@ -519,18 +975,18 @@
|
||||
- Fix: フォロワーへのメッセージの絵文字をemojisに含めるように
|
||||
- Fix: Nested proxy requestsを検出した際にブロックするように
|
||||
[ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)
|
||||
- Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正
|
||||
- Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/706)
|
||||
- Fix: 連合への配信時に、acctの大小文字が区別されてしまい正しくメンションが処理されないことがある問題を修正
|
||||
- Fix: 連合への配信時に、acctの大小文字が区別されてしまい正しくメンションが処理されないことがある問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/711)
|
||||
- Fix: ローカルユーザーへのメンションを含むノートが連合される際に正しいURLに変換されないことがある問題を修正
|
||||
- Fix: ローカルユーザーへのメンションを含むノートが連合される際に正しいURLに変換されないことがある問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/712)
|
||||
- Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正
|
||||
- Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
|
||||
- Fix: User Webhookテスト機能のMock Payloadを修正
|
||||
- Fix: アカウント削除のモデレーションログが動作していないのを修正 (#14996)
|
||||
- Fix: User Webhookテスト機能のMock Payloadを修正
|
||||
- Fix: アカウント削除のモデレーションログが動作していないのを修正 (#14996)
|
||||
- Fix: リノートミュートが新規投稿通知に対して作用していなかった問題を修正
|
||||
- Fix: Inboxの処理で生じるエラーを誤ってActivityとして処理することがある問題を修正
|
||||
- Fix: Inboxの処理で生じるエラーを誤ってActivityとして処理することがある問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/730)
|
||||
- Fix: セキュリティに関する修正
|
||||
|
||||
@@ -557,13 +1013,13 @@
|
||||
- Enhance: 個人宛のお知らせは「わかった」を押すと自動的にアーカイブされるように
|
||||
- Fix: `admin/emoji/update`エンドポイントのidのみ指定した時不正なエラーが発生するバグを修正
|
||||
- Fix: RBT有効時、リノートのリアクションが反映されない問題を修正
|
||||
- Fix: キューのエラーログを簡略化するように
|
||||
- Fix: キューのエラーログを簡略化するように
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/649)
|
||||
|
||||
## 2024.10.0
|
||||
|
||||
### Note
|
||||
- セキュリティ向上のため、サーバー初期設定時に使用する初期パスワードを設定できるようになりました。今後Misskeyサーバーを新たに設置する際には、初回の起動前にコンフィグファイルの`setupPassword`をコメントアウトし、初期パスワードを設定することをおすすめします。(すでに初期設定を完了しているサーバーについては、この変更に伴い対応する必要はありません)
|
||||
- セキュリティ向上のため、サーバー初期設定時に使用する初期パスワードを設定できるようになりました。今後Misskeyサーバーを新たに設置する際には、初回の起動前にコンフィグファイルの`setupPassword`をコメントアウトし、初期パスワードを設定することをおすすめします。(すでに初期設定を完了しているサーバーについては、この変更に伴い対応する必要はありません)
|
||||
- ホスティングサービスを運営している場合は、コンフィグファイルを構築する際に`setupPassword`をランダムな値に設定し、ユーザーに通知するようにシステムを更新することをおすすめします。
|
||||
- なお、初期パスワードが設定されていない場合でも初期設定を行うことが可能です(UI上で初期パスワードの入力欄を空欄にすると続行できます)。
|
||||
- ユーザーデータを読み込む際の型が一部変更されました。
|
||||
@@ -583,7 +1039,7 @@
|
||||
### Client
|
||||
- Enhance: デザインの調整
|
||||
- Enhance: ログイン画面の認証フローを改善
|
||||
- Fix: クライアント上での時間ベースの実績獲得動作が実績獲得後も発動していた問題を修正
|
||||
- Fix: クライアント上での時間ベースの実績獲得動作が実績獲得後も発動していた問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/657)
|
||||
|
||||
### Server
|
||||
@@ -601,7 +1057,7 @@
|
||||
- Feat: フォローされた際のメッセージを設定できるように
|
||||
- Feat: 連合をホワイトリスト制にできるように
|
||||
- Feat: UserWebhookとSystemWebhookのテスト送信機能を追加 (#14445)
|
||||
- Feat: モデレーターはユーザーにかかわらずファイルが添付されているノートを検索できるように
|
||||
- Feat: モデレーターはユーザーにかかわらずファイルが添付されているノートを検索できるように
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/680)
|
||||
- Feat: データエクスポートが完了した際に通知を発行するように
|
||||
- Enhance: ユーザーによるコンテンツインポートの可否をロールポリシーで制御できるように
|
||||
@@ -620,12 +1076,12 @@
|
||||
- Fix: サーバーメトリクスが2つ以上あるとリロード直後の表示がおかしくなる問題を修正
|
||||
- Fix: コントロールパネル内のAp requests内のチャートの表示がおかしかった問題を修正
|
||||
- Fix: 月の違う同じ日はセパレータが表示されないのを修正
|
||||
- Fix: タッチ画面でレンジスライダーを操作するとツールチップが複数表示される問題を修正
|
||||
- Fix: タッチ画面でレンジスライダーを操作するとツールチップが複数表示される問題を修正
|
||||
(Cherry-picked from https://github.com/taiyme/misskey/pull/265)
|
||||
- Fix: 縦横比が極端なカスタム絵文字を表示する際にレイアウトが崩れる箇所があるのを修正
|
||||
- Fix: 縦横比が極端なカスタム絵文字を表示する際にレイアウトが崩れる箇所があるのを修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/725)
|
||||
- Fix: 設定変更時のリロード確認ダイアログが複数個表示されることがある問題を修正
|
||||
- Fix: ファイルの詳細ページのファイルの説明で改行が正しく表示されない問題を修正
|
||||
- Fix: ファイルの詳細ページのファイルの説明で改行が正しく表示されない問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/bde6bb0bd2e8b0d027e724d2acdb8ae0585a8110)
|
||||
- Fix: 一部画面のページネーションが動作しにくくなっていたのを修正 ( #12766 , #11449 )
|
||||
|
||||
@@ -634,14 +1090,14 @@
|
||||
- Fix: アンテナの書き込み時にキーワードが与えられなかった場合のエラーをApiErrorとして投げるように
|
||||
- この変更により、公式フロントエンドでは入力の不備が内部エラーとして報告される代わりに一般的なエラーダイアログで報告されます
|
||||
- Fix: ファイルがサイズの制限を超えてアップロードされた際にエラーを返さなかった問題を修正
|
||||
- Fix: 外部ページを解析する際に、ページに紐づけられた関連リソースも読み込まれてしまう問題を修正
|
||||
- Fix: 外部ページを解析する際に、ページに紐づけられた関連リソースも読み込まれてしまう問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/26e0412fbb91447c37e8fb06ffb0487346063bb8)
|
||||
- Fix: Continue importing from file if single emoji import fails
|
||||
- Fix: `Retry-After`ヘッダーが送信されなかった問題を修正
|
||||
- Fix: `Retry-After`ヘッダーが送信されなかった問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/8a982c61c01909e7540ff1be9f019df07c3f0624)
|
||||
- Fix: サーバーサイドのDOM解析完了時にリソースを開放するように
|
||||
- Fix: サーバーサイドのDOM解析完了時にリソースを開放するように
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/634)
|
||||
- Fix: `<link rel="alternate">`を追って照会するのはOKレスポンスが返却された場合のみに
|
||||
- Fix: `<link rel="alternate">`を追って照会するのはOKレスポンスが返却された場合のみに
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/633)
|
||||
- Fix: メールにスタイルが適用されていなかった問題を修正
|
||||
|
||||
@@ -670,15 +1126,15 @@
|
||||
- 通知ページや通知カラム(デッキ)を開いている状態において、新たに発生した通知が既読されない問題が修正されます。
|
||||
- これにより、プッシュ通知が有効な同条件下の環境において、プッシュ通知が常に発生してしまう問題も修正されます。
|
||||
- Fix: Play各種エンドポイントの返り値に`visibility`が含まれていない問題を修正
|
||||
- Fix: サーバー情報取得の際にモデレーター限定の情報が取得できないことがあるのを修正
|
||||
- Fix: サーバー情報取得の際にモデレーター限定の情報が取得できないことがあるのを修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/582)
|
||||
- Fix: 公開範囲がダイレクトのノートをユーザーアクティビティのチャート生成に使用しないように
|
||||
- Fix: 公開範囲がダイレクトのノートをユーザーアクティビティのチャート生成に使用しないように
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/679)
|
||||
- Fix: ActivityPubのエンティティタイプ判定で不明なタイプを受け取った場合でも処理を継続するように
|
||||
- キュー処理のつまりが改善される可能性があります
|
||||
- Fix: リバーシの対局設定の変更が反映されないのを修正
|
||||
- Fix: 無制限にストリーミングのチャンネルに接続できる問題を修正
|
||||
- Fix: ベースロールのポリシーを変更した際にモデログに記録されないのを修正
|
||||
- Fix: ベースロールのポリシーを変更した際にモデログに記録されないのを修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/700)
|
||||
- Fix: Prevent memory leak from memory caches (#14310)
|
||||
- Fix: More reliable memory cache eviction (#14311)
|
||||
@@ -710,9 +1166,9 @@
|
||||
- Enhance: 内蔵APIドキュメントのデザイン・パフォーマンスを改善
|
||||
- Enhance: 非ログイン時に他サーバーに遷移するアクションを追加
|
||||
- Enhance: 非ログイン時のハイライトTLのデザインを改善
|
||||
- Enhance: フロントエンドのアクセシビリティ改善
|
||||
- Enhance: フロントエンドのアクセシビリティ改善
|
||||
(Based on https://github.com/taiyme/misskey/pull/226)
|
||||
- Enhance: サーバー情報ページ・お問い合わせページを改善
|
||||
- Enhance: サーバー情報ページ・お問い合わせページを改善
|
||||
(Cherry-picked from https://github.com/taiyme/misskey/pull/238)
|
||||
- Enhance: AiScriptを0.19.0にアップデート
|
||||
- Enhance: Allow negative delay for MFM animation elements (`tada`, `jelly`, `twitch`, `shake`, `spin`, `jump`, `bounce`, `rainbow`)
|
||||
@@ -721,7 +1177,7 @@
|
||||
- Enhance: 検索(ノート/ユーザー)において、入力に空白が含まれている場合は照会を行わないように
|
||||
- Enhance: 検索(ノート/ユーザー)において、照会を行うかどうか、ハッシュタグのノート/ユーザー一覧ページを表示するかどうかの確認ダイアログを出すように
|
||||
- Enhance: 検索(ノート/ユーザー)で `@` から始まる文字列(`@user@host`など)を入力すると、そのユーザーを照会できるように
|
||||
- Enhance: ドライブのファイル・フォルダをドラッグしなくても移動できるように
|
||||
- Enhance: ドライブのファイル・フォルダをドラッグしなくても移動できるように
|
||||
(Cherry-picked from https://github.com/nafu-at/misskey/commit/b89c2af6945c6a9f9f10e83f54d2bcf0f240b0b4, https://github.com/nafu-at/misskey/commit/8a7d710c6acb83f50c83f050bd1423c764d60a99)
|
||||
- Enhance: デッキのアンテナ・リスト選択画面からそれぞれを新規作成できるように
|
||||
- Enhance: ブラウザのコンテキストメニューを使用できるように
|
||||
@@ -729,19 +1185,19 @@
|
||||
- Fix: `/about#federation` ページなどで各インスタンスのチャートが表示されなくなっていた問題を修正
|
||||
- Fix: ユーザーページの追加情報のラベルを投稿者のサーバーの絵文字で表示する (#13968)
|
||||
- Fix: リバーシの対局を正しく共有できないことがある問題を修正
|
||||
- Fix: コントロールパネルでベースロールのポリシーを編集してもUI上では変更が反映されない問題を修正
|
||||
- Fix: コントロールパネルでベースロールのポリシーを編集してもUI上では変更が反映されない問題を修正
|
||||
- Fix: アンテナの編集画面のボタンに隙間を追加
|
||||
- Fix: テーマプレビューが見れない問題を修正
|
||||
- Fix: ショートカットキーが連打できる問題を修正
|
||||
- Fix: ショートカットキーが連打できる問題を修正
|
||||
(Cherry-picked from https://github.com/taiyme/misskey/pull/234)
|
||||
- Fix: MkSignin.vueのcredentialRequestからReactivityを削除(ProxyがPasskey認証処理に渡ることを避けるため)
|
||||
- Fix: 「アニメーション画像を再生しない」がオンのときでもサーバーのバナー画像・背景画像がアニメーションしてしまう問題を修正
|
||||
- Fix: 「アニメーション画像を再生しない」がオンのときでもサーバーのバナー画像・背景画像がアニメーションしてしまう問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/574)
|
||||
- Fix: Twitchの埋め込みが開けない問題を修正
|
||||
- Fix: 子メニューの高さがウィンドウからはみ出ることがある問題を修正
|
||||
- Fix: 個人宛てのダイアログ形式のお知らせが即時表示されない問題を修正
|
||||
- Fix: 一部の画像がセンシティブ指定されているときに画面に何も表示されないことがあるのを修正
|
||||
- Fix: リアクションしたユーザー一覧のユーザー名がはみ出る問題を修正
|
||||
- Fix: リアクションしたユーザー一覧のユーザー名がはみ出る問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/672)
|
||||
- Fix: `/share`ページにおいて絵文字ピッカーを開くことができない問題を修正
|
||||
- Fix: deck uiの通知音が重なる問題 (#14029)
|
||||
@@ -784,14 +1240,14 @@
|
||||
4. フォローしていない非アクティブなユーザ
|
||||
|
||||
また、自分自身のアカウントもサジェストされるようになりました。
|
||||
- Fix: 一般ユーザーから見たユーザーのバッジの一覧に公開されていないものが含まれることがある問題を修正
|
||||
- Fix: 一般ユーザーから見たユーザーのバッジの一覧に公開されていないものが含まれることがある問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/652)
|
||||
- Fix: ユーザーのリアクション一覧でミュート/ブロックが機能していなかった問題を修正
|
||||
- Fix: FTT有効時にリモートユーザーのノートがHTLにキャッシュされる問題を修正
|
||||
- Fix: 一部の通知がローカル上のリモートユーザーに対して行われていた問題を修正
|
||||
- Fix: エラーメッセージの誤字を修正 (#14213)
|
||||
- Fix: ソーシャルタイムラインにローカルタイムラインに表示される自分へのリプライが表示されない問題を修正
|
||||
- Fix: リノートのミュートが適用されるまでに時間がかかることがある問題を修正
|
||||
- Fix: リノートのミュートが適用されるまでに時間がかかることがある問題を修正
|
||||
(Cherry-picked from https://github.com/Type4ny-Project/Type4ny/commit/e9601029b52e0ad43d9131b555b614e56c84ebc1)
|
||||
- Fix: Steaming APIが不正なデータを受けた場合の動作が不安定である問題 #14251
|
||||
- Fix: `users/search`において `@` から始まる文字列が与えられた際の処理が正しくなかった問題を修正
|
||||
@@ -818,7 +1274,7 @@
|
||||
### General
|
||||
- Feat: エラートラッキングにSentryを使用できるようになりました
|
||||
- Enhance: URLプレビューの有効化・無効化を設定できるように #13569
|
||||
- Enhance: アンテナでBotによるノートを除外できるように
|
||||
- Enhance: アンテナでBotによるノートを除外できるように
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/545)
|
||||
- Enhance: クリップのノート数を表示するように
|
||||
- Enhance: コンディショナルロールの条件として以下を新たに追加 (#13667)
|
||||
@@ -837,7 +1293,7 @@
|
||||
|
||||
### Client
|
||||
- Feat: アップロードするファイルの名前をランダム文字列にできるように
|
||||
- Feat: 個別のお知らせにリンクで飛べるように
|
||||
- Feat: 個別のお知らせにリンクで飛べるように
|
||||
(Based on https://github.com/MisskeyIO/misskey/pull/639)
|
||||
- Enhance: 自分のノートの添付ファイルから直接ファイルの詳細ページに飛べるように
|
||||
- Enhance: 広告がMisskeyと同一ドメインの場合はRouterで遷移するように
|
||||
@@ -867,9 +1323,9 @@
|
||||
- Fix: 一部のページ内リンクが正しく動作しない問題を修正
|
||||
- Fix: 周年の実績が閏年を考慮しない問題を修正
|
||||
- Fix: ローカルURLのプレビューポップアップが左上に表示される
|
||||
- Fix: WebGL2をサポートしないブラウザで「季節に応じた画面の演出」が有効になっているとき、Misskeyが起動できなくなる問題を修正
|
||||
- Fix: WebGL2をサポートしないブラウザで「季節に応じた画面の演出」が有効になっているとき、Misskeyが起動できなくなる問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/459)
|
||||
- Fix: ページタイトルでローカルユーザーとリモートユーザーの区別がつかない問題を修正
|
||||
- Fix: ページタイトルでローカルユーザーとリモートユーザーの区別がつかない問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/528)
|
||||
- Fix: コードブロックのシンタックスハイライトで使用される定義ファイルをCDNから取得するように #13177
|
||||
- CDNから取得せずMisskey本体にバンドルする場合は`pacakges/frontend/vite.config.ts`を修正してください。
|
||||
@@ -892,13 +1348,13 @@
|
||||
- Enhance: ドライブのファイルがNSFWかどうか個別に連合されるように (#13756)
|
||||
- 可能な場合、ノートの添付ファイルのセンシティブ判定がファイル単位になります
|
||||
- Fix: リモートから配送されたアクティビティにJSON-LD compactionをかける
|
||||
- Fix: フォローリクエストを作成する際に既存のものは削除するように
|
||||
- Fix: フォローリクエストを作成する際に既存のものは削除するように
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/440)
|
||||
- Fix: エンドポイント`notes/translate`のエラーを改善
|
||||
- Fix: CleanRemoteFilesProcessorService report progress from 100% (#13632)
|
||||
- Fix: 一部の音声ファイルが映像ファイルとして扱われる問題を修正
|
||||
- Fix: リプライのみの引用リノートと、CWのみの引用リノートが純粋なリノートとして誤って扱われてしまう問題を修正
|
||||
- Fix: 登録にメール認証が必須になっている場合、登録されているメールアドレスを削除できないように
|
||||
- Fix: 登録にメール認証が必須になっている場合、登録されているメールアドレスを削除できないように
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/606)
|
||||
- Fix: Add Cache-Control to Bull Board
|
||||
- Fix: nginx経由で/files/にRangeリクエストされた場合に正しく応答できないのを修正
|
||||
@@ -1091,10 +1547,10 @@
|
||||
### Note
|
||||
- 依存関係の更新に伴い、Node.js 20.10.0が最小要件になりました
|
||||
- 絵文字の追加辞書を既にインストールしている場合は、お手数ですが再インストールのほどお願いします
|
||||
- 絵文字ピッカーにピン留め表示する絵文字設定が「リアクション用」と「絵文字入力用」に分かれました。以前の設定は「リアクション用」として使用されます。
|
||||
- 絵文字ピッカーにピン留め表示する絵文字設定が「リアクション用」と「絵文字入力用」に分かれました。以前の設定は「リアクション用」として使用されます。
|
||||
|
||||
**影響:**
|
||||
それにより、投稿フォームから表示される絵文字ピッカーのピン留め絵文字がリセットされたように感じるかもしれません(新設された"ピン留め(全般)"の設定が使われるため)。
|
||||
**影響:**
|
||||
それにより、投稿フォームから表示される絵文字ピッカーのピン留め絵文字がリセットされたように感じるかもしれません(新設された"ピン留め(全般)"の設定が使われるため)。
|
||||
投稿用のピン留め絵文字をアップデート前の状態にするには、以下の手順で操作します。
|
||||
|
||||
1. 「設定」メニューに移動し、「絵文字ピッカー」タブを選択します。
|
||||
@@ -1141,7 +1597,7 @@
|
||||
- Enhance: Unicode 15.0のサポート
|
||||
- Enhance: コードブロックのハイライト機能を利用するには言語を明示的に指定させるように
|
||||
- MFMでコードブロックを利用する際に意図しないハイライトが起こらないようになりました
|
||||
- 逆に、MFMでコードハイライトを利用したい際は言語を明示的に指定する必要があります
|
||||
- 逆に、MFMでコードハイライトを利用したい際は言語を明示的に指定する必要があります
|
||||
(例: ` ```js ` → Javascript, ` ```ais ` → AiScript)
|
||||
- Enhance: 絵文字などのオートコンプリートでShift+Tabを押すと前の候補を選択できるように
|
||||
- Enhance: チャンネルに新規の投稿がある場合にバッジを表示させる
|
||||
@@ -1548,9 +2004,9 @@
|
||||
|
||||
### General
|
||||
- 招待機能を改善しました
|
||||
* 過去に発行した招待コードを確認できるようになりました
|
||||
* ロールごとに招待コードの発行数制限と制限対象期間、有効期限を設定できるようになりました
|
||||
* 招待コードを作成したユーザーと使用したユーザーを確認できるようになりました
|
||||
* 過去に発行した招待コードを確認できるようになりました
|
||||
* ロールごとに招待コードの発行数制限と制限対象期間、有効期限を設定できるようになりました
|
||||
* 招待コードを作成したユーザーと使用したユーザーを確認できるようになりました
|
||||
- ユーザーにロールが期限付きでアサインされている場合、その期限をユーザーのモデレーションページで確認できるようになりました
|
||||
- identicon生成を無効にしてパフォーマンスを向上させることができるようになりました
|
||||
- サーバーのマシン情報の公開を無効にしてパフォーマンスを向上させることができるようになりました
|
||||
@@ -1713,9 +2169,9 @@ Meilisearchの設定に`index`が必要になりました。値はMisskeyサー
|
||||
* 「フォロワーのみ」の投稿は検索結果に表示されません。
|
||||
- 新規登録前に簡潔なルールをユーザーに表示できる、サーバールール機能を追加
|
||||
- ユーザーへの自分用メモ機能
|
||||
* ユーザーに対して、自分だけが見られるメモを追加できるようになりました。
|
||||
* ユーザーに対して、自分だけが見られるメモを追加できるようになりました。
|
||||
(自分自身に対してもメモを追加できます。)
|
||||
* ユーザーメニューから追加できます。
|
||||
* ユーザーメニューから追加できます。
|
||||
(デスクトップ表示ではusernameの右側のボタンからも追加可能)
|
||||
- チャンネルに色を設定できるようになりました。各ノートに設定した色のインジケーターが表示されます。
|
||||
- チャンネルをアーカイブできるようになりました。
|
||||
|
||||
7
CLAUDE.md
Normal file
7
CLAUDE.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Misskey – Claude Code Guide
|
||||
|
||||
ルール本体は [AGENTS.md](AGENTS.md) (Codex / Copilot と共有する単一ソース)。本ファイルは Claude Code 用の薄いラッパーで、`@AGENTS.md` 構文で本体規約をセッション開始時にコンテキストへ展開する。
|
||||
|
||||
Claude Code 固有の補助 (skills / agents / slash commands / docs) は `.claude/` 配下にコミット済。個人ローカル設定は `.claude/settings.local.json` に、MCP 認証情報は `.claude/.credentials.json` に置く (いずれも `.gitignore` 済)。
|
||||
|
||||
@AGENTS.md
|
||||
@@ -189,6 +189,14 @@ pnpm migrate
|
||||
|
||||
After finishing the migration, you can proceed.
|
||||
|
||||
#### Cloudflare tunnel
|
||||
Cloudflare tunnelを使うとローカルのMisskeyサーバーをインターネットに公開できます。
|
||||
HTTPSでしか動作しない機能を検証したい時や、スマホなど別のデバイスからローカルのMisskeyサーバーを検証したい時に便利です。
|
||||
|
||||
##### Cloudflare warpと併用する際のtips
|
||||
|
||||
> cloudflared (Cloudflare Tunnel) は region1.v2.argotunnel.com / region2.v2.argotunnel.com に QUIC/HTTP2 でアウトバウンド接続するのですが、WARP を有効化するとこのトラフィックが WARP 経由になってループ/切断します。これら 2 ホストを WARP のトンネル除外(split tunnel)に追加することで、cloudflared だけは WARP をバイパスして直接 Cloudflare エッジへ接続できるようになります。
|
||||
|
||||
### Start developing
|
||||
During development, it is useful to use the
|
||||
```
|
||||
@@ -575,11 +583,12 @@ enumの列挙の内容の削除は、その値をもつレコードを全て削
|
||||
### Migration作成方法
|
||||
packages/backendで:
|
||||
```sh
|
||||
pnpm dlx typeorm migration:generate -d ormconfig.js -o <migration name>
|
||||
pnpm dlx typeorm migration:generate -d ormconfig.js -o --esm <migration name>
|
||||
```
|
||||
|
||||
- 生成後、ファイルをmigration下に移してください
|
||||
- 作成されたスクリプトは不必要な変更を含むため除去してください
|
||||
- `-o` (`--outputJs`) で JS 形式、`--esm` で ESM 形式に生成する。Misskey の既存 migration はすべて ESM JS なので両方のオプションが必要
|
||||
|
||||
### コネクションには`markRaw`せよ
|
||||
**Vueのコンポーネントのdataオプションとして**misskey.jsのコネクションを設定するとき、必ず`markRaw`でラップしてください。インスタンスが不必要にリアクティブ化されることで、misskey.js内の処理で不具合が発生するとともに、パフォーマンス上の問題にも繋がる。なお、Composition APIを使う場合はこの限りではない(リアクティブ化はマニュアルなため)。
|
||||
@@ -618,3 +627,23 @@ color: hsl(from var(--MI_THEME-accent) h s calc(l - 10));
|
||||
color: color(from var(--MI_THEME-accent) srgb r g b / 0.5);
|
||||
```
|
||||
|
||||
## 考え方
|
||||
### DRYに囚われるな
|
||||
必要なのは一般化ではなく抽象化と考えます。
|
||||
盲信せず、誤った・不必要な共通化は避け、それが自然だと感じる場合は重複させる勇気を持ちましょう。
|
||||
|
||||
### Misskeyを複雑にしない実装
|
||||
それがいくら複雑であっても、Misskey固有のコンテキストと関心が分離されている(もしくは事実上分離されていると見做すことができる)実装であれば、それはMisskeyのコードベースに対する複雑性に影響を与えないと考えます。
|
||||
|
||||
例えるなら、VueやAiScriptといったMisskeyが使用しているライブラリの内部実装がいくら複雑だったとしても、「それを使用しているからMisskeyの実装は複雑である」ということにはならないのと同じです。
|
||||
|
||||
Misskeyのドメイン知識から関心が分離されているということは、Misskeyの実装について考える時にそれらの内部実装を考慮する必要が無く、認知負荷を増やさないからです。
|
||||
|
||||
また重要な点は、その実装が、Misskeyリポジトリの外部にあるか・内部にあるかということや、Misskeyがメンテナンスするものか・第三者がメンテナンスするものかといったことは複雑性を考える上ではほとんど無視できるという点です。
|
||||
|
||||
もちろんその実装がMisskeyリポジトリにあり、Misskeyがメンテナンスしなければならないものは、保守のコストはかかります。
|
||||
しかし、Misskeyの本質的な設計・実装という観点で見たときは、その実装は実質的に外部ライブラリのように振る舞います。
|
||||
換言すれば「たまたまMisskeyの開発者と同じ人たちがメンテナンスしているし、たまたまMisskeyのリポジトリ内に置いてあるだけの外部ライブラリ」です。
|
||||
|
||||
そのため、実装をなるべくMisskeyのドメイン知識から独立したものにすれば、Misskeyのコードベースの複雑性を上げることなく機能実装を行うことができ、お得であると言えます。
|
||||
もちろんそれにこだわって、些細な実装でもそのように分離してしまうとかえって認知負荷が増えたり、実装量が増えてメリットをデメリットが上回る場合もあるので、ケースバイケースではあります。
|
||||
|
||||
9
COPYING
9
COPYING
@@ -1,15 +1,8 @@
|
||||
Unless otherwise stated this repository is
|
||||
Copyright © 2014-2025 syuilo and contributors
|
||||
Copyright © 2014-2026 syuilo and contributors
|
||||
|
||||
And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE.
|
||||
|
||||
|
||||
Misskey includes several third-party Open-Source softwares.
|
||||
|
||||
Emoji keywords for Unicode 11 and below by Mu-An Chiou
|
||||
License: MIT
|
||||
https://github.com/muan/emojilib/blob/master/LICENSE
|
||||
|
||||
RsaSignature2017 implementation by Transmute Industries Inc
|
||||
License: MIT
|
||||
https://github.com/transmute-industries/RsaSignature2017/blob/master/LICENSE
|
||||
|
||||
10
Dockerfile
10
Dockerfile
@@ -1,6 +1,6 @@
|
||||
# syntax = docker/dockerfile:1.4
|
||||
# syntax = docker/dockerfile:1.23
|
||||
|
||||
ARG NODE_VERSION=22.15.0-bookworm
|
||||
ARG NODE_VERSION=22.22.2-bookworm
|
||||
|
||||
# build assets & compile TypeScript
|
||||
|
||||
@@ -18,10 +18,13 @@ WORKDIR /misskey
|
||||
|
||||
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
|
||||
COPY --link ["scripts", "./scripts"]
|
||||
COPY --link ["patches", "./patches"]
|
||||
COPY --link ["packages/backend/package.json", "./packages/backend/"]
|
||||
COPY --link ["packages/frontend-shared/package.json", "./packages/frontend-shared/"]
|
||||
COPY --link ["packages/frontend/package.json", "./packages/frontend/"]
|
||||
COPY --link ["packages/frontend-embed/package.json", "./packages/frontend-embed/"]
|
||||
COPY --link ["packages/frontend-builder/package.json", "./packages/frontend-builder/"]
|
||||
COPY --link ["packages/i18n/package.json", "./packages/i18n/"]
|
||||
COPY --link ["packages/icons-subsetter/package.json", "./packages/icons-subsetter/"]
|
||||
COPY --link ["packages/sw/package.json", "./packages/sw/"]
|
||||
COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
|
||||
@@ -53,6 +56,7 @@ WORKDIR /misskey
|
||||
|
||||
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
|
||||
COPY --link ["scripts", "./scripts"]
|
||||
COPY --link ["patches", "./patches"]
|
||||
COPY --link ["packages/backend/package.json", "./packages/backend/"]
|
||||
COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
|
||||
COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"]
|
||||
@@ -98,7 +102,7 @@ COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-js/
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-reversi/built ./packages/misskey-reversi/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-bubble-game/built ./packages/misskey-bubble-game/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/built ./packages/backend/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/fluent-emojis /misskey/fluent-emojis
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/i18n/built ./packages/i18n/built
|
||||
COPY --chown=misskey:misskey . ./
|
||||
|
||||
ENV LD_PRELOAD=/usr/local/lib/libjemalloc.so
|
||||
|
||||
14
README.md
14
README.md
@@ -24,6 +24,10 @@
|
||||
<a href="https://www.patreon.com/syuilo">
|
||||
<img src="https://custom-icon-badges.herokuapp.com/badge/become_a-patron-F96854?logoColor=F96854&style=for-the-badge&logo=patreon&labelColor=363B40" alt="become a patron"/></a>
|
||||
|
||||
[](https://deepwiki.com/misskey-dev/misskey)
|
||||
|
||||
<a href="https://flatt.tech/oss/gmo/trampoline" target="_blank"><img src="https://flatt.tech/assets/images/badges/gmo-oss.svg" height="24px"/></a>
|
||||
|
||||
</div>
|
||||
|
||||
## Thanks
|
||||
@@ -47,3 +51,13 @@ Thanks to [Crowdin](https://crowdin.com/) for providing the localization platfor
|
||||
<a href="https://hub.docker.com/"><img src="https://user-images.githubusercontent.com/20679825/230148221-f8e73a32-a49b-47c3-9029-9a15c3824f92.png" height="30" alt="Docker" /></a>
|
||||
|
||||
Thanks to [Docker](https://hub.docker.com/) for providing the container platform that helps us run Misskey in production.
|
||||
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
|
||||
Support us with a ⭐ !
|
||||
|
||||
[](https://star-history.com/#misskey-dev/misskey&Date)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@ Also, the later tasks are more indefinite and are subject to change as developme
|
||||
This is the phase we are at now. We need to make a high-maintenance environment that can withstand future development.
|
||||
|
||||
- ~~Make the number of type errors zero (backend)~~ → Done ✔️
|
||||
- Make the number of type errors zero (frontend)
|
||||
- ~~Make the number of type errors zero (frontend)~~ → Done ✔️
|
||||
- Improve CI
|
||||
- ~~Fix tests~~ → Done ✔️
|
||||
- Fix random test failures - https://github.com/misskey-dev/misskey/issues/7985 and https://github.com/misskey-dev/misskey/issues/7986
|
||||
|
||||
@@ -190,6 +190,9 @@ id: "aidx"
|
||||
# Number of worker processes
|
||||
#clusterLimit: 1
|
||||
|
||||
# Number of threads of extra thread pool for CPU-intensive tasks (per worker)
|
||||
#threadPoolSize: 1
|
||||
|
||||
# Job concurrency per worker
|
||||
# deliverJobConcurrency: 128
|
||||
# inboxJobConcurrency: 16
|
||||
|
||||
@@ -27,7 +27,7 @@ spec:
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
- name: postgres
|
||||
image: postgres:15-alpine
|
||||
image: postgres:18-alpine
|
||||
env:
|
||||
- name: POSTGRES_USER
|
||||
value: "example-misskey-user"
|
||||
|
||||
@@ -15,13 +15,13 @@ services:
|
||||
|
||||
db:
|
||||
restart: always
|
||||
image: postgres:15-alpine
|
||||
image: postgres:18-alpine
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env_file:
|
||||
- .config/docker.env
|
||||
volumes:
|
||||
- ./db:/var/lib/postgresql/data
|
||||
- ./db:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
||||
interval: 5s
|
||||
|
||||
@@ -37,13 +37,13 @@ services:
|
||||
|
||||
db:
|
||||
restart: always
|
||||
image: postgres:15-alpine
|
||||
image: postgres:18-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
env_file:
|
||||
- .config/docker.env
|
||||
volumes:
|
||||
- ./db:/var/lib/postgresql/data
|
||||
- ./db:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
||||
interval: 5s
|
||||
|
||||
@@ -78,6 +78,8 @@ describe('After setup instance', () => {
|
||||
cy.get('[data-cy-signup-password] input').type('alice1234');
|
||||
cy.get('[data-cy-signup-submit]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-password-retype] input').type('alice1234');
|
||||
cy.get('[data-cy-signup-submit]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-invitation-code] input').type('test-invitation-code');
|
||||
cy.get('[data-cy-signup-submit]').should('not.be.disabled');
|
||||
cy.get('[data-cy-signup-submit]').click();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["dom", "es5"],
|
||||
"target": "es5",
|
||||
"lib": ["dom"],
|
||||
"target": "esnext",
|
||||
"types": ["cypress", "node"]
|
||||
},
|
||||
"include": ["./**/*.ts"]
|
||||
|
||||
Submodule fluent-emojis deleted from cae981eb4c
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { StoryObj } from '@storybook/vue3';
|
||||
import { action } from 'storybook/actions';
|
||||
import type { StoryObj } from '@storybook/vue3';
|
||||
import { HttpResponse, http } from 'msw';
|
||||
import { abuseUserReport } from '../packages/frontend/.storybook/fakes.js';
|
||||
import { commonHandlers } from '../packages/frontend/.storybook/mocks.js';
|
||||
|
||||
232
idea/MkAnimatedBg.dotted-ripples.vue
Normal file
232
idea/MkAnimatedBg.dotted-ripples.vue
Normal file
@@ -0,0 +1,232 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<canvas ref="canvasEl" style="display: block; width: 100%; height: 100%; pointer-events: none;"></canvas>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, useTemplateRef } from 'vue';
|
||||
import isChromatic from 'chromatic/isChromatic';
|
||||
import { initShaderProgram } from '@/utility/webgl.js';
|
||||
|
||||
const VERTEX_SHADER = `#version 300 es
|
||||
in vec2 position;
|
||||
out vec2 in_uv;
|
||||
|
||||
void main() {
|
||||
in_uv = (position + 1.0) / 2.0;
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const FRAGMENT_SHADER = `#version 300 es
|
||||
precision mediump float;
|
||||
|
||||
const float PI = 3.141592653589793;
|
||||
const float TWO_PI = 6.283185307179586;
|
||||
const float HALF_PI = 1.5707963267948966;
|
||||
|
||||
in vec2 in_uv;
|
||||
uniform vec2 in_resolution;
|
||||
uniform float u_scale;
|
||||
uniform float u_time;
|
||||
uniform float u_seed;
|
||||
uniform float u_angle;
|
||||
uniform float u_radius;
|
||||
uniform vec3 u_color;
|
||||
uniform vec2 u_ripplePositions[16];
|
||||
uniform float u_rippleRadiuses[16];
|
||||
out vec4 out_color;
|
||||
|
||||
float getRipple(vec2 uv) {
|
||||
float strength = 0.0;
|
||||
float thickness = 0.05;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (u_rippleRadiuses[i] <= 0.0) continue;
|
||||
|
||||
float d = distance(uv, u_ripplePositions[i]);
|
||||
|
||||
// フチ
|
||||
if (d < u_rippleRadiuses[i] + thickness && d > u_rippleRadiuses[i] - thickness) {
|
||||
float gradate = abs(d - u_rippleRadiuses[i] + thickness) / thickness;
|
||||
strength += (1.0 - u_rippleRadiuses[i]) * gradate;
|
||||
}
|
||||
|
||||
// 内側
|
||||
if (d < u_rippleRadiuses[i] + thickness) {
|
||||
strength += 0.25 * (1.0 - u_rippleRadiuses[i]);
|
||||
}
|
||||
}
|
||||
return strength;
|
||||
}
|
||||
|
||||
void main() {
|
||||
float x_ratio = min(in_resolution.x / in_resolution.y, 1.0);
|
||||
float y_ratio = min(in_resolution.y / in_resolution.x, 1.0);
|
||||
|
||||
float angle = -(u_angle * PI);
|
||||
vec2 centeredUv = (in_uv - vec2(0.5, 0.5)) * vec2(x_ratio, y_ratio);
|
||||
vec2 rotatedUV = vec2(
|
||||
centeredUv.x * cos(angle) - centeredUv.y * sin(angle),
|
||||
centeredUv.x * sin(angle) + centeredUv.y * cos(angle)
|
||||
);
|
||||
vec2 uv = rotatedUV;
|
||||
|
||||
float time = u_time * 0.00025;
|
||||
|
||||
float size = 1.0 / u_scale;
|
||||
float size_half = size / 2.0;
|
||||
float modX = mod(uv.x, size);
|
||||
float modY = mod(uv.y, size);
|
||||
|
||||
vec2 pixelated_uv = vec2(
|
||||
(size * (floor((uv.x - 0.5 - size) / size) + 0.5)),
|
||||
(size * (floor((uv.y - 0.5 - size) / size) + 0.5))
|
||||
) + vec2(0.5 + size, 0.5 + size);
|
||||
|
||||
float strength = getRipple(pixelated_uv);
|
||||
|
||||
float opacity = min(max(strength, 0.0), 1.0);
|
||||
|
||||
float threshold = ((u_radius / 2.0) / u_scale);
|
||||
if (length(vec2(modX - size_half, modY - size_half)) < threshold) {
|
||||
out_color = vec4(u_color.r, u_color.g, u_color.b, opacity);
|
||||
//out_color = vec4(1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
// debug
|
||||
//float a = min(max(getRipple(uv), 0.0), 1.0);
|
||||
//out_color = vec4(u_color.r, u_color.g, u_color.b, (opacity + a) / 2.0);
|
||||
|
||||
out_color = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const canvasEl = useTemplateRef('canvasEl');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
scale?: number;
|
||||
}>(), {
|
||||
scale: 48,
|
||||
});
|
||||
|
||||
let handle: ReturnType<typeof window['requestAnimationFrame']> | null = null;
|
||||
|
||||
onMounted(() => {
|
||||
const canvas = canvasEl.value!;
|
||||
let width = canvas.offsetWidth;
|
||||
let height = canvas.offsetHeight;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
const maybeGl = canvas.getContext('webgl2', { preserveDrawingBuffer: false, alpha: true, premultipliedAlpha: false, antialias: true });
|
||||
if (maybeGl == null) return;
|
||||
|
||||
const gl = maybeGl;
|
||||
|
||||
const VERTICES = new Float32Array([-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1]);
|
||||
const vertexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, VERTICES, gl.STATIC_DRAW);
|
||||
|
||||
//gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
//gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
const shaderProgram = initShaderProgram(gl, VERTEX_SHADER, FRAGMENT_SHADER);
|
||||
|
||||
gl.useProgram(shaderProgram);
|
||||
|
||||
const positionLocation = gl.getAttribLocation(shaderProgram, 'position');
|
||||
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(positionLocation);
|
||||
|
||||
const in_resolution = gl.getUniformLocation(shaderProgram, 'in_resolution');
|
||||
gl.uniform2fv(in_resolution, [canvas.width, canvas.height]);
|
||||
|
||||
const u_time = gl.getUniformLocation(shaderProgram, 'u_time');
|
||||
const u_seed = gl.getUniformLocation(shaderProgram, 'u_seed');
|
||||
const u_scale = gl.getUniformLocation(shaderProgram, 'u_scale');
|
||||
const u_angle = gl.getUniformLocation(shaderProgram, 'u_angle');
|
||||
const u_radius = gl.getUniformLocation(shaderProgram, 'u_radius');
|
||||
const u_color = gl.getUniformLocation(shaderProgram, 'u_color');
|
||||
gl.uniform1f(u_seed, Math.random() * 1000);
|
||||
gl.uniform1f(u_scale, props.scale);
|
||||
gl.uniform1f(u_angle, 0.0);
|
||||
gl.uniform1f(u_radius, 0.15);
|
||||
gl.uniform3fv(u_color, [0.5, 1.0, 0]);
|
||||
|
||||
if (isChromatic()) {
|
||||
gl.uniform1f(u_time, 0);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
} else {
|
||||
let ripples = [] as { position: [number, number]; startTime: number; }[];
|
||||
const LIFE_TIME = 1000 * 4;
|
||||
|
||||
function render(timeStamp: number) {
|
||||
let sizeChanged = false;
|
||||
if (Math.abs(height - canvas.offsetHeight) > 2) {
|
||||
height = canvas.offsetHeight;
|
||||
canvas.height = height;
|
||||
sizeChanged = true;
|
||||
}
|
||||
if (Math.abs(width - canvas.offsetWidth) > 2) {
|
||||
width = canvas.offsetWidth;
|
||||
canvas.width = width;
|
||||
sizeChanged = true;
|
||||
}
|
||||
if (sizeChanged && gl) {
|
||||
gl.uniform2fv(in_resolution, [width, height]);
|
||||
gl.viewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
gl.uniform1f(u_time, timeStamp);
|
||||
|
||||
if (Math.random() < 0.01 && ripples.length < 16) {
|
||||
ripples.push({ position: [(Math.random() * 2) - 1, (Math.random() * 2) - 1], startTime: timeStamp });
|
||||
}
|
||||
|
||||
for (let i = 0; i < 16; i++) {
|
||||
const o = gl.getUniformLocation(shaderProgram, `u_ripplePositions[${i.toString()}]`);
|
||||
const r = gl.getUniformLocation(shaderProgram, `u_rippleRadiuses[${i.toString()}]`);
|
||||
const ripple = ripples[i];
|
||||
if (ripple == null) {
|
||||
gl.uniform2f(o, 0, 0);
|
||||
gl.uniform1f(r, 0.0);
|
||||
continue;
|
||||
}
|
||||
|
||||
const delta = timeStamp - ripple.startTime;
|
||||
|
||||
gl.uniform2f(o, ripple.position[0], ripple.position[1]);
|
||||
gl.uniform1f(r, delta / LIFE_TIME);
|
||||
}
|
||||
|
||||
ripples = ripples.filter(r => (timeStamp - r.startTime) < LIFE_TIME);
|
||||
if (ripples.length === 0) {
|
||||
ripples.push({ position: [(Math.random() * 2) - 1, (Math.random() * 2) - 1], startTime: timeStamp });
|
||||
}
|
||||
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
|
||||
handle = window.requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
handle = window.requestAnimationFrame(render);
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (handle) {
|
||||
window.cancelAnimationFrame(handle);
|
||||
}
|
||||
|
||||
// TODO: WebGLリソースの解放
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
</style>
|
||||
190
idea/MkAnimatedBg.dotted.vue
Normal file
190
idea/MkAnimatedBg.dotted.vue
Normal file
@@ -0,0 +1,190 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<canvas ref="canvasEl" style="display: block; width: 100%; height: 100%; pointer-events: none;"></canvas>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, useTemplateRef } from 'vue';
|
||||
import isChromatic from 'chromatic/isChromatic';
|
||||
import { GLSL_LIB_SNOISE, initShaderProgram } from '@/utility/webgl.js';
|
||||
|
||||
const VERTEX_SHADER = `#version 300 es
|
||||
in vec2 position;
|
||||
out vec2 in_uv;
|
||||
|
||||
void main() {
|
||||
in_uv = (position + 1.0) / 2.0;
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const FRAGMENT_SHADER = `#version 300 es
|
||||
precision mediump float;
|
||||
|
||||
const float PI = 3.141592653589793;
|
||||
const float TWO_PI = 6.283185307179586;
|
||||
const float HALF_PI = 1.5707963267948966;
|
||||
|
||||
${GLSL_LIB_SNOISE}
|
||||
|
||||
in vec2 in_uv;
|
||||
uniform vec2 in_resolution;
|
||||
uniform float u_scale;
|
||||
uniform float u_time;
|
||||
uniform float u_seed;
|
||||
uniform float u_angle;
|
||||
uniform float u_radius;
|
||||
uniform vec3 u_color;
|
||||
out vec4 out_color;
|
||||
|
||||
void main() {
|
||||
float x_ratio = min(in_resolution.x / in_resolution.y, 1.0);
|
||||
float y_ratio = min(in_resolution.y / in_resolution.x, 1.0);
|
||||
|
||||
float size = 1.0 / u_scale;
|
||||
float size_half = size / 2.0;
|
||||
|
||||
float angle = -(u_angle * PI);
|
||||
vec2 centeredUv = (in_uv - vec2(0.5, 0.5)) * vec2(x_ratio, y_ratio);
|
||||
vec2 rotatedUV = vec2(
|
||||
centeredUv.x * cos(angle) - centeredUv.y * sin(angle),
|
||||
centeredUv.x * sin(angle) + centeredUv.y * cos(angle)
|
||||
);
|
||||
vec2 uv = rotatedUV;
|
||||
|
||||
float modX = mod(uv.x, size);
|
||||
float modY = mod(uv.y, size);
|
||||
|
||||
vec2 pixelated_uv = vec2(
|
||||
(size * (floor((uv.x - 0.5 - size) / size) + 0.5)),
|
||||
(size * (floor((uv.y - 0.5 - size) / size) + 0.5))
|
||||
) + vec2(0.5 + size, 0.5 + size);
|
||||
|
||||
float time = u_time * 0.00025;
|
||||
|
||||
float noiseAScale = 1.0;
|
||||
float noiseAX = (pixelated_uv.x + u_seed) * (u_scale / noiseAScale);
|
||||
float noiseAY = (pixelated_uv.y + u_seed) * (u_scale / noiseAScale);
|
||||
float noiseA = snoise(vec3(noiseAX, noiseAY, time * 2.0));
|
||||
|
||||
float noiseBScale = 32.0;
|
||||
float noiseBX = (pixelated_uv.x + u_seed) * (u_scale / noiseBScale);
|
||||
float noiseBY = (pixelated_uv.y + u_seed) * (u_scale / noiseBScale);
|
||||
float noiseB = snoise(vec3(noiseBX, noiseBY, time));
|
||||
|
||||
float strength = 0.0;
|
||||
strength += noiseA * 0.2;
|
||||
strength += noiseB * 0.8;
|
||||
|
||||
float opacity = min(max(strength, 0.0), 1.0);
|
||||
|
||||
float threshold = ((u_radius / 2.0) / u_scale);
|
||||
if (length(vec2(modX - size_half, modY - size_half)) < threshold) {
|
||||
out_color = vec4(u_color.r, u_color.g, u_color.b, opacity);
|
||||
return;
|
||||
}
|
||||
|
||||
out_color = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const canvasEl = useTemplateRef('canvasEl');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
scale?: number;
|
||||
}>(), {
|
||||
scale: 48,
|
||||
});
|
||||
|
||||
let handle: ReturnType<typeof window['requestAnimationFrame']> | null = null;
|
||||
|
||||
onMounted(() => {
|
||||
const canvas = canvasEl.value!;
|
||||
let width = canvas.offsetWidth;
|
||||
let height = canvas.offsetHeight;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
const maybeGl = canvas.getContext('webgl2', { preserveDrawingBuffer: false, alpha: true, premultipliedAlpha: false, antialias: true });
|
||||
if (maybeGl == null) return;
|
||||
|
||||
const gl = maybeGl;
|
||||
|
||||
const VERTICES = new Float32Array([-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1]);
|
||||
const vertexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, VERTICES, gl.STATIC_DRAW);
|
||||
|
||||
//gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
//gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
const shaderProgram = initShaderProgram(gl, VERTEX_SHADER, FRAGMENT_SHADER);
|
||||
|
||||
gl.useProgram(shaderProgram);
|
||||
|
||||
const positionLocation = gl.getAttribLocation(shaderProgram, 'position');
|
||||
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(positionLocation);
|
||||
|
||||
const in_resolution = gl.getUniformLocation(shaderProgram, 'in_resolution');
|
||||
gl.uniform2fv(in_resolution, [canvas.width, canvas.height]);
|
||||
|
||||
const u_time = gl.getUniformLocation(shaderProgram, 'u_time');
|
||||
const u_seed = gl.getUniformLocation(shaderProgram, 'u_seed');
|
||||
const u_scale = gl.getUniformLocation(shaderProgram, 'u_scale');
|
||||
const u_angle = gl.getUniformLocation(shaderProgram, 'u_angle');
|
||||
const u_radius = gl.getUniformLocation(shaderProgram, 'u_radius');
|
||||
const u_color = gl.getUniformLocation(shaderProgram, 'u_color');
|
||||
gl.uniform1f(u_seed, Math.random() * 1000);
|
||||
gl.uniform1f(u_scale, props.scale);
|
||||
gl.uniform1f(u_angle, 0.0);
|
||||
gl.uniform1f(u_radius, 0.15);
|
||||
gl.uniform3fv(u_color, [0.5, 1.0, 0]);
|
||||
|
||||
if (isChromatic()) {
|
||||
gl.uniform1f(u_time, 0);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
} else {
|
||||
function render(timeStamp: number) {
|
||||
let sizeChanged = false;
|
||||
if (Math.abs(height - canvas.offsetHeight) > 2) {
|
||||
height = canvas.offsetHeight;
|
||||
canvas.height = height;
|
||||
sizeChanged = true;
|
||||
}
|
||||
if (Math.abs(width - canvas.offsetWidth) > 2) {
|
||||
width = canvas.offsetWidth;
|
||||
canvas.width = width;
|
||||
sizeChanged = true;
|
||||
}
|
||||
if (sizeChanged && gl) {
|
||||
gl.uniform2fv(in_resolution, [width, height]);
|
||||
gl.viewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
gl.uniform1f(u_time, timeStamp);
|
||||
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
|
||||
handle = window.requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
handle = window.requestAnimationFrame(render);
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (handle) {
|
||||
window.cancelAnimationFrame(handle);
|
||||
}
|
||||
|
||||
// TODO: WebGLリソースの解放
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
</style>
|
||||
@@ -68,7 +68,7 @@ receiveFollowRequest: "تلقيت طلب متابعة"
|
||||
followRequestAccepted: "قُبل طلب المتابعة"
|
||||
mention: "أشر الى"
|
||||
mentions: "الإشارات"
|
||||
directNotes: "الملاحظات المباشرة"
|
||||
directNotes: "رسالة خاصة"
|
||||
importAndExport: "إستورد / صدر"
|
||||
import: "استيراد"
|
||||
export: "تصدير"
|
||||
@@ -1008,6 +1008,17 @@ lastNDays: "آخر {n} أيام"
|
||||
surrender: "ألغِ"
|
||||
postForm: "أنشئ ملاحظة"
|
||||
information: "عن"
|
||||
inMinutes: "د"
|
||||
inDays: "ي"
|
||||
widgets: "التطبيقات المُصغّرة"
|
||||
presets: "إعدادات مسبقة"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
filename: "اسم الملف"
|
||||
_imageFrameEditor:
|
||||
font: "الخط"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
_chat:
|
||||
invitations: "دعوة"
|
||||
noHistory: "السجل فارغ"
|
||||
@@ -1354,6 +1365,14 @@ _widgets:
|
||||
userList: "قائمة المستخدمين"
|
||||
_userList:
|
||||
chooseList: "اختر قائمة"
|
||||
_widgetOptions:
|
||||
height: "الإرتفاع"
|
||||
_button:
|
||||
colored: "ملوّن"
|
||||
_clock:
|
||||
size: "الحجم"
|
||||
_birthdayFollowings:
|
||||
period: "المدة"
|
||||
_cw:
|
||||
hide: "إخفاء"
|
||||
show: "عرض المزيد"
|
||||
@@ -1394,6 +1413,9 @@ _postForm:
|
||||
replyPlaceholder: "رد على هذه الملاحظة…"
|
||||
quotePlaceholder: "اقتبس هذه الملاحظة…"
|
||||
channelPlaceholder: "انشر في قناة..."
|
||||
_howToUse:
|
||||
visibility_title: "الظهور"
|
||||
menu_title: "القائمة"
|
||||
_placeholders:
|
||||
a: "ما الذي تنوي فعله؟"
|
||||
b: "ماذا يحدث حولك ؟"
|
||||
@@ -1597,3 +1619,13 @@ _watermarkEditor:
|
||||
type: "نوع"
|
||||
image: "صور"
|
||||
advanced: "متقدم"
|
||||
_imageEffector:
|
||||
_fxProps:
|
||||
scale: "الحجم"
|
||||
size: "الحجم"
|
||||
offset: "الموضع"
|
||||
color: "اللون"
|
||||
opacity: "الشفافية"
|
||||
_qr:
|
||||
showTabTitle: "المظهر"
|
||||
raw: "نص"
|
||||
|
||||
@@ -848,6 +848,17 @@ sourceCode: "সোর্স কোড"
|
||||
flip: "উল্টান"
|
||||
postForm: "নোট লিখুন"
|
||||
information: "আপনার সম্পর্কে"
|
||||
inMinutes: "মিনিট"
|
||||
inDays: "দিন"
|
||||
widgets: "উইজেটগুলি"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
filename: "ফাইলের নাম"
|
||||
_imageFrameEditor:
|
||||
header: "হেডার"
|
||||
font: "ফন্ট"
|
||||
fontSerif: "সেরিফ"
|
||||
fontSansSerif: "স্যান্স সেরিফ"
|
||||
_chat:
|
||||
invitations: "আমন্ত্রণ"
|
||||
noHistory: "কোনো ইতিহাস নেই"
|
||||
@@ -1126,6 +1137,14 @@ _widgets:
|
||||
aichan: "আই চান"
|
||||
_userList:
|
||||
chooseList: "লিস্ট নির্বাচন করুন"
|
||||
_widgetOptions:
|
||||
height: "উচ্চতা"
|
||||
_button:
|
||||
colored: "রঙ্গিন"
|
||||
_clock:
|
||||
size: "আকার"
|
||||
_birthdayFollowings:
|
||||
period: "ব্যাপ্তিকাল"
|
||||
_cw:
|
||||
hide: "লুকান"
|
||||
show: "আরও দেখুন"
|
||||
@@ -1166,6 +1185,9 @@ _postForm:
|
||||
replyPlaceholder: "নোটটির জবাব দিন..."
|
||||
quotePlaceholder: "নোটটিকে উদ্ধৃত করুন..."
|
||||
channelPlaceholder: "চ্যানেলে পোস্ট করুন..."
|
||||
_howToUse:
|
||||
visibility_title: "দৃশ্যমানতা"
|
||||
menu_title: "মেনু"
|
||||
_placeholders:
|
||||
a: "আপনি এখন কি করছেন?"
|
||||
b: "আপনার আশে পাশে কি হচ্ছে?"
|
||||
@@ -1355,3 +1377,13 @@ _watermarkEditor:
|
||||
text: "লেখা"
|
||||
image: "ছবি"
|
||||
advanced: "উন্নত"
|
||||
_imageEffector:
|
||||
_fxProps:
|
||||
scale: "আকার"
|
||||
size: "আকার"
|
||||
color: "রং"
|
||||
opacity: "অস্বচ্ছতা"
|
||||
lightness: "উজ্জ্বল করুন"
|
||||
_qr:
|
||||
showTabTitle: "প্রদর্শন"
|
||||
raw: "লেখা"
|
||||
|
||||
@@ -83,6 +83,8 @@ files: "Fitxers"
|
||||
download: "Descarregar"
|
||||
driveFileDeleteConfirm: "Estàs segur que vols suprimir el fitxer \"{name}\"? Les notes associades a aquest fitxer també seran esborrades."
|
||||
unfollowConfirm: "Segur que vols deixar de seguir a {name}?"
|
||||
cancelFollowRequestConfirm: "Vols cancel·lar la teva sol·licitud de seguiment a {name}?"
|
||||
rejectFollowRequestConfirm: "Vols rebutjar la sol·licitud de seguiment de {name}?"
|
||||
exportRequested: "Has sol·licitat una exportació de dades. Això pot trigar una estona. S'afegirà a la teva unitat de disc un cop estigui completada."
|
||||
importRequested: "Has sol·licitat una importació de dades. Això pot trigar una estona."
|
||||
lists: "Llistes"
|
||||
@@ -253,6 +255,7 @@ noteDeleteConfirm: "Segur que voleu eliminar aquesta publicació?"
|
||||
pinLimitExceeded: "No podeu fixar més publicacions"
|
||||
done: "Fet"
|
||||
processing: "S'està processant..."
|
||||
preprocessing: "Preparant"
|
||||
preview: "Vista prèvia"
|
||||
default: "Per defecte"
|
||||
defaultValueIs: "Per defecte: {value}"
|
||||
@@ -261,7 +264,7 @@ noJobs: "No hi ha feines"
|
||||
federating: "Federant"
|
||||
blocked: "Bloquejat"
|
||||
suspended: "Anul·lar subscripció "
|
||||
all: "tot"
|
||||
all: "Tot"
|
||||
subscribing: "Subscrit a"
|
||||
publishing: "S'està publicant"
|
||||
notResponding: "Sense resposta"
|
||||
@@ -301,6 +304,7 @@ uploadFromUrlMayTakeTime: "La càrrega des de l'enllaç pot trigar un temps"
|
||||
uploadNFiles: "Pujar {n} arxius"
|
||||
explore: "Explora"
|
||||
messageRead: "Vist"
|
||||
readAllChatMessages: "Marcar tots els missatges com a llegits"
|
||||
noMoreHistory: "No hi ha res més per veure"
|
||||
startChat: "Comença a xatejar "
|
||||
nUsersRead: "Vist per {n}"
|
||||
@@ -333,6 +337,7 @@ fileName: "Nom del Fitxer"
|
||||
selectFile: "Selecciona un fitxer"
|
||||
selectFiles: "Selecciona fitxers"
|
||||
selectFolder: "Selecció de carpeta"
|
||||
unselectFolder: "Deixa de seleccionar la carpeta"
|
||||
selectFolders: "Selecció de carpetes"
|
||||
fileNotSelected: "Cap fitxer seleccionat"
|
||||
renameFile: "Canvia el nom del fitxer"
|
||||
@@ -345,6 +350,7 @@ addFile: "Afegeix un fitxer"
|
||||
showFile: "Mostrar fitxer"
|
||||
emptyDrive: "El teu Disc és buit"
|
||||
emptyFolder: "La carpeta està buida"
|
||||
dropHereToUpload: "Arrossega els arxius fins aquí per pujar-los al servidor"
|
||||
unableToDelete: "No es pot eliminar"
|
||||
inputNewFileName: "Introduïu el nom de fitxer nou"
|
||||
inputNewDescription: "Escriu el peu de foto."
|
||||
@@ -537,6 +543,7 @@ regenerate: "Regenera"
|
||||
fontSize: "Mida del text"
|
||||
mediaListWithOneImageAppearance: "Altura de la llista de fitxers amb una única imatge"
|
||||
limitTo: "Limita a {x}"
|
||||
showMediaListByGridInWideArea: "Mostra la llista de medis en vista quadrícula quan l'amplada de la pantalla ho permeti"
|
||||
noFollowRequests: "No tens sol·licituds de seguiment"
|
||||
openImageInNewTab: "Obre imatges a una nova pestanya"
|
||||
dashboard: "Tauler de control"
|
||||
@@ -648,7 +655,7 @@ disablePlayer: "Tanca el reproductor de vídeo"
|
||||
expandTweet: "Expandir post"
|
||||
themeEditor: "Editor de temes"
|
||||
description: "Descripció"
|
||||
describeFile: "Afegeix una descripció "
|
||||
describeFile: "Afegir text alternatiu"
|
||||
enterFileDescription: "Escriu un peu de foto"
|
||||
author: "Autor"
|
||||
leaveConfirm: "Hi ha canvis sense guardar. Els vols descartar?"
|
||||
@@ -772,6 +779,7 @@ lockedAccountInfo: "Tret que establiu la visibilitat de la nota a \"Només segui
|
||||
alwaysMarkSensitive: "Marcar com a sensible per defecte"
|
||||
loadRawImages: "Carregar les imatges originals en comptes de miniatures "
|
||||
disableShowingAnimatedImages: "No reproduir imatges animades"
|
||||
disableShowingAnimatedImages_caption: "Si les imatges animades no es reprodueixen, independentment d'aquesta configuració, és possible que la configuració d'accessibilitat del navegador i el sistema operatiu, els modes d'estalvi d'energia i similars estiguin interferint."
|
||||
highlightSensitiveMedia: "Ressalta els medis marcats com a sensibles"
|
||||
verificationEmailSent: "S'ha enviat un correu electrònic de verificació. Fes clic a l'enllaç per completar la verificació."
|
||||
notSet: "Sense definir"
|
||||
@@ -896,7 +904,7 @@ searchResult: "Resultats de la cerca"
|
||||
hashtags: "Etiquetes"
|
||||
troubleshooting: "Solucionar problemes"
|
||||
useBlurEffect: "Fes servir efectes de desenfocament a la interfície"
|
||||
learnMore: "Saber més "
|
||||
learnMore: "Saber-ne més "
|
||||
misskeyUpdated: "Misskey s'ha actualitzat "
|
||||
whatIsNew: "Mostra canvis"
|
||||
translate: "Traduir "
|
||||
@@ -1018,6 +1026,9 @@ pushNotificationAlreadySubscribed: "L'enviament de notificacions ja és activat"
|
||||
pushNotificationNotSupported: "El teu navegador o la teva instància no suporta l'enviament de notificacions "
|
||||
sendPushNotificationReadMessage: "Esborrar les notificacions enviades quan s'hagin llegit"
|
||||
sendPushNotificationReadMessageCaption: "Això pot fer que el teu dispositiu consumeixi més bateria"
|
||||
pleaseAllowPushNotification: "Si us plau, permet les notificacions del navegador"
|
||||
browserPushNotificationDisabled: "No s'ha pogut obtenir permisos per les notificacions"
|
||||
browserPushNotificationDisabledDescription: "No tens permisos per enviar notificacions des de {serverName}. Activa les notificacions a la configuració del teu navegador i tornar-ho a intentar."
|
||||
windowMaximize: "Maximitzar "
|
||||
windowMinimize: "Minimitzar"
|
||||
windowRestore: "Restaurar"
|
||||
@@ -1054,6 +1065,7 @@ permissionDeniedError: "Operació no permesa "
|
||||
permissionDeniedErrorDescription: "Aquest compte no té suficients permisos per dur a terme aquesta acció "
|
||||
preset: "Predefinit"
|
||||
selectFromPresets: "Escull des dels predefinits"
|
||||
custom: "Personalitzat"
|
||||
achievements: "Assoliments"
|
||||
gotInvalidResponseError: "Resposta del servidor invàlida "
|
||||
gotInvalidResponseErrorDescription: "No es pot contactar amb el servidor o potser es troba fora de línia per manteniment. Provar-ho de nou més tard."
|
||||
@@ -1061,8 +1073,8 @@ thisPostMayBeAnnoying: "Aquesta nota pot ser molesta per algú."
|
||||
thisPostMayBeAnnoyingHome: "Publicar a la línia de temps d'Inici"
|
||||
thisPostMayBeAnnoyingCancel: "Cancel·lar "
|
||||
thisPostMayBeAnnoyingIgnore: "Publicar de totes maneres"
|
||||
collapseRenotes: "Col·lapsar les renotes que ja has vist"
|
||||
collapseRenotesDescription: "Col·lapse les notes a les quals ja has reaccionat o que ja has renotat"
|
||||
collapseRenotes: "Col·lapsar els impulsos que ja has vist"
|
||||
collapseRenotesDescription: "Col·lapse les notes a les quals ja has reaccionat o que ja has impulsat."
|
||||
internalServerError: "Error intern del servidor"
|
||||
internalServerErrorDescription: "El servidor ha fallat de manera inexplicable."
|
||||
copyErrorInfo: "Copiar la informació de l'error "
|
||||
@@ -1092,6 +1104,7 @@ prohibitedWordsDescription2: "Fent servir espais crearà expressions AND si l'ex
|
||||
hiddenTags: "Etiquetes ocultes"
|
||||
hiddenTagsDescription: "La visibilitat de totes les notes que continguin qualsevol de les paraules configurades seran, automàticament, afegides a \"Inici\". Pots llistar diferents paraules separant les per línies noves."
|
||||
notesSearchNotAvailable: "La cerca de notes no es troba disponible."
|
||||
usersSearchNotAvailable: "La cerca d'usuaris no està disponible."
|
||||
license: "Llicència"
|
||||
unfavoriteConfirm: "Esborrar dels favorits?"
|
||||
myClips: "Els meus retalls"
|
||||
@@ -1166,6 +1179,7 @@ installed: "Instal·lats "
|
||||
branding: "Marca"
|
||||
enableServerMachineStats: "Publicar estadístiques del maquinari del servidor"
|
||||
enableIdenticonGeneration: "Activar la generació d'icones d'identificació "
|
||||
showRoleBadgesOfRemoteUsers: "Mostrar insígnies de rols d'instàncies remotes "
|
||||
turnOffToImprovePerformance: "Desactivant aquesta opció es pot millorar el rendiment."
|
||||
createInviteCode: "Crear codi d'invitació "
|
||||
createWithOptions: "Crear invitació amb opcions"
|
||||
@@ -1243,7 +1257,7 @@ releaseToRefresh: "Deixar anar per actualitzar"
|
||||
refreshing: "Recarregant..."
|
||||
pullDownToRefresh: "Llisca cap a baix per recarregar"
|
||||
useGroupedNotifications: "Mostrar les notificacions agrupades "
|
||||
signupPendingError: "Hi ha hagut un problema verificant l'adreça de correu electrònic. L'enllaç pot haver caducat."
|
||||
emailVerificationFailedError: "Hem tingut un problema en verificar la teva adreça de correu electrònic. És probable que l'enllaç estigui caducat."
|
||||
cwNotationRequired: "Si està activat \"Amagar contingut\" s'ha d'escriure una descripció "
|
||||
doReaction: "Afegeix una reacció "
|
||||
code: "Codi"
|
||||
@@ -1313,6 +1327,8 @@ availableRoles: "Roles disponibles "
|
||||
acknowledgeNotesAndEnable: "Activa'l després de comprendre els possibles perills."
|
||||
federationSpecified: "Aquest servidor treballa amb una federació de llistes blanques. No pot interactuar amb altres servidors que no siguin els especificats per l'administrador."
|
||||
federationDisabled: "La unió es troba deshabilitada en aquest servidor. No es pot interactuar amb usuaris d'altres servidors."
|
||||
draft: "Esborrany "
|
||||
draftsAndScheduledNotes: "Esborranys i publicacions programades"
|
||||
confirmOnReact: "Confirmar en reaccionar"
|
||||
reactAreYouSure: "Vols reaccionar amb \"{emoji}\"?"
|
||||
markAsSensitiveConfirm: "Vols marcar aquest contingut com a sensible?"
|
||||
@@ -1340,6 +1356,8 @@ postForm: "Formulari de publicació"
|
||||
textCount: "Nombre de caràcters "
|
||||
information: "Informació"
|
||||
chat: "Xat"
|
||||
directMessage: "Xateja amb aquest usuari"
|
||||
directMessage_short: "Missatge"
|
||||
migrateOldSettings: "Migrar la configuració anterior"
|
||||
migrateOldSettings_description: "Normalment això es fa automàticament, però si la transició no es fa, el procés es pot iniciar manualment. S'esborrarà la configuració actual."
|
||||
compress: "Comprimir "
|
||||
@@ -1350,7 +1368,7 @@ embed: "Incrustar"
|
||||
settingsMigrating: "Estem migrant la teva configuració. Si us plau espera un moment... (També pots fer la migració més tard, manualment, anant a Preferències → Altres → Migrar configuració antiga)"
|
||||
readonly: "Només lectura"
|
||||
goToDeck: "Tornar al tauler"
|
||||
federationJobs: "Treballs sindicats "
|
||||
federationJobs: "Treballs de federació"
|
||||
driveAboutTip: "Al Disc veure's una llista de tots els arxius que has anat pujant.<br>\nPots tornar-los a fer servir adjuntant-los a notes noves o pots adelantar-te i pujar arxius per publicar-los més tard!<br>\n<b>Tingués en compte que si esborres un arxiu també desapareixerà de tots els llocs on l'has fet servir (notes, pàgines, avatars, imatges de capçalera, etc.)</b><br>\nTambé pots crear carpetes per organitzar les."
|
||||
scrollToClose: "Desplaçar per tancar"
|
||||
advice: "Consell"
|
||||
@@ -1367,7 +1385,84 @@ redisplayAllTips: "Torna ha mostrat tots els trucs i consells"
|
||||
hideAllTips: "Amagar tots els trucs i consells"
|
||||
defaultImageCompressionLevel: "Nivell de comprensió de la imatge per defecte"
|
||||
defaultImageCompressionLevel_description: "Baixa, conserva la qualitat de la imatge però la mida de l'arxiu és més gran. <br>Alta, redueix la mida de l'arxiu però també la qualitat de la imatge."
|
||||
defaultCompressionLevel: "Nivell de compressió predeterminat"
|
||||
defaultCompressionLevel_description: "Si el redueixes augmentaràs la qualitat de la imatge, però la mida de l'arxiu serà més gran. <br>Si augmentes l'opció redueixes la mida de l'arxiu i la qualitat de la imatge és pitjor."
|
||||
inMinutes: "Minut(s)"
|
||||
inDays: "Di(a)(es)"
|
||||
safeModeEnabled: "Mode segur activat"
|
||||
pluginsAreDisabledBecauseSafeMode: "Les extensions no estan activades perquè el mode segur està activat."
|
||||
customCssIsDisabledBecauseSafeMode: "El CSS personalitzat no s'aplica perquè el mode segur es troba activat."
|
||||
themeIsDefaultBecauseSafeMode: "El tema predeterminat es farà servir mentre el mode segur estigui activat. Una vegada es desactivi el mode segur es restablirà el tema escollit."
|
||||
thankYouForTestingBeta: "Gràcies per ajudar-nos a provar la versió beta!"
|
||||
createUserSpecifiedNote: "Crear notes especificades per l'usuari "
|
||||
schedulePost: "Programar una nota"
|
||||
scheduleToPostOnX: "Programar una nota per {x}"
|
||||
scheduledToPostOnX: "S'ha programat la nota per {x}"
|
||||
schedule: "Programa"
|
||||
scheduled: "Programat"
|
||||
widgets: "Ginys"
|
||||
deviceInfo: "Informació del dispositiu"
|
||||
deviceInfoDescription: "En fer consultes tècniques influir la següent informació pot ajudar a resoldre'l més ràpidament."
|
||||
youAreAdmin: "Ets l'administrador "
|
||||
frame: "Marc"
|
||||
presets: "Predefinit"
|
||||
zeroPadding: "Sense omplir"
|
||||
nothingToConfigure: "No hi ha res a configurar"
|
||||
viewRenotedChannel: "Mirar el canal d'impulsos "
|
||||
_imageEditing:
|
||||
_vars:
|
||||
caption: "Títol de l'arxiu"
|
||||
filename: "Nom del Fitxer"
|
||||
filename_without_ext: "Nom de l'arxiu sense extensió "
|
||||
year: "Any"
|
||||
month: "Mes"
|
||||
day: "Dia"
|
||||
hour: "Hora"
|
||||
minute: "Minut"
|
||||
second: "Segon"
|
||||
camera_model: "Nom de la càmera "
|
||||
camera_lens_model: "Nom de la lent"
|
||||
camera_mm: "Distància focal"
|
||||
camera_mm_35: "Distància focal (equivalent a 35 mm)"
|
||||
camera_f: "Obertura"
|
||||
camera_s: "Velocitat d'obturació"
|
||||
camera_iso: "Sensibilitat ISO"
|
||||
gps_lat: "Latitud "
|
||||
gps_long: "Longitud "
|
||||
_imageFrameEditor:
|
||||
title: "Edició de fotogrames "
|
||||
tip: "Pots decorar les imatges afegint etiquetes que continguin marcs i metadades."
|
||||
header: "Capçalera"
|
||||
footer: "Peu de pàgina "
|
||||
borderThickness: "Amplada de la vora"
|
||||
labelThickness: "Amplada de l'etiqueta "
|
||||
labelScale: "Mida de l'etiqueta "
|
||||
centered: "Alinea al centre"
|
||||
captionMain: "Peu de foto (gran)"
|
||||
captionSub: "Peu de foto (petit)"
|
||||
availableVariables: "Variables disponibles"
|
||||
withQrCode: "Codi QR"
|
||||
backgroundColor: "Color del fons"
|
||||
textColor: "Color del text"
|
||||
font: "Lletra tipogràfica"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
quitWithoutSaveConfirm: "Sortir sense desar?"
|
||||
failedToLoadImage: "Error en carregar la imatge"
|
||||
_compression:
|
||||
_quality:
|
||||
high: "Qualitat alta"
|
||||
medium: "Qualitat mitjana"
|
||||
low: "Qualitat baixa"
|
||||
_size:
|
||||
large: "Mida gran"
|
||||
medium: "Mida mitjana"
|
||||
small: "Mida petita"
|
||||
_order:
|
||||
newest: "Més recent"
|
||||
oldest: "Antigues primer"
|
||||
_chat:
|
||||
messages: "Missatge"
|
||||
noMessagesYet: "Encara no tens missatges "
|
||||
newMessage: "Missatge nou"
|
||||
individualChat: "Xat individual "
|
||||
@@ -1455,6 +1550,12 @@ _settings:
|
||||
contentsUpdateFrequency_description2: "Quan s'activa el mode en temps real, el contingut s'actualitza en temps real, independentment d'aquesta configuració."
|
||||
showUrlPreview: "Mostrar vista prèvia d'URL"
|
||||
showAvailableReactionsFirstInNote: "Mostra les reacciones que pots fer servir al damunt"
|
||||
showPageTabBarBottom: "Mostrar les pestanyes de les línies de temps a la part inferior"
|
||||
emojiPaletteBanner: "Pots registrar ajustos preestablerts com paletes perquè es mostrin permanentment al selector d'emojis, o personalitzar la configuració de visió del selector."
|
||||
enableAnimatedImages: "Activar imatges animades"
|
||||
settingsPersistence_title: "Persistència de la configuració "
|
||||
settingsPersistence_description1: "Habilitar la persistència de la configuració permet que no es perdi la informació de la configuració "
|
||||
settingsPersistence_description2: "Depenent de l'entorn pot ser que no puguis habilitar aquesta opció."
|
||||
_chat:
|
||||
showSenderName: "Mostrar el nom del remitent"
|
||||
sendOnEnter: "Introdueix per enviar"
|
||||
@@ -1463,6 +1564,8 @@ _preferencesProfile:
|
||||
profileNameDescription: "Estableix un nom que identifiqui aquest dispositiu."
|
||||
profileNameDescription2: "Per exemple: \"PC Principal\", \"Smartphone\", etc"
|
||||
manageProfiles: "Gestionar perfils"
|
||||
shareSameProfileBetweenDevicesIsNotRecommended: "No recomanem compartir el mateix perfil en diferents dispositius."
|
||||
useSyncBetweenDevicesOptionIfYouWantToSyncSetting: "Si hi ha ajustos que vols sincronitzar entre diferents dispositius activa l'opció \"Sincronitza entre diferents dispositius\" individualment per cada una de les diferents opcions."
|
||||
_preferencesBackup:
|
||||
autoBackup: "Còpia de seguretat automàtica "
|
||||
restoreFromBackup: "Restaurar des d'una còpia de seguretat"
|
||||
@@ -1472,6 +1575,7 @@ _preferencesBackup:
|
||||
youNeedToNameYourProfileToEnableAutoBackup: "Has de posar-li un nom al teu perfil per poder activar les còpies de seguretat automàtiques."
|
||||
autoPreferencesBackupIsNotEnabledForThisDevice: "La còpia de seguretat automàtica no es troba activada en aquest dispositiu."
|
||||
backupFound: "Còpia de seguretat de la configuració trobada"
|
||||
forceBackup: "Còpia de seguretat forçada de la configuració "
|
||||
_accountSettings:
|
||||
requireSigninToViewContents: "És obligatori l'inici de sessió per poder veure el contingut"
|
||||
requireSigninToViewContentsDescription1: "Es requereix l'inici de sessió per poder veure totes les notes i el contingut que has creat. Amb això esperem evitar que els rastrejadors recopilin informació."
|
||||
@@ -1511,8 +1615,8 @@ _bubbleGame:
|
||||
highScore: "Millor puntuació "
|
||||
maxChain: "Nombre màxim de combos"
|
||||
yen: "{yen}Ien"
|
||||
estimatedQty: "{qty}peces"
|
||||
scoreSweets: "{onigiriQtyWithUnit}ongiris"
|
||||
estimatedQty: "{qty} Peces"
|
||||
scoreSweets: "{onigiriQtyWithUnit} Boles d'arròs "
|
||||
_howToPlay:
|
||||
section1: "Ajusta la posició i deixa caure l'objecte dintre la caixa."
|
||||
section2: "Quan dos objectes del mateix tipus es toquen, canviaran en un objecte diferent i guanyares punts."
|
||||
@@ -1523,7 +1627,7 @@ _announcement:
|
||||
needConfirmationToRead: "Es necessita confirmació de lectura de la notificació "
|
||||
needConfirmationToReadDescription: "Si s'activa es mostrarà un diàleg per confirmar la lectura d'aquesta notificació. A més aquesta notificació serà exclosa de qualsevol funcionalitat com \"Marcar tot com a llegit\"."
|
||||
end: "Final de la notificació "
|
||||
tooManyActiveAnnouncementDescription: "Tenir massa notificacions actives pot empitjorar l'experiència de l'usuari. Considera finalitzar els avisos que siguin antics."
|
||||
tooManyActiveAnnouncementDescription: "Tenir masses notificacions actives pot empitjorar l'experiència de l'usuari. Considera finalitzar els avisos que siguin antics."
|
||||
readConfirmTitle: "Marcar com llegida?"
|
||||
readConfirmText: "Això marcarà el contingut de \"{title}\" com llegit."
|
||||
shouldNotBeUsedToPresentPermanentInfo: "Ja que l'ús de notificacions pot impactar l'experiència dels nous usuaris, és recomanable fer servir les notificacions amb el flux d'informació en comptes de fer-les servir en un únic bloc."
|
||||
@@ -1584,7 +1688,7 @@ _initialTutorial:
|
||||
description: "Pots limitar qui pot veure les teves notes."
|
||||
public: "La teva nota serà visible per a tots els usuaris."
|
||||
home: "Publicar només a línia de temps d'Inici. La gent que visiti el teu perfil o mitjançant les remotes també la podran veure."
|
||||
followers: "Només visible per a seguidors. Només els teus seguidors la podran veure i ningú més. Ningú més podrà fer renotes."
|
||||
followers: "Només visible per a seguidors. Només els teus seguidors la podran veure i ningú més. Ningú més podrà fer impulsos."
|
||||
direct: "Només visible per a alguns seguidors, el destinatari rebre una notificació. Es pot fer servir com una alternativa als missatges directes."
|
||||
doNotSendConfidencialOnDirect1: "Tingues cura quan enviïs informació sensible."
|
||||
doNotSendConfidencialOnDirect2: "Els administradors del servidor poden veure tot el que escrius. Ves compte quan enviïs informació sensible en enviar notes directes a altres usuaris en servidors de poca confiança."
|
||||
@@ -1628,6 +1732,10 @@ _serverSettings:
|
||||
fanoutTimelineDbFallback: "Carregar de la base de dades"
|
||||
fanoutTimelineDbFallbackDescription: "Quan s'activa, la línia de temps fa servir la base de dades per consultes adicionals si la línia de temps no es troba a la memòria cau. Si és desactiva la càrrega del servidor és veure reduïda, però també és reduirà el nombre de línies de temps que és poden obtenir."
|
||||
reactionsBufferingDescription: "Quan s'activa aquesta opció millora bastant el rendiment en recuperar les línies de temps reduint la càrrega de la base. Com a contrapunt, augmentarà l'ús de memòria de Redís. Desactiva aquesta opció en cas de tenir un servidor amb poca memòria o si tens problemes d'inestabilitat."
|
||||
remoteNotesCleaning: "Neteja automàtica de notes remotes"
|
||||
remoteNotesCleaning_description: "Quan activis aquesta opció, periòdicament es netejaran les notes remotes que no es consultin, això evitarà que la base de dades se"
|
||||
remoteNotesCleaningMaxProcessingDuration: "Duració màxima del temps de funcionament del procés de neteja"
|
||||
remoteNotesCleaningExpiryDaysForEachNotes: "Duració mínima de conservació de les notes"
|
||||
inquiryUrl: "URL de consulta "
|
||||
inquiryUrlDescription: "Escriu adreça URL per al formulari de consulta per al mantenidor del servidor o una pàgina web amb el contacte d'informació."
|
||||
openRegistration: "Registres oberts"
|
||||
@@ -1646,6 +1754,11 @@ _serverSettings:
|
||||
userGeneratedContentsVisibilityForVisitor: "L'abast de la publicació del contingut generat per l'usuari"
|
||||
userGeneratedContentsVisibilityForVisitor_description: "Això ajuda a evitar problemes com que continguts remots inadequats que no hagin estat moderats correctament es publiquin a internet mitjançant el teu servidor."
|
||||
userGeneratedContentsVisibilityForVisitor_description2: "La publicació incondicional de tots els continguts del servidor a internet, incloent-hi els continguts remots rebuts pel servidor, comporta riscos. Això és extremadament important per els espectadors que desconeixen el caràcter descentralitzat dels continguts, ja que poden percebre erroneament els continguts remots com contingut generat per el propi servidor."
|
||||
restartServerSetupWizardConfirm_title: "Vols tornar a executar l'assistent de configuració inicial del servidor?"
|
||||
restartServerSetupWizardConfirm_text: "Algunes configuracions actuals seran restablertes."
|
||||
entrancePageStyle: "Estil de la pàgina d'inici"
|
||||
showTimelineForVisitor: "Mostrar la línia de temps"
|
||||
showActivitiesForVisitor: "Mostrar activitat"
|
||||
_userGeneratedContentsVisibilityForVisitor:
|
||||
all: "Tot obert al públic "
|
||||
localOnly: "Només es publiquen els continguts locals, el contingut remot es manté privat"
|
||||
@@ -1968,6 +2081,7 @@ _role:
|
||||
canManageAvatarDecorations: "Gestiona les decoracions dels avatars "
|
||||
driveCapacity: "Capacitat del disc"
|
||||
maxFileSize: "Mida màxima de l'arxiu que es pot carregar"
|
||||
maxFileSize_caption: "Pot haver-hi la possibilitat que existeixin altres opcions de configuració de l'etapa anterior, com podria ser el proxy invers i la CDN."
|
||||
alwaysMarkNsfw: "Marca sempre els fitxers com a sensibles"
|
||||
canUpdateBioMedia: "Permet l'edició d'una icona o un bàner"
|
||||
pinMax: "Nombre màxim de notes fixades"
|
||||
@@ -1982,6 +2096,7 @@ _role:
|
||||
descriptionOfRateLimitFactor: "Límits baixos són menys restrictius, límits alts són més restrictius."
|
||||
canHideAds: "Pot amagar la publicitat"
|
||||
canSearchNotes: "Pot cercar notes"
|
||||
canSearchUsers: "Pot cercar usuaris"
|
||||
canUseTranslator: "Pot fer servir el traductor"
|
||||
avatarDecorationLimit: "Nombre màxim de decoracions que es poden aplicar els avatars"
|
||||
canImportAntennas: "Autoritza la importació d'antenes "
|
||||
@@ -1993,6 +2108,9 @@ _role:
|
||||
uploadableFileTypes: "Tipus de fitxers que en podeu pujar"
|
||||
uploadableFileTypes_caption: "Especifica el tipus MIME. Es poden especificar diferents tipus MIME separats amb una nova línia, i es poden especificar comodins amb asteriscs (*). (Per exemple: image/*)"
|
||||
uploadableFileTypes_caption2: "Pot que no sigui possible determinar el tipus MIME d'alguns arxius. Per permetre aquests tipus d'arxius afegeix {x} a les especificacions."
|
||||
noteDraftLimit: "Nombre possible d'esborranys de notes al servidor"
|
||||
scheduledNoteLimit: "Màxim nombre de notes programades que es poden crear simultàniament"
|
||||
watermarkAvailable: "Pots fer servir la marca d'aigua"
|
||||
_condition:
|
||||
roleAssignedTo: "Assignat a rols manuals"
|
||||
isLocal: "Usuari local"
|
||||
@@ -2050,7 +2168,7 @@ _ad:
|
||||
timezoneinfo: "El dia de la setmana ve determinat del fus horari del servidor."
|
||||
adsSettings: "Configurar la publicitat"
|
||||
notesPerOneAd: "Interval d'emplaçament publicitari en temps real (Notes per anuncis)"
|
||||
setZeroToDisable: "Ajusta aquest valor a 0 per deshabilitar l'actualització d'anuncis en temps real"
|
||||
setZeroToDisable: "Ajusta aquest valor a 0 per deshabilitar l'actualització de publicitat en temps real"
|
||||
adsTooClose: "L'interval actual pot fer que l'experiència de l'usuari sigui dolenta perquè l'interval és molt baix."
|
||||
_forgotPassword:
|
||||
enterEmail: "Escriu l'adreça de correu electrònic amb la que et vas registrar. S'enviarà un correu electrònic amb un enllaç perquè puguis canviar-la."
|
||||
@@ -2068,8 +2186,8 @@ _email:
|
||||
title: "Has rebut una sol·licitud de seguiment"
|
||||
_plugin:
|
||||
install: "Instal·lar un afegit "
|
||||
installWarn: "Si us plau, no instal·lis afegits que no siguin de confiança."
|
||||
manage: "Gestionar els afegits"
|
||||
installWarn: "Si us plau, no instal·lis extensions que no siguin de confiança."
|
||||
manage: "Gestiona les extensions"
|
||||
viewSource: "Veure l'origen "
|
||||
viewLog: "Mostra el registre"
|
||||
_preferencesBackups:
|
||||
@@ -2152,6 +2270,7 @@ _theme:
|
||||
install: "Instal·lar un tema"
|
||||
manage: "Gestionar els temes "
|
||||
code: "Codi del tema"
|
||||
copyThemeCode: "Copiar el codi del tema"
|
||||
description: "Descripció"
|
||||
installed: "{name} Instal·lat "
|
||||
installedThemes: "Temes instal·lats "
|
||||
@@ -2251,6 +2370,7 @@ _time:
|
||||
minute: "Minut(s)"
|
||||
hour: "Hor(a)(es)"
|
||||
day: "Di(a)(es)"
|
||||
month: "Mes(os)"
|
||||
_2fa:
|
||||
alreadyRegistered: "J has registrat un dispositiu d'autenticació de doble factor."
|
||||
registerTOTP: "Registrar una aplicació autenticadora"
|
||||
@@ -2380,6 +2500,7 @@ _auth:
|
||||
scopeUser: "Opera com si fossis aquest usuari"
|
||||
pleaseLogin: "Si us plau, identificat per autoritzar l'aplicació."
|
||||
byClickingYouWillBeRedirectedToThisUrl: "Si es garanteix l'accés, seràs redirigit automàticament a la següent adreça URL"
|
||||
alreadyAuthorized: "Aquesta aplicació ja té accés."
|
||||
_antennaSources:
|
||||
all: "Totes les publicacions"
|
||||
homeTimeline: "Publicacions dels usuaris seguits"
|
||||
@@ -2425,7 +2546,45 @@ _widgets:
|
||||
chooseList: "Tria una llista"
|
||||
clicker: "Clicker"
|
||||
birthdayFollowings: "Usuaris que fan l'aniversari avui"
|
||||
chat: "Xat"
|
||||
chat: "Xateja amb aquest usuari"
|
||||
_widgetOptions:
|
||||
showHeader: "Mostrar la capçalera"
|
||||
transparent: "Fons transparent"
|
||||
height: "Alçada "
|
||||
_button:
|
||||
colored: "Colorit"
|
||||
_clock:
|
||||
size: "Mida"
|
||||
thickness: "Amplada de l'agulla "
|
||||
thicknessThin: "Esvelt "
|
||||
thicknessMedium: "Normal"
|
||||
thicknessThick: "Gruixut "
|
||||
graduations: "Marques de l'esfera "
|
||||
graduationDots: "Punt"
|
||||
graduationArabic: "Nombres àrabs "
|
||||
fadeGraduations: "Efecte gradient "
|
||||
sAnimation: "Animació de la maneta dels segons"
|
||||
sAnimationElastic: "Real"
|
||||
sAnimationEaseOut: "Suau"
|
||||
twentyFour: "Format 24 hores"
|
||||
labelTime: "Temps"
|
||||
labelTz: "Fus horari"
|
||||
labelTimeAndTz: "Hora i fus horari"
|
||||
timezone: "Fus horari"
|
||||
showMs: "Mostrar mil·lisegons"
|
||||
showLabel: "Mostrar etiqueta"
|
||||
_jobQueue:
|
||||
sound: "Reprodueix so"
|
||||
_rss:
|
||||
url: "URL del canal RSS"
|
||||
refreshIntervalSec: "Interval d'actualitzacions (segons)"
|
||||
maxEntries: "Nombre màxim d'entrades a mostrar"
|
||||
_rssTicker:
|
||||
shuffle: "Visualització aleatòria "
|
||||
duration: "Velocitat desplaçament bàner informatiu "
|
||||
reverse: "Desplaçament contrari"
|
||||
_birthdayFollowings:
|
||||
period: "Període"
|
||||
_cw:
|
||||
hide: "Amagar"
|
||||
show: "Carregar més"
|
||||
@@ -2470,6 +2629,20 @@ _postForm:
|
||||
replyPlaceholder: "Contestar..."
|
||||
quotePlaceholder: "Citar..."
|
||||
channelPlaceholder: "Publicar a un canal..."
|
||||
showHowToUse: "Mostrar les instruccions"
|
||||
_howToUse:
|
||||
content_title: "Cos principal"
|
||||
content_description: "Introdueix el contingut que vols publicar."
|
||||
toolbar_title: "Barra d'eines "
|
||||
toolbar_description: "Pots adjuntar arxius o enquestes, afegir anotacions o etiquetes i inserir emojis o mencions."
|
||||
account_title: "Menú del compte"
|
||||
account_description: "Pots anar canviant de comptes per publicar o veure una llista d'esborranys i les publicacions programades del teu compte."
|
||||
visibility_title: "Visibilitat"
|
||||
visibility_description: "Pots configurar la visibilitat de les teves notes."
|
||||
menu_title: "Menú"
|
||||
menu_description: "Pots fer altres accions com desar esborranys, programar publicacions i configurar reaccions."
|
||||
submit_title: "Botó per publicar"
|
||||
submit_description: "Publica les teves notes. També pots fer servir Ctrl + Enter / Cmd + Enter"
|
||||
_placeholders:
|
||||
a: "Que vols dir?..."
|
||||
b: "Alguna cosa interessant al teu voltant?..."
|
||||
@@ -2615,6 +2788,8 @@ _notification:
|
||||
youReceivedFollowRequest: "Has rebut una petició de seguiment"
|
||||
yourFollowRequestAccepted: "La teva petició de seguiment ha sigut acceptada"
|
||||
pollEnded: "Ja pots veure els resultats de l'enquesta "
|
||||
scheduledNotePosted: "Una nota programada ha sigut publicada"
|
||||
scheduledNotePostFailed: "Ha fallat la publicació d'una nota programada"
|
||||
newNote: "Nota nova"
|
||||
unreadAntennaNote: "Antena {name}"
|
||||
roleAssigned: "Rol assignat "
|
||||
@@ -2644,6 +2819,8 @@ _notification:
|
||||
quote: "Citar"
|
||||
reaction: "Reaccions"
|
||||
pollEnded: "Enquesta terminada"
|
||||
scheduledNotePosted: "Nota programada amb èxit "
|
||||
scheduledNotePostFailed: "Ha fallat la programació de la nota"
|
||||
receiveFollowRequest: "Rebuda una petició de seguiment"
|
||||
followRequestAccepted: "Petició de seguiment acceptada"
|
||||
roleAssigned: "Rol donat"
|
||||
@@ -2683,6 +2860,14 @@ _deck:
|
||||
usedAsMinWidthWhenFlexible: "L'amplada mínima es farà servir quan \"Ajust automàtic de l'amplada\" estigui activat"
|
||||
flexible: "Ajust automàtic de l'amplada"
|
||||
enableSyncBetweenDevicesForProfiles: "Activar la sincronització de la informació de perfils de dispositiu a dispositiu"
|
||||
showHowToUse: "Veure la descripció de la interfície d'usuari "
|
||||
_howToUse:
|
||||
addColumn_title: "Afegir columna"
|
||||
addColumn_description: "Pots seleccionar i afegir tipus de columnes."
|
||||
settings_title: "Configuració de la interfície d'usuari "
|
||||
settings_description: "Pots configurar la interfície d'usuari amb detall."
|
||||
switchProfile_title: "Canviar perfil"
|
||||
switchProfile_description: "Pots desar el disseny de la interfície d'usuari com un perfil i anar canviant entre ells quan vulguis."
|
||||
_columns:
|
||||
main: "Principal"
|
||||
widgets: "Ginys"
|
||||
@@ -2694,7 +2879,7 @@ _deck:
|
||||
mentions: "Mencions"
|
||||
direct: "Publicacions directes"
|
||||
roleTimeline: "Línia de temps dels rols"
|
||||
chat: "Xat"
|
||||
chat: "Xateja amb aquest usuari"
|
||||
_dialog:
|
||||
charactersExceeded: "Has arribat al màxim de caràcters! Actualment és {current} de {max}"
|
||||
charactersBelow: "Ets per sota del mínim de caràcters! Actualment és {current} de {min}"
|
||||
@@ -2743,6 +2928,8 @@ _abuseReport:
|
||||
notifiedWebhook: "Webhook que s'ha de fer servir"
|
||||
deleteConfirm: "Segur que vols esborrar el destinatari de l'informe de moderació?"
|
||||
_moderationLogTypes:
|
||||
clearQueue: "Esborra la cua de feina"
|
||||
promoteQueue: "Tornar a intentar la feina de la cua"
|
||||
createRole: "Rol creat"
|
||||
deleteRole: "Rol esborrat"
|
||||
updateRole: "Rol actualitzat"
|
||||
@@ -2800,6 +2987,7 @@ _fileViewer:
|
||||
url: "URL"
|
||||
uploadedAt: "Pujat el"
|
||||
attachedNotes: "Notes amb aquest fitxer"
|
||||
usage: "Ús "
|
||||
thisPageCanBeSeenFromTheAuthor: "Aquesta pàgina només la pot veure l'usuari que ha pujat aquest fitxer."
|
||||
_externalResourceInstaller:
|
||||
title: "Instal·lar des d'un lloc extern"
|
||||
@@ -3052,6 +3240,7 @@ _bootErrors:
|
||||
otherOption1: "Esborrar la configuració i la memòria cau del client"
|
||||
otherOption2: "Iniciar client senzill"
|
||||
otherOption3: "Iniciar l'eina de reparació "
|
||||
otherOption4: "Iniciar Misskey en mode segur"
|
||||
_search:
|
||||
searchScopeAll: "Tot"
|
||||
searchScopeLocal: "Local"
|
||||
@@ -3088,6 +3277,8 @@ _serverSetupWizard:
|
||||
doYouConnectToFediverse_description1: "Quan es connecta amb una xarxa de servidors distribuïts (Fedivers), els continguts poden intercanviar-se amb altres servidors i entre ells."
|
||||
doYouConnectToFediverse_description2: "La connexió amb el Fedivers també es coneix com a \"federació\"."
|
||||
youCanConfigureMoreFederationSettingsLater: "Les configuracions avançades, com especificar els servidors amb els quals es pot federar, es poden fer més tard."
|
||||
remoteContentsCleaning: "Neteja automàtica del contingut rebut"
|
||||
remoteContentsCleaning_description: "Quan es comença a federar es rep un munt de contingut, quan s'activa la neteja automàtica el contingut antic que no es consulta serà eliminat del servidor, el que permet estalviar espai d'emmagatzematge."
|
||||
adminInfo: "Informació de l'administrador "
|
||||
adminInfo_description: "Estableix la informació de l'administrador que es farà servir per rebre consultes."
|
||||
adminInfo_mustBeFilled: "Aquesta informació ha de ser omplerta si el servidor té els registres oberts o la federació es troba activada."
|
||||
@@ -3103,6 +3294,7 @@ _serverSetupWizard:
|
||||
text2: "Si ho desitges, agrairíem molt la teva donació per poder seguir desenvolupant el projecte."
|
||||
text3: "També hi ha privilegis especials per als donants!"
|
||||
_uploader:
|
||||
editImage: "Edició d'imatges"
|
||||
compressedToX: "Comprimit a {x}"
|
||||
savedXPercent: "{x}% d'estalvi "
|
||||
abortConfirm: "Hi ha un arxiu que no s'ha pujat, vols cancel·lar?"
|
||||
@@ -3132,17 +3324,20 @@ _watermarkEditor:
|
||||
title: "Editar la marca d'aigua "
|
||||
cover: "Cobrir-ho tot"
|
||||
repeat: "Repetir"
|
||||
preserveBoundingRect: "Ajusta'l per evitar que sobresortir en fer la rotació "
|
||||
opacity: "Opacitat"
|
||||
scale: "Mida"
|
||||
text: "Text"
|
||||
qr: "Codi QR"
|
||||
position: "Posició "
|
||||
margin: "Marge"
|
||||
type: "Tipus"
|
||||
image: "Imatges"
|
||||
advanced: "Avançat"
|
||||
angle: "Angle"
|
||||
stripe: "Bandes"
|
||||
stripeWidth: "Amplada de la banda"
|
||||
stripeFrequency: "Freqüència de la banda"
|
||||
angle: "Angle"
|
||||
polkadot: "Lunars"
|
||||
checker: "Escacs"
|
||||
polkadotMainDotOpacity: "Opacitat del lunar principal"
|
||||
@@ -3150,16 +3345,21 @@ _watermarkEditor:
|
||||
polkadotSubDotOpacity: "Opacitat del lunar secundari"
|
||||
polkadotSubDotRadius: "Mida del lunar secundari"
|
||||
polkadotSubDotDivisions: "Nombre de punts secundaris"
|
||||
leaveBlankToAccountUrl: "Si deixes aquest camp buit, es farà servir l'URL del teu compte"
|
||||
failedToLoadImage: "Error en carregar la imatge"
|
||||
_imageEffector:
|
||||
title: "Efecte"
|
||||
addEffect: "Afegeix un efecte"
|
||||
discardChangesConfirm: "Vols descartar els canvis i sortir?"
|
||||
failedToLoadImage: "Error en carregar la imatge"
|
||||
_fxs:
|
||||
chromaticAberration: "Aberració cromàtica"
|
||||
glitch: "Glitch"
|
||||
mirror: "Mirall"
|
||||
invert: "Inversió cromàtica "
|
||||
grayscale: "Monocrom "
|
||||
blur: "Desenfocament"
|
||||
pixelate: "Mosaic"
|
||||
colorAdjust: "Correcció de color"
|
||||
colorClamp: "Compressió cromàtica "
|
||||
colorClampAdvanced: "Compressió de cromàtica avançada "
|
||||
@@ -3171,3 +3371,72 @@ _imageEffector:
|
||||
checker: "Escacs"
|
||||
blockNoise: "Bloqueig de soroll"
|
||||
tearing: "Trencament d'imatge "
|
||||
fill: "Omplir"
|
||||
_fxProps:
|
||||
angle: "Angle"
|
||||
scale: "Mida"
|
||||
size: "Mida"
|
||||
radius: "Radi"
|
||||
samples: "Mida de la mostra"
|
||||
offset: "Posició "
|
||||
color: "Color"
|
||||
opacity: "Opacitat"
|
||||
normalize: "Normalitzar"
|
||||
amount: "Quantitat"
|
||||
lightness: "Brillantor"
|
||||
contrast: "Contrast"
|
||||
hue: "Tonalitat"
|
||||
brightness: "Brillantor"
|
||||
saturation: "Saturació"
|
||||
max: "Màxim"
|
||||
min: "Mínim"
|
||||
direction: "Direcció "
|
||||
phase: "Fase"
|
||||
frequency: "Freqüència "
|
||||
strength: "Intensitat"
|
||||
glitchChannelShift: "Canvi de canal "
|
||||
seed: "Llavors"
|
||||
redComponent: "Component vermell"
|
||||
greenComponent: "Component verd"
|
||||
blueComponent: "Component blau"
|
||||
threshold: "Llindar"
|
||||
centerX: "Centre de X"
|
||||
centerY: "Centre de Y"
|
||||
density: "Densitat"
|
||||
zoomLinesOutlineThickness: "Amplada de les vores exteriors"
|
||||
zoomLinesMaskSize: "Diàmetre del centre"
|
||||
circle: "Cercle"
|
||||
drafts: "Esborrany "
|
||||
_drafts:
|
||||
select: "Seleccionar esborrany"
|
||||
cannotCreateDraftAnymore: "S'ha sobrepassat el nombre màxim d'esborranys que es poden crear."
|
||||
cannotCreateDraft: "Amb aquest contingut no es poden crear esborranys."
|
||||
delete: "Esborrar esborranys"
|
||||
deleteAreYouSure: "Vols esborrar els esborranys?"
|
||||
noDrafts: "No hi ha esborranys"
|
||||
replyTo: "Respondre a {user}"
|
||||
quoteOf: "Citar les notes de {user}"
|
||||
postTo: "Destinat a {channel}"
|
||||
saveToDraft: "Desar com a esborrany"
|
||||
restoreFromDraft: "Restaurar des dels esborranys"
|
||||
restore: "Restaurar esborrany"
|
||||
listDrafts: "Llistat d'esborranys"
|
||||
schedule: "Programació esborranys"
|
||||
listScheduledNotes: "Llista de notes programades"
|
||||
cancelSchedule: "Cancel·lar la programació"
|
||||
qr: "Codi QR"
|
||||
_qr:
|
||||
showTabTitle: "Veure"
|
||||
readTabTitle: "Escanejar "
|
||||
shareTitle: "{name} {acct}"
|
||||
shareText: "Segueix-me al Fediverse"
|
||||
chooseCamera: "Seleccionar càmera "
|
||||
cannotToggleFlash: "No es pot activar el flaix"
|
||||
turnOnFlash: "Activar el flaix"
|
||||
turnOffFlash: "Apagar el flaix"
|
||||
startQr: "Reiniciar el lector de codis QR"
|
||||
stopQr: "Parar el lector de codis QR"
|
||||
noQrCodeFound: "No s'ha trobat cap codi QR"
|
||||
scanFile: "Escanejar la imatge des del dispositiu"
|
||||
raw: "Text"
|
||||
mfm: "MFM"
|
||||
|
||||
@@ -130,6 +130,7 @@ reactions: "Reakce"
|
||||
reactionSettingDescription2: "Přetažením změníte pořadí, kliknutím smažete, zmáčkněte \"+\" k přidání"
|
||||
rememberNoteVisibility: "Zapamatovat nastavení zobrazení poznámky"
|
||||
attachCancel: "Odstranit přílohu"
|
||||
deleteFile: "Smazat soubor"
|
||||
markAsSensitive: "Označit jako NSFW"
|
||||
unmarkAsSensitive: "Odznačit jako NSFW"
|
||||
enterFileName: "Zadejte název souboru"
|
||||
@@ -205,6 +206,7 @@ blockThisInstance: "Blokovat tuto instanci"
|
||||
silenceThisInstance: "Utišit tuto instanci"
|
||||
operations: "Operace"
|
||||
software: "Software"
|
||||
softwareName: "Software"
|
||||
version: "Verze"
|
||||
metadata: "Metadata"
|
||||
withNFiles: "{n} soubor(ů)"
|
||||
@@ -231,6 +233,7 @@ noteDeleteConfirm: "Jste si jistí že chcete smazat tuhle poznámku?"
|
||||
pinLimitExceeded: "Nemůžete připnout další poznámky."
|
||||
done: "Hotovo"
|
||||
processing: "Zpracovávám"
|
||||
preprocessing: "Připravuji..."
|
||||
preview: "Náhled"
|
||||
default: "Výchozí"
|
||||
defaultValueIs: "Základní hodnota: {value}"
|
||||
@@ -265,6 +268,7 @@ removed: "Smazáno"
|
||||
removeAreYouSure: "Jste si jistí že chcete smazat \"{x}\"?"
|
||||
deleteAreYouSure: "Jste si jistí že chcete smazat \"{x}\"?"
|
||||
resetAreYouSure: "Opravdu resetovat?"
|
||||
areYouSure: "Jste si jistí?"
|
||||
saved: "Uloženo"
|
||||
upload: "Nahrát soubory"
|
||||
keepOriginalUploading: "Ponechat originální obrázek"
|
||||
@@ -275,9 +279,12 @@ uploadFromUrl: "Nahrát z URL adresy"
|
||||
uploadFromUrlDescription: "URL adresa souboru, který chcete nahrát"
|
||||
uploadFromUrlRequested: "Upload zažádán"
|
||||
uploadFromUrlMayTakeTime: "Může trvat nějakou dobu, dokud nebude dokončeno nahrávání."
|
||||
uploadNFiles: "Uploadovat {n} souborů"
|
||||
explore: "Objevovat"
|
||||
messageRead: "Přečtené"
|
||||
readAllChatMessages: "Označit všechny zprávy za přečtené"
|
||||
noMoreHistory: "To je vše"
|
||||
startChat: "Začít chat"
|
||||
nUsersRead: "přečteno {n} uživateli"
|
||||
agreeTo: "Souhlasím s {0}"
|
||||
agree: "Souhlasím"
|
||||
@@ -308,12 +315,15 @@ selectFile: "Vybrat soubor"
|
||||
selectFiles: "Vybrat soubory"
|
||||
selectFolder: "Vyberte složku"
|
||||
selectFolders: "Vyberte složky"
|
||||
fileNotSelected: "Nebyl vybrán žádný soubor"
|
||||
renameFile: "Přejmenovat soubor"
|
||||
folderName: "Název složky"
|
||||
createFolder: "Vytvořit složku"
|
||||
renameFolder: "Přejmenovat složku"
|
||||
deleteFolder: "Odstranit složku"
|
||||
folder: "Složka "
|
||||
addFile: "Přidat soubor"
|
||||
showFile: "Procházet soubory"
|
||||
emptyDrive: "Váš disk je prázdný"
|
||||
emptyFolder: "Tato složka je prázdná"
|
||||
unableToDelete: "Nelze smazat"
|
||||
@@ -424,6 +434,7 @@ totp: "Ověřovací aplikace"
|
||||
totpDescription: "Použít ověřovací aplikaci pro použití jednorázových hesel"
|
||||
moderator: "Moderátor"
|
||||
moderation: "Moderování"
|
||||
moderationNote: "Poznámka moderátora"
|
||||
nUsersMentioned: "{n} uživatelů zmínilo"
|
||||
securityKeyAndPasskey: "Bezpečnostní klíče a tokeny"
|
||||
securityKey: "Bezpečnostní klíč"
|
||||
@@ -479,7 +490,9 @@ uiLanguage: "Jazyk uživatelského rozhraní"
|
||||
aboutX: "O {x}"
|
||||
emojiStyle: "Styl emoji"
|
||||
native: "Výchozí"
|
||||
menuStyle: "Styl nabídky"
|
||||
style: "Vzhled"
|
||||
drawer: "Boční menu"
|
||||
popup: "Vyskakovací okno"
|
||||
showNoteActionsOnlyHover: "Zobrazit akce poznámky jenom při naběhnutí myši"
|
||||
noHistory: "Žádná historie"
|
||||
@@ -535,6 +548,7 @@ deleteAll: "Smazat vše"
|
||||
showFixedPostForm: "Zobrazit formulář pro nové příspěvky nad časovou osou"
|
||||
showFixedPostFormInChannel: "Zobrazit vkládací formulář na vrcholu časové osy (Kanály)"
|
||||
newNoteRecived: "Jsou k dispozici nové poznámky"
|
||||
newNote: "Nová poznámka"
|
||||
sounds: "Zvuky"
|
||||
sound: "Zvuky"
|
||||
listen: "Poslouchat"
|
||||
@@ -614,6 +628,7 @@ medium: "Střední"
|
||||
small: "Malé"
|
||||
generateAccessToken: "Vygenerovat přístupový token"
|
||||
permission: "Oprávnění"
|
||||
adminPermission: "Administrátorská práva"
|
||||
enableAll: "Povolit vše"
|
||||
disableAll: "Vypnout vše"
|
||||
tokenRequested: "Povolit přístup k účtu"
|
||||
@@ -889,6 +904,9 @@ oneHour: "1 hodina"
|
||||
oneDay: "1 den"
|
||||
oneWeek: "1 týden"
|
||||
oneMonth: "1 měsíc"
|
||||
threeMonths: "3 měsíce"
|
||||
oneYear: "1 rok"
|
||||
threeDays: "3 dny"
|
||||
reflectMayTakeTime: "Může trvat nějakou dobu, než se projeví změny."
|
||||
failedToFetchAccountInformation: "Nepodařily se načíst informace o účtě"
|
||||
rateLimitExceeded: "Překročení rychlostního limitu"
|
||||
@@ -1026,6 +1044,8 @@ showClipButtonInNoteFooter: "Přidat \"Připnout\" do akčního menu poznámky"
|
||||
noteIdOrUrl: "ID nebo URL poznámky"
|
||||
video: "Video"
|
||||
videos: "Videa"
|
||||
audio: "Zvuk"
|
||||
audioFiles: "Zvuk"
|
||||
dataSaver: "Spořič dat"
|
||||
accountMigration: "Migrace účtu"
|
||||
accountMoved: "Tenhle uživatel se přesunul na nový účet:"
|
||||
@@ -1053,6 +1073,8 @@ preservedUsernames: "Rezervované uživatelské jména"
|
||||
preservedUsernamesDescription: "Seznam uživatelských jmén na rezervaci oddělené mezerama. Tyhle jména se potom nebudou moc použít při normálním procesu vytvoření účtu ale můžou být použiti manuálně administratorém. Existujících účtů se to nedotkne."
|
||||
createNoteFromTheFile: "Vytvořit poznámku z tohodle souboru"
|
||||
archive: "Archiv"
|
||||
archived: "Archivované"
|
||||
unarchive: "Obnovit"
|
||||
channelArchiveConfirmTitle: "Opravdu chcete archivovat {name}?"
|
||||
channelArchiveConfirmDescription: "Archivovaný kanál se objeví v seznamu kanálů nebo ve výsledcích hledání. Nové poznámky se nedají vložit do seznamu."
|
||||
thisChannelArchived: "Tenhle kanál je archivovaný"
|
||||
@@ -1099,6 +1121,7 @@ doYouAgree: "Souhlasíte?"
|
||||
beSureToReadThisAsItIsImportant: "Přečtěte si prosím tyto důležité informace."
|
||||
iHaveReadXCarefullyAndAgree: "Přečetl jsem si text \"{x}\" a souhlasím s ním."
|
||||
icon: "Avatar"
|
||||
forYou: "Pro vás"
|
||||
replies: "Odpovědět"
|
||||
renotes: "Přeposlat"
|
||||
sourceCode: "Zdrojový kód"
|
||||
@@ -1107,6 +1130,18 @@ lastNDays: "Posledních {n} dnů"
|
||||
surrender: "Zrušit"
|
||||
postForm: "Formulář pro odeslání"
|
||||
information: "Informace"
|
||||
inMinutes: "Minut"
|
||||
inDays: "Dnů"
|
||||
widgets: "Widgety"
|
||||
presets: "Předvolba"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
filename: "Název souboru"
|
||||
_imageFrameEditor:
|
||||
header: "Nadpis"
|
||||
font: "Písmo"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
_chat:
|
||||
invitations: "Pozvat"
|
||||
noHistory: "Žádná historie"
|
||||
@@ -1777,6 +1812,14 @@ _widgets:
|
||||
_userList:
|
||||
chooseList: "Vybrat seznam"
|
||||
clicker: "Clicker"
|
||||
_widgetOptions:
|
||||
height: "Výška"
|
||||
_button:
|
||||
colored: "Barevné"
|
||||
_clock:
|
||||
size: "Velikost"
|
||||
_birthdayFollowings:
|
||||
period: "Trvání"
|
||||
_cw:
|
||||
hide: "Skrýt"
|
||||
show: "Zobrazit více"
|
||||
@@ -1819,6 +1862,9 @@ _postForm:
|
||||
replyPlaceholder: "Odpovědět na tuto poznámku..."
|
||||
quotePlaceholder: "Citovat tuto poznámku..."
|
||||
channelPlaceholder: "Zveřejnit příspěvek do kanálu..."
|
||||
_howToUse:
|
||||
visibility_title: "Viditelnost"
|
||||
menu_title: "Menu"
|
||||
_placeholders:
|
||||
a: "Co máte v plánu?"
|
||||
b: "Co se děje kolem vás?"
|
||||
@@ -2002,7 +2048,7 @@ _deck:
|
||||
list: "Seznamy"
|
||||
channel: "Kanály"
|
||||
mentions: "Zmínění"
|
||||
direct: "Přímý"
|
||||
direct: "Přímé poznámky"
|
||||
roleTimeline: "Časová osa role"
|
||||
_dialog:
|
||||
charactersExceeded: "Překročili jste maximální počet znaků! V současné době je na hodnotě {current} z {max}."
|
||||
@@ -2051,3 +2097,14 @@ _watermarkEditor:
|
||||
type: "Typ"
|
||||
image: "Obrázky"
|
||||
advanced: "Pokročilé"
|
||||
_imageEffector:
|
||||
_fxProps:
|
||||
scale: "Velikost"
|
||||
size: "Velikost"
|
||||
offset: "Pozice"
|
||||
color: "Barva"
|
||||
opacity: "Průhlednost"
|
||||
lightness: "Zesvětlit"
|
||||
_qr:
|
||||
showTabTitle: "Zobrazit"
|
||||
raw: "Text"
|
||||
|
||||
@@ -83,6 +83,8 @@ files: "Dateien"
|
||||
download: "Herunterladen"
|
||||
driveFileDeleteConfirm: "Möchtest du die Datei „{name}“ wirklich löschen? Einige Inhalte, die diese Datei verwenden, werden auch verschwinden."
|
||||
unfollowConfirm: "Möchtest du {name} wirklich nicht mehr folgen?"
|
||||
cancelFollowRequestConfirm: "Möchten Sie die Voll-Anfrage an {name} zurückziehen?"
|
||||
rejectFollowRequestConfirm: "Möchtest du die Follow-Anfrage von {name} ablehnen?"
|
||||
exportRequested: "Du hast einen Export angefragt. Dies kann etwas Zeit in Anspruch nehmen. Sobald der Export abgeschlossen ist, wird er deiner Drive hinzugefügt."
|
||||
importRequested: "Du hast einen Import angefragt. Dies kann etwas Zeit in Anspruch nehmen."
|
||||
lists: "Listen"
|
||||
@@ -253,6 +255,7 @@ noteDeleteConfirm: "Möchtest du diese Notiz wirklich löschen?"
|
||||
pinLimitExceeded: "Du kannst nicht noch mehr Notizen anheften."
|
||||
done: "Fertig"
|
||||
processing: "In Bearbeitung …"
|
||||
preprocessing: "In Vorbereitung"
|
||||
preview: "Vorschau"
|
||||
default: "Standard"
|
||||
defaultValueIs: "Standardwert: {value}"
|
||||
@@ -301,6 +304,7 @@ uploadFromUrlMayTakeTime: "Es kann eine Weile dauern, bis das Hochladen abgeschl
|
||||
uploadNFiles: "Lade {n} Dateien hoch"
|
||||
explore: "Erkunden"
|
||||
messageRead: "Gelesen"
|
||||
readAllChatMessages: "Alle Nachrichten als gelesen markieren"
|
||||
noMoreHistory: "Kein weiterer Verlauf vorhanden"
|
||||
startChat: "Chat starten"
|
||||
nUsersRead: "Von {n} Benutzern gelesen"
|
||||
@@ -333,6 +337,7 @@ fileName: "Dateiname"
|
||||
selectFile: "Datei auswählen"
|
||||
selectFiles: "Dateien auswählen"
|
||||
selectFolder: "Ordner auswählen"
|
||||
unselectFolder: "Ordnerauswahl aufheben"
|
||||
selectFolders: "Ordner auswählen"
|
||||
fileNotSelected: "Keine Datei ausgewählt"
|
||||
renameFile: "Datei umbenennen"
|
||||
@@ -345,6 +350,7 @@ addFile: "Datei hinzufügen"
|
||||
showFile: "Datei anzeigen"
|
||||
emptyDrive: "Deine Drive ist leer"
|
||||
emptyFolder: "Dieser Ordner ist leer"
|
||||
dropHereToUpload: "Dateien hier ablegen, um sie hochzuladen."
|
||||
unableToDelete: "Nicht löschbar"
|
||||
inputNewFileName: "Gib einen neuen Dateinamen ein"
|
||||
inputNewDescription: "Gib eine neue Beschreibung ein"
|
||||
@@ -537,6 +543,7 @@ regenerate: "Regenerieren"
|
||||
fontSize: "Schriftgröße"
|
||||
mediaListWithOneImageAppearance: "Höhe von Medienlisten mit nur einem Bild"
|
||||
limitTo: "Auf {x} begrenzen"
|
||||
showMediaListByGridInWideArea: "Medienlisten auf breiteren Bildschirmen nebeneinander anzeigen"
|
||||
noFollowRequests: "Keine ausstehenden Follow-Anfragen vorhanden"
|
||||
openImageInNewTab: "Bilder in neuem Tab öffnen"
|
||||
dashboard: "Dashboard"
|
||||
@@ -772,6 +779,7 @@ lockedAccountInfo: "Auch wenn du Follow-Anfragen auf manuelle Bestätigung setzt
|
||||
alwaysMarkSensitive: "Medien standardmäßig als sensibel markieren"
|
||||
loadRawImages: "Anstatt Vorschaubilder immer Originalbilder anzeigen"
|
||||
disableShowingAnimatedImages: "Animierte Bilder nicht abspielen"
|
||||
disableShowingAnimatedImages_caption: "Unabhängig von dieser Einstellung kann es vorkommen, dass animierte Bilder nicht abgespielt werden, wenn z. B. die Barrierefreiheits- oder Energiespareinstellungen des Browsers oder des Betriebssystems eingreifen."
|
||||
highlightSensitiveMedia: "Sensitive Medien markieren"
|
||||
verificationEmailSent: "Eine Bestätigungsmail wurde an deine Email-Adresse versendet. Besuche den dort enthaltenen Link, um die Verifizierung abzuschließen."
|
||||
notSet: "Nicht konfiguriert"
|
||||
@@ -1018,6 +1026,9 @@ pushNotificationAlreadySubscribed: "Push-Benachrichtigungen sind bereits aktivie
|
||||
pushNotificationNotSupported: "Entweder dein Browser oder deine Instanz unterstützt Push-Benachrichtigungen nicht"
|
||||
sendPushNotificationReadMessage: "Push-Benachrichtigungen löschen, sobald sie gelesen wurden"
|
||||
sendPushNotificationReadMessageCaption: "Dies kann gegebenenfalls den Batterieverbrauch deines Gerätes erhöhen."
|
||||
pleaseAllowPushNotification: "Bitte erlauben Sie Benachrichtigungen in Ihrem Browser."
|
||||
browserPushNotificationDisabled: "Das Abrufen der Berechtigung zum Senden von Benachrichtigungen ist fehlgeschlagen."
|
||||
browserPushNotificationDisabledDescription: "Sie haben keine Berechtigung, Benachrichtigungen von {serverName} zu senden. Bitte erlauben Sie Benachrichtigungen in den Browser-Einstellungen und versuchen Sie es erneut."
|
||||
windowMaximize: "Maximieren"
|
||||
windowMinimize: "Minimieren"
|
||||
windowRestore: "Wiederherstellen"
|
||||
@@ -1054,6 +1065,7 @@ permissionDeniedError: "Aktion verweigert"
|
||||
permissionDeniedErrorDescription: "Dieses Benutzerkonto besitzt nicht die Berechtigung, um diese Aktion auszuführen."
|
||||
preset: "Vorlage"
|
||||
selectFromPresets: "Aus Vorlagen wählen"
|
||||
custom: "Benutzerdefiniert"
|
||||
achievements: "Errungenschaften"
|
||||
gotInvalidResponseError: "Ungültige Antwort des Servers"
|
||||
gotInvalidResponseErrorDescription: "Eventuell ist der Server momentan nicht erreichbar oder untergeht Wartungsarbeiten. Bitte versuche es später noch einmal."
|
||||
@@ -1092,6 +1104,7 @@ prohibitedWordsDescription2: "Durch die Verwendung von Leerzeichen können AND-V
|
||||
hiddenTags: "Ausgeblendete Hashtags"
|
||||
hiddenTagsDescription: "Die hier eingestellten Tags werden nicht mehr in den Trends angezeigt. Mit der Umschalttaste können mehrere ausgewählt werden."
|
||||
notesSearchNotAvailable: "Die Notizsuche ist nicht verfügbar."
|
||||
usersSearchNotAvailable: "Die Benutzersuche ist nicht verfügbar."
|
||||
license: "Lizenz"
|
||||
unfavoriteConfirm: "Wirklich aus Favoriten entfernen?"
|
||||
myClips: "Meine Clips"
|
||||
@@ -1166,6 +1179,7 @@ installed: "Installiert"
|
||||
branding: "Branding"
|
||||
enableServerMachineStats: "Hardwareinformationen des Servers veröffentlichen"
|
||||
enableIdenticonGeneration: "Generierung von Benutzer-Identicons aktivieren"
|
||||
showRoleBadgesOfRemoteUsers: "Rollensymbole anzeigen, die Remote-Benutzern zugewiesen wurden."
|
||||
turnOffToImprovePerformance: "Deaktivierung kann zu höherer Leistung führen."
|
||||
createInviteCode: "Einladung erstellen"
|
||||
createWithOptions: "Einladung mit Optionen erstellen"
|
||||
@@ -1243,7 +1257,7 @@ releaseToRefresh: "Zum Aktualisieren loslassen"
|
||||
refreshing: "Wird aktualisiert..."
|
||||
pullDownToRefresh: "Zum Aktualisieren ziehen"
|
||||
useGroupedNotifications: "Benachrichtigungen gruppieren"
|
||||
signupPendingError: "Beim Überprüfen der Mailadresse ist etwas schiefgelaufen. Der Link könnte abgelaufen sein."
|
||||
emailVerificationFailedError: "Es gab ein Problem bei der Überprüfung Ihrer E-Mail-Adresse. Der Link ist möglicherweise abgelaufen."
|
||||
cwNotationRequired: "Ist \"Inhaltswarnung verwenden\" aktiviert, muss eine Beschreibung gegeben werden."
|
||||
doReaction: "Reagieren"
|
||||
code: "Code"
|
||||
@@ -1313,6 +1327,8 @@ availableRoles: "Verfügbare Rollen"
|
||||
acknowledgeNotesAndEnable: "Schalten Sie dies erst ein, wenn Sie die Vorsichtsmaßnahmen verstanden haben."
|
||||
federationSpecified: "Dieser Server arbeitet mit Whitelist-Föderation. Er kann nicht mit anderen als den vom Administrator angegebenen Servern interagieren."
|
||||
federationDisabled: "Föderation ist auf diesem Server deaktiviert. Es ist nicht möglich, mit Benutzern auf anderen Servern zu interagieren."
|
||||
draft: "Entwurf"
|
||||
draftsAndScheduledNotes: "Entwürfe und geplante Beiträge"
|
||||
confirmOnReact: "Reagieren bestätigen"
|
||||
reactAreYouSure: "Willst du eine \"{emoji}\"-Reaktion hinzufügen?"
|
||||
markAsSensitiveConfirm: "Möchtest du dieses Medium als sensibel kennzeichnen?"
|
||||
@@ -1340,6 +1356,8 @@ postForm: "Notizfenster"
|
||||
textCount: "Zeichenanzahl"
|
||||
information: "Über"
|
||||
chat: "Chat"
|
||||
directMessage: "Mit dem Benutzer chatten"
|
||||
directMessage_short: "Nachrichten"
|
||||
migrateOldSettings: "Alte Client-Einstellungen migrieren"
|
||||
migrateOldSettings_description: "Dies sollte normalerweise automatisch geschehen, aber wenn die Migration aus irgendeinem Grund nicht erfolgreich war, kannst du den Migrationsprozess selbst manuell auslösen. Die aktuellen Konfigurationsinformationen werden dabei überschrieben."
|
||||
compress: "Komprimieren"
|
||||
@@ -1347,7 +1365,7 @@ right: "Rechts"
|
||||
bottom: "Unten"
|
||||
top: "Oben"
|
||||
embed: "Einbetten"
|
||||
settingsMigrating: "Ihre Einstellungen werden gerade migriert, Bitte warten Sie einen Moment... (Sie können die Einstellungen später auch manuell migrieren, indem Sie zu Einstellungen → Sonstiges → Alte Einstellungen migrieren gehen)"
|
||||
settingsMigrating: "Deine Einstellungen werden gerade migriert. Bitte warte einen Moment... (Du kannst die Einstellungen später auch manuell migrieren, indem du zu Einstellungen → Anderes → Alte Einstellungen migrieren gehst)"
|
||||
readonly: "Nur Lesezugriff"
|
||||
goToDeck: "Zurück zum Deck"
|
||||
federationJobs: "Föderation Jobs"
|
||||
@@ -1367,7 +1385,83 @@ redisplayAllTips: "Alle „Tipps und Tricks“ wieder anzeigen"
|
||||
hideAllTips: "Alle „Tipps und Tricks“ ausblenden"
|
||||
defaultImageCompressionLevel: "Standard-Bildkomprimierungsstufe"
|
||||
defaultImageCompressionLevel_description: "Ein niedrigerer Wert erhält die Bildqualität, erhöht aber die Dateigröße. <br>Höhere Werte reduzieren die Dateigröße, verringern aber die Bildqualität."
|
||||
defaultCompressionLevel: "Standard-Kompressionsgrad"
|
||||
defaultCompressionLevel_description: "Bei einem niedrigeren Wert bleibt die Qualität erhalten, aber die Dateigröße nimmt zu.<br> Bei einem höheren Wert lässt sich die Dateigröße verringern, aber die Qualität nimmt ab."
|
||||
inMinutes: "Minute(n)"
|
||||
inDays: "Tag(en)"
|
||||
safeModeEnabled: "Der abgesicherte Modus ist aktiviert."
|
||||
pluginsAreDisabledBecauseSafeMode: "Da der abgesicherte Modus aktiviert ist, sind alle Plugins deaktiviert."
|
||||
customCssIsDisabledBecauseSafeMode: "Da der abgesicherte Modus aktiviert ist, wird benutzerdefiniertes CSS nicht angewendet."
|
||||
themeIsDefaultBecauseSafeMode: "Solange der abgesicherte Modus aktiviert ist, wird das Standard-Theme verwendet. Wenn Sie den abgesicherten Modus deaktivieren, wird es wieder zurückgesetzt."
|
||||
thankYouForTestingBeta: "Vielen Dank für Ihre Unterstützung beim Testen der Beta-Version!"
|
||||
createUserSpecifiedNote: "Benutzerdefinierte Notiz erstellen"
|
||||
schedulePost: "Beitrag planen"
|
||||
scheduleToPostOnX: "Der Beitrag wird für {x} geplant.x"
|
||||
scheduledToPostOnX: "Der Beitrag ist für {x} geplant."
|
||||
schedule: "Planen"
|
||||
scheduled: "Geplant"
|
||||
widgets: "Widgets"
|
||||
deviceInfo: "Geräteinformation"
|
||||
deviceInfoDescription: "Bei technischen Anfragen kann es hilfreich sein, die folgenden Informationen anzugeben, da dies zur Lösung des Problems beitragen kann."
|
||||
youAreAdmin: "Sie sind ein Administrator"
|
||||
frame: "Rahmen"
|
||||
presets: "Vorlage"
|
||||
zeroPadding: "Nullauffüllung"
|
||||
nothingToConfigure: "Es sind keine Einstellungen verfügbar"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
caption: "Dateibeschriftung"
|
||||
filename: "Dateiname"
|
||||
filename_without_ext: "Dateiname ohne Erweiterung"
|
||||
year: "Jahr der Aufnahme"
|
||||
month: "Monat der Aufnahme"
|
||||
day: "Tag der Aufnahme"
|
||||
hour: "Stunde der Aufnahmezeit"
|
||||
minute: "Minute der Aufnahmezeit"
|
||||
second: "Sekunde der Aufnahmezeit"
|
||||
camera_model: "Kameraname"
|
||||
camera_lens_model: "Objektivname"
|
||||
camera_mm: "Brennweite"
|
||||
camera_mm_35: "Brennweite (35-mm-Äquivalent)"
|
||||
camera_f: "Blende"
|
||||
camera_s: "Verschlusszeit"
|
||||
camera_iso: "ISO-Empfindlichkeit"
|
||||
gps_lat: "Breitengrad"
|
||||
gps_long: "Längengrad"
|
||||
_imageFrameEditor:
|
||||
title: "Rahmenbearbeitung"
|
||||
tip: "Sie können das Bild dekorieren, indem Sie einen Rahmen sowie ein Etikett mit Metadaten hinzufügen."
|
||||
header: "Kopfzeile"
|
||||
footer: "Fußzeile"
|
||||
borderThickness: "Randbreite"
|
||||
labelThickness: "Beschriftungsbreite"
|
||||
labelScale: "Etikettenskala"
|
||||
centered: "Zentriert"
|
||||
captionMain: "Überschrift (groß)"
|
||||
captionSub: "Beschriftung (klein)"
|
||||
availableVariables: "Verfügbare Variablen"
|
||||
withQrCode: "QR-Code"
|
||||
backgroundColor: "Hintergrundfarbe"
|
||||
textColor: "Textfarbe"
|
||||
font: "Schriftart"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
quitWithoutSaveConfirm: "Nicht gespeicherte Änderungen verwerfen?"
|
||||
failedToLoadImage: "Das Laden des Bildes ist fehlgeschlagen."
|
||||
_compression:
|
||||
_quality:
|
||||
high: "Hohe Qualität"
|
||||
medium: "Mittlere Qualität"
|
||||
low: "Niedrige Qualität"
|
||||
_size:
|
||||
large: "Groß"
|
||||
medium: "Medium"
|
||||
small: "Klein"
|
||||
_order:
|
||||
newest: "Neueste zuerst"
|
||||
oldest: "Älteste zuerst"
|
||||
_chat:
|
||||
messages: "Nachrichten"
|
||||
noMessagesYet: "Noch keine Nachrichten"
|
||||
newMessage: "Neue Nachricht"
|
||||
individualChat: "Privater Chat"
|
||||
@@ -1455,6 +1549,12 @@ _settings:
|
||||
contentsUpdateFrequency_description2: "Wenn der Echtzeitmodus aktiviert ist, werden die Inhalte unabhängig von dieser Einstellung in Echtzeit aktualisiert."
|
||||
showUrlPreview: "URL-Vorschau anzeigen"
|
||||
showAvailableReactionsFirstInNote: "Zeige die verfügbaren Reaktionen im oberen Bereich an."
|
||||
showPageTabBarBottom: "Tab-Leiste der Seite unten anzeigen"
|
||||
emojiPaletteBanner: "Sie können Voreinstellungen, die im Emoji-Picker dauerhaft angezeigt werden sollen, als Palette registrieren oder die Anzeigeart des Pickers anpassen."
|
||||
enableAnimatedImages: "Animierte Bilder aktivieren"
|
||||
settingsPersistence_title: "Persistenz der Einstellungen"
|
||||
settingsPersistence_description1: "Durch das Aktivieren der persistenten Speicherung der Einstellungen kann verhindert werden, dass Einstellungsinformationen verloren gehen."
|
||||
settingsPersistence_description2: "Je nach Umgebung ist eine Aktivierung möglicherweise nicht möglich."
|
||||
_chat:
|
||||
showSenderName: "Name des Absenders anzeigen"
|
||||
sendOnEnter: "Eingabetaste sendet Nachricht"
|
||||
@@ -1463,6 +1563,8 @@ _preferencesProfile:
|
||||
profileNameDescription: "Lege einen Namen fest, der dieses Gerät identifiziert."
|
||||
profileNameDescription2: "Beispiel: \"Haupt-PC\", \"Smartphone\""
|
||||
manageProfiles: "Profile verwalten"
|
||||
shareSameProfileBetweenDevicesIsNotRecommended: "Es wird nicht empfohlen, dasselbe Profil auf mehreren Geräten zu teilen."
|
||||
useSyncBetweenDevicesOptionIfYouWantToSyncSetting: "Wenn es Einstellungselemente gibt, die Sie über mehrere Geräte synchronisieren möchten, aktivieren Sie bitte die Option „Über mehrere Geräte synchronisieren“ jeweils einzeln."
|
||||
_preferencesBackup:
|
||||
autoBackup: "Automatische Sicherung"
|
||||
restoreFromBackup: "Wiederherstellen aus der Sicherung"
|
||||
@@ -1472,6 +1574,7 @@ _preferencesBackup:
|
||||
youNeedToNameYourProfileToEnableAutoBackup: "Um die automatische Sicherung zu aktivieren, müssen Profilnamen festgelegt werden."
|
||||
autoPreferencesBackupIsNotEnabledForThisDevice: "Die automatische Sicherung der Einstellungen ist auf diesem Gerät nicht aktiviert."
|
||||
backupFound: "Konfigurationssicherung gefunden."
|
||||
forceBackup: "Erzwungenes Backup der Einstellungen"
|
||||
_accountSettings:
|
||||
requireSigninToViewContents: "Anmeldung erfordern, um Inhalte anzuzeigen"
|
||||
requireSigninToViewContentsDescription1: "Erfordere eine Anmeldung, um alle Notizen und andere Inhalte anzuzeigen, die du erstellt hast. Dadurch wird verhindert, dass Crawler deine Informationen sammeln."
|
||||
@@ -1628,6 +1731,10 @@ _serverSettings:
|
||||
fanoutTimelineDbFallback: "Auf die Datenbank zurückfallen"
|
||||
fanoutTimelineDbFallbackDescription: "Ist diese Option aktiviert, wird die Chronik auf zusätzliche Abfragen in der Datenbank zurückgreifen, wenn sich die Chronik nicht im Cache befindet. Eine Deaktivierung führt zu geringerer Serverlast, aber schränkt den Zeitraum der abrufbaren Chronik ein. "
|
||||
reactionsBufferingDescription: "Wenn diese Option aktiviert ist, kann sie die Leistung beim Erstellen von Reaktionen erheblich verbessern und die Belastung der Datenbank verringern. Allerdings steigt die Speichernutzung von Redis."
|
||||
remoteNotesCleaning: "Automatische Bereinigung von Remote-Beiträgen"
|
||||
remoteNotesCleaning_description: "Wenn diese Option aktiviert ist, werden Remote-Beiträge, die eine bestimmte Zeit überschritten haben, regelmäßig bereinigt, um ein Aufblähen der Datenbank zu verhindern."
|
||||
remoteNotesCleaningMaxProcessingDuration: "Maximale fortlaufende Dauer des Reinigungsverarbeitungsprozesses"
|
||||
remoteNotesCleaningExpiryDaysForEachNotes: "Mindestaufbewahrungsdauer für Notizen"
|
||||
inquiryUrl: "Kontakt-URL"
|
||||
inquiryUrlDescription: "Gib eine URL für das Kontaktformular der Serverbetreiber oder eine Webseite an, die Kontaktinformationen enthält."
|
||||
openRegistration: "Registrierung von Konten aktivieren"
|
||||
@@ -1645,6 +1752,12 @@ _serverSettings:
|
||||
allowExternalApRedirect_description: "Wenn diese Option aktiviert ist, können andere Server Inhalte von Drittanbietern über diesen Server abfragen, was jedoch zu Content-Spoofing führen kann."
|
||||
userGeneratedContentsVisibilityForVisitor: "Sichtbarkeit von nutzergenerierten Inhalten für Gäste"
|
||||
userGeneratedContentsVisibilityForVisitor_description: "Dies ist nützlich, um zu verhindern, dass unangemessene Inhalte, die nicht gut moderiert sind, ungewollt über deinen eigenen Server im Internet veröffentlicht werden."
|
||||
userGeneratedContentsVisibilityForVisitor_description2: "Die uneingeschränkte Veröffentlichung aller Inhalte des Servers im Internet, einschließlich der vom Server empfangenen Fremdinhalte, birgt Risiken. Dies ist besonders wichtig für Betrachter, die sich des dezentralen Charakters der Inhalte nicht bewusst sind, da sie selbst fremde Inhalte fälschlicherweise als auf dem Server erstellte Inhalte wahrnehmen könnten."
|
||||
restartServerSetupWizardConfirm_title: "Möchten Sie den Assistenten für die Ersteinrichtung des Servers erneut ausführen?"
|
||||
restartServerSetupWizardConfirm_text: "Einige aktuelle Einstellungen werden zurückgesetzt."
|
||||
entrancePageStyle: "Stil der Einstiegsseite"
|
||||
showTimelineForVisitor: "Zeitleiste anzeigen"
|
||||
showActivitiesForVisitor: "Aktivitäten anzeigen"
|
||||
_userGeneratedContentsVisibilityForVisitor:
|
||||
all: "Alles ist öffentlich"
|
||||
localOnly: "Nur lokale Inhalte werden veröffentlicht, fremde Inhalte bleiben privat"
|
||||
@@ -1967,6 +2080,7 @@ _role:
|
||||
canManageAvatarDecorations: "Profilbilddekorationen verwalten"
|
||||
driveCapacity: "Drive-Kapazität"
|
||||
maxFileSize: "Maximale Dateigröße, die hochgeladen werden kann"
|
||||
maxFileSize_caption: "Bei einem Reverse Proxy oder einem CDN können andere vorgelagerte Konfigurationswerte vorhanden sein."
|
||||
alwaysMarkNsfw: "Dateien immer als NSFW markieren"
|
||||
canUpdateBioMedia: "Kann ein Profil- oder ein Bannerbild bearbeiten"
|
||||
pinMax: "Maximale Anzahl an angehefteten Notizen"
|
||||
@@ -1981,6 +2095,7 @@ _role:
|
||||
descriptionOfRateLimitFactor: "Je niedriger desto weniger restriktiv, je höher destro restriktiver."
|
||||
canHideAds: "Kann Werbung ausblenden"
|
||||
canSearchNotes: "Nutzung der Notizsuchfunktion"
|
||||
canSearchUsers: "Nutzung der Benutzersuche"
|
||||
canUseTranslator: "Verwendung des Übersetzers"
|
||||
avatarDecorationLimit: "Maximale Anzahl an Profilbilddekorationen, die angebracht werden können"
|
||||
canImportAntennas: "Importieren von Antennen erlauben"
|
||||
@@ -1992,6 +2107,9 @@ _role:
|
||||
uploadableFileTypes: "Hochladbare Dateitypen"
|
||||
uploadableFileTypes_caption: "Gibt die zulässigen MIME-/Dateitypen an. Mehrere MIME-Typen können durch einen Zeilenumbruch getrennt angegeben werden, und Platzhalter können mit einem Sternchen (*) angegeben werden. (z. B. image/*)"
|
||||
uploadableFileTypes_caption2: "Bei manchen Dateien ist es nicht möglich, den Typ zu bestimmen. Um solche Dateien zuzulassen, füge {x} der Spezifikation hinzu."
|
||||
noteDraftLimit: "Anzahl der möglichen Entwürfe für serverseitige Notizen"
|
||||
scheduledNoteLimit: "Maximale Anzahl gleichzeitig erstellbarer geplanter Beiträge"
|
||||
watermarkAvailable: "Kann die Wasserzeichenfunktion verwenden"
|
||||
_condition:
|
||||
roleAssignedTo: "Manuellen Rollen zugewiesen"
|
||||
isLocal: "Lokaler Benutzer"
|
||||
@@ -2151,6 +2269,7 @@ _theme:
|
||||
install: "Farbschemata installieren"
|
||||
manage: "Farbschemaverwaltung"
|
||||
code: "Farbschemencode"
|
||||
copyThemeCode: "Farbschemencode kopieren"
|
||||
description: "Beschreibung"
|
||||
installed: "{name} wurde installiert"
|
||||
installedThemes: "Installierte Farbschemata"
|
||||
@@ -2250,6 +2369,7 @@ _time:
|
||||
minute: "Minute(n)"
|
||||
hour: "Stunde(n)"
|
||||
day: "Tag(en)"
|
||||
month: "Monat(e)"
|
||||
_2fa:
|
||||
alreadyRegistered: "Du hast bereits ein Gerät für Zwei-Faktor-Authentifizierung registriert."
|
||||
registerTOTP: "Authentifizierungs-App registrieren"
|
||||
@@ -2379,6 +2499,7 @@ _auth:
|
||||
scopeUser: "Als folgender Benutzer agieren"
|
||||
pleaseLogin: "Bitte logge dich ein, um Apps zu authorisieren."
|
||||
byClickingYouWillBeRedirectedToThisUrl: "Wenn der Zugang gewährt wird, wirst du automatisch zu folgender URL weitergeleitet"
|
||||
alreadyAuthorized: "Dieser Anwendung wurde bereits Zugriff gewährt."
|
||||
_antennaSources:
|
||||
all: "Alle Notizen"
|
||||
homeTimeline: "Notizen von Benutzern, denen gefolgt wird"
|
||||
@@ -2424,7 +2545,45 @@ _widgets:
|
||||
chooseList: "Liste auswählen"
|
||||
clicker: "Klickzähler"
|
||||
birthdayFollowings: "Nutzer, die heute Geburtstag haben"
|
||||
chat: "Chat"
|
||||
chat: "Mit dem Benutzer chatten"
|
||||
_widgetOptions:
|
||||
showHeader: "Kopfzeile anzeigen"
|
||||
transparent: "Hintergrund transparent machen"
|
||||
height: "Höhe"
|
||||
_button:
|
||||
colored: "Farbig"
|
||||
_clock:
|
||||
size: "Größe"
|
||||
thickness: "Dicke"
|
||||
thicknessThin: "Dünn"
|
||||
thicknessMedium: "Normal"
|
||||
thicknessThick: "Dick"
|
||||
graduations: "Zifferblattskala"
|
||||
graduationDots: "Punkt"
|
||||
graduationArabic: "Zahlen"
|
||||
fadeGraduations: "Skala ausblenden"
|
||||
sAnimation: "Zweite Animation"
|
||||
sAnimationElastic: "Elastisch"
|
||||
sAnimationEaseOut: "Weich"
|
||||
twentyFour: "24-Stunden-Format"
|
||||
labelTime: "Uhrzeit"
|
||||
labelTz: "Zeitzone"
|
||||
labelTimeAndTz: "Zeit und Zeitzone"
|
||||
timezone: "Zeitzone"
|
||||
showMs: "Millisekunden anzeigen"
|
||||
showLabel: "Beschriftung anzeigen"
|
||||
_jobQueue:
|
||||
sound: "Ton abspielen"
|
||||
_rss:
|
||||
url: "RSS-Feed-URL"
|
||||
refreshIntervalSec: "Aktualisierungsintervall (Sekunden)"
|
||||
maxEntries: "Maximale Anzahl der angezeigten Einträge"
|
||||
_rssTicker:
|
||||
shuffle: "Zufällige Anzeigereihenfolge"
|
||||
duration: "Banner-Scrollgeschwindigkeit (in Sekunden)"
|
||||
reverse: "In andere Richtung scrollen"
|
||||
_birthdayFollowings:
|
||||
period: "Dauer"
|
||||
_cw:
|
||||
hide: "Inhalt verbergen"
|
||||
show: "Inhalt anzeigen"
|
||||
@@ -2464,9 +2623,25 @@ _visibility:
|
||||
disableFederation: "Deföderieren"
|
||||
disableFederationDescription: "Nicht an andere Instanzen übertragen"
|
||||
_postForm:
|
||||
quitInspiteOfThereAreUnuploadedFilesConfirm: "Es gibt Dateien, die nicht hochgeladen wurden. Möchtest du diese verwerfen und das Formular schließen?"
|
||||
uploaderTip: "Die Datei wurde noch nicht hochgeladen. Über das Dateimenü kannst du sie umbenennen, das Bild zuschneiden, ein Wasserzeichen hinzufügen, komprimieren usw. Die Datei wird automatisch hochgeladen, wenn du eine Notiz veröffentlichst."
|
||||
replyPlaceholder: "Dieser Notiz antworten …"
|
||||
quotePlaceholder: "Diese Notiz zitieren …"
|
||||
channelPlaceholder: "In einen Kanal senden"
|
||||
showHowToUse: "Formularbeschreibung anzeigen"
|
||||
_howToUse:
|
||||
content_title: "Dieser Text"
|
||||
content_description: "Bitte geben Sie den Inhalt ein, den Sie veröffentlichen möchten."
|
||||
toolbar_title: "Symbolleiste"
|
||||
toolbar_description: "Sie können Dateien oder Umfragen anhängen, Anmerkungen und Hashtags festlegen sowie Emojis und Erwähnungen einfügen."
|
||||
account_title: "Profilmenü"
|
||||
account_description: "Du kannst das Konto wechseln, von dem du postest, und dir eine Liste der im Konto gespeicherten Entwürfe und geplanten Beiträge anzeigen lassen."
|
||||
visibility_title: "Sichtbarkeit"
|
||||
visibility_description: "Sie können den Umfang festlegen, in dem die Notizen veröffentlicht werden."
|
||||
menu_title: "Menü"
|
||||
menu_description: "Sie können außerdem weitere Aktionen durchführen, z. B. als Entwurf speichern, das Posten planen oder Reaktionen einstellen."
|
||||
submit_title: "Senden-Button"
|
||||
submit_description: "Du kannst die Notiz posten. Du kannst sie auch mit Strg + Enter / Cmd + Enter posten."
|
||||
_placeholders:
|
||||
a: "Was machst du momentan?"
|
||||
b: "Was ist um dich herum los?"
|
||||
@@ -2612,6 +2787,8 @@ _notification:
|
||||
youReceivedFollowRequest: "Du hast eine Follow-Anfrage erhalten"
|
||||
yourFollowRequestAccepted: "Deine Follow-Anfrage wurde akzeptiert"
|
||||
pollEnded: "Umfrageergebnisse sind verfügbar"
|
||||
scheduledNotePosted: "Geplante Notiz wurde veröffentlicht"
|
||||
scheduledNotePostFailed: "Veröffentlichen der geplanten Notiz fehlgeschlagen"
|
||||
newNote: "Neue Notiz"
|
||||
unreadAntennaNote: "Antenne {name}"
|
||||
roleAssigned: "Rolle zugewiesen"
|
||||
@@ -2641,6 +2818,8 @@ _notification:
|
||||
quote: "Zitationen"
|
||||
reaction: "Reaktionen"
|
||||
pollEnded: "Ende von Umfragen"
|
||||
scheduledNotePosted: "Der geplante Beitrag wurde erfolgreich veröffentlicht."
|
||||
scheduledNotePostFailed: "Der geplante Beitrag ist fehlgeschlagen."
|
||||
receiveFollowRequest: "Erhaltene Follow-Anfragen"
|
||||
followRequestAccepted: "Akzeptierte Follow-Anfragen"
|
||||
roleAssigned: "Rolle zugewiesen"
|
||||
@@ -2680,6 +2859,14 @@ _deck:
|
||||
usedAsMinWidthWhenFlexible: "Ist \"Automatische Breitenanpassung\" aktiviert, wird hierfür die minimale Breite verwendet"
|
||||
flexible: "Automatische Breitenanpassung"
|
||||
enableSyncBetweenDevicesForProfiles: "Aktivieren der Synchronisierung von Profilinformationen zwischen Geräten"
|
||||
showHowToUse: "Siehe dir die UI-Beschreibung an."
|
||||
_howToUse:
|
||||
addColumn_title: "Spalte hinzufügen"
|
||||
addColumn_description: "Sie können den Spaltentyp auswählen und hinzufügen."
|
||||
settings_title: "UI-Einstellungen"
|
||||
settings_description: "Sie können die detaillierten Einstellungen der Deck-UI vornehmen."
|
||||
switchProfile_title: "Profil wechseln"
|
||||
switchProfile_description: "Das UI-Layout kann als Profil gespeichert werden, sodass du jederzeit zwischen den Profilen wechseln kannst."
|
||||
_columns:
|
||||
main: "Hauptspalte"
|
||||
widgets: "Widgets"
|
||||
@@ -2691,7 +2878,7 @@ _deck:
|
||||
mentions: "Erwähnungen"
|
||||
direct: "Direktnachrichten"
|
||||
roleTimeline: "Rollenchronik"
|
||||
chat: "Chat"
|
||||
chat: "Mit dem Benutzer chatten"
|
||||
_dialog:
|
||||
charactersExceeded: "Maximallänge überschritten! Momentan {current} von {max}"
|
||||
charactersBelow: "Minimallänge unterschritten! Momentan {current} von {min}"
|
||||
@@ -2740,6 +2927,8 @@ _abuseReport:
|
||||
notifiedWebhook: "Zu verwendender Webhook"
|
||||
deleteConfirm: "Bist du sicher, dass du den Empfänger der Benachrichtigung entfernen möchtest?"
|
||||
_moderationLogTypes:
|
||||
clearQueue: "Warteschlange leeren"
|
||||
promoteQueue: "Warteschlange erneut ausführen"
|
||||
createRole: "Rolle erstellt"
|
||||
deleteRole: "Rolle gelöscht"
|
||||
updateRole: "Rolle aktualisiert"
|
||||
@@ -2797,6 +2986,7 @@ _fileViewer:
|
||||
url: "URL"
|
||||
uploadedAt: "Hochgeladen am"
|
||||
attachedNotes: "Zugehörige Notizen"
|
||||
usage: "Nutzung"
|
||||
thisPageCanBeSeenFromTheAuthor: "Nur der Benutzer, der diese Datei hochgeladen hat, kann diese Seite sehen."
|
||||
_externalResourceInstaller:
|
||||
title: "Von externer Seite installieren"
|
||||
@@ -2844,8 +3034,12 @@ _dataSaver:
|
||||
_avatar:
|
||||
title: "Animierte Profilbilder deaktivieren"
|
||||
description: "Die Animation von Profilbildern wird angehalten. Da animierte Bilder eine größere Dateigröße haben können als normale Bilder, kann dies den Datenverkehr weiter reduzieren."
|
||||
_urlPreviewThumbnail:
|
||||
title: "URL-Vorschaubilder ausblenden"
|
||||
description: "URL-Vorschaubilder werden nicht mehr geladen."
|
||||
_disableUrlPreview:
|
||||
title: "URL-Vorschau deaktivieren"
|
||||
description: "Deaktiviert die URL-Vorschaufunktion. Anders als bei reinen Vorschaubildern wird dadurch das Laden der verlinkten Informationen selbst reduziert."
|
||||
_code:
|
||||
title: "Code-Hervorhebungen ausblenden"
|
||||
description: "Wenn Code-Hervorhebungen in MFM usw. verwendet werden, werden sie erst geladen, wenn sie angetippt werden. Die Syntaxhervorhebung erfordert das Herunterladen der Definitionsdateien für jede Programmiersprache. Es ist daher zu erwarten, dass die Deaktivierung des automatischen Ladens dieser Dateien die Menge des Datenverkehrs reduziert."
|
||||
@@ -2903,6 +3097,8 @@ _offlineScreen:
|
||||
_urlPreviewSetting:
|
||||
title: "Einstellungen der URL-Vorschau"
|
||||
enable: "URL-Vorschau aktivieren"
|
||||
allowRedirect: "Umleitung von URL-Vorschauen erlauben"
|
||||
allowRedirectDescription: "Wenn für eine URL eine Umleitung festgelegt ist, kann diese Funktion aktiviert werden, um der Umleitung zu folgen und eine Vorschau des umgeleiteten Inhalts anzuzeigen. Die Deaktivierung spart Serverressourcen, aber der Inhalt des Weiterleitungsziels wird nicht angezeigt."
|
||||
timeout: "Zeitüberschreitung beim Abrufen der Vorschau (ms)"
|
||||
timeoutDescription: "Übersteigt die für die Vorschau benötigte Zeit diesen Wert, wird keine Vorschau generiert."
|
||||
maximumContentLength: "Maximale Content-Length (Bytes)"
|
||||
@@ -3043,6 +3239,7 @@ _bootErrors:
|
||||
otherOption1: "Client-Einstellungen und Cache löschen"
|
||||
otherOption2: "Einfachen Client starten"
|
||||
otherOption3: "Starte das Reparaturwerkzeug"
|
||||
otherOption4: "Misskey im abgesicherten Modus starten"
|
||||
_search:
|
||||
searchScopeAll: "Alle"
|
||||
searchScopeLocal: "Lokal"
|
||||
@@ -3064,8 +3261,11 @@ _serverSetupWizard:
|
||||
single_description: "Verwende den Server alleine als deinen eigenen."
|
||||
single_youCanCreateMultipleAccounts: "Bei Bedarf können mehrere Konten eingerichtet werden, auch wenn es sich um einen Ein-Personen-Server handelt."
|
||||
group: "Gruppenserver"
|
||||
group_description: "Lade andere vertrauenswürdige Benutzer ein und verwende es mit mehreren Personen."
|
||||
open: "Offener Server"
|
||||
open_description: "Registrierung für alle öffnen."
|
||||
openServerAdvice: "Die Aufnahme einer unbestimmten Anzahl von Nutzern birgt Risiken. Es wird empfohlen, mit einem zuverlässigen Moderationssystem zu arbeiten, um eventuell auftretende Probleme behandeln zu können."
|
||||
openServerAntiSpamAdvice: "Große Sorgfalt muss auch auf die Sicherheit gelegt werden, z. B. durch die Aktivierung von Anti-Bot-Funktionen wie reCAPTCHA, um sicherzustellen, dass der Server nicht zum Verbreiten von Spam genutzt wird."
|
||||
howManyUsersDoYouExpect: "Mit wie vielen Benutzern rechnest du?"
|
||||
_scale:
|
||||
small: "Weniger als 100 (kleiner Maßstab)"
|
||||
@@ -3076,6 +3276,10 @@ _serverSetupWizard:
|
||||
doYouConnectToFediverse_description1: "Bei Anschluss an ein Netz von verteilten Servern (Fediverse) können Inhalte mit anderen Servern ausgetauscht werden."
|
||||
doYouConnectToFediverse_description2: "Die Verbindung mit dem Fediverse wird auch als „Föderation“ bezeichnet."
|
||||
youCanConfigureMoreFederationSettingsLater: "Erweiterte Einstellungen, wie z. B. die Angabe von föderierbaren Servern, können später vorgenommen werden."
|
||||
remoteContentsCleaning: "Automatische Bereinigung von Remote-Inhalten"
|
||||
remoteContentsCleaning_description: "Wenn Sie eine Föderation durchführen, empfangen Sie fortlaufend viele Inhalte. Wenn Sie die automatische Bereinigung aktivieren, werden Remote-Inhalte, deren bestimmter Zeitraum abgelaufen ist, automatisch vom Server gelöscht, wodurch Speicherplatz eingespart werden kann."
|
||||
adminInfo: "Administrator-Informationen"
|
||||
adminInfo_description: "Legt die Administrator-Informationen fest, die für den Empfang von Anfragen verwendet werden."
|
||||
adminInfo_mustBeFilled: "Dies ist auf einem offenen Server oder bei aktivierter Föderation erforderlich."
|
||||
followingSettingsAreRecommended: "Die folgenden Einstellungen werden empfohlen"
|
||||
applyTheseSettings: "Diese Einstellungen anwenden"
|
||||
@@ -3089,6 +3293,7 @@ _serverSetupWizard:
|
||||
text2: "Wir würden uns über deine Unterstützung freuen, damit wir dieses Projekt auch in Zukunft weiterentwickeln können."
|
||||
text3: "Für Unterstützer gibt es auch besondere Vorteile!"
|
||||
_uploader:
|
||||
editImage: "Bild bearbeiten"
|
||||
compressedToX: "Komprimiert zu {x}"
|
||||
savedXPercent: "{x}% gespart"
|
||||
abortConfirm: "Einige Dateien wurden nicht hochgeladen. Möchtest du den Vorgang abbrechen?"
|
||||
@@ -3097,6 +3302,7 @@ _uploader:
|
||||
allowedTypes: "Hochladbare Dateitypen"
|
||||
tip: "Die Datei ist noch nicht hochgeladen worden. In diesem Dialog kannst du die Datei vor dem Hochladen anzeigen, umbenennen, komprimieren und zuschneiden. Wenn du fertig bist, klicke auf „Hochladen“, um den Upload zu starten."
|
||||
_clientPerformanceIssueTip:
|
||||
title: "Wenn du das Gefühl hast, dass der Akku sich schnell entlädt."
|
||||
makeSureDisabledAdBlocker: "Deaktiviere deinen Adblocker"
|
||||
makeSureDisabledAdBlocker_description: "Adblocker können die Leistung beeinträchtigen; vergewissere dich, ob in deinem Betriebssystem, Browser oder deinen Add-ons Adblocker aktiviert sind."
|
||||
makeSureDisabledCustomCss: "Benutzerdefiniertes CSS deaktivieren"
|
||||
@@ -3110,26 +3316,124 @@ _userLists:
|
||||
watermark: "Wasserzeichen"
|
||||
defaultPreset: "Standard-Voreinstellungen"
|
||||
_watermarkEditor:
|
||||
tip: "Dem Bild kann ein Wasserzeichen, z. B. eine Quellenangabe, hinzugefügt werden."
|
||||
quitWithoutSaveConfirm: "Nicht gespeicherte Änderungen verwerfen?"
|
||||
driveFileTypeWarn: "Diese Datei wird nicht unterstützt"
|
||||
driveFileTypeWarnDescription: "Bilddatei auswählen"
|
||||
title: "Wasserzeichen bearbeiten"
|
||||
cover: "Alles bedecken"
|
||||
repeat: "Wiederholen"
|
||||
preserveBoundingRect: "So einstellen, dass beim Drehen nichts herausragt"
|
||||
opacity: "Transparenz"
|
||||
scale: "Größe"
|
||||
text: "Text"
|
||||
qr: "QR-Code"
|
||||
position: "Position"
|
||||
margin: "Abstand"
|
||||
type: "Art"
|
||||
image: "Bilder"
|
||||
advanced: "Fortgeschritten"
|
||||
angle: "Winkel"
|
||||
stripe: "Streifen"
|
||||
stripeWidth: "Linienbreite"
|
||||
stripeFrequency: "Linienanzahl"
|
||||
polkadot: "Punktmuster"
|
||||
checker: "Prüfer"
|
||||
polkadotMainDotOpacity: "Deckkraft des Hauptpunktes"
|
||||
polkadotMainDotRadius: "Größe des Hauptpunktes"
|
||||
polkadotSubDotOpacity: "Deckkraft des Unterpunktes"
|
||||
polkadotSubDotRadius: "Größe des Unterpunktes"
|
||||
polkadotSubDotDivisions: "Anzahl der Unterpunkte"
|
||||
leaveBlankToAccountUrl: "Wenn Sie es leer lassen, wird das Profilbild des Kontos verwendet."
|
||||
failedToLoadImage: "Bild konnte nicht geladen werden"
|
||||
_imageEffector:
|
||||
title: "Effekte"
|
||||
addEffect: "Effekte hinzufügen"
|
||||
discardChangesConfirm: "Änderungen verwerfen und beenden?"
|
||||
failedToLoadImage: "Bild konnte nicht geladen werden"
|
||||
_fxs:
|
||||
chromaticAberration: "Chromatische Abweichung"
|
||||
glitch: "Glitch"
|
||||
mirror: "Spiegeln"
|
||||
invert: "Farben umkehren"
|
||||
grayscale: "Schwarzweiß"
|
||||
blur: "Verwischen"
|
||||
pixelate: "Verpixeln"
|
||||
colorAdjust: "Farbkorrektur"
|
||||
colorClamp: "Farbkomprimierung"
|
||||
colorClampAdvanced: "Farbkomprimierung (erweitert)"
|
||||
distort: "Verzerrung"
|
||||
threshold: "inarisierun"
|
||||
zoomLines: "Konzentrationslinien"
|
||||
stripe: "Streifen"
|
||||
polkadot: "Punktmuster"
|
||||
checker: "Prüfer"
|
||||
blockNoise: "Blockrauschen"
|
||||
tearing: "Tearing"
|
||||
fill: "Ausfüllen"
|
||||
_fxProps:
|
||||
angle: "Winkel"
|
||||
scale: "Größe"
|
||||
size: "Größe"
|
||||
radius: "Radius"
|
||||
samples: "Stichprobengröße"
|
||||
offset: "Position"
|
||||
color: "Farbe"
|
||||
opacity: "Transparenz"
|
||||
normalize: "Normalisierung"
|
||||
amount: "Menge"
|
||||
lightness: "Erhellen"
|
||||
contrast: "Kontrast"
|
||||
hue: "Farbton"
|
||||
brightness: "Helligkeit"
|
||||
saturation: "Sättigung"
|
||||
max: "Maximum"
|
||||
min: "Minimum"
|
||||
direction: "Richtung"
|
||||
phase: "Sättigung"
|
||||
frequency: "Häufigkeit"
|
||||
strength: "Stärke"
|
||||
glitchChannelShift: "Verschiebung"
|
||||
seed: "Seed-Wert"
|
||||
redComponent: "Rot-Anteil"
|
||||
greenComponent: "Grün-Anteil"
|
||||
blueComponent: "Blau-Anteil"
|
||||
threshold: "Schwellenwert"
|
||||
centerX: "Zentrum X"
|
||||
centerY: "Zentrum Y"
|
||||
zoomLinesMaskSize: "Mitteldurchmesser"
|
||||
circle: "Kreisförmig"
|
||||
drafts: "Entwurf"
|
||||
_drafts:
|
||||
select: "Entwurf auswählen"
|
||||
cannotCreateDraftAnymore: "Die Anzahl der Entwürfe, die erstellt werden können, wurde überschritten."
|
||||
cannotCreateDraft: "Mit diesem Inhalt kann kein Entwurf erstellt werden."
|
||||
delete: "Entwurf löschen"
|
||||
deleteAreYouSure: "Entwurf löschen?"
|
||||
noDrafts: "Keine Entwürfe"
|
||||
replyTo: "Antwort an {user}"
|
||||
quoteOf: "Zitat von {user}s Notiz"
|
||||
postTo: "Beitrag im {channel}"
|
||||
saveToDraft: "Als Entwurf speichern"
|
||||
restoreFromDraft: "Aus Entwurf wiederherstellen"
|
||||
restore: "Wiederherstellen"
|
||||
listDrafts: "Liste der Entwürfe"
|
||||
schedule: "Beitragsplanung"
|
||||
listScheduledNotes: "Liste der geplanten Beiträge"
|
||||
cancelSchedule: "Reservierung stornieren"
|
||||
qr: "QR-Code"
|
||||
_qr:
|
||||
showTabTitle: "Anzeigeart"
|
||||
readTabTitle: "Auslesen"
|
||||
shareTitle: "{name} {acct}"
|
||||
shareText: "Bitte folge mir im Fediverse!"
|
||||
chooseCamera: "Kamera auswählen"
|
||||
cannotToggleFlash: "Blitzauswahl nicht möglich"
|
||||
turnOnFlash: "Blitz einschalten"
|
||||
turnOffFlash: "Blitz ausschalten"
|
||||
startQr: "QR-Code-Leser starten"
|
||||
stopQr: "QR-Code-Leser stoppen"
|
||||
noQrCodeFound: "QR-Code wurde nicht gefunden"
|
||||
scanFile: "Gerätebilder scannen"
|
||||
raw: "Text"
|
||||
mfm: "MFM"
|
||||
|
||||
@@ -288,6 +288,10 @@ replies: "Απάντηση"
|
||||
renotes: "Κοινοποίηση σημειώματος"
|
||||
postForm: "Φόρμα δημοσίευσης"
|
||||
information: "Πληροφορίες"
|
||||
widgets: "Μαραφέτια"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
filename: "Όνομα αρχείου"
|
||||
_chat:
|
||||
members: "Μέλη"
|
||||
home: "Κεντρικό"
|
||||
@@ -353,6 +357,7 @@ _visibility:
|
||||
home: "Κεντρικό"
|
||||
homeDescription: "Δημοσίευση στο κεντρικό χρονολόγιο μόνο"
|
||||
followers: "Ακολουθούν"
|
||||
specified: "Απευθείας σημειώματα"
|
||||
_profile:
|
||||
name: "Όνομα"
|
||||
username: "Όνομα μέλους"
|
||||
@@ -395,6 +400,7 @@ _deck:
|
||||
antenna: "Αντένες"
|
||||
list: "Λίστα"
|
||||
mentions: "Επισημάνσεις"
|
||||
direct: "Απευθείας σημειώματα"
|
||||
_webhookSettings:
|
||||
name: "Όνομα"
|
||||
_moderationLogTypes:
|
||||
|
||||
@@ -81,8 +81,10 @@ import: "Import"
|
||||
export: "Export"
|
||||
files: "Files"
|
||||
download: "Download"
|
||||
driveFileDeleteConfirm: "Do you want to remove the file \"{name}\"? Some content using this file will also be removed."
|
||||
driveFileDeleteConfirm: "Are you sure you want to delete \"{name}\"? All notes with this file attached will also be deleted."
|
||||
unfollowConfirm: "Are you sure you want to unfollow {name}?"
|
||||
cancelFollowRequestConfirm: "Are you sure that you want to cancel your follow request to {name}?"
|
||||
rejectFollowRequestConfirm: "Are you sure that you want to reject the follow request from {name}?"
|
||||
exportRequested: "You've requested an export. This may take a while. It will be added to your Drive once completed."
|
||||
importRequested: "You've requested an import. This may take a while."
|
||||
lists: "Lists"
|
||||
@@ -253,6 +255,7 @@ noteDeleteConfirm: "Are you sure you want to delete this note?"
|
||||
pinLimitExceeded: "You cannot pin any more notes"
|
||||
done: "Done"
|
||||
processing: "Processing..."
|
||||
preprocessing: "Preparing..."
|
||||
preview: "Preview"
|
||||
default: "Default"
|
||||
defaultValueIs: "Default: {value}"
|
||||
@@ -301,6 +304,7 @@ uploadFromUrlMayTakeTime: "It may take some time until the upload is complete."
|
||||
uploadNFiles: "Upload {n} files"
|
||||
explore: "Explore"
|
||||
messageRead: "Read"
|
||||
readAllChatMessages: "Mark all messages as read"
|
||||
noMoreHistory: "There is no further history"
|
||||
startChat: "Start chat"
|
||||
nUsersRead: "read by {n}"
|
||||
@@ -327,12 +331,13 @@ dark: "Dark"
|
||||
lightThemes: "Light themes"
|
||||
darkThemes: "Dark themes"
|
||||
syncDeviceDarkMode: "Sync Dark Mode with your device settings"
|
||||
switchDarkModeManuallyWhenSyncEnabledConfirm: "\"{x}\" is turned on, Would you like to turn off synchronization and switch modes manually?"
|
||||
switchDarkModeManuallyWhenSyncEnabledConfirm: "\"{x}\" is turned on. Would you like to turn off synchronization and switch modes manually?"
|
||||
drive: "Drive"
|
||||
fileName: "Filename"
|
||||
selectFile: "Select a file"
|
||||
selectFiles: "Select files"
|
||||
selectFolder: "Select a folder"
|
||||
unselectFolder: "Deselect folder"
|
||||
selectFolders: "Select folders"
|
||||
fileNotSelected: "No file selected"
|
||||
renameFile: "Rename file"
|
||||
@@ -345,6 +350,7 @@ addFile: "Add a file"
|
||||
showFile: "Show files"
|
||||
emptyDrive: "Your Drive is empty"
|
||||
emptyFolder: "This folder is empty"
|
||||
dropHereToUpload: "Drop files here to upload"
|
||||
unableToDelete: "Unable to delete"
|
||||
inputNewFileName: "Enter a new filename"
|
||||
inputNewDescription: "Enter new alt text"
|
||||
@@ -537,6 +543,7 @@ regenerate: "Regenerate"
|
||||
fontSize: "Font size"
|
||||
mediaListWithOneImageAppearance: "Height of media lists with one image only"
|
||||
limitTo: "Limit to {x}"
|
||||
showMediaListByGridInWideArea: "Display the media list in a grid when the screen width is wide"
|
||||
noFollowRequests: "You don't have any pending follow requests"
|
||||
openImageInNewTab: "Open images in new tab"
|
||||
dashboard: "Dashboard"
|
||||
@@ -772,6 +779,7 @@ lockedAccountInfo: "Unless you set your note visiblity to \"Followers only\", yo
|
||||
alwaysMarkSensitive: "Mark as sensitive by default"
|
||||
loadRawImages: "Load original images instead of showing thumbnails"
|
||||
disableShowingAnimatedImages: "Don't play animated images"
|
||||
disableShowingAnimatedImages_caption: "If animated images do not play even if this setting is disabled, it may be due to browser or OS accessibility settings, power-saving settings, or similar factors."
|
||||
highlightSensitiveMedia: "Highlight sensitive media"
|
||||
verificationEmailSent: "A verification email has been sent. Please follow the included link to complete verification."
|
||||
notSet: "Not set"
|
||||
@@ -1018,6 +1026,9 @@ pushNotificationAlreadySubscribed: "Push notifications are already enabled"
|
||||
pushNotificationNotSupported: "Your browser or instance does not support push notifications"
|
||||
sendPushNotificationReadMessage: "Delete push notifications once they have been read"
|
||||
sendPushNotificationReadMessageCaption: "This may increase the power consumption of your device."
|
||||
pleaseAllowPushNotification: "Please enable push notifications in your browser"
|
||||
browserPushNotificationDisabled: "Failed to acquire permission to send notifications"
|
||||
browserPushNotificationDisabledDescription: "You do not have permission to send notifications from {serverName}. Please allow notifications in your browser settings and try again."
|
||||
windowMaximize: "Maximize"
|
||||
windowMinimize: "Minimize"
|
||||
windowRestore: "Restore"
|
||||
@@ -1054,6 +1065,7 @@ permissionDeniedError: "Operation denied"
|
||||
permissionDeniedErrorDescription: "This account does not have the permission to perform this action."
|
||||
preset: "Preset"
|
||||
selectFromPresets: "Choose from presets"
|
||||
custom: "Custom"
|
||||
achievements: "Achievements"
|
||||
gotInvalidResponseError: "Invalid server response"
|
||||
gotInvalidResponseErrorDescription: "The server may be unreachable or undergoing maintenance. Please try again later."
|
||||
@@ -1092,6 +1104,7 @@ prohibitedWordsDescription2: "Using spaces will create AND expressions and surro
|
||||
hiddenTags: "Hidden hashtags"
|
||||
hiddenTagsDescription: "Select tags which will not shown on trend list.\nMultiple tags could be registered by lines."
|
||||
notesSearchNotAvailable: "Note search is unavailable."
|
||||
usersSearchNotAvailable: "User search is not available."
|
||||
license: "License"
|
||||
unfavoriteConfirm: "Really remove from favorites?"
|
||||
myClips: "My clips"
|
||||
@@ -1166,6 +1179,7 @@ installed: "Installed"
|
||||
branding: "Branding"
|
||||
enableServerMachineStats: "Publish server hardware stats"
|
||||
enableIdenticonGeneration: "Enable user identicon generation"
|
||||
showRoleBadgesOfRemoteUsers: "Display the role badges assigned to remote users"
|
||||
turnOffToImprovePerformance: "Turning this off can increase performance."
|
||||
createInviteCode: "Generate invite"
|
||||
createWithOptions: "Generate with options"
|
||||
@@ -1216,8 +1230,8 @@ showRepliesToOthersInTimeline: "Show replies to others in timeline"
|
||||
hideRepliesToOthersInTimeline: "Hide replies to others from timeline"
|
||||
showRepliesToOthersInTimelineAll: "Show replies to others from everyone you follow in timeline"
|
||||
hideRepliesToOthersInTimelineAll: "Hide replies to others from everyone you follow in timeline"
|
||||
confirmShowRepliesAll: "This operation is irreversible. Would you really like to show replies to others from everyone you follow in your timeline?"
|
||||
confirmHideRepliesAll: "This operation is irreversible. Would you really like to hide replies to others from everyone you follow in your timeline?"
|
||||
confirmShowRepliesAll: "Are you sure you want to show replies from everyone you follow in your timeline? This action is irreversible."
|
||||
confirmHideRepliesAll: "Are you sure you want to hide replies from everyone you follow in your timeline? This action is irreversible."
|
||||
externalServices: "External Services"
|
||||
sourceCode: "Source code"
|
||||
sourceCodeIsNotYetProvided: "Source code is not yet available. Contact the administrator to fix this problem."
|
||||
@@ -1243,7 +1257,7 @@ releaseToRefresh: "Release to refresh"
|
||||
refreshing: "Refreshing..."
|
||||
pullDownToRefresh: "Pull down to refresh"
|
||||
useGroupedNotifications: "Display grouped notifications"
|
||||
signupPendingError: "There was a problem verifying the email address. The link may have expired."
|
||||
emailVerificationFailedError: "A problem occurred while verifying your email address. The link may have expired."
|
||||
cwNotationRequired: "If \"Hide content\" is enabled, a description must be provided."
|
||||
doReaction: "Add reaction"
|
||||
code: "Code"
|
||||
@@ -1302,7 +1316,7 @@ passkeyVerificationSucceededButPasswordlessLoginDisabled: "Passkey verification
|
||||
messageToFollower: "Message to followers"
|
||||
target: "Target"
|
||||
testCaptchaWarning: "This function is intended for CAPTCHA testing purposes.\n<strong>Do not use in a production environment.</strong>"
|
||||
prohibitedWordsForNameOfUser: "Prohibited words for user names"
|
||||
prohibitedWordsForNameOfUser: "Prohibited words for usernames"
|
||||
prohibitedWordsForNameOfUserDescription: "If any of the strings in this list are included in the user's name, the name will be denied. Users with moderator privileges are not affected by this restriction."
|
||||
yourNameContainsProhibitedWords: "Your name contains prohibited words"
|
||||
yourNameContainsProhibitedWordsDescription: "If you wish to use this name, please contact your server administrator."
|
||||
@@ -1313,6 +1327,8 @@ availableRoles: "Available roles"
|
||||
acknowledgeNotesAndEnable: "Turn on after understanding the precautions."
|
||||
federationSpecified: "This server is operated in a whitelist federation. Interacting with servers other than those designated by the administrator is not allowed."
|
||||
federationDisabled: "Federation is disabled on this server. You cannot interact with users on other servers."
|
||||
draft: "Drafts"
|
||||
draftsAndScheduledNotes: "Drafts and scheduled notes"
|
||||
confirmOnReact: "Confirm when reacting"
|
||||
reactAreYouSure: "Would you like to add a \"{emoji}\" reaction?"
|
||||
markAsSensitiveConfirm: "Do you want to set this media as sensitive?"
|
||||
@@ -1340,6 +1356,8 @@ postForm: "Posting form"
|
||||
textCount: "Character count"
|
||||
information: "About"
|
||||
chat: "Chat"
|
||||
directMessage: "Chat with user"
|
||||
directMessage_short: "Message"
|
||||
migrateOldSettings: "Migrate old client settings"
|
||||
migrateOldSettings_description: "This should be done automatically but if for some reason the migration was not successful, you can trigger the migration process yourself manually. The current configuration information will be overwritten."
|
||||
compress: "Compress"
|
||||
@@ -1366,8 +1384,85 @@ tip: "Tips & Tricks"
|
||||
redisplayAllTips: "Show all “Tips & Tricks” again"
|
||||
hideAllTips: "Hide all \"Tips & Tricks\""
|
||||
defaultImageCompressionLevel: "Default image compression level"
|
||||
defaultImageCompressionLevel_description: "High, reduces the file size but also the image quality. <br>High, reduces the file size but also the image quality."
|
||||
defaultImageCompressionLevel_description: "Lower level preserves image quality but increases file size.<br>Higher level reduce file size, but reduce image quality."
|
||||
defaultCompressionLevel: "Default compression level"
|
||||
defaultCompressionLevel_description: "Lower compression preserves quality but increases file size.<br>Higher compression reduces file size but lowers quality."
|
||||
inMinutes: "Minute(s)"
|
||||
inDays: "Day(s)"
|
||||
safeModeEnabled: "Safe mode is enabled"
|
||||
pluginsAreDisabledBecauseSafeMode: "All plugins are disabled because safe mode is enabled."
|
||||
customCssIsDisabledBecauseSafeMode: "Custom CSS is not applied because safe mode is enabled."
|
||||
themeIsDefaultBecauseSafeMode: "While safe mode is active, the default theme is used. Disabling safe mode will revert these changes."
|
||||
thankYouForTestingBeta: "Thank you for helping us test the beta version!"
|
||||
createUserSpecifiedNote: "Create a direct note"
|
||||
schedulePost: "Schedule note"
|
||||
scheduleToPostOnX: "Scheduled to note on {x}"
|
||||
scheduledToPostOnX: "Note is scheduled for {x}"
|
||||
schedule: "Schedule"
|
||||
scheduled: "Scheduled"
|
||||
widgets: "Widgets"
|
||||
deviceInfo: "Device information"
|
||||
deviceInfoDescription: "When making technical inquiries, including the following information may help resolve the issue."
|
||||
youAreAdmin: "You are admin"
|
||||
frame: "Frame"
|
||||
presets: "Preset"
|
||||
zeroPadding: "Zero padding"
|
||||
nothingToConfigure: "No configurable options available"
|
||||
viewRenotedChannel: "Show renoted channel"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
caption: "File caption"
|
||||
filename: "Filename"
|
||||
filename_without_ext: "Filename without extension"
|
||||
year: "Year of photography"
|
||||
month: "Month of photogrphy"
|
||||
day: "Date of photography"
|
||||
hour: "Time the photo was taken (hour)"
|
||||
minute: "Time the photo was taken (minute)"
|
||||
second: "Time the photo was taken (second)"
|
||||
camera_model: "Camera Name"
|
||||
camera_lens_model: "Lens model"
|
||||
camera_mm: "Focal length"
|
||||
camera_mm_35: "Focal length (in 35 mm format)"
|
||||
camera_f: "Aperture (f-number)"
|
||||
camera_s: "Shutter speed"
|
||||
camera_iso: "ISO"
|
||||
gps_lat: "Latitude"
|
||||
gps_long: "Longitude"
|
||||
_imageFrameEditor:
|
||||
title: "Edit frame"
|
||||
tip: "You can decorate images by adding labels that include frames and metadata."
|
||||
header: "Header"
|
||||
footer: "Footer"
|
||||
borderThickness: "Frame width"
|
||||
labelThickness: "Label width"
|
||||
labelScale: "Label scale"
|
||||
centered: "Centered"
|
||||
captionMain: "Caption (Big)"
|
||||
captionSub: "Caption (Small)"
|
||||
availableVariables: "Supported variables"
|
||||
withQrCode: "QR Code"
|
||||
backgroundColor: "Background color"
|
||||
textColor: "Text color"
|
||||
font: "Font"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
quitWithoutSaveConfirm: "Discard unsaved changes?"
|
||||
failedToLoadImage: "Failed to load image"
|
||||
_compression:
|
||||
_quality:
|
||||
high: "High quality"
|
||||
medium: "Medium quality"
|
||||
low: "Low quality"
|
||||
_size:
|
||||
large: "Large size"
|
||||
medium: "Medium size"
|
||||
small: "Small size"
|
||||
_order:
|
||||
newest: "Newest First"
|
||||
oldest: "Oldest First"
|
||||
_chat:
|
||||
messages: "Messages"
|
||||
noMessagesYet: "No messages yet"
|
||||
newMessage: "New message"
|
||||
individualChat: "Private Chat"
|
||||
@@ -1396,7 +1491,7 @@ _chat:
|
||||
muteThisRoom: "Mute room"
|
||||
deleteRoom: "Delete room"
|
||||
chatNotAvailableForThisAccountOrServer: "Chat is not enabled on this server or for this account."
|
||||
chatIsReadOnlyForThisAccountOrServer: "Chat is read-only on this instance or this account. You cannot write new messages or create/join chat rooms."
|
||||
chatIsReadOnlyForThisAccountOrServer: "Chat is read-only on this server or this account. You cannot write new messages or create/join chat rooms."
|
||||
chatNotAvailableInOtherAccount: "The chat function is disabled for the other user."
|
||||
cannotChatWithTheUser: "Cannot start a chat with this user"
|
||||
cannotChatWithTheUser_description: "Chat is either unavailable or the other party has not enabled chat."
|
||||
@@ -1455,6 +1550,12 @@ _settings:
|
||||
contentsUpdateFrequency_description2: "When real-time mode is on, content is updated in real time regardless of this setting."
|
||||
showUrlPreview: "Show URL preview"
|
||||
showAvailableReactionsFirstInNote: "Show available reactions at the top."
|
||||
showPageTabBarBottom: "Show page tab bar at the bottom"
|
||||
emojiPaletteBanner: "You can register presets as palettes to display prominently in the emoji picker or customize the appearance of the picker."
|
||||
enableAnimatedImages: "Enable animated images"
|
||||
settingsPersistence_title: "Persistence of Settings"
|
||||
settingsPersistence_description1: "Enabling setting persistence prevents configuration information from being lost."
|
||||
settingsPersistence_description2: "It may not be possible to enable this depending on the environment."
|
||||
_chat:
|
||||
showSenderName: "Show sender's name"
|
||||
sendOnEnter: "Press Enter to send"
|
||||
@@ -1463,6 +1564,8 @@ _preferencesProfile:
|
||||
profileNameDescription: "Set a name that identifies this device."
|
||||
profileNameDescription2: "Example: \"Main PC\", \"Smartphone\""
|
||||
manageProfiles: "Manage Profiles"
|
||||
shareSameProfileBetweenDevicesIsNotRecommended: "We do not recommend sharing the same profile across multiple devices."
|
||||
useSyncBetweenDevicesOptionIfYouWantToSyncSetting: "If there are settings you wish to synchronize across multiple devices, enable the “Synchronize across multiple devices” option individually for each device."
|
||||
_preferencesBackup:
|
||||
autoBackup: "Auto backup"
|
||||
restoreFromBackup: "Restore from backup"
|
||||
@@ -1472,6 +1575,7 @@ _preferencesBackup:
|
||||
youNeedToNameYourProfileToEnableAutoBackup: "A profile name must be set to enable auto backup."
|
||||
autoPreferencesBackupIsNotEnabledForThisDevice: "Settings auto backup is not enabled on this device."
|
||||
backupFound: "Settings backup is found"
|
||||
forceBackup: "Force a backup of settings"
|
||||
_accountSettings:
|
||||
requireSigninToViewContents: "Require sign-in to view contents"
|
||||
requireSigninToViewContentsDescription1: "Require login to view all notes and other content you have created. This will have the effect of preventing crawlers from collecting your information."
|
||||
@@ -1494,7 +1598,7 @@ _abuseUserReport:
|
||||
resolveTutorial: "If the report's content is legitimate, select \"Accept\" to mark it as resolved.\nIf the report's content is illegitimate, select \"Reject\" to ignore it."
|
||||
_delivery:
|
||||
status: "Delivery status"
|
||||
stop: "Suspended"
|
||||
stop: "Suspend"
|
||||
resume: "Delivery resume"
|
||||
_type:
|
||||
none: "Publishing"
|
||||
@@ -1628,6 +1732,10 @@ _serverSettings:
|
||||
fanoutTimelineDbFallback: "Fallback to database"
|
||||
fanoutTimelineDbFallbackDescription: "When enabled, the timeline will fall back to the database for additional queries if the timeline is not cached. Disabling it further reduces the server load by eliminating the fallback process, but limits the range of timelines that can be retrieved."
|
||||
reactionsBufferingDescription: "When enabled, performance during reaction creation will be greatly improved, reducing the load on the database. However, Redis memory usage will increase."
|
||||
remoteNotesCleaning: "Automatic cleanup of remote notes"
|
||||
remoteNotesCleaning_description: "When enabled, unused and outdated remote notes will be periodically cleaned up to prevent database bloat."
|
||||
remoteNotesCleaningMaxProcessingDuration: "Maximum cleanup processing time"
|
||||
remoteNotesCleaningExpiryDaysForEachNotes: "Minimum days to retain notes"
|
||||
inquiryUrl: "Inquiry URL"
|
||||
inquiryUrlDescription: "Specify a URL for the inquiry form to the server maintainer or a web page for the contact information."
|
||||
openRegistration: "Make the account creation open"
|
||||
@@ -1646,6 +1754,11 @@ _serverSettings:
|
||||
userGeneratedContentsVisibilityForVisitor: "Visibility of user-generated content to guests"
|
||||
userGeneratedContentsVisibilityForVisitor_description: "This is useful for preventing problems caused by inappropriate remote content that is not well moderated from being unintentionally published on the Internet via your own server."
|
||||
userGeneratedContentsVisibilityForVisitor_description2: "Unconditionally publishing all content on the server to the Internet, including remote content received by the server is risky. This is especially important for guests who are unaware of the distributed nature of the content, as they may mistakenly believe that even remote content is content created by users on the server."
|
||||
restartServerSetupWizardConfirm_title: "Restart server setup wizard?"
|
||||
restartServerSetupWizardConfirm_text: "Some current settings will be reset."
|
||||
entrancePageStyle: "Entrance page style"
|
||||
showTimelineForVisitor: "Show timeline"
|
||||
showActivitiesForVisitor: "Show activities"
|
||||
_userGeneratedContentsVisibilityForVisitor:
|
||||
all: "Everything is public"
|
||||
localOnly: "Only local content is published, remote content is kept private"
|
||||
@@ -1968,6 +2081,7 @@ _role:
|
||||
canManageAvatarDecorations: "Manage avatar decorations"
|
||||
driveCapacity: "Drive capacity"
|
||||
maxFileSize: "Upload-able max file size"
|
||||
maxFileSize_caption: "Reverse proxies, CDNs, and other front-end components may have their own configuration settings."
|
||||
alwaysMarkNsfw: "Always mark files as NSFW"
|
||||
canUpdateBioMedia: "Can edit an icon or a banner image"
|
||||
pinMax: "Maximum number of pinned notes"
|
||||
@@ -1982,17 +2096,21 @@ _role:
|
||||
descriptionOfRateLimitFactor: "Lower rate limits are less restrictive, higher ones more restrictive. "
|
||||
canHideAds: "Can hide ads"
|
||||
canSearchNotes: "Usage of note search"
|
||||
canSearchUsers: "User search"
|
||||
canUseTranslator: "Translator usage"
|
||||
avatarDecorationLimit: "Maximum number of avatar decorations that can be applied"
|
||||
canImportAntennas: "Allow importing antennas"
|
||||
canImportBlocking: "Allow importing blocking"
|
||||
canImportFollowing: "Allow importing following"
|
||||
canImportMuting: "Allow importing muting"
|
||||
canImportUserLists: "Allow importing lists"
|
||||
chatAvailability: "Allow Chat"
|
||||
avatarDecorationLimit: "Maximum number of avatar decorations"
|
||||
canImportAntennas: "Can import antennas"
|
||||
canImportBlocking: "Can import blocking"
|
||||
canImportFollowing: "Can import following"
|
||||
canImportMuting: "Can import muting"
|
||||
canImportUserLists: "Can import lists"
|
||||
chatAvailability: "Chat"
|
||||
uploadableFileTypes: "Uploadable file types"
|
||||
uploadableFileTypes_caption: "Specifies the allowed MIME/file types. Multiple MIME types can be specified by separating them with a new line, and wildcards can be specified with an asterisk (*). (e.g., image/*)"
|
||||
uploadableFileTypes_caption2: "Some files types might fail to be detected. To allow such files, add {x} to the specification."
|
||||
noteDraftLimit: "Number of possible drafts of server notes"
|
||||
scheduledNoteLimit: "Maximum number of simultaneous scheduled notes"
|
||||
watermarkAvailable: "Watermark function"
|
||||
_condition:
|
||||
roleAssignedTo: "Assigned to manual roles"
|
||||
isLocal: "Local user"
|
||||
@@ -2152,6 +2270,7 @@ _theme:
|
||||
install: "Install a theme"
|
||||
manage: "Manage themes"
|
||||
code: "Theme code"
|
||||
copyThemeCode: "Copy theme code"
|
||||
description: "Description"
|
||||
installed: "{name} has been installed"
|
||||
installedThemes: "Installed themes"
|
||||
@@ -2251,6 +2370,7 @@ _time:
|
||||
minute: "Minute(s)"
|
||||
hour: "Hour(s)"
|
||||
day: "Day(s)"
|
||||
month: "Month(s)"
|
||||
_2fa:
|
||||
alreadyRegistered: "You have already registered a 2-factor authentication device."
|
||||
registerTOTP: "Register authenticator app"
|
||||
@@ -2323,7 +2443,7 @@ _permissions:
|
||||
"read:admin:index-stats": "View database index stats"
|
||||
"read:admin:table-stats": "View database table stats"
|
||||
"read:admin:user-ips": "View user IP addresses"
|
||||
"read:admin:meta": "View instance metadata"
|
||||
"read:admin:meta": "View server metadata"
|
||||
"write:admin:reset-password": "Reset user password"
|
||||
"write:admin:resolve-abuse-user-report": "Resolve user report"
|
||||
"write:admin:send-email": "Send email"
|
||||
@@ -2334,7 +2454,7 @@ _permissions:
|
||||
"write:admin:unset-user-avatar": "Remove user avatar"
|
||||
"write:admin:unset-user-banner": "Remove user banner"
|
||||
"write:admin:unsuspend-user": "Unsuspend user"
|
||||
"write:admin:meta": "Manage instance metadata"
|
||||
"write:admin:meta": "Manage server metadata"
|
||||
"write:admin:user-note": "Manage moderation note"
|
||||
"write:admin:roles": "Manage roles"
|
||||
"read:admin:roles": "View roles"
|
||||
@@ -2380,6 +2500,7 @@ _auth:
|
||||
scopeUser: "Operate as the following user"
|
||||
pleaseLogin: "Please log in to authorize applications."
|
||||
byClickingYouWillBeRedirectedToThisUrl: "When access is granted, you will automatically be redirected to the following URL"
|
||||
alreadyAuthorized: "This application already has access permission."
|
||||
_antennaSources:
|
||||
all: "All notes"
|
||||
homeTimeline: "Notes from followed users"
|
||||
@@ -2425,7 +2546,45 @@ _widgets:
|
||||
chooseList: "Select a list"
|
||||
clicker: "Clicker"
|
||||
birthdayFollowings: "Today's Birthdays"
|
||||
chat: "Chat"
|
||||
chat: "Chat with user"
|
||||
_widgetOptions:
|
||||
showHeader: "Show header"
|
||||
transparent: "Make background transparent"
|
||||
height: "Height"
|
||||
_button:
|
||||
colored: "Colored"
|
||||
_clock:
|
||||
size: "Size"
|
||||
thickness: "Needle thickness"
|
||||
thicknessThin: "Thin"
|
||||
thicknessMedium: "Normal"
|
||||
thicknessThick: "Thick"
|
||||
graduations: "Dial markings"
|
||||
graduationDots: "Dot"
|
||||
graduationArabic: "Arabic numbers"
|
||||
fadeGraduations: "Fade the scale"
|
||||
sAnimation: "Second hand animation"
|
||||
sAnimationElastic: "Real"
|
||||
sAnimationEaseOut: "Smooth"
|
||||
twentyFour: "24 Hour Format"
|
||||
labelTime: "Time"
|
||||
labelTz: "Timezone"
|
||||
labelTimeAndTz: "Time and time zone"
|
||||
timezone: "Timezone"
|
||||
showMs: "Show Miliseconds"
|
||||
showLabel: "Show Label"
|
||||
_jobQueue:
|
||||
sound: "Play Sounds"
|
||||
_rss:
|
||||
url: "RSS Feed Url"
|
||||
refreshIntervalSec: "Update interval (in seconds)"
|
||||
maxEntries: "Maximum number of items to display"
|
||||
_rssTicker:
|
||||
shuffle: "Random display order"
|
||||
duration: "Banner scroll speed (in seconds)"
|
||||
reverse: "Scroll in the opposite direction"
|
||||
_birthdayFollowings:
|
||||
period: "Duration"
|
||||
_cw:
|
||||
hide: "Hide"
|
||||
show: "Show content"
|
||||
@@ -2470,6 +2629,20 @@ _postForm:
|
||||
replyPlaceholder: "Reply to this note..."
|
||||
quotePlaceholder: "Quote this note..."
|
||||
channelPlaceholder: "Post to a channel..."
|
||||
showHowToUse: "Show how to use this form"
|
||||
_howToUse:
|
||||
content_title: "Body"
|
||||
content_description: "Enter the content you wish to post here."
|
||||
toolbar_title: "Toolbars"
|
||||
toolbar_description: "You can attach files or poll, add annotations or hashtags, and insert emojis or mentions."
|
||||
account_title: "Account menu"
|
||||
account_description: "You can switch between accounts for posting, or view a list of drafts and scheduled posts saved to your account."
|
||||
visibility_title: "Visibility"
|
||||
visibility_description: "You can configure the visibility of your notes."
|
||||
menu_title: "Menu"
|
||||
menu_description: "You can save current content to drafts, schedule posts, set reactions, and perform other actions."
|
||||
submit_title: "Post button"
|
||||
submit_description: "Post your notes by pressing this button. You can also post using Ctrl + Enter / Cmd + Enter."
|
||||
_placeholders:
|
||||
a: "What are you up to?"
|
||||
b: "What's happening around you?"
|
||||
@@ -2615,6 +2788,8 @@ _notification:
|
||||
youReceivedFollowRequest: "You've received a follow request"
|
||||
yourFollowRequestAccepted: "Your follow request was accepted"
|
||||
pollEnded: "Poll results have become available"
|
||||
scheduledNotePosted: "Scheduled note has been posted"
|
||||
scheduledNotePostFailed: "Failed to post scheduled note"
|
||||
newNote: "New note"
|
||||
unreadAntennaNote: "Antenna {name}"
|
||||
roleAssigned: "Role given"
|
||||
@@ -2644,6 +2819,8 @@ _notification:
|
||||
quote: "Quotes"
|
||||
reaction: "Reactions"
|
||||
pollEnded: "Polls ending"
|
||||
scheduledNotePosted: "Scheduled note was successful"
|
||||
scheduledNotePostFailed: "Scheduled note failed"
|
||||
receiveFollowRequest: "Received follow requests"
|
||||
followRequestAccepted: "Accepted follow requests"
|
||||
roleAssigned: "Role given"
|
||||
@@ -2683,6 +2860,14 @@ _deck:
|
||||
usedAsMinWidthWhenFlexible: "Minimum width will be used for this when the \"Auto-adjust width\" option is enabled"
|
||||
flexible: "Auto-adjust width"
|
||||
enableSyncBetweenDevicesForProfiles: "Enable profile information sync between devices"
|
||||
showHowToUse: ""
|
||||
_howToUse:
|
||||
addColumn_title: "Add column"
|
||||
addColumn_description: "You can select and add column types."
|
||||
settings_title: "UI Settings"
|
||||
settings_description: "You can configure detailed settings for the deck UI."
|
||||
switchProfile_title: "Profile Switching"
|
||||
switchProfile_description: "You can save UI layouts as profiles and switch between them at any time."
|
||||
_columns:
|
||||
main: "Main"
|
||||
widgets: "Widgets"
|
||||
@@ -2694,7 +2879,7 @@ _deck:
|
||||
mentions: "Mentions"
|
||||
direct: "Direct notes"
|
||||
roleTimeline: "Role Timeline"
|
||||
chat: "Chat"
|
||||
chat: "Chat with user"
|
||||
_dialog:
|
||||
charactersExceeded: "You've exceeded the maximum character limit! Currently at {current} of {max}."
|
||||
charactersBelow: "You're below the minimum character limit! Currently at {current} of {min}."
|
||||
@@ -2743,6 +2928,8 @@ _abuseReport:
|
||||
notifiedWebhook: "Webhook to use"
|
||||
deleteConfirm: "Are you sure that you want to delete the notification recipient?"
|
||||
_moderationLogTypes:
|
||||
clearQueue: "Clear queue"
|
||||
promoteQueue: "Promote queue"
|
||||
createRole: "Role created"
|
||||
deleteRole: "Role deleted"
|
||||
updateRole: "Role updated"
|
||||
@@ -2766,7 +2953,7 @@ _moderationLogTypes:
|
||||
resetPassword: "Password reset"
|
||||
suspendRemoteInstance: "Remote instance suspended"
|
||||
unsuspendRemoteInstance: "Remote instance unsuspended"
|
||||
updateRemoteInstanceNote: "Moderation note updated for remote instance."
|
||||
updateRemoteInstanceNote: "Updated moderation note for remote servers"
|
||||
markSensitiveDriveFile: "File marked as sensitive"
|
||||
unmarkSensitiveDriveFile: "File unmarked as sensitive"
|
||||
resolveAbuseReport: "Report resolved"
|
||||
@@ -2800,6 +2987,7 @@ _fileViewer:
|
||||
url: "URL"
|
||||
uploadedAt: "Uploaded at"
|
||||
attachedNotes: "Attached notes"
|
||||
usage: "Used"
|
||||
thisPageCanBeSeenFromTheAuthor: "This page can only be seen by the user who uploaded this file."
|
||||
_externalResourceInstaller:
|
||||
title: "Install from external site"
|
||||
@@ -3052,6 +3240,7 @@ _bootErrors:
|
||||
otherOption1: "Delete client settings and cache"
|
||||
otherOption2: "Start the simple client"
|
||||
otherOption3: "Launch the repair tool"
|
||||
otherOption4: "Launch Misskey in safe mode"
|
||||
_search:
|
||||
searchScopeAll: "All"
|
||||
searchScopeLocal: "Local"
|
||||
@@ -3088,6 +3277,8 @@ _serverSetupWizard:
|
||||
doYouConnectToFediverse_description1: "When connected to a network of distributed servers (Fediverse) content can be exchanged with other servers."
|
||||
doYouConnectToFediverse_description2: "Connecting with the Fediverse is also called \"federation\""
|
||||
youCanConfigureMoreFederationSettingsLater: "Advanced settings such as specifying federated servers can be configured later."
|
||||
remoteContentsCleaning: "Automatic cleanup of received contents"
|
||||
remoteContentsCleaning_description: "Federation may result in a continuous inflow of content. Enabling automatic cleanup will remove outdated and unreferenced content from the server to save storage."
|
||||
adminInfo: "Administrator information"
|
||||
adminInfo_description: "Sets the administrator information used to receive inquiries."
|
||||
adminInfo_mustBeFilled: "Must be entered if public server or federation is on."
|
||||
@@ -3103,6 +3294,7 @@ _serverSetupWizard:
|
||||
text2: "We would appreciate your support so that we can continue to develop this software further into the future."
|
||||
text3: "There are also special benefits for supporters!"
|
||||
_uploader:
|
||||
editImage: "Edit Image"
|
||||
compressedToX: "Compressed to {x}"
|
||||
savedXPercent: "Saving {x}%"
|
||||
abortConfirm: "Some files have not been uploaded, do you want to abort?"
|
||||
@@ -3132,17 +3324,20 @@ _watermarkEditor:
|
||||
title: "Edit Watermark"
|
||||
cover: "Cover everything"
|
||||
repeat: "spread all over"
|
||||
preserveBoundingRect: "Adjust to prevent overflow when rotating"
|
||||
opacity: "Opacity"
|
||||
scale: "Size"
|
||||
text: "Text"
|
||||
qr: "QR Code"
|
||||
position: "Position"
|
||||
margin: "Margin"
|
||||
type: "Type"
|
||||
image: "Images"
|
||||
advanced: "Advanced"
|
||||
angle: "Angle"
|
||||
stripe: "Stripes"
|
||||
stripeWidth: "Line width"
|
||||
stripeFrequency: "Lines count"
|
||||
angle: "Angle"
|
||||
polkadot: "Polkadot"
|
||||
checker: "Checker"
|
||||
polkadotMainDotOpacity: "Opacity of the main dot"
|
||||
@@ -3150,17 +3345,22 @@ _watermarkEditor:
|
||||
polkadotSubDotOpacity: "Opacity of the secondary dot"
|
||||
polkadotSubDotRadius: "Size of the secondary dot"
|
||||
polkadotSubDotDivisions: "Number of sub-dots."
|
||||
leaveBlankToAccountUrl: "Leave blank to use account URL"
|
||||
failedToLoadImage: "Failed to load image"
|
||||
_imageEffector:
|
||||
title: "Effects"
|
||||
addEffect: "Add Effects"
|
||||
discardChangesConfirm: "Are you sure you want to leave? You have unsaved changes."
|
||||
failedToLoadImage: "Failed to load image"
|
||||
_fxs:
|
||||
chromaticAberration: "Chromatic Aberration"
|
||||
glitch: "Glitch"
|
||||
mirror: "Mirror"
|
||||
invert: "Invert Colors"
|
||||
grayscale: "white-black"
|
||||
colorAdjust: "Colour Correction"
|
||||
grayscale: "Grayscale"
|
||||
blur: "Blur"
|
||||
pixelate: "Pixelate"
|
||||
colorAdjust: "Color Correction"
|
||||
colorClamp: "Color Compression"
|
||||
colorClampAdvanced: "Color Compression (Advanced)"
|
||||
distort: "Distortion"
|
||||
@@ -3171,3 +3371,72 @@ _imageEffector:
|
||||
checker: "Checker"
|
||||
blockNoise: "Block Noise"
|
||||
tearing: "Tearing"
|
||||
fill: "Fill"
|
||||
_fxProps:
|
||||
angle: "Angle"
|
||||
scale: "Size"
|
||||
size: "Size"
|
||||
radius: "Radius"
|
||||
samples: "Sample count"
|
||||
offset: "Position"
|
||||
color: "Color"
|
||||
opacity: "Opacity"
|
||||
normalize: "Normalize"
|
||||
amount: "Amount"
|
||||
lightness: "Lighten"
|
||||
contrast: "Contrast"
|
||||
hue: "Hue"
|
||||
brightness: "Brightness"
|
||||
saturation: "Saturation"
|
||||
max: "Maximum"
|
||||
min: "Minimum"
|
||||
direction: "Direction"
|
||||
phase: "Phase"
|
||||
frequency: "Frequency"
|
||||
strength: "Strength"
|
||||
glitchChannelShift: "Channel shift"
|
||||
seed: "Seed value"
|
||||
redComponent: "Red component"
|
||||
greenComponent: "Green component"
|
||||
blueComponent: "Blue component"
|
||||
threshold: "Threshold"
|
||||
centerX: "Center X"
|
||||
centerY: "Center Y"
|
||||
density: "Density"
|
||||
zoomLinesOutlineThickness: "Outline shadow thickness"
|
||||
zoomLinesMaskSize: "Center diameter"
|
||||
circle: "Circular"
|
||||
drafts: "Drafts"
|
||||
_drafts:
|
||||
select: "Select Draft"
|
||||
cannotCreateDraftAnymore: "The number of drafts that can be created has been exceeded."
|
||||
cannotCreateDraft: "You cannot create a draft with this content."
|
||||
delete: "Delete Draft"
|
||||
deleteAreYouSure: "Delete draft?"
|
||||
noDrafts: "No drafts"
|
||||
replyTo: "Reply to {user}"
|
||||
quoteOf: "Citation to {user}'s note"
|
||||
postTo: "Posting to {channel}"
|
||||
saveToDraft: "Save to Draft"
|
||||
restoreFromDraft: "Restore from Draft"
|
||||
restore: "Restore"
|
||||
listDrafts: "List of Drafts"
|
||||
schedule: "Schedule note"
|
||||
listScheduledNotes: "Scheduled notes list"
|
||||
cancelSchedule: "Cancel schedule"
|
||||
qr: "QR Code"
|
||||
_qr:
|
||||
showTabTitle: "Display"
|
||||
readTabTitle: "Scan"
|
||||
shareTitle: "{name} {acct}"
|
||||
shareText: "Follow me on the Fediverse!"
|
||||
chooseCamera: "Choose camera"
|
||||
cannotToggleFlash: "Unable to toggle flashlight"
|
||||
turnOnFlash: "Turn on flashlight"
|
||||
turnOffFlash: "Turn off flashlight"
|
||||
startQr: "Resume QR code reader"
|
||||
stopQr: "Stop QR code reader"
|
||||
noQrCodeFound: "No QR code found"
|
||||
scanFile: "Scan image from device"
|
||||
raw: "Text"
|
||||
mfm: "MFM"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,11 +5,12 @@ introMisskey: "Bienvenue ! Misskey est un service de microblogage décentralis
|
||||
poweredByMisskeyDescription: "{name} est l'un des services propulsés par la plateforme ouverte <b>Misskey</b> (appelée \"instance Misskey\")."
|
||||
monthAndDay: "{day}/{month}"
|
||||
search: "Rechercher"
|
||||
reset: "Réinitialiser"
|
||||
notifications: "Notifications"
|
||||
username: "Nom d’utilisateur·rice"
|
||||
password: "Mot de passe"
|
||||
initialPasswordForSetup: "Mot de passe initial pour la configuration"
|
||||
initialPasswordIsIncorrect: "Mot de passe initial pour la configuration est incorrecte"
|
||||
initialPasswordIsIncorrect: "Le mot de passe initial pour la configuration est incorrect"
|
||||
initialPasswordForSetupDescription: "Utilisez le mot de passe que vous avez entré pour le fichier de configuration si vous avez installé Misskey vous-même.\nSi vous utilisez un service d'hébergement Misskey, utilisez le mot de passe fourni.\nSi vous n'avez pas défini de mot de passe, laissez le champ vide pour continuer."
|
||||
forgotPassword: "Mot de passe oublié"
|
||||
fetchingAsApObject: "Récupération depuis le fédiverse …"
|
||||
@@ -48,6 +49,7 @@ pin: "Épingler sur le profil"
|
||||
unpin: "Désépingler"
|
||||
copyContent: "Copier le contenu"
|
||||
copyLink: "Copier le lien"
|
||||
copyRemoteLink: "Copier le lien de la note"
|
||||
copyLinkRenote: "Copier le lien de la renote"
|
||||
delete: "Supprimer"
|
||||
deleteAndEdit: "Supprimer et réécrire"
|
||||
@@ -62,8 +64,8 @@ copyNoteId: "Copier l'identifiant de la note"
|
||||
copyFileId: "Copier l'identifiant du fichier"
|
||||
copyFolderId: "Copier l'identifiant du dossier"
|
||||
copyProfileUrl: "Copier l'URL du profil"
|
||||
searchUser: "Chercher un·e utilisateur·rice"
|
||||
searchThisUsersNotes: "Cherchez les notes de cet·te utilisateur·rice"
|
||||
searchUser: "Chercher un utilisateur"
|
||||
searchThisUsersNotes: "Cherchez les notes de cet utilisateur"
|
||||
reply: "Répondre"
|
||||
loadMore: "Afficher plus …"
|
||||
showMore: "Voir plus"
|
||||
@@ -81,6 +83,8 @@ files: "Fichiers"
|
||||
download: "Télécharger"
|
||||
driveFileDeleteConfirm: "Êtes-vous sûr·e de vouloir supprimer le fichier « {name} » ? Les notes avec ce fichier joint seront aussi supprimées."
|
||||
unfollowConfirm: "Désirez-vous vous désabonner de {name} ?"
|
||||
cancelFollowRequestConfirm: "Est-te vous sur de vouloir annuler la demande de suivi de {name} ?"
|
||||
rejectFollowRequestConfirm: "Refuser la demande de suivi de {name} ?"
|
||||
exportRequested: "Vous avez demandé une exportation. L’opération pourrait prendre un peu de temps. Une fois terminée, le fichier sera ajouté au Drive."
|
||||
importRequested: "Vous avez initié un import. Cela pourrait prendre un peu de temps."
|
||||
lists: "Listes"
|
||||
@@ -118,6 +122,8 @@ cantReRenote: "Impossible de renoter une Renote."
|
||||
quote: "Citer"
|
||||
inChannelRenote: "Renoter dans le canal"
|
||||
inChannelQuote: "Citer dans le canal"
|
||||
renoteToChannel: "Renoter sur le canal"
|
||||
renoteToOtherChannel: "Renoter sur un autre canal"
|
||||
pinnedNote: "Note épinglée"
|
||||
pinned: "Épingler sur le profil"
|
||||
you: "Vous"
|
||||
@@ -212,6 +218,7 @@ blockThisInstance: "Bloquer cette instance"
|
||||
silenceThisInstance: "Mettre cette instance en sourdine"
|
||||
operations: "Opérations"
|
||||
software: "Logiciel"
|
||||
softwareName: "Nom du logiciel"
|
||||
version: "Version"
|
||||
metadata: "Métadonnées"
|
||||
withNFiles: "{n} fichier(s)"
|
||||
@@ -231,6 +238,9 @@ blockedInstances: "Instances bloquées"
|
||||
blockedInstancesDescription: "Listez les instances que vous désirez bloquer, une par ligne. Ces instances ne seront plus en capacité d'interagir avec votre instance."
|
||||
silencedInstances: "Instances mises en sourdine"
|
||||
silencedInstancesDescription: "Énumérer les noms d'hôte des instances à mettre en sourdine. Tous les comptes des instances énumérées seront traités comme mis en sourdine, ne peuvent faire que des demandes de suivi et ne peuvent pas mentionner les comptes locaux s'ils ne sont pas suivis. Cela n'affectera pas les instances bloquées."
|
||||
mediaSilencedInstances: "Médias silencieux sur ces instances"
|
||||
mediaSilencedInstancesDescription: "Liste des noms de serveurs où vous voulez que les médias soient silencieux, séparés par un retour à la ligne.\nTous les comptes des instances listées seront considérés comme sensibles, et ne peuvent pas utilisés d'émojis personnalisés. Ceci n'affectera pas les serveurs bloquées."
|
||||
federationAllowedHosts: "Serveurs qui autorisent la fédération"
|
||||
muteAndBlock: "Masqué·e·s / Bloqué·e·s"
|
||||
mutedUsers: "Utilisateur·rice·s en sourdine"
|
||||
blockedUsers: "Utilisateur·rice·s bloqué·e·s"
|
||||
@@ -1208,7 +1218,6 @@ releaseToRefresh: "Relâcher pour rafraîchir"
|
||||
refreshing: "Rafraîchissement..."
|
||||
pullDownToRefresh: "Tirer vers le bas pour rafraîchir"
|
||||
useGroupedNotifications: "Grouper les notifications"
|
||||
signupPendingError: "Un problème est survenu lors de la vérification de votre adresse e-mail. Le lien a peut-être expiré."
|
||||
cwNotationRequired: "Si « Masquer le contenu » est activé, une description doit être fournie."
|
||||
doReaction: "Réagir"
|
||||
code: "Code"
|
||||
@@ -1272,6 +1281,18 @@ pleaseSelectAccount: "Sélectionner un compte"
|
||||
availableRoles: "Rôles disponibles"
|
||||
postForm: "Formulaire de publication"
|
||||
information: "Informations"
|
||||
inMinutes: "min"
|
||||
inDays: "j"
|
||||
widgets: "Widgets"
|
||||
presets: "Préréglage"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
filename: "Nom du fichier"
|
||||
_imageFrameEditor:
|
||||
header: "Entête"
|
||||
font: "Police de caractères"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
_chat:
|
||||
invitations: "Inviter"
|
||||
noHistory: "Pas d'historique"
|
||||
@@ -1994,6 +2015,14 @@ _widgets:
|
||||
_userList:
|
||||
chooseList: "Sélectionner une liste"
|
||||
birthdayFollowings: "Utilisateurs qui fêtent l'anniversaire aujourd'hui"
|
||||
_widgetOptions:
|
||||
height: "Hauteur"
|
||||
_button:
|
||||
colored: "Coloré"
|
||||
_clock:
|
||||
size: "Taille"
|
||||
_birthdayFollowings:
|
||||
period: "Durée"
|
||||
_cw:
|
||||
hide: "Masquer"
|
||||
show: "Afficher le contenu"
|
||||
@@ -2035,6 +2064,9 @@ _postForm:
|
||||
replyPlaceholder: "Répondre à cette note ..."
|
||||
quotePlaceholder: "Citez cette note ..."
|
||||
channelPlaceholder: "Publier au canal…"
|
||||
_howToUse:
|
||||
visibility_title: "Visibilité"
|
||||
menu_title: "Menu"
|
||||
_placeholders:
|
||||
a: "Quoi de neuf ?"
|
||||
b: "Il s'est passé quelque chose ?"
|
||||
@@ -2370,3 +2402,15 @@ _watermarkEditor:
|
||||
image: "Images"
|
||||
advanced: "Avancé"
|
||||
angle: "Angle"
|
||||
_imageEffector:
|
||||
_fxProps:
|
||||
angle: "Angle"
|
||||
scale: "Taille"
|
||||
size: "Taille"
|
||||
offset: "Position"
|
||||
color: "Couleur"
|
||||
opacity: "Transparence"
|
||||
lightness: "Clair"
|
||||
_qr:
|
||||
showTabTitle: "Affichage"
|
||||
raw: "Texte"
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
import * as fs from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname } from 'node:path';
|
||||
import * as yaml from 'js-yaml';
|
||||
import ts from 'typescript';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const parameterRegExp = /\{(\w+)\}/g;
|
||||
|
||||
function createMemberType(item) {
|
||||
if (typeof item !== 'string') {
|
||||
return ts.factory.createTypeLiteralNode(createMembers(item));
|
||||
}
|
||||
const parameters = Array.from(
|
||||
item.matchAll(parameterRegExp),
|
||||
([, parameter]) => parameter,
|
||||
);
|
||||
return parameters.length
|
||||
? ts.factory.createTypeReferenceNode(
|
||||
ts.factory.createIdentifier('ParameterizedString'),
|
||||
[
|
||||
ts.factory.createUnionTypeNode(
|
||||
parameters.map((parameter) =>
|
||||
ts.factory.createStringLiteral(parameter),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
|
||||
}
|
||||
|
||||
function createMembers(record) {
|
||||
return Object.entries(record).map(([k, v]) => {
|
||||
const node = ts.factory.createPropertySignature(
|
||||
undefined,
|
||||
ts.factory.createStringLiteral(k),
|
||||
undefined,
|
||||
createMemberType(v),
|
||||
);
|
||||
if (typeof v === 'string') {
|
||||
ts.addSyntheticLeadingComment(
|
||||
node,
|
||||
ts.SyntaxKind.MultiLineCommentTrivia,
|
||||
`*
|
||||
* ${v.replace(/\n/g, '\n * ')}
|
||||
`,
|
||||
true,
|
||||
);
|
||||
}
|
||||
return node;
|
||||
});
|
||||
}
|
||||
|
||||
export default function generateDTS() {
|
||||
const locale = yaml.load(fs.readFileSync(`${__dirname}/ja-JP.yml`, 'utf-8'));
|
||||
const members = createMembers(locale);
|
||||
const elements = [
|
||||
ts.factory.createVariableStatement(
|
||||
[ts.factory.createToken(ts.SyntaxKind.DeclareKeyword)],
|
||||
ts.factory.createVariableDeclarationList(
|
||||
[
|
||||
ts.factory.createVariableDeclaration(
|
||||
ts.factory.createIdentifier('kParameters'),
|
||||
undefined,
|
||||
ts.factory.createTypeOperatorNode(
|
||||
ts.SyntaxKind.UniqueKeyword,
|
||||
ts.factory.createKeywordTypeNode(ts.SyntaxKind.SymbolKeyword),
|
||||
),
|
||||
undefined,
|
||||
),
|
||||
],
|
||||
ts.NodeFlags.Const,
|
||||
),
|
||||
),
|
||||
ts.factory.createInterfaceDeclaration(
|
||||
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
|
||||
ts.factory.createIdentifier('ParameterizedString'),
|
||||
[
|
||||
ts.factory.createTypeParameterDeclaration(
|
||||
undefined,
|
||||
ts.factory.createIdentifier('T'),
|
||||
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
|
||||
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
|
||||
),
|
||||
],
|
||||
undefined,
|
||||
[
|
||||
ts.factory.createPropertySignature(
|
||||
undefined,
|
||||
ts.factory.createComputedPropertyName(
|
||||
ts.factory.createIdentifier('kParameters'),
|
||||
),
|
||||
undefined,
|
||||
ts.factory.createTypeReferenceNode(
|
||||
ts.factory.createIdentifier('T'),
|
||||
undefined,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
ts.factory.createInterfaceDeclaration(
|
||||
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
|
||||
ts.factory.createIdentifier('ILocale'),
|
||||
undefined,
|
||||
undefined,
|
||||
[
|
||||
ts.factory.createIndexSignature(
|
||||
undefined,
|
||||
[
|
||||
ts.factory.createParameterDeclaration(
|
||||
undefined,
|
||||
undefined,
|
||||
ts.factory.createIdentifier('_'),
|
||||
undefined,
|
||||
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
|
||||
undefined,
|
||||
),
|
||||
],
|
||||
ts.factory.createUnionTypeNode([
|
||||
ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
|
||||
ts.factory.createTypeReferenceNode(
|
||||
ts.factory.createIdentifier('ParameterizedString'),
|
||||
),
|
||||
ts.factory.createTypeReferenceNode(
|
||||
ts.factory.createIdentifier('ILocale'),
|
||||
undefined,
|
||||
),
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
ts.factory.createInterfaceDeclaration(
|
||||
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
|
||||
ts.factory.createIdentifier('Locale'),
|
||||
undefined,
|
||||
[
|
||||
ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [
|
||||
ts.factory.createExpressionWithTypeArguments(
|
||||
ts.factory.createIdentifier('ILocale'),
|
||||
undefined,
|
||||
),
|
||||
]),
|
||||
],
|
||||
members,
|
||||
),
|
||||
ts.factory.createVariableStatement(
|
||||
[ts.factory.createToken(ts.SyntaxKind.DeclareKeyword)],
|
||||
ts.factory.createVariableDeclarationList(
|
||||
[
|
||||
ts.factory.createVariableDeclaration(
|
||||
ts.factory.createIdentifier('locales'),
|
||||
undefined,
|
||||
ts.factory.createTypeLiteralNode([
|
||||
ts.factory.createIndexSignature(
|
||||
undefined,
|
||||
[
|
||||
ts.factory.createParameterDeclaration(
|
||||
undefined,
|
||||
undefined,
|
||||
ts.factory.createIdentifier('lang'),
|
||||
undefined,
|
||||
ts.factory.createKeywordTypeNode(
|
||||
ts.SyntaxKind.StringKeyword,
|
||||
),
|
||||
undefined,
|
||||
),
|
||||
],
|
||||
ts.factory.createTypeReferenceNode(
|
||||
ts.factory.createIdentifier('Locale'),
|
||||
undefined,
|
||||
),
|
||||
),
|
||||
]),
|
||||
undefined,
|
||||
),
|
||||
],
|
||||
ts.NodeFlags.Const,
|
||||
),
|
||||
),
|
||||
ts.factory.createFunctionDeclaration(
|
||||
[ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
|
||||
undefined,
|
||||
ts.factory.createIdentifier('build'),
|
||||
undefined,
|
||||
[],
|
||||
ts.factory.createTypeReferenceNode(
|
||||
ts.factory.createIdentifier('Locale'),
|
||||
undefined,
|
||||
),
|
||||
undefined,
|
||||
),
|
||||
ts.factory.createExportDefault(ts.factory.createIdentifier('locales')),
|
||||
];
|
||||
ts.addSyntheticLeadingComment(
|
||||
elements[0],
|
||||
ts.SyntaxKind.MultiLineCommentTrivia,
|
||||
' eslint-disable ',
|
||||
true,
|
||||
);
|
||||
ts.addSyntheticLeadingComment(
|
||||
elements[0],
|
||||
ts.SyntaxKind.SingleLineCommentTrivia,
|
||||
' This file is generated by locales/generateDTS.js',
|
||||
true,
|
||||
);
|
||||
ts.addSyntheticLeadingComment(
|
||||
elements[0],
|
||||
ts.SyntaxKind.SingleLineCommentTrivia,
|
||||
' Do not edit this file directly.',
|
||||
true,
|
||||
);
|
||||
const printed = ts
|
||||
.createPrinter({
|
||||
newLine: ts.NewLineKind.LineFeed,
|
||||
})
|
||||
.printList(
|
||||
ts.ListFormat.MultiLine,
|
||||
ts.factory.createNodeArray(elements),
|
||||
ts.createSourceFile(
|
||||
'index.d.ts',
|
||||
'',
|
||||
ts.ScriptTarget.ESNext,
|
||||
true,
|
||||
ts.ScriptKind.TS,
|
||||
),
|
||||
);
|
||||
|
||||
fs.writeFileSync(`${__dirname}/index.d.ts`, printed, 'utf-8');
|
||||
}
|
||||
@@ -5,9 +5,13 @@ introMisskey: "Selamat datang! Misskey adalah perangkat mikroblog tercatu bersif
|
||||
poweredByMisskeyDescription: "{name} adalah sebuah layanan (instance) yang menggunakan platform sumber terbuka <b>Misskey</b>."
|
||||
monthAndDay: "{day} {month}"
|
||||
search: "Penelusuran"
|
||||
reset: "Reset"
|
||||
notifications: "Notifikasi"
|
||||
username: "Nama Pengguna"
|
||||
password: "Kata sandi"
|
||||
initialPasswordForSetup: "Kata sandi untuk memulai konfigurasi awal"
|
||||
initialPasswordIsIncorrect: "Kata sandi untuk memulai konfigurasi awal salah."
|
||||
initialPasswordForSetupDescription: "Jika Anda menginstal Misskey sendiri, gunakan kata sandi yang Anda masukkan di berkas konfigurasi.\nJika Anda menggunakan layanan hosting Misskey, gunakan kata sandi yang diberikan.\nJika Anda belum mengatur kata sandi, biarkan kosong dan lanjutkan."
|
||||
forgotPassword: "Lupa Kata Sandi"
|
||||
fetchingAsApObject: "Mengambil data dari Fediverse..."
|
||||
ok: "OK"
|
||||
@@ -45,6 +49,7 @@ pin: "Sematkan ke profil"
|
||||
unpin: "Lepas sematan dari profil"
|
||||
copyContent: "Salin konten"
|
||||
copyLink: "Salin tautan"
|
||||
copyRemoteLink: "Salin tautan jarak jauh"
|
||||
copyLinkRenote: "Salin tautan renote"
|
||||
delete: "Hapus"
|
||||
deleteAndEdit: "Hapus dan sunting"
|
||||
@@ -212,8 +217,10 @@ perDay: "per Hari"
|
||||
stopActivityDelivery: "Berhenti mengirim aktivitas"
|
||||
blockThisInstance: "Blokir instansi ini"
|
||||
silenceThisInstance: "Senyapkan instansi ini"
|
||||
mediaSilenceThisInstance: "Server media senyap"
|
||||
operations: "Tindakan"
|
||||
software: "Perangkat lunak"
|
||||
softwareName: "Nama Perangkat Lunak"
|
||||
version: "Versi"
|
||||
metadata: "Metadata"
|
||||
withNFiles: "{n} berkas"
|
||||
@@ -233,6 +240,8 @@ blockedInstances: "Instansi terblokir"
|
||||
blockedInstancesDescription: "Daftar nama host dari instansi yang diperlukan untuk diblokir. Instansi yang didaftarkan tidak akan dapat berkomunikasi dengan instansi ini."
|
||||
silencedInstances: "Instansi yang disenyapkan"
|
||||
silencedInstancesDescription: "Daftar nama host dari instansi yang ingin kamu senyapkan. Semua akun dari instansi yang terdaftar akan diperlakukan sebagai disenyapkan. Hal ini membuat akun hanya dapat membuat permintaan mengikuti, dan tidak dapat menyebutkan akun lokal apabila tidak mengikuti. Hal ini tidak akan mempengaruhi instansi yang diblokir."
|
||||
mediaSilencedInstances: "Server dengan media dibisukan"
|
||||
mediaSilencedInstancesDescription: "Masukkan host server yang medianya ingin Anda bisukan, pisahkan dengan baris baru. Semua berkas dari akun di server ini akan dianggap sebagai sensitif dan emoji kustom tidak akan tersedia. Ini tidak akan membengaruhi server yang diblokir."
|
||||
federationAllowedHosts: "Server yang membolehkan federasi"
|
||||
muteAndBlock: "Bisukan / Blokir"
|
||||
mutedUsers: "Pengguna yang dibisukan"
|
||||
@@ -291,6 +300,7 @@ uploadFromUrlMayTakeTime: "Membutuhkan beberapa waktu hingga pengunggahan selesa
|
||||
explore: "Jelajahi"
|
||||
messageRead: "Telah dibaca"
|
||||
noMoreHistory: "Tidak ada sejarah lagi"
|
||||
startChat: "Kirim pesan"
|
||||
nUsersRead: "Dibaca oleh {n}"
|
||||
agreeTo: "Saya setuju kepada {0}"
|
||||
agree: "Setuju"
|
||||
@@ -390,7 +400,7 @@ enableHcaptcha: "Nyalakan hCaptcha"
|
||||
hcaptchaSiteKey: "Site Key"
|
||||
hcaptchaSecretKey: "Secret Key"
|
||||
mcaptcha: "mCaptcha"
|
||||
enableMcaptcha: "Nyalakan mCaptcha"
|
||||
enableMcaptcha: ""
|
||||
mcaptchaSiteKey: "Site key"
|
||||
mcaptchaSecretKey: "Secret Key"
|
||||
mcaptchaInstanceUrl: "URL instansi mCaptcha"
|
||||
@@ -503,6 +513,7 @@ emojiStyle: "Gaya emoji"
|
||||
native: "Native"
|
||||
menuStyle: "Gaya menu"
|
||||
style: "Gaya"
|
||||
popup: "Pemunculan"
|
||||
showNoteActionsOnlyHover: "Hanya tampilkan aksi catatan saat ditunjuk"
|
||||
showReactionsCount: "Lihat jumlah reaksi dalam catatan"
|
||||
noHistory: "Tidak ada riwayat"
|
||||
@@ -559,6 +570,7 @@ showFixedPostForm: "Tampilkan form posting di atas lini masa"
|
||||
showFixedPostFormInChannel: "Tampilkan form posting di atas lini masa (Kanal)"
|
||||
withRepliesByDefaultForNewlyFollowed: "Termasuk balasan dari pengguna baru yang diikuti pada lini masa secara bawaan"
|
||||
newNoteRecived: "Kamu mendapat catatan baru"
|
||||
newNote: "Catatan baru"
|
||||
sounds: "Bunyi"
|
||||
sound: "Bunyi"
|
||||
listen: "Dengarkan"
|
||||
@@ -1021,6 +1033,7 @@ permissionDeniedError: "Operasi ditolak"
|
||||
permissionDeniedErrorDescription: "Akun ini tidak memiliki izin untuk melakukan aksi ini."
|
||||
preset: "Prasetel"
|
||||
selectFromPresets: "Pilih dari prasetel"
|
||||
custom: "Penyesuaian"
|
||||
achievements: "Pencapaian"
|
||||
gotInvalidResponseError: "Respon peladen tidak valid"
|
||||
gotInvalidResponseErrorDescription: "Peladen tidak dapat dijangkau atau sedang dalam perawatan. Mohon coba lagi nanti."
|
||||
@@ -1040,7 +1053,7 @@ disableFederationConfirmWarn: "Mematikan federasi tidak membuat kiriman menjadi
|
||||
disableFederationOk: "Matikan federasi"
|
||||
invitationRequiredToRegister: "Instansi ini dalam mode undangan-saja. Kamu harus memasukkan kode undangan yang valid untuk mendaftar."
|
||||
emailNotSupported: "Instansi ini tidak mendukung mengirim surel"
|
||||
postToTheChannel: "Catat ke kanal"
|
||||
postToTheChannel: "Buat Catatan ke Kanal"
|
||||
cannotBeChangedLater: "Hal ini nantinya tidak dapat diubah lagi."
|
||||
reactionAcceptance: "Penerimaan reaksi"
|
||||
likeOnly: "Hanya suka"
|
||||
@@ -1103,6 +1116,7 @@ preservedUsernamesDescription: "Daftar nama pengguna yang dicadangkan dipisah de
|
||||
createNoteFromTheFile: "Buat catatan dari berkas ini"
|
||||
archive: "Arsipkan"
|
||||
archived: "Diarsipkan"
|
||||
unarchive: "Batalkan pengarsipan"
|
||||
channelArchiveConfirmTitle: "Yakin untuk mengarsipkan {name}?"
|
||||
channelArchiveConfirmDescription: "Kanal yang diarsipkan tidak akan muncul pada daftar kanal atau hasil pencarian. Postingan baru juga tidak dapat ditambahkan lagi."
|
||||
thisChannelArchived: "Kanal ini telah diarsipkan."
|
||||
@@ -1205,7 +1219,6 @@ releaseToRefresh: "Lepaskan untuk memuat ulang"
|
||||
refreshing: "Sedang memuat ulang..."
|
||||
pullDownToRefresh: "Tarik ke bawah untuk memuat ulang"
|
||||
useGroupedNotifications: "Tampilkan notifikasi secara dikelompokkan"
|
||||
signupPendingError: "Terdapat masalah ketika memverifikasi alamat surel. Tautan kemungkinan telah kedaluwarsa."
|
||||
cwNotationRequired: "Jika \"Sembunyikan konten\" diaktifkan, deskripsi harus disediakan."
|
||||
doReaction: "Tambahkan reaksi"
|
||||
code: "Kode"
|
||||
@@ -1245,6 +1258,7 @@ noDescription: "Tidak ada deskripsi"
|
||||
alwaysConfirmFollow: "Selalu konfirmasi ketika mengikuti"
|
||||
inquiry: "Hubungi kami"
|
||||
tryAgain: "Silahkan coba lagi."
|
||||
sensitiveMediaRevealConfirm: "Media sensitif. Apakah ingin melihat?"
|
||||
createdLists: "Senarai yang dibuat"
|
||||
createdAntennas: "Antena yang dibuat"
|
||||
fromX: "Dari {x}"
|
||||
@@ -1252,18 +1266,52 @@ noteOfThisUser: "Catatan oleh pengguna ini"
|
||||
clipNoteLimitExceeded: "Klip ini tak bisa ditambahi lagi catatan."
|
||||
performance: "Kinerja"
|
||||
modified: "Diubah"
|
||||
discard: "Buang"
|
||||
thereAreNChanges: "Ada {n} perubahan"
|
||||
signinWithPasskey: "Masuk dengan kunci sandi"
|
||||
unknownWebAuthnKey: "Kunci sandi tidak terdaftar."
|
||||
passkeyVerificationFailed: "Verifikasi kunci sandi gagal."
|
||||
passkeyVerificationSucceededButPasswordlessLoginDisabled: "Verifikasi kunci sandi berhasil, namun pemasukan tanpa sandi dinonaktifkan."
|
||||
messageToFollower: "Pesan kepada pengikut"
|
||||
prohibitedWordsForNameOfUser: "Kata yang dilarang untuk nama pengguna"
|
||||
lockdown: "Kuncitara"
|
||||
noName: "Tidak ada nama"
|
||||
skip: "Lewati"
|
||||
paste: "Tempel"
|
||||
emojiPalette: "Palet emoji"
|
||||
postForm: "Buat catatan"
|
||||
information: "Informasi"
|
||||
chat: "Obrolan"
|
||||
directMessage: "Obrolan pengguna"
|
||||
right: "Kanan"
|
||||
bottom: "Bawah"
|
||||
top: "Atas"
|
||||
advice: "Saran"
|
||||
inMinutes: "menit"
|
||||
inDays: "hari"
|
||||
widgets: "Widget"
|
||||
presets: "Prasetel"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
filename: "Nama berkas"
|
||||
_imageFrameEditor:
|
||||
header: "Header"
|
||||
font: "Font"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans-serif"
|
||||
_chat:
|
||||
invitations: "Undang"
|
||||
history: "Riwayat obrolan"
|
||||
noHistory: "Tidak ada riwayat"
|
||||
members: "Anggota"
|
||||
home: "Beranda"
|
||||
send: "Kirim"
|
||||
chatWithThisUser: "Obrolan pengguna"
|
||||
_settings:
|
||||
webhook: "Webhook"
|
||||
contentsUpdateFrequency: "Frekuensi pembaruan konten"
|
||||
_preferencesProfile:
|
||||
profileName: "Nama profil"
|
||||
_abuseUserReport:
|
||||
accept: "Setuju"
|
||||
reject: "Tolak"
|
||||
@@ -1957,6 +2005,7 @@ _sfx:
|
||||
noteMy: "Catatan (Saya)"
|
||||
notification: "Notifikasi"
|
||||
reaction: "Ketika memilih reaksi"
|
||||
chatMessage: "Obrolan pengguna"
|
||||
_soundSettings:
|
||||
driveFile: "Menggunakan berkas audio dalam Drive"
|
||||
driveFileWarn: "Pilih berkas audio dari Drive"
|
||||
@@ -2159,6 +2208,15 @@ _widgets:
|
||||
chooseList: "Pilih daftar"
|
||||
clicker: "Pengeklik"
|
||||
birthdayFollowings: "Pengguna yang merayakan hari ulang tahunnya hari ini"
|
||||
chat: "Obrolan pengguna"
|
||||
_widgetOptions:
|
||||
height: "Tinggi"
|
||||
_button:
|
||||
colored: "Diwarnai"
|
||||
_clock:
|
||||
size: "Ukuran"
|
||||
_birthdayFollowings:
|
||||
period: "Durasi"
|
||||
_cw:
|
||||
hide: "Sembunyikan"
|
||||
show: "Lihat konten"
|
||||
@@ -2201,6 +2259,9 @@ _postForm:
|
||||
replyPlaceholder: "Balas ke catatan ini..."
|
||||
quotePlaceholder: "Kutip catatan ini..."
|
||||
channelPlaceholder: "Posting ke kanal"
|
||||
_howToUse:
|
||||
visibility_title: "Visibilitas"
|
||||
menu_title: "Menu"
|
||||
_placeholders:
|
||||
a: "Sedang apa kamu saat ini?"
|
||||
b: "Apa yang terjadi di sekitarmu?"
|
||||
@@ -2400,13 +2461,14 @@ _deck:
|
||||
main: "Utama"
|
||||
widgets: "Widget"
|
||||
notifications: "Notifikasi"
|
||||
tl: "Lini masa"
|
||||
tl: "Beranda"
|
||||
antenna: "Antena"
|
||||
list: "Daftar"
|
||||
channel: "Kanal"
|
||||
mentions: "Sebutan"
|
||||
direct: "Langsung"
|
||||
roleTimeline: "Lini masa peran"
|
||||
chat: "Obrolan pengguna"
|
||||
_dialog:
|
||||
charactersExceeded: "Kamu telah melebihi batas karakter maksimum! Saat ini pada {current} dari {max}."
|
||||
charactersBelow: "Kamu berada di bawah batas minimum karakter! Saat ini pada {current} dari {min}."
|
||||
@@ -2618,3 +2680,15 @@ _watermarkEditor:
|
||||
image: "Gambar"
|
||||
advanced: "Tingkat lanjut"
|
||||
angle: "Sudut"
|
||||
_imageEffector:
|
||||
_fxProps:
|
||||
angle: "Sudut"
|
||||
scale: "Ukuran"
|
||||
size: "Ukuran"
|
||||
offset: "Posisi"
|
||||
color: "Warna"
|
||||
opacity: "Opasitas"
|
||||
lightness: "Menerangkan"
|
||||
_qr:
|
||||
showTabTitle: "Tampilkan"
|
||||
raw: "Teks"
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
/**
|
||||
* Languages Loader
|
||||
*/
|
||||
|
||||
import * as fs from 'node:fs';
|
||||
import * as yaml from 'js-yaml';
|
||||
|
||||
const merge = (...args) => args.reduce((a, c) => ({
|
||||
...a,
|
||||
...c,
|
||||
...Object.entries(a)
|
||||
.filter(([k]) => c && typeof c[k] === 'object')
|
||||
.reduce((a, [k, v]) => (a[k] = merge(v, c[k]), a), {})
|
||||
}), {});
|
||||
|
||||
const languages = [
|
||||
'ar-SA',
|
||||
'ca-ES',
|
||||
'cs-CZ',
|
||||
'da-DK',
|
||||
'de-DE',
|
||||
'en-US',
|
||||
'es-ES',
|
||||
'fr-FR',
|
||||
'id-ID',
|
||||
'it-IT',
|
||||
'ja-JP',
|
||||
'ja-KS',
|
||||
'kab-KAB',
|
||||
'kn-IN',
|
||||
'ko-KR',
|
||||
'nl-NL',
|
||||
'no-NO',
|
||||
'pl-PL',
|
||||
'pt-PT',
|
||||
'ru-RU',
|
||||
'sk-SK',
|
||||
'th-TH',
|
||||
'ug-CN',
|
||||
'uk-UA',
|
||||
'vi-VN',
|
||||
'zh-CN',
|
||||
'zh-TW',
|
||||
];
|
||||
|
||||
const primaries = {
|
||||
'en': 'US',
|
||||
'ja': 'JP',
|
||||
'zh': 'CN',
|
||||
};
|
||||
|
||||
// 何故か文字列にバックスペース文字が混入することがあり、YAMLが壊れるので取り除く
|
||||
const clean = (text) => text.replace(new RegExp(String.fromCodePoint(0x08), 'g'), '');
|
||||
|
||||
export function build() {
|
||||
// vitestの挙動を調整するため、一度ローカル変数化する必要がある
|
||||
// https://github.com/vitest-dev/vitest/issues/3988#issuecomment-1686599577
|
||||
// https://github.com/misskey-dev/misskey/pull/14057#issuecomment-2192833785
|
||||
const metaUrl = import.meta.url;
|
||||
const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, metaUrl), 'utf-8'))) || {}, a), {});
|
||||
|
||||
// 空文字列が入ることがあり、フォールバックが動作しなくなるのでプロパティごと消す
|
||||
const removeEmpty = (obj) => {
|
||||
for (const [k, v] of Object.entries(obj)) {
|
||||
if (v === '') {
|
||||
delete obj[k];
|
||||
} else if (typeof v === 'object') {
|
||||
removeEmpty(v);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
removeEmpty(locales);
|
||||
|
||||
return Object.entries(locales)
|
||||
.reduce((a, [k, v]) => (a[k] = (() => {
|
||||
const [lang] = k.split('-');
|
||||
switch (k) {
|
||||
case 'ja-JP': return v;
|
||||
case 'ja-KS':
|
||||
case 'en-US': return merge(locales['ja-JP'], v);
|
||||
default: return merge(
|
||||
locales['ja-JP'],
|
||||
locales['en-US'],
|
||||
locales[`${lang}-${primaries[lang]}`] ?? {},
|
||||
v
|
||||
);
|
||||
}
|
||||
})(), a), {});
|
||||
}
|
||||
|
||||
export default build();
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user