Compare commits
634 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7495206db2 | ||
![]() |
fe87d16d46 | ||
![]() |
0db54386cd | ||
![]() |
772258b0b8 | ||
![]() |
3ef002e14d | ||
![]() |
b90d473ae5 | ||
![]() |
f5091d524b | ||
![]() |
ee5720df2c | ||
![]() |
afe2037985 | ||
![]() |
878cd18144 | ||
![]() |
e8c8f67a09 | ||
![]() |
7b29e7cf7e | ||
![]() |
723d3e6871 | ||
![]() |
f063dee12a | ||
![]() |
db4b315d3d | ||
![]() |
64d00b08a3 | ||
![]() |
74736a941e | ||
![]() |
c40366f20a | ||
![]() |
d73e52ac2a | ||
![]() |
9fac8a611f | ||
![]() |
9c774a50f8 | ||
![]() |
4f20ee1909 | ||
![]() |
1440c5bc65 | ||
![]() |
5829b2a7c1 | ||
![]() |
e3c4bc18d0 | ||
![]() |
8555ec2f72 | ||
![]() |
8d7cefbbbe | ||
![]() |
5aa5896b22 | ||
![]() |
8a55bdd89d | ||
![]() |
6444ef6444 | ||
![]() |
701ab6cc68 | ||
![]() |
3c6ce7a943 | ||
![]() |
1e54afd217 | ||
![]() |
4e90fd3a06 | ||
![]() |
0463c6bb0f | ||
![]() |
f31f986d66 | ||
![]() |
c203c8302b | ||
![]() |
dea4a7b389 | ||
![]() |
0caf9b0706 | ||
![]() |
5f655c9fd7 | ||
![]() |
44aed53998 | ||
![]() |
f9ff621d4a | ||
![]() |
23a5a75778 | ||
![]() |
a78475844a | ||
![]() |
575cf2935e | ||
![]() |
ae43aa1bc0 | ||
![]() |
0ba71c6a47 | ||
![]() |
643f7d1803 | ||
![]() |
5d06da4db2 | ||
![]() |
2934b09361 | ||
![]() |
97341d3fa0 | ||
![]() |
a95546ede0 | ||
![]() |
7b44727b23 | ||
![]() |
debe648a98 | ||
![]() |
fda8cf77ed | ||
![]() |
8aaab195c6 | ||
![]() |
4096ddcbd0 | ||
![]() |
ae6cc11ad2 | ||
![]() |
dab7e527de | ||
![]() |
8b92feac71 | ||
![]() |
4beb3e5755 | ||
![]() |
55f63229cd | ||
![]() |
7827aeb695 | ||
![]() |
cce768aaac | ||
![]() |
80b83c0624 | ||
![]() |
73b683bb4d | ||
![]() |
d78a5c0863 | ||
![]() |
683e5b6abe | ||
![]() |
653b8f6352 | ||
![]() |
9ec6afa375 | ||
![]() |
adff5382ca | ||
![]() |
704aabd703 | ||
![]() |
f7b1ef0690 | ||
![]() |
929982117f | ||
![]() |
56a530d769 | ||
![]() |
7ef75fb06b | ||
![]() |
112a72abdf | ||
![]() |
71813e03ee | ||
![]() |
9b05b6ef28 | ||
![]() |
54a87b25b3 | ||
![]() |
55e97864bd | ||
![]() |
95733c9490 | ||
![]() |
e19ae644f1 | ||
![]() |
ac4ea25267 | ||
![]() |
611e4f34dc | ||
![]() |
faf017f333 | ||
![]() |
5eec896615 | ||
![]() |
17f35174ea | ||
![]() |
bf71b31123 | ||
![]() |
9399a44c82 | ||
![]() |
c96418806f | ||
![]() |
7945eddef6 | ||
![]() |
0ede390fef | ||
![]() |
85959a3b9b | ||
![]() |
946c3a25b9 | ||
![]() |
f9d697128a | ||
![]() |
532ef744f4 | ||
![]() |
27a961814b | ||
![]() |
5a5b65e9bf | ||
![]() |
96673ad610 | ||
![]() |
a9025aea0d | ||
![]() |
f38ab0b973 | ||
![]() |
150dac00cf | ||
![]() |
bcb1a9c5d3 | ||
![]() |
2e55aea584 | ||
![]() |
4f5a3f0df5 | ||
![]() |
e265b538cc | ||
![]() |
b186504718 | ||
![]() |
fc27890f13 | ||
![]() |
a583939767 | ||
![]() |
52e3bcfd29 | ||
![]() |
85d29a3f9d | ||
![]() |
18944d389d | ||
![]() |
e90ac5d6a4 | ||
![]() |
cb9a6ae774 | ||
![]() |
3ef09aa6b2 | ||
![]() |
4db22e45a2 | ||
![]() |
f966d0b32c | ||
![]() |
ba3879a95a | ||
![]() |
c6cef0162d | ||
![]() |
6d09aa86e9 | ||
![]() |
b711f0f9c6 | ||
![]() |
8fefb3a4c9 | ||
![]() |
400cdf0f26 | ||
![]() |
bce8c5a315 | ||
![]() |
f44dc2dd05 | ||
![]() |
df950d2fc5 | ||
![]() |
5e1f804dd1 | ||
![]() |
15de89f2f9 | ||
![]() |
df647a415c | ||
![]() |
fc66231f8e | ||
![]() |
71df3e1566 | ||
![]() |
168c22fc98 | ||
![]() |
792ec23d7a | ||
![]() |
ff625253ce | ||
![]() |
8c872c6b22 | ||
![]() |
541f5bc0a6 | ||
![]() |
77ff7b9df0 | ||
![]() |
203cc5075e | ||
![]() |
7abfcd06da | ||
![]() |
724f81c7f3 | ||
![]() |
4d2e98af7b | ||
![]() |
08221fdda7 | ||
![]() |
c0f72970b9 | ||
![]() |
18bc4a49e8 | ||
![]() |
f90b6dbed4 | ||
![]() |
d2d991ff34 | ||
![]() |
190a5e175b | ||
![]() |
a05f5a91b8 | ||
![]() |
4d02ff27be | ||
![]() |
df92b41d25 | ||
![]() |
075af96338 | ||
![]() |
64bbc55336 | ||
![]() |
06c621acc1 | ||
![]() |
d040dc19bc | ||
![]() |
a38ae4a402 | ||
![]() |
772063aade | ||
![]() |
31c26354c5 | ||
![]() |
64b331c5b2 | ||
![]() |
94f8a145ec | ||
![]() |
b357afa30a | ||
![]() |
fee0437493 | ||
![]() |
663b8864c1 | ||
![]() |
c6eafdde30 | ||
![]() |
f32ff95256 | ||
![]() |
0452b75c3e | ||
![]() |
97efd23ec8 | ||
![]() |
ea3e311528 | ||
![]() |
0565454419 | ||
![]() |
35c79c2f29 | ||
![]() |
e6089aec48 | ||
![]() |
dd3f7834c3 | ||
![]() |
f8cf18d880 | ||
![]() |
2ac7e242b6 | ||
![]() |
d8b604a94f | ||
![]() |
a1f7b00981 | ||
![]() |
b7ee42198c | ||
![]() |
d66e4b7ff9 | ||
![]() |
7f9789cf65 | ||
![]() |
b41c18e033 | ||
![]() |
3c73a7ec6d | ||
![]() |
182c09d952 | ||
![]() |
9fb86aed04 | ||
![]() |
b8f7b13b05 | ||
![]() |
1ee1d5b6d1 | ||
![]() |
154c38c314 | ||
![]() |
3c0626752a | ||
![]() |
511ef77fb7 | ||
![]() |
4df3ede500 | ||
![]() |
e83c080af8 | ||
![]() |
054220db70 | ||
![]() |
97bff010a8 | ||
![]() |
487a3079cd | ||
![]() |
2d5158c680 | ||
![]() |
837be06b72 | ||
![]() |
7e0d8dd4d7 | ||
![]() |
146fb23d7d | ||
![]() |
61455ffe29 | ||
![]() |
c267baafdc | ||
![]() |
42248a306a | ||
![]() |
694ec7ebe1 | ||
![]() |
e3b3f8fac1 | ||
![]() |
b390363b25 | ||
![]() |
f6f8cdbcf2 | ||
![]() |
f46f53b8a3 | ||
![]() |
a2fcae4383 | ||
![]() |
483f043768 | ||
![]() |
f8e0f4f21f | ||
![]() |
9c3613e96d | ||
![]() |
d9cacdc86d | ||
![]() |
aa3d2deeaa | ||
![]() |
e64912545a | ||
![]() |
b247be80cc | ||
![]() |
343f2f1f33 | ||
![]() |
2d590df900 | ||
![]() |
ba56b2b9fd | ||
![]() |
bf472b0c5e | ||
![]() |
f7961f34c5 | ||
![]() |
e369031a28 | ||
![]() |
186d7bbfd9 | ||
![]() |
60a11f8da5 | ||
![]() |
1181fcdceb | ||
![]() |
8cb9852058 | ||
![]() |
53d46d1cbe | ||
![]() |
275e1c8de9 | ||
![]() |
d46eca4c87 | ||
![]() |
2927fb1597 | ||
![]() |
8c72e011d2 | ||
![]() |
69662e24c3 | ||
![]() |
96099ffe98 | ||
![]() |
ae16b45c11 | ||
![]() |
cfee87d3ef | ||
![]() |
5fcf5bc635 | ||
![]() |
14bcb813cc | ||
![]() |
6af19794b6 | ||
![]() |
8316186695 | ||
![]() |
85d3023cd5 | ||
![]() |
78414dee29 | ||
![]() |
084135141f | ||
![]() |
467a21f028 | ||
![]() |
6e284c44d6 | ||
![]() |
daf9a449e8 | ||
![]() |
960268fd33 | ||
![]() |
8c331da315 | ||
![]() |
b0d626d862 | ||
![]() |
a51fbd7316 | ||
![]() |
063f372f3c | ||
![]() |
987168b863 | ||
![]() |
4ee40c3345 | ||
![]() |
654daff7ce | ||
![]() |
64e10e9619 | ||
![]() |
b89cffe98d | ||
![]() |
bd76ba702f | ||
![]() |
5d52e9ce6b | ||
![]() |
3c29027ca3 | ||
![]() |
2ff3069d23 | ||
![]() |
4198246351 | ||
![]() |
2b6389b4dc | ||
![]() |
d7df75ae6c | ||
![]() |
11c30eccb3 | ||
![]() |
ab8c6515b8 | ||
![]() |
d4ad36fa41 | ||
![]() |
4d688be3df | ||
![]() |
d2b75f3501 | ||
![]() |
46b78cb4ff | ||
![]() |
5d6e0d0f37 | ||
![]() |
e19d0a37bb | ||
![]() |
dea3e2132e | ||
![]() |
91c1ceefbd | ||
![]() |
5c50989970 | ||
![]() |
2a7e3b9c51 | ||
![]() |
ab302df0ae | ||
![]() |
21e5809993 | ||
![]() |
c58afc67e8 | ||
![]() |
8e344f2deb | ||
![]() |
c28f4ffb3f | ||
![]() |
2a40240310 | ||
![]() |
0e9fba9287 | ||
![]() |
2e3dd2a30a | ||
![]() |
dda5f6559d | ||
![]() |
4152e59638 | ||
![]() |
9d5a92bce6 | ||
![]() |
30172b92e6 | ||
![]() |
8468a9d4c7 | ||
![]() |
626cfb61ac | ||
![]() |
9603f3fa4f | ||
![]() |
619a1b9e53 | ||
![]() |
62e76ad588 | ||
![]() |
236d72685d | ||
![]() |
72a5f7b1e2 | ||
![]() |
d1c16a90b4 | ||
![]() |
33a9783ae5 | ||
![]() |
4d64fd665e | ||
![]() |
96443384fe | ||
![]() |
69939f1edb | ||
![]() |
e3c0058942 | ||
![]() |
3dc2361654 | ||
![]() |
ec2f709018 | ||
![]() |
ea06665c51 | ||
![]() |
83b7010d6a | ||
![]() |
71654cbe47 | ||
![]() |
e8f96e848a | ||
![]() |
251abf21d4 | ||
![]() |
d103427932 | ||
![]() |
74a4bd704c | ||
![]() |
c62f3e0e45 | ||
![]() |
a56a969433 | ||
![]() |
1016f94bbb | ||
![]() |
e98cce9aee | ||
![]() |
d4bdb5d327 | ||
![]() |
db4378415e | ||
![]() |
9b594880c8 | ||
![]() |
d44fc3db2f | ||
![]() |
5133b0a0c0 | ||
![]() |
815469304f | ||
![]() |
c651921c79 | ||
![]() |
d18c835221 | ||
![]() |
e38335077e | ||
![]() |
34c150cf73 | ||
![]() |
24cb3ba091 | ||
![]() |
c07eaef2d1 | ||
![]() |
5df708ac9f | ||
![]() |
38ffbe95e9 | ||
![]() |
8bec4042fc | ||
![]() |
ee7ef89dfb | ||
![]() |
54a5246061 | ||
![]() |
fa6eae2937 | ||
![]() |
795be20ee1 | ||
![]() |
87d3a06dcd | ||
![]() |
8b5c917195 | ||
![]() |
c7da0e59ff | ||
![]() |
eb14acbe0c | ||
![]() |
56860a6bef | ||
![]() |
735687be21 | ||
![]() |
592cdfa910 | ||
![]() |
f2ad1a0406 | ||
![]() |
fab0cc51b3 | ||
![]() |
3a26acbdb2 | ||
![]() |
8d0c31bcda | ||
![]() |
0b99293d4c | ||
![]() |
802153ff9b | ||
![]() |
ec73e2d237 | ||
![]() |
c32b020535 | ||
![]() |
c4441804e2 | ||
![]() |
6c9d80d4e8 | ||
![]() |
a231f8d26c | ||
![]() |
82af9320c0 | ||
![]() |
fceebf7388 | ||
![]() |
08da258b63 | ||
![]() |
5994926440 | ||
![]() |
30f2da4215 | ||
![]() |
1a2229f886 | ||
![]() |
1e166490d9 | ||
![]() |
1c57e6f80a | ||
![]() |
a6537a8748 | ||
![]() |
842b75977b | ||
![]() |
9b3dccf60c | ||
![]() |
2d533e0cd8 | ||
![]() |
9e1925c808 | ||
![]() |
142d59be85 | ||
![]() |
d9a5e06b5b | ||
![]() |
b6889e9ac6 | ||
![]() |
dc82203e9b | ||
![]() |
6a30d32e7d | ||
![]() |
d9780606b3 | ||
![]() |
fffa32df48 | ||
![]() |
cad49892d3 | ||
![]() |
f0a29721c9 | ||
![]() |
13caf37991 | ||
![]() |
b71a602107 | ||
![]() |
e6ce0dd43a | ||
![]() |
094a5214f1 | ||
![]() |
0932fcd114 | ||
![]() |
f26643cea3 | ||
![]() |
63b1689155 | ||
![]() |
59dc929431 | ||
![]() |
deaadc33db | ||
![]() |
0ba92a4f29 | ||
![]() |
7dc5009ec7 | ||
![]() |
0ee827afd3 | ||
![]() |
551d1b7f86 | ||
![]() |
7ed1b695f5 | ||
![]() |
7ad31b9b33 | ||
![]() |
edd8992f7f | ||
![]() |
96fe42cfcb | ||
![]() |
c3872b4a38 | ||
![]() |
762945113d | ||
![]() |
037e9230fc | ||
![]() |
3f59ebf986 | ||
![]() |
e51e1d2b09 | ||
![]() |
26cc49eb69 | ||
![]() |
7987bb491c | ||
![]() |
16b7ac5a87 | ||
![]() |
5932cb8609 | ||
![]() |
dfe694d39f | ||
![]() |
278624f2c8 | ||
![]() |
899f42c070 | ||
![]() |
8ce1d4d6a3 | ||
![]() |
52225d703b | ||
![]() |
81739af7cb | ||
![]() |
25473222cc | ||
![]() |
0b7be70935 | ||
![]() |
818b71abd6 | ||
![]() |
25575e8510 | ||
![]() |
6c85adcf23 | ||
![]() |
5dc92d7a40 | ||
![]() |
4e2b966b80 | ||
![]() |
d34f8c3cb9 | ||
![]() |
9049ecb1cf | ||
![]() |
7bebea087c | ||
![]() |
1c79e30436 | ||
![]() |
1d7933349b | ||
![]() |
d002f67140 | ||
![]() |
da3447765b | ||
![]() |
cbf5663179 | ||
![]() |
b217fba235 | ||
![]() |
7f7e6d5aba | ||
![]() |
87c5a9d9a6 | ||
![]() |
8ca1fe3f0a | ||
![]() |
763ae8f1a6 | ||
![]() |
c65256d02b | ||
![]() |
bd2ac515d1 | ||
![]() |
681f372889 | ||
![]() |
c2eec272e6 | ||
![]() |
bd720491a9 | ||
![]() |
a408226509 | ||
![]() |
c015e99e6e | ||
![]() |
de47a17be7 | ||
![]() |
d38fc490ad | ||
![]() |
662167e792 | ||
![]() |
36c91f03d9 | ||
![]() |
33ccee26b5 | ||
![]() |
ed5cb991e3 | ||
![]() |
bea84ec2bf | ||
![]() |
08c176e549 | ||
![]() |
810ed50976 | ||
![]() |
2684541693 | ||
![]() |
a5b12bac54 | ||
![]() |
fea1b06e43 | ||
![]() |
182ca5d434 | ||
![]() |
facde9a75d | ||
![]() |
41385640b9 | ||
![]() |
7bad9db32e | ||
![]() |
af66f0a497 | ||
![]() |
95e1b80f41 | ||
![]() |
556e2eba95 | ||
![]() |
efe530cb17 | ||
![]() |
34e7c99283 | ||
![]() |
4157ea8bc3 | ||
![]() |
550517bbf3 | ||
![]() |
eb910cd8a1 | ||
![]() |
75131c4e8a | ||
![]() |
ee29ab95be | ||
![]() |
e97951fc51 | ||
![]() |
dfabdef60f | ||
![]() |
5a87763193 | ||
![]() |
6bb90f56fa | ||
![]() |
c883ae1350 | ||
![]() |
09e25e6a02 | ||
![]() |
bf5d43054b | ||
![]() |
63b3c65691 | ||
![]() |
f193da7f67 | ||
![]() |
40f38c2c0a | ||
![]() |
db439ef804 | ||
![]() |
56eb896a03 | ||
![]() |
68d43e43b6 | ||
![]() |
c60517e49a | ||
![]() |
3f59d261f2 | ||
![]() |
4068d220e5 | ||
![]() |
18968e7208 | ||
![]() |
38656103c0 | ||
![]() |
0f65b1bcc5 | ||
![]() |
a628821834 | ||
![]() |
6ceff60c1e | ||
![]() |
d762a6ce58 | ||
![]() |
75a8037a46 | ||
![]() |
1179920790 | ||
![]() |
b323a160e3 | ||
![]() |
b157e9535e | ||
![]() |
7668475bd6 | ||
![]() |
8bda2a1fb7 | ||
![]() |
b092086b5b | ||
![]() |
69a0d9034f | ||
![]() |
f5be8fd313 | ||
![]() |
7f835d7f76 | ||
![]() |
ddbb7c5993 | ||
![]() |
00a3fe39e8 | ||
![]() |
7537fb88d4 | ||
![]() |
a81bc71a1e | ||
![]() |
0a0aa0e2db | ||
![]() |
c56b94ae96 | ||
![]() |
e90712706d | ||
![]() |
eb0623331f | ||
![]() |
d15bd59109 | ||
![]() |
60e0b19372 | ||
![]() |
922eb937ff | ||
![]() |
87573284f1 | ||
![]() |
a91c585f55 | ||
![]() |
953ea21d5e | ||
![]() |
ecb00968bc | ||
![]() |
50ad8adb2d | ||
![]() |
16878caf09 | ||
![]() |
5bc30c5493 | ||
![]() |
85d89cf4c4 | ||
![]() |
db693f598b | ||
![]() |
0494c770a1 | ||
![]() |
c473b62aed | ||
![]() |
f19ac5320e | ||
![]() |
612e3aafbc | ||
![]() |
0e97fec451 | ||
![]() |
e8c8626ee4 | ||
![]() |
d89e0f07f8 | ||
![]() |
e7f81a42ce | ||
![]() |
ac614148b8 | ||
![]() |
5eb02b4901 | ||
![]() |
65631525f6 | ||
![]() |
969435cfe9 | ||
![]() |
c932f7a25b | ||
![]() |
42d164dc57 | ||
![]() |
a7e60f80bd | ||
![]() |
3dd5f313b7 | ||
![]() |
883962c393 | ||
![]() |
8a30ff1c76 | ||
![]() |
e47c354916 | ||
![]() |
496f42805d | ||
![]() |
c3d34bda37 | ||
![]() |
bb6ede2b8f | ||
![]() |
822400a1ba | ||
![]() |
e3e08843f1 | ||
![]() |
ce0d4f77fa | ||
![]() |
94fdb4e974 | ||
![]() |
4d425fc8a4 | ||
![]() |
c6cdfa2f5a | ||
![]() |
0fff2e4f16 | ||
![]() |
80a2172715 | ||
![]() |
5a0a297634 | ||
![]() |
948a133b7b | ||
![]() |
2ee826c958 | ||
![]() |
539409faf8 | ||
![]() |
606e46e4d7 | ||
![]() |
a179cfd69a | ||
![]() |
d8379253d4 | ||
![]() |
c3344fbd68 | ||
![]() |
4cebd6e84a | ||
![]() |
90fbf9dbb0 | ||
![]() |
d365b9f634 | ||
![]() |
a2f06acaa4 | ||
![]() |
8c90cbcbfb | ||
![]() |
a4a47772dc | ||
![]() |
5dde1f4602 | ||
![]() |
9dc0909eeb | ||
![]() |
0ed2592e41 | ||
![]() |
76cff98220 | ||
![]() |
60604b6f51 | ||
![]() |
f410b7aecb | ||
![]() |
1a61f2cee9 | ||
![]() |
78a8293520 | ||
![]() |
03cfb4fc8d | ||
![]() |
144345a359 | ||
![]() |
fd2c01515e | ||
![]() |
219570e08b | ||
![]() |
69df556ff5 | ||
![]() |
5f4a52574f | ||
![]() |
5a1f6c5839 | ||
![]() |
91d0342fe8 | ||
![]() |
8cc236daf8 | ||
![]() |
d283ec69f7 | ||
![]() |
d1aea7596c | ||
![]() |
c934987b14 | ||
![]() |
00c9f4a2e5 | ||
![]() |
6605c1d07f | ||
![]() |
7325d66c52 | ||
![]() |
a485061e22 | ||
![]() |
1f63f50343 | ||
![]() |
cd3170dabd | ||
![]() |
841cedc5f8 | ||
![]() |
7f4882734d | ||
![]() |
e7d647d412 | ||
![]() |
913d14a58a | ||
![]() |
909272ec3d | ||
![]() |
7af40ffbbe | ||
![]() |
9df79a3ec9 | ||
![]() |
4f2eee06aa | ||
![]() |
1b9cf76008 | ||
![]() |
d035a43ed6 | ||
![]() |
95ee9a6e09 | ||
![]() |
02a63cdcb3 | ||
![]() |
f02125dd47 | ||
![]() |
c11e813146 | ||
![]() |
a365849048 | ||
![]() |
a493c9f769 | ||
![]() |
a13f522b2a | ||
![]() |
1ed70b2e2c | ||
![]() |
86d5a599b7 | ||
![]() |
c226fc8d63 | ||
![]() |
bbf4e1c413 | ||
![]() |
a24a20a83d | ||
![]() |
725600da8f | ||
![]() |
f74a32ed9b | ||
![]() |
e08e72dd10 | ||
![]() |
ce02e1e528 | ||
![]() |
0b27d8a717 | ||
![]() |
2782e7d26f | ||
![]() |
2c83a05e80 | ||
![]() |
467f68502a | ||
![]() |
d95b0dee6b | ||
![]() |
a1f3323fa5 | ||
![]() |
494796a7f0 | ||
![]() |
94f2c20d35 | ||
![]() |
c1deb9438d | ||
![]() |
ea86527c66 | ||
![]() |
d1a18fe266 | ||
![]() |
737064da82 | ||
![]() |
606cc85ff5 | ||
![]() |
dcfc8f1b30 | ||
![]() |
ebe4b84f14 | ||
![]() |
699d4897db | ||
![]() |
fcdfd8d323 | ||
![]() |
db8625c31a | ||
![]() |
b65f265c55 | ||
![]() |
c55237d09c | ||
![]() |
ed698b7b82 | ||
![]() |
d4ff19f013 | ||
![]() |
972fb8eb40 | ||
![]() |
4de75448b6 | ||
![]() |
e8ef8f0004 | ||
![]() |
a319b30382 | ||
![]() |
8278616eeb | ||
![]() |
771f011506 | ||
![]() |
826865869a | ||
![]() |
3c77ae7b62 | ||
![]() |
60c30ece10 | ||
![]() |
76a0d0fee9 | ||
![]() |
d50624f0a0 |
@@ -5,12 +5,6 @@ executors:
|
||||
working_directory: /tmp/workspace
|
||||
docker:
|
||||
- image: misskey/ci:latest
|
||||
- image: circleci/mongo:latest
|
||||
with-redis:
|
||||
working_directory: /tmp/workspace
|
||||
docker:
|
||||
- image: misskey/ci:latest
|
||||
- image: circleci/mongo:latest
|
||||
- image: circleci/redis:latest
|
||||
docker:
|
||||
working_directory: /tmp/workspace
|
||||
@@ -62,22 +56,10 @@ jobs:
|
||||
executor:
|
||||
type: string
|
||||
default: "default"
|
||||
without_redis:
|
||||
type: boolean
|
||||
default: false
|
||||
executor: <<parameters.executor>>
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- when:
|
||||
condition: <<parameters.without_redis>>
|
||||
steps:
|
||||
- run:
|
||||
name: Configure
|
||||
command: |
|
||||
mv .config/test.yml .config/test_redis.yml
|
||||
touch .config/test.yml
|
||||
cat .config/test_redis.yml | while IFS= read line; do if [[ "$line" = '# __REDIS__' ]]; then break; else echo "$line" >> .config/test.yml; fi; done
|
||||
- run:
|
||||
name: Test
|
||||
command: |
|
||||
@@ -140,32 +122,14 @@ workflows:
|
||||
branches:
|
||||
only: master
|
||||
- test:
|
||||
name: manual-test-with-redis
|
||||
executor: with-redis
|
||||
name: manual-test
|
||||
requires:
|
||||
- manual-build
|
||||
filters:
|
||||
branches:
|
||||
ignore: master
|
||||
- test:
|
||||
name: auto-test-without-redis
|
||||
executor: with-redis
|
||||
requires:
|
||||
- auto-build
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- test:
|
||||
name: manual-test-with-redis
|
||||
without_redis: true
|
||||
requires:
|
||||
- manual-build
|
||||
filters:
|
||||
branches:
|
||||
ignore: master
|
||||
- test:
|
||||
name: auto-test-without-redis
|
||||
without_redis: true
|
||||
name: auto-test
|
||||
requires:
|
||||
- auto-build
|
||||
filters:
|
||||
|
4
.config/docker_example.env
Normal file
4
.config/docker_example.env
Normal file
@@ -0,0 +1,4 @@
|
||||
# db settings
|
||||
POSTGRES_PASSWORD=example-misskey-pass
|
||||
POSTGRES_USER=example-misskey-user
|
||||
POSTGRES_DB=misskey
|
@@ -1,8 +1,16 @@
|
||||
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
# Misskey configuration
|
||||
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
# ┌─────┐
|
||||
#───┘ URL └─────────────────────────────────────────────────────
|
||||
|
||||
# Final accessible URL seen by a user.
|
||||
url: https://example.tld/
|
||||
|
||||
# ┌───────────────────────┐
|
||||
#───┘ Port and TLS settings └───────────────────────────────────
|
||||
|
||||
### Port and TLS settings ######################################
|
||||
#
|
||||
# Misskey supports two deployment options for public.
|
||||
#
|
||||
@@ -30,28 +38,51 @@ url: https://example.tld/
|
||||
# You need to set Certificate in 'https' section.
|
||||
|
||||
# To use option 1, uncomment below line.
|
||||
# port: 3000 # A port that your Misskey server should listen.
|
||||
#port: 3000 # A port that your Misskey server should listen.
|
||||
|
||||
# To use option 2, uncomment below lines.
|
||||
# port: 443
|
||||
#
|
||||
# https:
|
||||
# # path for certification
|
||||
# key: /etc/letsencrypt/live/example.tld/privkey.pem
|
||||
# cert: /etc/letsencrypt/live/example.tld/fullchain.pem
|
||||
#port: 443
|
||||
|
||||
################################################################
|
||||
#https:
|
||||
# # path for certification
|
||||
# key: /etc/letsencrypt/live/example.tld/privkey.pem
|
||||
# cert: /etc/letsencrypt/live/example.tld/fullchain.pem
|
||||
|
||||
# ┌──────────────────────────┐
|
||||
#───┘ PostgreSQL configuration └────────────────────────────────
|
||||
|
||||
mongodb:
|
||||
db:
|
||||
host: localhost
|
||||
port: 27017
|
||||
port: 5432
|
||||
|
||||
# Database name
|
||||
db: misskey
|
||||
|
||||
# Auth
|
||||
user: example-misskey-user
|
||||
pass: example-misskey-pass
|
||||
|
||||
# ┌─────────────────────┐
|
||||
#───┘ Redis configuration └─────────────────────────────────────
|
||||
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
#pass: example-pass
|
||||
|
||||
# ┌─────────────────────────────┐
|
||||
#───┘ Elasticsearch configuration └─────────────────────────────
|
||||
|
||||
#elasticsearch:
|
||||
# host: localhost
|
||||
# port: 9200
|
||||
# pass: null
|
||||
|
||||
# ┌────────────────────────────────────┐
|
||||
#───┘ File storage (Drive) configuration └──────────────────────
|
||||
|
||||
drive:
|
||||
storage: 'db'
|
||||
storage: 'fs'
|
||||
|
||||
# OR
|
||||
|
||||
@@ -88,26 +119,28 @@ drive:
|
||||
# accessKey: XXX
|
||||
# secretKey: YYY
|
||||
|
||||
# ┌───────────────┐
|
||||
#───┘ ID generation └───────────────────────────────────────────
|
||||
|
||||
# You can select the ID generation method.
|
||||
# You don't usually need to change this setting, but you can
|
||||
# change it according to your preferences.
|
||||
|
||||
# Available methods:
|
||||
# aid ... Short, Millisecond accuracy
|
||||
# meid ... Similar to ObjectID, Millisecond accuracy
|
||||
# ulid ... Millisecond accuracy
|
||||
# objectid ... This is left for backward compatibility
|
||||
|
||||
id: 'aid'
|
||||
|
||||
# ┌─────────────────────┐
|
||||
#───┘ Other configuration └─────────────────────────────────────
|
||||
|
||||
# If enabled:
|
||||
# The first account created is automatically marked as Admin.
|
||||
autoAdmin: true
|
||||
|
||||
#
|
||||
# Below settings are optional
|
||||
#
|
||||
|
||||
# Redis
|
||||
#redis:
|
||||
# host: localhost
|
||||
# port: 6379
|
||||
# pass: example-pass
|
||||
|
||||
# Elasticsearch
|
||||
#elasticsearch:
|
||||
# host: localhost
|
||||
# port: 9200
|
||||
# pass: null
|
||||
|
||||
# Whether disable HSTS
|
||||
#disableHsts: true
|
||||
|
||||
|
@@ -1,13 +0,0 @@
|
||||
var user = {
|
||||
user: 'example-misskey-user',
|
||||
pwd: 'example-misskey-pass',
|
||||
roles: [
|
||||
{
|
||||
role: 'readWrite',
|
||||
db: 'misskey'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
db.createUser(user);
|
||||
|
6
.dockerignore
Executable file → Normal file
6
.dockerignore
Executable file → Normal file
@@ -5,8 +5,8 @@
|
||||
.vscode
|
||||
Dockerfile
|
||||
build/
|
||||
db/
|
||||
docker-compose.yml
|
||||
node_modules/
|
||||
mongo/
|
||||
redis/
|
||||
elasticsearch/
|
||||
node_modules/
|
||||
redis/
|
||||
|
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
@@ -1,7 +1,7 @@
|
||||
# PATH OWNERS
|
||||
/.autogen/ @acid-chicken
|
||||
/.circleci/ @syuilo @acid-chicken
|
||||
/.config/ @syuilo @AyaMorisawa @mei23 @acid-chicken
|
||||
/.config/ @syuilo @AyaMorisawa @mei23 @acid-chicken @rinsuki
|
||||
# /.config/mongo_initdb_example.js @khws4v1
|
||||
/.github/ @syuilo @AyaMorisawa @acid-chicken
|
||||
/.vscode/ @acid-chicken
|
||||
@@ -12,7 +12,7 @@
|
||||
# /docs/*.fr.md @BoFFire
|
||||
# /docs/docker.*.md @khws4v1
|
||||
/locales/ @syuilo
|
||||
/src/ @syuilo @AyaMorisawa @mei23 @acid-chicken
|
||||
/src/ @syuilo @AyaMorisawa @mei23 @acid-chicken @rinsuki
|
||||
# /src/crypto_key.cc @akihikodaki
|
||||
# /src/crypto_key.d.ts @akihikodaki
|
||||
/.dockerignore @syuilo # @khws4v1
|
||||
|
14
.github/ISSUE_TEMPLATE/01_bug-report.md
vendored
14
.github/ISSUE_TEMPLATE/01_bug-report.md
vendored
@@ -1,30 +1,30 @@
|
||||
---
|
||||
name: Bug Report
|
||||
name: 🐛 Bug Report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
labels: ⚠️bug?
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Summary
|
||||
## 💡 Summary
|
||||
|
||||
<!-- Tell us what the bug is -->
|
||||
|
||||
# Expected Behavior
|
||||
## 🙂 Expected Behavior
|
||||
|
||||
<!--- Tell us what should happen -->
|
||||
|
||||
# Actual Behavior
|
||||
## ☹️ Actual Behavior
|
||||
|
||||
<!--- Tell us what happens instead of the expected behavior -->
|
||||
|
||||
# Steps to Reproduce
|
||||
## 📝 Steps to Reproduce
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
# Environment
|
||||
## 📌 Environment
|
||||
|
||||
<!-- Tell us where on the platform it happens -->
|
||||
|
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: Client-side Bug Report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug, client-side
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Summary
|
||||
|
||||
<!-- Tell us what the bug is -->
|
||||
|
||||
# Expected Behavior
|
||||
|
||||
<!--- Tell us what should happen -->
|
||||
|
||||
# Actual Behavior
|
||||
|
||||
<!--- Tell us what happens instead of the expected behavior -->
|
||||
|
||||
# Steps to Reproduce
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
# Environment
|
||||
|
||||
<!-- Tell us where on the platform it happens -->
|
||||
<!-- e.g. desktop or mobile version, your browser, your OS -->
|
@@ -1,12 +1,12 @@
|
||||
---
|
||||
name: Feature Request
|
||||
name: ✨ Feature Request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: feature
|
||||
labels: ✨Feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Summary
|
||||
## Summary
|
||||
|
||||
<!-- Tell us what the suggestion is -->
|
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: Server-side Bug Report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug, server-side
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Summary
|
||||
|
||||
<!-- Tell us what the bug is -->
|
||||
|
||||
# Expected Behavior
|
||||
|
||||
<!--- Tell us what should happen -->
|
||||
|
||||
# Actual Behavior
|
||||
|
||||
<!--- Tell us what happens instead of the expected behavior -->
|
||||
|
||||
# Steps to Reproduce
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
# Environment
|
||||
|
||||
<!-- Tell us where on the platform it happens -->
|
||||
<!-- e.g. your Node.js version, your OS -->
|
@@ -1,12 +0,0 @@
|
||||
---
|
||||
name: Client-side Feature Request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: client-side, feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Summary
|
||||
|
||||
<!-- Tell us what the suggestion is -->
|
@@ -1,12 +0,0 @@
|
||||
---
|
||||
name: Server-side Feature Request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: feature, server-side
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Summary
|
||||
|
||||
<!-- Tell us what the suggestion is -->
|
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,4 +1,4 @@
|
||||
# Summary
|
||||
## Summary
|
||||
|
||||
<!--
|
||||
-
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -8,14 +8,15 @@
|
||||
built
|
||||
/data
|
||||
/.cache-loader
|
||||
/db
|
||||
/elasticsearch
|
||||
npm-debug.log
|
||||
*.pem
|
||||
run.bat
|
||||
api-docs.json
|
||||
*.log
|
||||
/redis
|
||||
/mongo
|
||||
/elasticsearch
|
||||
*.code-workspace
|
||||
yarn.lock
|
||||
.DS_Store
|
||||
/files
|
||||
|
353
CHANGELOG.md
353
CHANGELOG.md
@@ -1,6 +1,359 @@
|
||||
ChangeLog
|
||||
=========
|
||||
|
||||
If you encounter any problems with updating, please try the following:
|
||||
1. `npm run clean` or `npm run cleanall`
|
||||
2. Retry update (Don't forget `npm i`)
|
||||
|
||||
How to migrate to v11 from v10
|
||||
------------------------------
|
||||
1. v11をインストールしたい場所に syuilo/misskey をクローン
|
||||
2. config を設定する
|
||||
* PostgreSQL(`db`)の設定とは別に、v10からMongoDBの設定をコピペしてくる(例は下にあります)
|
||||
* `id`の設定を`meid`または`objectid`にする
|
||||
|
||||
``` yml
|
||||
db:
|
||||
host: localhost
|
||||
port: 5432
|
||||
db: misskey
|
||||
user: x
|
||||
pass: x
|
||||
|
||||
mongodb:
|
||||
user: x
|
||||
pass: x
|
||||
host: localhost
|
||||
port: 27017
|
||||
db: misskey
|
||||
```
|
||||
3. migration ブランチに切り替え
|
||||
4. `npm i`
|
||||
5. `npm run build`
|
||||
6. `npm run init`
|
||||
7. `npm run migrate`
|
||||
8. master ブランチに戻す
|
||||
9. enjoy
|
||||
|
||||
11.4.0 (2019/04/25)
|
||||
-------------------
|
||||
### Improvements
|
||||
* 検索でローカルの投稿のみに絞れるように
|
||||
* 検索で特定のインスタンスの投稿のみに絞れるように
|
||||
* 検索で特定のユーザーの投稿のみに絞れるように
|
||||
|
||||
### Fixes
|
||||
* 投稿が増殖する問題を修正
|
||||
* ストリームで過去の投稿が流れてくる問題を修正
|
||||
* モバイル版のユーザーページで遷移してもユーザー名が変わらない問題を修正
|
||||
* お知らせを切り替えても内容が変わらない問題を修正
|
||||
|
||||
11.3.1 (2019/04/24)
|
||||
-------------------
|
||||
### Fixes
|
||||
* Webからファイルがアップロードできない問題を修正
|
||||
|
||||
11.3.0 (2019/04/24)
|
||||
-------------------
|
||||
### Improvements
|
||||
* お知らせにMFMを使えるように
|
||||
* お知らせに画像を添付できるように
|
||||
|
||||
### Fixes
|
||||
* 投稿のタグ検索APIで大文字小文字が区別されていたのを修正
|
||||
* 公開範囲がホームの投稿がグローバルTLに流れる問題を修正
|
||||
* モバイルビューの投稿詳細にて acct が長いとアイコンが圧迫面接される問題を修正
|
||||
|
||||
11.2.2 (2019/04/22)
|
||||
-------------------
|
||||
### Fixes
|
||||
* 2段階認証を有効にするとログインできない問題を修正
|
||||
* リモートユーザーの修復処理が自動的に実行されない問題を修正
|
||||
* リモートユーザー情報が更新されない問題を修正
|
||||
|
||||
11.2.1 (2019/04/21)
|
||||
-------------------
|
||||
### Fixes
|
||||
* MEIDが25桁になっているのを修正
|
||||
* リモートユーザー情報が更新されない問題を修正
|
||||
|
||||
11.2.0 (2019/04/18)
|
||||
-------------------
|
||||
### Improvements
|
||||
* 検索で日付(日時)を入力するとタイムラインをその時点まで遡るように
|
||||
* APIコンソールでエンドポイントをサジェストするように
|
||||
* モバイル版でドライブのメニューを使いやすく
|
||||
* サイレンス時に確認を表示するように
|
||||
* ユーザーメニューでブロックなどの操作を行う時に確認するように
|
||||
|
||||
### Fixes
|
||||
* アプリケーション連携画面でパーミッションが表示されない問題を修正
|
||||
* アンケートウィジットでもMFMを使用するように
|
||||
* フォローしてないユーザーのホーム投稿がSTLに流れてくる問題を修正
|
||||
* モバイル版でウィジェットを設定できない問題を修正
|
||||
* スプラッシュがクリックに反応するように
|
||||
|
||||
11.1.6 (2019/04/18)
|
||||
-------------------
|
||||
### Fixes
|
||||
* 未認知ユーザーからActivityが飛んできた場合に処理できない問題を修正
|
||||
* その投稿を見たのにも関わらずメンションインジケーターが点灯し続ける問題を修正
|
||||
* ハッシュタグの判定を改善
|
||||
* サーバーのエラーハンドリングを改善
|
||||
|
||||
11.1.5 (2019/04/17)
|
||||
-------------------
|
||||
### Fixes
|
||||
* ユーザー名に含まれているカスタム絵文字が表示されないことがある問題を修正
|
||||
* 壁紙の設定ができない問題を修正
|
||||
* デザインの調整
|
||||
|
||||
11.1.4 (2019/04/17)
|
||||
-------------------
|
||||
### Fixes
|
||||
* タイムライン取得時に削除されたファイルを添付している投稿が含まれているとサーバーでエラーになる問題を修正
|
||||
* 管理画面のインスタンスメニューで変更前の設定が読み込まれないことがある問題を修正
|
||||
* 猫ではないのに猫のままで表示される問題を修正
|
||||
* admin/driveのアイコンがずれてる問題を修正
|
||||
* チャートで大きな数値を扱えない問題を修正
|
||||
* UIの修正
|
||||
|
||||
11.1.3 (2019/04/16)
|
||||
-------------------
|
||||
### Fixes
|
||||
* アプリからAPIにリクエストするときにランダムなユーザーがリクエストしたことになる問題を修正
|
||||
|
||||
11.1.2 (2019/04/15)
|
||||
-------------------
|
||||
### Fixes
|
||||
* 画像描画の依存関係を変更
|
||||
* リモートユーザーのファイルを削除するときに古い方からではなく新しい方から削除されるのを修正
|
||||
* リアクションしてないのにリアクションしたことになる問題を修正
|
||||
* APIドキュメントの修正
|
||||
|
||||
11.1.1 (2019/04/15)
|
||||
-------------------
|
||||
### Fixes
|
||||
* Metaタグの application-name を Misskey で固定するように修正
|
||||
* トークメッセージが既読にならない問題を修正
|
||||
* デフォルトでHTLを表示するように
|
||||
|
||||
11.1.0 (2019/04/15)
|
||||
-------------------
|
||||
### Improvements
|
||||
* アイコン未設定時にランダムな画像を表示するように
|
||||
* 管理者やモデレーターはレートリミット無効に
|
||||
|
||||
### Fixes
|
||||
* メンションの「あなた」インジケーターが表示されない問題を修正
|
||||
* ブロックAPIでエラーが発生する問題を修正
|
||||
* プッシュ通知の購読に失敗する問題を修正
|
||||
|
||||
11.0.3 (2019/04/15)
|
||||
-------------------
|
||||
### Fixes
|
||||
* ハッシュタグ検索APIが動作しない問題を修正
|
||||
* モデレーターなのにアカウントメニューに「管理」が表示されない問題を修正
|
||||
* プッシュ通知の購読に失敗する問題を修正
|
||||
* ユーザー取得APIでユーザーを指定しない場合エラーになる問題を修正
|
||||
|
||||
11.0.2 (2019/04/15)
|
||||
-------------------
|
||||
### Fixes
|
||||
* アプリが作成できない問題を修正
|
||||
* 「ハイライト」が表示されない問題を修正
|
||||
* リモートの投稿に添付されている画像が小さい問題を修正
|
||||
* モバイル版でリストの名前が表示されない問題を修正
|
||||
* APIドキュメントにパーミッション一覧を追加
|
||||
|
||||
11.0.1 (2019/04/15)
|
||||
-------------------
|
||||
### Improvements
|
||||
* 不要な依存関係を削除
|
||||
|
||||
11.0.0 daybreak (2019/04/14)
|
||||
----------------------------
|
||||
### Improvements
|
||||
* **データベースがMongoDBからPostgreSQLに変更されました**
|
||||
* **Redisが必須に**
|
||||
* アカウントを完全に削除できるように
|
||||
* 投稿フォームで添付ファイルの閲覧注意を確認/設定できるように
|
||||
* ミュート/ブロック時にそのユーザーの投稿のウォッチをすべて解除するように
|
||||
|
||||
### Fixes
|
||||
* フォロー申請数が実際より1すくなくなる問題を修正
|
||||
* リストからアカウント削除したユーザーを削除できない問題を修正
|
||||
* リストTLでフォローしていないユーザーの非公開投稿が流れる問題を修正
|
||||
* リストTLでダイレクト投稿が流れない問題を修正
|
||||
* ミュートしているユーザーの投稿がタイムラインに流れてくることがある問題を修正
|
||||
|
||||
### APIの破壊的変更
|
||||
* v10時点で deprecated だったパラメータなどを削除
|
||||
* ユーザーリストの title が name に
|
||||
* リバーシの対局の`settings`プロパティがなくなり、その中にあったプロパティがすべて上の階層に
|
||||
* 例えば`game.settings.map`は`game.map`になる
|
||||
|
||||
### 既知の問題
|
||||
* ユーザー認証無しでのアプリが作成できない
|
||||
* 依存ライブラリの問題と思わるため、対応が難しい
|
||||
|
||||
### Migration
|
||||
coming soon...
|
||||
|
||||
10.100.0
|
||||
----------
|
||||
* ユーザーリストでフォローボタンを表示するように
|
||||
* ドライブのファイルのサムネイルを修正
|
||||
* 投稿ウィジットでローカルのみの公開範囲で投稿できない問題を修正
|
||||
* TLを遡った時に抜けがある時がある問題を修正
|
||||
* ユーザータイムラインが投稿日時順ではなくなっているのを修正
|
||||
* 10.99.0 でチャートのレンダリングがおかしい問題を修正
|
||||
|
||||
10.99.0
|
||||
----------
|
||||
* manifest.json にインスタンス名を反映させるように
|
||||
* Metaに投稿やユーザーのIDを設定するように
|
||||
* 設定でポートが指定されていない場合、環境変数を参照するように
|
||||
* フォローインポートで途中にエラーになるユーザーがいると途中で終了してしまう問題を修正
|
||||
* フォローインポートで自分が含まれていた場合自分をフォローしてしまう問題を修正
|
||||
* ServiceWorkerの設定がUIで有効にならない問題を修正
|
||||
* ユーザー一覧でのユーザーの自己紹介が複数行になることがある問題を修正
|
||||
* フォローインポートでAPI limitに達していても正常にリクエストされたように表示されてしまう問題を修正
|
||||
* DBに保存されたrepository urlを変更する方法がない問題を修正
|
||||
* デスクトップDeckだとviaが投稿内に2箇所表示される問題を修正
|
||||
* デザインの調整
|
||||
* 依存関係の更新
|
||||
* ローカリゼーション
|
||||
|
||||
10.98.3
|
||||
----------
|
||||
* リアクションのカスタム絵文字の情報がNoteに添付されない問題を修正
|
||||
* フォルダーの移動をするとき親フォルダーに自分自身を指定できてしまう問題を修正
|
||||
* デザインの調整
|
||||
|
||||
10.98.2
|
||||
----------
|
||||
* 他のインスタンスから添付画像が見れない問題を修正
|
||||
|
||||
10.98.1
|
||||
----------
|
||||
* ドライブのファイルのサムネイルが表示されない問題を修正
|
||||
* APでカスタム絵文字を送る時に常にimage/pngで送っている問題を修正
|
||||
* いくらいじってもページリロードするとmisskeyのテーマがdark(future)になっちゃう問題を修正
|
||||
|
||||
10.98.0
|
||||
----------
|
||||
* ドライブのファイルダウンロード時に元のファイル名を尊重するように
|
||||
* ドライブで画像以外のファイルを分かりやすく表示するように
|
||||
* TwemojiのCDNを変更
|
||||
* モバイルで通知の設定がない問題を修正
|
||||
* デザインの調整
|
||||
|
||||
10.97.2
|
||||
----------
|
||||
* ビルド時に警告が出ないように修正
|
||||
|
||||
10.97.1
|
||||
----------
|
||||
* デザインの調整
|
||||
|
||||
10.97.0
|
||||
----------
|
||||
* リアクションに絵文字やカスタム絵文字を使えるように
|
||||
* 不明なリアクションのフォールバックに star を使えるように
|
||||
* デザインの調整
|
||||
|
||||
10.96.0
|
||||
----------
|
||||
* 連合ユーザーの投稿に対してActivityPubオブジェクトを要求されたら元のインスタンスにリダイレクトするように
|
||||
* updatePersonを試行した時点でもlastFetchedAtを更新するように
|
||||
* 管理画面でリモートインスタンスの登録日時を表示
|
||||
* ユーザーサジェストが機能しなくなっていた問題を修正
|
||||
* 最近使ったハッシュタグ表示が機能していない問題を修正
|
||||
* バグ修正
|
||||
* デザインの調整
|
||||
|
||||
10.95.0
|
||||
----------
|
||||
* ジョブを一覧できるように
|
||||
* MFMでURLを明示する構文の追加
|
||||
* Articleタイプのアクティビティを受け入れるように
|
||||
* 凍結されたユーザーをサジェストしないように
|
||||
* ファビコンが保存されないのを修正
|
||||
* キューのジョブクリアの動作を修正
|
||||
* デザインの調整
|
||||
|
||||
10.94.0
|
||||
----------
|
||||
* Faviconを設定できるように
|
||||
* アカウントを凍結したときすべてのフォローを解除するように
|
||||
* シェアページが機能していない問題を修正
|
||||
* インスタンスブロックをしていてもRenote等すると取得されてしまう問題を修正
|
||||
* デザインの調整
|
||||
|
||||
10.93.1
|
||||
----------
|
||||
* データのエクスポートとインポートの動作を修正
|
||||
* デザインの調整
|
||||
|
||||
10.93.0
|
||||
----------
|
||||
* フォローリストをインポートできるように
|
||||
* embedプレイヤーを閉じれるように
|
||||
* リストをインポートしたときにプロキシアカウントがフォローするように修正
|
||||
* Web Share Targetの動作を修正
|
||||
* おすすめアンケートのチョイスを修正
|
||||
* デザインの調整
|
||||
|
||||
10.92.4
|
||||
----------
|
||||
* リストのエクスポートをできるように
|
||||
* ジョブキューウィジェットを追加
|
||||
* URLプレビューのサムネイルが表示されないことがある問題を修正
|
||||
|
||||
10.92.3
|
||||
----------
|
||||
* 管理画面の各種ジョブ数がおかしい問題を修正
|
||||
* ジョブキューの動作を調整
|
||||
|
||||
10.92.2
|
||||
----------
|
||||
* 管理画面で各種ジョブ数を一覧できるように
|
||||
* ジョブキューの動作を修正
|
||||
* notes/children が遅い問題を修正
|
||||
|
||||
10.92.1
|
||||
----------
|
||||
* アンケートの結果をリモートと同期するように
|
||||
* ジョブキューを有効に
|
||||
* 投稿の返信一覧に引用Renoteも含めるように
|
||||
* robots.txt追加
|
||||
* デザインの調整
|
||||
|
||||
10.92.0
|
||||
----------
|
||||
* Mastodonのアンケートに対応
|
||||
* 複数回答できるアンケートを作成できるように
|
||||
* アンケートに期限を設定できるように
|
||||
* 絵文字ピッカーを改良
|
||||
* ハッシュタグの判定を改善
|
||||
* デッキのタグTLで別のタグをクリックしてもTLが変わらない問題を修正
|
||||
* ユーザーサジェストで表示名が変わらない問題を修正
|
||||
* UIのバグ修正
|
||||
* デザインの調整
|
||||
* など
|
||||
|
||||
10.91.2
|
||||
----------
|
||||
* 10.91.1 で追加した依存関係にXSS脆弱性があったので他のパッケージに差し替え
|
||||
* 初期アクセスでテーマが正しく設定されない問題を修正
|
||||
|
||||
10.91.1
|
||||
----------
|
||||
* ログビューを強化
|
||||
* テーマの切り替えをなめらかに
|
||||
* SVGの判定を修正
|
||||
|
||||
10.91.0
|
||||
----------
|
||||
* ログを管理画面で見れるように
|
||||
|
127
CONTRIBUTING.md
127
CONTRIBUTING.md
@@ -46,7 +46,40 @@ Convert な(na) to にゃ(nya)
|
||||
Revert Nyaize
|
||||
|
||||
## Code style
|
||||
### Don't use `export default`
|
||||
### セミコロンを省略しない
|
||||
ASI Hazardを避けるためでもある
|
||||
|
||||
### 中括弧を省略しない
|
||||
Bad:
|
||||
``` ts
|
||||
if (foo)
|
||||
bar;
|
||||
else
|
||||
baz;
|
||||
```
|
||||
|
||||
Good:
|
||||
``` ts
|
||||
if (foo) {
|
||||
bar;
|
||||
} else {
|
||||
baz;
|
||||
}
|
||||
```
|
||||
|
||||
ただし**`if`が一行**の時だけは省略しても良い
|
||||
Good:
|
||||
``` ts
|
||||
if (foo) bar;
|
||||
```
|
||||
|
||||
### `export default`を使わない
|
||||
インテリセンスと相性が悪かったりするため
|
||||
|
||||
参考:
|
||||
* https://gfx.hatenablog.com/entry/2017/11/24/135343
|
||||
* https://basarat.gitbooks.io/typescript/docs/tips/defaultIsBad.html
|
||||
|
||||
Bad:
|
||||
``` ts
|
||||
export default function(foo: string): string {
|
||||
@@ -72,3 +105,95 @@ src ... Source code
|
||||
test ... Test code
|
||||
|
||||
```
|
||||
|
||||
## Notes
|
||||
### placeholder
|
||||
SQLをクエリビルダで組み立てる際、使用するプレースホルダは重複してはならない
|
||||
例えば
|
||||
``` ts
|
||||
query.andWhere(new Brackets(qb => {
|
||||
for (const type of ps.fileType) {
|
||||
qb.orWhere(`:type = ANY(note.attachedFileTypes)`, { type: type });
|
||||
}
|
||||
}));
|
||||
```
|
||||
と書くと、ループ中で`type`というプレースホルダが複数回使われてしまいおかしくなる
|
||||
だから次のようにする必要がある
|
||||
```ts
|
||||
query.andWhere(new Brackets(qb => {
|
||||
for (const type of ps.fileType) {
|
||||
const i = ps.fileType.indexOf(type);
|
||||
qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type });
|
||||
}
|
||||
}));
|
||||
```
|
||||
|
||||
### `null` in SQL
|
||||
SQLを発行する際、パラメータが`null`になる可能性のある場合はSQL文を出し分けなければならない
|
||||
例えば
|
||||
``` ts
|
||||
query.where('file.folderId = :folderId', { folderId: ps.folderId });
|
||||
```
|
||||
という処理で、`ps.folderId`が`null`だと結果的に`file.folderId = null`のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない
|
||||
だから次のようにする必要がある
|
||||
``` ts
|
||||
if (ps.folderId) {
|
||||
query.where('file.folderId = :folderId', { folderId: ps.folderId });
|
||||
} else {
|
||||
query.where('file.folderId IS NULL');
|
||||
}
|
||||
```
|
||||
|
||||
### `[]` in SQL
|
||||
SQLを発行する際、`IN`のパラメータが`[]`(空の配列)になる可能性のある場合はSQL文を出し分けなければならない
|
||||
例えば
|
||||
``` ts
|
||||
const users = await Users.find({
|
||||
id: In(userIds)
|
||||
});
|
||||
```
|
||||
という処理で、`userIds`が`[]`だと結果的に`user.id IN ()`のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない
|
||||
だから次のようにする必要がある
|
||||
``` ts
|
||||
const users = userIds.length > 0 ? await Users.find({
|
||||
id: In(userIds)
|
||||
}) : [];
|
||||
```
|
||||
|
||||
### 配列のインデックス in SQL
|
||||
SQLでは配列のインデックスは**1始まり**。
|
||||
`[a, b, c]`の `a`にアクセスしたいなら`[0]`ではなく`[1]`と書く
|
||||
|
||||
### `undefined`にご用心
|
||||
MongoDBの時とは違い、findOneでレコードを取得する時に対象レコードが存在しない場合 **`undefined`** が返ってくるので注意。
|
||||
MongoDBは`null`で返してきてたので、その感覚で`if (x === null)`とか書くとバグる。代わりに`if (x == null)`と書いてください
|
||||
|
||||
### 簡素な`undefined`チェック
|
||||
データベースからレコードを取得するときに、プログラムの流れ的に(ほぼ)絶対`undefined`にはならない場合でも、`undefined`チェックしないとTypeScriptに怒られます。
|
||||
でもいちいち複数行を費やして、発生するはずのない`undefined`をチェックするのも面倒なので、`ensure`というユーティリティ関数を用意しています。
|
||||
例えば、
|
||||
``` ts
|
||||
const user = await Users.findOne(userId);
|
||||
// この時点で user の型は User | undefined
|
||||
if (user == null) {
|
||||
throw 'missing user';
|
||||
}
|
||||
// この時点で user の型は User
|
||||
```
|
||||
という処理を`ensure`を使うと
|
||||
``` ts
|
||||
const user = await Users.findOne(userId).then(ensure);
|
||||
// この時点で user の型は User
|
||||
```
|
||||
という風に書けます。
|
||||
もちろん`ensure`内部でエラーを握りつぶすようなことはしておらず、万が一`undefined`だった場合はPromiseがRejectされ後続の処理は実行されません。
|
||||
``` ts
|
||||
const user = await Users.findOne(userId).then(ensure);
|
||||
// 万が一 Users.findOne の結果が undefined だったら、ensure でエラーが発生するので
|
||||
// この行に到達することは無い
|
||||
// なので、.then(ensure) は
|
||||
// if (user == null) {
|
||||
// throw 'missing user';
|
||||
// }
|
||||
// の糖衣構文のような扱いです
|
||||
```
|
||||
|
@@ -21,11 +21,11 @@ RUN apk add --no-cache \
|
||||
pkgconfig \
|
||||
python \
|
||||
zlib-dev
|
||||
RUN npm i -g yarn
|
||||
|
||||
COPY package.json ./
|
||||
RUN npm i
|
||||
COPY . ./
|
||||
RUN yarn install
|
||||
RUN yarn build
|
||||
RUN npm run build
|
||||
|
||||
FROM base AS runner
|
||||
|
||||
|
67
README.md
67
README.md
@@ -1,4 +1,4 @@
|
||||
<img src="https://github.com/syuilo/misskey/blob/develop/assets/ai-orig.png?raw=true" align="right" height="320px"/>
|
||||
<a href="https://xn--931a.moe/"><img src="https://github.com/syuilo/misskey/blob/develop/assets/ai-orig.png?raw=true" align="right" height="320px"/></a>
|
||||
|
||||
[](https://misskey.xyz/)
|
||||
================================================================
|
||||
@@ -59,7 +59,7 @@ Organize and store your files! Want to post a picture you have already uploaded?
|
||||
|
||||
---
|
||||
|
||||
...and more! Experience Misskey with your own eyes at [misskey.xyz](https://misskey.xyz) or join one of the [other instances](https://joinmisskey.github.io/) that are available.
|
||||
...and more! Experience Misskey with your own eyes at [misskey.io](https://misskey.io/) or join one of the [other instances](https://joinmisskey.github.io/) that are available.
|
||||
|
||||
Screen shots
|
||||
----------------------------------------------------------------
|
||||
@@ -88,12 +88,14 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
||||
<td><img src="https://avatars0.githubusercontent.com/u/10798641?s=460&v=4" alt="AyaMorisawa" width="100"></td>
|
||||
<td><img src="https://avatars1.githubusercontent.com/u/30769358?s=460&v=4" alt="mei23" width="100"></td>
|
||||
<td><img src="https://avatars2.githubusercontent.com/u/20679825?s=460&v=4" alt="acid-chicken" width="100"></td>
|
||||
<td><img src="https://avatars2.githubusercontent.com/u/6533808?s=460&v=4" alt="rinsuki" width="100"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/syuilo">@syuilo</a></td>
|
||||
<td align="center"><a href="https://github.com/AyaMorisawa">@AyaMorisawa</a></td>
|
||||
<td align="center"><a href="https://github.com/mei23">@mei23</a></td>
|
||||
<td align="center"><a href="https://github.com/acid-chicken">@acid-chicken</a></td>
|
||||
<td align="center"><a href="https://github.com/rinsuki">@rinsuki</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -101,56 +103,71 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
||||
----------------------------------------------------------------
|
||||
<!-- PATREON_START -->
|
||||
<table><tr>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/1?token-time=2145916800&token-hash=WeuDzzz24cRXJogyIkU-mxARqkdyms-rcZKbO-GpGjw%3D" alt="weep" width="100"></td>
|
||||
<td><img src="https://c8.patreon.com/2/200/12059069" alt="naga_rus" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/3?token-time=2145916800&token-hash=c8HeVqLtmdgH-gSBJg8i10gmOcwllM87MDHeznl3el0%3D" alt="Melilot" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5888816/36da0f7c15954df0ab13f9abdf227f66/1.jpeg?token-time=2145916800&token-hash=at8QpJXJ8C0zINY_NmoMKv-MhXVoUK-YzTgaJPJzJYU%3D" alt="Hiroshi Seki" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/3.png?token-time=2145916800&token-hash=oH_i7gJjNT7Ot6j9JiVwy7ZJIBqACVnzLqlz4YrDAZA%3D" alt="weepjp" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13099460/43cecdbaa63a40d79bf50a96b9910b9d/1.jpe?token-time=2145916800&token-hash=bqwLTk0Wo0hUJJ8J5y7ii05bLzz-_CDA7Bo0Mp4RFU0%3D" alt="ne_moni" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/4.jpe?token-time=2145916800&token-hash=zEyJqVM7u9d8Ri-65fJYSJcWF1jBH1nJ5a3taRzrTmw%3D" alt="Melilot" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5670915/ee175f0bfb6347ffa4ea101a8c097bff/1.jpg?token-time=2145916800&token-hash=mPLM9CA-riFHx-myr3bLZJuH2xBRHA9se5VbHhLIOuA%3D" alt="osapon" width="100"></td>
|
||||
<td><img src="https://c8.patreon.com/2/200/16869916" alt="見当かなみ" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12999811/5f349fafcce44dd1824a8b1ebbec4564/3?token-time=2145916800&token-hash=LtV2lRi3L2jOWMLwccr9qWYfPrFlzIo2jYZHKzHEb6k%3D" alt="Xeltica" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1?token-time=2145916800&token-hash=1FlxS9MEgmNGH_RHUVHbO5hIXB5I1z0lvA33CTvYvjA%3D" alt="gutfuckllc" width="100"></td>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/weepjp">weep</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12059069">naga_rus</a></td>
|
||||
<td><a href="https://www.patreon.com/rane_hs">Hiroshi Seki</a></td>
|
||||
<td><a href="https://www.patreon.com/weepjp">weepjp</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=13099460">ne_moni</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td>
|
||||
<td><a href="https://www.patreon.com/osapon">osapon</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ</a></td>
|
||||
<td><a href="https://www.patreon.com/Xeltica">Xeltica</a></td>
|
||||
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
|
||||
</tr></table>
|
||||
<table><tr>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/11357794/923ce94cd8c44ba788ee931907881839/1?token-time=2145916800&token-hash=0xgcpqvFDqRcV_YIEhcPNVH7gs9sLg_BBnTJXCkN4ao%3D" alt="mydarkstar" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1.png?token-time=2145916800&token-hash=FMV7cPKBD1TU2WTbl1jg6AcdKSvTb2BSFcDhgc-EO8w%3D" alt="gutfuckllc" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/11357794/923ce94cd8c44ba788ee931907881839/1.png?token-time=2145916800&token-hash=9nEQje_eMvUjq9a7L3uBqW-MQbS-rRMaMgd7UYVoFNM%3D" alt="mydarkstar" width="100"></td>
|
||||
<td><img src="https://c8.patreon.com/2/200/12718187" alt="Peter G." width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1?token-time=2145916800&token-hash=2PsbFNw0tnubZzgSXD01R6hIgncfiElG7H7HX2Y3dyo%3D" alt="nemu" width="100"></td>
|
||||
<td><img src="https://c8.patreon.com/2/200/18833336" alt="itiradi" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1.jpe?token-time=2145916800&token-hash=UQRWf01TwHDV4Cls1K0YAOAjM29ssif7hLVq0ESQ0hs%3D" alt="nemu" width="100"></td>
|
||||
<td><img src="https://c8.patreon.com/2/200/17866454" alt="sikyosyounin" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3?token-time=2145916800&token-hash=9JtETp0X8gI280Ne1E8bxn6j4Lw5o2k4mJkICx97V_k%3D" alt="YUKIMOCHI" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3.png?token-time=2145916800&token-hash=KjfQL8nf3AIf6WqzLshBYAyX44piAqOAZiYXgZS_H6A%3D" alt="YUKIMOCHI" width="100"></td>
|
||||
<td><img src="https://c8.patreon.com/2/200/17463605" alt="Sampot" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17880724/311738c8a48f4a6b9443c2445a75adde/1?token-time=2145916800&token-hash=95p8VdGX45E8BitZR_eOcDlqCjumjzNLBPQJrJdeCpI%3D" alt="takimura" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17195955/be45e5e14c3e48b2bee0456c84e19df4/4?token-time=2145916800&token-hash=SbdZeN5SmsuT9stD6v0jN1z0hftg0FmRiCTxysU0Ihw%3D" alt="Damillora" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19356899/496b4681d33b4520bd7688e0fd19c04d/2.jpeg?token-time=2145916800&token-hash=_sTj3dUBOhn9qwiJ7F19Qd-yWWfUqJC_0jG1h0agEqQ%3D" alt="sheeta.s" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13737140/1adf7835017d479280d90fe8d30aade2/1.png?token-time=2145916800&token-hash=0pdle8h5pDZrww0BDOjdz6zO-HudeGTh36a3qi1biVU%3D" alt="Satsuki Yanagi" width="100"></td>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
|
||||
<td><a href="https://www.patreon.com/mydarkstar">mydarkstar</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12718187">Peter G.</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=18833336">itiradi</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=13039004">nemu</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=17866454">sikyosyounin</a></td>
|
||||
<td><a href="https://www.patreon.com/yukimochi">YUKIMOCHI</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=17463605">Sampot</a></td>
|
||||
<td><a href="https://www.patreon.com/takimura">takimura</a></td>
|
||||
<td><a href="https://www.patreon.com/damillora">Damillora</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=19356899">sheeta.s</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=13737140">Satsuki Yanagi</a></td>
|
||||
</tr></table>
|
||||
<table><tr>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4389829/9f709180ac714651a70f74a82f3ffdb9/2?token-time=2145916800&token-hash=zcwFxb2zopzWwksKVU1YpfAEjsl4yKT02aQ6yiAFRiQ%3D" alt="natalie" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1?token-time=2145916800&token-hash=5T8XcaAf9Zyzfg3QubR06s_kJZkArVEM2dwObrBVAU4%3D" alt="Hiratake" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1?token-time=2145916800&token-hash=Ksk_2l3gjPDbnzMUOCSW1E-hdPJsNs2tSR4_RAakRK8%3D" alt="dansup" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1?token-time=2145916800&token-hash=CXe9AqlZy9AsYfiWd3OBYVOzvODoN47Litz0Tu4BFpU%3D" alt="Gargron" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5731881/4b6038e6cda34c04b83a5fcce3806a93/1?token-time=2145916800&token-hash=xhR1n6NAAyEb-IUXLD6_dshkFa3mefU5ZZuk1L8qKTs%3D" alt="Nokotaro Takeda" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1?token-time=2145916800&token-hash=uR-48MQ0A4j0irQSrCAQZJ-sJUSs_Fkihlg3-l59b7c%3D" alt="Takashi Shibuya" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17880724/311738c8a48f4a6b9443c2445a75adde/1.jpe?token-time=2145916800&token-hash=CPxGQhKIlEaa6WUcgbyHixyKEhakiw9RFdOhsIJBQ_o%3D" alt="takimura" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17195955/be45e5e14c3e48b2bee0456c84e19df4/4.jpe?token-time=2145916800&token-hash=UslrPVM-8TXOe8AapuNiaFYjcIJgPNcU-fKpGbfGJNI%3D" alt="Damillora" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/16900731/83884b38afc74d4cbe83c30a13b10edd/1.png?token-time=2145916800&token-hash=R5Tog8RWg0rguRoCIoir3lThokrdPvs8Utfikhc0nhY%3D" alt="Atsuko Tominaga" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4389829/9f709180ac714651a70f74a82f3ffdb9/3.png?token-time=2145916800&token-hash=FTm3WVom4dJ9NwWMU4OpCL_8Yc13WiwEbKrDPyTZTPs%3D" alt="natalie" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1.jpe?token-time=2145916800&token-hash=EWxXhVbZYH7KB4IDT3joc8TbIg8zPO40x1r5IDn3R7c%3D" alt="Hiratake" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18072312/98e894d960314fa7bc236a72a39488fe/1.jpe?token-time=2145916800&token-hash=qA8j97lIZNc-74AuZ0p4F3ms6sKPeKjtNt2vEuwpsyo%3D" alt="Hekovic" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1.jpeg?token-time=2145916800&token-hash=L55UhJ0rcuNAH3w_ryeeGN4hC6taoOixyAhraEi0bzw%3D" alt="dansup" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1.jpeg?token-time=2145916800&token-hash=d8jBQLMOHD87KtXs5C9fk1o58DMF73pQ-dYH3uZJPBE%3D" alt="Gargron" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5731881/4b6038e6cda34c04b83a5fcce3806a93/1.png?token-time=2145916800&token-hash=hBayGfOmQH3kRMdNnDe4oCZD_9fsJWSt29xXR3KRMVk%3D" alt="Nokotaro Takeda" width="100"></td>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/takimura">takimura</a></td>
|
||||
<td><a href="https://www.patreon.com/damillora">Damillora</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=16900731">Atsuko Tominaga</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=4389829">natalie</a></td>
|
||||
<td><a href="https://www.patreon.com/hiratake">Hiratake</a></td>
|
||||
<td><a href="https://www.patreon.com/hekovic">Hekovic</a></td>
|
||||
<td><a href="https://www.patreon.com/dansup">dansup</a></td>
|
||||
<td><a href="https://www.patreon.com/mastodon">Gargron</a></td>
|
||||
<td><a href="https://www.patreon.com/takenoko">Nokotaro Takeda</a></td>
|
||||
</tr></table>
|
||||
<table><tr>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1.jpeg?token-time=2145916800&token-hash=vGe7wXGqmA8Q7m-kDNb6fyGdwk-Dxk4F-ut8ZZu51RM%3D" alt="Takashi Shibuya" width="100"></td>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
||||
</tr></table>
|
||||
|
||||
**Last updated:** Fri, 01 Mar 2019 23:59:07 UTC
|
||||
**Last updated:** Wed, 24 Apr 2019 05:56:07 UTC
|
||||
<!-- PATREON_END -->
|
||||
|
||||
:four_leaf_clover: Copyright
|
||||
|
4
assets/robots.txt
Normal file
4
assets/robots.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
user-agent: *
|
||||
allow: /
|
||||
|
||||
# todo: sitemap
|
@@ -1,9 +0,0 @@
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'crypto_key',
|
||||
'sources': ['src/crypto_key.cc'],
|
||||
'include_dirs': ['<!(node -e "require(\'nan\')")']
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
const mongo = require('mongodb');
|
||||
const User = require('../built/models/user').default;
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
const user = args[0];
|
||||
|
||||
const q = user.startsWith('@') ? {
|
||||
username: user.split('@')[1],
|
||||
host: user.split('@')[2] || null
|
||||
} : { _id: new mongo.ObjectID(user) };
|
||||
|
||||
console.log(`Mark as admin ${user}...`);
|
||||
|
||||
User.update(q, {
|
||||
$set: {
|
||||
isAdmin: true
|
||||
}
|
||||
}).then(() => {
|
||||
console.log(`Done ${user}`);
|
||||
}, e => {
|
||||
console.error(e);
|
||||
});
|
@@ -1,57 +0,0 @@
|
||||
// for Node.js interpret
|
||||
|
||||
const chalk = require('chalk');
|
||||
const sequential = require('promise-sequential');
|
||||
|
||||
const { default: User } = require('../../built/models/user');
|
||||
const { default: DriveFile } = require('../../built/models/drive-file');
|
||||
|
||||
async function main() {
|
||||
const promiseGens = [];
|
||||
|
||||
const count = await DriveFile.count({});
|
||||
|
||||
let prev;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
promiseGens.push(() => {
|
||||
const promise = new Promise(async (res, rej) => {
|
||||
const file = await DriveFile.findOne(prev ? {
|
||||
_id: { $gt: prev._id }
|
||||
} : {}, {
|
||||
sort: {
|
||||
_id: 1
|
||||
}
|
||||
});
|
||||
|
||||
prev = file;
|
||||
|
||||
const user = await User.findOne({ _id: file.metadata.userId });
|
||||
|
||||
DriveFile.update({
|
||||
_id: file._id
|
||||
}, {
|
||||
$set: {
|
||||
'metadata._user': {
|
||||
host: user.host
|
||||
}
|
||||
}
|
||||
}).then(() => {
|
||||
res([i, file]);
|
||||
}).catch(rej);
|
||||
});
|
||||
|
||||
promise.then(([i, file]) => {
|
||||
console.log(chalk`{gray ${i}} {green done: {bold ${file._id}} ${file.filename}}`);
|
||||
});
|
||||
|
||||
return promise;
|
||||
});
|
||||
}
|
||||
|
||||
return await sequential(promiseGens);
|
||||
}
|
||||
|
||||
main().then(() => {
|
||||
console.log('ALL DONE');
|
||||
}).catch(console.error);
|
@@ -1,71 +0,0 @@
|
||||
// for Node.js interpret
|
||||
|
||||
const chalk = require('chalk');
|
||||
const sequential = require('promise-sequential');
|
||||
|
||||
const { default: User } = require('../../built/models/user');
|
||||
const { default: DriveFile } = require('../../built/models/drive-file');
|
||||
|
||||
async function main() {
|
||||
const promiseGens = [];
|
||||
|
||||
const count = await User.count({});
|
||||
|
||||
let prev;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
promiseGens.push(() => {
|
||||
const promise = new Promise(async (res, rej) => {
|
||||
const user = await User.findOne(prev ? {
|
||||
_id: { $gt: prev._id }
|
||||
} : {}, {
|
||||
sort: {
|
||||
_id: 1
|
||||
}
|
||||
});
|
||||
|
||||
prev = user;
|
||||
|
||||
const set = {};
|
||||
|
||||
if (user.avatarId != null) {
|
||||
const file = await DriveFile.findOne({ _id: user.avatarId });
|
||||
|
||||
if (file && file.metadata.properties.avgColor) {
|
||||
set.avatarColor = file.metadata.properties.avgColor;
|
||||
}
|
||||
}
|
||||
|
||||
if (user.bannerId != null) {
|
||||
const file = await DriveFile.findOne({ _id: user.bannerId });
|
||||
|
||||
if (file && file.metadata.properties.avgColor) {
|
||||
set.bannerColor = file.metadata.properties.avgColor;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(set).length === 0) return res([i, user]);
|
||||
|
||||
User.update({
|
||||
_id: user._id
|
||||
}, {
|
||||
$set: set
|
||||
}).then(() => {
|
||||
res([i, user]);
|
||||
}).catch(rej);
|
||||
});
|
||||
|
||||
promise.then(([i, user]) => {
|
||||
console.log(chalk`{gray ${i}} {green done: {bold ${user._id}} @${user.username}}`);
|
||||
});
|
||||
|
||||
return promise;
|
||||
});
|
||||
}
|
||||
|
||||
return await sequential(promiseGens);
|
||||
}
|
||||
|
||||
main().then(() => {
|
||||
console.log('ALL DONE');
|
||||
}).catch(console.error);
|
@@ -1,9 +0,0 @@
|
||||
const { default: DriveFile } = require('../../built/models/drive-file');
|
||||
|
||||
DriveFile.update({}, {
|
||||
$rename: {
|
||||
'metadata.isMetaOnly': 'metadata.withoutChunks'
|
||||
}
|
||||
}, {
|
||||
multi: true
|
||||
});
|
@@ -1,134 +0,0 @@
|
||||
const { default: Stats } = require('../../built/models/stats');
|
||||
const { default: User } = require('../../built/models/user');
|
||||
const { default: Note } = require('../../built/models/note');
|
||||
const { default: DriveFile } = require('../../built/models/drive-file');
|
||||
|
||||
const now = new Date();
|
||||
const y = now.getFullYear();
|
||||
const m = now.getMonth();
|
||||
const d = now.getDate();
|
||||
const today = new Date(y, m, d);
|
||||
|
||||
async function main() {
|
||||
const localUsersCount = await User.count({
|
||||
host: null
|
||||
});
|
||||
|
||||
const remoteUsersCount = await User.count({
|
||||
host: { $ne: null }
|
||||
});
|
||||
|
||||
const localNotesCount = await Note.count({
|
||||
'_user.host': null
|
||||
});
|
||||
|
||||
const remoteNotesCount = await Note.count({
|
||||
'_user.host': { $ne: null }
|
||||
});
|
||||
|
||||
const localDriveFilesCount = await DriveFile.count({
|
||||
'metadata._user.host': null
|
||||
});
|
||||
|
||||
const remoteDriveFilesCount = await DriveFile.count({
|
||||
'metadata._user.host': { $ne: null }
|
||||
});
|
||||
|
||||
const localDriveFilesSize = await DriveFile
|
||||
.aggregate([{
|
||||
$match: {
|
||||
'metadata._user.host': null,
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
}
|
||||
}, {
|
||||
$project: {
|
||||
length: true
|
||||
}
|
||||
}, {
|
||||
$group: {
|
||||
_id: null,
|
||||
usage: { $sum: '$length' }
|
||||
}
|
||||
}])
|
||||
.then(aggregates => {
|
||||
if (aggregates.length > 0) {
|
||||
return aggregates[0].usage;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const remoteDriveFilesSize = await DriveFile
|
||||
.aggregate([{
|
||||
$match: {
|
||||
'metadata._user.host': { $ne: null },
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
}
|
||||
}, {
|
||||
$project: {
|
||||
length: true
|
||||
}
|
||||
}, {
|
||||
$group: {
|
||||
_id: null,
|
||||
usage: { $sum: '$length' }
|
||||
}
|
||||
}])
|
||||
.then(aggregates => {
|
||||
if (aggregates.length > 0) {
|
||||
return aggregates[0].usage;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
await Stats.insert({
|
||||
date: today,
|
||||
users: {
|
||||
local: {
|
||||
total: localUsersCount,
|
||||
diff: 0
|
||||
},
|
||||
remote: {
|
||||
total: remoteUsersCount,
|
||||
diff: 0
|
||||
}
|
||||
},
|
||||
notes: {
|
||||
local: {
|
||||
total: localNotesCount,
|
||||
diff: 0,
|
||||
diffs: {
|
||||
normal: 0,
|
||||
reply: 0,
|
||||
renote: 0
|
||||
}
|
||||
},
|
||||
remote: {
|
||||
total: remoteNotesCount,
|
||||
diff: 0,
|
||||
diffs: {
|
||||
normal: 0,
|
||||
reply: 0,
|
||||
renote: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
drive: {
|
||||
local: {
|
||||
totalCount: localDriveFilesCount,
|
||||
totalSize: localDriveFilesSize,
|
||||
diffCount: 0,
|
||||
diffSize: 0
|
||||
},
|
||||
remote: {
|
||||
totalCount: remoteDriveFilesCount,
|
||||
totalSize: remoteDriveFilesSize,
|
||||
diffCount: 0,
|
||||
diffSize: 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log('done');
|
||||
}
|
||||
|
||||
main();
|
@@ -1,144 +0,0 @@
|
||||
const { default: Stats } = require('../../built/models/stats');
|
||||
const { default: User } = require('../../built/models/user');
|
||||
const { default: Note } = require('../../built/models/note');
|
||||
const { default: DriveFile } = require('../../built/models/drive-file');
|
||||
|
||||
const now = new Date();
|
||||
const y = now.getFullYear();
|
||||
const m = now.getMonth();
|
||||
const d = now.getDate();
|
||||
const h = now.getHours();
|
||||
const date = new Date(y, m, d, h);
|
||||
|
||||
async function main() {
|
||||
await Stats.update({}, {
|
||||
$set: {
|
||||
span: 'day'
|
||||
}
|
||||
}, {
|
||||
multi: true
|
||||
});
|
||||
|
||||
const localUsersCount = await User.count({
|
||||
host: null
|
||||
});
|
||||
|
||||
const remoteUsersCount = await User.count({
|
||||
host: { $ne: null }
|
||||
});
|
||||
|
||||
const localNotesCount = await Note.count({
|
||||
'_user.host': null
|
||||
});
|
||||
|
||||
const remoteNotesCount = await Note.count({
|
||||
'_user.host': { $ne: null }
|
||||
});
|
||||
|
||||
const localDriveFilesCount = await DriveFile.count({
|
||||
'metadata._user.host': null
|
||||
});
|
||||
|
||||
const remoteDriveFilesCount = await DriveFile.count({
|
||||
'metadata._user.host': { $ne: null }
|
||||
});
|
||||
|
||||
const localDriveFilesSize = await DriveFile
|
||||
.aggregate([{
|
||||
$match: {
|
||||
'metadata._user.host': null,
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
}
|
||||
}, {
|
||||
$project: {
|
||||
length: true
|
||||
}
|
||||
}, {
|
||||
$group: {
|
||||
_id: null,
|
||||
usage: { $sum: '$length' }
|
||||
}
|
||||
}])
|
||||
.then(aggregates => {
|
||||
if (aggregates.length > 0) {
|
||||
return aggregates[0].usage;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const remoteDriveFilesSize = await DriveFile
|
||||
.aggregate([{
|
||||
$match: {
|
||||
'metadata._user.host': { $ne: null },
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
}
|
||||
}, {
|
||||
$project: {
|
||||
length: true
|
||||
}
|
||||
}, {
|
||||
$group: {
|
||||
_id: null,
|
||||
usage: { $sum: '$length' }
|
||||
}
|
||||
}])
|
||||
.then(aggregates => {
|
||||
if (aggregates.length > 0) {
|
||||
return aggregates[0].usage;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
await Stats.insert({
|
||||
date: date,
|
||||
span: 'hour',
|
||||
users: {
|
||||
local: {
|
||||
total: localUsersCount,
|
||||
diff: 0
|
||||
},
|
||||
remote: {
|
||||
total: remoteUsersCount,
|
||||
diff: 0
|
||||
}
|
||||
},
|
||||
notes: {
|
||||
local: {
|
||||
total: localNotesCount,
|
||||
diff: 0,
|
||||
diffs: {
|
||||
normal: 0,
|
||||
reply: 0,
|
||||
renote: 0
|
||||
}
|
||||
},
|
||||
remote: {
|
||||
total: remoteNotesCount,
|
||||
diff: 0,
|
||||
diffs: {
|
||||
normal: 0,
|
||||
reply: 0,
|
||||
renote: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
drive: {
|
||||
local: {
|
||||
totalCount: localDriveFilesCount,
|
||||
totalSize: localDriveFilesSize,
|
||||
diffCount: 0,
|
||||
diffSize: 0
|
||||
},
|
||||
remote: {
|
||||
totalCount: remoteDriveFilesCount,
|
||||
totalSize: remoteDriveFilesSize,
|
||||
diffCount: 0,
|
||||
diffSize: 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log('done');
|
||||
}
|
||||
|
||||
main();
|
@@ -5,8 +5,8 @@ services:
|
||||
build: .
|
||||
restart: always
|
||||
links:
|
||||
- mongo
|
||||
# - redis
|
||||
- db
|
||||
- redis
|
||||
# - es
|
||||
ports:
|
||||
- "127.0.0.1:3000:3000"
|
||||
@@ -14,26 +14,23 @@ services:
|
||||
- internal_network
|
||||
- external_network
|
||||
|
||||
# redis:
|
||||
# restart: always
|
||||
# image: redis:4.0-alpine
|
||||
# networks:
|
||||
# - internal_network
|
||||
### Uncomment to enable Redis persistance
|
||||
## volumes:
|
||||
## - ./redis:/data
|
||||
|
||||
mongo:
|
||||
redis:
|
||||
restart: always
|
||||
image: mongo:4.1
|
||||
image: redis:4.0-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
environment:
|
||||
MONGO_INITDB_DATABASE: "misskey"
|
||||
volumes:
|
||||
- ./.config/mongo_initdb.js:/docker-entrypoint-initdb.d/mongo_initdb.js:ro
|
||||
### Uncomment to enable MongoDB persistance
|
||||
# - ./mongo:/data
|
||||
- ./redis:/data
|
||||
|
||||
db:
|
||||
restart: always
|
||||
image: postgres:11.2-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
env_file:
|
||||
- .config/docker.env
|
||||
volumes:
|
||||
- ./db:/var/lib/postgresql/data
|
||||
|
||||
# es:
|
||||
# restart: always
|
||||
@@ -42,9 +39,8 @@ services:
|
||||
# - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
# networks:
|
||||
# - internal_network
|
||||
#### Uncomment to enable ES persistence
|
||||
## volumes:
|
||||
## - ./elasticsearch:/usr/share/elasticsearch/data
|
||||
# volumes:
|
||||
# - ./elasticsearch:/usr/share/elasticsearch/data
|
||||
|
||||
networks:
|
||||
internal_network:
|
||||
|
@@ -1,22 +0,0 @@
|
||||
Comment faire une sauvegarde de votre Misskey ?
|
||||
==========================
|
||||
|
||||
Assurez-vous d'avoir installé **mongodb-tools**.
|
||||
|
||||
---
|
||||
|
||||
Dans votre terminal :
|
||||
``` shell
|
||||
$ mongodump --archive=db-backup -u <VotreNomdUtilisateur> -p <VotreMotDePasse>
|
||||
```
|
||||
|
||||
Pour plus de détails, merci de consulter [la documentation de mongodump](https://docs.mongodb.com/manual/reference/program/mongodump/).
|
||||
|
||||
Restauration
|
||||
-------
|
||||
|
||||
``` shell
|
||||
$ mongorestore --archive=db-backup
|
||||
```
|
||||
|
||||
Pour plus de détails, merci de consulter [la documentation de mongorestore](https://docs.mongodb.com/manual/reference/program/mongorestore/).
|
@@ -1,22 +0,0 @@
|
||||
How to backup your Misskey
|
||||
==========================
|
||||
|
||||
Make sure **mongodb-tools** installed.
|
||||
|
||||
---
|
||||
|
||||
In your shell:
|
||||
``` shell
|
||||
$ mongodump --archive=db-backup -u <YourUserName> -p <YourPassword>
|
||||
```
|
||||
|
||||
For details, please see [mongodump docs](https://docs.mongodb.com/manual/reference/program/mongodump/).
|
||||
|
||||
Restore
|
||||
-------
|
||||
|
||||
``` shell
|
||||
$ mongorestore --archive=db-backup
|
||||
```
|
||||
|
||||
For details, please see [mongorestore docs](https://docs.mongodb.com/manual/reference/program/mongorestore/).
|
@@ -9,15 +9,51 @@ This guide describes how to install and setup Misskey with Docker.
|
||||
|
||||
*1.* Download Misskey
|
||||
----------------------------------------------------------------
|
||||
1. `git clone -b master git://github.com/syuilo/misskey.git` Clone Misskey repository's master branch.
|
||||
2. `cd misskey` Move to misskey directory.
|
||||
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest) tag.
|
||||
1. Clone Misskey repository's master branch.
|
||||
|
||||
`git clone -b master git://github.com/syuilo/misskey.git`
|
||||
|
||||
2. Move to misskey directory.
|
||||
|
||||
`cd misskey`
|
||||
|
||||
3. Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest) tag.
|
||||
|
||||
`git checkout master`
|
||||
|
||||
*2.* Configure Misskey
|
||||
----------------------------------------------------------------
|
||||
1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`.
|
||||
2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` Copy the `.config/mongo_initdb_example.js` and rename it to `mongo_initdb.js`.
|
||||
3. Edit `default.yml` and `mongo_initdb.js`.
|
||||
|
||||
Create configuration files with following:
|
||||
|
||||
```bash
|
||||
cd .config
|
||||
cp example.yml default.yml
|
||||
cp docker_example.env docker.env
|
||||
```
|
||||
|
||||
### `default.yml`
|
||||
|
||||
Edit this file the same as non-Docker environment.
|
||||
However hostname of Postgresql, Redis and Elasticsearch are not `localhost`, they are set in `docker-compose.yml`.
|
||||
The following is default hostname:
|
||||
|
||||
| Service | Hostname |
|
||||
|---------------|----------|
|
||||
| Postgresql | `db` |
|
||||
| Redis | `redis` |
|
||||
| Elasticsearch | `es` |
|
||||
|
||||
### `docker.env`
|
||||
|
||||
Configure Postgresql in this file.
|
||||
The minimum required settings are:
|
||||
|
||||
| name | Description |
|
||||
|---------------------|---------------|
|
||||
| `POSTGRES_PASSWORD` | Password |
|
||||
| `POSTGRES_USER` | Username |
|
||||
| `POSTGRES_DB` | Database name |
|
||||
|
||||
*3.* Configure Docker
|
||||
----------------------------------------------------------------
|
||||
@@ -29,7 +65,13 @@ Build misskey with the following:
|
||||
|
||||
`docker-compose build`
|
||||
|
||||
*5.* That is it.
|
||||
*5.* Init DB
|
||||
----------------------------------------------------------------
|
||||
``` shell
|
||||
docker-compose run --rm web npm run init
|
||||
```
|
||||
|
||||
*6.* That is it.
|
||||
----------------------------------------------------------------
|
||||
Well done! Now you have an environment to run Misskey.
|
||||
|
||||
@@ -37,9 +79,9 @@ Well done! Now you have an environment to run Misskey.
|
||||
Just `docker-compose up -d`. GLHF!
|
||||
|
||||
### How to update your Misskey server to the latest version
|
||||
1. `git fetch`
|
||||
2. `git stash`
|
||||
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)`
|
||||
1. `git stash`
|
||||
2. `git checkout master`
|
||||
3. `git pull`
|
||||
4. `git stash pop`
|
||||
5. `docker-compose build`
|
||||
6. Check [ChangeLog](../CHANGELOG.md) for migration information
|
||||
|
@@ -10,9 +10,17 @@ Ce guide explique comment installer et configurer Misskey avec Docker.
|
||||
|
||||
*1.* Télécharger Misskey
|
||||
----------------------------------------------------------------
|
||||
1. `git clone -b master git://github.com/syuilo/misskey.git` Clone le dépôt de Misskey sur la branche master.
|
||||
2. `cd misskey` Naviguez dans le dossier du dépôt.
|
||||
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` Checkout sur le tag de la [dernière version](https://github.com/syuilo/misskey/releases/latest).
|
||||
1. Clone le dépôt de Misskey sur la branche master.
|
||||
|
||||
`git clone -b master git://github.com/syuilo/misskey.git`
|
||||
|
||||
2. Naviguez dans le dossier du dépôt.
|
||||
|
||||
`cd misskey`
|
||||
|
||||
3. Checkout sur le tag de la [dernière version](https://github.com/syuilo/misskey/releases/latest).
|
||||
|
||||
`git checkout master`
|
||||
|
||||
*2.* Configuration de Misskey
|
||||
----------------------------------------------------------------
|
||||
@@ -38,9 +46,9 @@ Parfait, Vous avez un environnement prêt pour démarrer Misskey.
|
||||
Utilisez la commande `docker-compose up -d`. GLHF!
|
||||
|
||||
### How to update your Misskey server to the latest version
|
||||
1. `git fetch`
|
||||
2. `git stash`
|
||||
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)`
|
||||
1. `git stash`
|
||||
2. `git checkout master`
|
||||
3. `git pull`
|
||||
4. `git stash pop`
|
||||
5. `docker-compose build`
|
||||
6. Consultez le [ChangeLog](../CHANGELOG.md) pour avoir les éventuelles informations de migration
|
||||
@@ -52,14 +60,28 @@ Utilisez la commande `docker-compose up -d`. GLHF!
|
||||
### Configuration d'ElasticSearch (pour la fonction de recherche)
|
||||
*1.* Préparation de l'environnement
|
||||
----------------------------------------------------------------
|
||||
1. `mkdir elasticsearch && chown 1000:1000 elasticsearch` Permet de créer le dossier d'accueil de la base ElasticSearch aves les bons droits
|
||||
2. `sysctl -w vm.max_map_count=262144` Augmente la valeur max du paramètre map_count du système (valeur minimum pour pouvoir lancer ES)
|
||||
1. Permet de créer le dossier d'accueil de la base ElasticSearch aves les bons droits
|
||||
|
||||
`mkdir elasticsearch && chown 1000:1000 elasticsearch`
|
||||
|
||||
2. Augmente la valeur max du paramètre map_count du système (valeur minimum pour pouvoir lancer ES)
|
||||
|
||||
`sysctl -w vm.max_map_count=262144`
|
||||
|
||||
*2.* Après lancement du docker-compose, initialisation de la base ElasticSearch
|
||||
----------------------------------------------------------------
|
||||
1. `docker-compose -it web /bin/sh` Connexion dans le conteneur web
|
||||
2. `apk add curl` Ajout du paquet curl
|
||||
3. `curl -X PUT "es:9200/misskey" -H 'Content-Type: application/json' -d'{ "settings" : { "index" : { } }}'` Création de la base ES
|
||||
1. Connexion dans le conteneur web
|
||||
|
||||
`docker-compose -it web /bin/sh`
|
||||
|
||||
2. Ajout du paquet curl
|
||||
|
||||
`apk add curl`
|
||||
|
||||
3. Création de la base ES
|
||||
|
||||
`curl -X PUT "es:9200/misskey" -H 'Content-Type: application/json' -d'{ "settings" : { "index" : { } }}'`
|
||||
|
||||
4. `exit`
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
@@ -9,15 +9,51 @@ Dockerを使ったMisskey構築方法
|
||||
|
||||
*1.* Misskeyのダウンロード
|
||||
----------------------------------------------------------------
|
||||
1. `git clone -b master git://github.com/syuilo/misskey.git` masterブランチからMisskeyレポジトリをクローン
|
||||
2. `cd misskey` misskeyディレクトリに移動
|
||||
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認
|
||||
1. masterブランチからMisskeyレポジトリをクローン
|
||||
|
||||
*2.* 設定ファイルを作成する
|
||||
`git clone -b master git://github.com/syuilo/misskey.git`
|
||||
|
||||
2. misskeyディレクトリに移動
|
||||
|
||||
`cd misskey`
|
||||
|
||||
3. [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認
|
||||
|
||||
`git checkout master`
|
||||
|
||||
*2.* 設定ファイルの作成と編集
|
||||
----------------------------------------------------------------
|
||||
1. `cp .config/example.yml .config/default.yml` `.config/example.yml`をコピーし名前を`default.yml`にする
|
||||
2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` `.config/mongo_initdb_example.js`をコピーし名前を`mongo_initdb.js`にする
|
||||
3. `default.yml`と`mongo_initdb.js`を編集する
|
||||
|
||||
下記コマンドで設定ファイルを作成してください。
|
||||
|
||||
```bash
|
||||
cd .config
|
||||
cp example.yml default.yml
|
||||
cp docker_example.env docker.env
|
||||
```
|
||||
|
||||
### `default.yml`の編集
|
||||
|
||||
非Docker環境と同じ様に編集してください。
|
||||
ただし、Postgresql、RedisとElasticsearchのホストは`localhost`ではなく、`docker-compose.yml`で設定されたサービス名になっています。
|
||||
標準設定では次の通りです。
|
||||
|
||||
| サービス | ホスト名 |
|
||||
|---------------|---------|
|
||||
| Postgresql |`db` |
|
||||
| Redis |`redis` |
|
||||
| Elasticsearch |`es` |
|
||||
|
||||
### `docker.env`の編集
|
||||
|
||||
このファイルはPostgresqlの設定を記述します。
|
||||
最低限記述する必要がある設定は次の通りです。
|
||||
|
||||
| 設定 | 内容 |
|
||||
|---------------------|--------------|
|
||||
| `POSTGRES_PASSWORD` | パスワード |
|
||||
| `POSTGRES_USER` | ユーザー名 |
|
||||
| `POSTGRES_DB` | データベース名 |
|
||||
|
||||
*3.* Dockerの設定
|
||||
----------------------------------------------------------------
|
||||
@@ -29,7 +65,13 @@ Dockerを使ったMisskey構築方法
|
||||
|
||||
`docker-compose build`
|
||||
|
||||
*5.* 以上です!
|
||||
*5.* データベースを初期化
|
||||
----------------------------------------------------------------
|
||||
``` shell
|
||||
docker-compose run --rm web npm run init
|
||||
```
|
||||
|
||||
*6.* 以上です!
|
||||
----------------------------------------------------------------
|
||||
お疲れ様でした。これでMisskeyを動かす準備は整いました。
|
||||
|
||||
@@ -37,9 +79,9 @@ Dockerを使ったMisskey構築方法
|
||||
`docker-compose up -d`するだけです。GLHF!
|
||||
|
||||
### Misskeyを最新バージョンにアップデートする方法:
|
||||
1. `git fetch`
|
||||
2. `git stash`
|
||||
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)`
|
||||
1. `git stash`
|
||||
2. `git checkout master`
|
||||
3. `git pull`
|
||||
4. `git stash pop`
|
||||
5. `docker-compose build`
|
||||
6. [ChangeLog](../CHANGELOG.md)でマイグレーション情報を確認する
|
||||
|
@@ -29,7 +29,7 @@ server {
|
||||
listen [::]:443 http2;
|
||||
server_name example.tld;
|
||||
ssl on;
|
||||
ssl_session_cache shared:ssl_session_cache:10m;
|
||||
ssl_session_cache shared:ssl_session_cache:10m;
|
||||
|
||||
# To use Let's Encrypt certificate
|
||||
ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem;
|
||||
|
106
docs/setup.en.md
106
docs/setup.en.md
@@ -22,37 +22,45 @@ adduser --disabled-password --disabled-login misskey
|
||||
Please install and setup these softwares:
|
||||
|
||||
#### Dependencies :package:
|
||||
* **[Node.js](https://nodejs.org/en/)** >= 10.0.0
|
||||
* **[MongoDB](https://www.mongodb.com/)** >= 3.6
|
||||
* **[Node.js](https://nodejs.org/en/)** >= 11.7.0
|
||||
* **[PostgreSQL](https://www.postgresql.org/)** >= 10
|
||||
* **[Redis](https://redis.io/)**
|
||||
|
||||
##### Optional
|
||||
* [Redis](https://redis.io/)
|
||||
* Redis is optional, but we strongly recommended to install it
|
||||
* [Elasticsearch](https://www.elastic.co/) - required to enable the search feature
|
||||
* [FFmpeg](https://www.ffmpeg.org/)
|
||||
|
||||
*3.* Setup MongoDB
|
||||
*3.* Install Misskey
|
||||
----------------------------------------------------------------
|
||||
As root:
|
||||
1. `mongo` Go to the mongo shell
|
||||
2. `use misskey` Use the misskey database
|
||||
3. `db.createUser( { user: "misskey", pwd: "<password>", roles: [ { role: "readWrite", db: "misskey" } ] } )` Create the misskey user.
|
||||
4. `exit` You're done!
|
||||
1. Connect to misskey user.
|
||||
|
||||
*4.* Install Misskey
|
||||
----------------------------------------------------------------
|
||||
1. `su - misskey` Connect to misskey user.
|
||||
2. `git clone -b master git://github.com/syuilo/misskey.git` Clone the misskey repo from master branch.
|
||||
3. `cd misskey` Navigate to misskey directory
|
||||
4. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest)
|
||||
5. `npm install` Install misskey dependencies.
|
||||
`su - misskey`
|
||||
|
||||
*5.* Configure Misskey
|
||||
2. Clone the misskey repo from master branch.
|
||||
|
||||
`git clone -b master git://github.com/syuilo/misskey.git`
|
||||
|
||||
3. Navigate to misskey directory
|
||||
|
||||
`cd misskey`
|
||||
|
||||
4. Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest)
|
||||
|
||||
`git checkout master`
|
||||
|
||||
5. Install misskey dependencies.
|
||||
|
||||
`npm install`
|
||||
|
||||
*4.* Configure Misskey
|
||||
----------------------------------------------------------------
|
||||
1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`.
|
||||
1. Copy the `.config/example.yml` and rename it to `default.yml`.
|
||||
|
||||
`cp .config/example.yml .config/default.yml`
|
||||
|
||||
2. Edit `default.yml`
|
||||
|
||||
*6.* Build Misskey
|
||||
*5.* Build Misskey
|
||||
----------------------------------------------------------------
|
||||
|
||||
Build misskey with the following:
|
||||
@@ -68,6 +76,12 @@ If you're still encountering errors about some modules, use node-gyp:
|
||||
3. `node-gyp build`
|
||||
4. `NODE_ENV=production npm run build`
|
||||
|
||||
*6.* Init DB
|
||||
----------------------------------------------------------------
|
||||
``` shell
|
||||
npm run init
|
||||
```
|
||||
|
||||
*7.* That is it.
|
||||
----------------------------------------------------------------
|
||||
Well done! Now, you have an environment that run to Misskey.
|
||||
@@ -77,37 +91,45 @@ Just `NODE_ENV=production npm start`. GLHF!
|
||||
|
||||
### Launch with systemd
|
||||
|
||||
1. Create a systemd service here: `/etc/systemd/system/misskey.service`
|
||||
1. Create a systemd service here
|
||||
|
||||
`/etc/systemd/system/misskey.service`
|
||||
|
||||
2. Edit it, and paste this and save:
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=Misskey daemon
|
||||
```
|
||||
[Unit]
|
||||
Description=Misskey daemon
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=misskey
|
||||
ExecStart=/usr/bin/npm start
|
||||
WorkingDirectory=/home/misskey/misskey
|
||||
Environment="NODE_ENV=production"
|
||||
TimeoutSec=60
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=misskey
|
||||
Restart=always
|
||||
[Service]
|
||||
Type=simple
|
||||
User=misskey
|
||||
ExecStart=/usr/bin/npm start
|
||||
WorkingDirectory=/home/misskey/misskey
|
||||
Environment="NODE_ENV=production"
|
||||
TimeoutSec=60
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=misskey
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
3. `systemctl daemon-reload ; systemctl enable misskey` Reload systemd and enable the misskey service.
|
||||
4. `systemctl start misskey` Start the misskey service.
|
||||
3. Reload systemd and enable the misskey service.
|
||||
|
||||
`systemctl daemon-reload ; systemctl enable misskey`
|
||||
|
||||
4. Start the misskey service.
|
||||
|
||||
`systemctl start misskey`
|
||||
|
||||
You can check if the service is running with `systemctl status misskey`.
|
||||
|
||||
### How to update your Misskey server to the latest version
|
||||
1. `git fetch`
|
||||
2. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)`
|
||||
1. `git checkout master`
|
||||
2. `git pull`
|
||||
3. `npm install`
|
||||
4. `NODE_ENV=production npm run build`
|
||||
5. Check [ChangeLog](../CHANGELOG.md) for migration information
|
||||
|
102
docs/setup.fr.md
102
docs/setup.fr.md
@@ -22,37 +22,45 @@ adduser --disabled-password --disabled-login misskey
|
||||
Installez les paquets suivants :
|
||||
|
||||
#### Dépendences :package:
|
||||
* **[Node.js](https://nodejs.org/en/)** >= 10.0.0
|
||||
* **[MongoDB](https://www.mongodb.com/)** >= 3.6
|
||||
* **[Node.js](https://nodejs.org/en/)** >= 11.7.0
|
||||
* **[PostgreSQL](https://www.postgresql.org/)** >= 10
|
||||
* **[Redis](https://redis.io/)**
|
||||
|
||||
##### Optionnels
|
||||
* [Redis](https://redis.io/)
|
||||
* Redis est optionnel mais nous vous recommandons vivement de l'installer
|
||||
* [Elasticsearch](https://www.elastic.co/) - requis pour pouvoir activer la fonctionnalité de recherche
|
||||
* [FFmpeg](https://www.ffmpeg.org/)
|
||||
|
||||
*3.* Paramètrage de MongoDB
|
||||
*3.* Installation de Misskey
|
||||
----------------------------------------------------------------
|
||||
En root :
|
||||
1. `mongo` Ouvrez le shell mongo
|
||||
2. `use misskey` Utilisez la base de données misskey
|
||||
3. `db.createUser( { user: "misskey", pwd: "<password>", roles: [ { role: "readWrite", db: "misskey" } ] } )` Créez l'utilisateur misskey.
|
||||
4. `exit` Vous avez terminé !
|
||||
1. Basculez vers l'utilisateur misskey.
|
||||
|
||||
*4.* Installation de Misskey
|
||||
----------------------------------------------------------------
|
||||
1. `su - misskey` Basculez vers l'utilisateur misskey.
|
||||
2. `git clone -b master git://github.com/syuilo/misskey.git` Clonez la branche master du dépôt misskey.
|
||||
3. `cd misskey` Accédez au dossier misskey.
|
||||
4. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` Checkout sur le tag de la [version la plus récente](https://github.com/syuilo/misskey/releases/latest)
|
||||
5. `npm install` Installez les dépendances de misskey.
|
||||
`su - misskey`
|
||||
|
||||
*5.* Création du fichier de configuration
|
||||
2. Clonez la branche master du dépôt misskey.
|
||||
|
||||
`git clone -b master git://github.com/syuilo/misskey.git`
|
||||
|
||||
3. Accédez au dossier misskey.
|
||||
|
||||
`cd misskey`
|
||||
|
||||
4. Checkout sur le tag de la [version la plus récente](https://github.com/syuilo/misskey/releases/latest)
|
||||
|
||||
`git checkout master`
|
||||
|
||||
5. Installez les dépendances de misskey.
|
||||
|
||||
`npm install`
|
||||
|
||||
*4.* Création du fichier de configuration
|
||||
----------------------------------------------------------------
|
||||
1. `cp .config/example.yml .config/default.yml` Copiez le fichier `.config/example.yml` et renommez-le`default.yml`.
|
||||
1. Copiez le fichier `.config/example.yml` et renommez-le`default.yml`.
|
||||
|
||||
`cp .config/example.yml .config/default.yml`
|
||||
|
||||
2. Editez le fichier `default.yml`
|
||||
|
||||
*6.* Construction de Misskey
|
||||
*5.* Construction de Misskey
|
||||
----------------------------------------------------------------
|
||||
|
||||
Construisez Misskey comme ceci :
|
||||
@@ -68,7 +76,7 @@ Si vous rencontrez des erreurs concernant certains modules, utilisez node-gyp:
|
||||
3. `node-gyp build`
|
||||
4. `NODE_ENV=production npm run build`
|
||||
|
||||
*7.* C'est tout.
|
||||
*6.* C'est tout.
|
||||
----------------------------------------------------------------
|
||||
Excellent ! Maintenant, vous avez un environnement prêt pour lancer Misskey
|
||||
|
||||
@@ -77,37 +85,45 @@ Lancez tout simplement `NODE_ENV=production npm start`. Bonne chance et amusez-v
|
||||
|
||||
### Démarrage avec systemd
|
||||
|
||||
1. Créez un service systemd sur : `/etc/systemd/system/misskey.service`
|
||||
1. Créez un service systemd sur
|
||||
|
||||
`/etc/systemd/system/misskey.service`
|
||||
|
||||
2. Editez-le puis copiez et coller ceci dans le fichier :
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=Misskey daemon
|
||||
```
|
||||
[Unit]
|
||||
Description=Misskey daemon
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=misskey
|
||||
ExecStart=/usr/bin/npm start
|
||||
WorkingDirectory=/home/misskey/misskey
|
||||
Environment="NODE_ENV=production"
|
||||
TimeoutSec=60
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=misskey
|
||||
Restart=always
|
||||
[Service]
|
||||
Type=simple
|
||||
User=misskey
|
||||
ExecStart=/usr/bin/npm start
|
||||
WorkingDirectory=/home/misskey/misskey
|
||||
Environment="NODE_ENV=production"
|
||||
TimeoutSec=60
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=misskey
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
3. `systemctl daemon-reload ; systemctl enable misskey` Redémarre systemd et active le service misskey.
|
||||
4. `systemctl start misskey` Démarre le service misskey.
|
||||
3. Redémarre systemd et active le service misskey.
|
||||
|
||||
`systemctl daemon-reload ; systemctl enable misskey`
|
||||
|
||||
4. Démarre le service misskey.
|
||||
|
||||
`systemctl start misskey`
|
||||
|
||||
Vous pouvez vérifier si le service a démarré en utilisant la commande `systemctl status misskey`.
|
||||
|
||||
### Méthode de mise à jour vers la plus récente version de Misskey
|
||||
1. `git fetch`
|
||||
2. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)`
|
||||
1. `git checkout master`
|
||||
2. `git pull`
|
||||
3. `npm install`
|
||||
4. `NODE_ENV=production npm run build`
|
||||
5. Consultez [ChangeLog](../CHANGELOG.md) pour les information de migration.
|
||||
|
117
docs/setup.ja.md
117
docs/setup.ja.md
@@ -22,44 +22,46 @@ adduser --disabled-password --disabled-login misskey
|
||||
これらのソフトウェアをインストール・設定してください:
|
||||
|
||||
#### 依存関係 :package:
|
||||
* **[Node.js](https://nodejs.org/en/)** (10.0.0以上)
|
||||
* **[MongoDB](https://www.mongodb.com/)** (3.6以上)
|
||||
* **[Node.js](https://nodejs.org/en/)** (11.7.0以上)
|
||||
* **[PostgreSQL](https://www.postgresql.org/)** (10以上)
|
||||
* **[Redis](https://redis.io/)**
|
||||
|
||||
##### オプション
|
||||
* [Redis](https://redis.io/)
|
||||
* Redisはオプションですが、インストールすることを強く推奨します。
|
||||
* インストールしなくていいのは、あなたのインスタンスが自分専用のときだけとお考えください。
|
||||
* 具体的には、Redisをインストールしないと、次の事が出来なくなります:
|
||||
* Misskeyプロセスを複数起動しての負荷分散
|
||||
* レートリミット
|
||||
* ジョブキュー
|
||||
* Twitter連携
|
||||
* [Elasticsearch](https://www.elastic.co/)
|
||||
* 検索機能を有効にするためにはインストールが必要です。
|
||||
* [FFmpeg](https://www.ffmpeg.org/)
|
||||
|
||||
*3.* MongoDBの設定
|
||||
*3.* Misskeyのインストール
|
||||
----------------------------------------------------------------
|
||||
ルートで:
|
||||
1. `mongo` mongoシェルを起動
|
||||
2. `use misskey` misskeyデータベースを使用
|
||||
3. `db.createUser( { user: "misskey", pwd: "<password>", roles: [ { role: "readWrite", db: "misskey" } ] } )` misskeyユーザーを作成
|
||||
4. `exit` mongoシェルを終了
|
||||
1. misskeyユーザーを使用
|
||||
|
||||
*4.* Misskeyのインストール
|
||||
----------------------------------------------------------------
|
||||
1. `su - misskey` misskeyユーザーを使用
|
||||
2. `git clone -b master git://github.com/syuilo/misskey.git` masterブランチからMisskeyレポジトリをクローン
|
||||
3. `cd misskey` misskeyディレクトリに移動
|
||||
4. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認
|
||||
5. `npm install` Misskeyの依存パッケージをインストール
|
||||
`su - misskey`
|
||||
|
||||
*5.* 設定ファイルを作成する
|
||||
2. masterブランチからMisskeyレポジトリをクローン
|
||||
|
||||
`git clone -b master git://github.com/syuilo/misskey.git`
|
||||
|
||||
3. misskeyディレクトリに移動
|
||||
|
||||
`cd misskey`
|
||||
|
||||
4. [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認
|
||||
|
||||
`git checkout master`
|
||||
|
||||
5. Misskeyの依存パッケージをインストール
|
||||
|
||||
`npm install`
|
||||
|
||||
*4.* 設定ファイルを作成する
|
||||
----------------------------------------------------------------
|
||||
1. `cp .config/example.yml .config/default.yml` `.config/example.yml`をコピーし名前を`default.yml`にする。
|
||||
1. `.config/example.yml`をコピーし名前を`default.yml`にする。
|
||||
|
||||
`cp .config/example.yml .config/default.yml`
|
||||
|
||||
2. `default.yml` を編集する。
|
||||
|
||||
*6.* Misskeyのビルド
|
||||
*5.* Misskeyのビルド
|
||||
----------------------------------------------------------------
|
||||
|
||||
次のコマンドでMisskeyをビルドしてください:
|
||||
@@ -74,6 +76,12 @@ Debianをお使いであれば、`build-essential`パッケージをインスト
|
||||
3. `node-gyp build`
|
||||
4. `NODE_ENV=production npm run build`
|
||||
|
||||
*6.* データベースを初期化
|
||||
----------------------------------------------------------------
|
||||
``` shell
|
||||
npm run init
|
||||
```
|
||||
|
||||
*7.* 以上です!
|
||||
----------------------------------------------------------------
|
||||
お疲れ様でした。これでMisskeyを動かす準備は整いました。
|
||||
@@ -82,43 +90,52 @@ Debianをお使いであれば、`build-essential`パッケージをインスト
|
||||
`NODE_ENV=production npm start`するだけです。GLHF!
|
||||
|
||||
### systemdを用いた起動
|
||||
1. systemdサービスのファイルを作成: `/etc/systemd/system/misskey.service`
|
||||
1. systemdサービスのファイルを作成
|
||||
|
||||
`/etc/systemd/system/misskey.service`
|
||||
|
||||
2. エディタで開き、以下のコードを貼り付けて保存:
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=Misskey daemon
|
||||
```
|
||||
[Unit]
|
||||
Description=Misskey daemon
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=misskey
|
||||
ExecStart=/usr/bin/npm start
|
||||
WorkingDirectory=/home/misskey/misskey
|
||||
Environment="NODE_ENV=production"
|
||||
TimeoutSec=60
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=misskey
|
||||
Restart=always
|
||||
[Service]
|
||||
Type=simple
|
||||
User=misskey
|
||||
ExecStart=/usr/bin/npm start
|
||||
WorkingDirectory=/home/misskey/misskey
|
||||
Environment="NODE_ENV=production"
|
||||
TimeoutSec=60
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=misskey
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
CentOSで1024以下のポートを使用してMisskeyを使用する場合は`ExecStart=/usr/bin/sudo /usr/bin/npm start`に変更する必要があります。
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
3. `systemctl daemon-reload ; systemctl enable misskey` systemdを再読み込みしmisskeyサービスを有効化
|
||||
4. `systemctl start misskey` misskeyサービスの起動
|
||||
CentOSで1024以下のポートを使用してMisskeyを使用する場合は`ExecStart=/usr/bin/sudo /usr/bin/npm start`に変更する必要があります。
|
||||
|
||||
3. systemdを再読み込みしmisskeyサービスを有効化
|
||||
|
||||
`systemctl daemon-reload ; systemctl enable misskey`
|
||||
|
||||
4. misskeyサービスの起動
|
||||
|
||||
`systemctl start misskey`
|
||||
|
||||
`systemctl status misskey`と入力すると、サービスの状態を調べることができます。
|
||||
|
||||
### Misskeyを最新バージョンにアップデートする方法:
|
||||
1. `git fetch`
|
||||
2. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)`
|
||||
1. `git checkout master`
|
||||
2. `git pull`
|
||||
3. `npm install`
|
||||
4. `NODE_ENV=production npm run build`
|
||||
5. [ChangeLog](../CHANGELOG.md)でマイグレーション情報を確認する
|
||||
|
||||
なにか問題が発生した場合は、`npm run clean`すると直る場合があります。
|
||||
なにか問題が発生した場合は、`npm run clean`または`npm run cleanall`すると直る場合があります。
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
|
11
gulpfile.ts
11
gulpfile.ts
@@ -5,7 +5,6 @@
|
||||
import * as gulp from 'gulp';
|
||||
import * as gutil from 'gulp-util';
|
||||
import * as ts from 'gulp-typescript';
|
||||
const yaml = require('gulp-yaml');
|
||||
const sourcemaps = require('gulp-sourcemaps');
|
||||
import tslint from 'gulp-tslint';
|
||||
const cssnano = require('gulp-cssnano');
|
||||
@@ -50,7 +49,6 @@ gulp.task('build:copy:views', () =>
|
||||
|
||||
gulp.task('build:copy', gulp.parallel('build:copy:views', () =>
|
||||
gulp.src([
|
||||
'./build/Release/crypto_key.node',
|
||||
'./src/const.json',
|
||||
'./src/server/web/views/**/*',
|
||||
'./src/**/assets/**/*',
|
||||
@@ -121,17 +119,11 @@ gulp.task('copy:client', () =>
|
||||
])
|
||||
.pipe(isProduction ? (imagemin as any)() : gutil.noop())
|
||||
.pipe(rename(path => {
|
||||
path.dirname = path.dirname.replace('assets', '.');
|
||||
path.dirname = path.dirname!.replace('assets', '.');
|
||||
}))
|
||||
.pipe(gulp.dest('./built/client/assets/'))
|
||||
);
|
||||
|
||||
gulp.task('locales', () =>
|
||||
gulp.src('./locales/*.yml')
|
||||
.pipe(yaml({ schema: 'DEFAULT_SAFE_SCHEMA' }))
|
||||
.pipe(gulp.dest('./built/client/assets/locales/'))
|
||||
);
|
||||
|
||||
gulp.task('doc', () =>
|
||||
gulp.src('./src/docs/**/*.styl')
|
||||
.pipe(stylus())
|
||||
@@ -149,7 +141,6 @@ gulp.task('build', gulp.parallel(
|
||||
'build:ts',
|
||||
'build:copy',
|
||||
'build:client',
|
||||
'locales',
|
||||
'doc'
|
||||
));
|
||||
|
||||
|
1623
locales/ca-ES.yml
1623
locales/ca-ES.yml
File diff suppressed because it is too large
Load Diff
1200
locales/cs-CZ.yml
Normal file
1200
locales/cs-CZ.yml
Normal file
File diff suppressed because it is too large
Load Diff
1313
locales/de-DE.yml
1313
locales/de-DE.yml
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
---
|
||||
meta:
|
||||
lang: "English"
|
||||
divider: ""
|
||||
common:
|
||||
misskey: "A ⭐ of the fediverse"
|
||||
about-title: "A ⭐ of the fediverse."
|
||||
@@ -25,8 +24,8 @@ common:
|
||||
application-authorization: "Application authorizations"
|
||||
close: "Close"
|
||||
do-not-copy-paste: "Please do not enter or paste the code here. Account may be compromised."
|
||||
load-more: "Load more"
|
||||
enter-password: "Please enter the Password"
|
||||
load-more: "Read more"
|
||||
enter-password: "Enter your password"
|
||||
2fa: "Two-factor authentication"
|
||||
customize-home: "Customize home layout"
|
||||
featured-notes: "Featured notes"
|
||||
@@ -70,6 +69,27 @@ common:
|
||||
following: "Following"
|
||||
followers: "Followers"
|
||||
favorites: "Favorites"
|
||||
permissions:
|
||||
"read:account": "View account information"
|
||||
"write:account": "Update your account information"
|
||||
"read:blocks": "View Blocks"
|
||||
"write:blocks": "Work with Blocks"
|
||||
"read:drive": "Browse the Drive"
|
||||
"write:drive": "Work with the Drive"
|
||||
"read:favorites": "View Favorites"
|
||||
"write:favorites": "Work with Favorites"
|
||||
"read:following": "View Follower info"
|
||||
"write:following": "Work with Follow info"
|
||||
"read:messaging": "View Messaging"
|
||||
"write:messaging": "Work with Messaging"
|
||||
"read:mutes": "View Muted"
|
||||
"write:mutes": "Work with Muted"
|
||||
"write:notes": "Create and delete posts"
|
||||
"read:notifications": "View notifications"
|
||||
"write:notifications": "Work with notifications"
|
||||
"read:reactions": "View reactions"
|
||||
"write:reactions": "Work with reactions"
|
||||
"write:votes": "Vote"
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "Following users will show their posts in your timeline."
|
||||
explore: "Find users"
|
||||
@@ -115,7 +135,7 @@ common:
|
||||
a: "What are you doing?"
|
||||
b: "What's happening?"
|
||||
c: "What’s on your mind?"
|
||||
d: "Would you post any words?"
|
||||
d: "What do you want to say?"
|
||||
e: "Write here"
|
||||
f: "Waiting for your writing."
|
||||
settings: "Settings"
|
||||
@@ -170,9 +190,9 @@ common:
|
||||
deck-column-align-flexible: "Flexible"
|
||||
deck-column-width: "Deck column width"
|
||||
deck-column-width-narrow: "Narrow"
|
||||
deck-column-width-narrower: "Somewhat narrow"
|
||||
deck-column-width-narrower: "Narrower"
|
||||
deck-column-width-normal: "Regular"
|
||||
deck-column-width-wider: "Somewhat wide"
|
||||
deck-column-width-wider: "Slightly wide"
|
||||
deck-column-width-wide: "Wide"
|
||||
use-shadow: "Use shadows in the UI"
|
||||
rounded-corners: "Round the corners of the UI"
|
||||
@@ -224,8 +244,8 @@ common:
|
||||
search: "Search"
|
||||
delete: "Delete"
|
||||
loading: "Loading"
|
||||
ok: "It's OK"
|
||||
cancel: "Quit"
|
||||
ok: "Confirm"
|
||||
cancel: "Cancel"
|
||||
update-available-title: "Update available"
|
||||
update-available: "A new version of Misskey is now available({newer}, the current version is {current}). Reload the page to apply updates."
|
||||
my-token-regenerated: "Your token has been regenerated, so you will be signed out."
|
||||
@@ -277,21 +297,13 @@ common:
|
||||
nav: "Navigation"
|
||||
tips: "Tips"
|
||||
hashtags: "Hashtags"
|
||||
queue: "Queue"
|
||||
dev: "Failed to create the application. Please try again."
|
||||
ai-chan-kawaii: "Ai-chan kawaii!"
|
||||
you: "You"
|
||||
auth/views/form.vue:
|
||||
share-access: "Would you allow <i>{name}</i> to access your account?"
|
||||
permission-ask: "This application requires the following permissions:"
|
||||
account-read: "View account information."
|
||||
account-write: "Modify account information."
|
||||
note-write: "Post."
|
||||
like-write: "React to posts."
|
||||
following-write: "Follow and unfollow."
|
||||
drive-read: "Read your drive."
|
||||
drive-write: "Upload/delete files in your drive."
|
||||
notification-read: "Read your notifications."
|
||||
notification-write: "Manage your notifications."
|
||||
cancel: "Cancel"
|
||||
accept: "Allow access."
|
||||
auth/views/index.vue:
|
||||
@@ -305,7 +317,7 @@ auth/views/index.vue:
|
||||
error: "Session does not exist."
|
||||
sign-in: "Please sign in."
|
||||
common/views/pages/explore.vue:
|
||||
verified-users: "Verified accounts"
|
||||
verified-users: "Official accounts"
|
||||
popular-users: "Popular users"
|
||||
recently-updated-users: "Recently active users"
|
||||
recently-registered-users: "Users who joined recently"
|
||||
@@ -315,6 +327,7 @@ common/views/pages/explore.vue:
|
||||
users-info: "Currently, {users} users are registered here"
|
||||
common/views/components/url-preview.vue:
|
||||
enable-player: "Enable playback"
|
||||
disable-player: "Close the player"
|
||||
common/views/components/user-list.vue:
|
||||
no-users: "There are no users."
|
||||
common/views/components/games/reversi/reversi.vue:
|
||||
@@ -476,30 +489,57 @@ common/views/components/user-menu.vue:
|
||||
mention: "Mention"
|
||||
mute: "Mute"
|
||||
unmute: "Unmute"
|
||||
mute-confirm: "Are you sure you want to mute this user?"
|
||||
unmute-confirm: "Are you certain that you want to unmute this user?"
|
||||
block: "Block"
|
||||
unblock: "Unblock"
|
||||
block-confirm: "Are you sure you want to block this user?"
|
||||
unblock-confirm: "Are you certain that you want to unblock this user?"
|
||||
push-to-list: "Add to list"
|
||||
select-list: "Select a list"
|
||||
report-abuse: "Report abuse"
|
||||
report-abuse-detail: "What kind of nuisance did you encounter?"
|
||||
report-abuse-reported: "The issue has been reported to the administrator. Your cooperation is much appreciated."
|
||||
silence: "Mute"
|
||||
unsilence: "Unmute"
|
||||
silence: "Silence"
|
||||
unsilence: "Unsilence"
|
||||
silence-confirm: "Are you sure that you want to silence this user?"
|
||||
unsilence-confirm: "Are you sure that you want to stop silencing this user?"
|
||||
suspend: "Suspend"
|
||||
unsuspend: "Unsuspend"
|
||||
suspend-confirm: "Are you sure that you want to suspend this user?"
|
||||
unsuspend-confirm: "Are you sure that you want to unsuspend this user?"
|
||||
common/views/components/poll.vue:
|
||||
vote-to: "Vote for '{}'"
|
||||
vote-count: "{} votes"
|
||||
total-users: "{} users voted"
|
||||
total-votes: "{} votes in total"
|
||||
vote: "Vote"
|
||||
show-result: "Show results"
|
||||
voted: "Voted"
|
||||
closed: "Ended"
|
||||
remaining-days: "{d} days, {h} hours remain"
|
||||
remaining-hours: "{h} hours, and {m} minutes remain"
|
||||
remaining-minutes: "{m} minutes, and {s} seconds remaining"
|
||||
remaining-seconds: "{s} seconds remaining"
|
||||
common/views/components/poll-editor.vue:
|
||||
no-only-one-choice: "At least two choices are required"
|
||||
choice-n: "Choice {}"
|
||||
remove: "Delete the choice"
|
||||
add: "+ Add a choice"
|
||||
destroy: "Discard the poll"
|
||||
multiple: "More than one answer is allowed"
|
||||
expiration: "Valid until"
|
||||
infinite: "Indefinitely"
|
||||
at: "Date and time pick"
|
||||
after: "Progression specifics"
|
||||
no-more: "You cannot add any more"
|
||||
deadline-date: "Finish date"
|
||||
deadline-time: "Time duration"
|
||||
interval: "Duration"
|
||||
unit: "Unit"
|
||||
second: "Seconds"
|
||||
minute: "Minutes"
|
||||
hour: "Hours"
|
||||
day: "S"
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "Send a reaction"
|
||||
common/views/components/emoji-picker.vue:
|
||||
@@ -521,7 +561,7 @@ common/views/components/signin.vue:
|
||||
signin-with-twitter: "Log in with Twitter"
|
||||
signin-with-github: "Sign in with GitHub"
|
||||
signin-with-discord: "Sign in with Discord"
|
||||
login-failed: "Log in failed. Make sure you have entered your correct username and password."
|
||||
login-failed: "Logging in has failed. Make sure you have entered the correct username and password."
|
||||
common/views/components/signup.vue:
|
||||
invitation-code: "Invitation code"
|
||||
invitation-info: "If you do not have an invitation code, please contact an <a href=\"{}\">administrator</a>."
|
||||
@@ -629,12 +669,16 @@ common/views/components/profile-editor.vue:
|
||||
email-verified: "Your email has been verified."
|
||||
email-not-verified: "Email address is not confirmed. Please check your inbox."
|
||||
export: "Export"
|
||||
import: "Import"
|
||||
export-and-import: "Export and Import"
|
||||
export-targets:
|
||||
all-notes: "All posted Notes"
|
||||
following-list: "List of followers"
|
||||
mute-list: "List of muted accounts"
|
||||
blocking-list: "List of blocked accounts"
|
||||
user-lists: "Lists"
|
||||
export-requested: "You have requested an export. This may take a while. After the export is complete, the resulting file will be added to the drive."
|
||||
import-requested: "You have initiated an import. This may take quite some time."
|
||||
enter-password: "Please enter your password"
|
||||
danger-zone: "Cautious options"
|
||||
delete-account: "Remove the account"
|
||||
@@ -646,6 +690,9 @@ common/views/components/user-list-editor.vue:
|
||||
remove-user: "Remove from this list"
|
||||
delete-are-you-sure: "Delete list \"$1\"?"
|
||||
deleted: "Deleted successfully"
|
||||
common/views/components/user-lists.vue:
|
||||
create-list: "Create a list"
|
||||
list-name: "List name"
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "Checking"
|
||||
no-broadcasts: "No announcements"
|
||||
@@ -816,10 +863,6 @@ desktop/views/components/home.vue:
|
||||
desktop/views/input-dialog.vue:
|
||||
cancel: "Cancel"
|
||||
ok: "OK"
|
||||
desktop/views/components/messaging-room-window.vue:
|
||||
title: "Messages:"
|
||||
desktop/views/components/messaging-window.vue:
|
||||
title: "Messaging"
|
||||
desktop/views/components/note-detail.vue:
|
||||
private: "Post is private"
|
||||
deleted: "Post has been removed"
|
||||
@@ -858,7 +901,6 @@ desktop/views/components/post-form.vue:
|
||||
posting: "Posting"
|
||||
attach-media-from-local: "Attach media from your device"
|
||||
attach-media-from-drive: "Attach media from your Drive"
|
||||
attach-cancel: "Cancel attachment"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "Create a poll"
|
||||
text-remain: "{} characters remaining"
|
||||
@@ -951,6 +993,10 @@ common/views/components/password-settings.vue:
|
||||
not-match: "The new passwords do not match"
|
||||
changed: "Password changed"
|
||||
failed: "Failed to change password"
|
||||
common/views/components/post-form-attaches.vue:
|
||||
attach-cancel: "Remove Attachment"
|
||||
mark-as-sensitive: "Mark as 'sensitive'"
|
||||
unmark-as-sensitive: "Unmark as 'sensitive'"
|
||||
desktop/views/components/sub-note-content.vue:
|
||||
private: "This post is private"
|
||||
deleted: "This post has been deleted"
|
||||
@@ -961,18 +1007,16 @@ desktop/views/components/settings.tags.vue:
|
||||
query: "Query (optional)"
|
||||
add: "Add"
|
||||
save: "Save"
|
||||
desktop/views/components/taskmanager.vue:
|
||||
title: "Task Manager"
|
||||
desktop/views/components/timeline.vue:
|
||||
home: "Home"
|
||||
local: "Local"
|
||||
hybrid: "Social"
|
||||
global: "Global"
|
||||
mentions: "Mentions"
|
||||
messages: "Messages"
|
||||
messages: "Direct posts"
|
||||
list: "Lists"
|
||||
hashtag: "Hashtag"
|
||||
add-tag-timeline: "Add hashtag tl"
|
||||
add-tag-timeline: "Add hashtag cloud"
|
||||
add-list: "Add list"
|
||||
list-name: "List name"
|
||||
desktop/views/components/ui.header.vue:
|
||||
@@ -997,8 +1041,6 @@ desktop/views/components/received-follow-requests-window.vue:
|
||||
reject: "Reject"
|
||||
desktop/views/components/user-lists-window.vue:
|
||||
title: "User lists"
|
||||
create-list: "Create a list"
|
||||
list-name: "List name"
|
||||
desktop/views/components/user-preview.vue:
|
||||
notes: "Posts"
|
||||
following: "Following"
|
||||
@@ -1023,6 +1065,7 @@ admin/views/index.vue:
|
||||
hashtags: "Hashtags"
|
||||
abuse: "Abuse"
|
||||
queue: "Job Queue"
|
||||
logs: "Logs"
|
||||
back-to-misskey: "Back to Misskey"
|
||||
admin/views/dashboard.vue:
|
||||
dashboard: "Dashboard"
|
||||
@@ -1033,7 +1076,7 @@ admin/views/dashboard.vue:
|
||||
this-instance: "This instance"
|
||||
federated: "Federated"
|
||||
admin/views/queue.vue:
|
||||
operation: "Action(s)"
|
||||
title: "Queue"
|
||||
remove-all-jobs: "Clear all queued jobs"
|
||||
admin/views/abuse.vue:
|
||||
title: "Abuse"
|
||||
@@ -1089,15 +1132,12 @@ admin/views/instance.vue:
|
||||
disable-local-timeline: "Disable the Local Timeline"
|
||||
disable-global-timeline: "Disable global timeline"
|
||||
disabling-timelines-info: "Even if you disable these timelines, the administrator as well as moderators can use them continually."
|
||||
enable-emoji-reaction: "Enable pictograms for reactions"
|
||||
use-star-for-reaction-fallback: "Use the star as fallback for unknown reaction"
|
||||
invite: "Invite"
|
||||
save: "Save"
|
||||
saved: "Saved"
|
||||
user-recommendation-config: "Recommended users"
|
||||
enable-external-user-recommendation: "Enable external user recommendations"
|
||||
external-user-recommendation-engine: "Engine"
|
||||
external-user-recommendation-engine-desc: "Example : https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}"
|
||||
external-user-recommendation-timeout: "Timeout"
|
||||
external-user-recommendation-timeout-desc: "Number of milliseconds (ex. 300,000)"
|
||||
email-config: "Email server settings"
|
||||
email-config-info: "Used to confirm email and password reset etc."
|
||||
enable-email: "Enable email delivery"
|
||||
@@ -1177,8 +1217,10 @@ admin/views/users.vue:
|
||||
unsuspend: "Unsuspend"
|
||||
unsuspend-confirm: "Are you sure you want to unsuspend this account?"
|
||||
unsuspended: "The user has successfully unsuspended."
|
||||
make-silence: "Mute"
|
||||
unmake-silence: "Unmute"
|
||||
make-silence: "Silence"
|
||||
silence-confirm: "Silence user?"
|
||||
unmake-silence: "Unsilence"
|
||||
unsilence-confirm: "Are you certain that you want to stop silencing this user?"
|
||||
verify: "Verify account"
|
||||
verify-confirm: "Do you want this to be a verified account?"
|
||||
verified: "The account is now being verified"
|
||||
@@ -1196,7 +1238,7 @@ admin/views/users.vue:
|
||||
updatedAtAsc: "Last Updated (Ascending)"
|
||||
updatedAtDesc: "Last Updated (Descending)"
|
||||
state:
|
||||
title: "Status"
|
||||
title: "Sort"
|
||||
all: "All"
|
||||
admin: "Administrator"
|
||||
moderator: "Moderator"
|
||||
@@ -1251,13 +1293,14 @@ admin/views/announcements.vue:
|
||||
admin/views/hashtags.vue:
|
||||
hided-tags: "Hidden Tags"
|
||||
admin/views/federation.vue:
|
||||
federation: "Federation"
|
||||
instance: "Instance"
|
||||
host: "Host"
|
||||
notes: "Notes"
|
||||
users: "Users"
|
||||
following: "Following"
|
||||
followers: "Followers"
|
||||
status: "Status"
|
||||
caught-at: "Created at"
|
||||
status: "Statuses"
|
||||
latest-request-sent-at: "Time of last request sent"
|
||||
latest-request-received-at: "Last request received at"
|
||||
remove-all-following: "Withold all followers"
|
||||
@@ -1265,7 +1308,7 @@ admin/views/federation.vue:
|
||||
block: "Block"
|
||||
marked-as-closed: "Marked as closed"
|
||||
lookup: "Look up"
|
||||
instances: "Instances"
|
||||
instances: "Federated"
|
||||
instance-not-registered: "The instance has not been discovered"
|
||||
sort: "Sort by"
|
||||
sorts:
|
||||
@@ -1273,19 +1316,19 @@ admin/views/federation.vue:
|
||||
caughtAtDesc: "Date of discovery (Descending)"
|
||||
lastCommunicatedAtAsc: "The date and time of the older interactions"
|
||||
lastCommunicatedAtDesc: "The date and time of the newer interactions"
|
||||
notesAsc: "Order by least Notes posted"
|
||||
notesDesc: "Order by most Notes posted"
|
||||
notesAsc: "Least Notes posted"
|
||||
notesDesc: "Most Notes posted"
|
||||
usersAsc: "Less followers"
|
||||
usersDesc: "More followers"
|
||||
followingAsc: "Least followed"
|
||||
followingDesc: "Has more followers"
|
||||
followersAsc: "Sort by having less followers"
|
||||
followersDesc: "Sort by the larger number of followers"
|
||||
followingDesc: "Most followed"
|
||||
followersAsc: "Having less followers"
|
||||
followersDesc: "The largest number of followers"
|
||||
driveUsageAsc: "Least storage used"
|
||||
driveUsageDesc: "Most storage used"
|
||||
driveFilesAsc: "By the smallest number of files stored on Drive"
|
||||
driveFilesDesc: "By the largest number of files stored on Drive"
|
||||
state: "Status"
|
||||
driveFilesAsc: "Least files stored on Drive"
|
||||
driveFilesDesc: "The largest number of files stored on Drive"
|
||||
state: "Sort"
|
||||
states:
|
||||
all: "All"
|
||||
blocked: "Blocked"
|
||||
@@ -1328,8 +1371,6 @@ desktop/views/pages/selectdrive.vue:
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "Search feature is turned off in the settings for this instance."
|
||||
not-found: "No posts were found for '{q}'"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "Share on {name}"
|
||||
desktop/views/pages/tag.vue:
|
||||
no-posts-found: "No posts contains \"{q}\" found."
|
||||
desktop/views/pages/user-list.users.vue:
|
||||
@@ -1353,7 +1394,7 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "Following"
|
||||
followers: "Followers"
|
||||
is-bot: "This account is a Bot"
|
||||
no-description: "The user has not written their profile introduction"
|
||||
no-description: "This user has not written their profile introduction"
|
||||
years-old: "{age} years old"
|
||||
year: "/"
|
||||
month: "/"
|
||||
@@ -1364,8 +1405,6 @@ desktop/views/pages/user/user.timeline.vue:
|
||||
with-replies: "Posts and replies"
|
||||
with-media: "Media"
|
||||
my-posts: "My posts"
|
||||
desktop/views/widgets/messaging.vue:
|
||||
title: "Message"
|
||||
desktop/views/widgets/notifications.vue:
|
||||
title: "Notifications"
|
||||
desktop/views/widgets/polls.vue:
|
||||
@@ -1375,6 +1414,7 @@ desktop/views/widgets/polls.vue:
|
||||
desktop/views/widgets/post-form.vue:
|
||||
title: "Post"
|
||||
note: "Post"
|
||||
something-happened: "Could not be posted in this circumstance."
|
||||
desktop/views/widgets/profile.vue:
|
||||
update-banner: "Click to edit your banner"
|
||||
update-avatar: "Click to edit your avatar"
|
||||
@@ -1393,12 +1433,11 @@ mobile/views/components/drive.vue:
|
||||
file-count: "File(s)"
|
||||
nothing-in-drive: "There's nothing stored."
|
||||
folder-is-empty: "This folder is empty"
|
||||
prompt: "What do you want to do? (Please enter a number): <1 → Upload a file | 2 → Upload a file from a URL | 3 → Create a folder | 4 → Change this folder's name | 5 → Move this folder | 6 → Delete this folder>"
|
||||
deletion-alert: "Sorry! Deleting a folder is not yet implemented."
|
||||
folder-name: "Folder name"
|
||||
here-is-root: "Currently, you are on the root, not inside of any folder."
|
||||
url-prompt: "URL of the file you want to upload"
|
||||
uploading: "Upload requested. It may take a while for the upload to finish."
|
||||
folder-name-cannot-empty: "Folder name cannot be blank."
|
||||
mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "Choose files"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
@@ -1451,7 +1490,7 @@ mobile/views/components/post-form.vue:
|
||||
quote-placeholder: "Quote this post... (optional)"
|
||||
reply-placeholder: "Reply to this note..."
|
||||
cw-placeholder: "Comments for the post (optional)"
|
||||
location-alert: "Your device does not provide location services"
|
||||
geolocation-alert: "Your device does not provide location services."
|
||||
error: "Error"
|
||||
username-prompt: "Enter user name"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
@@ -1472,9 +1511,16 @@ mobile/views/components/ui.nav.vue:
|
||||
game: "Games"
|
||||
admin: "Admin"
|
||||
about: "About Misskey"
|
||||
mobile/views/pages/drive.vue:
|
||||
contextmenu:
|
||||
upload: "Upload a file"
|
||||
url-upload: "Upload file from a URL"
|
||||
create-folder: "Create a folder"
|
||||
rename-folder: "Rename folder"
|
||||
move-folder: "Move this folder"
|
||||
delete-folder: "Delete this folder"
|
||||
mobile/views/pages/user-lists.vue:
|
||||
title: "Lists"
|
||||
enter-list-name: "Enter a name of the list to make"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "Your account is now ready! 📦"
|
||||
mobile/views/pages/followers.vue:
|
||||
@@ -1487,7 +1533,7 @@ mobile/views/pages/home.vue:
|
||||
hybrid: "Social"
|
||||
global: "Global"
|
||||
mentions: "Mentions"
|
||||
messages: "Messages"
|
||||
messages: "Direct posts"
|
||||
mobile/views/pages/tag.vue:
|
||||
no-posts-found: "No posts contains \"{q}\" found."
|
||||
mobile/views/pages/widgets.vue:
|
||||
@@ -1558,8 +1604,8 @@ deck:
|
||||
stack-left: "Stack to the left"
|
||||
pop-right: "Dock on the right"
|
||||
disabled-timeline:
|
||||
title: "Timeline has been disabled"
|
||||
description: "Timeline has been disabled by the administrator."
|
||||
title: "The timeline has been disabled"
|
||||
description: "This timeline has been disabled by the server's administrator."
|
||||
deck/deck.tl-column.vue:
|
||||
is-media-only: "Only media posts"
|
||||
edit: "Options"
|
||||
@@ -1601,24 +1647,14 @@ dev/views/apps.vue:
|
||||
create-app: "Create app"
|
||||
app-missing: "No apps"
|
||||
dev/views/new-app.vue:
|
||||
new-app: "New Application"
|
||||
create-app: "Creating application"
|
||||
app-name: "Application name"
|
||||
app-name-desc: "The name of your app"
|
||||
app-name-ex: "ex) Misskey for iOS"
|
||||
app-overview: "Application summary"
|
||||
app-desc: "A brief description or introduction of your app."
|
||||
app-desc-ex: "ex) Misskey iOS client."
|
||||
app-overview-desc: "A brief description, or an introduction of your app."
|
||||
callback-url: "The callback URL (optional)"
|
||||
callback-url-desc: "The URL to redirect to after the user is authenticated via the authentication form."
|
||||
authority: "Permissions"
|
||||
authority-desc: "Only the functions requested here can be accessed via the API."
|
||||
authority-warning: "You can change it even after creating the application, but if you give different permissions, all user keys associated at that time will be invalidated."
|
||||
account-read: "View account information."
|
||||
account-write: "Modify account information."
|
||||
note-write: "Post."
|
||||
reaction-write: "Add or remove reactions."
|
||||
following-write: "Follow and unfollow."
|
||||
drive-read: "Read the drive."
|
||||
drive-write: "Upload/delete files in the drive."
|
||||
notification-read: "Read your notifications."
|
||||
notification-write: "Manage your notifications."
|
||||
|
1101
locales/es-ES.yml
1101
locales/es-ES.yml
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
---
|
||||
meta:
|
||||
lang: "Français"
|
||||
divider: ""
|
||||
common:
|
||||
misskey: "Une ⭐ du fédiverse"
|
||||
about-title: "Une ⭐ du fédiverse."
|
||||
@@ -14,7 +13,7 @@ common:
|
||||
rich-contents-desc: "Partagez vos idées, les événements et les sujets qui vous tiennent à cœur ainsi que tout autre chose que vous souhaitez partager avec les autres. Si vous le désirez, vous pouvez décorer vos messages en utilisant une syntaxe différente ou en y joignant des sondages et des fichiers, tels que les photos ou les vidéos que vous aimez."
|
||||
reaction: "Réactions"
|
||||
reaction-desc: "Une manière simple d'exprimer vos émotions. Misskey peut attacher diverses réactions aux publications des autres utilisateurs. Si vous essayez les réactions sur Misskey, vous ne pourrez plus retourner sur une autre plateforme de réseaux sociaux n'offrant que des « J'aime »."
|
||||
ui: "Interface utilisateur"
|
||||
ui: "Interface"
|
||||
ui-desc: "Aucune interface graphique ne peut plaire à tout le monde. Par conséquent, Misskey possède une interface utilisateur hautement personnalisable selon vos goûts. Vous pouvez rendre votre page d'accueil originale en modifiant la mise en page de votre fil et en déplaçant les widgets que vous pouvez facilement ajuster pour vous approprier cet espace."
|
||||
drive: "Drive"
|
||||
drive-desc: "Vous voulez poster une photo que vous avez déjà transférée ? Vous souhaitez organiser, nommer et créer un dossier pour vos fichiers téléversés ? Misskey Drive est la meilleure solution pour vous. Très facile de partager vos fichiers en ligne."
|
||||
@@ -30,15 +29,14 @@ common:
|
||||
2fa: "Authentification à deux facteurs"
|
||||
customize-home: "Personnaliser la disposition de votre accueil"
|
||||
featured-notes: "Les notes mises en avant"
|
||||
dark-mode: "ダークモード"
|
||||
signin: "ログイン"
|
||||
signup: "新規登録"
|
||||
signout: "ログアウト"
|
||||
reload-to-apply-the-setting: "この設定を反映するにはページをリロードする必要があります。今すぐリロードしますか?"
|
||||
dark-mode: "Mode nuit"
|
||||
signin: "Se connecter"
|
||||
signup: "S'enregistrer"
|
||||
signout: "Se déconnecter"
|
||||
reload-to-apply-the-setting: "Le rechargement de la page est nécessaire pour appliquer ces paramètres. Désirez-vous la recharger maintenant ?"
|
||||
got-it: "J’ai compris !"
|
||||
customization-tips:
|
||||
title: "Conseils de personnalisation"
|
||||
paragraph: "<p>ホームのカスタマイズでは、ウィジェットを追加/削除したり、ドラッグ&ドロップして並べ替えたりすることができます。</p><p>一部のウィジェットは、<strong><strong>右</strong>クリック</strong>することで表示を変更することができます。</p><p>ウィジェットを削除するには、ヘッダーの<strong>「ゴミ箱」</strong>と書かれたエリアにウィジェットをドラッグ&ドロップします。</p><p>カスタマイズを終了するには、右上の「完了」をクリックします。</p>"
|
||||
gotit: "Compris !"
|
||||
notification:
|
||||
file-uploaded: "Le fichier a été téléversé !"
|
||||
@@ -69,7 +67,17 @@ common:
|
||||
explore: "Découvrir"
|
||||
following: "Suit"
|
||||
followers: "Abonné·e·s"
|
||||
favorites: "お気に入り"
|
||||
favorites: "Mettre cette note en favoris"
|
||||
permissions:
|
||||
"read:account": "Afficher les informations du compte"
|
||||
"write:account": "Mettre à jour les informations de votre compte"
|
||||
"read:drive": "Parcourir le Drive"
|
||||
"write:drive": "Écrire sur le Drive"
|
||||
"read:favorites": "Afficher les favoris"
|
||||
"write:notes": "Créer ou supprimer des publications"
|
||||
"read:notifications": "Afficher les notifications"
|
||||
"read:reactions": "Lire les réactions"
|
||||
"write:votes": "Vote"
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "Les utilisateurs suivants afficheront leurs publications sur votre fil."
|
||||
explore: "Trouver des utilisateurs"
|
||||
@@ -118,114 +126,110 @@ common:
|
||||
d: "Désirez-vous publier quelques mots ?"
|
||||
e: "Écrivez ici"
|
||||
f: "En attente de vos écrits"
|
||||
settings: "設定"
|
||||
settings: "Paramètres"
|
||||
_settings:
|
||||
profile: "プロフィール"
|
||||
notification: "通知"
|
||||
apps: "アプリ"
|
||||
tags: "ハッシュタグ"
|
||||
mute-and-block: "ミュート/ブロック"
|
||||
blocking: "ブロック"
|
||||
security: "セキュリティ"
|
||||
signin: "ログイン履歴"
|
||||
password: "パスワード"
|
||||
other: "その他"
|
||||
appearance: "デザイン"
|
||||
behavior: "動作"
|
||||
fetch-on-scroll: "スクロールで自動読み込み"
|
||||
fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。"
|
||||
note-visibility: "投稿の公開範囲"
|
||||
default-note-visibility: "デフォルトの公開範囲"
|
||||
remember-note-visibility: "投稿の公開範囲を記憶する"
|
||||
web-search-engine: "ウェブ検索エンジン"
|
||||
web-search-engine-desc: "例: https://www.google.com/?#q={{query}}"
|
||||
keep-cw: "CW保持"
|
||||
keep-cw-desc: "投稿にリプライする際、リプライ元の投稿にCWが設定されていたとき、デフォルトで同じCWを設定するようにします。"
|
||||
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
|
||||
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
|
||||
use-avatar-reversi-stones: "リバーシの石にアバターを使う"
|
||||
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
|
||||
disable-showing-animated-images: "アニメーション画像を再生しない"
|
||||
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
|
||||
always-show-nsfw: "常に閲覧注意のメディアを表示する"
|
||||
always-mark-nsfw: "常にメディアを閲覧注意として投稿"
|
||||
show-full-acct: "ユーザー名のホストを省略しない"
|
||||
show-via: "viaを表示する"
|
||||
reduce-motion: "UIの動きを減らす"
|
||||
this-setting-is-this-device-only: "このデバイスのみ"
|
||||
use-os-default-emojis: "OS標準の絵文字を使用"
|
||||
line-width: "線の太さ"
|
||||
line-width-thin: "細い"
|
||||
line-width-normal: "普通"
|
||||
line-width-thick: "太い"
|
||||
font-size: "文字の大きさ"
|
||||
font-size-x-small: "小さい"
|
||||
font-size-small: "少し小さい"
|
||||
font-size-medium: "普通"
|
||||
font-size-large: "少し大きい"
|
||||
font-size-x-large: "大きい"
|
||||
deck-column-align: "デッキのカラムの配置"
|
||||
deck-column-align-center: "中央"
|
||||
deck-column-align-left: "左"
|
||||
deck-column-align-flexible: "フレキシブル"
|
||||
deck-column-width: "デッキのカラムの幅"
|
||||
deck-column-width-narrow: "狭"
|
||||
deck-column-width-narrower: "やや狭"
|
||||
deck-column-width-normal: "普通"
|
||||
deck-column-width-wider: "やや広"
|
||||
deck-column-width-wide: "広"
|
||||
use-shadow: "UIに影を使用"
|
||||
rounded-corners: "UIの角を丸める"
|
||||
circle-icons: "円形のアイコンを使用"
|
||||
contrasted-acct: "ユーザー名にコントラストを付ける"
|
||||
wallpaper: "壁紙"
|
||||
choose-wallpaper: "壁紙を選択"
|
||||
delete-wallpaper: "壁紙を削除"
|
||||
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
|
||||
show-clock-on-header: "右上に時計を表示する"
|
||||
show-reply-target: "リプライ先を表示する"
|
||||
timeline: "タイムライン"
|
||||
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
|
||||
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
|
||||
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
|
||||
remain-deleted-note: "削除された投稿を表示し続ける"
|
||||
sound: "サウンド"
|
||||
enable-sounds: "サウンドを有効にする"
|
||||
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。"
|
||||
volume: "ボリューム"
|
||||
test: "テスト"
|
||||
update: "Misskey Update"
|
||||
version: "バージョン:"
|
||||
latest-version: "最新のバージョン:"
|
||||
update-checking: "アップデートを確認中"
|
||||
do-update: "アップデートを確認"
|
||||
update-settings: "詳細設定"
|
||||
no-updates: "利用可能な更新はありません"
|
||||
no-updates-desc: "お使いのMisskeyは最新です。"
|
||||
update-available: "新しいバージョンが利用可能です"
|
||||
update-available-desc: "ページを再度読み込みすると更新が適用されます。"
|
||||
advanced-settings: "高度な設定"
|
||||
debug-mode: "デバッグモードを有効にする"
|
||||
debug-mode-desc: "この設定はブラウザに記憶されます。"
|
||||
navbar-position: "ナビゲーションバーの位置"
|
||||
navbar-position-top: "上"
|
||||
navbar-position-left: "左"
|
||||
navbar-position-right: "右"
|
||||
i-am-under-limited-internet: "私は通信を制限されている"
|
||||
post-style: "投稿の表示スタイル"
|
||||
post-style-standard: "標準"
|
||||
post-style-smart: "スマート"
|
||||
notification-position: "通知の表示"
|
||||
notification-position-bottom: "下"
|
||||
notification-position-top: "上"
|
||||
disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
|
||||
load-raw-images: "添付された画像を高画質で表示する"
|
||||
load-remote-media: "リモートサーバーのメディアを表示する"
|
||||
profile: "Votre profil"
|
||||
notification: "Notifications"
|
||||
apps: "Applications"
|
||||
tags: "Hashtags"
|
||||
mute-and-block: "Silencer / Bloquer"
|
||||
blocking: "En cours blocage"
|
||||
security: "Sécurité"
|
||||
signin: "Historique des connexions"
|
||||
password: "Mot de passe"
|
||||
other: "Avancé"
|
||||
appearance: "Apparence"
|
||||
behavior: "Comportement"
|
||||
fetch-on-scroll: "Chargement automatique lors du défilement"
|
||||
fetch-on-scroll-desc: "Chargement automatique du contenu lors du défilement de la page."
|
||||
note-visibility: "Visibilité de la publication"
|
||||
default-note-visibility: "Visibilité par défaut"
|
||||
remember-note-visibility: "Se souvenir du mode de visibilité de la publication"
|
||||
web-search-engine: "Moteur de recherche Web"
|
||||
web-search-engine-desc: "Exemple : https://www.google.com/?#q={{query}}"
|
||||
keep-cw: "Maintenir l'avertissement de contenu"
|
||||
i-like-sushi: "Je préfère les sushis plutôt que le pudding"
|
||||
show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi"
|
||||
use-avatar-reversi-stones: "Utiliser l’avatar comme pion dans Reversi"
|
||||
disable-animated-mfm: "Désactiver les textes animés dans les publications"
|
||||
disable-showing-animated-images: "Désactiver l'animation des images"
|
||||
suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie"
|
||||
always-show-nsfw: "Toujours afficher les contenus sensibles"
|
||||
always-mark-nsfw: "Toujours marquer les notes ayant des médias comme sensibles"
|
||||
show-full-acct: "Afficher l’adresse complète de l’utilisateur"
|
||||
show-via: "Afficher via"
|
||||
reduce-motion: "Réduire les animations dans l’interface utilisateur"
|
||||
this-setting-is-this-device-only: "Uniquement sur cet appareil"
|
||||
use-os-default-emojis: "Utiliser les émojis standards du système"
|
||||
line-width: "Epaisseur du trait"
|
||||
line-width-thin: "Fine"
|
||||
line-width-normal: "Normale"
|
||||
line-width-thick: "Épaisse"
|
||||
font-size: "Taille du texte"
|
||||
font-size-x-small: "Très petit"
|
||||
font-size-small: "Petite"
|
||||
font-size-medium: "Normale"
|
||||
font-size-large: "Grande"
|
||||
font-size-x-large: "Large"
|
||||
deck-column-align: "Alignement des colonnes du Deck"
|
||||
deck-column-align-center: "Centrer"
|
||||
deck-column-align-left: "À gauche"
|
||||
deck-column-align-flexible: "Flexible"
|
||||
deck-column-width: "Largeur des colonnes du Deck"
|
||||
deck-column-width-narrow: "Étroite"
|
||||
deck-column-width-narrower: "Légèrement étroite"
|
||||
deck-column-width-normal: "Normale"
|
||||
deck-column-width-wider: "Légèrement large"
|
||||
deck-column-width-wide: "Large"
|
||||
use-shadow: "Utiliser les ombres dans l'interface utilisateur"
|
||||
rounded-corners: "Coins arrondis de l'interface utilisateur"
|
||||
circle-icons: "Utiliser des icônes circulaires"
|
||||
contrasted-acct: "Ajouter du contraste au nom de l’utilisateur"
|
||||
wallpaper: "Image du fond d'écran"
|
||||
choose-wallpaper: "Sélectionner un fond d'écran"
|
||||
delete-wallpaper: "Supprimer le fond d'écran"
|
||||
post-form-on-timeline: "Afficher le champs de saisie en haut du fil"
|
||||
show-clock-on-header: "Afficher l'horloge sur le coté supérieur droit"
|
||||
timeline: "Fil d’actualité"
|
||||
show-my-renotes: "Afficher mes republications dans le fil"
|
||||
remain-deleted-note: "Continuer à afficher les notes supprimées"
|
||||
sound: "Son"
|
||||
enable-sounds: "Activer les sons"
|
||||
enable-sounds-desc: "Jouer un son lorsque vous recevez un message/publication. Ce paramètre est sauvegardé dans le navigateur."
|
||||
volume: "Volume"
|
||||
test: "Test"
|
||||
update: "Mise à jour de Misskey"
|
||||
version: "Version actuelle :"
|
||||
latest-version: "Dernière version :"
|
||||
update-checking: "Recherche de mises à jour"
|
||||
do-update: "Rechercher des mises à jour"
|
||||
update-settings: "Paramètres avancés"
|
||||
no-updates: "Aucune mise à jour disponible"
|
||||
no-updates-desc: "Votre Misskey est à jour."
|
||||
update-available: "Nouvelle version disponible !"
|
||||
update-available-desc: "Les mises à jour seront appliquées une fois la page est rechargée."
|
||||
advanced-settings: "Paramètres avancés"
|
||||
debug-mode: "Activer le mode débogage"
|
||||
debug-mode-desc: "Ce paramètre est stocké dans le navigateur."
|
||||
navbar-position: "Position de la barre de navigation"
|
||||
navbar-position-top: "En haut"
|
||||
navbar-position-left: "À gauche"
|
||||
navbar-position-right: "À droite"
|
||||
i-am-under-limited-internet: "J'ai un accès Internet limité"
|
||||
post-style: "Style d'affichage des notes"
|
||||
post-style-standard: "Standard"
|
||||
post-style-smart: "Intelligent"
|
||||
notification-position: "Afficher les notifications"
|
||||
notification-position-bottom: "en bas"
|
||||
notification-position-top: "En haut"
|
||||
disable-via-mobile: "Enlever la mention publié via 'mobile'"
|
||||
load-raw-images: "Afficher les photos jointes dans leur qualité originale"
|
||||
load-remote-media: "Afficher les médias depuis le serveur distant"
|
||||
search: "Recherche"
|
||||
delete: "Supprimer"
|
||||
loading: "Chargement en cours …"
|
||||
ok: "おk"
|
||||
cancel: "やめる"
|
||||
ok: "Confirmer"
|
||||
cancel: "Quitter"
|
||||
update-available-title: "Mise à jour disponible"
|
||||
update-available: "Une nouvelle version de Misskey est disponible ({newer}, version actuelle: {current}). Veuillez recharger la page pour appliquer la mise à jour."
|
||||
my-token-regenerated: "Votre jeton vient d’être généré, vous allez maintenant être déconnecté."
|
||||
@@ -239,7 +243,7 @@ common:
|
||||
view-on-remote: " Consulter le profil complet"
|
||||
renoted-by: "Renoté par {user}"
|
||||
no-notes: "Sans aucune note"
|
||||
turn-on-darkmode: "Basculer vers le mode nuit"
|
||||
turn-on-darkmode: "Mode nuit"
|
||||
turn-off-darkmode: "Mode jour"
|
||||
error:
|
||||
title: "Une erreur est survenue"
|
||||
@@ -277,21 +281,13 @@ common:
|
||||
nav: "Navigation"
|
||||
tips: "Conseils"
|
||||
hashtags: "Hashtags"
|
||||
queue: "File d'attente"
|
||||
dev: "Échec lors de la création de l’application. Veuillez réessayer."
|
||||
ai-chan-kawaii: "Ai-Chan est mignonne !"
|
||||
you: "Vous"
|
||||
auth/views/form.vue:
|
||||
share-access: "Désirez-vous autoriser <i>{name}</i> à avoir accès à votre compte ?"
|
||||
permission-ask: "Cette application nécessite les autorisations suivantes :"
|
||||
account-read: "Afficher les informations du compte."
|
||||
account-write: "Modifications des informations du compte."
|
||||
note-write: "Publier."
|
||||
like-write: "Réagir aux publications."
|
||||
following-write: "Suivre des comptes et se désabonner."
|
||||
drive-read: "Lire votre Drive"
|
||||
drive-write: "Téléverser/supprimer des fichiers dans votre Drive."
|
||||
notification-read: "Lire vos notifications."
|
||||
notification-write: "Gérer vos notifications."
|
||||
cancel: "Annuler"
|
||||
accept: "Autoriser l’accès"
|
||||
auth/views/index.vue:
|
||||
@@ -314,7 +310,8 @@ common/views/pages/explore.vue:
|
||||
explore: "Explorer {host}"
|
||||
users-info: "Actuellement, {users} utilisateurs se sont inscrit ici"
|
||||
common/views/components/url-preview.vue:
|
||||
enable-player: "プレイヤーを開く"
|
||||
enable-player: "Activer la lecture"
|
||||
disable-player: "Fermer le lecteur"
|
||||
common/views/components/user-list.vue:
|
||||
no-users: "Il n'y a aucun utilisateur"
|
||||
common/views/components/games/reversi/reversi.vue:
|
||||
@@ -349,7 +346,6 @@ common/views/components/games/reversi/reversi.room.vue:
|
||||
black-or-white: "Noirs/Blancs"
|
||||
black-is: "{} Noirs"
|
||||
rules: "Règles"
|
||||
is-llotheo: "石の少ない方が勝ち(ロセオ)"
|
||||
looped-map: "Carte en boucle"
|
||||
can-put-everywhere: "Peut poser partout"
|
||||
settings-of-the-bot: "Configuration du bot"
|
||||
@@ -490,16 +486,33 @@ common/views/components/user-menu.vue:
|
||||
common/views/components/poll.vue:
|
||||
vote-to: "Voter pour '{}'"
|
||||
vote-count: "{} votes"
|
||||
total-users: "{} utilisateur·rice·s ont voté"
|
||||
total-votes: "{} Total des votes"
|
||||
vote: "Vote"
|
||||
show-result: "Montrer les résultats"
|
||||
voted: "Voté"
|
||||
closed: "Terminé"
|
||||
remaining-days: "{d} jours, {h} heures restantes"
|
||||
remaining-hours: "{h} heures et {m} minutes restantes"
|
||||
remaining-minutes: "{m} minutes et {s} secondes restantes"
|
||||
remaining-seconds: "{s} secondes restantes"
|
||||
common/views/components/poll-editor.vue:
|
||||
no-only-one-choice: "Vous devez saisir au moins deux choix."
|
||||
choice-n: "Choix {}"
|
||||
remove: "Supprimer ce choix"
|
||||
add: "+ Ajouter un choix"
|
||||
destroy: "Annuler ce sondage"
|
||||
expiration: "Valide jusqu'à"
|
||||
infinite: "Illimité"
|
||||
at: "Choisir une date et une durée"
|
||||
no-more: "Vous ne pouvez pas en ajouter davantage"
|
||||
deadline-date: "Date d’échéance"
|
||||
deadline-time: "Durée"
|
||||
interval: "Durée"
|
||||
unit: "Unité"
|
||||
second: "secondes"
|
||||
minute: "Minutes"
|
||||
hour: "Heures"
|
||||
day: "D"
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "Choisissez votre réaction"
|
||||
common/views/components/emoji-picker.vue:
|
||||
@@ -629,12 +642,16 @@ common/views/components/profile-editor.vue:
|
||||
email-verified: "L’adresse du courrier électronique a été vérifiée."
|
||||
email-not-verified: "Adresse de courriel n’est pas confirmée. Veuillez vérifier votre boite de réception."
|
||||
export: "Exporter"
|
||||
import: "Importer"
|
||||
export-and-import: "Exportation et importation"
|
||||
export-targets:
|
||||
all-notes: "Toutes les notes publiées"
|
||||
following-list: "Liste des abonnements"
|
||||
mute-list: "Liste des comptes mis en sourdine"
|
||||
blocking-list: "Liste des comptes bloqués"
|
||||
user-lists: "Listes"
|
||||
export-requested: "Vous avez demandé une exportation. Cela peut prendre un certain temps. Une fois l'exportation terminée, le fichier résultant sera ajouté dans le Drive."
|
||||
import-requested: "Vous avez initié un import. Ceci peut prendre un peu de temps."
|
||||
enter-password: "Veuillez saisir votre mot de passe"
|
||||
danger-zone: "Zone de danger"
|
||||
delete-account: "Supprimer le compte"
|
||||
@@ -646,6 +663,9 @@ common/views/components/user-list-editor.vue:
|
||||
remove-user: "Retirer de cette liste"
|
||||
delete-are-you-sure: "Voulez-vous vraiment supprimer la liste « $1 » ?"
|
||||
deleted: "Supprimé"
|
||||
common/views/components/user-lists.vue:
|
||||
create-list: "Créer une liste"
|
||||
list-name: "Nom de la liste"
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "Récupération"
|
||||
no-broadcasts: "Aucune annonce"
|
||||
@@ -695,7 +715,6 @@ common/views/widgets/tips.vue:
|
||||
tips-line19: "Plusieurs fenêtres peuvent être détachées en dehors du navigateur."
|
||||
tips-line20: "Pourcentage sur le widget calendrier qui indique le pourcentage de temps passé"
|
||||
tips-line21: "Vous pouvez aussi utiliser l'API pour développer des Bots."
|
||||
tips-line23: "藍かわいいよ藍"
|
||||
tips-line24: "Misskey est fonctionnel depuis 2014"
|
||||
tips-line25: "Vous pouvez recevoir les notifications de Misskey dans un navigateur web compatible"
|
||||
common/views/pages/not-found.vue:
|
||||
@@ -816,10 +835,6 @@ desktop/views/components/home.vue:
|
||||
desktop/views/input-dialog.vue:
|
||||
cancel: "Annuler"
|
||||
ok: "OK"
|
||||
desktop/views/components/messaging-room-window.vue:
|
||||
title: "Messages :"
|
||||
desktop/views/components/messaging-window.vue:
|
||||
title: "Messagerie"
|
||||
desktop/views/components/note-detail.vue:
|
||||
private: "cette publication est privée"
|
||||
deleted: "cette publication a été supprimée"
|
||||
@@ -858,7 +873,6 @@ desktop/views/components/post-form.vue:
|
||||
posting: "Publication …"
|
||||
attach-media-from-local: "Joindre un média depuis votre appareil"
|
||||
attach-media-from-drive: "Joindre un média depuis votre Drive"
|
||||
attach-cancel: "Annuler le fichier attaché"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "Créer un sondage"
|
||||
text-remain: "{} caractères restants"
|
||||
@@ -951,6 +965,10 @@ common/views/components/password-settings.vue:
|
||||
not-match: "Les nouveaux mots de passe ne sont pas identiques"
|
||||
changed: "Mot de passe modifié avec succès"
|
||||
failed: "Échec lors de la modification du mot de passe"
|
||||
common/views/components/post-form-attaches.vue:
|
||||
attach-cancel: "Enlever le fichier attaché"
|
||||
mark-as-sensitive: "Marquer comme sensible"
|
||||
unmark-as-sensitive: "Ne pas marquer comme sensible"
|
||||
desktop/views/components/sub-note-content.vue:
|
||||
private: "cette publication est privée"
|
||||
deleted: "cette publication a été supprimée"
|
||||
@@ -961,15 +979,13 @@ desktop/views/components/settings.tags.vue:
|
||||
query: "Requête (optionnelle)"
|
||||
add: "Ajouter"
|
||||
save: "Enregistrer"
|
||||
desktop/views/components/taskmanager.vue:
|
||||
title: "Gestionnaire de tâches"
|
||||
desktop/views/components/timeline.vue:
|
||||
home: "Accueil"
|
||||
local: "Local"
|
||||
hybrid: "Social"
|
||||
global: "Global"
|
||||
mentions: "Mentions"
|
||||
messages: "Messages"
|
||||
messages: "Messages directs"
|
||||
list: "Listes"
|
||||
hashtag: "Hashtag"
|
||||
add-tag-timeline: "Ajouter un fil de hashtags"
|
||||
@@ -997,8 +1013,6 @@ desktop/views/components/received-follow-requests-window.vue:
|
||||
reject: "Refuser"
|
||||
desktop/views/components/user-lists-window.vue:
|
||||
title: "Listes de l'utilisateur"
|
||||
create-list: "Créer une liste"
|
||||
list-name: "Nom de la liste"
|
||||
desktop/views/components/user-preview.vue:
|
||||
notes: "Publications"
|
||||
following: "Abonné à"
|
||||
@@ -1023,6 +1037,7 @@ admin/views/index.vue:
|
||||
hashtags: "Hashtags"
|
||||
abuse: "Abus"
|
||||
queue: "File d’attente"
|
||||
logs: "Journaux"
|
||||
back-to-misskey: "Retour vers Misskey"
|
||||
admin/views/dashboard.vue:
|
||||
dashboard: "Tableau de bord"
|
||||
@@ -1033,7 +1048,7 @@ admin/views/dashboard.vue:
|
||||
this-instance: "Cette instance"
|
||||
federated: "Fédérées"
|
||||
admin/views/queue.vue:
|
||||
operation: "Action(s)"
|
||||
title: "File d'attente"
|
||||
remove-all-jobs: "Enlever toutes les tâches en attente"
|
||||
admin/views/abuse.vue:
|
||||
title: "Abus"
|
||||
@@ -1055,7 +1070,6 @@ admin/views/instance.vue:
|
||||
maintainer-email: "Contact administratif"
|
||||
drive-config: "Paramètres du lecteur"
|
||||
cache-remote-files: "Mettre en cache des fichiers distants"
|
||||
cache-remote-files-desc: "この設定を無効にすると、リモートファイルをキャッシュせず直リンクするようになります。そのためサーバーのストレージを節約できますが、プライバシー設定で直リンクを無効にしているユーザーにはファイルが見えなくなったり、サムネイルが生成されないので通信量が増加します。通常はこの設定をオンにしておくことをおすすめします。"
|
||||
local-drive-capacity-mb: "Volume du lecteur par utilisateur"
|
||||
remote-drive-capacity-mb: "Volume du lecteur par utilisateur distant"
|
||||
mb: "en mégaoctets"
|
||||
@@ -1080,7 +1094,6 @@ admin/views/instance.vue:
|
||||
discord-integration-client-id: "ID client"
|
||||
discord-integration-client-secret: "Secret client"
|
||||
proxy-account-config: "Compte proxy"
|
||||
proxy-account-info: "プロキシアカウントは、特定の条件下でユーザーのリモートフォローを代行するアカウントです。例えば、ユーザーがリモートユーザーをリストに入れたとき、リストに入れられたユーザーを誰もフォローしていないとアクティビティがサーバーに配達されないため、代わりにプロキシアカウントがフォローするようにします。"
|
||||
proxy-account-username: "Nom d’utilisateur du compte proxy"
|
||||
proxy-account-username-desc: "Spécifiez le nom d’utilisateur du compte utilisé comme proxy."
|
||||
proxy-account-warn: "Avant d’entamer cette action, vous devez au préalable avoir créé un compte avec ce nom d’utilisateur."
|
||||
@@ -1093,11 +1106,6 @@ admin/views/instance.vue:
|
||||
save: "Sauvegarder"
|
||||
saved: "Enregistré"
|
||||
user-recommendation-config: "Utilisateurs"
|
||||
enable-external-user-recommendation: "Activer la recommandation des utilisateurs distants"
|
||||
external-user-recommendation-engine: "Moteur"
|
||||
external-user-recommendation-engine-desc: "Exemple : https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}"
|
||||
external-user-recommendation-timeout: "Délai d’expiration"
|
||||
external-user-recommendation-timeout-desc: "En millisecondes (par exemple : 300000)"
|
||||
email-config: "Paramètres du serveur de messagerie"
|
||||
email-config-info: "Utilisé pour confirmer votre adresse de courrier électronique et la réinitialisation de votre mot de passe."
|
||||
enable-email: "Activation de la distribution du courrier"
|
||||
@@ -1251,47 +1259,41 @@ admin/views/announcements.vue:
|
||||
admin/views/hashtags.vue:
|
||||
hided-tags: "Tags cachés"
|
||||
admin/views/federation.vue:
|
||||
federation: "Fédération"
|
||||
instance: "Instance"
|
||||
host: "Hôte"
|
||||
notes: "Notes"
|
||||
users: "Utilisateur·rice·s"
|
||||
following: "Abonnements"
|
||||
followers: "Abonné·e·s"
|
||||
caught-at: "Créé le"
|
||||
status: "Statuts"
|
||||
latest-request-sent-at: "Dernière requête envoyée"
|
||||
latest-request-received-at: "Dernière requête reçue"
|
||||
remove-all-following: "フォローを全解除"
|
||||
remove-all-following-info: "Se désabonner de tous les comptes de {host}. Exécutez cette commande si l'instance n'existe plus."
|
||||
block: "Bloquer"
|
||||
marked-as-closed: "Marquées comme fermées"
|
||||
lookup: "Recherche"
|
||||
instances: "Instances"
|
||||
instance-not-registered: "そのインスタンスは登録されていません"
|
||||
instances: "Fédérées"
|
||||
instance-not-registered: "L’instance n’a pas encore été découverte"
|
||||
sort: "Trier par"
|
||||
sorts:
|
||||
caughtAtAsc: "Date d’inscription (Ascendant)"
|
||||
caughtAtDesc: "Date d’inscription (Descendant)"
|
||||
lastCommunicatedAtAsc: "La date et l'heure des interactions plus anciennes"
|
||||
lastCommunicatedAtDesc: "La date et l'heure des nouvelles interactions"
|
||||
notesAsc: "投稿が少ない順"
|
||||
notesDesc: "Description des notes"
|
||||
usersAsc: "ユーザーが少ない順"
|
||||
usersDesc: "ユーザーが多い順"
|
||||
usersAsc: "Peu d'abonnés"
|
||||
followingAsc: "Les moins suivies"
|
||||
followingDesc: "Ayant le plus d'abonné·e·s"
|
||||
followersAsc: "Ayant le moins d'abonné·e·s"
|
||||
followersDesc: "Ayant le plus d'abonné·e·s"
|
||||
driveUsageAsc: "Moins d'espace de stockage utilisé"
|
||||
driveUsageDesc: "ドライブ使用量が多い順"
|
||||
driveFilesAsc: "ドライブのファイル数が少ない順"
|
||||
driveFilesDesc: "ドライブのファイル数が多い順"
|
||||
state: "État"
|
||||
states:
|
||||
all: "Tout"
|
||||
blocked: "Bloquées"
|
||||
not-responding: "Sans réponse"
|
||||
marked-as-closed: "Marquée comme fermée"
|
||||
result-is-truncated: "上位{n}件を表示しています。"
|
||||
charts: "Graphs"
|
||||
chart-srcs:
|
||||
requests: "Requêtes"
|
||||
@@ -1300,10 +1302,8 @@ admin/views/federation.vue:
|
||||
notes: "Augmentation/diminution du nombre des notes"
|
||||
notes-total: "Nombre total des notes"
|
||||
ff: "Augmentation des abonné·e·s"
|
||||
ff-total: "フォロー/フォロワーの積算"
|
||||
drive-usage: "Augmentation et diminution de la capacité stockage"
|
||||
drive-usage-total: "Utilisation totale du stockage"
|
||||
drive-files: "ドライブファイル数の増減"
|
||||
drive-files-total: "Nombre total des fichiers sur le Drive"
|
||||
chart-spans:
|
||||
hour: "Par heure"
|
||||
@@ -1328,8 +1328,6 @@ desktop/views/pages/selectdrive.vue:
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "La fonction de recherche est désactivée dans les paramètres de l’instance."
|
||||
not-found: "Aucune publication trouvée pour « {q} »."
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "Partager avec {name}"
|
||||
desktop/views/pages/tag.vue:
|
||||
no-posts-found: "Aucune publication contenant « {q} » n’a été trouvée."
|
||||
desktop/views/pages/user-list.users.vue:
|
||||
@@ -1364,8 +1362,6 @@ desktop/views/pages/user/user.timeline.vue:
|
||||
with-replies: "Publications et réponses"
|
||||
with-media: "Média"
|
||||
my-posts: "Mes Messages"
|
||||
desktop/views/widgets/messaging.vue:
|
||||
title: "Messagerie"
|
||||
desktop/views/widgets/notifications.vue:
|
||||
title: "Notifications"
|
||||
desktop/views/widgets/polls.vue:
|
||||
@@ -1393,10 +1389,7 @@ mobile/views/components/drive.vue:
|
||||
file-count: "Fichier·s"
|
||||
nothing-in-drive: "Rien"
|
||||
folder-is-empty: "Ce dossier est vide"
|
||||
prompt: "Que veux-tu faire ? (Entrez un nombre): <1 → Télécharger le fichier | 2 → Télécharger le fichier avec l'URL | 3 → Créer le dossier | 4 → Modifier le nom du dossier | 5 → Déplacer ce dossier | 6 → Supprimer ce dossier >"
|
||||
deletion-alert: "Désolé ! La suppression d’un dossier n’est pas encore implémentée."
|
||||
folder-name: "Nom du dossier"
|
||||
here-is-root: "現在いる場所はルートで、フォルダではありません。"
|
||||
url-prompt: "URL du fichier que vous souhaitez téléverser"
|
||||
uploading: "Envoi demandé. Le téléversement pourrait prendre un certain temps avant de s'achever."
|
||||
mobile/views/components/drive-file-chooser.vue:
|
||||
@@ -1451,7 +1444,7 @@ mobile/views/components/post-form.vue:
|
||||
quote-placeholder: "Citer ce billet ... (Facultatif)"
|
||||
reply-placeholder: "Répondre à cette note"
|
||||
cw-placeholder: "Commenter le contenu (optionnel)"
|
||||
location-alert: "Votre appareil ne prend pas en charge les services de localisation"
|
||||
geolocation-alert: "Votre appareil ne prend pas en charge les services de localisation"
|
||||
error: "Erreur"
|
||||
username-prompt: "Saisir un nom d'utilisateur"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
@@ -1472,9 +1465,12 @@ mobile/views/components/ui.nav.vue:
|
||||
game: "Jeux"
|
||||
admin: "Admin"
|
||||
about: "À propos de Misskey"
|
||||
mobile/views/pages/drive.vue:
|
||||
contextmenu:
|
||||
upload: "Téléverser un fichier"
|
||||
create-folder: "Créer un dossier"
|
||||
mobile/views/pages/user-lists.vue:
|
||||
title: "Listes"
|
||||
enter-list-name: "Nom de la liste"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "Votre compte est prêt ! 📦"
|
||||
mobile/views/pages/followers.vue:
|
||||
@@ -1487,14 +1483,13 @@ mobile/views/pages/home.vue:
|
||||
hybrid: "Social"
|
||||
global: "Global"
|
||||
mentions: "Mentions"
|
||||
messages: "Messages"
|
||||
messages: "Messages directs"
|
||||
mobile/views/pages/tag.vue:
|
||||
no-posts-found: "Aucune publication ayant pour hashtag « {q} » n’a été trouvée."
|
||||
mobile/views/pages/widgets.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
widgets-hints: "ウィジェットを追加/削除したり並べ替えたりできます。ウィジェットを移動するには「三」をドラッグします。ウィジェットを削除するには「x」をタップします。いくつかのウィジェットはタップすることで表示を変更できます。"
|
||||
add-widget: "追加"
|
||||
customization-tips: "カスタマイズのヒント"
|
||||
dashboard: "Tableau de bord"
|
||||
add-widget: "Ajouter"
|
||||
customization-tips: "Conseils de personnalisation"
|
||||
mobile/views/pages/widgets/activity.vue:
|
||||
activity: "Activité"
|
||||
mobile/views/pages/share.vue:
|
||||
@@ -1547,7 +1542,7 @@ deck:
|
||||
direct: "Messages directs"
|
||||
notifications: "Notifications"
|
||||
list: "Listes"
|
||||
select-list: "リストを選択してください"
|
||||
select-list: "Sélectionnez une liste"
|
||||
swap-left: "Déplacer à gauche"
|
||||
swap-right: "Déplacer à droite"
|
||||
swap-up: "Déplacer vers le haut"
|
||||
@@ -1604,21 +1599,9 @@ dev/views/new-app.vue:
|
||||
create-app: "Création d’une application"
|
||||
app-name: "Nom de l’application"
|
||||
app-name-desc: "Le nom de votre application"
|
||||
app-name-ex: "p. ex. Misskey pour iOS"
|
||||
app-overview: "Description courte de l’application"
|
||||
app-desc: "Brève description introductive à votre application."
|
||||
app-desc-ex: "p. ex) Misskey pour iOS"
|
||||
callback-url: "L’Url de callback (facultatif)"
|
||||
callback-url-desc: "Vous pouvez définir l’URL de redirection lorsque l’utilisateur s’est authentifié via formulaire d’authentification."
|
||||
authority: "Autorisations "
|
||||
authority-desc: "Sont accessibles via l’API, uniquement les fonctionnalités demandées ici."
|
||||
authority-warning: "Vous pouvez le changer même après avoir créé l'application, mais si vous attribuez une nouvelle permission, toutes les clés utilisateur associées seront dès lors invalides."
|
||||
account-read: "Afficher les informations du compte"
|
||||
account-write: "Modifications des informations du compte"
|
||||
note-write: "Publications."
|
||||
reaction-write: "Ajout et suppression de réactions."
|
||||
following-write: "S’abonner et se désabonner."
|
||||
drive-read: "Lecture du Drive."
|
||||
drive-write: "Téléversement/suppression des fichiers de votre Lecteur."
|
||||
notification-read: "Lire vos notifications."
|
||||
notification-write: "Gestion de vos notifications."
|
||||
|
@@ -5,22 +5,49 @@
|
||||
const fs = require('fs');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
const langs = ['de-DE', 'en-US', 'fr-FR', 'ja-JP', 'ja-KS', 'pl-PL', 'es-ES', 'nl-NL', 'zh-CN', 'ko-KR'];
|
||||
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 loadLocale = lang => yaml.safeLoad(fs.readFileSync(`${__dirname}/${lang}.yml`, 'utf-8'));
|
||||
const locales = langs
|
||||
.map(lang => [lang, loadLocale(lang)])
|
||||
.map(([lang, locale], _, locales) => {
|
||||
switch (lang) {
|
||||
case 'ja-JP': return [lang, locale];
|
||||
case 'en-US': return [lang, { ...locales['ja-JP'], ...locale }];
|
||||
default: return [lang, {
|
||||
...(lang.startsWith('ja-') ? {} : locales['en-US']),
|
||||
...locales['ja-JP'],
|
||||
...locale
|
||||
}];
|
||||
const languages = [
|
||||
'cs-CZ',
|
||||
'de-DE',
|
||||
'en-US',
|
||||
'es-ES',
|
||||
'fr-FR',
|
||||
'ja-JP',
|
||||
'ja-KS',
|
||||
'ko-KR',
|
||||
'nl-NL',
|
||||
'pl-PL',
|
||||
'zh-CN',
|
||||
'zh-TW',
|
||||
];
|
||||
|
||||
const primaries = {
|
||||
'en': 'US',
|
||||
'ja': 'JP',
|
||||
'zh': 'CN',
|
||||
};
|
||||
|
||||
const locales = languages.reduce((a, c) => (a[c] = yaml.safeLoad(fs.readFileSync(`${__dirname}/${c}.yml`, 'utf-8')) || {}, a), {});
|
||||
|
||||
module.exports = 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
|
||||
);
|
||||
}
|
||||
})
|
||||
.map(([lang, locale]) => ({ [lang]: loadLocale(lang) }));
|
||||
|
||||
module.exports = locales.reduce((a, b) => ({ ...a, ...b }));
|
||||
})(), a), {});
|
||||
|
1620
locales/it-IT.yml
1620
locales/it-IT.yml
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,7 @@ common:
|
||||
signup: "新規登録"
|
||||
signout: "ログアウト"
|
||||
reload-to-apply-the-setting: "この設定を反映するにはページをリロードする必要があります。今すぐリロードしますか?"
|
||||
fetching-as-ap-object: "連合に照会中"
|
||||
|
||||
got-it: "わかった"
|
||||
customization-tips:
|
||||
@@ -73,6 +74,28 @@ common:
|
||||
followers: "フォロワー"
|
||||
favorites: "お気に入り"
|
||||
|
||||
permissions:
|
||||
"read:account": "アカウントの情報を見る"
|
||||
"write:account": "アカウントの情報を変更する"
|
||||
"read:blocks": "ブロックを見る"
|
||||
"write:blocks": "ブロックを操作する"
|
||||
"read:drive": "ドライブを見る"
|
||||
"write:drive": "ドライブを操作する"
|
||||
"read:favorites": "お気に入りを見る"
|
||||
"write:favorites": "お気に入りを操作する"
|
||||
"read:following": "フォローの情報を見る"
|
||||
"write:following": "フォロー・フォロー解除する"
|
||||
"read:messaging": "トークを見る"
|
||||
"write:messaging": "トークを操作する"
|
||||
"read:mutes": "ミュートを見る"
|
||||
"write:mutes": "ミュートを操作する"
|
||||
"write:notes": "投稿を作成・削除する"
|
||||
"read:notifications": "通知を見る"
|
||||
"write:notifications": "通知を操作する"
|
||||
"read:reactions": "リアクションを見る"
|
||||
"write:reactions": "リアクションを操作する"
|
||||
"write:votes": "投票する"
|
||||
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "ユーザーをフォローすると投稿がタイムラインに表示されます。"
|
||||
explore: "ユーザーを探索する"
|
||||
@@ -291,6 +314,7 @@ common:
|
||||
nav: "ナビゲーション"
|
||||
tips: "ヒント"
|
||||
hashtags: "ハッシュタグ"
|
||||
queue: "キュー"
|
||||
|
||||
dev: "アプリの作成に失敗しました。再度お試しください。"
|
||||
ai-chan-kawaii: "藍ちゃかわいい"
|
||||
@@ -299,15 +323,6 @@ common:
|
||||
auth/views/form.vue:
|
||||
share-access: "<i>{name}</i>があなたのアカウントにアクセスすることを許可しますか?"
|
||||
permission-ask: "このアプリは次の権限を要求しています:"
|
||||
account-read: "アカウントの情報を見る。"
|
||||
account-write: "アカウントの情報を操作する。"
|
||||
note-write: "投稿する。"
|
||||
like-write: "いいねしたりいいね解除する。"
|
||||
following-write: "フォローしたりフォロー解除する。"
|
||||
drive-read: "ドライブを見る。"
|
||||
drive-write: "ドライブを操作する。"
|
||||
notification-read: "通知を見る。"
|
||||
notification-write: "通知を操作する。"
|
||||
cancel: "キャンセル"
|
||||
accept: "アクセスを許可"
|
||||
|
||||
@@ -334,6 +349,7 @@ common/views/pages/explore.vue:
|
||||
|
||||
common/views/components/url-preview.vue:
|
||||
enable-player: "プレイヤーを開く"
|
||||
disable-player: "プレイヤーを閉じる"
|
||||
|
||||
common/views/components/user-list.vue:
|
||||
no-users: "ユーザーがいません"
|
||||
@@ -512,8 +528,12 @@ common/views/components/user-menu.vue:
|
||||
mention: "メンション"
|
||||
mute: "ミュート"
|
||||
unmute: "ミュート解除"
|
||||
mute-confirm: "このユーザーをミュートしますか?"
|
||||
unmute-confirm: "このユーザーをミュート解除しますか?"
|
||||
block: "ブロック"
|
||||
unblock: "ブロック解除"
|
||||
block-confirm: "このユーザーをブロックしますか?"
|
||||
unblock-confirm: "このユーザーをブロック解除しますか?"
|
||||
push-to-list: "リストに追加"
|
||||
select-list: "リストを選択してください"
|
||||
report-abuse: "スパムを報告"
|
||||
@@ -521,16 +541,25 @@ common/views/components/user-menu.vue:
|
||||
report-abuse-reported: "管理者に報告されました。ご協力ありがとうございました。"
|
||||
silence: "サイレンス"
|
||||
unsilence: "サイレンス解除"
|
||||
silence-confirm: "このユーザーをサイレンスしますか?"
|
||||
unsilence-confirm: "このユーザーをサイレンス解除しますか?"
|
||||
suspend: "凍結"
|
||||
unsuspend: "凍結解除"
|
||||
suspend-confirm: "このユーザーを凍結しますか?"
|
||||
unsuspend-confirm: "このユーザーを凍結解除しますか?"
|
||||
|
||||
common/views/components/poll.vue:
|
||||
vote-to: "「{}」に投票する"
|
||||
vote-count: "{}票"
|
||||
total-users: "{}人が投票"
|
||||
total-votes: "計{}票"
|
||||
vote: "投票する"
|
||||
show-result: "結果を見る"
|
||||
voted: "投票済み"
|
||||
closed: "終了済み"
|
||||
remaining-days: "終了まであと{d}日{h}時間"
|
||||
remaining-hours: "終了まであと{h}時間{m}分"
|
||||
remaining-minutes: "終了まであと{m}分{s}秒"
|
||||
remaining-seconds: "終了まであと{s}秒"
|
||||
|
||||
common/views/components/poll-editor.vue:
|
||||
no-only-one-choice: "アンケートには、選択肢が最低2つ必要です"
|
||||
@@ -538,6 +567,20 @@ common/views/components/poll-editor.vue:
|
||||
remove: "この選択肢を削除"
|
||||
add: "+選択肢を追加"
|
||||
destroy: "アンケートを破棄"
|
||||
multiple: "複数回答可"
|
||||
expiration: "期限"
|
||||
infinite: "無期限"
|
||||
at: "日時指定"
|
||||
after: "経過指定"
|
||||
no-more: "これ以上追加できません"
|
||||
deadline-date: "期日"
|
||||
deadline-time: "時間"
|
||||
interval: "期間"
|
||||
unit: "単位"
|
||||
second: "秒"
|
||||
minute: "分"
|
||||
hour: "時間"
|
||||
day: "日"
|
||||
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "リアクションを選択"
|
||||
@@ -682,12 +725,16 @@ common/views/components/profile-editor.vue:
|
||||
email-verified: "メールアドレスが確認されました"
|
||||
email-not-verified: "メールアドレスが確認されていません。メールボックスをご確認ください。"
|
||||
export: "エクスポート"
|
||||
import: "インポート"
|
||||
export-and-import: "エクスポートとインポート"
|
||||
export-targets:
|
||||
all-notes: "すべての投稿データ"
|
||||
following-list: "フォロー"
|
||||
mute-list: "ミュート"
|
||||
blocking-list: "ブロック"
|
||||
user-lists: "リスト"
|
||||
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||
import-requested: "インポートをリクエストしました。これには時間がかかる場合があります。"
|
||||
enter-password: "パスワードを入力してください"
|
||||
danger-zone: "危険な設定"
|
||||
delete-account: "アカウントを削除"
|
||||
@@ -701,6 +748,10 @@ common/views/components/user-list-editor.vue:
|
||||
delete-are-you-sure: "リスト「$1」を削除しますか?"
|
||||
deleted: "削除しました"
|
||||
|
||||
common/views/components/user-lists.vue:
|
||||
create-list: "リストを作成"
|
||||
list-name: "リスト名"
|
||||
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "確認中"
|
||||
no-broadcasts: "お知らせはありません"
|
||||
@@ -901,12 +952,6 @@ desktop/views/input-dialog.vue:
|
||||
cancel: "キャンセル"
|
||||
ok: "決定"
|
||||
|
||||
desktop/views/components/messaging-room-window.vue:
|
||||
title: "メッセージ:"
|
||||
|
||||
desktop/views/components/messaging-window.vue:
|
||||
title: "メッセージ"
|
||||
|
||||
desktop/views/components/note-detail.vue:
|
||||
private: "この投稿は非公開です"
|
||||
deleted: "この投稿は削除されました"
|
||||
@@ -949,7 +994,6 @@ desktop/views/components/post-form.vue:
|
||||
posting: "投稿中"
|
||||
attach-media-from-local: "PCからメディアを添付"
|
||||
attach-media-from-drive: "ドライブからメディアを添付"
|
||||
attach-cancel: "添付取り消し"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "アンケートを作成"
|
||||
text-remain: "残り{}文字"
|
||||
@@ -1055,6 +1099,11 @@ common/views/components/password-settings.vue:
|
||||
changed: "パスワードを変更しました"
|
||||
failed: "パスワード変更に失敗しました"
|
||||
|
||||
common/views/components/post-form-attaches.vue:
|
||||
attach-cancel: "添付取り消し"
|
||||
mark-as-sensitive: "閲覧注意に設定"
|
||||
unmark-as-sensitive: "閲覧注意を解除"
|
||||
|
||||
desktop/views/components/sub-note-content.vue:
|
||||
private: "この投稿は非公開です"
|
||||
deleted: "この投稿は削除されました"
|
||||
@@ -1067,16 +1116,13 @@ desktop/views/components/settings.tags.vue:
|
||||
add: "追加"
|
||||
save: "保存"
|
||||
|
||||
desktop/views/components/taskmanager.vue:
|
||||
title: "タスクマネージャ"
|
||||
|
||||
desktop/views/components/timeline.vue:
|
||||
home: "ホーム"
|
||||
local: "ローカル"
|
||||
hybrid: "ソーシャル"
|
||||
global: "グローバル"
|
||||
mentions: "あなた宛て"
|
||||
messages: "メッセージ"
|
||||
messages: "ダイレクト投稿"
|
||||
list: "リスト"
|
||||
hashtag: "ハッシュタグ"
|
||||
add-tag-timeline: "ハッシュタグを追加"
|
||||
@@ -1112,8 +1158,6 @@ desktop/views/components/received-follow-requests-window.vue:
|
||||
|
||||
desktop/views/components/user-lists-window.vue:
|
||||
title: "リスト"
|
||||
create-list: "リストを作成"
|
||||
list-name: "リスト名"
|
||||
|
||||
desktop/views/components/user-preview.vue:
|
||||
notes: "投稿"
|
||||
@@ -1156,7 +1200,7 @@ admin/views/dashboard.vue:
|
||||
federated: "連合"
|
||||
|
||||
admin/views/queue.vue:
|
||||
operation: "操作"
|
||||
title: "キュー"
|
||||
remove-all-jobs: "すべてのジョブをクリア"
|
||||
|
||||
admin/views/abuse.vue:
|
||||
@@ -1214,15 +1258,12 @@ admin/views/instance.vue:
|
||||
disable-local-timeline: "ローカルタイムラインを無効にする"
|
||||
disable-global-timeline: "グローバルタイムラインを無効にする"
|
||||
disabling-timelines-info: "これらのタイムラインを無効にしても、管理者およびモデレーターは引き続き利用できます。"
|
||||
enable-emoji-reaction: "リアクションに絵文字を使えるようにする"
|
||||
use-star-for-reaction-fallback: "不明なリアクションのフォールバックに star を使う"
|
||||
invite: "招待"
|
||||
save: "保存"
|
||||
saved: "保存しました"
|
||||
user-recommendation-config: "おすすめユーザー"
|
||||
enable-external-user-recommendation: "外部ユーザーレコメンデーションを有効にする"
|
||||
external-user-recommendation-engine: "エンジン"
|
||||
external-user-recommendation-engine-desc: "例: https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}"
|
||||
external-user-recommendation-timeout: "タイムアウト"
|
||||
external-user-recommendation-timeout-desc: "ミリ秒単位 (例: 300000)"
|
||||
email-config: "メールサーバーの設定"
|
||||
email-config-info: "メールアドレス確認やパスワードリセットの際に使われます。"
|
||||
enable-email: "メール配信を有効にする"
|
||||
@@ -1306,7 +1347,9 @@ admin/views/users.vue:
|
||||
unsuspend-confirm: "凍結を解除しますか?"
|
||||
unsuspended: "凍結を解除しました"
|
||||
make-silence: "サイレンス"
|
||||
silence-confirm: "サイレンスしますか?"
|
||||
unmake-silence: "サイレンスの解除"
|
||||
unsilence-confirm: "サイレンスを解除しますか?"
|
||||
verify: "公式アカウントにする"
|
||||
verify-confirm: "公式アカウントにしますか?"
|
||||
verified: "公式アカウントにしました"
|
||||
@@ -1384,12 +1427,13 @@ admin/views/hashtags.vue:
|
||||
hided-tags: "Hidden Tags"
|
||||
|
||||
admin/views/federation.vue:
|
||||
federation: "連合"
|
||||
instance: "インスタンス"
|
||||
host: "ホスト"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
following: "フォロー中"
|
||||
followers: "フォロワー"
|
||||
caught-at: "登録日時"
|
||||
status: "ステータス"
|
||||
latest-request-sent-at: "直近のリクエスト送信"
|
||||
latest-request-received-at: "直近のリクエスト受信"
|
||||
@@ -1398,7 +1442,7 @@ admin/views/federation.vue:
|
||||
block: "ブロック"
|
||||
marked-as-closed: "閉鎖されているとマーク"
|
||||
lookup: "照会"
|
||||
instances: "インスタンス"
|
||||
instances: "連合"
|
||||
instance-not-registered: "そのインスタンスは登録されていません"
|
||||
sort: "ソート"
|
||||
sorts:
|
||||
@@ -1467,9 +1511,6 @@ desktop/views/pages/search.vue:
|
||||
not-available: "検索機能はインスタンスの設定で無効になっています。"
|
||||
not-found: "「{q}」に関する投稿は見つかりませんでした。"
|
||||
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "{name}で共有"
|
||||
|
||||
desktop/views/pages/tag.vue:
|
||||
no-posts-found: "ハッシュタグ「{q}」が付けられた投稿は見つかりませんでした。"
|
||||
|
||||
@@ -1511,9 +1552,6 @@ desktop/views/pages/user/user.timeline.vue:
|
||||
with-media: "メディア"
|
||||
my-posts: "私の投稿"
|
||||
|
||||
desktop/views/widgets/messaging.vue:
|
||||
title: "メッセージ"
|
||||
|
||||
desktop/views/widgets/notifications.vue:
|
||||
title: "通知"
|
||||
|
||||
@@ -1525,6 +1563,7 @@ desktop/views/widgets/polls.vue:
|
||||
desktop/views/widgets/post-form.vue:
|
||||
title: "投稿"
|
||||
note: "投稿"
|
||||
something-happened: "何らかの事情で投稿できませんでした。"
|
||||
|
||||
desktop/views/widgets/profile.vue:
|
||||
update-banner: "クリックでバナー編集"
|
||||
@@ -1547,12 +1586,11 @@ mobile/views/components/drive.vue:
|
||||
file-count: "ファイル"
|
||||
nothing-in-drive: "ドライブには何もありません"
|
||||
folder-is-empty: "このフォルダは空です"
|
||||
prompt: "何をしますか?(数字を入力してください): <1 → ファイルをアップロード | 2 → ファイルをURLでアップロード | 3 → フォルダ作成 | 4 → このフォルダ名を変更 | 5 → このフォルダを移動 | 6 → このフォルダを削除>"
|
||||
deletion-alert: "ごめんなさい!フォルダの削除は未実装です...。"
|
||||
folder-name: "フォルダー名"
|
||||
here-is-root: "現在いる場所はルートで、フォルダではありません。"
|
||||
url-prompt: "アップロードしたいファイルのURL"
|
||||
uploading: "アップロードをリクエストしました。アップロードが完了するまで時間がかかる場合があります。"
|
||||
folder-name-cannot-empty: "フォルダ名を空白にすることはできません。"
|
||||
|
||||
mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "ファイルを選択"
|
||||
@@ -1617,7 +1655,7 @@ mobile/views/components/post-form.vue:
|
||||
quote-placeholder: "この投稿を引用... (オプション)"
|
||||
reply-placeholder: "この投稿への返信..."
|
||||
cw-placeholder: "内容への注釈 (オプション)"
|
||||
location-alert: "お使いの端末は位置情報に対応していません"
|
||||
geolocation-alert: "お使いの端末は位置情報に対応していません"
|
||||
error: "エラー"
|
||||
username-prompt: "ユーザー名を入力してください"
|
||||
|
||||
@@ -1642,9 +1680,17 @@ mobile/views/components/ui.nav.vue:
|
||||
admin: "管理"
|
||||
about: "Misskeyについて"
|
||||
|
||||
mobile/views/pages/drive.vue:
|
||||
contextmenu:
|
||||
upload: "ファイルをアップロード"
|
||||
url-upload: "ファイルをURLでアップロード"
|
||||
create-folder: "フォルダーを作成"
|
||||
rename-folder: "フォルダー名を変更"
|
||||
move-folder: "このフォルダを移動"
|
||||
delete-folder: "このフォルダを削除"
|
||||
|
||||
mobile/views/pages/user-lists.vue:
|
||||
title: "リスト"
|
||||
enter-list-name: "リスト名を入力してください"
|
||||
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めましょう"
|
||||
@@ -1661,7 +1707,7 @@ mobile/views/pages/home.vue:
|
||||
hybrid: "ソーシャル"
|
||||
global: "グローバル"
|
||||
mentions: "あなた宛て"
|
||||
messages: "メッセージ"
|
||||
messages: "ダイレクト投稿"
|
||||
|
||||
mobile/views/pages/tag.vue:
|
||||
no-posts-found: "ハッシュタグ「{q}」が付けられた投稿は見つかりませんでした。"
|
||||
@@ -1796,24 +1842,18 @@ dev/views/apps.vue:
|
||||
app-missing: "アプリなし"
|
||||
|
||||
dev/views/new-app.vue:
|
||||
new-app: "新しいアプリケーション"
|
||||
new-app-info: "アプリケーションはAPIからでも作成できます。 (app/create)"
|
||||
create-app: "アプリケーションの作成"
|
||||
app-name: "アプリケーション名"
|
||||
app-name-placeholder: "ex) Misskey for iOS"
|
||||
app-name-desc: "あなたのアプリの名称。"
|
||||
app-name-ex: "ex) Misskey for iOS"
|
||||
app-overview: "アプリの概要"
|
||||
app-desc: "あなたのアプリの簡単な説明や紹介。"
|
||||
app-desc-ex: "ex) Misskey iOSクライアント。"
|
||||
app-overview-placeholder: " ex) Misskey iOSクライアント。"
|
||||
app-overview-desc: "あなたのアプリの簡単な説明や紹介。"
|
||||
callback-url: "コールバックURL (オプション)"
|
||||
callback-url-placeholder: "ex) https://your.app.example.com/callback.php"
|
||||
callback-url-desc: "ユーザーが認証フォームで認証した際にリダイレクトするURLを設定できます。"
|
||||
authority: "権限"
|
||||
authority-desc: "ここで要求した機能だけがAPIからアクセスできます。"
|
||||
authority-warning: "アプリ作成後も変更できますが、新たな権限を付与する場合、その時点で関連付けられているユーザーキーはすべて無効になります。"
|
||||
account-read: "アカウントの情報を見る。"
|
||||
account-write: "アカウントの情報を操作する。"
|
||||
note-write: "投稿する。"
|
||||
reaction-write: "リアクションしたりリアクションをキャンセルする。"
|
||||
following-write: "フォローしたりフォロー解除する。"
|
||||
drive-read: "ドライブを見る。"
|
||||
drive-write: "ドライブを操作する。"
|
||||
notification-read: "通知を見る。"
|
||||
notification-write: "通知を操作する。"
|
||||
|
@@ -1,7 +1,6 @@
|
||||
---
|
||||
meta:
|
||||
lang: "日本語 (関西弁)"
|
||||
divider: ""
|
||||
common:
|
||||
misskey: "A ⭐ of fediverse"
|
||||
about-title: "A ⭐ of fediverse."
|
||||
@@ -28,13 +27,6 @@ common:
|
||||
load-more: "もっとあらへんのか!"
|
||||
enter-password: "パスワードを入れてや"
|
||||
2fa: "二段階認証"
|
||||
customize-home: "ホームをカスタマイズ"
|
||||
featured-notes: "ハイライト"
|
||||
dark-mode: "ダークモード"
|
||||
signin: "ログイン"
|
||||
signup: "新規登録"
|
||||
signout: "ログアウト"
|
||||
reload-to-apply-the-setting: "この設定を反映するにはページをリロードする必要があります。今すぐリロードしますか?"
|
||||
got-it: "ほい"
|
||||
customization-tips:
|
||||
title: "カスタマイズのヒント"
|
||||
@@ -64,15 +56,12 @@ common:
|
||||
drive: "ドライブ"
|
||||
messaging: "トーク"
|
||||
home: "ホーム"
|
||||
deck: "デッキ"
|
||||
timeline: "タイムライン"
|
||||
explore: "みつける"
|
||||
following: "フォロー中"
|
||||
following: "フォローしとる"
|
||||
followers: "フォロワー"
|
||||
favorites: "お気に入り"
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "ユーザーをフォローすると投稿がタイムラインに表示されます。"
|
||||
explore: "ユーザーを探索する"
|
||||
permissions:
|
||||
"write:votes": "投票するで"
|
||||
weekday-short:
|
||||
sunday: "日"
|
||||
monday: "月"
|
||||
@@ -118,129 +107,25 @@ common:
|
||||
d: "言うときたいことは?"
|
||||
e: "ここに書いてや"
|
||||
f: "あんさんが書くんを待っちょります..."
|
||||
settings: "設定"
|
||||
_settings:
|
||||
profile: "プロフィール"
|
||||
notification: "通知"
|
||||
apps: "アプリ"
|
||||
tags: "ハッシュタグ"
|
||||
mute-and-block: "ミュート/ブロック"
|
||||
blocking: "ブロック"
|
||||
security: "セキュリティ"
|
||||
signin: "ログイン履歴"
|
||||
password: "パスワード"
|
||||
other: "その他"
|
||||
appearance: "デザイン"
|
||||
behavior: "動作"
|
||||
fetch-on-scroll: "スクロールで自動読み込み"
|
||||
fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。"
|
||||
note-visibility: "投稿の公開範囲"
|
||||
default-note-visibility: "デフォルトの公開範囲"
|
||||
remember-note-visibility: "投稿の公開範囲を記憶する"
|
||||
web-search-engine: "ウェブ検索エンジン"
|
||||
web-search-engine-desc: "例: https://www.google.com/?#q={{query}}"
|
||||
keep-cw: "CW保持"
|
||||
keep-cw-desc: "投稿にリプライする際、リプライ元の投稿にCWが設定されていたとき、デフォルトで同じCWを設定するようにします。"
|
||||
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
|
||||
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
|
||||
use-avatar-reversi-stones: "リバーシの石にアバターを使う"
|
||||
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
|
||||
disable-showing-animated-images: "アニメーション画像を再生しない"
|
||||
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
|
||||
always-show-nsfw: "常に閲覧注意のメディアを表示する"
|
||||
always-mark-nsfw: "常にメディアを閲覧注意として投稿"
|
||||
show-full-acct: "ユーザー名のホストを省略しない"
|
||||
show-via: "viaを表示する"
|
||||
reduce-motion: "UIの動きを減らす"
|
||||
this-setting-is-this-device-only: "このデバイスのみ"
|
||||
use-os-default-emojis: "OS標準の絵文字を使用"
|
||||
line-width: "線の太さ"
|
||||
line-width-thin: "細い"
|
||||
line-width-normal: "普通"
|
||||
line-width-thick: "太い"
|
||||
font-size: "文字の大きさ"
|
||||
font-size-x-small: "小さい"
|
||||
font-size-small: "少し小さい"
|
||||
font-size-medium: "普通"
|
||||
font-size-large: "少し大きい"
|
||||
font-size-x-large: "大きい"
|
||||
deck-column-align: "デッキのカラムの配置"
|
||||
deck-column-align-center: "中央"
|
||||
deck-column-align-left: "左"
|
||||
deck-column-align-flexible: "フレキシブル"
|
||||
deck-column-width: "デッキのカラムの幅"
|
||||
deck-column-width-narrow: "狭"
|
||||
deck-column-width-narrower: "やや狭"
|
||||
deck-column-width-normal: "普通"
|
||||
deck-column-width-wider: "やや広"
|
||||
deck-column-width-wide: "広"
|
||||
use-shadow: "UIに影を使用"
|
||||
rounded-corners: "UIの角を丸める"
|
||||
circle-icons: "円形のアイコンを使用"
|
||||
contrasted-acct: "ユーザー名にコントラストを付ける"
|
||||
wallpaper: "壁紙"
|
||||
choose-wallpaper: "壁紙を選択"
|
||||
delete-wallpaper: "壁紙を削除"
|
||||
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
|
||||
show-clock-on-header: "右上に時計を表示する"
|
||||
show-reply-target: "リプライ先を表示する"
|
||||
timeline: "タイムライン"
|
||||
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
|
||||
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
|
||||
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
|
||||
remain-deleted-note: "削除された投稿を表示し続ける"
|
||||
sound: "サウンド"
|
||||
enable-sounds: "サウンドを有効にする"
|
||||
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。"
|
||||
volume: "ボリューム"
|
||||
test: "テスト"
|
||||
update: "Misskey Update"
|
||||
version: "バージョン:"
|
||||
latest-version: "最新のバージョン:"
|
||||
update-checking: "アップデートを確認中"
|
||||
do-update: "アップデートを確認"
|
||||
update-settings: "詳細設定"
|
||||
no-updates: "利用可能な更新はありません"
|
||||
no-updates-desc: "お使いのMisskeyは最新です。"
|
||||
update-available: "新しいバージョンが利用可能です"
|
||||
update-available-desc: "ページを再度読み込みすると更新が適用されます。"
|
||||
advanced-settings: "高度な設定"
|
||||
debug-mode: "デバッグモードを有効にする"
|
||||
debug-mode-desc: "この設定はブラウザに記憶されます。"
|
||||
navbar-position: "ナビゲーションバーの位置"
|
||||
navbar-position-top: "上"
|
||||
navbar-position-left: "左"
|
||||
navbar-position-right: "右"
|
||||
i-am-under-limited-internet: "私は通信を制限されている"
|
||||
post-style: "投稿の表示スタイル"
|
||||
post-style-standard: "標準"
|
||||
post-style-smart: "スマート"
|
||||
notification-position: "通知の表示"
|
||||
notification-position-bottom: "下"
|
||||
notification-position-top: "上"
|
||||
disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
|
||||
load-raw-images: "添付された画像を高画質で表示する"
|
||||
load-remote-media: "リモートサーバーのメディアを表示する"
|
||||
search: "検索"
|
||||
delete: "削除"
|
||||
loading: "読み込み中"
|
||||
ok: "おk"
|
||||
cancel: "やめる"
|
||||
update-available-title: "更新があんで"
|
||||
update-available: "Misskeyの新しいバージョンがあんで({newer}。現在{current}をつこてるわ)。ページを再度読み込みしたると更新が適用されるわ。"
|
||||
my-token-regenerated: "あんさんのトークンが更新されたらしいわ。すまんがとりあえずサインアウトすんで。"
|
||||
verified-user: "アメちゃん付きアカウント"
|
||||
hide-password: "パスワードを隠す"
|
||||
show-password: "パスワードを表示する"
|
||||
do-not-use-in-production: "開発ビルドや。本番環境で使わんといて!知らんで!"
|
||||
user-suspended: "このユーザーは凍結されています。"
|
||||
is-remote-user: "このユーザー情報は不正確な可能性があります。"
|
||||
is-remote-post: "この投稿情報はコピーです。"
|
||||
view-on-remote: "ちゃんとした情報見せてや!"
|
||||
renoted-by: "{user}がRenote"
|
||||
no-notes: "投稿がありません"
|
||||
turn-on-darkmode: "闇に飲まれる"
|
||||
turn-off-darkmode: "光あれ"
|
||||
error:
|
||||
title: "問題が起こったわ"
|
||||
retry: "もっぺん"
|
||||
@@ -279,19 +164,10 @@ common:
|
||||
hashtags: "ハッシュタグ"
|
||||
dev: "アプリの作成あかんかったわ。もっぺんやってみて。"
|
||||
ai-chan-kawaii: "藍ちゃめっさべっぴんさんや"
|
||||
you: "あなた"
|
||||
you: "あんさん"
|
||||
auth/views/form.vue:
|
||||
share-access: "あんたのアカウントに<i>{name}</i>がアクセスしようとしてるで?ええか?"
|
||||
permission-ask: "このアプリは次の権限を要求してんで:"
|
||||
account-read: "アカウントの情報を見させてもらうで。"
|
||||
account-write: "アカウントの情報を操作させてもらうで。"
|
||||
note-write: "投稿させてもらうで。"
|
||||
like-write: "いいねしたりいいね解除させてもらうで。"
|
||||
following-write: "フォローしたりフォロー解除させてもらうで。"
|
||||
drive-read: "ドライブを見させてもらうで。"
|
||||
drive-write: "ドライブを操作させてもらうで。"
|
||||
notification-read: "通知を見させてもらうで。"
|
||||
notification-write: "通知を操作させてもらうで。"
|
||||
cancel: "やめとくわ"
|
||||
accept: "アクセスを許可や!"
|
||||
auth/views/index.vue:
|
||||
@@ -305,18 +181,8 @@ auth/views/index.vue:
|
||||
error: "セッションが存在してへん。"
|
||||
sign-in: "サインインしてや"
|
||||
common/views/pages/explore.vue:
|
||||
verified-users: "公式アカウント"
|
||||
popular-users: "人気のユーザー"
|
||||
recently-updated-users: "最近投稿したユーザー"
|
||||
recently-registered-users: "新規ユーザー"
|
||||
popular-tags: "人気のタグ"
|
||||
verified-users: "アメちゃん付きアカウント"
|
||||
federated: "連合"
|
||||
explore: "{host}を探索"
|
||||
users-info: "現在{users}ユーザーが登録されています"
|
||||
common/views/components/url-preview.vue:
|
||||
enable-player: "プレイヤーを開く"
|
||||
common/views/components/user-list.vue:
|
||||
no-users: "ユーザーがいません"
|
||||
common/views/components/games/reversi/reversi.vue:
|
||||
matching:
|
||||
waiting-for: "{}を待っとります"
|
||||
@@ -388,7 +254,6 @@ common/views/components/media-banner.vue:
|
||||
sensitive: "見せたらあかん"
|
||||
click-to-show: "押してみ、見せたるわ"
|
||||
common/views/components/theme.vue:
|
||||
theme: "テーマ"
|
||||
light-theme: "ナイトゲームちゃう時のテーマどないする?"
|
||||
dark-theme: "ナイトゲームの時のテーマどないする?"
|
||||
light-themes: "デイゲーム"
|
||||
@@ -405,7 +270,6 @@ common/views/components/theme.vue:
|
||||
base-theme: "この色が背景や!"
|
||||
base-theme-light: "Light"
|
||||
base-theme-dark: "Dark"
|
||||
find-more-theme: "その他のテーマを入手"
|
||||
theme-name: "テーマ名"
|
||||
preview-created-theme: "試してみる"
|
||||
invalid-theme: "このテーマあかんわ、なんか間違うとる"
|
||||
@@ -427,8 +291,6 @@ common/views/components/theme.vue:
|
||||
common/views/components/cw-button.vue:
|
||||
hide: "もうええわ"
|
||||
show: "見たいやろ?"
|
||||
chars: "{count}文字"
|
||||
files: "{count}ファイル"
|
||||
poll: "アンケート"
|
||||
common/views/components/messaging.vue:
|
||||
search-user: "ユーザーを探す"
|
||||
@@ -459,38 +321,22 @@ common/views/components/nav.vue:
|
||||
develop: "開発者"
|
||||
feedback: "フィードバック"
|
||||
common/views/components/note-menu.vue:
|
||||
mention: "メンション"
|
||||
detail: "もっと"
|
||||
copy-content: "内容をコピー"
|
||||
copy-link: "リンクをコピー"
|
||||
favorite: "お気に入り"
|
||||
unfavorite: "お気に入りやめる"
|
||||
watch: "ウォッチ"
|
||||
unwatch: "ウォッチ解除"
|
||||
pin: "ピン留め"
|
||||
unpin: "ピン留めやめる"
|
||||
delete: "ほかす"
|
||||
delete-confirm: "この投稿を削除してもええか?"
|
||||
remote: "投稿元に行ってみよか"
|
||||
common/views/components/user-menu.vue:
|
||||
mention: "メンション"
|
||||
mute: "ミュート"
|
||||
unmute: "ミュート解除"
|
||||
block: "ブロック"
|
||||
unblock: "ブロック解除"
|
||||
push-to-list: "リストに追加"
|
||||
select-list: "リストを選択してください"
|
||||
report-abuse: "スパムを報告"
|
||||
report-abuse-detail: "どのような迷惑行為を行っていますか?"
|
||||
report-abuse-reported: "管理者に報告されました。ご協力ありがとうございました。"
|
||||
silence: "サイレンス"
|
||||
unsilence: "サイレンス解除"
|
||||
suspend: "凍結"
|
||||
unsuspend: "凍結解除"
|
||||
common/views/components/poll.vue:
|
||||
vote-to: "「{}」に投票や!"
|
||||
vote-count: "{}票"
|
||||
total-users: "{}人が投票"
|
||||
vote: "投票するで"
|
||||
show-result: "結果を見よか"
|
||||
voted: "投票済みや"
|
||||
@@ -500,6 +346,7 @@ common/views/components/poll-editor.vue:
|
||||
remove: "この選択肢を消すで"
|
||||
add: "+選択肢を追加"
|
||||
destroy: "アンケートをほかそ"
|
||||
day: "日"
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "リアクション、どれにするんや?"
|
||||
common/views/components/emoji-picker.vue:
|
||||
@@ -554,11 +401,6 @@ common/views/components/stream-indicator.vue:
|
||||
connected: "つないだわ"
|
||||
common/views/components/notification-settings.vue:
|
||||
title: "通知"
|
||||
mark-as-read-all-notifications: "すべての通知を既読にする"
|
||||
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
|
||||
mark-as-read-all-talk-messages: "すべてのトークを既読にする"
|
||||
auto-watch: "投稿の自動ウォッチ"
|
||||
auto-watch-desc: "リアクションしたり返信したりした投稿に関する通知を自動的に受け取るようにします。"
|
||||
common/views/components/integration-settings.vue:
|
||||
title: "サービス連携"
|
||||
connect: "つなげる"
|
||||
@@ -608,7 +450,6 @@ common/views/components/profile-editor.vue:
|
||||
account: "アカウント"
|
||||
location: "場所"
|
||||
description: "自己紹介"
|
||||
you-can-include-hashtags: "ハッシュタグを含めることができます。"
|
||||
language: "言語"
|
||||
birthday: "誕生日"
|
||||
avatar: "アイコン"
|
||||
@@ -617,7 +458,6 @@ common/views/components/profile-editor.vue:
|
||||
is-bot: "このアカウントはBotやで"
|
||||
is-locked: "他人のフォローは許可してからや!"
|
||||
careful-bot: "Botからのフォローだけは許可制や"
|
||||
auto-accept-followed: "フォローしているユーザーからのフォローを自動承認する"
|
||||
advanced: "その他"
|
||||
privacy: "プライバシーってなんや?オカンの年齢か?"
|
||||
save: "保存"
|
||||
@@ -629,23 +469,17 @@ common/views/components/profile-editor.vue:
|
||||
email-verified: "このメールアドレスOKや!"
|
||||
email-not-verified: "メールアドレスが確認されとらん。メールボックスもっぺん見てくれへん?"
|
||||
export: "エクスポート"
|
||||
import: "インポート"
|
||||
export-targets:
|
||||
all-notes: "すべての投稿データ"
|
||||
following-list: "フォロー"
|
||||
mute-list: "ミュート"
|
||||
blocking-list: "ブロック"
|
||||
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
||||
enter-password: "パスワードを入力してください"
|
||||
danger-zone: "危険な設定"
|
||||
delete-account: "アカウントを削除"
|
||||
account-deleted: "アカウントが削除されました。データが消えるまで時間がかかる場合があります。"
|
||||
user-lists: "リスト"
|
||||
enter-password: "パスワードを入れてや"
|
||||
common/views/components/user-list-editor.vue:
|
||||
users: "ユーザー"
|
||||
rename: "リスト名を変更"
|
||||
delete: "リストを削除"
|
||||
remove-user: "このリストから削除"
|
||||
delete-are-you-sure: "リスト「$1」を削除しますか?"
|
||||
deleted: "削除しました"
|
||||
common/views/components/user-lists.vue:
|
||||
list-name: "リスト名"
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "見てみるわ…"
|
||||
no-broadcasts: "お知らせはあらへんで"
|
||||
@@ -695,11 +529,8 @@ common/views/widgets/tips.vue:
|
||||
tips-line19: "いくつかのウィンドウはブラウザの外に切り離すことができんで"
|
||||
tips-line20: "カレンダーウィジェットのパーセンテージは、経過の割合を示してんねん"
|
||||
tips-line21: "APIをつこてbotの開発なども行えるで"
|
||||
tips-line23: "藍かわいいよ藍"
|
||||
tips-line24: "Misskeyは2014年にサービスを開始したんよ"
|
||||
tips-line25: "対応ブラウザやったらMisskeyを開いとらんでも通知を受け取れんで"
|
||||
common/views/pages/not-found.vue:
|
||||
page-not-found: "ページが見つかりませんでした"
|
||||
common/views/pages/follow.vue:
|
||||
signed-in-as: "{}としてサインイン中"
|
||||
following: "フォローしとる"
|
||||
@@ -816,22 +647,16 @@ desktop/views/components/home.vue:
|
||||
desktop/views/input-dialog.vue:
|
||||
cancel: "やめとくわ"
|
||||
ok: "これや!"
|
||||
desktop/views/components/messaging-room-window.vue:
|
||||
title: "メッセージ:"
|
||||
desktop/views/components/messaging-window.vue:
|
||||
title: "メッセージ"
|
||||
desktop/views/components/note-detail.vue:
|
||||
private: "この投稿は見せられへんわ"
|
||||
deleted: "この投稿なんか無くなってもうたわ"
|
||||
location: "ここおるで:"
|
||||
renote: "Renote"
|
||||
add-reaction: "リアクション"
|
||||
undo-reaction: "リアクション解除"
|
||||
desktop/views/components/note.vue:
|
||||
reply: "返す"
|
||||
renote: "Renote"
|
||||
add-reaction: "リアクション"
|
||||
undo-reaction: "リアクション解除"
|
||||
detail: "もっと"
|
||||
private: "この投稿は見せられへんわ"
|
||||
deleted: "この投稿なんか無くなってもうたわ"
|
||||
@@ -858,8 +683,6 @@ desktop/views/components/post-form.vue:
|
||||
posting: "投稿中"
|
||||
attach-media-from-local: "PCからメディア持ってくる"
|
||||
attach-media-from-drive: "ドライブからメディア持ってくる"
|
||||
attach-cancel: "くっつけるのやめよか"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "アンケートを作成"
|
||||
text-remain: "残り{}文字"
|
||||
recent-tags: "最近のタグ"
|
||||
@@ -910,8 +733,8 @@ desktop/views/components/settings.2fa.vue:
|
||||
failed: "なんか設定に失敗したで。トークンを間違えとらんか確認してや。"
|
||||
info: "次のサインインからは、パスワードに加えてデバイスに出とるトークンを入力してな。"
|
||||
common/views/components/media-image.vue:
|
||||
sensitive: "閲覧注意"
|
||||
click-to-show: "クリックして表示"
|
||||
sensitive: "ちょっと見せられへんわ"
|
||||
click-to-show: "クリックして見せるで"
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "API使うんやったらこのトークンを「i」っちゅうパラメータにくっつけてリクエストできるで。"
|
||||
caution: "アカウント勝手にいじられるかも知れんから、このトークンは教えたらあかんし、アプリにも書いたらあかんで(これはフリちゃうで)"
|
||||
@@ -950,26 +773,23 @@ common/views/components/password-settings.vue:
|
||||
enter-new-password-again: "もっぺん入れてや"
|
||||
not-match: "パスワードがおうとらん"
|
||||
changed: "パスワード変えたわ"
|
||||
failed: "パスワード変更に失敗しました"
|
||||
common/views/components/post-form-attaches.vue:
|
||||
mark-as-sensitive: "見たらあかん感じにしとく"
|
||||
unmark-as-sensitive: "やっぱ見せたるわ"
|
||||
desktop/views/components/sub-note-content.vue:
|
||||
private: "この投稿は見せられへんわ"
|
||||
deleted: "この投稿なんか無くなってもうたわ"
|
||||
media-count: "{}つのメディア"
|
||||
poll: "アンケート"
|
||||
desktop/views/components/settings.tags.vue:
|
||||
title: "タグ"
|
||||
query: "クエリ (省略可)"
|
||||
add: "追加"
|
||||
add: "増やす"
|
||||
save: "保存"
|
||||
desktop/views/components/taskmanager.vue:
|
||||
title: "タスクマネージャ"
|
||||
desktop/views/components/timeline.vue:
|
||||
home: "ホーム"
|
||||
local: "ローカル"
|
||||
hybrid: "ソーシャル"
|
||||
global: "グローバル"
|
||||
mentions: "あんた宛て"
|
||||
messages: "メッセージ"
|
||||
messages: "ダイレクト投稿"
|
||||
list: "リスト"
|
||||
hashtag: "ハッシュタグ"
|
||||
add-tag-timeline: "ハッシュタグ増やす"
|
||||
@@ -997,8 +817,6 @@ desktop/views/components/received-follow-requests-window.vue:
|
||||
reject: "許さん"
|
||||
desktop/views/components/user-lists-window.vue:
|
||||
title: "リスト"
|
||||
create-list: "新しいリストを作成"
|
||||
list-name: "リスト名"
|
||||
desktop/views/components/user-preview.vue:
|
||||
notes: "投稿"
|
||||
following: "フォロー"
|
||||
@@ -1021,8 +839,6 @@ admin/views/index.vue:
|
||||
federation: "連合"
|
||||
announcements: "知っといてや"
|
||||
hashtags: "ハッシュタグ"
|
||||
abuse: "スパム報告"
|
||||
queue: "ジョブキュー"
|
||||
back-to-misskey: "Misskeyに戻る"
|
||||
admin/views/dashboard.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
@@ -1032,14 +848,8 @@ admin/views/dashboard.vue:
|
||||
instances: "インスタンス"
|
||||
this-instance: "ワイのインスタンス"
|
||||
federated: "連合"
|
||||
admin/views/queue.vue:
|
||||
operation: "操作"
|
||||
remove-all-jobs: "すべてのジョブをクリア"
|
||||
admin/views/abuse.vue:
|
||||
title: "スパム報告"
|
||||
target: "対象"
|
||||
reporter: "報告者"
|
||||
details: "詳細"
|
||||
details: "もっと"
|
||||
remove-report: "削除"
|
||||
admin/views/instance.vue:
|
||||
instance: "インスタンス"
|
||||
@@ -1047,7 +857,6 @@ admin/views/instance.vue:
|
||||
instance-description: "インスタンスの紹介"
|
||||
host: "ホスト"
|
||||
banner-url: "バナー画像URL"
|
||||
error-image-url: "エラー画像URL"
|
||||
languages: "インスタンスの対象言語"
|
||||
languages-desc: "スペースで区切って複数設定できるで。"
|
||||
maintainer-config: "管理者情報"
|
||||
@@ -1087,17 +896,10 @@ admin/views/instance.vue:
|
||||
max-note-text-length: "投稿の最大文字数"
|
||||
disable-registration: "ユーザー登録の受付を止める"
|
||||
disable-local-timeline: "ローカルタイムラインを使えんようにする"
|
||||
disable-global-timeline: "グローバルタイムラインを無効にする"
|
||||
disabling-timelines-info: "これらのタイムラインを無効にしても、管理者およびモデレーターは引き続き利用できます。"
|
||||
invite: "来てや"
|
||||
save: "保存"
|
||||
saved: "保存したで!"
|
||||
user-recommendation-config: "このユーザーええで"
|
||||
enable-external-user-recommendation: "外部ユーザーレコメンデーションを使えるようにする"
|
||||
external-user-recommendation-engine: "エンジン"
|
||||
external-user-recommendation-engine-desc: "例: https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}"
|
||||
external-user-recommendation-timeout: "タイムアウト"
|
||||
external-user-recommendation-timeout-desc: "ミリ秒単位 (例: 300000)"
|
||||
email-config: "メールサーバーの設定"
|
||||
email-config-info: "メールアドレス確認やパスワードリセットの際に使うで。"
|
||||
enable-email: "メール配信を有効にする"
|
||||
@@ -1106,15 +908,8 @@ admin/views/instance.vue:
|
||||
smtp-secure-info: "STARTTLS使用時はオフにします。"
|
||||
smtp-host: "SMTPホスト"
|
||||
smtp-port: "SMTPポート"
|
||||
smtp-auth: "SMTP認証を行う"
|
||||
smtp-user: "SMTPユーザー"
|
||||
smtp-pass: "SMTPパスワード"
|
||||
serviceworker-config: "ServiceWorker"
|
||||
enable-serviceworker: "ServiceWorkerを有効にする"
|
||||
serviceworker-info: "プッシュ通知を行うには有効する必要があります。"
|
||||
vapid-publickey: "VAPID公開鍵"
|
||||
vapid-privatekey: "VAPID秘密鍵"
|
||||
vapid-info: "ServiceWorkerを有効にする場合、VAPIDキーペアを生成する必要があります。シェルで次のようにします:"
|
||||
admin/views/charts.vue:
|
||||
title: "チャート"
|
||||
per-day: "1日ごと"
|
||||
@@ -1133,7 +928,6 @@ admin/views/charts.vue:
|
||||
notes-total: "投稿の積算"
|
||||
users: "ユーザーの増減"
|
||||
users-total: "ユーザーの積算"
|
||||
active-users: "アクティブユーザー数"
|
||||
drive: "ドライブ使用量の増減"
|
||||
drive-total: "ドライブ使用量の積算"
|
||||
drive-files: "ドライブのファイル数の増減"
|
||||
@@ -1143,168 +937,61 @@ admin/views/charts.vue:
|
||||
network-usage: "通信量"
|
||||
admin/views/drive.vue:
|
||||
operation: "操作"
|
||||
fileid-or-url: "ファイルIDまたはファイルURL"
|
||||
file-not-found: "ファイルが見つかりません"
|
||||
lookup: "照会"
|
||||
sort:
|
||||
title: "ソート"
|
||||
createdAtAsc: "アップロード日時が古い順"
|
||||
createdAtDesc: "アップロード日時が新しい順"
|
||||
sizeAsc: "サイズが小さい順"
|
||||
sizeDesc: "サイズが大きい順"
|
||||
origin:
|
||||
title: "オリジン"
|
||||
combined: "ローカル+リモート"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
delete: "削除"
|
||||
deleted: "削除しました"
|
||||
mark-as-sensitive: "閲覧注意に設定"
|
||||
unmark-as-sensitive: "閲覧注意を解除"
|
||||
marked-as-sensitive: "閲覧注意に設定しました"
|
||||
unmarked-as-sensitive: "閲覧注意を解除しました"
|
||||
mark-as-sensitive: "見たらあかん感じにしとく"
|
||||
unmark-as-sensitive: "やっぱ見せたるわ"
|
||||
admin/views/users.vue:
|
||||
operation: "操作"
|
||||
username-or-userid: "ユーザー名またはユーザーID"
|
||||
user-not-found: "ユーザーが見つからへん!"
|
||||
lookup: "照会"
|
||||
reset-password: "パスワードをリセット"
|
||||
reset-password-confirm: "パスワードをリセットしますか?"
|
||||
password-updated: "パスワードは現在「{password} 」やで"
|
||||
suspend: "凍結"
|
||||
suspend-confirm: "凍結しますか?"
|
||||
suspended: "凍結しました"
|
||||
unsuspend: "凍結の解除"
|
||||
unsuspend-confirm: "凍結を解除しますか?"
|
||||
unsuspended: "凍結を解除しました"
|
||||
make-silence: "サイレンス"
|
||||
unmake-silence: "サイレンスの解除"
|
||||
verify: "公式アカウントにする"
|
||||
verify-confirm: "公式アカウントにしますか?"
|
||||
verified: "公式アカウントにしました"
|
||||
unverify: "公式アカウントを解除する"
|
||||
unverify-confirm: "公式アカウントを解除しますか?"
|
||||
unverified: "公式アカウントを解除しました"
|
||||
update-remote-user: "リモートユーザー情報の更新"
|
||||
remote-user-updated: "リモートユーザー情報を更新しました"
|
||||
users:
|
||||
title: "ユーザー"
|
||||
sort:
|
||||
title: "ソート"
|
||||
createdAtAsc: "登録日時が古い順"
|
||||
createdAtDesc: "登録日時が新しい順"
|
||||
updatedAtAsc: "更新日時が古い順"
|
||||
updatedAtDesc: "更新日時が新しい順"
|
||||
state:
|
||||
title: "状態"
|
||||
all: "すべて"
|
||||
admin: "管理者"
|
||||
moderator: "モデレーター"
|
||||
adminOrModerator: "管理者+モデレーター"
|
||||
verified: "公式アカウント"
|
||||
silenced: "サイレンス済み"
|
||||
suspended: "凍結済み"
|
||||
verified: "アメちゃん付きアカウント"
|
||||
origin:
|
||||
title: "オリジン"
|
||||
combined: "ローカル+リモート"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
createdAt: "登録日時"
|
||||
updatedAt: "更新日時"
|
||||
admin/views/moderators.vue:
|
||||
add-moderator:
|
||||
title: "モデレーターの登録"
|
||||
add: "登録"
|
||||
added: "モデレーターを登録しました"
|
||||
remove: "解除"
|
||||
removed: "モデレーター登録を解除しました"
|
||||
admin/views/emoji.vue:
|
||||
add-emoji:
|
||||
title: "絵文字の登録"
|
||||
name: "絵文字名"
|
||||
name-desc: "a~z 0~9 _ の文字が使えます。"
|
||||
aliases: "エイリアス"
|
||||
aliases-desc: "スペースで区切って複数設定できます。"
|
||||
url: "絵文字画像URL"
|
||||
add: "追加"
|
||||
info: "50KB以下のPNG画像をおすすめします。"
|
||||
added: "絵文字を登録しました"
|
||||
add: "増やす"
|
||||
emojis:
|
||||
title: "絵文字一覧"
|
||||
update: "更新"
|
||||
remove: "削除"
|
||||
updated: "更新しました"
|
||||
remove-emoji:
|
||||
are-you-sure: "「$1」を削除しますか?"
|
||||
removed: "削除しました"
|
||||
admin/views/announcements.vue:
|
||||
announcements: "お知らせ"
|
||||
announcements: "知っときや"
|
||||
save: "保存"
|
||||
remove: "削除"
|
||||
add: "追加"
|
||||
title: "タイトル"
|
||||
text: "内容"
|
||||
saved: "保存しました"
|
||||
_remove:
|
||||
are-you-sure: "「$1」を削除しますか?"
|
||||
removed: "削除しました"
|
||||
admin/views/hashtags.vue:
|
||||
hided-tags: "Hidden Tags"
|
||||
add: "増やす"
|
||||
saved: "保存したで!"
|
||||
admin/views/federation.vue:
|
||||
federation: "連合"
|
||||
instance: "インスタンス"
|
||||
host: "ホスト"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
following: "フォロー中"
|
||||
following: "フォローしとる"
|
||||
followers: "フォロワー"
|
||||
status: "ステータス"
|
||||
latest-request-sent-at: "直近のリクエスト送信"
|
||||
latest-request-received-at: "直近のリクエスト受信"
|
||||
remove-all-following: "フォローを全解除"
|
||||
remove-all-following-info: "{host}からのフォローをすべて解除します。そのインスタンスがもう存在しなくなった場合などに実行してください。"
|
||||
block: "ブロック"
|
||||
marked-as-closed: "閉鎖されているとマーク"
|
||||
lookup: "照会"
|
||||
instances: "インスタンス"
|
||||
instance-not-registered: "そのインスタンスは登録されていません"
|
||||
sort: "ソート"
|
||||
sorts:
|
||||
caughtAtAsc: "登録日時が古い順"
|
||||
caughtAtDesc: "登録日時が新しい順"
|
||||
lastCommunicatedAtAsc: "最後にやり取りした日時が古い順"
|
||||
lastCommunicatedAtDesc: "最後にやり取りした日時が新しい順"
|
||||
notesAsc: "投稿が少ない順"
|
||||
notesDesc: "投稿が多い順"
|
||||
usersAsc: "ユーザーが少ない順"
|
||||
usersDesc: "ユーザーが多い順"
|
||||
followingAsc: "フォローが少ない順"
|
||||
followingDesc: "フォローが多い順"
|
||||
followersAsc: "フォロワーが少ない順"
|
||||
followersDesc: "フォロワーが多い順"
|
||||
driveUsageAsc: "ドライブ使用量が少ない順"
|
||||
driveUsageDesc: "ドライブ使用量が多い順"
|
||||
driveFilesAsc: "ドライブのファイル数が少ない順"
|
||||
driveFilesDesc: "ドライブのファイル数が多い順"
|
||||
state: "状態"
|
||||
instances: "連合"
|
||||
states:
|
||||
all: "すべて"
|
||||
blocked: "ブロック"
|
||||
not-responding: "応答なし"
|
||||
marked-as-closed: "閉鎖とマーク済み"
|
||||
result-is-truncated: "上位{n}件を表示しています。"
|
||||
charts: "チャート"
|
||||
chart-srcs:
|
||||
requests: "リクエスト"
|
||||
users: "ユーザーの増減"
|
||||
users-total: "ユーザーの積算"
|
||||
notes: "投稿の増減"
|
||||
notes-total: "投稿の積算"
|
||||
ff: "フォロー/フォロワーの増減"
|
||||
ff-total: "フォロー/フォロワーの積算"
|
||||
drive-usage: "ドライブ使用量の増減"
|
||||
drive-usage-total: "ドライブ使用量の積算"
|
||||
drive-files: "ドライブファイル数の増減"
|
||||
drive-files-total: "ドライブファイル数の積算"
|
||||
chart-spans:
|
||||
hour: "1時間ごと"
|
||||
day: "1日ごと"
|
||||
@@ -1327,11 +1014,6 @@ desktop/views/pages/selectdrive.vue:
|
||||
upload: "PCからドライブにファイル上げる"
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "検索機能は使えへんわ。管理者がそう言うとる。"
|
||||
not-found: "「{q}」に関する投稿は見つかりませんでした。"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "{name}で共有"
|
||||
desktop/views/pages/tag.vue:
|
||||
no-posts-found: "ハッシュタグ「{q}」が付けられた投稿は見つかりませんでした。"
|
||||
desktop/views/pages/user-list.users.vue:
|
||||
users: "ユーザー"
|
||||
add-user: "ユーザー増やす"
|
||||
@@ -1353,19 +1035,15 @@ desktop/views/pages/user/user.header.vue:
|
||||
following: "フォロー"
|
||||
followers: "フォロワー"
|
||||
is-bot: "このアカウントはBotや"
|
||||
no-description: "自己紹介はありません"
|
||||
years-old: "{age}歳"
|
||||
year: "年"
|
||||
month: "月"
|
||||
day: "日"
|
||||
follows-you: "フォローされています"
|
||||
follows-you: "フォローされとるで"
|
||||
desktop/views/pages/user/user.timeline.vue:
|
||||
default: "投稿"
|
||||
with-replies: "投稿と返信"
|
||||
with-media: "メディア"
|
||||
my-posts: "私の投稿"
|
||||
desktop/views/widgets/messaging.vue:
|
||||
title: "メッセージ"
|
||||
desktop/views/widgets/notifications.vue:
|
||||
title: "通知"
|
||||
desktop/views/widgets/polls.vue:
|
||||
@@ -1393,10 +1071,7 @@ mobile/views/components/drive.vue:
|
||||
file-count: "ファイル"
|
||||
nothing-in-drive: "ドライブには何もあらへんで。"
|
||||
folder-is-empty: "このフォルダ何もないわ"
|
||||
prompt: "何すんの?(数字を入れてや): <1 → ファイルをアップロード | 2 → ファイルをURLでアップロード | 3 → フォルダ作成 | 4 → このフォルダ名を変更 | 5 → このフォルダを移動 | 6 → このフォルダを削除>"
|
||||
deletion-alert: "フォルダの削除は未実装やねん...。堪忍な!"
|
||||
folder-name: "フォルダー名"
|
||||
here-is-root: "現在いる場所はルートで、フォルダではありません。"
|
||||
url-prompt: "このURLのファイルをアップロードしたいねん"
|
||||
uploading: "アップロードをリクエストしたで。アップロードが完了するまで時間がかかるかも分からん、知らんけど。"
|
||||
mobile/views/components/drive-file-chooser.vue:
|
||||
@@ -1451,7 +1126,7 @@ mobile/views/components/post-form.vue:
|
||||
quote-placeholder: "この投稿を持ってくる(オプション)"
|
||||
reply-placeholder: "この投稿への返信..."
|
||||
cw-placeholder: "内容への注釈 (オプション)"
|
||||
location-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。"
|
||||
geolocation-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。"
|
||||
error: "エラー"
|
||||
username-prompt: "ユーザー名を入力してや"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
@@ -1472,9 +1147,12 @@ mobile/views/components/ui.nav.vue:
|
||||
game: "ゲーム"
|
||||
admin: "管理"
|
||||
about: "Misskeyってなんや?"
|
||||
mobile/views/pages/drive.vue:
|
||||
contextmenu:
|
||||
upload: "ファイル上げる"
|
||||
create-folder: "フォルダー作る"
|
||||
mobile/views/pages/user-lists.vue:
|
||||
title: "リスト"
|
||||
enter-list-name: "リスト名を入力してや"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めようや"
|
||||
mobile/views/pages/followers.vue:
|
||||
@@ -1484,16 +1162,14 @@ mobile/views/pages/following.vue:
|
||||
mobile/views/pages/home.vue:
|
||||
home: "ホーム"
|
||||
local: "ローカル"
|
||||
hybrid: "ソーシャル"
|
||||
global: "グローバル"
|
||||
mentions: "あんた宛て"
|
||||
messages: "メッセージ"
|
||||
messages: "ダイレクト投稿"
|
||||
mobile/views/pages/tag.vue:
|
||||
no-posts-found: "ハッシュタグ「{q}」が付けられた投稿はあらへんかった。"
|
||||
mobile/views/pages/widgets.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
widgets-hints: "ウィジェットを追加/削除したり並べ替えたりできます。ウィジェットを移動するには「三」をドラッグします。ウィジェットを削除するには「x」をタップします。いくつかのウィジェットはタップすることで表示を変更できます。"
|
||||
add-widget: "追加"
|
||||
add-widget: "増やす"
|
||||
customization-tips: "カスタマイズのヒント"
|
||||
mobile/views/pages/widgets/activity.vue:
|
||||
activity: "やっとること"
|
||||
@@ -1531,7 +1207,7 @@ mobile/views/pages/user/home.vue:
|
||||
activity: "やっとること"
|
||||
keywords: "キーワード"
|
||||
domains: "よく出るドメイン"
|
||||
frequently-replied-users: "よく話すユーザー"
|
||||
frequently-replied-users: "よう話すツレ"
|
||||
followers-you-know: "知っとるフォロワー"
|
||||
last-used-at: "最後いつ来た?"
|
||||
mobile/views/pages/user/home.photos.vue:
|
||||
@@ -1540,14 +1216,12 @@ deck:
|
||||
widgets: "ウィジェット"
|
||||
home: "ホーム"
|
||||
local: "ローカル"
|
||||
hybrid: "ソーシャル"
|
||||
hashtag: "ハッシュタグ"
|
||||
global: "グローバル"
|
||||
mentions: "あんた宛て"
|
||||
direct: "ダイレクト投稿"
|
||||
notifications: "通知"
|
||||
list: "リスト"
|
||||
select-list: "リストを選択してください"
|
||||
swap-left: "左に移動や!"
|
||||
swap-right: "右に移動や!"
|
||||
swap-up: "上に移動や!"
|
||||
@@ -1557,14 +1231,11 @@ deck:
|
||||
rename: "名前を変えるで"
|
||||
stack-left: "左に重ねんで!"
|
||||
pop-right: "右に出すで!"
|
||||
disabled-timeline:
|
||||
title: "無効化されたタイムライン"
|
||||
description: "サーバーの運営者により、このタイムラインは使用できない状態に設定されています。"
|
||||
deck/deck.tl-column.vue:
|
||||
is-media-only: "メディア投稿だけや"
|
||||
edit: "オプション"
|
||||
deck/deck.user-column.vue:
|
||||
follows-you: "フォローされています"
|
||||
follows-you: "フォローされとるで"
|
||||
posts: "投稿"
|
||||
following: "フォロー"
|
||||
followers: "フォロワー"
|
||||
@@ -1604,21 +1275,9 @@ dev/views/new-app.vue:
|
||||
create-app: "アプリケーション作る"
|
||||
app-name: "アプリケーションの名前"
|
||||
app-name-desc: "あんたのアプリの名前。"
|
||||
app-name-ex: "ex) 関西ミスキー保安協会"
|
||||
app-overview: "このアプリどんなん?"
|
||||
app-desc: "あんたのアプリどんなんか教えて"
|
||||
app-desc-ex: "ex) 関西人なら誰でも口ずさめるこのCMがついにMisskeyへ。"
|
||||
callback-url: "コールバックURL (無くてもええで)"
|
||||
callback-url-desc: "ユーザーが認証フォームで認証した後どこに連れてくかを設定できるで"
|
||||
authority: "権限"
|
||||
authority-desc: "ここにチェックした機能しかAPIからアクセスできひんから気ぃつけてな"
|
||||
authority-warning: "アプリ作った後でも変えれるけど、新しいやつ追加したらそん時関連付いてるユーザーキーは全部ほかされるで。"
|
||||
account-read: "アカウントの情報見せて"
|
||||
account-write: "アカウントの情報いじらせて"
|
||||
note-write: "投稿させて"
|
||||
reaction-write: "リアクションしたりそれをキャンセルさせて"
|
||||
following-write: "フォローとかフォロー解除させて"
|
||||
drive-read: "ドライブ見せて"
|
||||
drive-write: "ドライブいじらせて"
|
||||
notification-read: "通知見せて"
|
||||
notification-write: "通知いじらせて"
|
||||
|
@@ -1,14 +1,13 @@
|
||||
---
|
||||
meta:
|
||||
lang: "한국어"
|
||||
divider: ""
|
||||
common:
|
||||
misskey: "연합우주의 ⭐"
|
||||
about-title: "연합우주의 ⭐."
|
||||
about: "Misskey를 찾아주셔서 감사합니다. Misskey는 지구에서 태어난 <b>분산 마이크로 블로그 SNS </b> 입니다. Fediverse(다양한 SNS로 구성되는 우주)에 존재하는 다른 SNS와 상호 연결되어 있습니다. 잠시 도시의 번잡함에서 벗어나 새로운 인터넷에 다이브 해 보지 않겠습니까."
|
||||
intro:
|
||||
title: "Misskey란?"
|
||||
about: "Misskey는 오픈소스 <b>분산형 마이크로블로그 SNS</b>입니다. 다양하고 폭넓게 커스터마이징할 수 있는 UI, 글에 대한 반응, 파일을 관리할 수 있는 드라이브 등의 선진적인 기능을 갖추고 있습니다. 더하여 Fediverse라고 부르는 네트워크에 연결할 수 있어 다른 SNS와도 주고받을 수 있습니다. 예를 들자면, 당신이 무언가를 게시하면, 해당 게시물은 Misskey 뿐만 아니라 다른 SNS에도 전해집니다. 살짝 어떤 행성에서 다른 행성으로 전파를 발신하고 있는 모습을 상상해주세요."
|
||||
about: "Misskey는 오픈소스 <b>분산형 마이크로블로그 SNS</b>입니다. 다양하고 폭넓게 커스터마이징할 수 있는 UI, 글에 대한 리액션, 파일을 관리할 수 있는 드라이브 등의 선진적인 기능을 갖추고 있습니다. 더하여 Fediverse라고 부르는 네트워크에 연결할 수 있어 다른 SNS와도 주고받을 수 있습니다. 예를 들자면, 당신이 무언가를 게시하면, 해당 게시물은 Misskey 뿐만 아니라 다른 SNS에도 전해집니다. 살짝 어떤 행성에서 다른 행성으로 전파를 발신하고 있는 모습을 상상해주세요."
|
||||
features: "특징"
|
||||
rich-contents: "글"
|
||||
rich-contents-desc: "자신의 생각, 화제의 사건, 모두와 공유하고 싶은 것을 올려주세요. 필요한 경우 다양한 스타일을 사용하여 글을 장식하거나 마음에 드는 이미지, 영상 등의 파일이나 투표를 올리는 것도 가능합니다."
|
||||
@@ -70,6 +69,12 @@ common:
|
||||
following: "팔로우 중"
|
||||
followers: "팔로워"
|
||||
favorites: "즐겨찾기"
|
||||
permissions:
|
||||
"read:account": "계정 정보 보기"
|
||||
"write:account": "계정 정보 변경"
|
||||
"read:drive": "드라이브 보기"
|
||||
"write:drive": "드라이브 수정"
|
||||
"write:votes": "투표하기"
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "사용자를 팔로우하면 글이 타임라인에 표시됩니다."
|
||||
explore: "사용자 탐색"
|
||||
@@ -277,21 +282,13 @@ common:
|
||||
nav: "내비게이션"
|
||||
tips: "팁"
|
||||
hashtags: "해시태그"
|
||||
queue: "큐"
|
||||
dev: "앱을 만드는 데 실패했습니다. 다시 시도하시기 바랍니다."
|
||||
ai-chan-kawaii: "아이쨩 귀여워"
|
||||
you: "당신"
|
||||
auth/views/form.vue:
|
||||
share-access: "<i>{name}</i>가 당신의 계정에 엑세스하도록 허용하시겠습니까?"
|
||||
permission-ask: "이 앱은 다음의 권한을 요청합니다:"
|
||||
account-read: "계정 정보 보기."
|
||||
account-write: "계정 정보의 수정."
|
||||
note-write: "게시하기."
|
||||
like-write: "좋아요 하거나 좋아요 해제하기."
|
||||
following-write: "팔로우하거나 팔로우를 취소하기."
|
||||
drive-read: "드라이브 보기."
|
||||
drive-write: "드라이브의 수정."
|
||||
notification-read: "알림 읽기."
|
||||
notification-write: "알림 수정하기."
|
||||
cancel: "취소"
|
||||
accept: "접근 권한 허용"
|
||||
auth/views/index.vue:
|
||||
@@ -315,6 +312,7 @@ common/views/pages/explore.vue:
|
||||
users-info: "현재 {users} 사용자가 등록되어 있습니다"
|
||||
common/views/components/url-preview.vue:
|
||||
enable-player: "플레이어 열기"
|
||||
disable-player: "플레이어 닫기"
|
||||
common/views/components/user-list.vue:
|
||||
no-users: "사용자가 없습니다"
|
||||
common/views/components/games/reversi/reversi.vue:
|
||||
@@ -490,18 +488,37 @@ common/views/components/user-menu.vue:
|
||||
common/views/components/poll.vue:
|
||||
vote-to: "\"{}\"에 투표하기"
|
||||
vote-count: "{}표"
|
||||
total-users: "{}명이 투표"
|
||||
total-votes: "총 {}표"
|
||||
vote: "투표하기"
|
||||
show-result: "결과 보기"
|
||||
voted: "투표함"
|
||||
closed: "종료됨"
|
||||
remaining-days: "종료까지 앞으로 {d}일 {h}시간"
|
||||
remaining-hours: "종료까지 앞으로 {h}시간 {m}분"
|
||||
remaining-minutes: "종료까지 앞으로 {m}분 {s}초"
|
||||
remaining-seconds: "종료까지 앞으로 {s}초"
|
||||
common/views/components/poll-editor.vue:
|
||||
no-only-one-choice: "투표에는 선택지가 최소한 두 개 필요합니다"
|
||||
choice-n: "선택지 {}"
|
||||
remove: "이 선택지를 제거"
|
||||
add: "+선택지 추가"
|
||||
destroy: "투표 제거"
|
||||
multiple: "복수 응답 가능"
|
||||
expiration: "기한"
|
||||
infinite: "무기한"
|
||||
at: "일시 지정"
|
||||
after: "기간 지정"
|
||||
no-more: "더 이상 추가할 수 없습니다"
|
||||
deadline-date: "기한"
|
||||
deadline-time: "시간"
|
||||
interval: "기간"
|
||||
unit: "단위"
|
||||
second: "초"
|
||||
minute: "분"
|
||||
hour: "시간"
|
||||
day: "일"
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "반응 선택"
|
||||
choose-reaction: "리액션 선택"
|
||||
common/views/components/emoji-picker.vue:
|
||||
custom-emoji: "커스텀 이모지"
|
||||
people: "사람들"
|
||||
@@ -629,12 +646,16 @@ common/views/components/profile-editor.vue:
|
||||
email-verified: "매일 주소가 확인되었습니다"
|
||||
email-not-verified: "메일 주소가 확인되지 않았습니다. 받은 편지함을 확인하여 주시기 바랍니다."
|
||||
export: "내보내기"
|
||||
import: "가져오기"
|
||||
export-and-import: "내보내기와 가져오기"
|
||||
export-targets:
|
||||
all-notes: "모든 글 데이터"
|
||||
following-list: "팔로잉"
|
||||
mute-list: "뮤트"
|
||||
blocking-list: "차단"
|
||||
user-lists: "리스트"
|
||||
export-requested: "내보내기를 요청하였습니다. 이 작업은 시간이 걸릴 수 있습니다. 내보내기가 완료되면 드라이브에 파일이 추가됩니다."
|
||||
import-requested: "가져오기를 요청하였습니다. 이 작업에는 시간이 걸릴 수 있습니다."
|
||||
enter-password: "비밀번호를 입력하여 주십시오"
|
||||
danger-zone: "위험한 설정"
|
||||
delete-account: "계정 삭제"
|
||||
@@ -646,6 +667,8 @@ common/views/components/user-list-editor.vue:
|
||||
remove-user: "이 리스트에서 제거"
|
||||
delete-are-you-sure: "리스트 \"$1\"을 삭제하시겠습니까?"
|
||||
deleted: "삭제하였습니다"
|
||||
common/views/components/user-lists.vue:
|
||||
list-name: "리스트 이름"
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "확인중"
|
||||
no-broadcasts: "공지사항이 없습니다"
|
||||
@@ -816,10 +839,6 @@ desktop/views/components/home.vue:
|
||||
desktop/views/input-dialog.vue:
|
||||
cancel: "취소"
|
||||
ok: "확인"
|
||||
desktop/views/components/messaging-room-window.vue:
|
||||
title: "메시지:"
|
||||
desktop/views/components/messaging-window.vue:
|
||||
title: "메시지"
|
||||
desktop/views/components/note-detail.vue:
|
||||
private: "이 글은 비공개입니다"
|
||||
deleted: "이 글은 삭제되었습니다"
|
||||
@@ -858,7 +877,6 @@ desktop/views/components/post-form.vue:
|
||||
posting: "게시중"
|
||||
attach-media-from-local: "PC에서 미디어 첨부"
|
||||
attach-media-from-drive: "드라이브에서 미디어 첨부"
|
||||
attach-cancel: "첨부 취소"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "투표 만들기"
|
||||
text-remain: "{}문자 남음"
|
||||
@@ -951,6 +969,10 @@ common/views/components/password-settings.vue:
|
||||
not-match: "새 비밀번호가 일치하지 않습니다"
|
||||
changed: "비밀번호를 변경하였습니다"
|
||||
failed: "비밀번호 변경을 실패하였습니다."
|
||||
common/views/components/post-form-attaches.vue:
|
||||
attach-cancel: "첨부 취소"
|
||||
mark-as-sensitive: "열람주의로 설정"
|
||||
unmark-as-sensitive: "열람주의 해제"
|
||||
desktop/views/components/sub-note-content.vue:
|
||||
private: "이 글은 비공개입니다"
|
||||
deleted: "이 글은 삭제되었습니다"
|
||||
@@ -961,15 +983,13 @@ desktop/views/components/settings.tags.vue:
|
||||
query: "쿼리 (생략 가능)"
|
||||
add: "추가"
|
||||
save: "저장"
|
||||
desktop/views/components/taskmanager.vue:
|
||||
title: "작업 관리자"
|
||||
desktop/views/components/timeline.vue:
|
||||
home: "홈"
|
||||
local: "로컬"
|
||||
hybrid: "소셜"
|
||||
global: "글로벌"
|
||||
mentions: "받은 멘션"
|
||||
messages: "메시지"
|
||||
messages: "다이렉트 게시글"
|
||||
list: "리스트"
|
||||
hashtag: "해시태그"
|
||||
add-tag-timeline: "해시태그 추가"
|
||||
@@ -997,8 +1017,6 @@ desktop/views/components/received-follow-requests-window.vue:
|
||||
reject: "거부"
|
||||
desktop/views/components/user-lists-window.vue:
|
||||
title: "리스트"
|
||||
create-list: "리스트 만들기"
|
||||
list-name: "리스트 이름"
|
||||
desktop/views/components/user-preview.vue:
|
||||
notes: "글"
|
||||
following: "팔로잉"
|
||||
@@ -1023,6 +1041,7 @@ admin/views/index.vue:
|
||||
hashtags: "해시태그"
|
||||
abuse: "스팸 신고"
|
||||
queue: "작업 대기열"
|
||||
logs: "로그"
|
||||
back-to-misskey: "Misskey로 돌아가기"
|
||||
admin/views/dashboard.vue:
|
||||
dashboard: "대시보드"
|
||||
@@ -1033,7 +1052,7 @@ admin/views/dashboard.vue:
|
||||
this-instance: "이 인스턴스"
|
||||
federated: "연합"
|
||||
admin/views/queue.vue:
|
||||
operation: "동작"
|
||||
title: "큐"
|
||||
remove-all-jobs: "모든 작업 제거"
|
||||
admin/views/abuse.vue:
|
||||
title: "스팸 신고"
|
||||
@@ -1089,15 +1108,12 @@ admin/views/instance.vue:
|
||||
disable-local-timeline: "로컬 타임라인 비활성화"
|
||||
disable-global-timeline: "글로벌 타임라인 비활성화"
|
||||
disabling-timelines-info: "이 타임라인들을 비활성화해도 관리자 및 모더레이터는 계속 사용할 수 있습니다."
|
||||
enable-emoji-reaction: "리액션에 이모지를 사용할 수 있게 함"
|
||||
use-star-for-reaction-fallback: "알 수 없는 리액션을 star로 대체하여 사용"
|
||||
invite: "초대"
|
||||
save: "저장"
|
||||
saved: "저장하였습니다"
|
||||
user-recommendation-config: "추천 사용자"
|
||||
enable-external-user-recommendation: "외부 사용자 추천 활성화"
|
||||
external-user-recommendation-engine: "엔진"
|
||||
external-user-recommendation-engine-desc: "예: https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}"
|
||||
external-user-recommendation-timeout: "타임 아웃"
|
||||
external-user-recommendation-timeout-desc: "밀리초 (예: 300000)"
|
||||
email-config: "메일 서버 설정"
|
||||
email-config-info: "메일 주소 확인 혹은 비밀번호 재설정에 사용 됩니다."
|
||||
enable-email: "메일 발신 활성화"
|
||||
@@ -1251,12 +1267,13 @@ admin/views/announcements.vue:
|
||||
admin/views/hashtags.vue:
|
||||
hided-tags: "Hidden Tags"
|
||||
admin/views/federation.vue:
|
||||
federation: "연합"
|
||||
instance: "인스턴스"
|
||||
host: "호스트"
|
||||
notes: "글"
|
||||
users: "사용자"
|
||||
following: "팔로우 중"
|
||||
followers: "팔로워"
|
||||
caught-at: "등록 날짜"
|
||||
status: "상태"
|
||||
latest-request-sent-at: "마지막으로 요청을 전송한 시간"
|
||||
latest-request-received-at: "마지막으로 요청을 받은 시간"
|
||||
@@ -1265,7 +1282,7 @@ admin/views/federation.vue:
|
||||
block: "차단"
|
||||
marked-as-closed: "폐쇄된 것으로 표시"
|
||||
lookup: "조회"
|
||||
instances: "인스턴스"
|
||||
instances: "연합"
|
||||
instance-not-registered: "해당 인스턴스가 등록되어 있지 않습니다"
|
||||
sort: "정렬"
|
||||
sorts:
|
||||
@@ -1328,8 +1345,6 @@ desktop/views/pages/selectdrive.vue:
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "검색 기능은 인스턴스 설정에서 비활성화되어 있습니다."
|
||||
not-found: "\"{q}\" 와 일치하는 글을 찾을 수 없습니다."
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "{name}(으)로 공유"
|
||||
desktop/views/pages/tag.vue:
|
||||
no-posts-found: "해시태그 \"{q}\"가 붙은 글을 찾을 수 없습니다."
|
||||
desktop/views/pages/user-list.users.vue:
|
||||
@@ -1364,8 +1379,6 @@ desktop/views/pages/user/user.timeline.vue:
|
||||
with-replies: "글과 답글"
|
||||
with-media: "미디어"
|
||||
my-posts: "내 글"
|
||||
desktop/views/widgets/messaging.vue:
|
||||
title: "메시지"
|
||||
desktop/views/widgets/notifications.vue:
|
||||
title: "알림"
|
||||
desktop/views/widgets/polls.vue:
|
||||
@@ -1393,8 +1406,6 @@ mobile/views/components/drive.vue:
|
||||
file-count: "파일"
|
||||
nothing-in-drive: "드라이브에 아무것도 없습니다"
|
||||
folder-is-empty: "폴더가 비어있습니다"
|
||||
prompt: "무엇을 하시겠습니까? (숫자를 입력하여 주십시오): <1 → 파일 업로드 | 2 → 파일을 URL에서 업로드 | 3 → 폴더 만들기 | 4 → 이 폴더의 이름을 변경 | 5 → 현재 폴더 이동| 6 → 현재 폴더 삭제>"
|
||||
deletion-alert: "죄송합니다! 폴더 삭제는 아직 구현되지 않았습니다..."
|
||||
folder-name: "폴더 이름"
|
||||
here-is-root: "현재 경로는 루트 경로로 폴더가 아닙니다."
|
||||
url-prompt: "업로드 하려는 파일의 URL"
|
||||
@@ -1451,7 +1462,7 @@ mobile/views/components/post-form.vue:
|
||||
quote-placeholder: "이 글을 인용... (선택적)"
|
||||
reply-placeholder: "이 글에 답글..."
|
||||
cw-placeholder: "내용 주석 (선택적)"
|
||||
location-alert: "사용하시는 장치가 위치정보 기능에 대응하지 않습니다"
|
||||
geolocation-alert: "사용하시는 장치가 위치정보 기능에 대응하지 않습니다"
|
||||
error: "오류"
|
||||
username-prompt: "사용자명을 입력하여 주십시오"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
@@ -1472,9 +1483,12 @@ mobile/views/components/ui.nav.vue:
|
||||
game: "게임"
|
||||
admin: "관리"
|
||||
about: "Misskey에 대하여"
|
||||
mobile/views/pages/drive.vue:
|
||||
contextmenu:
|
||||
upload: "파일 업로드"
|
||||
create-folder: "폴더 만들기"
|
||||
mobile/views/pages/user-lists.vue:
|
||||
title: "리스트"
|
||||
enter-list-name: "리스트명을 입력하십시오"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 이제 시작해도 됩니다"
|
||||
mobile/views/pages/followers.vue:
|
||||
@@ -1487,7 +1501,7 @@ mobile/views/pages/home.vue:
|
||||
hybrid: "소셜"
|
||||
global: "글로벌"
|
||||
mentions: "받은 멘션"
|
||||
messages: "메시지"
|
||||
messages: "다이렉트 게시글"
|
||||
mobile/views/pages/tag.vue:
|
||||
no-posts-found: "해시태그 \"{q}\"가 붙은 글을 찾을 수 없습니다."
|
||||
mobile/views/pages/widgets.vue:
|
||||
@@ -1604,21 +1618,9 @@ dev/views/new-app.vue:
|
||||
create-app: "어플리케이션 생성"
|
||||
app-name: "어플리케이션 이름"
|
||||
app-name-desc: "앱의 이름."
|
||||
app-name-ex: "ex) Misskey for iOS"
|
||||
app-overview: "앱 개요"
|
||||
app-desc: "어플리케이션에 대한 간단한 설명."
|
||||
app-desc-ex: "ex) Misskey iOS 클라이언트."
|
||||
callback-url: "콜백 URL (옵션)"
|
||||
callback-url-desc: "사용자가 인증 폼에서 인증한 뒤 리다이렉트할 URL을 설정합니다."
|
||||
authority: "권한"
|
||||
authority-desc: "이곳에서 요청한 권한에 한정하여 API로 액세스할 수 있습니다."
|
||||
authority-warning: "앱을 생성한 뒤에도 변경할 수 있지만, 새로운 권한을 설정하는 경우 그 시점부터 예전에 발급받았던 유저 키는 모두 무효화됩니다."
|
||||
account-read: "계정 정보 보기."
|
||||
account-write: "계정 정보 편집."
|
||||
note-write: "글 쓰기."
|
||||
reaction-write: "리액션을 하거나 리액션을 취소할 수 있음."
|
||||
following-write: "팔로우하거나 팔로우 해제하기."
|
||||
drive-read: "드라이브 보기."
|
||||
drive-write: "드라이브를 조작."
|
||||
notification-read: "알림 보기."
|
||||
notification-write: "알림 조작."
|
||||
|
1247
locales/nl-NL.yml
1247
locales/nl-NL.yml
File diff suppressed because it is too large
Load Diff
1292
locales/no-NO.yml
1292
locales/no-NO.yml
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1465
locales/pt-PT.yml
1465
locales/pt-PT.yml
File diff suppressed because it is too large
Load Diff
1500
locales/ru-RU.yml
1500
locales/ru-RU.yml
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
---
|
||||
meta:
|
||||
lang: "中文(简体)"
|
||||
divider: ""
|
||||
common:
|
||||
misskey: "Fediverse中的一颗⭐"
|
||||
about-title: "Fediverse中的一颗⭐"
|
||||
@@ -35,6 +34,7 @@ common:
|
||||
signup: "注册"
|
||||
signout: "退出"
|
||||
reload-to-apply-the-setting: "必须重新加载页面以应用此设置。 确实要立即重新加载吗?"
|
||||
fetching-as-ap-object: "联合查询"
|
||||
got-it: "知道了"
|
||||
customization-tips:
|
||||
title: "自定义提示"
|
||||
@@ -70,6 +70,27 @@ common:
|
||||
following: "正在关注"
|
||||
followers: "关注者"
|
||||
favorites: "最爱"
|
||||
permissions:
|
||||
"read:account": "查看账户信息"
|
||||
"write:account": "更改我的帐户信息"
|
||||
"read:blocks": "查看黑名单"
|
||||
"write:blocks": "编辑黑名单"
|
||||
"read:drive": "查看网盘"
|
||||
"write:drive": "管理网盘文件"
|
||||
"read:favorites": "查看收藏夹"
|
||||
"write:favorites": "编辑收藏夹"
|
||||
"read:following": "查看关注信息"
|
||||
"write:following": "关注/取消关注"
|
||||
"read:messaging": "查看对话"
|
||||
"write:messaging": "对话操作"
|
||||
"read:mutes": "查看屏蔽列表"
|
||||
"write:mutes": "编辑屏蔽列表"
|
||||
"write:notes": "创建或删除帖子"
|
||||
"read:notifications": "查看通知"
|
||||
"write:notifications": "管理通知"
|
||||
"read:reactions": "查看回应"
|
||||
"write:reactions": "回应操作"
|
||||
"write:votes": "投票"
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "关注其他用户时,帖子将显示在时间线中。"
|
||||
explore: "查找用户"
|
||||
@@ -125,7 +146,7 @@ common:
|
||||
apps: "应用程序"
|
||||
tags: "标签"
|
||||
mute-and-block: "屏蔽/拉黑"
|
||||
blocking: "屏蔽"
|
||||
blocking: "拉黑"
|
||||
security: "安全性"
|
||||
signin: "登录历史"
|
||||
password: "密码"
|
||||
@@ -142,7 +163,7 @@ common:
|
||||
keep-cw: "保留内容警告"
|
||||
keep-cw-desc: "在回复帖子时,如果原帖设置了内容警告,默认情况下回帖也会设置相同的内容警告。"
|
||||
i-like-sushi: "相比于布丁来说, 我更喜欢寿司。"
|
||||
show-reversi-board-labels: "在 Reversi 中显示行和列表签"
|
||||
show-reversi-board-labels: "在黑白棋中显示行和列表签"
|
||||
use-avatar-reversi-stones: "用头像作为黑白棋的棋子"
|
||||
disable-animated-mfm: "在帖子中禁用动画文本"
|
||||
disable-showing-animated-images: "不播放动画"
|
||||
@@ -185,9 +206,9 @@ common:
|
||||
show-clock-on-header: "在右上角显示时钟"
|
||||
show-reply-target: "显示回复目标"
|
||||
timeline: "时间线"
|
||||
show-my-renotes: "在时间线上显示我的Renote"
|
||||
show-renoted-my-notes: "在时间线上显示我的帖子的Renote"
|
||||
show-local-renotes: "在时间线上显示本地帖子的Renote"
|
||||
show-my-renotes: "在时间线上显示我的转推"
|
||||
show-renoted-my-notes: "在时间线上显示我的帖子的转推"
|
||||
show-local-renotes: "在时间线上显示本地帖子的转推"
|
||||
remain-deleted-note: "继续显示已删除的帖子"
|
||||
sound: "声音"
|
||||
enable-sounds: "开启声音"
|
||||
@@ -237,7 +258,7 @@ common:
|
||||
is-remote-user: "此用户信息可能不准确。"
|
||||
is-remote-post: "该投稿已被复制."
|
||||
view-on-remote: "查看准确的信息"
|
||||
renoted-by: "由 {user} Renote"
|
||||
renoted-by: "由 {user} 转推"
|
||||
no-notes: "没有帖子"
|
||||
turn-on-darkmode: "切换暗色主题"
|
||||
turn-off-darkmode: "切换亮色主题"
|
||||
@@ -277,21 +298,13 @@ common:
|
||||
nav: "导航"
|
||||
tips: "提示"
|
||||
hashtags: "标签"
|
||||
queue: "队列"
|
||||
dev: "构建应用程序失败,请再试一次。"
|
||||
ai-chan-kawaii: "小蓝真可爱"
|
||||
you: "您"
|
||||
auth/views/form.vue:
|
||||
share-access: "您要允许<i>{name}</i>来访问您的账户吗?"
|
||||
permission-ask: "这个应用程序需要以下权限:"
|
||||
account-read: "查看账户信息"
|
||||
account-write: "修改账户信息"
|
||||
note-write: "投稿。"
|
||||
like-write: "点赞或取消赞。"
|
||||
following-write: "关注或取消关注。"
|
||||
drive-read: "查看您的网盘"
|
||||
drive-write: "管理网盘文件。"
|
||||
notification-read: "查看通知。"
|
||||
notification-write: "管理通知。"
|
||||
cancel: "取消"
|
||||
accept: "允许访问。"
|
||||
auth/views/index.vue:
|
||||
@@ -315,6 +328,7 @@ common/views/pages/explore.vue:
|
||||
users-info: "当前有{users}个注册用户"
|
||||
common/views/components/url-preview.vue:
|
||||
enable-player: "打开播放器"
|
||||
disable-player: "关闭播放器"
|
||||
common/views/components/user-list.vue:
|
||||
no-users: "无用户"
|
||||
common/views/components/games/reversi/reversi.vue:
|
||||
@@ -325,8 +339,8 @@ common/views/components/games/reversi/reversi.game.vue:
|
||||
surrender: "认输"
|
||||
surrendered: "已认输"
|
||||
is-llotheo: "棋子较少一方获胜(LLoTheO规则)"
|
||||
looped-map: "环形棋盘"
|
||||
can-put-everywhere: "可以下在任意放置"
|
||||
looped-map: "循环棋盘"
|
||||
can-put-everywhere: "可以下在任意位置"
|
||||
common/views/components/games/reversi/reversi.index.vue:
|
||||
title: "Misskey 黑白棋"
|
||||
sub-title: "和其他人一起来玩Misskey黑白棋"
|
||||
@@ -350,8 +364,8 @@ common/views/components/games/reversi/reversi.room.vue:
|
||||
black-is: "{}是黑"
|
||||
rules: "规则"
|
||||
is-llotheo: "棋子较少一方获胜(LLoTheO规则)"
|
||||
looped-map: "环形棋盘"
|
||||
can-put-everywhere: "可以下在任意放置"
|
||||
looped-map: "循环棋盘"
|
||||
can-put-everywhere: "可以下在任意位置"
|
||||
settings-of-the-bot: "机器人设定"
|
||||
this-game-is-started-soon: "游戏即将在数秒后开始"
|
||||
waiting-for-other: "等待对手准备"
|
||||
@@ -467,8 +481,8 @@ common/views/components/note-menu.vue:
|
||||
unfavorite: "取消收藏"
|
||||
watch: "关注"
|
||||
unwatch: "取消关注"
|
||||
pin: "固定个人资料"
|
||||
unpin: "解除固定"
|
||||
pin: "置顶"
|
||||
unpin: "取消置顶"
|
||||
delete: "删除"
|
||||
delete-confirm: "确定删除这个投稿吗?"
|
||||
remote: "显示原始投稿"
|
||||
@@ -476,8 +490,12 @@ common/views/components/user-menu.vue:
|
||||
mention: "提到"
|
||||
mute: "屏蔽"
|
||||
unmute: "解除屏蔽"
|
||||
mute-confirm: "屏蔽此用户?"
|
||||
unmute-confirm: "取消屏蔽用户?"
|
||||
block: "拉黑"
|
||||
unblock: "取消拉黑"
|
||||
block-confirm: "确定拉黑此用户?"
|
||||
unblock-confirm: "取消拉黑此用户?"
|
||||
push-to-list: "添加至列表"
|
||||
select-list: "请选择一个列表"
|
||||
report-abuse: "举报骚扰"
|
||||
@@ -485,21 +503,44 @@ common/views/components/user-menu.vue:
|
||||
report-abuse-reported: "已报告给管理员。 非常感谢你的合作。"
|
||||
silence: "禁言"
|
||||
unsilence: "解除禁言"
|
||||
silence-confirm: "确认屏蔽此用户?"
|
||||
unsilence-confirm: "取消屏蔽此用户?"
|
||||
suspend: "冻结"
|
||||
unsuspend: "解除冻结"
|
||||
suspend-confirm: "确认冻结此用户?"
|
||||
unsuspend-confirm: "确认解冻此用户?"
|
||||
common/views/components/poll.vue:
|
||||
vote-to: "为\"{}\"投票"
|
||||
vote-count: "{}票"
|
||||
total-users: "{} 人投票"
|
||||
total-votes: "总票数{}"
|
||||
vote: "投票"
|
||||
show-result: "显示结果"
|
||||
voted: "已投票"
|
||||
closed: "已截止"
|
||||
remaining-days: "{d}天{h}小时后截止"
|
||||
remaining-hours: "{h}小时{m}分后截止"
|
||||
remaining-minutes: "{m}分{s}秒后截止"
|
||||
remaining-seconds: "{s}秒后截止"
|
||||
common/views/components/poll-editor.vue:
|
||||
no-only-one-choice: "至少选择两个选项"
|
||||
choice-n: "选择{}"
|
||||
remove: "删除选项"
|
||||
add: "+添加一个选项"
|
||||
destroy: "放弃投票"
|
||||
multiple: "允许多个投票"
|
||||
expiration: "截止时间"
|
||||
infinite: "永久"
|
||||
at: "指定日期"
|
||||
after: "指定时间"
|
||||
no-more: "最多只能添加十个回答"
|
||||
deadline-date: "日期"
|
||||
deadline-time: "时间"
|
||||
interval: "时长"
|
||||
unit: "单位"
|
||||
second: "秒"
|
||||
minute: "分"
|
||||
hour: "小时"
|
||||
day: "日"
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "选择回应"
|
||||
common/views/components/emoji-picker.vue:
|
||||
@@ -558,7 +599,7 @@ common/views/components/notification-settings.vue:
|
||||
mark-as-read-all-unread-notes: "将所有帖子标为已读"
|
||||
mark-as-read-all-talk-messages: "将所有对话标为已读"
|
||||
auto-watch: "自动查看帖子"
|
||||
auto-watch-desc: "自动接收有关您做出反应或回复的帖子的通知。"
|
||||
auto-watch-desc: "自动接收有关您做出回应或回复的帖子的通知。"
|
||||
common/views/components/integration-settings.vue:
|
||||
title: "服务合作"
|
||||
connect: "连接"
|
||||
@@ -629,12 +670,16 @@ common/views/components/profile-editor.vue:
|
||||
email-verified: "电子邮件地址已验证"
|
||||
email-not-verified: "邮件地址尚未验证。 请检查您的邮箱。"
|
||||
export: "导出"
|
||||
import: "导入"
|
||||
export-and-import: "导出/导入"
|
||||
export-targets:
|
||||
all-notes: "所有发帖"
|
||||
following-list: "关注列表"
|
||||
mute-list: "屏蔽列表"
|
||||
blocking-list: "黑名单"
|
||||
user-lists: "列表"
|
||||
export-requested: "导出请求已提交。可能需要花一些时间。导出的文件将保存到网盘中。"
|
||||
import-requested: "导入请求已提交。这可能需要花一点时间。"
|
||||
enter-password: "请输入您的密码"
|
||||
danger-zone: "危险选项"
|
||||
delete-account: "删除帐户"
|
||||
@@ -646,6 +691,9 @@ common/views/components/user-list-editor.vue:
|
||||
remove-user: "从此列表中删除"
|
||||
delete-are-you-sure: "删除列表“$1”?"
|
||||
deleted: "已删除"
|
||||
common/views/components/user-lists.vue:
|
||||
create-list: "创建列表"
|
||||
list-name: "列表名称"
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "确认中"
|
||||
no-broadcasts: "没有公告"
|
||||
@@ -688,7 +736,7 @@ common/views/widgets/tips.vue:
|
||||
tips-line8: "可以从设置中定制主页。"
|
||||
tips-line9: "Misskey 根据 AGPLv3 获得许可。"
|
||||
tips-line10: "使用Time Machine(时光机)小部件可以轻松追溯到过去的时间轴。"
|
||||
tips-line11: "您可以点击“...”将帖子固定到用户页面"
|
||||
tips-line11: "您可以点击“...”将帖子置顶到用户页面"
|
||||
tips-line13: "附在帖子上的所有文件都会保存到网盘中。"
|
||||
tips-line14: "在自定义首页布局时,您可以右键单击窗口小部件以更改其设计。"
|
||||
tips-line17: "用“**”围绕文本将突出显示它。"
|
||||
@@ -723,7 +771,7 @@ desktop/views/components/activity.chart.vue:
|
||||
total: "黑 ... 总计"
|
||||
notes: "蓝 ... 投稿"
|
||||
replies: "红 ... 回复"
|
||||
renotes: "绿 ... 转发"
|
||||
renotes: "绿 ... 转推"
|
||||
desktop/views/components/activity.vue:
|
||||
title: "活动"
|
||||
toggle: "切换显示"
|
||||
@@ -816,22 +864,18 @@ desktop/views/components/home.vue:
|
||||
desktop/views/input-dialog.vue:
|
||||
cancel: "取消"
|
||||
ok: "确定"
|
||||
desktop/views/components/messaging-room-window.vue:
|
||||
title: "信息:"
|
||||
desktop/views/components/messaging-window.vue:
|
||||
title: "正在聊天"
|
||||
desktop/views/components/note-detail.vue:
|
||||
private: "私密投稿"
|
||||
deleted: "投稿已删除"
|
||||
location: "位置信息"
|
||||
renote: "转发"
|
||||
add-reaction: "添加一个反应"
|
||||
undo-reaction: "取消反应"
|
||||
renote: "转推"
|
||||
add-reaction: "回应"
|
||||
undo-reaction: "取消回应"
|
||||
desktop/views/components/note.vue:
|
||||
reply: "回复"
|
||||
renote: "Renote"
|
||||
add-reaction: "添加一个反应"
|
||||
undo-reaction: "取消反应"
|
||||
renote: "转推"
|
||||
add-reaction: "回应"
|
||||
undo-reaction: "取消回应"
|
||||
detail: "详细信息"
|
||||
private: "这个投稿是私密的"
|
||||
deleted: "投稿已删除"
|
||||
@@ -848,17 +892,16 @@ desktop/views/components/post-form.vue:
|
||||
quote-placeholder: "引用这个帖子…"
|
||||
submit: "投稿"
|
||||
reply: "回复"
|
||||
renote: "转发"
|
||||
renote: "转推"
|
||||
posted: "已发送投稿!"
|
||||
replied: "已回复!"
|
||||
reposted: "已转发!"
|
||||
reposted: "已转推!"
|
||||
note-failed: "发帖失败"
|
||||
reply-failed: "回复失败"
|
||||
renote-failed: "转发失败"
|
||||
renote-failed: "转推失败"
|
||||
posting: "发送中"
|
||||
attach-media-from-local: "从设备中添加媒体文件"
|
||||
attach-media-from-drive: "从网盘中添加媒体文件"
|
||||
attach-cancel: "删除附件"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "创建一个投票"
|
||||
text-remain: "还剩{}字"
|
||||
@@ -880,13 +923,13 @@ desktop/views/components/progress-dialog.vue:
|
||||
desktop/views/components/renote-form.vue:
|
||||
quote: "引用..."
|
||||
cancel: "取消"
|
||||
renote: "重新发送"
|
||||
renote-home: "重新发送(首页)"
|
||||
renote: "转推"
|
||||
renote-home: "转推(首页)"
|
||||
reposting: "重新发送中..."
|
||||
success: "已重新发送!"
|
||||
failure: "重新发送失败"
|
||||
success: "已转推!"
|
||||
failure: "转推失败"
|
||||
desktop/views/components/renote-form-window.vue:
|
||||
title: "您是否要重新发送?"
|
||||
title: "您是否要转推?"
|
||||
desktop/views/pages/user-following-or-followers.vue:
|
||||
following: "{user}的正在关注"
|
||||
followers: "{user}的关注者"
|
||||
@@ -936,7 +979,7 @@ common/views/components/drive-settings.vue:
|
||||
common/views/components/mute-and-block.vue:
|
||||
mute-and-block: "屏蔽/拉黑"
|
||||
mute: "屏蔽"
|
||||
block: "拉黑中"
|
||||
block: "拉黑"
|
||||
no-muted-users: "无屏蔽用户"
|
||||
no-blocked-users: "无拉黑的用户"
|
||||
word-mute: "文字屏蔽"
|
||||
@@ -951,6 +994,10 @@ common/views/components/password-settings.vue:
|
||||
not-match: "新密码不匹配"
|
||||
changed: "密码已更改"
|
||||
failed: "更改密码失败"
|
||||
common/views/components/post-form-attaches.vue:
|
||||
attach-cancel: "删除附件"
|
||||
mark-as-sensitive: "标记为“敏感”"
|
||||
unmark-as-sensitive: "取消标记为“敏感”"
|
||||
desktop/views/components/sub-note-content.vue:
|
||||
private: "这个帖子是私密的"
|
||||
deleted: "帖子已删除"
|
||||
@@ -961,15 +1008,13 @@ desktop/views/components/settings.tags.vue:
|
||||
query: "查询 (可选)"
|
||||
add: "添加"
|
||||
save: "保存"
|
||||
desktop/views/components/taskmanager.vue:
|
||||
title: "任务管理器"
|
||||
desktop/views/components/timeline.vue:
|
||||
home: "首页"
|
||||
local: "本地"
|
||||
hybrid: "社交"
|
||||
global: "全球"
|
||||
mentions: "提到的"
|
||||
messages: "信息"
|
||||
messages: "直接发布"
|
||||
list: "列表"
|
||||
hashtag: "标签"
|
||||
add-tag-timeline: "添加标签"
|
||||
@@ -997,8 +1042,6 @@ desktop/views/components/received-follow-requests-window.vue:
|
||||
reject: "拒绝"
|
||||
desktop/views/components/user-lists-window.vue:
|
||||
title: "用户列表"
|
||||
create-list: "创建列表"
|
||||
list-name: "列表名称"
|
||||
desktop/views/components/user-preview.vue:
|
||||
notes: "帖子"
|
||||
following: "关注中"
|
||||
@@ -1023,6 +1066,7 @@ admin/views/index.vue:
|
||||
hashtags: "标签"
|
||||
abuse: "举报垃圾信息"
|
||||
queue: "作业队列"
|
||||
logs: "登录"
|
||||
back-to-misskey: "返回 Misskey"
|
||||
admin/views/dashboard.vue:
|
||||
dashboard: "Dashboard"
|
||||
@@ -1033,7 +1077,7 @@ admin/views/dashboard.vue:
|
||||
this-instance: "此实例"
|
||||
federated: "联合"
|
||||
admin/views/queue.vue:
|
||||
operation: "操作"
|
||||
title: "队列"
|
||||
remove-all-jobs: "清除所有作业"
|
||||
admin/views/abuse.vue:
|
||||
title: "举报垃圾信息"
|
||||
@@ -1089,15 +1133,12 @@ admin/views/instance.vue:
|
||||
disable-local-timeline: "停用本地时间线功能"
|
||||
disable-global-timeline: "禁用全局时间线"
|
||||
disabling-timelines-info: "即使禁用时间线,管理员和版主仍然可用。"
|
||||
enable-emoji-reaction: "在回应上使用表情符号"
|
||||
use-star-for-reaction-fallback: "使用默认的star来表示未知的回应"
|
||||
invite: "邀请"
|
||||
save: "保存"
|
||||
saved: "保存完毕"
|
||||
user-recommendation-config: "推荐用户"
|
||||
enable-external-user-recommendation: "启用外部用户推荐"
|
||||
external-user-recommendation-engine: "引擎"
|
||||
external-user-recommendation-engine-desc: "例如: https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}"
|
||||
external-user-recommendation-timeout: "超时"
|
||||
external-user-recommendation-timeout-desc: "单位为毫秒 (例如:300000)"
|
||||
email-config: "电子邮件服务器设置"
|
||||
email-config-info: "用于确认电子邮件和密码重置等。"
|
||||
enable-email: "启用电子邮件送递"
|
||||
@@ -1178,7 +1219,9 @@ admin/views/users.vue:
|
||||
unsuspend-confirm: "是否解除冻结?"
|
||||
unsuspended: "已成功解除用户冻结"
|
||||
make-silence: "禁言"
|
||||
silence-confirm: "确认屏蔽?"
|
||||
unmake-silence: "解除禁言"
|
||||
unsilence-confirm: "解除屏蔽?"
|
||||
verify: "认证用户"
|
||||
verify-confirm: "是否官方账号?"
|
||||
verified: "此账户已被认证"
|
||||
@@ -1251,12 +1294,13 @@ admin/views/announcements.vue:
|
||||
admin/views/hashtags.vue:
|
||||
hided-tags: "隐藏标签"
|
||||
admin/views/federation.vue:
|
||||
federation: "联合"
|
||||
instance: "例"
|
||||
host: "主机名"
|
||||
notes: "帖子"
|
||||
users: "用户"
|
||||
following: "正在关注"
|
||||
followers: "关注者"
|
||||
caught-at: "注册日期"
|
||||
status: "状态"
|
||||
latest-request-sent-at: "上次发送的请求"
|
||||
latest-request-received-at: "上次收到的请求"
|
||||
@@ -1265,7 +1309,7 @@ admin/views/federation.vue:
|
||||
block: "拉黑"
|
||||
marked-as-closed: "标记为已关闭"
|
||||
lookup: "查询"
|
||||
instances: "实例"
|
||||
instances: "联合"
|
||||
instance-not-registered: "实例未注册"
|
||||
sort: "排序"
|
||||
sorts:
|
||||
@@ -1328,8 +1372,6 @@ desktop/views/pages/selectdrive.vue:
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "在此实例的设置中关闭搜索功能。"
|
||||
not-found: "没有找到“{q}”的帖子"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "共享{name}"
|
||||
desktop/views/pages/tag.vue:
|
||||
no-posts-found: "没有找到带有主题标签“{q}”的帖子"
|
||||
desktop/views/pages/user-list.users.vue:
|
||||
@@ -1364,8 +1406,6 @@ desktop/views/pages/user/user.timeline.vue:
|
||||
with-replies: "帖子与回复"
|
||||
with-media: "媒体"
|
||||
my-posts: "我的帖子"
|
||||
desktop/views/widgets/messaging.vue:
|
||||
title: "信息"
|
||||
desktop/views/widgets/notifications.vue:
|
||||
title: "通知"
|
||||
desktop/views/widgets/polls.vue:
|
||||
@@ -1375,6 +1415,7 @@ desktop/views/widgets/polls.vue:
|
||||
desktop/views/widgets/post-form.vue:
|
||||
title: "帖子"
|
||||
note: "帖子"
|
||||
something-happened: "由于某种原因无法发帖。"
|
||||
desktop/views/widgets/profile.vue:
|
||||
update-banner: "点击来剪辑背景"
|
||||
update-avatar: "点击来剪辑头像"
|
||||
@@ -1393,12 +1434,11 @@ mobile/views/components/drive.vue:
|
||||
file-count: "文件"
|
||||
nothing-in-drive: "网盘为空"
|
||||
folder-is-empty: "这文件夹是空的"
|
||||
prompt: "您想要干什么呢?(请输入数字):<1 → 上传文件 | 2 → 从URL上传文件 | 3 → 创建新文件夹 | 4 → 更改这个文件夹的名称 | 5 → 移动这个文件夹 | 6 → 删除这个文件夹>"
|
||||
deletion-alert: "抱歉! 删除文件夹功能尚未实现。"
|
||||
folder-name: "文件夹名称"
|
||||
here-is-root: "当前位置为根目录。"
|
||||
url-prompt: "要上传的文件的URL"
|
||||
uploading: "已请求上传。 上传完成可能需要一段时间。"
|
||||
folder-name-cannot-empty: "文件夹名不能为空。"
|
||||
mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "选择文件"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
@@ -1429,7 +1469,7 @@ mobile/views/components/note.vue:
|
||||
location: "位置信息"
|
||||
mobile/views/components/note-detail.vue:
|
||||
reply: "回复"
|
||||
reaction: "反应"
|
||||
reaction: "回应"
|
||||
private: "这个帖子是私密的"
|
||||
deleted: "帖子已删除"
|
||||
location: "位置信息"
|
||||
@@ -1447,11 +1487,11 @@ mobile/views/components/post-form.vue:
|
||||
add-visible-user: "添加用户"
|
||||
submit: "帖子"
|
||||
reply: "回复"
|
||||
renote: "Renote"
|
||||
renote: "转推"
|
||||
quote-placeholder: "引用这个帖子t... (可选)"
|
||||
reply-placeholder: "回复这个帖子"
|
||||
cw-placeholder: "评论帖子(可选)"
|
||||
location-alert: "您的设备不提供定位服务"
|
||||
geolocation-alert: "您的设备不提供位置服务"
|
||||
error: "错误"
|
||||
username-prompt: "请输入用户名"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
@@ -1472,9 +1512,16 @@ mobile/views/components/ui.nav.vue:
|
||||
game: "游戏"
|
||||
admin: "管理"
|
||||
about: "关于 Misskey"
|
||||
mobile/views/pages/drive.vue:
|
||||
contextmenu:
|
||||
upload: "上传文件"
|
||||
url-upload: "从URL上传文件"
|
||||
create-folder: "创建文件夹"
|
||||
rename-folder: "重命名文件夹"
|
||||
move-folder: "移动此文件夹"
|
||||
delete-folder: "删除此文件夹"
|
||||
mobile/views/pages/user-lists.vue:
|
||||
title: "列表"
|
||||
enter-list-name: "输入要列出的列表的名称"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "您的账户现已准备就绪! 📦"
|
||||
mobile/views/pages/followers.vue:
|
||||
@@ -1484,10 +1531,10 @@ mobile/views/pages/following.vue:
|
||||
mobile/views/pages/home.vue:
|
||||
home: "首页"
|
||||
local: "Local"
|
||||
hybrid: "Social"
|
||||
hybrid: "社交"
|
||||
global: "Global"
|
||||
mentions: "Mentions"
|
||||
messages: "信息"
|
||||
messages: "直接发布"
|
||||
mobile/views/pages/tag.vue:
|
||||
no-posts-found: "没有找到带有主题标签“{q}”的帖子"
|
||||
mobile/views/pages/widgets.vue:
|
||||
@@ -1540,7 +1587,7 @@ deck:
|
||||
widgets: "小部件"
|
||||
home: "首页"
|
||||
local: "Local"
|
||||
hybrid: "Social"
|
||||
hybrid: "社交"
|
||||
hashtag: "标签"
|
||||
global: "Global"
|
||||
mentions: "Mentions"
|
||||
@@ -1571,7 +1618,7 @@ deck/deck.user-column.vue:
|
||||
images: "图片"
|
||||
activity: "活动"
|
||||
timeline: "时间线"
|
||||
pinned-notes: "标记投稿"
|
||||
pinned-notes: "置顶帖"
|
||||
docs:
|
||||
edit-this-page-on-github: "发现错误或想要为文档做出贡献?"
|
||||
edit-this-page-on-github-link: "在GitHub上编辑这个页面。"
|
||||
@@ -1601,24 +1648,18 @@ dev/views/apps.vue:
|
||||
create-app: "创建应用"
|
||||
app-missing: "没有应用"
|
||||
dev/views/new-app.vue:
|
||||
new-app: "新应用"
|
||||
new-app-info: "可以从 API 中创建应用。 (app/create)"
|
||||
create-app: "正在创建应用"
|
||||
app-name: "应用名称"
|
||||
app-name-placeholder: "ex) iOS版Misskey"
|
||||
app-name-desc: "您应用的名称"
|
||||
app-name-ex: "ex) iOS版本的Misskey"
|
||||
app-overview: "应用摘要"
|
||||
app-desc: "您的应用的简要说明或介绍。"
|
||||
app-desc-ex: "ex) iOS版Misskey客户端."
|
||||
app-overview-placeholder: " ex) iOS版Misskey客户端."
|
||||
app-overview-desc: "您的应用的简要说明或介绍。"
|
||||
callback-url: "回应URL (optional)"
|
||||
callback-url-placeholder: "ex) https://your.app.example.com/callback.php"
|
||||
callback-url-desc: "通过身份验证表单对用户进行身份验证后重定向到的URL。"
|
||||
authority: "权限"
|
||||
authority-desc: "只能通过API访问此处请求的功能。"
|
||||
authority-warning: "您可以在创建应用程序后对其进行更改,但如果您授予不同的权限,则当时关联的所有用户密钥都将失效。"
|
||||
account-read: "查看账户信息"
|
||||
account-write: "修改账户信息"
|
||||
note-write: "投稿。"
|
||||
reaction-write: "添加或删除反应。"
|
||||
following-write: "关注和不关注"
|
||||
drive-read: "查看网盘"
|
||||
drive-write: "管理网盘文件。"
|
||||
notification-read: "阅读您的通知"
|
||||
notification-write: "管理通知"
|
||||
|
88
locales/zh-TW.yml
Normal file
88
locales/zh-TW.yml
Normal file
@@ -0,0 +1,88 @@
|
||||
---
|
||||
meta:
|
||||
lang: "中文(繁体)"
|
||||
common:
|
||||
intro:
|
||||
title: "什麽是 Misskey 呢?"
|
||||
rich-contents: "發佈"
|
||||
reaction: "回應"
|
||||
drive: "雲端硬碟"
|
||||
adblock:
|
||||
detected: "請禁用廣告封鎖器"
|
||||
close: "關閉"
|
||||
enter-password: "請輸入密碼"
|
||||
2fa: "雙重身份驗證"
|
||||
dark-mode: "夜間模式"
|
||||
signup: "註冊"
|
||||
signout: "登出"
|
||||
notification:
|
||||
reversi-invited: "您已被邀請加入壹場遊戲"
|
||||
reversi-invited-by: "來自{}的邀請"
|
||||
notified-by: "來自{}的邀請"
|
||||
time:
|
||||
future: "未來"
|
||||
just_now: "剛剛"
|
||||
drive: "雲端硬碟"
|
||||
weekday:
|
||||
sunday: "週日"
|
||||
monday: "週一"
|
||||
tuesday: "週二"
|
||||
wednesday: "週三"
|
||||
thursday: "週四"
|
||||
friday: "週五"
|
||||
saturday: "週六"
|
||||
reactions:
|
||||
like: "贊"
|
||||
love: "喜歡"
|
||||
congrats: "恭喜"
|
||||
_settings:
|
||||
password: "密碼"
|
||||
font-size: "字體大小"
|
||||
font-size-x-small: "小"
|
||||
font-size-small: "較小"
|
||||
deck-column-width-wide: "寬"
|
||||
timeline: "時間軸"
|
||||
common/views/components/connect-failed.troubleshooter.vue:
|
||||
flush: "清除快取"
|
||||
common/views/components/theme.vue:
|
||||
light-themes: "淺色主題"
|
||||
dark-themes: "深色主題"
|
||||
install-a-theme: "安裝主題"
|
||||
save-created-theme: "保存主題"
|
||||
common/views/components/signin.vue:
|
||||
signin-with-twitter: "用 Twitter 帳號登入"
|
||||
signin-with-github: "用 GitHub 帳號登入"
|
||||
signin-with-discord: "用 Discord 帳號登入"
|
||||
login-failed: "登錄失敗。 請檢查用戶名和密碼。"
|
||||
common/views/components/signup.vue:
|
||||
invitation-code: "邀請碼"
|
||||
username: "用戶名"
|
||||
available: "可用"
|
||||
too-long: "請不要超過20個字元"
|
||||
password: "密碼"
|
||||
password-placeholder: "建議至少8個字元"
|
||||
common/views/components/stream-indicator.vue:
|
||||
connecting: "正在連線"
|
||||
reconnecting: "正在重新連線"
|
||||
connected: "已建立連線"
|
||||
common/views/components/integration-settings.vue:
|
||||
disconnect: "中斷連線"
|
||||
common/views/components/github-setting.vue:
|
||||
reconnect: "重新連線"
|
||||
disconnect: "中斷連線"
|
||||
common/views/components/discord-setting.vue:
|
||||
reconnect: "重新連線"
|
||||
disconnect: "中斷連線"
|
||||
common/views/components/language-settings.vue:
|
||||
recommended: "推薦"
|
||||
auto: "自動"
|
||||
specify-language: "指定語言"
|
||||
common/views/components/profile-editor.vue:
|
||||
title: "個人資料"
|
||||
name: "名稱"
|
||||
birthday: "生日:"
|
||||
privacy: "隱私"
|
||||
admin/views/dashboard.vue:
|
||||
drive: "雲端硬碟"
|
||||
admin/views/charts.vue:
|
||||
drive: "雲端硬碟"
|
162
package.json
162
package.json
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <i@syuilo.com>",
|
||||
"version": "10.91.0",
|
||||
"codename": "nighthike",
|
||||
"version": "11.4.0",
|
||||
"codename": "daybreak",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/syuilo/misskey.git"
|
||||
@@ -11,7 +11,7 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node ./index.js",
|
||||
"debug": "DEBUG=misskey:* node ./index.js",
|
||||
"init": "node ./built/init.js",
|
||||
"build": "webpack && gulp build",
|
||||
"webpack": "webpack",
|
||||
"watch": "webpack --watch",
|
||||
@@ -23,106 +23,102 @@
|
||||
"format": "gulp format"
|
||||
},
|
||||
"dependencies": {
|
||||
"@elastic/elasticsearch": "7.0.0-rc.2",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.15",
|
||||
"@fortawesome/free-brands-svg-icons": "5.7.2",
|
||||
"@fortawesome/free-regular-svg-icons": "5.7.2",
|
||||
"@fortawesome/free-solid-svg-icons": "5.7.2",
|
||||
"@fortawesome/vue-fontawesome": "0.1.5",
|
||||
"@koa/cors": "2.2.3",
|
||||
"@prezzemolo/rap": "0.1.2",
|
||||
"@prezzemolo/zip": "0.0.3",
|
||||
"@types/bcryptjs": "2.4.2",
|
||||
"@types/chai-http": "3.0.5",
|
||||
"@types/bull": "3.5.11",
|
||||
"@types/dateformat": "3.0.0",
|
||||
"@types/deep-equal": "1.0.1",
|
||||
"@types/double-ended-queue": "2.1.0",
|
||||
"@types/elasticsearch": "5.0.30",
|
||||
"@types/file-type": "10.6.0",
|
||||
"@types/gulp": "4.0.5",
|
||||
"@types/file-type": "10.9.1",
|
||||
"@types/gulp": "4.0.6",
|
||||
"@types/gulp-mocha": "0.0.32",
|
||||
"@types/gulp-rename": "0.0.33",
|
||||
"@types/gulp-replace": "0.0.31",
|
||||
"@types/gulp-uglify": "3.0.6",
|
||||
"@types/gulp-util": "3.0.34",
|
||||
"@types/is-root": "1.0.0",
|
||||
"@types/is-svg": "3.0.0",
|
||||
"@types/is-url": "1.2.28",
|
||||
"@types/js-yaml": "3.12.0",
|
||||
"@types/js-yaml": "3.12.1",
|
||||
"@types/jsdom": "12.2.3",
|
||||
"@types/katex": "0.10.1",
|
||||
"@types/koa": "2.0.48",
|
||||
"@types/koa-bodyparser": "5.0.2",
|
||||
"@types/koa-compress": "2.0.8",
|
||||
"@types/koa-compress": "2.0.9",
|
||||
"@types/koa-cors": "0.0.0",
|
||||
"@types/koa-favicon": "2.0.19",
|
||||
"@types/koa-logger": "3.1.1",
|
||||
"@types/koa-mount": "3.0.1",
|
||||
"@types/koa-multer": "1.0.0",
|
||||
"@types/koa-router": "7.0.39",
|
||||
"@types/koa-send": "4.1.1",
|
||||
"@types/koa-router": "7.0.40",
|
||||
"@types/koa-send": "4.1.2",
|
||||
"@types/koa-views": "2.0.3",
|
||||
"@types/koa__cors": "2.2.3",
|
||||
"@types/lolex": "3.1.1",
|
||||
"@types/minio": "7.0.1",
|
||||
"@types/mkdirp": "0.5.2",
|
||||
"@types/mocha": "5.2.5",
|
||||
"@types/mongodb": "3.1.20",
|
||||
"@types/node": "10.12.24",
|
||||
"@types/nodemailer": "4.6.6",
|
||||
"@types/mocha": "5.2.6",
|
||||
"@types/node": "11.13.4",
|
||||
"@types/nodemailer": "4.6.7",
|
||||
"@types/nprogress": "0.0.29",
|
||||
"@types/oauth": "0.9.1",
|
||||
"@types/parse5": "5.0.0",
|
||||
"@types/parsimmon": "1.10.0",
|
||||
"@types/portscanner": "2.1.0",
|
||||
"@types/pug": "2.0.4",
|
||||
"@types/qrcode": "1.3.0",
|
||||
"@types/qrcode": "1.3.2",
|
||||
"@types/random-seed": "0.3.3",
|
||||
"@types/ratelimiter": "2.1.28",
|
||||
"@types/redis": "2.8.10",
|
||||
"@types/redis": "2.8.12",
|
||||
"@types/rename": "1.0.1",
|
||||
"@types/request": "2.48.1",
|
||||
"@types/request-promise-native": "1.0.15",
|
||||
"@types/request-stats": "3.0.0",
|
||||
"@types/rimraf": "2.0.2",
|
||||
"@types/seedrandom": "2.4.27",
|
||||
"@types/sharp": "0.21.2",
|
||||
"@types/sharp": "0.22.1",
|
||||
"@types/showdown": "1.9.2",
|
||||
"@types/speakeasy": "2.0.3",
|
||||
"@types/speakeasy": "2.0.4",
|
||||
"@types/systeminformation": "3.23.1",
|
||||
"@types/tinycolor2": "1.4.1",
|
||||
"@types/tmp": "0.0.33",
|
||||
"@types/tmp": "0.1.0",
|
||||
"@types/uuid": "3.4.4",
|
||||
"@types/web-push": "3.3.0",
|
||||
"@types/webpack": "4.4.24",
|
||||
"@types/webpack": "4.4.27",
|
||||
"@types/webpack-stream": "3.2.10",
|
||||
"@types/websocket": "0.0.40",
|
||||
"@types/ws": "6.0.1",
|
||||
"animejs": "3.0.1",
|
||||
"apexcharts": "3.5.0",
|
||||
"apexcharts": "3.6.8",
|
||||
"autobind-decorator": "2.4.0",
|
||||
"autosize": "4.0.2",
|
||||
"autwh": "0.1.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"bee-queue": "1.2.2",
|
||||
"bootstrap-vue": "2.0.0-rc.11",
|
||||
"cafy": "15.1.0",
|
||||
"bootstrap-vue": "2.0.0-rc.13",
|
||||
"bull": "3.7.0",
|
||||
"cafy": "15.1.1",
|
||||
"chai": "4.2.0",
|
||||
"chai-http": "4.2.1",
|
||||
"chalk": "2.4.2",
|
||||
"commander": "2.19.0",
|
||||
"cli-highlight": "2.1.0",
|
||||
"commander": "2.20.0",
|
||||
"content-disposition": "0.5.3",
|
||||
"crc-32": "1.2.0",
|
||||
"css-loader": "2.1.0",
|
||||
"css-loader": "2.1.1",
|
||||
"cssnano": "4.1.10",
|
||||
"dateformat": "3.0.3",
|
||||
"deep-equal": "1.0.1",
|
||||
"deepcopy": "0.6.3",
|
||||
"diskusage": "1.0.0",
|
||||
"diskusage": "1.1.0",
|
||||
"double-ended-queue": "2.1.0-0",
|
||||
"elasticsearch": "15.3.1",
|
||||
"emojilib": "2.4.0",
|
||||
"escape-regexp": "0.0.1",
|
||||
"eslint": "5.12.0",
|
||||
"eslint": "5.16.0",
|
||||
"eslint-plugin-vue": "5.2.2",
|
||||
"eventemitter3": "3.1.0",
|
||||
"feed": "2.0.2",
|
||||
"file-type": "10.7.1",
|
||||
"feed": "2.0.4",
|
||||
"file-type": "10.11.0",
|
||||
"fuckadblock": "3.2.1",
|
||||
"gulp": "4.0.0",
|
||||
"gulp-cssnano": "2.1.3",
|
||||
@@ -130,23 +126,22 @@
|
||||
"gulp-mocha": "6.0.0",
|
||||
"gulp-rename": "1.4.0",
|
||||
"gulp-replace": "1.0.0",
|
||||
"gulp-sourcemaps": "2.6.4",
|
||||
"gulp-sourcemaps": "2.6.5",
|
||||
"gulp-stylus": "2.7.0",
|
||||
"gulp-tslint": "8.1.3",
|
||||
"gulp-typescript": "5.0.0",
|
||||
"gulp-uglify": "3.0.1",
|
||||
"gulp-tslint": "8.1.4",
|
||||
"gulp-typescript": "5.0.1",
|
||||
"gulp-uglify": "3.0.2",
|
||||
"gulp-util": "3.0.8",
|
||||
"gulp-yaml": "2.0.3",
|
||||
"hard-source-webpack-plugin": "0.13.1",
|
||||
"html-minifier": "3.5.21",
|
||||
"html-minifier": "4.0.0",
|
||||
"http-signature": "1.2.0",
|
||||
"insert-text-at-cursor": "0.1.2",
|
||||
"is-root": "2.0.0",
|
||||
"is-svg": "3.0.0",
|
||||
"js-yaml": "3.12.1",
|
||||
"jsdom": "13.2.0",
|
||||
"insert-text-at-cursor": "0.2.0",
|
||||
"is-root": "2.1.0",
|
||||
"is-svg": "4.1.0",
|
||||
"js-yaml": "3.13.1",
|
||||
"jsdom": "14.1.0",
|
||||
"json5": "2.1.0",
|
||||
"json5-loader": "1.0.1",
|
||||
"json5-loader": "2.0.0",
|
||||
"katex": "0.10.1",
|
||||
"koa": "2.7.0",
|
||||
"koa-bodyparser": "4.2.1",
|
||||
@@ -159,50 +154,52 @@
|
||||
"koa-router": "7.4.0",
|
||||
"koa-send": "5.0.0",
|
||||
"koa-slow": "2.1.0",
|
||||
"koa-views": "6.1.5",
|
||||
"koa-views": "6.2.0",
|
||||
"langmap": "0.0.16",
|
||||
"loader-utils": "1.2.3",
|
||||
"lolex": "3.1.0",
|
||||
"lookup-dns-cache": "2.1.0",
|
||||
"minio": "7.0.5",
|
||||
"mkdirp": "0.5.1",
|
||||
"mocha": "5.2.0",
|
||||
"minio": "7.0.6",
|
||||
"mocha": "6.1.3",
|
||||
"moji": "0.5.1",
|
||||
"moment": "2.24.0",
|
||||
"mongodb": "3.1.13",
|
||||
"monk": "6.0.6",
|
||||
"ms": "2.1.1",
|
||||
"nan": "2.12.1",
|
||||
"nested-property": "0.0.7",
|
||||
"nodemailer": "5.1.1",
|
||||
"node-fetch": "2.3.0",
|
||||
"nodemailer": "6.1.1",
|
||||
"nprogress": "0.2.0",
|
||||
"object-assign-deep": "0.4.0",
|
||||
"on-build-webpack": "0.1.0",
|
||||
"os-utils": "0.0.14",
|
||||
"parse5": "5.1.0",
|
||||
"parsimmon": "1.12.0",
|
||||
"pg": "7.10.0",
|
||||
"portscanner": "2.2.0",
|
||||
"postcss-loader": "3.0.0",
|
||||
"prismjs": "1.15.0",
|
||||
"prismjs": "1.16.0",
|
||||
"progress-bar-webpack-plugin": "1.12.1",
|
||||
"promise-any": "0.2.0",
|
||||
"promise-limit": "2.7.0",
|
||||
"promise-sequential": "1.1.1",
|
||||
"pug": "2.0.3",
|
||||
"punycode": "2.1.1",
|
||||
"pureimage": "0.1.6",
|
||||
"qrcode": "1.3.3",
|
||||
"randomcolor": "0.5.3",
|
||||
"ratelimiter": "3.2.0",
|
||||
"random-seed": "0.3.0",
|
||||
"randomcolor": "0.5.4",
|
||||
"ratelimiter": "3.3.0",
|
||||
"recaptcha-promise": "0.1.3",
|
||||
"reconnecting-websocket": "4.1.10",
|
||||
"redis": "2.8.0",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"rename": "1.0.4",
|
||||
"request": "2.88.0",
|
||||
"request-promise-native": "1.0.5",
|
||||
"request-promise-native": "1.0.7",
|
||||
"request-stats": "3.0.0",
|
||||
"require-all": "3.0.0",
|
||||
"rimraf": "2.6.3",
|
||||
"rndstr": "1.0.0",
|
||||
"s-age": "1.1.2",
|
||||
"seedrandom": "2.4.4",
|
||||
"sharp": "0.21.3",
|
||||
"sharp": "0.22.0",
|
||||
"showdown": "1.9.0",
|
||||
"showdown-highlightjs-extension": "0.1.2",
|
||||
"speakeasy": "2.0.0",
|
||||
@@ -211,47 +208,50 @@
|
||||
"stylus": "0.54.5",
|
||||
"stylus-loader": "3.0.2",
|
||||
"summaly": "2.2.0",
|
||||
"systeminformation": "4.0.14",
|
||||
"systeminformation": "4.1.5",
|
||||
"syuilo-password-strength": "0.0.1",
|
||||
"terser-webpack-plugin": "1.2.3",
|
||||
"textarea-caret": "3.1.0",
|
||||
"tinycolor2": "1.4.1",
|
||||
"tmp": "0.0.33",
|
||||
"tmp": "0.1.0",
|
||||
"ts-loader": "5.3.3",
|
||||
"ts-node": "8.0.2",
|
||||
"tslint": "5.13.1",
|
||||
"ts-node": "7.0.1",
|
||||
"tslint": "5.15.0",
|
||||
"tslint-sonarts": "1.9.0",
|
||||
"typeorm": "0.2.16-rc.1",
|
||||
"typescript": "3.3.3333",
|
||||
"typescript-eslint-parser": "22.0.0",
|
||||
"uglify-es": "3.3.9",
|
||||
"ulid": "2.3.0",
|
||||
"url-loader": "1.1.2",
|
||||
"uuid": "3.3.2",
|
||||
"v-animate-css": "0.0.3",
|
||||
"v-debounce": "0.1.2",
|
||||
"video-thumbnail-generator": "1.1.3",
|
||||
"vue": "2.6.8",
|
||||
"vue": "2.6.10",
|
||||
"vue-color": "2.7.0",
|
||||
"vue-content-loading": "1.5.3",
|
||||
"vue-content-loading": "1.6.0",
|
||||
"vue-cropperjs": "3.0.0",
|
||||
"vue-i18n": "8.8.2",
|
||||
"vue-i18n": "8.10.0",
|
||||
"vue-js-modal": "1.3.28",
|
||||
"vue-json-pretty": "1.6.0",
|
||||
"vue-loader": "15.7.0",
|
||||
"vue-marquee-text-component": "1.1.1",
|
||||
"vue-prism-component": "1.1.1",
|
||||
"vue-router": "3.0.2",
|
||||
"vue-router": "3.0.6",
|
||||
"vue-sequential-entrance": "1.1.3",
|
||||
"vue-style-loader": "4.1.2",
|
||||
"vue-svg-inline-loader": "1.2.12",
|
||||
"vue-template-compiler": "2.6.8",
|
||||
"vuedraggable": "2.18.1",
|
||||
"vue-svg-inline-loader": "1.2.15",
|
||||
"vue-template-compiler": "2.6.10",
|
||||
"vuedraggable": "2.20.0",
|
||||
"vuewordcloud": "18.7.11",
|
||||
"vuex": "3.1.0",
|
||||
"vuex-persistedstate": "2.5.4",
|
||||
"web-push": "3.3.3",
|
||||
"webfinger.js": "2.7.0",
|
||||
"webpack": "4.28.4",
|
||||
"webpack-cli": "3.2.1",
|
||||
"webpack": "4.30.0",
|
||||
"webpack-cli": "3.3.0",
|
||||
"websocket": "1.0.28",
|
||||
"ws": "6.1.4",
|
||||
"ws": "6.2.1",
|
||||
"xev": "2.0.1"
|
||||
}
|
||||
}
|
||||
|
17
src/@types/deepcopy.d.ts
vendored
17
src/@types/deepcopy.d.ts
vendored
@@ -1,17 +0,0 @@
|
||||
declare module 'deepcopy';
|
||||
|
||||
declare namespace deepcopy {
|
||||
type DeepcopyCustomizerValueType = 'Object';
|
||||
|
||||
type DeepcopyCustomizer<T> = (
|
||||
value: T,
|
||||
valueType: DeepcopyCustomizerValueType) => T;
|
||||
|
||||
interface DeepcopyOptions<T> {
|
||||
customizer: DeepcopyCustomizer<T>;
|
||||
}
|
||||
|
||||
export function deepcopy<T>(
|
||||
value: T,
|
||||
options?: DeepcopyOptions<T> | DeepcopyCustomizer<T>): T;
|
||||
}
|
7
src/@types/escape-regexp.d.ts
vendored
7
src/@types/escape-regexp.d.ts
vendored
@@ -1,7 +0,0 @@
|
||||
declare module 'escape-regexp' {
|
||||
function escapeRegExp(str: string): string;
|
||||
|
||||
namespace escapeRegExp {} // Hack
|
||||
|
||||
export = escapeRegExp;
|
||||
}
|
2
src/@types/koa-slow.d.ts
vendored
2
src/@types/koa-slow.d.ts
vendored
@@ -8,7 +8,7 @@ declare module 'koa-slow' {
|
||||
|
||||
function slow(options?: ISlowOptions): Middleware;
|
||||
|
||||
namespace slow { } // Hack
|
||||
namespace slow {} // Hack
|
||||
|
||||
export = slow;
|
||||
}
|
||||
|
65
src/@types/webfinger.js.d.ts
vendored
65
src/@types/webfinger.js.d.ts
vendored
@@ -1,65 +0,0 @@
|
||||
declare module 'webfinger.js' {
|
||||
interface IWebFingerConstructorConfig {
|
||||
tls_only?: boolean;
|
||||
webfist_fallback?: boolean;
|
||||
uri_fallback?: boolean;
|
||||
request_timeout?: number;
|
||||
}
|
||||
|
||||
type JRDProperties = { [type: string]: string };
|
||||
|
||||
interface IJRDLink {
|
||||
rel: string;
|
||||
type?: string;
|
||||
href?: string;
|
||||
template?: string;
|
||||
titles?: { [lang: string]: string };
|
||||
properties?: JRDProperties;
|
||||
}
|
||||
|
||||
interface IJRD {
|
||||
subject?: string;
|
||||
expires?: Date;
|
||||
aliases?: string[];
|
||||
properties?: JRDProperties;
|
||||
links?: IJRDLink[];
|
||||
}
|
||||
|
||||
interface IIDXLinks {
|
||||
'avatar': IJRDLink[];
|
||||
'remotestorage': IJRDLink[];
|
||||
'blog': IJRDLink[];
|
||||
'vcard': IJRDLink[];
|
||||
'updates': IJRDLink[];
|
||||
'share': IJRDLink[];
|
||||
'profile': IJRDLink[];
|
||||
'webfist': IJRDLink[];
|
||||
'camlistore': IJRDLink[];
|
||||
[type: string]: IJRDLink[];
|
||||
}
|
||||
|
||||
interface IIDXProperties {
|
||||
'name': string;
|
||||
[type: string]: string;
|
||||
}
|
||||
|
||||
interface IIDX {
|
||||
links: IIDXLinks;
|
||||
properties: IIDXProperties;
|
||||
}
|
||||
|
||||
interface ILookupCallbackResult {
|
||||
object: IJRD;
|
||||
json: string;
|
||||
idx: IIDX;
|
||||
}
|
||||
|
||||
type LookupCallback = (err: Error | string, result?: ILookupCallbackResult) => void;
|
||||
|
||||
export class WebFinger {
|
||||
constructor(config?: IWebFingerConstructorConfig);
|
||||
|
||||
public lookup(address: string, cb: LookupCallback): NodeJS.Timeout;
|
||||
public lookupLink(address: string, rel: string, cb: IJRDLink): void;
|
||||
}
|
||||
}
|
@@ -5,8 +5,7 @@ program
|
||||
.version(pkg.version)
|
||||
.option('--no-daemons', 'Disable daemon processes (for debbuging)')
|
||||
.option('--disable-clustering', 'Disable clustering')
|
||||
.option('--disable-queue', 'Disable job queue processing')
|
||||
.option('--only-server', 'Run server only (without job queue)')
|
||||
.option('--only-server', 'Run server only (without job queue processing)')
|
||||
.option('--only-queue', 'Pocessing job queue only (without server)')
|
||||
.option('--quiet', 'Suppress all logs')
|
||||
.option('--verbose', 'Enable all logs')
|
||||
@@ -15,7 +14,9 @@ program
|
||||
.option('--color', 'This option is a dummy for some external program\'s (e.g. forever) issue.')
|
||||
.parse(process.argv);
|
||||
|
||||
/*if (process.env.MK_DISABLE_QUEUE)*/ program.disableQueue = true;
|
||||
if (process.env.MK_ONLY_QUEUE) program.onlyQueue = true;
|
||||
if (process.env.NODE_ENV === 'test') program.disableClustering = true;
|
||||
if (process.env.NODE_ENV === 'test') program.quiet = true;
|
||||
if (process.env.NODE_ENV === 'test') program.noDaemons = true;
|
||||
|
||||
export { program };
|
||||
|
77
src/boot/index.ts
Normal file
77
src/boot/index.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import * as cluster from 'cluster';
|
||||
import chalk from 'chalk';
|
||||
import Xev from 'xev';
|
||||
|
||||
import Logger from '../services/logger';
|
||||
import { program } from '../argv';
|
||||
|
||||
// for typeorm
|
||||
import 'reflect-metadata';
|
||||
import { masterMain } from './master';
|
||||
import { workerMain } from './worker';
|
||||
|
||||
const logger = new Logger('core', 'cyan');
|
||||
const clusterLogger = logger.createSubLogger('cluster', 'orange', false);
|
||||
const ev = new Xev();
|
||||
|
||||
/**
|
||||
* Init process
|
||||
*/
|
||||
export default async function() {
|
||||
process.title = `Misskey (${cluster.isMaster ? 'master' : 'worker'})`;
|
||||
|
||||
if (cluster.isMaster || program.disableClustering) {
|
||||
await masterMain();
|
||||
|
||||
if (cluster.isMaster) {
|
||||
ev.mount();
|
||||
}
|
||||
}
|
||||
|
||||
if (cluster.isWorker || program.disableClustering) {
|
||||
await workerMain();
|
||||
}
|
||||
|
||||
// ユニットテスト時にMisskeyが子プロセスで起動された時のため
|
||||
// それ以外のときは process.send は使えないので弾く
|
||||
if (process.send) {
|
||||
process.send('ok');
|
||||
}
|
||||
}
|
||||
|
||||
//#region Events
|
||||
|
||||
// Listen new workers
|
||||
cluster.on('fork', worker => {
|
||||
clusterLogger.debug(`Process forked: [${worker.id}]`);
|
||||
});
|
||||
|
||||
// Listen online workers
|
||||
cluster.on('online', worker => {
|
||||
clusterLogger.debug(`Process is now online: [${worker.id}]`);
|
||||
});
|
||||
|
||||
// Listen for dying workers
|
||||
cluster.on('exit', worker => {
|
||||
// Replace the dead worker,
|
||||
// we're not sentimental
|
||||
clusterLogger.error(chalk.red(`[${worker.id}] died :(`));
|
||||
cluster.fork();
|
||||
});
|
||||
|
||||
// Display detail of unhandled promise rejection
|
||||
if (!program.quiet) {
|
||||
process.on('unhandledRejection', console.dir);
|
||||
}
|
||||
|
||||
// Display detail of uncaught exception
|
||||
process.on('uncaughtException', err => {
|
||||
logger.error(err);
|
||||
});
|
||||
|
||||
// Dying away...
|
||||
process.on('exit', code => {
|
||||
logger.info(`The process is going to exit with code ${code}`);
|
||||
});
|
||||
|
||||
//#endregion
|
176
src/boot/master.ts
Normal file
176
src/boot/master.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
import * as os from 'os';
|
||||
import * as cluster from 'cluster';
|
||||
import chalk from 'chalk';
|
||||
import * as portscanner from 'portscanner';
|
||||
import * as isRoot from 'is-root';
|
||||
|
||||
import Logger from '../services/logger';
|
||||
import loadConfig from '../config/load';
|
||||
import { Config } from '../config/types';
|
||||
import { lessThan } from '../prelude/array';
|
||||
import * as pkg from '../../package.json';
|
||||
import { program } from '../argv';
|
||||
import { showMachineInfo } from '../misc/show-machine-info';
|
||||
import { initDb } from '../db/postgre';
|
||||
|
||||
const logger = new Logger('core', 'cyan');
|
||||
const bootLogger = logger.createSubLogger('boot', 'magenta', false);
|
||||
|
||||
function greet() {
|
||||
if (!program.quiet) {
|
||||
//#region Misskey logo
|
||||
const v = `v${pkg.version}`;
|
||||
console.log(' _____ _ _ ');
|
||||
console.log(' | |_|___ ___| |_ ___ _ _ ');
|
||||
console.log(' | | | | |_ -|_ -| \'_| -_| | |');
|
||||
console.log(' |_|_|_|_|___|___|_,_|___|_ |');
|
||||
console.log(' ' + chalk.gray(v) + (' |___|\n'.substr(v.length)));
|
||||
//#endregion
|
||||
|
||||
console.log(' Misskey is maintained by @syuilo, @AyaMorisawa, @mei23, @acid-chicken, and @rinsuki.');
|
||||
console.log(chalk.keyword('orange')(' If you like Misskey, please donate to support development. https://www.patreon.com/syuilo'));
|
||||
|
||||
console.log('');
|
||||
console.log(chalk`< ${os.hostname()} {gray (PID: ${process.pid.toString()})} >`);
|
||||
}
|
||||
|
||||
bootLogger.info('Welcome to Misskey!');
|
||||
bootLogger.info(`Misskey v${pkg.version}`, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init master process
|
||||
*/
|
||||
export async function masterMain() {
|
||||
greet();
|
||||
|
||||
let config!: Config;
|
||||
|
||||
try {
|
||||
// initialize app
|
||||
config = await init();
|
||||
|
||||
if (config.port == null) {
|
||||
bootLogger.error('The port is not configured. Please configure port.', null, true);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (process.platform === 'linux' && isWellKnownPort(config.port) && !isRoot()) {
|
||||
bootLogger.error('You need root privileges to listen on well-known port on Linux', null, true);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!await isPortAvailable(config.port)) {
|
||||
bootLogger.error(`Port ${config.port} is already in use`, null, true);
|
||||
process.exit(1);
|
||||
}
|
||||
} catch (e) {
|
||||
bootLogger.error('Fatal error occurred during initialization', null, true);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
bootLogger.succ('Misskey initialized');
|
||||
|
||||
if (!program.disableClustering) {
|
||||
await spawnWorkers(config.clusterLimit);
|
||||
}
|
||||
|
||||
if (!program.noDaemons) {
|
||||
require('../daemons/server-stats').default();
|
||||
require('../daemons/notes-stats').default();
|
||||
require('../daemons/queue-stats').default();
|
||||
}
|
||||
|
||||
bootLogger.succ(`Now listening on port ${config.port} on ${config.url}`, null, true);
|
||||
}
|
||||
|
||||
const runningNodejsVersion = process.version.slice(1).split('.').map(x => parseInt(x, 10));
|
||||
const requiredNodejsVersion = [11, 7, 0];
|
||||
const satisfyNodejsVersion = !lessThan(runningNodejsVersion, requiredNodejsVersion);
|
||||
|
||||
function isWellKnownPort(port: number): boolean {
|
||||
return port < 1024;
|
||||
}
|
||||
|
||||
async function isPortAvailable(port: number): Promise<boolean> {
|
||||
return await portscanner.checkPortStatus(port, '127.0.0.1') === 'closed';
|
||||
}
|
||||
|
||||
function showEnvironment(): void {
|
||||
const env = process.env.NODE_ENV;
|
||||
const logger = bootLogger.createSubLogger('env');
|
||||
logger.info(typeof env == 'undefined' ? 'NODE_ENV is not set' : `NODE_ENV: ${env}`);
|
||||
|
||||
if (env !== 'production') {
|
||||
logger.warn('The environment is not in production mode.');
|
||||
logger.warn('DO NOT USE FOR PRODUCTION PURPOSE!', null, true);
|
||||
}
|
||||
|
||||
logger.info(`You ${isRoot() ? '' : 'do not '}have root privileges`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init app
|
||||
*/
|
||||
async function init(): Promise<Config> {
|
||||
showEnvironment();
|
||||
|
||||
const nodejsLogger = bootLogger.createSubLogger('nodejs');
|
||||
|
||||
nodejsLogger.info(`Version ${runningNodejsVersion.join('.')}`);
|
||||
|
||||
if (!satisfyNodejsVersion) {
|
||||
nodejsLogger.error(`Node.js version is less than ${requiredNodejsVersion.join('.')}. Please upgrade it.`, null, true);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await showMachineInfo(bootLogger);
|
||||
|
||||
const configLogger = bootLogger.createSubLogger('config');
|
||||
let config;
|
||||
|
||||
try {
|
||||
config = loadConfig();
|
||||
} catch (exception) {
|
||||
if (typeof exception === 'string') {
|
||||
configLogger.error(exception);
|
||||
process.exit(1);
|
||||
}
|
||||
if (exception.code === 'ENOENT') {
|
||||
configLogger.error('Configuration file not found', null, true);
|
||||
process.exit(1);
|
||||
}
|
||||
throw exception;
|
||||
}
|
||||
|
||||
configLogger.succ('Loaded');
|
||||
|
||||
// Try to connect to DB
|
||||
try {
|
||||
bootLogger.info('Connecting database...');
|
||||
await initDb();
|
||||
} catch (e) {
|
||||
bootLogger.error('Cannot connect to database', null, true);
|
||||
bootLogger.error(e);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
async function spawnWorkers(limit: number = Infinity) {
|
||||
const workers = Math.min(limit, os.cpus().length);
|
||||
bootLogger.info(`Starting ${workers} worker${workers === 1 ? '' : 's'}...`);
|
||||
await Promise.all([...Array(workers)].map(spawnWorker));
|
||||
bootLogger.succ('All workers started');
|
||||
}
|
||||
|
||||
function spawnWorker(): Promise<void> {
|
||||
return new Promise(res => {
|
||||
const worker = cluster.fork();
|
||||
worker.on('message', message => {
|
||||
if (message !== 'ready') return;
|
||||
res();
|
||||
});
|
||||
});
|
||||
}
|
20
src/boot/worker.ts
Normal file
20
src/boot/worker.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import * as cluster from 'cluster';
|
||||
import { initDb } from '../db/postgre';
|
||||
|
||||
/**
|
||||
* Init worker process
|
||||
*/
|
||||
export async function workerMain() {
|
||||
await initDb();
|
||||
|
||||
// start server
|
||||
await require('../server').default();
|
||||
|
||||
// start job queue
|
||||
require('../queue').default();
|
||||
|
||||
if (cluster.isWorker) {
|
||||
// Send a 'ready' message to parent process
|
||||
process.send!('ready');
|
||||
}
|
||||
}
|
@@ -9,6 +9,9 @@
|
||||
<ui-textarea v-model="announcement.text">
|
||||
<span>{{ $t('text') }}</span>
|
||||
</ui-textarea>
|
||||
<ui-input v-model="announcement.image">
|
||||
<span>{{ $t('image-url') }}</span>
|
||||
</ui-input>
|
||||
<ui-horizon-group class="fit-bottom">
|
||||
<ui-button @click="save()"><fa :icon="['far', 'save']"/> {{ $t('save') }}</ui-button>
|
||||
<ui-button @click="remove(i)"><fa :icon="['far', 'trash-alt']"/> {{ $t('remove') }}</ui-button>
|
||||
@@ -43,7 +46,8 @@ export default Vue.extend({
|
||||
add() {
|
||||
this.announcements.unshift({
|
||||
title: '',
|
||||
text: ''
|
||||
text: '',
|
||||
image: null
|
||||
});
|
||||
},
|
||||
|
||||
|
@@ -181,7 +181,12 @@ export default Vue.extend({
|
||||
},
|
||||
grid: {
|
||||
clipMarkers: false,
|
||||
borderColor: 'rgba(0, 0, 0, 0.1)'
|
||||
borderColor: 'rgba(0, 0, 0, 0.1)',
|
||||
xaxis: {
|
||||
lines: {
|
||||
show: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
stroke: {
|
||||
curve: 'straight',
|
||||
@@ -240,6 +245,7 @@ export default Vue.extend({
|
||||
federationInstancesChart(total: boolean): any {
|
||||
return {
|
||||
series: [{
|
||||
name: 'Instances',
|
||||
data: this.format(total
|
||||
? this.stats.federation.instance.total
|
||||
: sum(this.stats.federation.instance.inc, negate(this.stats.federation.instance.dec))
|
196
src/client/app/admin/views/dashboard.queue-charts.vue
Normal file
196
src/client/app/admin/views/dashboard.queue-charts.vue
Normal file
@@ -0,0 +1,196 @@
|
||||
<template>
|
||||
<div class="mzxlfysy">
|
||||
<div>
|
||||
<header>
|
||||
<span><fa :icon="faInbox"/> In</span>
|
||||
<span v-if="latestStats">{{ latestStats.inbox.activeSincePrevTick | number }} / {{ latestStats.inbox.delayed | number }}</span>
|
||||
</header>
|
||||
<div ref="in"></div>
|
||||
</div>
|
||||
<div>
|
||||
<header>
|
||||
<span><fa :icon="faPaperPlane"/> Out</span>
|
||||
<span v-if="latestStats">{{ latestStats.deliver.activeSincePrevTick | number }} / {{ latestStats.deliver.delayed | number }}</span>
|
||||
</header>
|
||||
<div ref="out"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import { faInbox } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faPaperPlane } from '@fortawesome/free-regular-svg-icons';
|
||||
import ApexCharts from 'apexcharts';
|
||||
|
||||
const limit = 150;
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
return {
|
||||
stats: [],
|
||||
inChart: null,
|
||||
outChart: null,
|
||||
faInbox, faPaperPlane
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
latestStats(): any {
|
||||
return this.stats[this.stats.length - 1];
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
stats(stats) {
|
||||
this.inChart.updateSeries([{
|
||||
data: stats.map((x, i) => ({ x: i, y: x.inbox.activeSincePrevTick }))
|
||||
}, {
|
||||
data: stats.map((x, i) => ({ x: i, y: x.inbox.active }))
|
||||
}, {
|
||||
data: stats.map((x, i) => ({ x: i, y: x.inbox.waiting }))
|
||||
}, {
|
||||
data: stats.map((x, i) => ({ x: i, y: x.inbox.delayed }))
|
||||
}]);
|
||||
this.outChart.updateSeries([{
|
||||
data: stats.map((x, i) => ({ x: i, y: x.deliver.activeSincePrevTick }))
|
||||
}, {
|
||||
data: stats.map((x, i) => ({ x: i, y: x.deliver.active }))
|
||||
}, {
|
||||
data: stats.map((x, i) => ({ x: i, y: x.deliver.waiting }))
|
||||
}, {
|
||||
data: stats.map((x, i) => ({ x: i, y: x.deliver.delayed }))
|
||||
}]);
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
const chartOpts = {
|
||||
chart: {
|
||||
type: 'area',
|
||||
height: 200,
|
||||
animations: {
|
||||
dynamicAnimation: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
toolbar: {
|
||||
show: false
|
||||
},
|
||||
zoom: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
grid: {
|
||||
clipMarkers: false,
|
||||
borderColor: 'rgba(0, 0, 0, 0.1)'
|
||||
},
|
||||
stroke: {
|
||||
curve: 'straight',
|
||||
width: 2
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
},
|
||||
colors: ['#00E396', '#00BCD4', '#FFB300', '#e53935'],
|
||||
series: [{ data: [] }, { data: [] }, { data: [] }, { data: [] }] as any,
|
||||
xaxis: {
|
||||
type: 'numeric',
|
||||
labels: {
|
||||
show: false
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
show: false,
|
||||
min: 0,
|
||||
}
|
||||
};
|
||||
|
||||
this.inChart = new ApexCharts(this.$refs.in, chartOpts);
|
||||
this.outChart = new ApexCharts(this.$refs.out, chartOpts);
|
||||
|
||||
this.inChart.render();
|
||||
this.outChart.render();
|
||||
|
||||
const connection = this.$root.stream.useSharedConnection('queueStats');
|
||||
connection.on('stats', this.onStats);
|
||||
connection.on('statsLog', this.onStatsLog);
|
||||
connection.send('requestLog', {
|
||||
id: Math.random().toString().substr(2, 8),
|
||||
length: limit
|
||||
});
|
||||
|
||||
this.$once('hook:beforeDestroy', () => {
|
||||
connection.dispose();
|
||||
this.inChart.destroy();
|
||||
this.outChart.destroy();
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
onStats(stats) {
|
||||
this.stats.push(stats);
|
||||
if (this.stats.length > limit) this.stats.shift();
|
||||
},
|
||||
|
||||
onStatsLog(statsLog) {
|
||||
for (const stats of statsLog.reverse()) {
|
||||
this.onStats(stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.mzxlfysy
|
||||
display flex
|
||||
|
||||
> div
|
||||
display block
|
||||
flex 1
|
||||
padding 20px 12px 0 12px
|
||||
box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
|
||||
background var(--face)
|
||||
border-radius 8px
|
||||
|
||||
&:first-child
|
||||
margin-right 16px
|
||||
|
||||
> header
|
||||
display flex
|
||||
padding 0 8px
|
||||
margin-bottom -16px
|
||||
color var(--adminDashboardCardFg)
|
||||
font-size 14px
|
||||
|
||||
> span
|
||||
&:last-child
|
||||
margin-left auto
|
||||
opacity 0.7
|
||||
|
||||
> span
|
||||
opacity 0.7
|
||||
|
||||
> div
|
||||
margin-bottom -10px
|
||||
|
||||
@media (max-width 1000px)
|
||||
display block
|
||||
margin-bottom 26px
|
||||
|
||||
> div
|
||||
&:first-child
|
||||
margin-right 0
|
||||
margin-bottom 26px
|
||||
|
||||
</style>
|
@@ -73,6 +73,10 @@
|
||||
<x-charts ref="charts"/>
|
||||
</div>
|
||||
|
||||
<div class="queue">
|
||||
<x-queue/>
|
||||
</div>
|
||||
|
||||
<div class="cpu-memory">
|
||||
<x-cpu-memory :connection="connection"/>
|
||||
</div>
|
||||
@@ -86,9 +90,10 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../i18n';
|
||||
import XCpuMemory from "./cpu-memory.vue";
|
||||
import XCharts from "./charts.vue";
|
||||
import XApLog from "./ap-log.vue";
|
||||
import XCpuMemory from "./dashboard.cpu-memory.vue";
|
||||
import XQueue from "./dashboard.queue-charts.vue";
|
||||
import XCharts from "./dashboard.charts.vue";
|
||||
import XApLog from "./dashboard.ap-log.vue";
|
||||
import { faDatabase } from '@fortawesome/free-solid-svg-icons';
|
||||
import MarqueeText from 'vue-marquee-text-component';
|
||||
import randomColor from 'randomcolor';
|
||||
@@ -98,6 +103,7 @@ export default Vue.extend({
|
||||
|
||||
components: {
|
||||
XCpuMemory,
|
||||
XQueue,
|
||||
XCharts,
|
||||
XApLog,
|
||||
MarqueeText
|
||||
@@ -274,6 +280,9 @@ export default Vue.extend({
|
||||
> .charts
|
||||
margin-bottom 16px
|
||||
|
||||
> .queue
|
||||
margin-bottom 16px
|
||||
|
||||
> .cpu-memory
|
||||
margin-bottom 16px
|
||||
|
||||
|
@@ -38,7 +38,7 @@
|
||||
<div class="kidvdlkg" v-for="file in files">
|
||||
<div @click="file._open = !file._open">
|
||||
<div>
|
||||
<div class="thumbnail" :style="thumbnail(file)"></div>
|
||||
<x-file-thumbnail class="thumbnail" :file="file" fit="contain" @click="showFileMenu(file)"/>
|
||||
</div>
|
||||
<div>
|
||||
<header>
|
||||
@@ -48,7 +48,7 @@
|
||||
<div>
|
||||
<div>
|
||||
<span style="margin-right:16px;">{{ file.type }}</span>
|
||||
<span>{{ file.datasize | bytes }}</span>
|
||||
<span>{{ file.size | bytes }}</span>
|
||||
</div>
|
||||
<div><mk-time :time="file.createdAt" mode="detail"/></div>
|
||||
</div>
|
||||
@@ -75,10 +75,15 @@ import Vue from 'vue';
|
||||
import i18n from '../../i18n';
|
||||
import { faCloud, faTerminal, faSearch } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faTrashAlt, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons';
|
||||
import XFileThumbnail from '../../common/views/components/drive-file-thumbnail.vue';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('admin/views/drive.vue'),
|
||||
|
||||
components: {
|
||||
XFileThumbnail
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
file: null,
|
||||
@@ -151,13 +156,6 @@ export default Vue.extend({
|
||||
});
|
||||
},
|
||||
|
||||
thumbnail(file: any): any {
|
||||
return {
|
||||
'background-color': file.properties.avgColor && file.properties.avgColor.length == 3 ? `rgb(${file.properties.avgColor.join(',')})` : 'transparent',
|
||||
'background-image': `url(${file.thumbnailUrl})`
|
||||
};
|
||||
},
|
||||
|
||||
async del(file: any) {
|
||||
const process = async () => {
|
||||
await this.$root.api('drive/files/delete', { fileId: file.id });
|
||||
@@ -179,9 +177,9 @@ export default Vue.extend({
|
||||
this.$root.api('drive/files/update', {
|
||||
fileId: file.id,
|
||||
isSensitive: !file.isSensitive
|
||||
}).then(() => {
|
||||
file.isSensitive = !file.isSensitive;
|
||||
});
|
||||
|
||||
file.isSensitive = !file.isSensitive;
|
||||
},
|
||||
|
||||
async show() {
|
||||
@@ -244,7 +242,7 @@ export default Vue.extend({
|
||||
|
||||
> div:nth-child(1)
|
||||
> .thumbnail
|
||||
display block
|
||||
display flex
|
||||
width 64px
|
||||
height 64px
|
||||
background-size cover
|
||||
|
@@ -1,43 +1,58 @@
|
||||
<template>
|
||||
<div>
|
||||
<ui-card>
|
||||
<template #title><fa :icon="faTerminal"/> {{ $t('federation') }}</template>
|
||||
<template #title><fa :icon="faTerminal"/> {{ $t('instance') }}</template>
|
||||
<section class="fit-top">
|
||||
<ui-input class="target" v-model="target" type="text" @enter="showInstance()">
|
||||
<span>{{ $t('host') }}</span>
|
||||
<template #prefix><fa :icon="faServer"/></template>
|
||||
</ui-input>
|
||||
<ui-button @click="showInstance()"><fa :icon="faSearch"/> {{ $t('lookup') }}</ui-button>
|
||||
|
||||
<div class="instance" v-if="instance">
|
||||
<ui-input :value="instance.host" type="text" readonly>
|
||||
<span>{{ $t('host') }}</span>
|
||||
</ui-input>
|
||||
<ui-horizon-group inputs>
|
||||
<ui-input :value="instance.host" type="text" readonly>
|
||||
<span>{{ $t('host') }}</span>
|
||||
<template #prefix><fa :icon="faServer"/></template>
|
||||
</ui-input>
|
||||
<ui-input :value="instance.caughtAt | date" type="text" readonly>
|
||||
<span>{{ $t('caught-at') }}</span>
|
||||
<template #prefix><fa :icon="faCrosshairs"/></template>
|
||||
</ui-input>
|
||||
</ui-horizon-group>
|
||||
<ui-horizon-group inputs>
|
||||
<ui-input :value="instance.notesCount | number" type="text" readonly>
|
||||
<span>{{ $t('notes') }}</span>
|
||||
<template #prefix><fa :icon="faEnvelopeOpenText"/></template>
|
||||
</ui-input>
|
||||
<ui-input :value="instance.usersCount | number" type="text" readonly>
|
||||
<span>{{ $t('users') }}</span>
|
||||
<template #prefix><fa :icon="faUsers"/></template>
|
||||
</ui-input>
|
||||
</ui-horizon-group>
|
||||
<ui-horizon-group inputs>
|
||||
<ui-input :value="instance.followingCount | number" type="text" readonly>
|
||||
<span>{{ $t('following') }}</span>
|
||||
<template #prefix><fa :icon="faCaretDown"/></template>
|
||||
</ui-input>
|
||||
<ui-input :value="instance.followersCount | number" type="text" readonly>
|
||||
<span>{{ $t('followers') }}</span>
|
||||
<template #prefix><fa :icon="faCaretUp"/></template>
|
||||
</ui-input>
|
||||
</ui-horizon-group>
|
||||
<ui-horizon-group inputs>
|
||||
<ui-input :value="instance.latestRequestSentAt" type="text" readonly>
|
||||
<ui-input :value="instance.latestRequestSentAt | date" type="text" readonly>
|
||||
<span>{{ $t('latest-request-sent-at') }}</span>
|
||||
<template #prefix><fa :icon="faPaperPlane"/></template>
|
||||
</ui-input>
|
||||
<ui-input :value="instance.latestStatus" type="text" readonly>
|
||||
<span>{{ $t('status') }}</span>
|
||||
<template #prefix><fa :icon="faTrafficLight"/></template>
|
||||
</ui-input>
|
||||
</ui-horizon-group>
|
||||
<ui-input :value="instance.latestRequestReceivedAt" type="text" readonly>
|
||||
<ui-input :value="instance.latestRequestReceivedAt | date" type="text" readonly>
|
||||
<span>{{ $t('latest-request-received-at') }}</span>
|
||||
<template #prefix><fa :icon="faInbox"/></template>
|
||||
</ui-input>
|
||||
<ui-switch v-model="instance.isBlocked" @change="updateInstance()">{{ $t('block') }}</ui-switch>
|
||||
<ui-switch v-model="instance.isMarkedAsClosed" @change="updateInstance()">{{ $t('marked-as-closed') }}</ui-switch>
|
||||
@@ -133,7 +148,8 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../i18n';
|
||||
import { faGlobe, faTerminal, faSearch, faMinusCircle, faServer } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faPaperPlane } from '@fortawesome/free-regular-svg-icons';
|
||||
import { faGlobe, faTerminal, faSearch, faMinusCircle, faServer, faCrosshairs, faEnvelopeOpenText, faUsers, faCaretDown, faCaretUp, faTrafficLight, faInbox } from '@fortawesome/free-solid-svg-icons';
|
||||
import ApexCharts from 'apexcharts';
|
||||
import * as tinycolor from 'tinycolor2';
|
||||
|
||||
@@ -144,19 +160,23 @@ const negate = arr => arr.map(x => -x);
|
||||
export default Vue.extend({
|
||||
i18n: i18n('admin/views/federation.vue'),
|
||||
|
||||
filters: {
|
||||
date: v => v ? new Date(v).toLocaleString() : 'N/A'
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
instance: null,
|
||||
target: null,
|
||||
sort: '+lastCommunicatedAt',
|
||||
state: 'all',
|
||||
limit: 50,
|
||||
limit: 100,
|
||||
instances: [],
|
||||
chart: null,
|
||||
chartSrc: 'requests',
|
||||
chartSpan: 'hour',
|
||||
chartInstance: null,
|
||||
faGlobe, faTerminal, faSearch, faMinusCircle, faServer
|
||||
faGlobe, faTerminal, faSearch, faMinusCircle, faServer, faCrosshairs, faEnvelopeOpenText, faUsers, faCaretDown, faCaretUp, faPaperPlane, faTrafficLight, faInbox
|
||||
};
|
||||
},
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
<ui-card>
|
||||
<template #title>{{ $t('hided-tags') }}</template>
|
||||
<section>
|
||||
<textarea class="jdnqwkzlnxcfftthoybjxrebyolvoucw" v-model="hidedTags"></textarea>
|
||||
<textarea class="jdnqwkzlnxcfftthoybjxrebyolvoucw" v-model="hiddenTags"></textarea>
|
||||
<ui-button @click="save">{{ $t('save') }}</ui-button>
|
||||
</section>
|
||||
</ui-card>
|
||||
@@ -18,18 +18,18 @@ export default Vue.extend({
|
||||
i18n: i18n('admin/views/hashtags.vue'),
|
||||
data() {
|
||||
return {
|
||||
hidedTags: '',
|
||||
hiddenTags: '',
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$root.getMeta().then(meta => {
|
||||
this.hidedTags = meta.hidedTags.join('\n');
|
||||
this.hiddenTags = meta.hiddenTags.join('\n');
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
this.$root.api('admin/update-meta', {
|
||||
hidedTags: this.hidedTags.split('\n')
|
||||
hiddenTags: this.hiddenTags.split('\n')
|
||||
}).then(() => {
|
||||
//this.$root.os.apis.dialog({ text: `Saved` });
|
||||
}).catch(e => {
|
||||
|
@@ -6,6 +6,7 @@
|
||||
<ui-input :value="host" readonly>{{ $t('host') }}</ui-input>
|
||||
<ui-input v-model="name">{{ $t('instance-name') }}</ui-input>
|
||||
<ui-textarea v-model="description">{{ $t('instance-description') }}</ui-textarea>
|
||||
<ui-input v-model="iconUrl"><template #icon><fa icon="link"/></template>{{ $t('icon-url') }}</ui-input>
|
||||
<ui-input v-model="mascotImageUrl"><template #icon><fa icon="link"/></template>{{ $t('logo-url') }}</ui-input>
|
||||
<ui-input v-model="bannerUrl"><template #icon><fa icon="link"/></template>{{ $t('banner-url') }}</ui-input>
|
||||
<ui-input v-model="errorImageUrl"><template #icon><fa icon="link"/></template>{{ $t('error-image-url') }}</ui-input>
|
||||
@@ -24,6 +25,8 @@
|
||||
<ui-switch v-model="disableLocalTimeline">{{ $t('disable-local-timeline') }}</ui-switch>
|
||||
<ui-switch v-model="disableGlobalTimeline">{{ $t('disable-global-timeline') }}</ui-switch>
|
||||
<ui-info>{{ $t('disabling-timelines-info') }}</ui-info>
|
||||
<ui-switch v-model="enableEmojiReaction">{{ $t('enable-emoji-reaction') }}</ui-switch>
|
||||
<ui-switch v-model="useStarForReactionFallback">{{ $t('use-star-for-reaction-fallback') }}</ui-switch>
|
||||
</section>
|
||||
<section class="fit-bottom">
|
||||
<header><fa icon="cloud"/> {{ $t('drive-config') }}</header>
|
||||
@@ -74,12 +77,6 @@
|
||||
<header>summaly Proxy</header>
|
||||
<ui-input v-model="summalyProxy">URL</ui-input>
|
||||
</section>
|
||||
<section>
|
||||
<header><fa :icon="faUserPlus"/> {{ $t('user-recommendation-config') }}</header>
|
||||
<ui-switch v-model="enableExternalUserRecommendation">{{ $t('enable-external-user-recommendation') }}</ui-switch>
|
||||
<ui-input v-model="externalUserRecommendationEngine" :disabled="!enableExternalUserRecommendation">{{ $t('external-user-recommendation-engine') }}<template #desc>{{ $t('external-user-recommendation-engine-desc') }}</template></ui-input>
|
||||
<ui-input v-model="externalUserRecommendationTimeout" type="number" :disabled="!enableExternalUserRecommendation">{{ $t('external-user-recommendation-timeout') }}<template #suffix>ms</template><template #desc>{{ $t('external-user-recommendation-timeout-desc') }}</template></ui-input>
|
||||
</section>
|
||||
<section>
|
||||
<ui-button @click="updateMeta">{{ $t('save') }}</ui-button>
|
||||
</section>
|
||||
@@ -154,9 +151,12 @@ export default Vue.extend({
|
||||
disableRegistration: false,
|
||||
disableLocalTimeline: false,
|
||||
disableGlobalTimeline: false,
|
||||
enableEmojiReaction: true,
|
||||
useStarForReactionFallback: false,
|
||||
mascotImageUrl: null,
|
||||
bannerUrl: null,
|
||||
errorImageUrl: null,
|
||||
iconUrl: null,
|
||||
name: null,
|
||||
description: null,
|
||||
languages: null,
|
||||
@@ -178,9 +178,6 @@ export default Vue.extend({
|
||||
discordClientSecret: null,
|
||||
proxyAccount: null,
|
||||
inviteCode: null,
|
||||
enableExternalUserRecommendation: false,
|
||||
externalUserRecommendationEngine: null,
|
||||
externalUserRecommendationTimeout: null,
|
||||
summalyProxy: null,
|
||||
enableEmail: false,
|
||||
email: null,
|
||||
@@ -198,15 +195,18 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
created() {
|
||||
this.$root.getMeta().then(meta => {
|
||||
this.maintainerName = meta.maintainer.name;
|
||||
this.maintainerEmail = meta.maintainer.email;
|
||||
this.$root.getMeta(true).then(meta => {
|
||||
this.maintainerName = meta.maintainerName;
|
||||
this.maintainerEmail = meta.maintainerEmail;
|
||||
this.disableRegistration = meta.disableRegistration;
|
||||
this.disableLocalTimeline = meta.disableLocalTimeline;
|
||||
this.disableGlobalTimeline = meta.disableGlobalTimeline;
|
||||
this.enableEmojiReaction = meta.enableEmojiReaction;
|
||||
this.useStarForReactionFallback = meta.useStarForReactionFallback;
|
||||
this.mascotImageUrl = meta.mascotImageUrl;
|
||||
this.bannerUrl = meta.bannerUrl;
|
||||
this.errorImageUrl = meta.errorImageUrl;
|
||||
this.iconUrl = meta.iconUrl;
|
||||
this.name = meta.name;
|
||||
this.description = meta.description;
|
||||
this.languages = meta.langs.join(' ');
|
||||
@@ -227,9 +227,6 @@ export default Vue.extend({
|
||||
this.enableDiscordIntegration = meta.enableDiscordIntegration;
|
||||
this.discordClientId = meta.discordClientId;
|
||||
this.discordClientSecret = meta.discordClientSecret;
|
||||
this.enableExternalUserRecommendation = meta.enableExternalUserRecommendation;
|
||||
this.externalUserRecommendationEngine = meta.externalUserRecommendationEngine;
|
||||
this.externalUserRecommendationTimeout = meta.externalUserRecommendationTimeout;
|
||||
this.summalyProxy = meta.summalyProxy;
|
||||
this.enableEmail = meta.enableEmail;
|
||||
this.email = meta.email;
|
||||
@@ -264,9 +261,12 @@ export default Vue.extend({
|
||||
disableRegistration: this.disableRegistration,
|
||||
disableLocalTimeline: this.disableLocalTimeline,
|
||||
disableGlobalTimeline: this.disableGlobalTimeline,
|
||||
enableEmojiReaction: this.enableEmojiReaction,
|
||||
useStarForReactionFallback: this.useStarForReactionFallback,
|
||||
mascotImageUrl: this.mascotImageUrl,
|
||||
bannerUrl: this.bannerUrl,
|
||||
errorImageUrl: this.errorImageUrl,
|
||||
iconUrl: this.iconUrl,
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
langs: this.languages.split(' '),
|
||||
@@ -287,9 +287,6 @@ export default Vue.extend({
|
||||
enableDiscordIntegration: this.enableDiscordIntegration,
|
||||
discordClientId: this.discordClientId,
|
||||
discordClientSecret: this.discordClientSecret,
|
||||
enableExternalUserRecommendation: this.enableExternalUserRecommendation,
|
||||
externalUserRecommendationEngine: this.externalUserRecommendationEngine,
|
||||
externalUserRecommendationTimeout: parseInt(this.externalUserRecommendationTimeout, 10),
|
||||
summalyProxy: this.summalyProxy,
|
||||
enableEmail: this.enableEmail,
|
||||
email: this.email,
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<template #title><fa :icon="faStream"/> {{ $t('logs') }}</template>
|
||||
<section class="fit-top">
|
||||
<ui-horizon-group inputs>
|
||||
<ui-input v-model="domain">
|
||||
<ui-input v-model="domain" :debounce="true">
|
||||
<span>{{ $t('domain') }}</span>
|
||||
</ui-input>
|
||||
<ui-select v-model="level">
|
||||
@@ -19,8 +19,11 @@
|
||||
</ui-horizon-group>
|
||||
|
||||
<div class="nqjzuvev">
|
||||
<code v-for="log in logs" :key="log._id" :class="log.level">
|
||||
<mk-time :time="log.createdAt"/> [{{ log.domain.join(' ') }}] {{ log.message }}
|
||||
<code v-for="log in logs" :key="log.id" :class="log.level">
|
||||
<details>
|
||||
<summary><mk-time :time="log.createdAt"/> [{{ log.domain.join('.') }}] {{ log.message }}</summary>
|
||||
<vue-json-pretty v-if="log.data" :data="log.data"></vue-json-pretty>
|
||||
</details>
|
||||
</code>
|
||||
</div>
|
||||
</section>
|
||||
@@ -32,10 +35,15 @@
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../i18n';
|
||||
import { faStream } from '@fortawesome/free-solid-svg-icons';
|
||||
import VueJsonPretty from 'vue-json-pretty';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('admin/views/logs.vue'),
|
||||
|
||||
components: {
|
||||
VueJsonPretty
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
logs: [],
|
||||
@@ -66,9 +74,9 @@ export default Vue.extend({
|
||||
this.$root.api('admin/logs', {
|
||||
level: this.level === 'all' ? null : this.level,
|
||||
domain: this.domain === '' ? null : this.domain,
|
||||
limit: 50
|
||||
limit: 100
|
||||
}).then(logs => {
|
||||
this.logs = logs;
|
||||
this.logs = logs.reverse();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -77,11 +85,10 @@ export default Vue.extend({
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.nqjzuvev
|
||||
white-space nowrap
|
||||
overflow auto
|
||||
padding 8px
|
||||
background #000
|
||||
color #fff
|
||||
font-size 14px
|
||||
|
||||
> code
|
||||
display block
|
||||
|
@@ -1,26 +1,261 @@
|
||||
<template>
|
||||
<div>
|
||||
<ui-card>
|
||||
<template #title>{{ $t('operation') }}</template>
|
||||
<template #title><fa :icon="faChartBar"/> {{ $t('title') }}</template>
|
||||
<section class="wptihjuy">
|
||||
<header><fa :icon="faPaperPlane"/> Deliver</header>
|
||||
<ui-info warn v-if="latestStats && latestStats.deliver.waiting > 0">The queue is jammed.</ui-info>
|
||||
<ui-horizon-group inputs v-if="latestStats" class="fit-bottom">
|
||||
<ui-input :value="latestStats.deliver.activeSincePrevTick | number" type="text" readonly>
|
||||
<span>Process</span>
|
||||
<template #prefix><fa :icon="fasPlayCircle"/></template>
|
||||
<template #suffix>jobs/tick</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.deliver.active | number" type="text" readonly>
|
||||
<span>Active</span>
|
||||
<template #prefix><fa :icon="farPlayCircle"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.deliver.waiting | number" type="text" readonly>
|
||||
<span>Waiting</span>
|
||||
<template #prefix><fa :icon="faStopCircle"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.deliver.delayed | number" type="text" readonly>
|
||||
<span>Delayed</span>
|
||||
<template #prefix><fa :icon="faStopwatch"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
</ui-horizon-group>
|
||||
<div ref="deliverChart" class="chart"></div>
|
||||
</section>
|
||||
<section class="wptihjuy">
|
||||
<header><fa :icon="faInbox"/> Inbox</header>
|
||||
<ui-info warn v-if="latestStats && latestStats.inbox.waiting > 0">The queue is jammed.</ui-info>
|
||||
<ui-horizon-group inputs v-if="latestStats" class="fit-bottom">
|
||||
<ui-input :value="latestStats.inbox.activeSincePrevTick | number" type="text" readonly>
|
||||
<span>Process</span>
|
||||
<template #prefix><fa :icon="fasPlayCircle"/></template>
|
||||
<template #suffix>jobs/tick</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.inbox.active | number" type="text" readonly>
|
||||
<span>Active</span>
|
||||
<template #prefix><fa :icon="farPlayCircle"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.inbox.waiting | number" type="text" readonly>
|
||||
<span>Waiting</span>
|
||||
<template #prefix><fa :icon="faStopCircle"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.inbox.delayed | number" type="text" readonly>
|
||||
<span>Delayed</span>
|
||||
<template #prefix><fa :icon="faStopwatch"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
</ui-horizon-group>
|
||||
<div ref="inboxChart" class="chart"></div>
|
||||
</section>
|
||||
<section>
|
||||
<ui-button @click="removeAllJobs">{{ $t('remove-all-jobs') }}</ui-button>
|
||||
</section>
|
||||
</ui-card>
|
||||
|
||||
<ui-card>
|
||||
<template #title><fa :icon="faTasks"/> {{ $t('jobs') }}</template>
|
||||
<section class="fit-top">
|
||||
<ui-horizon-group inputs>
|
||||
<ui-select v-model="domain">
|
||||
<template #label>{{ $t('queue') }}</template>
|
||||
<option value="deliver">{{ $t('domains.deliver') }}</option>
|
||||
<option value="inbox">{{ $t('domains.inbox') }}</option>
|
||||
</ui-select>
|
||||
<ui-select v-model="state">
|
||||
<template #label>{{ $t('state') }}</template>
|
||||
<option value="delayed">{{ $t('states.delayed') }}</option>
|
||||
</ui-select>
|
||||
</ui-horizon-group>
|
||||
<sequential-entrance animation="entranceFromTop" delay="25">
|
||||
<div class="xvvuvgsv" v-for="job in jobs">
|
||||
<b>{{ job.id }}</b>
|
||||
<template v-if="domain === 'deliver'">
|
||||
<span>{{ job.data.to }}</span>
|
||||
</template>
|
||||
<template v-if="domain === 'inbox'">
|
||||
<span>{{ job.activity.id }}</span>
|
||||
</template>
|
||||
</div>
|
||||
</sequential-entrance>
|
||||
<ui-info v-if="jobs.length == jobsLimit">{{ $t('result-is-truncated', { n: jobsLimit }) }}</ui-info>
|
||||
</section>
|
||||
</ui-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../i18n';
|
||||
import ApexCharts from 'apexcharts';
|
||||
import * as tinycolor from 'tinycolor2';
|
||||
import { faTasks, faInbox, faStopwatch, faPlayCircle as fasPlayCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faPaperPlane, faStopCircle, faPlayCircle as farPlayCircle, faChartBar } from '@fortawesome/free-regular-svg-icons';
|
||||
|
||||
const limit = 200;
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('admin/views/queue.vue'),
|
||||
|
||||
data() {
|
||||
return {
|
||||
stats: [],
|
||||
deliverChart: null,
|
||||
inboxChart: null,
|
||||
jobs: [],
|
||||
jobsLimit: 50,
|
||||
domain: 'deliver',
|
||||
state: 'delayed',
|
||||
faTasks, faPaperPlane, faInbox, faStopwatch, faStopCircle, farPlayCircle, fasPlayCircle, faChartBar
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
latestStats(): any {
|
||||
return this.stats[this.stats.length - 1];
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
stats(stats) {
|
||||
this.inboxChart.updateSeries([{
|
||||
name: 'Process',
|
||||
type: 'area',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.inbox.activeSincePrevTick }))
|
||||
}, {
|
||||
name: 'Active',
|
||||
type: 'area',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.inbox.active }))
|
||||
}, {
|
||||
name: 'Waiting',
|
||||
type: 'line',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.inbox.waiting }))
|
||||
}, {
|
||||
name: 'Delayed',
|
||||
type: 'line',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.inbox.delayed }))
|
||||
}]);
|
||||
this.deliverChart.updateSeries([{
|
||||
name: 'Process',
|
||||
type: 'area',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.deliver.activeSincePrevTick }))
|
||||
}, {
|
||||
name: 'Active',
|
||||
type: 'area',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.deliver.active }))
|
||||
}, {
|
||||
name: 'Waiting',
|
||||
type: 'line',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.deliver.waiting }))
|
||||
}, {
|
||||
name: 'Delayed',
|
||||
type: 'line',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.deliver.delayed }))
|
||||
}]);
|
||||
},
|
||||
|
||||
domain() {
|
||||
this.jobs = [];
|
||||
this.fetchJobs();
|
||||
},
|
||||
|
||||
state() {
|
||||
this.jobs = [];
|
||||
this.fetchJobs();
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.fetchJobs();
|
||||
|
||||
const chartOpts = id => ({
|
||||
chart: {
|
||||
id,
|
||||
group: 'queue',
|
||||
type: 'area',
|
||||
height: 200,
|
||||
animations: {
|
||||
dynamicAnimation: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
toolbar: {
|
||||
show: false
|
||||
},
|
||||
zoom: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
grid: {
|
||||
clipMarkers: false,
|
||||
borderColor: 'rgba(0, 0, 0, 0.1)',
|
||||
xaxis: {
|
||||
lines: {
|
||||
show: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
stroke: {
|
||||
curve: 'straight',
|
||||
width: 2
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false
|
||||
},
|
||||
legend: {
|
||||
labels: {
|
||||
colors: tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--text')).toRgbString()
|
||||
},
|
||||
},
|
||||
series: [] as any,
|
||||
colors: ['#00E396', '#00BCD4', '#FFB300', '#e53935'],
|
||||
xaxis: {
|
||||
type: 'numeric',
|
||||
labels: {
|
||||
show: false
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
show: false,
|
||||
min: 0,
|
||||
}
|
||||
});
|
||||
|
||||
this.inboxChart = new ApexCharts(this.$refs.inboxChart, chartOpts('a'));
|
||||
this.deliverChart = new ApexCharts(this.$refs.deliverChart, chartOpts('b'));
|
||||
|
||||
this.inboxChart.render();
|
||||
this.deliverChart.render();
|
||||
|
||||
const connection = this.$root.stream.useSharedConnection('queueStats');
|
||||
connection.on('stats', this.onStats);
|
||||
connection.on('statsLog', this.onStatsLog);
|
||||
connection.send('requestLog', {
|
||||
id: Math.random().toString().substr(2, 8),
|
||||
length: limit
|
||||
});
|
||||
|
||||
this.$once('hook:beforeDestroy', () => {
|
||||
connection.dispose();
|
||||
this.inboxChart.destroy();
|
||||
this.deliverChart.destroy();
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
async removeAllJobs() {
|
||||
const process = async () => {
|
||||
@@ -38,6 +273,39 @@ export default Vue.extend({
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
onStats(stats) {
|
||||
this.stats.push(stats);
|
||||
if (this.stats.length > limit) this.stats.shift();
|
||||
},
|
||||
|
||||
onStatsLog(statsLog) {
|
||||
for (const stats of statsLog.reverse()) {
|
||||
this.onStats(stats);
|
||||
}
|
||||
},
|
||||
|
||||
fetchJobs() {
|
||||
this.$root.api('admin/queue/jobs', {
|
||||
domain: this.domain,
|
||||
state: this.state,
|
||||
limit: this.jobsLimit
|
||||
}).then(jobs => {
|
||||
this.jobs = jobs;
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.wptihjuy
|
||||
> .chart
|
||||
min-height 200px !important
|
||||
margin 0 -8px
|
||||
|
||||
.xvvuvgsv
|
||||
> b
|
||||
margin-right 16px
|
||||
|
||||
</style>
|
||||
|
@@ -165,7 +165,7 @@ export default Vue.extend({
|
||||
|
||||
/** 処理対象ユーザーの情報を更新する */
|
||||
async refreshUser() {
|
||||
this.$root.api('admin/show-user', { userId: this.user._id }).then(info => {
|
||||
this.$root.api('admin/show-user', { userId: this.user.id }).then(info => {
|
||||
this.user = info;
|
||||
});
|
||||
},
|
||||
@@ -173,7 +173,7 @@ export default Vue.extend({
|
||||
async resetPassword() {
|
||||
if (!await this.getConfirmed(this.$t('reset-password-confirm'))) return;
|
||||
|
||||
this.$root.api('admin/reset-password', { userId: this.user._id }).then(res => {
|
||||
this.$root.api('admin/reset-password', { userId: this.user.id }).then(res => {
|
||||
this.$root.dialog({
|
||||
type: 'success',
|
||||
text: this.$t('password-updated', { password: res.password })
|
||||
@@ -187,7 +187,7 @@ export default Vue.extend({
|
||||
this.verifying = true;
|
||||
|
||||
const process = async () => {
|
||||
await this.$root.api('admin/verify-user', { userId: this.user._id });
|
||||
await this.$root.api('admin/verify-user', { userId: this.user.id });
|
||||
this.$root.dialog({
|
||||
type: 'success',
|
||||
text: this.$t('verified')
|
||||
@@ -212,7 +212,7 @@ export default Vue.extend({
|
||||
this.unverifying = true;
|
||||
|
||||
const process = async () => {
|
||||
await this.$root.api('admin/unverify-user', { userId: this.user._id });
|
||||
await this.$root.api('admin/unverify-user', { userId: this.user.id });
|
||||
this.$root.dialog({
|
||||
type: 'success',
|
||||
text: this.$t('unverified')
|
||||
@@ -232,8 +232,10 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
async silenceUser() {
|
||||
if (!await this.getConfirmed(this.$t('silence-confirm'))) return;
|
||||
|
||||
const process = async () => {
|
||||
await this.$root.api('admin/silence-user', { userId: this.user._id });
|
||||
await this.$root.api('admin/silence-user', { userId: this.user.id });
|
||||
this.$root.dialog({
|
||||
type: 'success',
|
||||
splash: true
|
||||
@@ -251,8 +253,10 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
async unsilenceUser() {
|
||||
if (!await this.getConfirmed(this.$t('unsilence-confirm'))) return;
|
||||
|
||||
const process = async () => {
|
||||
await this.$root.api('admin/unsilence-user', { userId: this.user._id });
|
||||
await this.$root.api('admin/unsilence-user', { userId: this.user.id });
|
||||
this.$root.dialog({
|
||||
type: 'success',
|
||||
splash: true
|
||||
@@ -275,7 +279,7 @@ export default Vue.extend({
|
||||
this.suspending = true;
|
||||
|
||||
const process = async () => {
|
||||
await this.$root.api('admin/suspend-user', { userId: this.user._id });
|
||||
await this.$root.api('admin/suspend-user', { userId: this.user.id });
|
||||
this.$root.dialog({
|
||||
type: 'success',
|
||||
text: this.$t('suspended')
|
||||
@@ -300,7 +304,7 @@ export default Vue.extend({
|
||||
this.unsuspending = true;
|
||||
|
||||
const process = async () => {
|
||||
await this.$root.api('admin/unsuspend-user', { userId: this.user._id });
|
||||
await this.$root.api('admin/unsuspend-user', { userId: this.user.id });
|
||||
this.$root.dialog({
|
||||
type: 'success',
|
||||
text: this.$t('unsuspended')
|
||||
@@ -320,7 +324,7 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
async updateRemoteUser() {
|
||||
this.$root.api('admin/update-remote-user', { userId: this.user._id }).then(res => {
|
||||
this.$root.api('admin/update-remote-user', { userId: this.user.id }).then(res => {
|
||||
this.$root.dialog({
|
||||
type: 'success',
|
||||
text: this.$t('remote-user-updated')
|
||||
|
@@ -14,15 +14,7 @@
|
||||
<h2>{{ $t('permission-ask') }}</h2>
|
||||
<ul>
|
||||
<template v-for="p in app.permission">
|
||||
<li v-if="p == 'account-read'">{{ $t('account-read') }}</li>
|
||||
<li v-if="p == 'account-write'">{{ $t('account-write') }}</li>
|
||||
<li v-if="p == 'note-write'">{{ $t('note-write') }}</li>
|
||||
<li v-if="p == 'like-write'">{{ $t('like-write') }}</li>
|
||||
<li v-if="p == 'following-write'">{{ $t('following-write') }}</li>
|
||||
<li v-if="p == 'drive-read'">{{ $t('drive-read') }}</li>
|
||||
<li v-if="p == 'drive-write'">{{ $t('drive-write') }}</li>
|
||||
<li v-if="p == 'notification-read'">{{ $t('notification-read') }}</li>
|
||||
<li v-if="p == 'notification-write'">{{ $t('notification-write') }}</li>
|
||||
<li :key="p">{{ $t(`@.permissions.${p}`) }}</li>
|
||||
</template>
|
||||
</ul>
|
||||
</section>
|
||||
|
@@ -45,15 +45,9 @@ export default function <T extends object>(data: {
|
||||
this.$watch('props', () => {
|
||||
this.mergeProps();
|
||||
});
|
||||
|
||||
this.bakeProps();
|
||||
},
|
||||
|
||||
methods: {
|
||||
bakeProps() {
|
||||
this.bakedOldProps = JSON.stringify(this.props);
|
||||
},
|
||||
|
||||
mergeProps() {
|
||||
if (data.props) {
|
||||
const defaultProps = data.props();
|
||||
@@ -65,17 +59,10 @@ export default function <T extends object>(data: {
|
||||
},
|
||||
|
||||
save() {
|
||||
if (this.bakedOldProps == JSON.stringify(this.props)) return;
|
||||
|
||||
this.bakeProps();
|
||||
|
||||
if (this.platform == 'deck') {
|
||||
this.$store.commit('device/updateDeckColumn', this.column);
|
||||
} else {
|
||||
this.$root.api('i/update_widget', {
|
||||
id: this.id,
|
||||
data: this.props
|
||||
});
|
||||
this.$store.commit('device/updateWidget', this.widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
31
src/client/app/common/scripts/gen-search-query.ts
Normal file
31
src/client/app/common/scripts/gen-search-query.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import parseAcct from '../../../../misc/acct/parse';
|
||||
import { host as localHost } from '../../config';
|
||||
|
||||
export async function genSearchQuery(v: any, q: string) {
|
||||
let host: string;
|
||||
let userId: string;
|
||||
if (q.split(' ').some(x => x.startsWith('@'))) {
|
||||
for (const at of q.split(' ').filter(x => x.startsWith('@')).map(x => x.substr(1))) {
|
||||
if (at.includes('.')) {
|
||||
if (at === localHost || at === '.') {
|
||||
host = null;
|
||||
} else {
|
||||
host = at;
|
||||
}
|
||||
} else {
|
||||
const user = await v.$root.api('users/show', parseAcct(at)).catch(x => null);
|
||||
if (user) {
|
||||
userId = user.id;
|
||||
} else {
|
||||
// todo: show error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return {
|
||||
query: q.split(' ').filter(x => !x.startsWith('/') && !x.startsWith('@')).join(' '),
|
||||
host: host,
|
||||
userId: userId
|
||||
};
|
||||
}
|
@@ -70,8 +70,8 @@ export default (opts: Opts = {}) => ({
|
||||
},
|
||||
|
||||
reactionsCount(): number {
|
||||
return this.appearNote.reactionCounts
|
||||
? sum(Object.values(this.appearNote.reactionCounts))
|
||||
return this.appearNote.reactions
|
||||
? sum(Object.values(this.appearNote.reactions))
|
||||
: 0;
|
||||
},
|
||||
|
||||
@@ -134,7 +134,7 @@ export default (opts: Opts = {}) => ({
|
||||
},
|
||||
|
||||
reactDirectly(reaction) {
|
||||
(this.$root.api('notes/reactions/create', {
|
||||
this.$root.api('notes/reactions/create', {
|
||||
noteId: this.appearNote.id,
|
||||
reaction: reaction
|
||||
});
|
||||
|
@@ -87,16 +87,16 @@ export default prop => ({
|
||||
case 'reacted': {
|
||||
const reaction = body.reaction;
|
||||
|
||||
if (this.$_ns_target.reactionCounts == null) {
|
||||
Vue.set(this.$_ns_target, 'reactionCounts', {});
|
||||
if (this.$_ns_target.reactions == null) {
|
||||
Vue.set(this.$_ns_target, 'reactions', {});
|
||||
}
|
||||
|
||||
if (this.$_ns_target.reactionCounts[reaction] == null) {
|
||||
Vue.set(this.$_ns_target.reactionCounts, reaction, 0);
|
||||
if (this.$_ns_target.reactions[reaction] == null) {
|
||||
Vue.set(this.$_ns_target.reactions, reaction, 0);
|
||||
}
|
||||
|
||||
// Increment the count
|
||||
this.$_ns_target.reactionCounts[reaction]++;
|
||||
this.$_ns_target.reactions[reaction]++;
|
||||
|
||||
if (body.userId == this.$store.state.i.id) {
|
||||
Vue.set(this.$_ns_target, 'myReaction', reaction);
|
||||
@@ -107,16 +107,16 @@ export default prop => ({
|
||||
case 'unreacted': {
|
||||
const reaction = body.reaction;
|
||||
|
||||
if (this.$_ns_target.reactionCounts == null) {
|
||||
if (this.$_ns_target.reactions == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.$_ns_target.reactionCounts[reaction] == null) {
|
||||
if (this.$_ns_target.reactions[reaction] == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Decrement the count
|
||||
if (this.$_ns_target.reactionCounts[reaction] > 0) this.$_ns_target.reactionCounts[reaction]--;
|
||||
if (this.$_ns_target.reactions[reaction] > 0) this.$_ns_target.reactions[reaction]--;
|
||||
|
||||
if (body.userId == this.$store.state.i.id) {
|
||||
Vue.set(this.$_ns_target, 'myReaction', null);
|
||||
@@ -125,9 +125,11 @@ export default prop => ({
|
||||
}
|
||||
|
||||
case 'pollVoted': {
|
||||
if (body.userId == this.$store.state.i.id) return;
|
||||
const choice = body.choice;
|
||||
this.$_ns_target.poll.choices.find(c => c.id === choice).votes++;
|
||||
this.$_ns_target.poll.choices[choice].votes++;
|
||||
if (body.userId == this.$store.state.i.id) {
|
||||
Vue.set(this.$_ns_target.poll.choices[choice], 'isVoted', true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -135,7 +137,6 @@ export default prop => ({
|
||||
Vue.set(this.$_ns_target, 'deletedAt', body.deletedAt);
|
||||
Vue.set(this.$_ns_target, 'renote', null);
|
||||
this.$_ns_target.text = null;
|
||||
this.$_ns_target.tags = [];
|
||||
this.$_ns_target.fileIds = [];
|
||||
this.$_ns_target.poll = null;
|
||||
this.$_ns_target.geo = null;
|
||||
|
64
src/client/app/common/scripts/search.ts
Normal file
64
src/client/app/common/scripts/search.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { faHistory } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
export async function search(v: any, q: string) {
|
||||
q = q.trim();
|
||||
|
||||
if (q.startsWith('@') && !q.includes(' ')) {
|
||||
v.$router.push(`/${q}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (q.startsWith('#')) {
|
||||
v.$router.push(`/tags/${encodeURIComponent(q.substr(1))}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// like 2018/03/12
|
||||
if (/^[0-9]{4}\/[0-9]{2}\/[0-9]{2}/.test(q.replace(/-/g, '/'))) {
|
||||
const date = new Date(q.replace(/-/g, '/'));
|
||||
|
||||
// 日付しか指定されてない場合、例えば 2018/03/12 ならユーザーは
|
||||
// 2018/03/12 のコンテンツを「含む」結果になることを期待するはずなので
|
||||
// 23時間59分進める(そのままだと 2018/03/12 00:00:00 「まで」の
|
||||
// 結果になってしまい、2018/03/12 のコンテンツは含まれない)
|
||||
if (q.replace(/-/g, '/').match(/^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$/)) {
|
||||
date.setHours(23, 59, 59, 999);
|
||||
}
|
||||
|
||||
v.$root.$emit('warp', date);
|
||||
v.$root.dialog({
|
||||
icon: faHistory,
|
||||
splash: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (q.startsWith('https://')) {
|
||||
const dialog = v.$root.dialog({
|
||||
type: 'waiting',
|
||||
text: v.$t('@.fetching-as-ap-object'),
|
||||
showOkButton: false,
|
||||
showCancelButton: false,
|
||||
cancelableByBgClick: false
|
||||
});
|
||||
|
||||
try {
|
||||
const res = await v.$root.api('ap/show', {
|
||||
uri: q
|
||||
});
|
||||
dialog.close();
|
||||
if (res.type == 'User') {
|
||||
v.$router.push(`/@${res.object.username}@${res.object.host}`);
|
||||
} else if (res.type == 'Note') {
|
||||
v.$router.push(`/notes/${res.object.id}`);
|
||||
}
|
||||
} catch (e) {
|
||||
dialog.close();
|
||||
// TODO: Show error
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
v.$router.push(`/search?q=${encodeURIComponent(q)}`);
|
||||
}
|
@@ -69,7 +69,7 @@ export default Vue.extend({
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '90%'
|
||||
columnWidth: '80%'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<li v-for="user in users" @click="complete(type, user)" @keydown="onKeydown" tabindex="-1">
|
||||
<img class="avatar" :src="user.avatarUrl" alt=""/>
|
||||
<span class="name">
|
||||
<mk-user-name :user="user"/>
|
||||
<mk-user-name :user="user" :key="user.id"/>
|
||||
</span>
|
||||
<span class="username">@{{ user | acct }}</span>
|
||||
</li>
|
||||
@@ -30,6 +30,7 @@
|
||||
import Vue from 'vue';
|
||||
import * as emojilib from 'emojilib';
|
||||
import contains from '../../../common/scripts/contains';
|
||||
import { twemojiBase } from '../../../../../misc/twemoji-base';
|
||||
|
||||
type EmojiDef = {
|
||||
emoji: string;
|
||||
@@ -54,7 +55,7 @@ const emjdb: EmojiDef[] = lib.map((x: any) => ({
|
||||
emoji: x[1].char,
|
||||
name: x[0],
|
||||
aliasOf: null,
|
||||
url: `https://twemoji.maxcdn.com/2/svg/${char2file(x[1].char)}.svg`
|
||||
url: `${twemojiBase}/2/svg/${char2file(x[1].char)}.svg`
|
||||
}));
|
||||
|
||||
for (const x of lib as any) {
|
||||
@@ -64,7 +65,7 @@ for (const x of lib as any) {
|
||||
emoji: x[1].char,
|
||||
name: k,
|
||||
aliasOf: x[0],
|
||||
url: `https://twemoji.maxcdn.com/2/svg/${char2file(x[1].char)}.svg`
|
||||
url: `${twemojiBase}/2/svg/${char2file(x[1].char)}.svg`
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -55,11 +55,7 @@ export default Vue.extend({
|
||||
},
|
||||
icon(): any {
|
||||
return {
|
||||
backgroundColor: this.lightmode
|
||||
? `rgb(${this.user.avatarColor.slice(0, 3).join(',')})`
|
||||
: this.user.avatarColor && this.user.avatarColor.length == 3
|
||||
? `rgb(${this.user.avatarColor.join(',')})`
|
||||
: null,
|
||||
backgroundColor: this.user.avatarColor,
|
||||
backgroundImage: this.lightmode ? null : `url(${this.url})`,
|
||||
borderRadius: this.$store.state.settings.circleIcons ? '100%' : null
|
||||
};
|
||||
@@ -67,7 +63,7 @@ export default Vue.extend({
|
||||
},
|
||||
mounted() {
|
||||
if (this.user.avatarColor) {
|
||||
this.$el.style.color = `rgb(${this.user.avatarColor.slice(0, 3).join(',')})`;
|
||||
this.$el.style.color = this.user.avatarColor;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -82,6 +78,7 @@ export default Vue.extend({
|
||||
.mk-avatar
|
||||
display inline-block
|
||||
vertical-align bottom
|
||||
flex-shrink 0
|
||||
|
||||
&:not(.cat)
|
||||
overflow hidden
|
||||
|
@@ -6,7 +6,17 @@
|
||||
<mk-signin/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="icon" v-if="!input && !select && !user" :class="type"><fa :icon="icon"/></div>
|
||||
<div class="icon" v-if="icon">
|
||||
<fa :icon="icon"/>
|
||||
</div>
|
||||
<div class="icon" v-else-if="!input && !select && !user" :class="type">
|
||||
<fa icon="check" v-if="type === 'success'"/>
|
||||
<fa :icon="faTimesCircle" v-if="type === 'error'"/>
|
||||
<fa icon="exclamation-triangle" v-if="type === 'warning'"/>
|
||||
<fa icon="info-circle" v-if="type === 'info'"/>
|
||||
<fa :icon="faQuestionCircle" v-if="type === 'question'"/>
|
||||
<fa icon="spinner" pulse v-if="type === 'waiting'"/>
|
||||
</div>
|
||||
<header v-if="title" v-html="title"></header>
|
||||
<div class="body" v-if="text" v-html="text"></div>
|
||||
<ui-input v-if="input" v-model="inputValue" autofocus :type="input.type || 'text'" :placeholder="input.placeholder" @keydown="onInputKeydown"></ui-input>
|
||||
@@ -14,8 +24,8 @@
|
||||
<ui-select v-if="select" v-model="selectedValue" autofocus>
|
||||
<option v-for="item in select.items" :value="item.value">{{ item.text }}</option>
|
||||
</ui-select>
|
||||
<ui-horizon-group no-grow class="buttons fit-bottom" v-if="!splash">
|
||||
<ui-button @click="ok" primary :autofocus="!input && !select && !user">{{ (showCancelButton || input || select || user) ? $t('@.ok') : $t('@.got-it') }}</ui-button>
|
||||
<ui-horizon-group no-grow class="buttons fit-bottom" v-if="!splash && (showOkButton || showCancelButton)">
|
||||
<ui-button @click="ok" v-if="showOkButton" primary :autofocus="!input && !select && !user">{{ (showCancelButton || input || select || user) ? $t('@.ok') : $t('@.got-it') }}</ui-button>
|
||||
<ui-button @click="cancel" v-if="showCancelButton || input || select || user">{{ $t('@.cancel') }}</ui-button>
|
||||
</ui-horizon-group>
|
||||
</template>
|
||||
@@ -55,10 +65,21 @@ export default Vue.extend({
|
||||
user: {
|
||||
required: false
|
||||
},
|
||||
icon: {
|
||||
required: false
|
||||
},
|
||||
showOkButton: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showCancelButton: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
cancelableByBgClick: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
splash: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
@@ -69,22 +90,11 @@ export default Vue.extend({
|
||||
return {
|
||||
inputValue: this.input && this.input.default ? this.input.default : null,
|
||||
userInputValue: null,
|
||||
selectedValue: null
|
||||
selectedValue: null,
|
||||
faTimesCircle, faQuestionCircle
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
icon(): any {
|
||||
switch (this.type) {
|
||||
case 'success': return 'check';
|
||||
case 'error': return faTimesCircle;
|
||||
case 'warning': return 'exclamation-triangle';
|
||||
case 'info': return 'info-circle';
|
||||
case 'question': return faQuestionCircle;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
(this.$refs.bg as any).style.pointerEvents = 'auto';
|
||||
@@ -113,6 +123,8 @@ export default Vue.extend({
|
||||
|
||||
methods: {
|
||||
async ok() {
|
||||
if (!this.showOkButton) return;
|
||||
|
||||
if (this.user) {
|
||||
const user = await this.$root.api('users/show', parseAcct(this.userInputValue));
|
||||
if (user) {
|
||||
@@ -156,7 +168,9 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
onBgClick() {
|
||||
this.cancel();
|
||||
if (this.cancelableByBgClick) {
|
||||
this.cancel();
|
||||
}
|
||||
},
|
||||
|
||||
onInputKeydown(e) {
|
||||
@@ -183,9 +197,6 @@ export default Vue.extend({
|
||||
height 100%
|
||||
|
||||
&.splash
|
||||
&, *
|
||||
pointer-events none !important
|
||||
|
||||
> .main
|
||||
min-width 0
|
||||
width initial
|
||||
@@ -243,7 +254,7 @@ export default Vue.extend({
|
||||
margin-top 8px
|
||||
|
||||
> .body
|
||||
margin 16px 0
|
||||
margin 16px 0 0 0
|
||||
|
||||
> .buttons
|
||||
margin-top 16px
|
||||
|
183
src/client/app/common/views/components/drive-file-thumbnail.vue
Normal file
183
src/client/app/common/views/components/drive-file-thumbnail.vue
Normal file
@@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<div class="zdjebgpv" :class="{ detail }" ref="thumbnail" :style="`background-color: ${ background }`">
|
||||
<img
|
||||
:src="file.url"
|
||||
:alt="file.name"
|
||||
:title="file.name"
|
||||
@load="onThumbnailLoaded"
|
||||
v-if="detail && is === 'image'"/>
|
||||
<video
|
||||
:src="file.url"
|
||||
ref="volumectrl"
|
||||
preload="metadata"
|
||||
controls
|
||||
v-else-if="detail && is === 'video'"/>
|
||||
<img :src="file.thumbnailUrl" alt="" @load="onThumbnailLoaded" :style="`object-fit: ${ fit }`" v-else-if="isThumbnailAvailable"/>
|
||||
<fa :icon="faFileImage" class="icon" v-else-if="is === 'image'"/>
|
||||
<fa :icon="faFileVideo" class="icon" v-else-if="is === 'video'"/>
|
||||
|
||||
<audio
|
||||
:src="file.url"
|
||||
ref="volumectrl"
|
||||
preload="metadata"
|
||||
controls
|
||||
v-else-if="detail && is === 'audio'"/>
|
||||
<fa :icon="faMusic" class="icon" v-else-if="is === 'audio' || is === 'midi'"/>
|
||||
|
||||
<fa :icon="faFileCsv" class="icon" v-else-if="is === 'csv'"/>
|
||||
<fa :icon="faFilePdf" class="icon" v-else-if="is === 'pdf'"/>
|
||||
<fa :icon="faFileAlt" class="icon" v-else-if="is === 'textfile'"/>
|
||||
<fa :icon="faFileArchive" class="icon" v-else-if="is === 'archive'"/>
|
||||
<fa :icon="faFile" class="icon" v-else/>
|
||||
|
||||
<fa :icon="faFilm" class="icon-sub" v-if="!detail && isThumbnailAvailable && is === 'video'"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import anime from 'animejs';
|
||||
import {
|
||||
faFile,
|
||||
faFileAlt,
|
||||
faFileImage,
|
||||
faMusic,
|
||||
faFileVideo,
|
||||
faFileCsv,
|
||||
faFilePdf,
|
||||
faFileArchive,
|
||||
faFilm
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
file: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
fit: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
detail: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isContextmenuShowing: false,
|
||||
isDragging: false,
|
||||
|
||||
faFile,
|
||||
faFileAlt,
|
||||
faFileImage,
|
||||
faMusic,
|
||||
faFileVideo,
|
||||
faFileCsv,
|
||||
faFilePdf,
|
||||
faFileArchive,
|
||||
faFilm
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
is(): 'image' | 'video' | 'midi' | 'audio' | 'csv' | 'pdf' | 'textfile' | 'archive' | 'unknown' {
|
||||
if (this.file.type.startsWith('image/')) return 'image';
|
||||
if (this.file.type.startsWith('video/')) return 'video';
|
||||
if (this.file.type === 'audio/midi') return 'midi';
|
||||
if (this.file.type.startsWith('audio/')) return 'audio';
|
||||
if (this.file.type.endsWith('/csv')) return 'csv';
|
||||
if (this.file.type.endsWith('/pdf')) return 'pdf';
|
||||
if (this.file.type.startsWith('text/')) return 'textfile';
|
||||
if ([
|
||||
"application/zip",
|
||||
"application/x-cpio",
|
||||
"application/x-bzip",
|
||||
"application/x-bzip2",
|
||||
"application/java-archive",
|
||||
"application/x-rar-compressed",
|
||||
"application/x-tar",
|
||||
"application/gzip",
|
||||
"application/x-7z-compressed"
|
||||
].some(e => e === this.file.type)) return 'archive';
|
||||
return 'unknown';
|
||||
},
|
||||
isThumbnailAvailable(): boolean {
|
||||
return this.file.thumbnailUrl
|
||||
? (this.is === 'image' || this.is === 'video')
|
||||
: false;
|
||||
},
|
||||
background(): string {
|
||||
return this.file.properties.avgColor || 'transparent';
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const audioTag = this.$refs.volumectrl as HTMLAudioElement;
|
||||
if (audioTag) audioTag.volume = this.$store.state.device.mediaVolume;
|
||||
},
|
||||
methods: {
|
||||
onThumbnailLoaded() {
|
||||
if (this.file.properties.avgColor) {
|
||||
anime({
|
||||
targets: this.$refs.thumbnail,
|
||||
backgroundColor: 'transparent', // TODO fade
|
||||
duration: 100,
|
||||
easing: 'linear'
|
||||
});
|
||||
}
|
||||
},
|
||||
volumechange() {
|
||||
const audioTag = this.$refs.volumectrl as HTMLAudioElement;
|
||||
this.$store.commit('device/set', { key: 'mediaVolume', value: audioTag.volume });
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.zdjebgpv
|
||||
display flex
|
||||
|
||||
> img,
|
||||
> .icon
|
||||
pointer-events none
|
||||
|
||||
> .icon-sub
|
||||
position absolute
|
||||
width 30%
|
||||
height auto
|
||||
margin 0
|
||||
right 4%
|
||||
bottom 4%
|
||||
|
||||
> *
|
||||
margin auto
|
||||
|
||||
&:not(.detail)
|
||||
> img
|
||||
height 100%
|
||||
width 100%
|
||||
object-fit cover
|
||||
|
||||
> .icon
|
||||
height 65%
|
||||
width 65%
|
||||
|
||||
> video,
|
||||
> audio
|
||||
width 100%
|
||||
|
||||
&.detail
|
||||
> .icon
|
||||
height 100px
|
||||
width 100px
|
||||
margin 16px
|
||||
|
||||
> *:not(.icon)
|
||||
max-height 300px
|
||||
max-width 100%
|
||||
height 100%
|
||||
object-fit contain
|
||||
|
||||
</style>
|
@@ -3,32 +3,31 @@
|
||||
<header>
|
||||
<button v-for="category in categories"
|
||||
:title="category.text"
|
||||
@click="go(category.ref)"
|
||||
@click="go(category)"
|
||||
:class="{ active: category.isActive }"
|
||||
>
|
||||
<fa :icon="category.icon" fixed-width/>
|
||||
</button>
|
||||
</header>
|
||||
<div class="emojis" ref="emojis" @scroll.passive="onScroll">
|
||||
<section v-for="category in categories" :ref="category.ref">
|
||||
<header><fa :icon="category.icon" fixed-width/> {{ category.text }}</header>
|
||||
<div v-if="category.name">
|
||||
<button v-for="emoji in Object.entries(lib).filter(([k, v]) => v.category === category.name)"
|
||||
:title="emoji[0]"
|
||||
@click="chosen(emoji[1].char)"
|
||||
>
|
||||
<mk-emoji :emoji="emoji[1].char"/>
|
||||
</button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<button v-for="emoji in customEmojis"
|
||||
:title="emoji.name"
|
||||
@click="chosen(`:${emoji.name}:`)"
|
||||
>
|
||||
<img :src="emoji.url" :alt="emoji.name"/>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
<div class="emojis">
|
||||
<header><fa :icon="categories.find(x => x.isActive).icon" fixed-width/> {{ categories.find(x => x.isActive).text }}</header>
|
||||
<div v-if="categories.find(x => x.isActive).name">
|
||||
<button v-for="emoji in Object.entries(lib).filter(([k, v]) => v.category === categories.find(x => x.isActive).name)"
|
||||
:title="emoji[0]"
|
||||
@click="chosen(emoji[1].char)"
|
||||
:key="emoji[0]"
|
||||
>
|
||||
<mk-emoji :emoji="emoji[1].char"/>
|
||||
</button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<button v-for="emoji in customEmojis"
|
||||
:title="emoji.name"
|
||||
@click="chosen(`:${emoji.name}:`)"
|
||||
>
|
||||
<img :src="emoji.url" :alt="emoji.name"/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -48,55 +47,46 @@ export default Vue.extend({
|
||||
lib,
|
||||
customEmojis: [],
|
||||
categories: [{
|
||||
ref: 'customEmojiSection',
|
||||
text: this.$t('custom-emoji'),
|
||||
icon: faAsterisk,
|
||||
isActive: true
|
||||
}, {
|
||||
name: 'people',
|
||||
ref: 'peopleSection',
|
||||
text: this.$t('people'),
|
||||
icon: ['far', 'laugh'],
|
||||
isActive: false
|
||||
}, {
|
||||
name: 'animals_and_nature',
|
||||
ref: 'animalsAndNatureSection',
|
||||
text: this.$t('animals-and-nature'),
|
||||
icon: faLeaf,
|
||||
isActive: false
|
||||
}, {
|
||||
name: 'food_and_drink',
|
||||
ref: 'foodAndDrinkSection',
|
||||
text: this.$t('food-and-drink'),
|
||||
icon: faUtensils,
|
||||
isActive: false
|
||||
}, {
|
||||
name: 'activity',
|
||||
ref: 'activitySection',
|
||||
text: this.$t('activity'),
|
||||
icon: faFutbol,
|
||||
isActive: false
|
||||
}, {
|
||||
name: 'travel_and_places',
|
||||
ref: 'travelAndPlacesSection',
|
||||
text: this.$t('travel-and-places'),
|
||||
icon: faCity,
|
||||
isActive: false
|
||||
}, {
|
||||
name: 'objects',
|
||||
ref: 'objectsSection',
|
||||
text: this.$t('objects'),
|
||||
icon: faDice,
|
||||
isActive: false
|
||||
}, {
|
||||
name: 'symbols',
|
||||
ref: 'symbolsSection',
|
||||
text: this.$t('symbols'),
|
||||
icon: faHeart,
|
||||
isActive: false
|
||||
}, {
|
||||
name: 'flags',
|
||||
ref: 'flagsSection',
|
||||
text: this.$t('flags'),
|
||||
icon: faFlag,
|
||||
isActive: false
|
||||
@@ -109,15 +99,9 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
methods: {
|
||||
go(ref) {
|
||||
this.$refs.emojis.scrollTop = this.$refs[ref][0].offsetTop;
|
||||
},
|
||||
|
||||
onScroll(e) {
|
||||
for (const x of this.categories) {
|
||||
const top = e.target.scrollTop;
|
||||
const el = this.$refs[x.ref][0];
|
||||
x.isActive = el.offsetTop <= top && el.offsetTop + el.offsetHeight > top;
|
||||
go(category) {
|
||||
for (const c of this.categories) {
|
||||
c.isActive = c.name === category.name;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -156,47 +140,46 @@ export default Vue.extend({
|
||||
overflow-y auto
|
||||
overflow-x hidden
|
||||
|
||||
> section
|
||||
> header
|
||||
position sticky
|
||||
top 0
|
||||
left 0
|
||||
z-index 1
|
||||
padding 8px
|
||||
background var(--faceHeader)
|
||||
color var(--text)
|
||||
font-size 12px
|
||||
> header
|
||||
position sticky
|
||||
top 0
|
||||
left 0
|
||||
z-index 1
|
||||
padding 8px
|
||||
background var(--faceHeader)
|
||||
color var(--text)
|
||||
font-size 12px
|
||||
|
||||
> div
|
||||
display grid
|
||||
grid-template-columns 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr
|
||||
gap 4px
|
||||
padding 8px
|
||||
> div
|
||||
display grid
|
||||
grid-template-columns 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr
|
||||
gap 4px
|
||||
padding 8px
|
||||
|
||||
> button
|
||||
padding 0
|
||||
width 100%
|
||||
> button
|
||||
padding 0
|
||||
width 100%
|
||||
|
||||
&:before
|
||||
content ''
|
||||
display block
|
||||
width 1px
|
||||
height 0
|
||||
padding-bottom 100%
|
||||
|
||||
&:hover
|
||||
> *
|
||||
transform scale(1.2)
|
||||
transition transform 0s
|
||||
&:before
|
||||
content ''
|
||||
display block
|
||||
width 1px
|
||||
height 0
|
||||
padding-bottom 100%
|
||||
|
||||
&:hover
|
||||
> *
|
||||
position absolute
|
||||
top 0
|
||||
left 0
|
||||
width 100%
|
||||
height 100%
|
||||
font-size 28px
|
||||
transition transform 0.2s ease
|
||||
pointer-events none
|
||||
transform scale(1.2)
|
||||
transition transform 0s
|
||||
|
||||
> *
|
||||
position absolute
|
||||
top 0
|
||||
left 0
|
||||
width 100%
|
||||
height 100%
|
||||
font-size 28px
|
||||
transition transform 0.2s ease
|
||||
pointer-events none
|
||||
|
||||
</style>
|
||||
|
@@ -10,6 +10,7 @@ import Vue from 'vue';
|
||||
// スクリプトサイズがデカい
|
||||
//import { lib } from 'emojilib';
|
||||
import { getStaticImageUrl } from '../../../common/scripts/get-static-image-url';
|
||||
import { twemojiBase } from '../../../../../misc/twemoji-base';
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
@@ -29,7 +30,11 @@ export default Vue.extend({
|
||||
customEmojis: {
|
||||
required: false,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
isReaction: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
@@ -46,7 +51,7 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
useOsDefaultEmojis(): boolean {
|
||||
return this.$store.state.device.useOsDefaultEmojis;
|
||||
return this.$store.state.device.useOsDefaultEmojis && !this.isReaction;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -73,7 +78,7 @@ export default Vue.extend({
|
||||
if (!codes.includes('200d')) codes = codes.filter(x => x != 'fe0f');
|
||||
codes = codes.filter(x => x && x.length);
|
||||
|
||||
this.url = `https://twemoji.maxcdn.com/2/svg/${codes.join('-')}.svg`;
|
||||
this.url = `${twemojiBase}/2/svg/${codes.join('-')}.svg`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<a class="a" href="https://github.com/syuilo/misskey" target="_blank" title="View source on GitHub">
|
||||
<a class="a" :href="repositoryUrl" target="_blank" title="View source on GitHub">
|
||||
<svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="aria-hidden">
|
||||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
|
||||
<path class="octo-arm" d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor"></path>
|
||||
@@ -8,9 +8,19 @@
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
return {
|
||||
repositoryUrl: 'https://github.com/syuilo/misskey'
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
|
||||
|
||||
.a
|
||||
display block
|
||||
|
||||
|
@@ -5,17 +5,17 @@
|
||||
|
||||
<div style="overflow: hidden; line-height: 28px;">
|
||||
<p class="turn" v-if="!iAmPlayer && !game.isEnded">
|
||||
<mfm :text="$t('@.reversi.turn-of', { name: $options.filters.userName(turnUser) })" :should-break="false" :plain-text="true" :custom-emojis="turnUser.emojis"/>
|
||||
<mfm :key="'turn:' + $options.filters.userName(turnUser)" :text="$t('@.reversi.turn-of', { name: $options.filters.userName(turnUser) })" :should-break="false" :plain-text="true" :custom-emojis="turnUser.emojis"/>
|
||||
<mk-ellipsis/>
|
||||
</p>
|
||||
<p class="turn" v-if="logPos != logs.length">
|
||||
<mfm :text="$t('@.reversi.past-turn-of', { name: $options.filters.userName(turnUser) })" :should-break="false" :plain-text="true" :custom-emojis="turnUser.emojis"/>
|
||||
<mfm :key="'past-turn-of:' + $options.filters.userName(turnUser)" :text="$t('@.reversi.past-turn-of', { name: $options.filters.userName(turnUser) })" :should-break="false" :plain-text="true" :custom-emojis="turnUser.emojis"/>
|
||||
</p>
|
||||
<p class="turn1" v-if="iAmPlayer && !game.isEnded && !isMyTurn">{{ $t('@.reversi.opponent-turn') }}<mk-ellipsis/></p>
|
||||
<p class="turn2" v-if="iAmPlayer && !game.isEnded && isMyTurn" v-animate-css="{ classes: 'tada', iteration: 'infinite' }">{{ $t('@.reversi.my-turn') }}</p>
|
||||
<p class="result" v-if="game.isEnded && logPos == logs.length">
|
||||
<template v-if="game.winner">
|
||||
<mfm :text="$t('@.reversi.won', { name: $options.filters.userName(game.winner) })" :should-break="false" :plain-text="true" :custom-emojis="game.winner.emojis"/>
|
||||
<mfm :key="'won'" :text="$t('@.reversi.won', { name: $options.filters.userName(game.winner) })" :should-break="false" :plain-text="true" :custom-emojis="game.winner.emojis"/>
|
||||
<span v-if="game.surrendered != null"> ({{ $t('surrendered') }})</span>
|
||||
</template>
|
||||
<template v-else>{{ $t('@.reversi.drawn') }}</template>
|
||||
@@ -24,11 +24,11 @@
|
||||
|
||||
<div class="board">
|
||||
<div class="labels-x" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
|
||||
<span v-for="i in game.settings.map[0].length">{{ String.fromCharCode(64 + i) }}</span>
|
||||
<span v-for="i in game.map[0].length">{{ String.fromCharCode(64 + i) }}</span>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="labels-y" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
|
||||
<div v-for="i in game.settings.map.length">{{ i }}</div>
|
||||
<div v-for="i in game.map.length">{{ i }}</div>
|
||||
</div>
|
||||
<div class="cells" :style="cellsStyle">
|
||||
<div v-for="(stone, i) in o.board"
|
||||
@@ -46,11 +46,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="labels-y" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
|
||||
<div v-for="i in game.settings.map.length">{{ i }}</div>
|
||||
<div v-for="i in game.map.length">{{ i }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="labels-x" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
|
||||
<span v-for="i in game.settings.map[0].length">{{ String.fromCharCode(64 + i) }}</span>
|
||||
<span v-for="i in game.map[0].length">{{ String.fromCharCode(64 + i) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -71,9 +71,9 @@
|
||||
</div>
|
||||
|
||||
<div class="info">
|
||||
<p v-if="game.settings.isLlotheo">{{ $t('is-llotheo') }}</p>
|
||||
<p v-if="game.settings.loopedBoard">{{ $t('looped-map') }}</p>
|
||||
<p v-if="game.settings.canPutEverywhere">{{ $t('can-put-everywhere') }}</p>
|
||||
<p v-if="game.isLlotheo">{{ $t('is-llotheo') }}</p>
|
||||
<p v-if="game.loopedBoard">{{ $t('looped-map') }}</p>
|
||||
<p v-if="game.canPutEverywhere">{{ $t('can-put-everywhere') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -160,8 +160,8 @@ export default Vue.extend({
|
||||
|
||||
cellsStyle(): any {
|
||||
return {
|
||||
'grid-template-rows': `repeat(${this.game.settings.map.length}, 1fr)`,
|
||||
'grid-template-columns': `repeat(${this.game.settings.map[0].length}, 1fr)`
|
||||
'grid-template-rows': `repeat(${this.game.map.length}, 1fr)`,
|
||||
'grid-template-columns': `repeat(${this.game.map[0].length}, 1fr)`
|
||||
};
|
||||
}
|
||||
},
|
||||
@@ -169,10 +169,10 @@ export default Vue.extend({
|
||||
watch: {
|
||||
logPos(v) {
|
||||
if (!this.game.isEnded) return;
|
||||
this.o = new Reversi(this.game.settings.map, {
|
||||
isLlotheo: this.game.settings.isLlotheo,
|
||||
canPutEverywhere: this.game.settings.canPutEverywhere,
|
||||
loopedBoard: this.game.settings.loopedBoard
|
||||
this.o = new Reversi(this.game.map, {
|
||||
isLlotheo: this.game.isLlotheo,
|
||||
canPutEverywhere: this.game.canPutEverywhere,
|
||||
loopedBoard: this.game.loopedBoard
|
||||
});
|
||||
for (const log of this.logs.slice(0, v)) {
|
||||
this.o.put(log.color, log.pos);
|
||||
@@ -184,10 +184,10 @@ export default Vue.extend({
|
||||
created() {
|
||||
this.game = this.initGame;
|
||||
|
||||
this.o = new Reversi(this.game.settings.map, {
|
||||
isLlotheo: this.game.settings.isLlotheo,
|
||||
canPutEverywhere: this.game.settings.canPutEverywhere,
|
||||
loopedBoard: this.game.settings.loopedBoard
|
||||
this.o = new Reversi(this.game.map, {
|
||||
isLlotheo: this.game.isLlotheo,
|
||||
canPutEverywhere: this.game.canPutEverywhere,
|
||||
loopedBoard: this.game.loopedBoard
|
||||
});
|
||||
|
||||
for (const log of this.game.logs) {
|
||||
@@ -286,10 +286,10 @@ export default Vue.extend({
|
||||
onRescue(game) {
|
||||
this.game = game;
|
||||
|
||||
this.o = new Reversi(this.game.settings.map, {
|
||||
isLlotheo: this.game.settings.isLlotheo,
|
||||
canPutEverywhere: this.game.settings.canPutEverywhere,
|
||||
loopedBoard: this.game.settings.loopedBoard
|
||||
this.o = new Reversi(this.game.map, {
|
||||
isLlotheo: this.game.isLlotheo,
|
||||
canPutEverywhere: this.game.canPutEverywhere,
|
||||
loopedBoard: this.game.loopedBoard
|
||||
});
|
||||
|
||||
for (const log of this.game.logs) {
|
||||
|
@@ -17,9 +17,9 @@
|
||||
</header>
|
||||
|
||||
<div>
|
||||
<div class="random" v-if="game.settings.map == null"><fa icon="dice"/></div>
|
||||
<div class="board" v-else :style="{ 'grid-template-rows': `repeat(${ game.settings.map.length }, 1fr)`, 'grid-template-columns': `repeat(${ game.settings.map[0].length }, 1fr)` }">
|
||||
<div v-for="(x, i) in game.settings.map.join('')"
|
||||
<div class="random" v-if="game.map == null"><fa icon="dice"/></div>
|
||||
<div class="board" v-else :style="{ 'grid-template-rows': `repeat(${ game.map.length }, 1fr)`, 'grid-template-columns': `repeat(${ game.map[0].length }, 1fr)` }">
|
||||
<div v-for="(x, i) in game.map.join('')"
|
||||
:data-none="x == ' '"
|
||||
@click="onPixelClick(i, x)">
|
||||
<fa v-if="x == 'b'" :icon="fasCircle"/>
|
||||
@@ -35,9 +35,9 @@
|
||||
</header>
|
||||
|
||||
<div>
|
||||
<form-radio v-model="game.settings.bw" value="random" @change="updateSettings">{{ $t('random') }}</form-radio>
|
||||
<form-radio v-model="game.settings.bw" :value="1" @change="updateSettings">{{ this.$t('black-is').split('{}')[0] }}<b><mk-user-name :user="game.user1"/></b>{{ this.$t('black-is').split('{}')[1] }}</form-radio>
|
||||
<form-radio v-model="game.settings.bw" :value="2" @change="updateSettings">{{ this.$t('black-is').split('{}')[0] }}<b><mk-user-name :user="game.user2"/></b>{{ this.$t('black-is').split('{}')[1] }}</form-radio>
|
||||
<form-radio v-model="game.bw" value="random" @change="updateSettings('bw')">{{ $t('random') }}</form-radio>
|
||||
<form-radio v-model="game.bw" :value="1" @change="updateSettings('bw')">{{ this.$t('black-is').split('{}')[0] }}<b><mk-user-name :user="game.user1"/></b>{{ this.$t('black-is').split('{}')[1] }}</form-radio>
|
||||
<form-radio v-model="game.bw" :value="2" @change="updateSettings('bw')">{{ this.$t('black-is').split('{}')[0] }}<b><mk-user-name :user="game.user2"/></b>{{ this.$t('black-is').split('{}')[1] }}</form-radio>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -47,9 +47,9 @@
|
||||
</header>
|
||||
|
||||
<div>
|
||||
<ui-switch v-model="game.settings.isLlotheo" @change="updateSettings">{{ $t('is-llotheo') }}</ui-switch>
|
||||
<ui-switch v-model="game.settings.loopedBoard" @change="updateSettings">{{ $t('looped-map') }}</ui-switch>
|
||||
<ui-switch v-model="game.settings.canPutEverywhere" @change="updateSettings">{{ $t('can-put-everywhere') }}</ui-switch>
|
||||
<ui-switch v-model="game.isLlotheo" @change="updateSettings('isLlotheo')">{{ $t('is-llotheo') }}</ui-switch>
|
||||
<ui-switch v-model="game.loopedBoard" @change="updateSettings('loopedBoard')">{{ $t('looped-map') }}</ui-switch>
|
||||
<ui-switch v-model="game.canPutEverywhere" @change="updateSettings('canPutEverywhere')">{{ $t('can-put-everywhere') }}</ui-switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -159,8 +159,8 @@ export default Vue.extend({
|
||||
this.connection.on('initForm', this.onInitForm);
|
||||
this.connection.on('message', this.onMessage);
|
||||
|
||||
if (this.game.user1Id != this.$store.state.i.id && this.game.settings.form1) this.form = this.game.settings.form1;
|
||||
if (this.game.user2Id != this.$store.state.i.id && this.game.settings.form2) this.form = this.game.settings.form2;
|
||||
if (this.game.user1Id != this.$store.state.i.id && this.game.form1) this.form = this.game.form1;
|
||||
if (this.game.user2Id != this.$store.state.i.id && this.game.form2) this.form = this.game.form2;
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
@@ -189,18 +189,19 @@ export default Vue.extend({
|
||||
this.$forceUpdate();
|
||||
},
|
||||
|
||||
updateSettings() {
|
||||
updateSettings(key: string) {
|
||||
this.connection.send('updateSettings', {
|
||||
settings: this.game.settings
|
||||
key: key,
|
||||
value: this.game[key]
|
||||
});
|
||||
},
|
||||
|
||||
onUpdateSettings(settings) {
|
||||
this.game.settings = settings;
|
||||
if (this.game.settings.map == null) {
|
||||
onUpdateSettings({ key, value }) {
|
||||
this.game[key] = value;
|
||||
if (this.game.map == null) {
|
||||
this.mapName = null;
|
||||
} else {
|
||||
const found = Object.values(maps).find(x => x.data.join('') == this.game.settings.map.join(''));
|
||||
const found = Object.values(maps).find(x => x.data.join('') == this.game.map.join(''));
|
||||
this.mapName = found ? found.name : '-Custom-';
|
||||
}
|
||||
},
|
||||
@@ -224,27 +225,27 @@ export default Vue.extend({
|
||||
|
||||
onMapChange() {
|
||||
if (this.mapName == null) {
|
||||
this.game.settings.map = null;
|
||||
this.game.map = null;
|
||||
} else {
|
||||
this.game.settings.map = Object.values(maps).find(x => x.name == this.mapName).data;
|
||||
this.game.map = Object.values(maps).find(x => x.name == this.mapName).data;
|
||||
}
|
||||
this.$forceUpdate();
|
||||
this.updateSettings();
|
||||
},
|
||||
|
||||
onPixelClick(pos, pixel) {
|
||||
const x = pos % this.game.settings.map[0].length;
|
||||
const y = Math.floor(pos / this.game.settings.map[0].length);
|
||||
const x = pos % this.game.map[0].length;
|
||||
const y = Math.floor(pos / this.game.map[0].length);
|
||||
const newPixel =
|
||||
pixel == ' ' ? '-' :
|
||||
pixel == '-' ? 'b' :
|
||||
pixel == 'b' ? 'w' :
|
||||
' ';
|
||||
const line = this.game.settings.map[y].split('');
|
||||
const line = this.game.map[y].split('');
|
||||
line[x] = newPixel;
|
||||
this.$set(this.game.settings.map, y, line.join(''));
|
||||
this.$set(this.game.map, y, line.join(''));
|
||||
this.$forceUpdate();
|
||||
this.updateSettings();
|
||||
this.updateSettings('map');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -106,7 +106,7 @@ export default Vue.extend({
|
||||
async nav(game, actualNav = true) {
|
||||
if (this.selfNav) {
|
||||
// 受け取ったゲーム情報が省略されたものなら完全な情報を取得する
|
||||
if (game != null && (game.settings == null || game.settings.map == null)) {
|
||||
if (game != null && game.map == null) {
|
||||
game = await this.$root.api('games/reversi/games/show', {
|
||||
gameId: game.id
|
||||
});
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<div class="nhasjydimbopojusarffqjyktglcuxjy" v-if="meta">
|
||||
<div class="banner" :style="{ backgroundImage: meta.bannerUrl ? `url(${meta.bannerUrl})` : null }"></div>
|
||||
|
||||
<h1>{{ meta.name }}</h1>
|
||||
<h1>{{ meta.name || 'Misskey' }}</h1>
|
||||
<p v-html="meta.description || this.$t('@.about')"></p>
|
||||
<router-link to="/">{{ $t('start') }}</router-link>
|
||||
</div>
|
||||
|
@@ -52,7 +52,7 @@ export default Vue.extend({
|
||||
}
|
||||
|
||||
return {
|
||||
'background-color': this.image.properties.avgColor && this.image.properties.avgColor.length == 3 ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent',
|
||||
'background-color': this.image.properties.avgColor || 'transparent',
|
||||
'background-image': url
|
||||
};
|
||||
}
|
||||
|
@@ -33,10 +33,12 @@ export default Vue.extend({
|
||||
},
|
||||
computed: {
|
||||
canonical(): string {
|
||||
return `@${this.username}@${toUnicode(this.host)}`;
|
||||
return this.host === localHost ? `@${this.username}` : `@${this.username}@${toUnicode(this.host)}`;
|
||||
},
|
||||
isMe(): boolean {
|
||||
return this.$store.getters.isSignedIn && this.canonical.toLowerCase() === `@${this.$store.state.i.username}@${toUnicode(localHost)}`.toLowerCase();
|
||||
return this.$store.getters.isSignedIn && (
|
||||
`@${this.username}@${toUnicode(this.host)}` === `@${this.$store.state.i.username}@${toUnicode(localHost)}`.toLowerCase()
|
||||
);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@@ -85,7 +85,10 @@ export default Vue.extend({
|
||||
}
|
||||
} else {
|
||||
if (items[0].kind == 'file') {
|
||||
alert(this.$t('only-one-file-attached'));
|
||||
this.$root.dialog({
|
||||
type: 'error',
|
||||
text: this.$t('only-one-file-attached')
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -107,7 +110,10 @@ export default Vue.extend({
|
||||
return;
|
||||
} else if (e.dataTransfer.files.length > 1) {
|
||||
e.preventDefault();
|
||||
alert(this.$t('only-one-file-attached'));
|
||||
this.$root.dialog({
|
||||
type: 'error',
|
||||
text: this.$t('only-one-file-attached')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user