Compare commits

...

238 Commits

Author SHA1 Message Date
0fe0b6d254 10.26.0 2018-10-20 02:52:11 +09:00
b794216eaf Merge pull request #2940 from syuilo/l10n_develop
New Crowdin translations
2018-10-20 02:51:43 +09:00
1fccde38f6 デッキのキーボードショートカットを強化 2018-10-20 02:49:39 +09:00
41bd436d3e デッキのキーボードショートカットを強化 2018-10-20 02:40:37 +09:00
c66155ed48 Improve shortcut key detection 2018-10-20 01:45:31 +09:00
627bd410fa New translations ja-JP.yml (German) 2018-10-19 22:22:36 +09:00
41a3932c6b New translations ja-JP.yml (English) 2018-10-19 22:12:39 +09:00
785b8d7846 New translations ja-JP.yml (French) 2018-10-19 21:02:41 +09:00
622c8f9598 New translations ja-JP.yml (French) 2018-10-19 20:52:24 +09:00
ef978a6364 10.25.0 2018-10-19 15:07:46 +09:00
d95fbe1c6b fix(package): update reconnecting-websocket to version 4.1.10 (#2937) 2018-10-19 15:04:46 +09:00
d4ffddc2ab Merge pull request #2936 from syuilo/l10n_develop
New Crowdin translations
2018-10-19 15:04:36 +09:00
3d497cedfc デッキで'T'のショートカットを使えるように 2018-10-19 15:03:23 +09:00
e8de29ae79 Resolve #2935 2018-10-19 14:34:51 +09:00
b622946844 10.24.0 2018-10-19 11:14:27 +09:00
d013f78cc7 New translations ja-JP.yml (Norwegian) 2018-10-19 11:12:15 +09:00
2afbafdb3b New translations ja-JP.yml (Dutch) 2018-10-19 11:12:11 +09:00
67148114a8 New translations ja-JP.yml (Japanese, Kansai) 2018-10-19 11:12:05 +09:00
7903140ec2 New translations ja-JP.yml (Spanish) 2018-10-19 11:12:01 +09:00
cefd296200 New translations ja-JP.yml (Russian) 2018-10-19 11:11:55 +09:00
99d1c15851 New translations ja-JP.yml (Portuguese) 2018-10-19 11:11:51 +09:00
a3107ab26f New translations ja-JP.yml (Polish) 2018-10-19 11:11:46 +09:00
854cfae75b New translations ja-JP.yml (Korean) 2018-10-19 11:11:42 +09:00
36ab82957d New translations ja-JP.yml (Italian) 2018-10-19 11:11:36 +09:00
de9f54386c New translations ja-JP.yml (German) 2018-10-19 11:11:32 +09:00
7f43820765 New translations ja-JP.yml (French) 2018-10-19 11:11:28 +09:00
955e907e7f New translations ja-JP.yml (English) 2018-10-19 11:11:24 +09:00
4c18022e7d New translations ja-JP.yml (Chinese Simplified) 2018-10-19 11:11:20 +09:00
509f59e46d New translations ja-JP.yml (Catalan) 2018-10-19 11:11:16 +09:00
f14c372f5e Resolve #2719 2018-10-19 11:10:49 +09:00
f028800a96 10.23.1 2018-10-19 10:26:16 +09:00
8a1ce7a4f3 Merge pull request #2934 from syuilo/l10n_develop
New Crowdin translations
2018-10-19 10:25:19 +09:00
ea7a139ae0 New translations ja-JP.yml (English) 2018-10-19 10:21:31 +09:00
63959eb3da New translations ja-JP.yml (Norwegian) 2018-10-19 10:12:38 +09:00
a6adbc4e56 New translations ja-JP.yml (Dutch) 2018-10-19 10:12:33 +09:00
b418cb67ba New translations ja-JP.yml (Japanese, Kansai) 2018-10-19 10:12:29 +09:00
0ccc360c0a New translations ja-JP.yml (Spanish) 2018-10-19 10:12:24 +09:00
1e0dda3c40 New translations ja-JP.yml (Russian) 2018-10-19 10:12:20 +09:00
9197793bc8 New translations ja-JP.yml (Portuguese) 2018-10-19 10:12:16 +09:00
29f62241bc New translations ja-JP.yml (Polish) 2018-10-19 10:12:12 +09:00
8de1e91dec New translations ja-JP.yml (Korean) 2018-10-19 10:12:08 +09:00
de822a22d4 New translations ja-JP.yml (Italian) 2018-10-19 10:12:05 +09:00
f2cef456bd New translations ja-JP.yml (German) 2018-10-19 10:11:59 +09:00
5d681d0fd6 New translations ja-JP.yml (French) 2018-10-19 10:11:55 +09:00
2ed24ebd75 New translations ja-JP.yml (English) 2018-10-19 10:11:51 +09:00
6e6824ecb0 New translations ja-JP.yml (Chinese Simplified) 2018-10-19 10:11:47 +09:00
0504a4f659 New translations ja-JP.yml (Catalan) 2018-10-19 10:11:42 +09:00
9a261755d2 Fix key 2018-10-19 10:05:30 +09:00
8533663b26 ✌️ 2018-10-19 09:20:11 +09:00
0a4015b8a2 Refactoring 2018-10-19 09:19:55 +09:00
dcfe56322e New translations ja-JP.yml (Norwegian) 2018-10-19 07:12:41 +09:00
d00a693026 New translations ja-JP.yml (Dutch) 2018-10-19 07:12:35 +09:00
fb36ecad70 New translations ja-JP.yml (Japanese, Kansai) 2018-10-19 07:12:32 +09:00
26c39768ca New translations ja-JP.yml (Spanish) 2018-10-19 07:12:28 +09:00
df8abcfce8 New translations ja-JP.yml (Russian) 2018-10-19 07:12:24 +09:00
e3aab0e9e3 New translations ja-JP.yml (Portuguese) 2018-10-19 07:12:18 +09:00
e3dfc49ed0 New translations ja-JP.yml (Polish) 2018-10-19 07:12:14 +09:00
8485284f63 New translations ja-JP.yml (Korean) 2018-10-19 07:12:10 +09:00
e549e19c03 New translations ja-JP.yml (Italian) 2018-10-19 07:12:06 +09:00
2ace47cbb9 New translations ja-JP.yml (German) 2018-10-19 07:12:02 +09:00
dc184e7bc9 New translations ja-JP.yml (French) 2018-10-19 07:11:57 +09:00
aef1bd094b New translations ja-JP.yml (English) 2018-10-19 07:11:53 +09:00
4f8b22f53b New translations ja-JP.yml (Chinese Simplified) 2018-10-19 07:11:48 +09:00
0f3cbafe91 New translations ja-JP.yml (Catalan) 2018-10-19 07:11:44 +09:00
16ad232c40 10.23.0 2018-10-19 07:06:41 +09:00
4d235a2be5 Merge pull request #2931 from syuilo/l10n_develop
New Crowdin translations
2018-10-19 07:05:44 +09:00
aadf6fa9b1 UI整理 2018-10-19 07:03:29 +09:00
a72e9bc8b2 New translations ja-JP.yml (English) 2018-10-19 07:02:12 +09:00
f11ef93a81 🎨 2018-10-19 06:57:57 +09:00
9136556218 New translations ja-JP.yml (Norwegian) 2018-10-19 06:52:58 +09:00
3ead008295 New translations ja-JP.yml (Dutch) 2018-10-19 06:52:54 +09:00
9ff5693442 New translations ja-JP.yml (Japanese, Kansai) 2018-10-19 06:52:48 +09:00
ac84b42394 New translations ja-JP.yml (Spanish) 2018-10-19 06:52:44 +09:00
a79361c71f New translations ja-JP.yml (Russian) 2018-10-19 06:52:38 +09:00
85e17d5dc7 New translations ja-JP.yml (Portuguese) 2018-10-19 06:52:35 +09:00
45493fd093 New translations ja-JP.yml (Polish) 2018-10-19 06:52:29 +09:00
6f987a2391 New translations ja-JP.yml (Korean) 2018-10-19 06:52:24 +09:00
ddf785a393 New translations ja-JP.yml (Italian) 2018-10-19 06:52:18 +09:00
b8e20fe717 New translations ja-JP.yml (German) 2018-10-19 06:52:15 +09:00
82555bf9b6 New translations ja-JP.yml (French) 2018-10-19 06:52:11 +09:00
ffe6f6c168 New translations ja-JP.yml (English) 2018-10-19 06:52:05 +09:00
6b11f5bb7d New translations ja-JP.yml (Chinese Simplified) 2018-10-19 06:52:01 +09:00
1a65d14864 New translations ja-JP.yml (Catalan) 2018-10-19 06:51:57 +09:00
6c1f1ffdb1 デッキのカラムを左揃えか中央揃えか選べるように 2018-10-19 06:47:55 +09:00
61cdbd5dd2 New translations ja-JP.yml (English) 2018-10-19 06:41:45 +09:00
e7e321e2b3 fix(package): update vue-sweetalert2 to version 1.5.6 (#2932) 2018-10-19 06:38:46 +09:00
fb5f6fdc10 未読の投稿をすべて既読にできるように 2018-10-19 06:36:59 +09:00
00290fbf75 Fix bug 2018-10-19 06:29:25 +09:00
ff02dc723b 🎨 2018-10-19 06:24:15 +09:00
67521c0d2a New translations ja-JP.yml (Norwegian) 2018-10-19 06:23:12 +09:00
da8765150b New translations ja-JP.yml (Dutch) 2018-10-19 06:23:06 +09:00
ea7f51bc12 New translations ja-JP.yml (Japanese, Kansai) 2018-10-19 06:23:02 +09:00
1b34b3b7e2 New translations ja-JP.yml (Spanish) 2018-10-19 06:22:59 +09:00
bca4ceb7ae New translations ja-JP.yml (Russian) 2018-10-19 06:22:53 +09:00
5648cd53d0 New translations ja-JP.yml (Portuguese) 2018-10-19 06:22:49 +09:00
8dab37539f New translations ja-JP.yml (Polish) 2018-10-19 06:22:45 +09:00
2dd42c0061 New translations ja-JP.yml (Korean) 2018-10-19 06:22:39 +09:00
dfafed504a New translations ja-JP.yml (Italian) 2018-10-19 06:22:35 +09:00
9fcd2bcb0a New translations ja-JP.yml (German) 2018-10-19 06:22:29 +09:00
4c701b91a6 New translations ja-JP.yml (French) 2018-10-19 06:22:25 +09:00
84f7aa6d09 New translations ja-JP.yml (English) 2018-10-19 06:22:21 +09:00
82f0c64dee New translations ja-JP.yml (Chinese Simplified) 2018-10-19 06:22:18 +09:00
4b7c6b124b New translations ja-JP.yml (Catalan) 2018-10-19 06:22:14 +09:00
e043b678d4 i18n 2018-10-19 06:21:11 +09:00
fef4f7fce8 #2930 (#2933)
* wip

* wip

* Clean up

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* 🎨

* wip

* wip
2018-10-19 06:18:33 +09:00
9732b3521a New translations ja-JP.yml (French) 2018-10-18 07:13:01 +09:00
a59fcc4aec New translations ja-JP.yml (French) 2018-10-18 07:03:14 +09:00
979e1e78fb New translations ja-JP.yml (French) 2018-10-18 06:51:20 +09:00
c1a929022f Merge pull request #2929 from syuilo/l10n_develop
New Crowdin translations
2018-10-18 05:15:59 +09:00
611bb81032 Merge pull request #2928 from syuilo/greenkeeper/webpack-4.21.0
Update webpack to the latest version 🚀
2018-10-18 05:15:43 +09:00
5047020e6d New translations ja-JP.yml (German) 2018-10-18 05:12:23 +09:00
fb74a6a689 New translations ja-JP.yml (German) 2018-10-18 05:03:26 +09:00
a14a216c8d New translations ja-JP.yml (English) 2018-10-18 05:03:19 +09:00
549e212a59 New translations ja-JP.yml (English) 2018-10-18 04:52:34 +09:00
1bdc91ad47 New translations ja-JP.yml (German) 2018-10-18 04:42:28 +09:00
67f288479c New translations ja-JP.yml (English) 2018-10-18 04:42:22 +09:00
496e45c2bb New translations ja-JP.yml (German) 2018-10-18 04:32:18 +09:00
e458bd3cc7 New translations ja-JP.yml (English) 2018-10-18 04:32:12 +09:00
031911c463 New translations ja-JP.yml (German) 2018-10-18 04:21:47 +09:00
4aa7f638f9 New translations ja-JP.yml (German) 2018-10-18 04:20:03 +09:00
f6f4ea69ae fix(package): update webpack to version 4.21.0 2018-10-17 17:54:09 +00:00
ef945597f2 Merge pull request #2926 from syuilo/l10n_develop
New Crowdin translations
2018-10-17 22:43:47 +09:00
3ab4e1d368 fix(package): update showdown to version 1.8.7 (#2925) 2018-10-17 22:43:23 +09:00
c6216f5b5f fix(package): update @types/elasticsearch to version 5.0.28 (#2924) 2018-10-17 22:43:04 +09:00
4f24d58a79 Make clear elasticsearch is required and not optional for the search to work (#2927) 2018-10-17 22:42:45 +09:00
73d6e7ba66 New translations ja-JP.yml (Japanese, Kansai) 2018-10-17 13:21:23 +09:00
949707e18e New translations ja-JP.yml (Japanese, Kansai) 2018-10-17 13:12:49 +09:00
f51b299c17 10.22.1 2018-10-17 05:54:52 +09:00
d2e0faa533 Disable secure cookie 2018-10-17 05:54:31 +09:00
22015044a5 10.22.0 2018-10-17 04:17:19 +09:00
61f86dcb2b Resolve #2923
Allow option to disable sending HSTS headers even if https:// is used in url
2018-10-17 04:15:41 +09:00
8f3bce6b11 Add some messaging API tests 2018-10-17 04:01:13 +09:00
ee736e73a9 Merge pull request #2922 from syuilo/greenkeeper/reconnecting-websocket-4.1.9
Update reconnecting-websocket to the latest version 🚀
2018-10-17 03:54:08 +09:00
99f867897e fix(package): update reconnecting-websocket to version 4.1.9 2018-10-16 18:53:19 +00:00
c66c5b6e75 Fix bug 2018-10-17 03:47:32 +09:00
f25ecc19b9 🎨 2018-10-17 03:41:55 +09:00
48e09970f3 Merge pull request #2921 from syuilo/l10n_develop
New Crowdin translations
2018-10-16 22:46:43 +09:00
f05cb79604 10.21.3 2018-10-16 22:26:43 +09:00
46d3293edd Fix #2920 2018-10-16 22:21:08 +09:00
9703d613cf 10.21.2 2018-10-16 20:59:49 +09:00
704e217dbb オブジェクトストレージのURLに拡張子を含めるように 2018-10-16 20:59:36 +09:00
a103032d94 10.21.1 2018-10-16 20:34:32 +09:00
c7207a4bd7 Fix #2919 2018-10-16 20:33:13 +09:00
35c65fe589 Clean up 2018-10-16 20:29:35 +09:00
6d5bd0c484 10.21.0 2018-10-16 20:19:55 +09:00
cfbb6e8092 オブジェクトストレージのURLにファイル名を含めるのを廃止 2018-10-16 20:14:06 +09:00
feef4a933e Update src/tools/clean-remote-files.ts 2018-10-16 20:10:46 +09:00
468bc67569 Improve test 2018-10-16 19:52:14 +09:00
0d517fa52f Greenkeeper/monorepo.fortawesome 5.4.1 (#2917)
* fix(package): update @fortawesome/fontawesome-svg-core to version 1.2.6

Closes #2861

* fix(package): update @fortawesome/free-regular-svg-icons to version 5.4.1

Closes #2861

* fix(package): update @fortawesome/free-solid-svg-icons to version 5.4.1

Closes #2861
2018-10-16 12:28:45 +09:00
d9054367c1 fix(package): update @fortawesome/free-brands-svg-icons to version 5.4.1 (#2916)
Closes #2859
2018-10-16 12:27:03 +09:00
1213373027 Use cache with RSS (#2915) 2018-10-16 12:24:54 +09:00
100a525507 Update autogen.sh (#2914)
refs: 8b98c08a81 (commitcomment-30911933)
2018-10-16 11:45:11 +09:00
1bec4e2d12 10.20.0 2018-10-16 11:44:35 +09:00
03cd1d27bf New Crowdin translations (#2910)
* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)
2018-10-16 11:38:43 +09:00
9427a756c9 Update mongodb 2018-10-16 11:38:09 +09:00
d32b2a8ce5 fix(package): update @types/node to version 10.12.0 (#2912) 2018-10-16 10:46:45 +09:00
15473b4368 fix(package): update @types/webpack to version 4.4.17 (#2911) 2018-10-16 10:46:38 +09:00
54de0dc4a7 Update config for CI 2018-10-16 10:36:27 +09:00
0162eaf826 Update signin.ts 2018-10-16 10:33:05 +09:00
572cfafbe1 Add some API tests 2018-10-16 10:18:47 +09:00
4d6335ce9a Add some tests and fix 2018-10-16 09:45:36 +09:00
1c9c4af9f1 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-10-16 08:58:54 +09:00
a6844ebc9d Add some tests 2018-10-16 08:58:45 +09:00
072492c29b Implement /api/v1/instance/peers (#2913)
* Implement /api/v1/instance/peers

* Use punycode

* Remove Cache-Control

* Rename
2018-10-16 08:55:55 +09:00
99da4f9839 Add some tests and some fixes 2018-10-16 08:54:36 +09:00
88664486af Refactor 2018-10-16 08:27:20 +09:00
80daf7c749 Implement API tests 2018-10-16 06:37:21 +09:00
92ba64c35c New translations ja-JP.yml (German) 2018-10-16 06:11:24 +09:00
a8ee51ffd6 New translations ja-JP.yml (German) 2018-10-16 05:51:14 +09:00
5538afc61d New translations ja-JP.yml (German) 2018-10-16 05:42:36 +09:00
beb2f7e558 fix(package): update @types/sharp to version 0.21.0 (#2908) 2018-10-16 05:21:07 +09:00
6243184c95 fix(package): update @types/gulp-uglify to version 3.0.6 (#2906) 2018-10-16 05:20:57 +09:00
1b3baef966 Merge pull request #2898 from syuilo/l10n_develop
New Crowdin translations
2018-10-16 05:20:40 +09:00
98f38ee29b fix(package): update vue-svg-inline-loader to version 1.2.1 (#2909) 2018-10-16 05:20:17 +09:00
09b82bfea4 fix(package): update chart.js to version 2.7.3 (#2907) 2018-10-16 05:20:02 +09:00
937f686264 New translations ja-JP.yml (Russian) 2018-10-15 20:53:38 +09:00
9bc9cbac21 New translations ja-JP.yml (English) 2018-10-15 18:22:42 +09:00
6024550158 New translations ja-JP.yml (Norwegian) 2018-10-15 18:14:29 +09:00
4ae5f82171 New translations ja-JP.yml (Dutch) 2018-10-15 18:14:23 +09:00
6d2c9dcee9 New translations ja-JP.yml (Japanese, Kansai) 2018-10-15 18:14:18 +09:00
0f1b0e1870 New translations ja-JP.yml (Spanish) 2018-10-15 18:14:11 +09:00
81c682cdc8 New translations ja-JP.yml (Russian) 2018-10-15 18:14:05 +09:00
ab9fa67d9f New translations ja-JP.yml (Portuguese) 2018-10-15 18:14:00 +09:00
9537fce335 New translations ja-JP.yml (Polish) 2018-10-15 18:13:53 +09:00
9d97e7e348 New translations ja-JP.yml (Korean) 2018-10-15 18:13:48 +09:00
ebe7939412 New translations ja-JP.yml (Italian) 2018-10-15 18:13:43 +09:00
807e3e8ca7 New translations ja-JP.yml (German) 2018-10-15 18:13:37 +09:00
a59faf9117 New translations ja-JP.yml (French) 2018-10-15 18:13:32 +09:00
d786036155 New translations ja-JP.yml (English) 2018-10-15 18:13:25 +09:00
61d6ed5489 New translations ja-JP.yml (Chinese Simplified) 2018-10-15 18:13:21 +09:00
b38200d48a New translations ja-JP.yml (Catalan) 2018-10-15 18:13:16 +09:00
a0c396a842 10.19.0 2018-10-15 18:03:28 +09:00
88fbc53e37 Resolve #2314 2018-10-15 18:02:57 +09:00
a2206b2d52 🎨 2018-10-15 17:55:59 +09:00
a95ff447d7 🎨 2018-10-15 17:43:25 +09:00
49dbd7f9d2 Fix following from Preroma does not complete (#2905)
* In Follow Accept/Reject, send previous received id

* In Follow Accept/Reject, send Activity.actor
2018-10-15 16:51:22 +09:00
2ad2779096 10.18.0 2018-10-15 06:03:50 +09:00
23045369aa 🎨 2018-10-15 06:03:15 +09:00
116faf26e6 10.17.0 2018-10-15 05:29:58 +09:00
2582b8d132 🎨 2018-10-15 05:28:35 +09:00
63f7941073 🎨 2018-10-15 05:18:39 +09:00
676f026085 🎨 2018-10-15 04:36:31 +09:00
a13319fd86 New translations ja-JP.yml (Norwegian) 2018-10-14 19:52:13 +09:00
be8765278c New translations ja-JP.yml (Dutch) 2018-10-14 19:52:08 +09:00
c8bb3dc209 New translations ja-JP.yml (Japanese, Kansai) 2018-10-14 19:52:03 +09:00
ea16befb73 New translations ja-JP.yml (Spanish) 2018-10-14 19:51:59 +09:00
20b1bb7681 New translations ja-JP.yml (Russian) 2018-10-14 19:51:55 +09:00
bd10eb50eb New translations ja-JP.yml (Portuguese) 2018-10-14 19:51:50 +09:00
d47c0eb31a New translations ja-JP.yml (Polish) 2018-10-14 19:51:45 +09:00
177e8bb19f New translations ja-JP.yml (Korean) 2018-10-14 19:51:41 +09:00
d156111637 New translations ja-JP.yml (Italian) 2018-10-14 19:51:37 +09:00
8c13d3e50b New translations ja-JP.yml (German) 2018-10-14 19:51:33 +09:00
6ff01016f0 New translations ja-JP.yml (French) 2018-10-14 19:51:30 +09:00
5d659da012 New translations ja-JP.yml (English) 2018-10-14 19:51:26 +09:00
28e7552a1a New translations ja-JP.yml (Chinese Simplified) 2018-10-14 19:51:21 +09:00
53d264814b New translations ja-JP.yml (Catalan) 2018-10-14 19:51:15 +09:00
2d6b20d34b 10.16.0 2018-10-14 19:45:51 +09:00
99073b56df Resolve #2900 2018-10-14 19:44:30 +09:00
5dce81c0db 非ASCIIなドメインへのメンションの修正 (#2903)
* punycodeでされたmentionのラベルをunicodeとして表示する

* post-form mentionはpunycodeにする

* mentionの表示はURLもAPI向けもunicodeにする
2018-10-14 16:56:19 +09:00
be82d845a4 expose user recommendation config in /api/meta (#2902) 2018-10-14 16:54:09 +09:00
f49ccd0cd3 10.15.0 2018-10-14 10:17:04 +09:00
69d83f535d Clean up 2018-10-14 10:16:07 +09:00
c7988fb6f5 🎨 2018-10-14 10:16:02 +09:00
3961fd08c9 Fix #2901 2018-10-14 10:06:10 +09:00
935b074a7a New translations ja-JP.yml (Norwegian) 2018-10-13 20:12:19 +09:00
9d9c609bfb New translations ja-JP.yml (Dutch) 2018-10-13 20:12:15 +09:00
f6a664f181 New translations ja-JP.yml (Japanese, Kansai) 2018-10-13 20:12:10 +09:00
fce68d1f75 New translations ja-JP.yml (Spanish) 2018-10-13 20:12:06 +09:00
88739c2444 New translations ja-JP.yml (Russian) 2018-10-13 20:12:02 +09:00
7e2f10fce3 New translations ja-JP.yml (Portuguese) 2018-10-13 20:11:58 +09:00
a494c3a5cc New translations ja-JP.yml (Polish) 2018-10-13 20:11:53 +09:00
d6bb702883 New translations ja-JP.yml (Korean) 2018-10-13 20:11:48 +09:00
d15a972c68 New translations ja-JP.yml (Italian) 2018-10-13 20:11:44 +09:00
2ae7d31725 New translations ja-JP.yml (German) 2018-10-13 20:11:40 +09:00
2e329b1888 New translations ja-JP.yml (French) 2018-10-13 20:11:36 +09:00
522d40328b New translations ja-JP.yml (English) 2018-10-13 20:11:32 +09:00
2ecbff45bf New translations ja-JP.yml (Chinese Simplified) 2018-10-13 20:11:28 +09:00
b6f7282c13 New translations ja-JP.yml (Catalan) 2018-10-13 20:11:24 +09:00
137 changed files with 3986 additions and 1892 deletions

View File

@ -30,7 +30,7 @@ while :
touch patreon.cache && \
rm patreon.cache && \
cat patreon.raw.cache | \
jq -r '(.data|map(select(.relationships.currently_entitled_tiers.data[]))|map(.relationships.user.data.id))as$data|.included|map(select(.attributes.hide_pledges==false))|map(select(.id as$id|$data|contains([$id])))|map(.attributes|[.full_name,.thumb_url,.url]|@tsv)|.[]|@text' >> patreon.cache && \
jq -r '(.data|map(select(.relationships.currently_entitled_tiers.data[]))|map(.relationships.user.data.id))as$data|.included|map(select(.id as$id|$data|contains([$id])))|map(.attributes|[.full_name,.thumb_url,.url]|@tsv)|.[]|@text' >> patreon.cache && \
echo '<table><tr>' >> patreon.md.cache && \
cat patreon.cache | \
awk -F'\t' '{print $2,$1}' | \

View File

@ -1,12 +1,8 @@
maintainer: '@syuilo'
url: 'https://misskey.xyz'
secondary_url: 'https://himasaku.net'
maintainer:
name: syuilo
url: 'https://syuilo.com'
url: 'http://misskey.local'
port: 80
https:
enable: false
key: null
cert: null
ca: null
mongodb:
host: localhost
port: 27017
@ -21,6 +17,3 @@ elasticsearch:
host: localhost
port: 9200
pass: ''
recaptcha:
site_key: hima
secret_key: saku

View File

@ -1,12 +1,8 @@
maintainer: '@syuilo'
url: 'https://misskey.xyz'
secondary_url: 'https://himasaku.net'
maintainer:
name: syuilo
url: 'https://syuilo.com'
url: 'http://misskey.local'
port: 80
https:
enable: false
key: null
cert: null
ca: null
mongodb:
host: localhost
port: 27017
@ -21,6 +17,3 @@ elasticsearch:
host: localhost
port: 9200
pass: ''
recaptcha:
site_key: hima
secret_key: saku

View File

@ -28,7 +28,7 @@ Please install and setup these softwares:
##### Optional
* [Redis](https://redis.io/)
* Redis is optional, but we strongly recommended to install it
* [Elasticsearch](https://www.elastic.co/) - used to provide searching feature instead of MongoDB
* [Elasticsearch](https://www.elastic.co/) - required to enable the search feature
*3.* Setup MongoDB
----------------------------------------------------------------

View File

@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "確認中"
no-broadcasts: "お知らせはありません"
@ -640,7 +659,7 @@ desktop/views/components/note-detail.vue:
location: "位置情報"
renote: "Renote"
add-reaction: "リアクション"
desktop/views/components/notes.note.vue:
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "返信"
renote: "Renote"
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "詳細設定"
api-via-stream: "ストリームを経由したAPIリクエスト"
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。"
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "デザインと表示"
customize: "ホームをカスタマイズ"
wallpaper: "壁紙"
choose-wallpaper: "壁紙を選択"
delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-clock-on-header: "右上に時計を表示する"
show-reply-target: "リプライ先を表示する"
timeline: "タイムライン"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。"
volume: "ボリューム"
test: "テスト"
mobile: "モバイル"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
language: "言語"
pick-language: "言語を選択"
recommended: "推奨"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "ツール"
task-manager: "タスクマネージャ"
third-parties: "サードパーティ"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
detail: "詳細..."
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/settings.profile.vue:
avatar: "アイコン"
choice-avatar: "画像を選択"
name: "名前"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
save: "保存"
locked-account: "アカウントの保護"
is-locked: "フォローを承認制にする"
other: "その他"
is-bot: "このアカウントはBotです"
is-cat: "このアカウントはCatです"
profile-updated: "プロフィールを更新しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
edit: "オプション"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "{}がRenote"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "ハッシュ (md5)"
exif: "EXIF"
nsfw: "閲覧注意"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "閲覧注意"
click-to-show: "クリックして表示"
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?"
mobile/views/pages/games/reversi.vue:
reversi: "リバーシ"
mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-locked: "フォローを承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
mobile/views/pages/search.vue:
search: "検索"
empty: "「{}」に関する投稿は見つかりませんでした。"

View File

@ -3,44 +3,44 @@ meta:
lang: "Deutsch"
divider: ""
common:
misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse."
misskey: "Ein ⭐ des Fediversums"
about-title: "Ein ⭐ des Fediversums."
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。"
intro:
title: "Misskeyって?"
title: "Was ist Misskey?"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
features: "Funktionen"
rich-contents: "Notizen"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction: "Reaktionen"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui: "Benutzeroberfläche"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive: "Drive"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock:
detected: "広告ブロッカーを無効にしてください"
detected: "Bitte deaktivieren Sie den Werbeblocker."
warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。"
application-authorization: "アプリの連携"
close: "閉じる"
application-authorization: "Autorisierte Anwendungen"
close: "Schließen"
do-not-copy-paste: "ここにコードを入力したり張り付けたりしないでください。アカウントが不正利用される可能性があります。"
got-it: "わかった"
got-it: "Verstanden!"
customization-tips:
title: "カスタマイズのヒント"
title: "Anpassung-Tipps"
paragraph1: "ホームのカスタマイズでは、ウィジェットを追加/削除したり、ドラッグ&ドロップして並べ替えたりすることができます。"
paragraph2: "一部のウィジェットは、<strong><strong>右</strong>クリック</strong>することで表示を変更することができます。"
paragraph3: "ウィジェットを削除するには、ヘッダーの<strong>「ゴミ箱」</strong>と書かれたエリアにウィジェットをドラッグ&ドロップします。"
paragraph4: "カスタマイズを終了するには、右上の「完了」をクリックします。"
gotit: "Got it!"
gotit: "Verstanden!"
notification:
file-uploaded: "ファイルがアップロードされました"
message-from: "{}さんからメッセージ:"
file-uploaded: "Datei hochgeladen!"
message-from: "Nachricht von {}:"
reversi-invited: "対局への招待があります"
reversi-invited-by: "{}さんから"
notified-by: "{}さんから"
reply-from: "{}さんから返信:"
quoted-by: "{}さんが引用:"
reversi-invited-by: "Eingeladen von {}:"
notified-by: "Benachrichtigt von {}:"
reply-from: "Antwort von {}:"
quoted-by: "Zitiert von {}:"
time:
unknown: "Unbekannt"
future: "Zukunft"
@ -52,8 +52,8 @@ common:
weeks_ago: "vor {0} Woche{0:n}"
months_ago: "vor {0} Monat{0:en}"
years_ago: "vor {} Jahr{0:en}"
month-and-day: "{month}月 {day}日"
trash: "ゴミ箱"
month-and-day: "{day}/{month}"
trash: "Papierkorb"
weekday-short:
sunday: "So"
monday: "Mo"
@ -63,15 +63,15 @@ common:
friday: "Fr"
saturday: "Sa"
weekday:
sunday: "日曜日"
monday: "月曜日"
tuesday: "火曜日"
wednesday: "水曜日"
thursday: "木曜日"
friday: "金曜日"
saturday: "土曜日"
sunday: "Sonntag"
monday: "Montag"
tuesday: "Dienstag"
wednesday: "Mittwoch"
thursday: "Donnerstag"
friday: "Freitag"
saturday: "Samstag"
reactions:
like: "いいね"
like: "Gefällt mir"
love: "Lieben"
laugh: "Lachen"
hmm: "Hmm...?"
@ -82,14 +82,14 @@ common:
rip: "RIP"
pudding: "Pudding"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
public: "Öffentlich"
home: "Startseite"
home-desc: "Nur auf die Startseite posten"
followers: "Abonnenten"
followers-desc: "Nur für diejenigen sichtbar, die dir folgen"
specified: "Direkt"
specified-desc: "Nur für bestimmte Benutzer posten"
private: "Privat"
note-placeholders:
a: "Was machst du gerade?"
b: "Was ist so passiert?"
@ -97,34 +97,34 @@ common:
d: "Willst du etwas sagen?"
e: "Schreib hier etwas!"
f: "Warte darauf, das du schreibst."
search: "検索"
search: "Suche"
delete: "Löschen"
loading: "Laden"
ok: "OK"
update-available-title: "更新があります"
update-available-title: "Aktualisierung verfügbar"
update-available: "Eine neue Version von Misskey ist verfügbar ({newer}, aktuell ist {current}). Lade die Seite neu um die aktuelle Version zu laden"
my-token-regenerated: "Dein Token wurde generiert. Du wirst jetzt abgemeldet."
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
i-like-sushi: "Ich bevorzuge Sushi anstelle von Pudding"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
verified-user: "Verifizierter Benutzer"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
always-show-nsfw: "常に閲覧注意のメディアを表示する"
always-mark-nsfw: "常にメディアを閲覧注意として投稿"
show-full-acct: "ユーザー名のホストを省略しない"
reduce-motion: "UIの動きを減らす"
this-setting-is-this-device-only: "このデバイスのみ"
do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。'
reduce-motion: "Animationen der Benutzeroberfläche reduzieren"
this-setting-is-this-device-only: "Nur auf diesem Gerät"
do-not-use-in-production: 'Dies ist eine Entwicklungsversion. Nicht in einer Produktionsumgebung verwenden.'
reversi:
drawn: "引き分け"
my-turn: "あなたのターンです"
opponent-turn: "相手のターンです"
turn-of: "{}のターンです"
past-turn-of: "{}のターン"
won: "{}の勝ち"
black: ""
white: ""
total: "合計"
drawn: "Unentschieden"
my-turn: "Du bist am Zug"
opponent-turn: "Dein Gegner ist an der Reihe"
turn-of: "{} ist am Zug"
past-turn-of: "Zug von {}"
won: "{} hat gewonnen!"
black: "Schwarz"
white: "Weiß"
total: "Gesamt"
this-turn: "{}ターン目"
widgets:
analog-clock: "Analoge Uhr"
@ -142,23 +142,23 @@ common:
broadcast: "ブロードキャスト"
notifications: "Benachrichtigungen"
users: "Empfohlene Benutzer"
polls: "アンケート"
polls: "Umfrage"
post-form: "Beitragsform"
messaging: "Nachrichten"
server: "Server-Info"
donation: "Spenden"
nav: "Navigation"
tips: "Tipps"
hashtags: "ハッシュタグ"
hashtags: "Hashtags"
deck:
widgets: "Widget hinzufügen:"
home: "Startseite"
local: "Lokal"
hybrid: "ソーシャル"
hashtag: "ハッシュタグ"
hashtag: "Hashtag"
global: "Global"
mentions: "あなた宛て"
direct: "ダイレクト投稿"
mentions: "Erwähnungen"
direct: "Direktnachrichten"
notifications: "Mitteilungen"
list: "Listen"
swap-left: "Nach links"
@ -175,67 +175,67 @@ auth/views/form.vue:
permission-ask: "このアプリは次の権限を要求しています:"
account-read: "アカウントの情報を見る。"
account-write: "アカウントの情報を操作する。"
note-write: "投稿する。"
note-write: "Senden."
like-write: "いいねしたりいいね解除する。"
following-write: "フォローしたりフォロー解除する。"
drive-read: "ドライブを見る。"
drive-write: "ドライブを操作する。"
notification-read: "通知を見る。"
notification-write: "通知を操作する。"
cancel: "キャンセル"
accept: "アクセスを許可"
cancel: "Abbrechen"
accept: "Zugriff erlauben."
auth/views/index.vue:
loading: "読み込み中"
denied: "アプリケーションの連携をキャンセルしました。"
loading: "Lädt"
denied: "Autorisierung der Anwendung wurde verweigert."
denied-paragraph: "このアプリがあなたのアカウントにアクセスすることはありません。"
already-authorized: "このアプリは既に連携済みです"
allowed: "アプリケーションの連携を許可しました"
already-authorized: "Diese Anwendung ist bereits autorisiert."
allowed: "Autorisierung der Anwendung wurde erlaubt."
callback-url: "アプリケーションに戻っています"
please-go-back: "アプリケーションに戻って、やっていってください。"
error: "セッションが存在しません。"
sign-in: "サインインしてください"
please-go-back: "Bitte gehen Sie zurück zur Anwendung."
error: "Sitzung ist nicht vorhanden."
sign-in: "Bitte melde dich an."
common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "{}を待っています"
cancel: "キャンセル"
waiting-for: "Warten auf {}"
cancel: "Abbrechen"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrender: "Aufgeben"
surrendered: "投了により"
is-llotheo: "石の少ない方が勝ち(ロセオ)"
looped-map: "ループマップ"
can-put-everywhere: "どこでも置けるモード"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"
invite: "招待"
rule: "遊び方"
sub-title: "Spiele Reversi mit deinen Freunden!"
invite: "Einladen"
rule: "Spielanleitung"
rule-desc: "リバーシは、相手と交互に石をボードに置いて、相手の石を挟んで自分の色に変えてゆき、最終的に残った石が多い方が勝ちというボードゲームです。"
mode-invite: "招待"
mode-invite: "Einladen"
mode-invite-desc: "指定したユーザーと対戦するモードです。"
invitations: "対局の招待があります!"
my-games: "自分の対局"
all-games: "みんなの対局"
enter-username: "ユーザー名を入力してください"
all-games: "Alle Spiele"
enter-username: "Bitte gib einen Benutzernamen ein"
game-state:
ended: "終了"
ended: "Fertig"
playing: "進行中"
common/views/components/games/reversi/reversi.room.vue:
settings-of-the-game: "ゲームの設定"
choose-map: "マップを選択"
random: "ランダム"
black-or-white: "先手/後手"
black-is: "{}が黒"
rules: "ルール"
settings-of-the-game: "Spieleinstellungen"
choose-map: "Wähle eine Karte"
random: "Zufällige Auswahl"
black-or-white: "Schwarz/Weiß"
black-is: "Schwarz ist {}"
rules: "Regeln"
is-llotheo: "石の少ない方が勝ち(ロセオ)"
looped-map: "ループマップ"
can-put-everywhere: "どこでも置けるモード"
settings-of-the-bot: "Botの設定"
this-game-is-started-soon: "ゲームは数秒後に開始されます"
waiting-for-other: "相手の準備が完了するのを待っています"
waiting-for-other: "Warte auf den Gegner"
waiting-for-me: "あなたの準備が完了するのを待っています"
waiting-for-both: "準備中"
cancel: "キャンセル"
ready: "準備完了"
cancel: "Abbrechen"
ready: "Bereit"
cancel-ready: "準備続行"
common/views/components/connect-failed.vue:
title: "Verbindung zum Server ist fehlgeschlagen"
@ -262,29 +262,29 @@ common/views/components/connect-failed.troubleshooter.vue:
flush: "Cache leeren"
set-version: "Version angeben"
common/views/components/media-banner.vue:
sensitive: "閲覧注意"
click-to-show: "クリックして表示"
sensitive: "Dieser Inhalt ist NSFW"
click-to-show: "Klicke zum den Inhalt anzusehen"
common/views/components/theme.vue:
light-theme: "非ダークモード時に使用するテーマ"
dark-theme: "ダークモード時に使用するテーマ"
light-themes: "明るいテーマ"
dark-themes: "暗いテーマ"
light-theme: "Thema"
dark-theme: "Thema während des Nachtmodus"
light-themes: "Helles Thema"
dark-themes: "Dunkles Thema"
install-a-theme: "テーマのインストール"
theme-code: "テーマコード"
install: "インストール"
installed: "「{}」をインストールしました"
create-a-theme: "テーマの作成"
save-created-theme: "テーマを保存"
primary-color: "プライマリ カラー"
secondary-color: "セカンダリ カラー"
text-color: "文字色"
base-theme: "ベーステーマ"
base-theme-light: "Light"
base-theme-dark: "Dark"
theme-name: "テーマ名"
preview-created-theme: "プレビュー"
invalid-theme: "テーマが正しくありません。"
already-installed: "既にそのテーマはインストールされています。"
install: "Anwenden"
installed: "\"{}\" wurde installiert"
create-a-theme: "Thema erstellen"
save-created-theme: "Thema speichern"
primary-color: "Primäre Farbe"
secondary-color: "Sekundäre Farbe"
text-color: "Textfarbe"
base-theme: "Basisthema"
base-theme-light: "Hell"
base-theme-dark: "Dunkel"
theme-name: "Name des Themas"
preview-created-theme: "Vorschau"
invalid-theme: "Thema ist ungültig"
already-installed: "Thema ist bereits installiert"
saved: "保存しました"
manage-themes: "テーマの管理"
builtin-themes: "標準テーマ"
@ -293,10 +293,10 @@ common/views/components/theme.vue:
select-theme: "テーマを選択してください"
uninstall: "アンインストール"
uninstalled: "「{}」をアンインストールしました"
author: "作者"
author: "Autor"
desc: "説明"
export: "エクスポート"
import: "インポート"
export: "Exportieren"
import: "Importieren"
import-by-code: "またはコードをペースト"
theme-name-required: "テーマ名は必須です。"
common/views/components/cw-button.vue:
@ -335,7 +335,7 @@ common/views/components/note-menu.vue:
detail: "詳細"
copy-link: "リンクをコピー"
favorite: "Diese Anmerkung favorisieren"
unfavorite: "お気に入り解除"
unfavorite: "Entfavorisieren"
pin: "An die Profilseite pinnen"
unpin: "ピン留め解除"
delete: "Löschen"
@ -362,7 +362,7 @@ common/views/components/signin.vue:
token: "Token"
signing-in: "Melde an..."
signin: "Anmelden"
or: "または"
or: "Oder"
signin-with-twitter: "Twitterでログイン"
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
common/views/components/signup.vue:
@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "Laden"
no-broadcasts: "Keine Broadcasts"
@ -510,7 +529,7 @@ desktop/views/components/charts.vue:
notes: "投稿"
users: "ユーザー"
drive: "ドライブ"
network: "ネットワーク"
network: "Netzwerk"
charts:
notes: "投稿の増減 (統合)"
local-notes: "投稿の増減 (ローカル)"
@ -522,9 +541,9 @@ desktop/views/components/charts.vue:
drive-total: "ドライブ使用量の積算"
drive-files: "ドライブのファイル数の増減"
drive-files-total: "ドライブのファイル数の積算"
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
network-requests: "Anfragen"
network-time: "Antwortzeit"
network-usage: "Datenverkehr"
desktop/views/components/choose-file-from-drive-window.vue:
choose-file: "Datei auswählen"
upload: "Dateien von deinem PC hochladen"
@ -640,25 +659,25 @@ desktop/views/components/note-detail.vue:
location: "Ort"
renote: "Anmerkung"
add-reaction: "Reaktion hinzufügen"
desktop/views/components/notes.note.vue:
reposted-by: "Auch geteilt von"
reply: "Antworten"
renote: "Anmerken"
add-reaction: "Eine Reaktion hinzufügen"
detail: "Zeige Details"
private: "Dieser Beitrag ist eine privat"
deleted: "Dieser Beitrag wurde entfernt"
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "返信"
renote: "Renote"
add-reaction: "リアクション"
detail: "詳細"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/components/notes.vue:
error: "Laden fehlgeschlagen."
retry: "Erneut versuchen"
load-more: "もっと読み込む"
load-more: "Mehr laden"
desktop/views/components/notifications.vue:
more: "Mehr"
empty: "Keine Benachrichtigungen"
desktop/views/components/post-form.vue:
add-visible-user: "+ユーザーを追加"
add-visible-user: "+Nutzer hinzufügen"
attach-location-information: "位置情報を添付する"
hide-contents: "内容を隠す"
hide-contents: "Inhalt verstecken"
reply-placeholder: "Antworte auf diese Anmerkung..."
quote-placeholder: "Zitiere diese Anmerkung..."
submit: "Beitragsform"
@ -679,10 +698,10 @@ desktop/views/components/post-form.vue:
text-remain: "{} Zeichen verbleibend"
recent-tags: "最近"
click-to-tagging: "クリックでタグ付け"
visibility: "公開範囲"
visibility: "Sichtbarkeit"
geolocation-alert: "お使いの端末は位置情報に対応していません"
error: "エラー"
enter-username: "ユーザー名を入力してください"
error: "Fehler"
enter-username: "Bitte gib einen Benutzernamen ein..."
annotations: "内容への注釈 (オプション)"
desktop/views/components/post-form-window.vue:
note: "Neue Notiz"
@ -726,30 +745,36 @@ desktop/views/components/settings.vue:
advanced: "Erweiterte Einstellungen"
api-via-stream: "API-Anfrage via stream"
api-via-stream-desc: "API-Anfrage über WebSocket statt native Aktualisierungs-API (für bessere Leistung). Diese Einstellung wird im Browser gespeichert."
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "Erscheinungsbild und Anzeige"
customize: "Startseite anpassen"
wallpaper: "壁紙"
choose-wallpaper: "壁紙を選択"
delete-wallpaper: "壁紙を削除"
dark-mode: "Nacht Modus"
use-shadow: "UIに影を使用"
rounded-corners: "UIの角を丸める"
rounded-corners: "Abgerundete Ecken"
circle-icons: "Kreisförmige Icons"
contrasted-acct: "ユーザー名にコントラストを付ける"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-clock-on-header: "右上に時計を表示する"
show-reply-target: "Zeige Antworten"
timeline: "タイムライン"
show-my-renotes: "Zeige meine Reposts auf der Zeitleiste"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Karte anzeigen"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "Ton"
enable-sounds: "Ton aktivieren"
enable-sounds-desc: "Spiel einen Ton ab beim Erhalten eines Beitrags bzw. einer Nachricht. Diese Einstellung wird im Browser gespeichert."
volume: "Lautstärke"
test: "Test"
mobile: "Mobil"
disable-via-mobile: "Diesen Beitrag nicht mit 'vom Handy' absenden"
language: "Sprache"
pick-language: "Sprache auswählen"
recommended: "Empfohlen"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "Werkzeuge"
task-manager: "Taskmanager"
third-parties: "サードパーティ"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
detail: "詳細..."
@ -818,26 +847,12 @@ desktop/views/components/settings.drive.vue:
desktop/views/components/settings.mute.vue:
no-users: "ミュートしているユーザーはいません"
desktop/views/components/settings.password.vue:
reset: "パスワードを変更する"
reset: "Passwort ändern"
enter-current-password: "Derzeitiges Passwort eingeben"
enter-new-password: "Neues Passwort eingeben"
enter-new-password-again: "Neues Passwort erneut eingeben"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/settings.profile.vue:
avatar: "アイコン"
choice-avatar: "画像を選択"
name: "名前"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
save: "Profil aktualisieren"
locked-account: "アカウントの保護"
is-locked: "フォローを承認制にする"
other: "その他"
is-bot: "このアカウントはBotです"
is-cat: "このアカウントはCatです"
profile-updated: "プロフィールを更新しました"
not-match: "Passwörter stimmen nicht überein."
changed: "Passwort geändert"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@ -897,7 +912,7 @@ desktop/views/components/user-preview.vue:
desktop/views/components/users-list.vue:
all: "すべて"
iknow: "知り合い"
load-more: "もっと"
load-more: "Mehr"
fetching: "Lade…"
desktop/views/components/users-list-item.vue:
followed: "フォローされています"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
edit: "オプション"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "{}がRenote"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "ハッシュ (md5)"
exif: "EXIF"
nsfw: "閲覧注意"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "閲覧注意"
click-to-show: "クリックして表示"
@ -1158,19 +1173,19 @@ mobile/views/components/ui.nav.vue:
mobile/views/components/user-timeline.vue:
no-notes: "このユーザーは投稿していないようです。"
no-notes-with-media: "メディア付き投稿はありません。"
load-more: "もっと"
load-more: "Mehr"
mobile/views/components/users-list.vue:
all: "すべて"
known: "知り合い"
load-more: "もっと"
load-more: "Mehr"
mobile/views/pages/favorites.vue:
title: "お気に入り"
title: "Favoriten"
mobile/views/pages/user-lists.vue:
title: "リスト"
enter-list-name: "リスト名を入力してください"
mobile/views/pages/drive.vue:
drive: "ドライブ"
more: "もっと見る"
more: "Mehr laden"
mobile/views/pages/signup.vue:
lets-start: "📦 始めましょう"
mobile/views/pages/followers.vue:
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?"
mobile/views/pages/games/reversi.vue:
reversi: "リバーシ"
mobile/views/pages/settings/settings.profile.vue:
title: "Profil"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-locked: "フォローを承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "Profil wurde aktualisiert"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
mobile/views/pages/search.vue:
search: "検索"
empty: "「{}」に関する投稿は見つかりませんでした。"
@ -1301,7 +1299,7 @@ mobile/views/pages/user/home.vue:
recent-notes: "最近の投稿"
images: "画像"
activity: "アクティビティ"
keywords: "キーワード"
keywords: "Schlagwörter"
domains: "頻出ドメイン"
frequently-replied-users: "よく会話するユーザー"
followers-you-know: "知り合いのフォロワー"

View File

@ -110,7 +110,7 @@ common:
verified-user: "Verified account"
disable-animated-mfm: "Disable animated texts in a post"
always-show-nsfw: "Always show NSFW contents"
always-mark-nsfw: "Always post with a warning about media attachment"
always-mark-nsfw: "Always mark posts with media attachments as NSFW"
show-full-acct: "Do not omit the hostname from the username"
reduce-motion: "Reduce motion in UI"
this-setting-is-this-device-only: "Only for this device"
@ -265,7 +265,7 @@ common/views/components/media-banner.vue:
sensitive: "NSFW"
click-to-show: "Click to show"
common/views/components/theme.vue:
light-theme: "Theme during non-dark mode"
light-theme: "Theme"
dark-theme: "Theme during dark mode"
light-themes: "Light theme"
dark-themes: "Dark theme"
@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{} users mentioned"
empty: "No popular hashtag trends"
common/views/components/profile-editor.vue:
title: "Profile"
name: "Name"
account: "Account"
location: "Location"
description: "About me"
birthday: "Birthday"
avatar: "Avatar"
banner: "Banner"
is-cat: "This account is a Cat"
is-bot: "This account is a Bot"
is-locked: "Follower requests require approval"
careful-bot: "Follower requests from bots require approval"
advanced: "Advanced"
privacy: "Privacy"
save: "Update profile"
saved: "Profile updated successfully"
uploading: "Uploading"
upload-failed: "Failed to upload"
common/views/widgets/broadcast.vue:
fetching: "Fetching"
no-broadcasts: "No announcements"
@ -463,7 +482,7 @@ common/views/widgets/tips.vue:
tips-line10: "Using the Time Machine widget makes it easy to trace back to the past timeline."
tips-line11: "You can pin posts to user page by clicking on \"...\""
tips-line13: "All the files attached to the post are saved to Drive."
tips-line14: "While customizing the home, you can right click on the widget and change the design."
tips-line14: "While customizing your home layout, you can right click on a widget to change its design."
tips-line17: "Surrounding the text with ** ** will highlight it."
tips-line19: "Several windows can be detached outside the browser."
tips-line20: "The percentage of the calendar widget shows the percentage of time elapsed."
@ -640,14 +659,14 @@ desktop/views/components/note-detail.vue:
location: "Location"
renote: "Repost"
add-reaction: "Add a reaction"
desktop/views/components/notes.note.vue:
desktop/views/components/note.vue:
reposted-by: "Reposted by {}"
reply: "Reply"
renote: "Repost"
renote: "Renote"
add-reaction: "Add a reaction"
detail: "Show details"
private: "Post is private"
deleted: "Post has been deleted"
detail: "Details"
private: "This post is private"
deleted: "This post has been deleted"
desktop/views/components/notes.vue:
error: "Loading failed."
retry: "Retry"
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "Advanced settings"
api-via-stream: "API request via stream"
api-via-stream-desc: "API request is performed via the WebSocket connection instead of native fetch API (for better performance). This setting is stored in the browser."
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "Design and display"
customize: "Customize home layout"
wallpaper: "Wallpaper"
choose-wallpaper: "Choose a background"
delete-wallpaper: "Remove background"
dark-mode: "Dark Mode"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "Show recent popular hashtags on the post form"
show-clock-on-header: "Show clock on upper-right"
show-reply-target: "Display reply target"
timeline: "Timeline"
show-my-renotes: "Show my renotes in the timeline"
show-renoted-my-notes: "Show renoted my posts in timelines"
show-local-renotes: "Show renoted local posts in timelines"
show-maps: "Display a map to show the location"
deck-column-align: "Deck column alignment"
deck-column-align-center: "Center"
deck-column-align-left: "Left"
sound: "Sound"
enable-sounds: "Enable sound"
enable-sounds-desc: "Play a sound when you receive a post/message. This setting is stored in the browser."
volume: "Volume"
test: "Test"
mobile: "Mobile"
disable-via-mobile: "Don't mark the post as 'from mobile'"
language: "Language"
pick-language: "Select a language"
recommended: "Recommended"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "Tools"
task-manager: "Task Manager"
third-parties: "Third-parties"
navbar-position: "Navigation bar position"
navbar-position-top: "Top"
navbar-position-left: "Left"
navbar-position-right: "Right"
desktop/views/components/settings.2fa.vue:
intro: "If you set up 2-step verification, you will not only need a password at sign-in, but also a pre-registered physical device (such as your smartphone), which will improve security."
detail: "Details…"
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "Enter new password again"
not-match: "The new passwords do not match"
changed: "Password updated"
desktop/views/components/settings.profile.vue:
avatar: "Avatar"
choice-avatar: "Select an image"
name: "Name"
location: "Location"
description: "Description"
birthday: "Birthday"
save: "Update profile"
locked-account: "Protect your account"
is-locked: "Follow request needs approval"
other: "Other"
is-bot: "This account is a Bot"
is-cat: "This account is a Cat"
profile-updated: "Your profile has been updated"
desktop/views/components/sub-note-content.vue:
private: "This post is private"
deleted: "This post has been deleted"
@ -870,7 +885,7 @@ desktop/views/components/ui.header.account.vue:
admin: "Admin"
settings: "Settings"
signout: "Sign out"
dark: "Submerge in dark"
dark: "Toggle dark mode"
desktop/views/components/ui.header.nav.vue:
home: "Home"
deck: "Deck"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "Only media posts"
is-media-view: "Media view"
edit: "Options"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "Reposted by {}"
private: "This post is private"
deleted: "This post has been deleted"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "Pinned posts"
desktop/views/pages/stats/stats.vue:
all-users: "All Users"
original-users: "Users on this instance"
@ -954,7 +967,7 @@ desktop/views/pages/welcome.vue:
signup-button: "Sign up"
timeline: "Timeline"
announcements: "Announcements"
photos: "Recent uploaded"
photos: "Recent Images"
powered-by-misskey: "Powered by <b>Misskey</b>."
info: "Information"
desktop/views/pages/drive.vue:
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "Hash (md5)"
exif: "EXIF"
nsfw: "NSFW"
mark-as-sensitive: "Mark as 'sensitive'"
unmark-as-sensitive: "Unmark as 'sensitive'"
mobile/views/components/media-image.vue:
sensitive: "NSFW"
click-to-show: "Click to show"
@ -1157,7 +1172,7 @@ mobile/views/components/ui.nav.vue:
about: "About Misskey"
mobile/views/components/user-timeline.vue:
no-notes: "It seems this user hasn't posted anything yet."
no-notes-with-media: "There are no posts attaching media"
no-notes-with-media: "There are no notes with media attachments"
load-more: "More"
mobile/views/components/users-list.vue:
all: "All"
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "Do you wish to mark all notifications as read?"
mobile/views/pages/games/reversi.vue:
reversi: "Reversi"
mobile/views/pages/settings/settings.profile.vue:
title: "Profile"
name: "Name"
account: "Account"
location: "Location"
description: "Biography"
birthday: "Birthday"
avatar: "Avatar"
banner: "Banner"
is-cat: "This account is a Cat"
is-locked: "Follow request needs approval"
advanced: "Advanced"
privacy: "Privacy"
save: "Update profile"
saved: "Profile updated"
uploading: "Uploading"
upload-failed: "Failed to upload"
mobile/views/pages/search.vue:
search: "Search"
empty: "No posts were found for '{}'"

View File

@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "Recuperando"
no-broadcasts: "Sin emisión"
@ -640,14 +659,14 @@ desktop/views/components/note-detail.vue:
location: "Localización"
renote: "Republicar"
add-reaction: "Agregar una reacción"
desktop/views/components/notes.note.vue:
reposted-by: "Republicado por {}"
reply: "Responder"
renote: "Republicar"
add-reaction: "Agregar una reacción"
detail: "Mostrar detalles"
private: "Esta publicación es privada"
deleted: "Esta publicación ha sido borrada"
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "返信"
renote: "Renote"
add-reaction: "リアクション"
detail: "詳細"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/components/notes.vue:
error: "Error al cargar."
retry: "Reintentar"
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "Configuración avanzada"
api-via-stream: "Solicitar API por medio de un stream"
api-via-stream-desc: "Las peticiones de las API se realizan por conexiones WebSocket en lugar de las tradicionales (para una mejora en el rendimiento). Esta función depende del navegador."
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "Diseño y pantalla"
customize: "Personaliza la página principal"
wallpaper: "壁紙"
choose-wallpaper: "Elije un fondo"
delete-wallpaper: "Suprimir fondo"
dark-mode: "Modo Nocturno"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-clock-on-header: "右上に時計を表示する"
show-reply-target: "リプライ先を表示する"
timeline: "タイムライン"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。"
volume: "ボリューム"
test: "テスト"
mobile: "モバイル"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
language: "言語"
pick-language: "言語を選択"
recommended: "推奨"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "Herramientas"
task-manager: "Navegador de tareas"
third-parties: "Servicios externos"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
detail: "Ver detalles..."
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "Ingresar nueva contraseña de nuevo"
not-match: "Las nuevas contraseñas no se corresponden consigo mismas"
changed: "Contraseña actualizada"
desktop/views/components/settings.profile.vue:
avatar: "Avatar"
choice-avatar: "Escoger una imagen"
name: "Nombre"
location: "Localización"
description: "Descripción"
birthday: "Fecha de nacimiento"
save: "Perfil actualizado"
locked-account: "Protege tu cuenta"
is-locked: "フォローを承認制にする"
other: "その他"
is-bot: "このアカウントはBotです"
is-cat: "このアカウントはCatです"
profile-updated: "プロフィールを更新しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
edit: "オプション"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "{}がRenote"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "ハッシュ (md5)"
exif: "EXIF"
nsfw: "閲覧注意"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "閲覧注意"
click-to-show: "クリックして表示"
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?"
mobile/views/pages/games/reversi.vue:
reversi: "リバーシ"
mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-locked: "フォローを承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
mobile/views/pages/search.vue:
search: "検索"
empty: "「{}」に関する投稿は見つかりませんでした。"

View File

@ -5,7 +5,7 @@ meta:
common:
misskey: "Une ⭐ du fédiverse"
about-title: "Une ⭐ du fédivers."
about: "Merci d'avoir découvert Misskey. Misskey est une <b>plateforme de microblogage distribuée</b> née sur Terre. Parce qu'il fait partie du Fédivers (un univers composé de diverses plateformes de réseaux sociaux organisées), il est mutuellement connecté avec d'autres plateformes de réseaux sociaux. Désirez-vous prendre une pause, pendant un instant, loin de l'agitation de la ville et plonger dans un nouvel Internet ?"
about: "Merci davoir choisis Misskey. Misskey est une <b>plateforme de micro-blogging distribuée</b> née sur Terre et fait partie du Fédiverse (un univers composé de diverses plateformes de réseaux sociaux organisées), elle est connectée mutuellement avec dautres plateformes de réseaux sociaux. Désirez-vous prendre une pause, un court instant, loin de lagitation de la ville et plonger dans un Internet dun nouveau genre ?"
intro:
title: "Cest quoi Misskey ?"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
@ -43,7 +43,7 @@ common:
quoted-by: "Cité·e par {} :"
time:
unknown: "inconnu"
future: "à l'instant"
future: "à linstant"
just_now: "à l'instant"
seconds_ago: "Il y a {} seconde·s"
minutes_ago: "Il y a {} minute·s"
@ -106,11 +106,11 @@ common:
my-token-regenerated: "Votre jeton vient dêtre généré, vous allez maintenant être déconnecté."
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-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
use-contrast-reversi-stones: "Icône avec contraste sur Reversi"
verified-user: "Compte vérifié"
disable-animated-mfm: "Désactiver les textes animés dans les publications"
always-show-nsfw: "常に閲覧注意のメディアを表示する"
always-mark-nsfw: "常にメディアを閲覧注意として投稿"
always-show-nsfw: "Toujours afficher les contenus sensibles"
always-mark-nsfw: "Toujours marquer les notes ayant des attachements comme sensibles"
show-full-acct: "Afficher ladresse complète de lutilisateur"
reduce-motion: "Réduire les animations dans linterface utilisateur"
this-setting-is-this-device-only: "Uniquement sur cet appareil"
@ -254,7 +254,7 @@ common/views/components/connect-failed.troubleshooter.vue:
no-network: "Aucune connexion au réseau"
no-network-desc: "Veuillez vérifier que vous êtes bien connecté au réseau."
no-internet: "Aucune connexion internet."
no-internet-desc: "Veuillez vérifier que vous êtes bien connecté à internet."
no-internet-desc: "Assurez-vous que vous êtes bien connectés à internet."
no-server: "Impossible de se connecter au serveur"
no-server-desc: "Votre connexion semble correcte, mais il a été impossible de vous connecter au serveur de Misskey. Il se peut que le serveur soit hors-ligne ou en maintenance, veuillez ressayer plus tard."
success: "Connexion au serveur de Misskey réussie !"
@ -265,8 +265,8 @@ common/views/components/media-banner.vue:
sensitive: "Contenu sensible"
click-to-show: "Cliquer pour afficher"
common/views/components/theme.vue:
light-theme: "非ダークモード時に使用するテーマ"
dark-theme: "ダークモード時に使用するテーマ"
light-theme: "Thème durant le mode clair"
dark-theme: "Thème durant le mode sombre"
light-themes: "Thème clair"
dark-themes: "Thème sombre"
install-a-theme: "Installer un thème"
@ -335,7 +335,7 @@ common/views/components/note-menu.vue:
detail: "Détails"
copy-link: "Copier le lien"
favorite: "Mettre cette note en favoris"
unfavorite: "お気に入り解除"
unfavorite: "Retirer des favoris"
pin: "Épingler sur votre profil"
unpin: "Désépingler"
delete: "Supprimer"
@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{} utilisateurs·rices mentionnés·es"
empty: "Aucune tendance"
common/views/components/profile-editor.vue:
title: "Profil"
name: "Nom"
account: "Compte"
location: "Lieu"
description: "À propos de moi"
birthday: "Date de naissance"
avatar: "Avatar"
banner: "Bannière"
is-cat: "Ce compte est un Chat"
is-bot: "Ce compte est un Bot"
is-locked: "Demandes dabonnements requièrent lapprobation"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "Avancé"
privacy: "Vie privée"
save: "Mettre à jour le profil"
saved: "Profil mis à jour avec succès"
uploading: "En cours d'envoi …"
upload-failed: "Échec de l'envoi"
common/views/widgets/broadcast.vue:
fetching: "Récupération"
no-broadcasts: "Aucune annonce"
@ -640,14 +659,14 @@ desktop/views/components/note-detail.vue:
location: "Géolocalisation"
renote: "Republier"
add-reaction: "Ajouter votre reaction"
desktop/views/components/notes.note.vue:
reposted-by: "Reposté par {}"
desktop/views/components/note.vue:
reposted-by: "Partagé par {}"
reply: "Répondre"
renote: "Republier"
add-reaction: "Ajouter votre reaction"
detail: "Afficher les détails"
private: "cette publication est privée"
deleted: "cette publication a été supprimée"
renote: "Partager"
add-reaction: "リアクション"
detail: "詳細"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/components/notes.vue:
error: "Échec du chargement."
retry: "Réessayer"
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "Paramètres avancés"
api-via-stream: "Requête API via le flux"
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。"
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "Affichage et design"
customize: "Personnaliser l'Accueil"
wallpaper: "壁紙"
choose-wallpaper: "Sélectionner un fond d'écran"
delete-wallpaper: "Supprimer le fond d'écran"
dark-mode: "Mode nuit"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie"
show-clock-on-header: "Afficher l'horloge à droite sur le coté supérieur"
show-reply-target: "Afficher les réponses"
timeline: "タイムライン"
show-my-renotes: "Afficher mes republications dans le fil"
show-renoted-my-notes: "Afficher mes republications dans les fils"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Afficher la carte"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "Son"
enable-sounds: "Activer le son"
enable-sounds-desc: "Jouer un son lorsque vous recevez un message. Ce paramètre est sauvegardé dans le navigateur."
volume: "Volume"
test: "Test"
mobile: "Mobile"
disable-via-mobile: "Enlever la mention publié via 'un périphérique mobile'"
language: "Langue"
pick-language: "Sélectionner une langue"
recommended: "Recommandé"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "Outils"
task-manager: "Gestionnaire de tâches"
third-parties: "Services tiers"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "En haut"
navbar-position-left: "à gauche"
navbar-position-right: "à droite"
desktop/views/components/settings.2fa.vue:
intro: "Si vous configurez la vérication en deux étapes vous aurez non seulement besoin de votre mot de passe mais aussi un appareil déjà pré-enregistré(tel que votre smartphone) ce qui ameliora grandement la sécurité de votre compte."
detail: "Voir les détails..."
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "Entrez à nouveau le nouveau mot de passe"
not-match: "Le nouveau mot de passe ne correspond pas."
changed: "Mot de passe modifié avec succès"
desktop/views/components/settings.profile.vue:
avatar: "Avatar"
choice-avatar: "Choose an image"
name: "Nom"
location: "Localisation"
description: "Description"
birthday: "Date de naissance"
save: "Mettre à jour le profil"
locked-account: "Protéger votre compte"
is-locked: "Demande dabonnement en attente dapprobation"
other: "Autre"
is-bot: "Ce compte est un Bot"
is-cat: "Ce compte est un Chat"
profile-updated: "Profil mis à jour"
desktop/views/components/sub-note-content.vue:
private: "cette publication est privée"
deleted: "cette publication a été supprimée"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "Les publications médias uniquement"
is-media-view: "Vue média"
edit: "Options"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "Reposté par {}"
private: "cette publication est privée"
deleted: "cette publication a été supprimée"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "Toutes les utilisateurrices"
original-users: "Utilisateur·rice·s sur cette instance"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "Hash (md5)"
exif: "EXIF"
nsfw: "CW"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "Le contenu est NSFW"
click-to-show: "Cliquer pour afficher"
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "Êtes vous sûr de vouloir marqués toutes les notifications non-lus en tant que lus?"
mobile/views/pages/games/reversi.vue:
reversi: "Reversi"
mobile/views/pages/settings/settings.profile.vue:
title: "Profil"
name: "Nom"
account: "Compte"
location: "Lieu"
description: "Description"
birthday: "Date de naissance"
avatar: "Avatar"
banner: "Bannière"
is-cat: "Ce compte est un Bot"
is-locked: "Demande dabonnement en attente dapprobation"
advanced: "Avancé"
privacy: "Vie privée"
save: "Mettre à jour le profil"
saved: "Profil mis à jour avec succès"
uploading: "En cours d'envoi"
upload-failed: "Échec de l'envoi"
mobile/views/pages/search.vue:
search: "Chercher"
empty: "Aucun message trouvé pour '{}' "

View File

@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "確認中"
no-broadcasts: "お知らせはありません"
@ -640,7 +659,7 @@ desktop/views/components/note-detail.vue:
location: "位置情報"
renote: "Renote"
add-reaction: "リアクション"
desktop/views/components/notes.note.vue:
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "返信"
renote: "Renote"
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "詳細設定"
api-via-stream: "ストリームを経由したAPIリクエスト"
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。"
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "デザインと表示"
customize: "ホームをカスタマイズ"
wallpaper: "壁紙"
choose-wallpaper: "壁紙を選択"
delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-clock-on-header: "右上に時計を表示する"
show-reply-target: "リプライ先を表示する"
timeline: "タイムライン"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。"
volume: "ボリューム"
test: "テスト"
mobile: "モバイル"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
language: "言語"
pick-language: "言語を選択"
recommended: "推奨"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "ツール"
task-manager: "タスクマネージャ"
third-parties: "サードパーティ"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
detail: "詳細..."
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/settings.profile.vue:
avatar: "アイコン"
choice-avatar: "画像を選択"
name: "名前"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
save: "保存"
locked-account: "アカウントの保護"
is-locked: "フォローを承認制にする"
other: "その他"
is-bot: "このアカウントはBotです"
is-cat: "このアカウントはCatです"
profile-updated: "プロフィールを更新しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
edit: "オプション"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "{}がRenote"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "ハッシュ (md5)"
exif: "EXIF"
nsfw: "閲覧注意"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "閲覧注意"
click-to-show: "クリックして表示"
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?"
mobile/views/pages/games/reversi.vue:
reversi: "リバーシ"
mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-locked: "フォローを承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
mobile/views/pages/search.vue:
search: "検索"
empty: "「{}」に関する投稿は見つかりませんでした。"

View File

@ -456,6 +456,26 @@ common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "確認中"
no-broadcasts: "お知らせはありません"
@ -718,7 +738,7 @@ desktop/views/components/note-detail.vue:
renote: "Renote"
add-reaction: "リアクション"
desktop/views/components/notes.note.vue:
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "返信"
renote: "Renote"
@ -814,9 +834,13 @@ desktop/views/components/settings.vue:
advanced: "詳細設定"
api-via-stream: "ストリームを経由したAPIリクエスト"
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。"
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "デザインと表示"
customize: "ホームをカスタマイズ"
wallpaper: "壁紙"
choose-wallpaper: "壁紙を選択"
delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード"
@ -828,10 +852,14 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-clock-on-header: "右上に時計を表示する"
show-reply-target: "リプライ先を表示する"
timeline: "タイムライン"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
@ -839,9 +867,6 @@ desktop/views/components/settings.vue:
volume: "ボリューム"
test: "テスト"
mobile: "モバイル"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
language: "言語"
pick-language: "言語を選択"
recommended: "推奨"
@ -883,6 +908,11 @@ desktop/views/components/settings.vue:
task-manager: "タスクマネージャ"
third-parties: "サードパーティ"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
detail: "詳細..."
@ -928,22 +958,6 @@ desktop/views/components/settings.password.vue:
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/settings.profile.vue:
avatar: "アイコン"
choice-avatar: "画像を選択"
name: "名前"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
save: "保存"
locked-account: "アカウントの保護"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
other: "その他"
is-bot: "このアカウントはBotです"
is-cat: "このアカウントはCatです"
profile-updated: "プロフィールを更新しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@ -1064,10 +1078,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-view: "メディアビュー"
edit: "オプション"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "{}がRenote"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
@ -1234,6 +1246,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "ハッシュ (md5)"
exif: "EXIF"
nsfw: "閲覧注意"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "閲覧注意"
@ -1410,25 +1424,6 @@ mobile/views/pages/notifications.vue:
mobile/views/pages/games/reversi.vue:
reversi: "リバーシ"
mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
mobile/views/pages/search.vue:
search: "検索"
empty: "「{}」に関する投稿は見つかりませんでした。"

View File

@ -17,7 +17,7 @@ common:
ui: "インターフェイス"
ui-desc: "このUIええ言うてたで、知らんけど。あんたの好みのUIなんて知ったこっちゃない。Misskeyは好きにいじれるからな、レイアウトやデザイン変えたり、色んなウィジェットひっつけたりして、あんただけのMisskey作って楽しんでな"
drive: "ドライブ"
drive-desc: "「こないだの画像、どこやったかな…また投稿したいんやけど…」「さっきのファイルあのフォルダに直しといて」そんなこと言わんとって。Misskeyはもとからドライブ機能持っとるさかい、心配あらへん。ファイルの「わけわけ」したってな。"
drive-desc: "「こないだの画像、どこやったかな…また投稿したいんやけど…」「さっきのファイルあのフォルダに直しといて」そんなこと言わんとって。Misskeyはもとからドライブ機能持っとるさかい、心配あらへん。ファイルの「わけわけ」したってな。"
outro: "Misskeyの機能は無限大や知らんけど。知らん言うとるやんけ、あんたが見に行けやMisskeyは分散型SNSやから、ここがあかんくても他がある。阪神でもオリックスでもワイは応援するで"
adblock:
detected: "広告ブロッカーを無効にしてや"
@ -369,7 +369,7 @@ common/views/components/signup.vue:
invitation-code: "招待コード"
invitation-info: "招待コードをもっとらんのやったら、<a href=\"{}\">管理者</a>まで連絡してや。"
username: "ユーザー名"
checking: "確認中や…"
checking: "確認中や…"
available: "使えるで"
unavailable: "もう使われとるで"
error: "通信あかんわ"
@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "流行は自分で作るんや"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "見てみるわ…"
no-broadcasts: "お知らせはあらへんで"
@ -491,10 +510,10 @@ desktop:
choose-avatar: "アバターにする画像選んでや"
invalid-filetype: "この形式のファイル無理やねん"
desktop/views/components/activity.chart.vue:
total: "黒いの 全部"
notes: "青いの 投稿"
replies: "赤いの 返信"
renotes: "みどり… Renotes"
total: "黒いの ... 全部"
notes: "青いの ... 投稿"
replies: "赤いの ... 返信"
renotes: "碧いの ... Renotes"
desktop/views/components/activity.vue:
title: "アクティビティ"
toggle: "表示変える"
@ -552,7 +571,7 @@ desktop/views/components/drive.file.vue:
unmark-as-sensitive: "やっぱ見せたるわ"
copy-url: "URLをコピー"
download: "ダウンロード"
else-files: "もっとあるで…"
else-files: "まだあんで..."
set-as-avatar: "アイコンにする"
set-as-banner: "バナーにする"
open-in-app: "アプリで開く"
@ -586,7 +605,7 @@ desktop/views/components/drive.vue:
url-upload: "URLアップロード"
url-of-file: "このURLのファイルをアップロードしたいねん"
url-upload-requested: "アップロードしたい言うといたで"
may-take-time: "アップロード終わるまで時間かかるわ、知らんけど。たこ焼き何個食べれるやろか…"
may-take-time: "アップロード終わるんにちょい時間かかるかもしれへんわ。"
create-folder: "フォルダー作成"
folder-name: "フォルダー名"
contextmenu:
@ -616,7 +635,7 @@ desktop/views/components/following.vue:
desktop/views/components/friends-maker.vue:
title: "おもろそうやな:"
empty: "おもろいユーザー居らんかったわ"
fetching: "読みんどるで…"
fetching: "読みんどります"
refresh: "もっとあるやろ!"
close: "さいなら"
desktop/views/components/game-window.vue:
@ -640,14 +659,14 @@ desktop/views/components/note-detail.vue:
location: "ここおるで:"
renote: "Renote"
add-reaction: "リアクション"
desktop/views/components/notes.note.vue:
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "返"
reply: "返"
renote: "Renote"
add-reaction: "リアクション"
detail: "もっと"
private: "この投稿は見せられへんわ"
deleted: "この投稿なんか無くなってもうたわ"
detail: "詳細"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/components/notes.vue:
error: "あかん、読み込めへんわ"
retry: "もっぺん"
@ -688,11 +707,11 @@ desktop/views/components/post-form-window.vue:
note: "新規投稿"
reply: "返す"
attaches: "添付: {}メディア"
uploading-media: "{}個のメディアを上げてるで…"
uploading-media: "{}個のメディアを上げとんねん……"
desktop/views/components/progress-dialog.vue:
waiting: "待っとる"
desktop/views/components/renote-form.vue:
quote: "ってくる…"
quote: "ってくる…"
cancel: "やめとくわ"
renote: "Renote"
reposting: "やっとります..."
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "もっと設定"
api-via-stream: "ストリームを経由したAPIリクエスト"
api-via-stream-desc: "この設定をオンにすると、WebSocket接続を経由してAPIリクエストが行われんで(パフォーマンス向上するかも、知らんけど)。オフにすると、ネイティブの fetch API が利用されるで。この設定はこのデバイスのみ有効やで。"
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "見た感じ"
customize: "ホームをカスタマイズ"
wallpaper: "壁紙"
choose-wallpaper: "壁紙選ぶ"
delete-wallpaper: "壁紙ほかす"
dark-mode: "夜にすんで"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示すんで"
show-clock-on-header: "右上をカリヨン広場にする(時計表示)"
show-reply-target: "どこにリプライするんや見せて"
timeline: "タイムライン"
show-my-renotes: "わしのRenoteもタイムライン載せてくれや"
show-renoted-my-notes: "わしのRenoteもタイムライン載せてくれや"
show-local-renotes: "ローカル投稿のRenoteも見たいんや"
show-maps: "地図勝手にバァーって開いてくれ"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "サウンド"
enable-sounds: "サウンド鳴らす"
enable-sounds-desc: "投稿やメッセージもろたとき、音鳴らしたるわ。大丈夫や、この設定はブラウザが覚えてくれとる。"
volume: "ボリューム"
test: "テスト"
mobile: "モバイル"
disable-via-mobile: "「モバイルからの投稿」フラグなんて要らんわ"
language: "言語"
pick-language: "言語選んでや"
recommended: "おすすめ"
@ -768,7 +793,7 @@ desktop/views/components/settings.vue:
update: "Misskey Update"
version: "バージョン:"
latest-version: "最新のバージョン:"
update-checking: "アップデートはあらへんか…"
update-checking: "アップデートはあらへんか…"
do-update: "アップデートあるか見てみる"
update-settings: "もっと設定"
prevent-update: "アップデートしたないわ、また今度や(やめときや)"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "ツール"
task-manager: "タスクマネージャ"
third-parties: "サードパーティ"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "二段階認証を設定すると、サインイン時にパスワードだけとちゃうくて、予め登録しておいた物理的なデバイス(例えばあんさんのスマートフォンなど)も必要になり、よりセキュリティが向上すんで。"
detail: "詳細..."
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "もういっぺんさらのパスワードを入れてや"
not-match: "パスワードがおうとらん"
changed: "パスワード変えたわ"
desktop/views/components/settings.profile.vue:
avatar: "アイコン"
choice-avatar: "画像選んでや"
name: "名前"
location: "場所"
description: "ワイのこと"
birthday: "誕生日"
save: "保存"
locked-account: "アカウント守る"
is-locked: "他人のフォローは許可してからや!"
other: "その他"
is-bot: "このアカウントはBotやで"
is-cat: "このアカウントはCatやで"
profile-updated: "プロフィールを更新したで"
desktop/views/components/sub-note-content.vue:
private: "この投稿は見せられへんわ"
deleted: "この投稿なんか無くなってもうたわ"
@ -898,7 +913,7 @@ desktop/views/components/users-list.vue:
all: "すべて"
iknow: "知っとる"
load-more: "もっと"
fetching: "読みんどるで…"
fetching: "読みんどります"
desktop/views/components/users-list-item.vue:
followed: "フォローされとるで"
desktop/views/components/window.vue:
@ -936,21 +951,19 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿だけや"
is-media-view: "メディアビュー"
edit: "オプション"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "{}がRenote"
private: "この投稿は見せられへんわ"
deleted: "この投稿なんか無くなってもうたわ"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "ここの人らだけ"
all-notes: "全ての投稿"
original-notes: "このインスタンスの投稿"
desktop/views/pages/welcome.vue:
about: "もっと…"
about: "もうちょい……"
gotit: "ほい"
signin: "サインイン"
signup: "サインアップ"
signin-button: "サインイン中…"
signin-button: "やっとる"
signup-button: "サインアップ"
timeline: "タイムライン"
announcements: "知っときや"
@ -984,11 +997,11 @@ desktop/views/pages/user-list.users.vue:
username: "ユーザー名"
desktop/views/pages/user/user.followers-you-know.vue:
title: "知っとるフォロワー"
loading: "読み込んどる…"
loading: "読み込んどります"
no-users: "フォロワー全員知らんわ"
desktop/views/pages/user/user.friends.vue:
title: "よう話すツレ"
loading: "読み込んどる…"
loading: "読み込んどります"
no-users: "よう話すツレは居らん"
desktop/views/pages/user/user.vue:
is-suspended: "このユーザーはあかんわ。凍結されとる。"
@ -998,7 +1011,7 @@ desktop/views/pages/user/user.home.vue:
last-used-at: "最後いつ来た?"
desktop/views/pages/user/user.photos.vue:
title: "写真"
loading: "読み込んどる…"
loading: "読み込んどります"
no-photos: "写真はあらへんで"
desktop/views/pages/user/user.profile.vue:
follows-you: "フォローされとるで"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "ハッシュ(md5)"
exif: "EXIF"
nsfw: "ちょっと見せられへんわ"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "見たらあかんで"
click-to-show: "押してみ、見せたるわ"
@ -1089,7 +1104,7 @@ mobile/views/components/follow-button.vue:
mobile/views/components/friends-maker.vue:
title: "おもろそうやな"
empty: "おすすめのユーザーはおらん。"
fetching: "読みんどるで…"
fetching: "読みんどります"
refresh: "もっとあるやろ!"
close: "さいなら"
mobile/views/components/note.vue:
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "通知全部読んだか?"
mobile/views/pages/games/reversi.vue:
reversi: "リバーシ"
mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "ワイのこと"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatや"
is-locked: "他人のフォローは許可してからや!"
advanced: "その他"
privacy: "プライバシーってなんや?オカンの年齢か?"
save: "保存"
saved: "プロフィールを保存したで"
uploading: "アップロードしとるで…"
upload-failed: "これアップロードでけへんわ"
mobile/views/pages/search.vue:
search: "探す"
empty: "ワイは「{}」なんて投稿知らんわ、無いんちゃう?知らんけど。"
@ -1276,7 +1274,7 @@ mobile/views/pages/settings.vue:
update: "あんたのMisskeyいつのや"
version: "バージョン:"
latest-version: "いっちゃん新しいやつ:"
update-checking: "アップデートはあらへんか…"
update-checking: "アップデートあるか見とるで"
check-for-updates: "アップデートあるんかな?"
no-updates: "アップデートあらへんわ"
no-updates-desc: "つこてるMisskeyは最新や"
@ -1307,16 +1305,16 @@ mobile/views/pages/user/home.vue:
followers-you-know: "知っとるフォロワー"
last-used-at: "最後いつ来た?"
mobile/views/pages/user/home.followers-you-know.vue:
loading: "読み込んどる…"
loading: "読み込んどります"
no-users: "知っとるユーザーは居らん"
mobile/views/pages/user/home.friends.vue:
loading: "読み込んどる…"
loading: "読み込んどります"
no-users: "よう話すユーザーは居らん"
mobile/views/pages/user/home.notes.vue:
loading: "読み込んどる…"
loading: "読み込んどります"
no-notes: "投稿はあらへん"
mobile/views/pages/user/home.photos.vue:
loading: "読み込んどる…"
loading: "読み込んどります"
no-photos: "写真はあらへんで"
docs:
edit-this-page-on-github: "間違いや改善点を見つけましたか?"

View File

@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "確認中"
no-broadcasts: "お知らせはありません"
@ -640,7 +659,7 @@ desktop/views/components/note-detail.vue:
location: "位置情報"
renote: "Renote"
add-reaction: "リアクション"
desktop/views/components/notes.note.vue:
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "返信"
renote: "Renote"
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "詳細設定"
api-via-stream: "ストリームを経由したAPIリクエスト"
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。"
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "デザインと表示"
customize: "ホームをカスタマイズ"
wallpaper: "壁紙"
choose-wallpaper: "壁紙を選択"
delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-clock-on-header: "右上に時計を表示する"
show-reply-target: "リプライ先を表示する"
timeline: "タイムライン"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。"
volume: "ボリューム"
test: "テスト"
mobile: "モバイル"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
language: "言語"
pick-language: "言語を選択"
recommended: "推奨"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "ツール"
task-manager: "タスクマネージャ"
third-parties: "サードパーティ"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
detail: "詳細..."
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/settings.profile.vue:
avatar: "アイコン"
choice-avatar: "画像を選択"
name: "名前"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
save: "保存"
locked-account: "アカウントの保護"
is-locked: "フォローを承認制にする"
other: "その他"
is-bot: "このアカウントはBotです"
is-cat: "このアカウントはCatです"
profile-updated: "プロフィールを更新しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
edit: "オプション"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "{}がRenote"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "ハッシュ (md5)"
exif: "EXIF"
nsfw: "閲覧注意"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "閲覧注意"
click-to-show: "クリックして表示"
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?"
mobile/views/pages/games/reversi.vue:
reversi: "リバーシ"
mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-locked: "フォローを承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
mobile/views/pages/search.vue:
search: "検索"
empty: "「{}」に関する投稿は見つかりませんでした。"

View File

@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "Bezig met ophalen"
no-broadcasts: "Geen uitzendingen"
@ -640,12 +659,12 @@ desktop/views/components/note-detail.vue:
location: "Locatie"
renote: "Renote"
add-reaction: "リアクション"
desktop/views/components/notes.note.vue:
reposted-by: "Hergeplaatst door {}"
reply: "Antwoord"
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "返信"
renote: "Renote"
add-reaction: "Reactie toevoegen"
detail: "Details tonen"
add-reaction: "リアクション"
detail: "詳細"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/components/notes.vue:
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "Geavanceerde instellingen"
api-via-stream: "API-verzoek via stream"
api-via-stream-desc: "API-verzoek wordt uitgevoerd via de WebSocket-verbinding i.p.v. de ingebouwde ophaal-API (voor verbeterde prestaties). Deze instelling wordt opgeslagen in je browser."
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "Ontwerp en weergave"
customize: "Startpagina aanpassen"
wallpaper: "壁紙"
choose-wallpaper: "壁紙を選択"
delete-wallpaper: "壁紙を削除"
dark-mode: "Donkere modus"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-clock-on-header: "右上に時計を表示する"
show-reply-target: "Antwoord-knop tonen"
timeline: "タイムライン"
show-my-renotes: "Mijn renote tonen op de tijdlijn"
show-renoted-my-notes: "Mijn gerenote bericht tonen op de tijdlijn"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Kaart tonen"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "Geluid"
enable-sounds: "Geluid inschakelen"
enable-sounds-desc: "Een geluid afspelen bij het ontvangen van een bericht. Deze instelling wordt opgeslagen in je browser."
volume: "Volume"
test: "Testen"
mobile: "Mobiel"
disable-via-mobile: "Berichten niet markeren als 'via mobiel'"
language: "Taal"
pick-language: "Selecteer een taal"
recommended: "Aanbevolen"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "Hulpmiddelen"
task-manager: "Taakbeheer"
third-parties: "Derde partij"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "Als je verificatie in twee stappen instelt, dan heb je niet alleen een wachtwoord nodig bij het inloggen, maar ook een geregistreerd fysiek apparaat (zoals je smartphone). Dit verhoogt de veiligheid. "
detail: "Details bekijken..."
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "Voer je nieuwe wachtwoord nogmaals in"
not-match: "Het nieuwe wachtwoord komt niet overeen"
changed: "Wachtwoord bijgewerkt"
desktop/views/components/settings.profile.vue:
avatar: "Gebruikersafbeelding"
choice-avatar: "Kies een afbeelding"
name: "Naam"
location: "Locatie"
description: "Omschrijving"
birthday: "Geboortedatum"
save: "Profiel bijwerken"
locked-account: "アカウントの保護"
is-locked: "フォローを承認制にする"
other: "その他"
is-bot: "Dit account is een Bot"
is-cat: "Dit account is een Kat"
profile-updated: "プロフィールを更新しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
edit: "オプション"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "{}がRenote"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "Hash (md5)"
exif: "EXIF"
nsfw: "閲覧注意"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "閲覧注意"
click-to-show: "クリックして表示"
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "Weet je zeker dat je alle meldingen wilt markeren als gelezen?"
mobile/views/pages/games/reversi.vue:
reversi: "リバーシ"
mobile/views/pages/settings/settings.profile.vue:
title: "Profiel"
name: "Naam"
account: "Account"
location: "Locatie"
description: "Omschrijving"
birthday: "Geboortedatum"
avatar: "Gebruikersafbeelding"
banner: "Omslagfoto"
is-cat: "Dit account is een Kat"
is-locked: "フォローを承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "Profiel bijwerken"
saved: "Profiel bijgewerkt"
uploading: "Bezig met uploaden"
upload-failed: "Upload mislukt"
mobile/views/pages/search.vue:
search: "Zoeken"
empty: "Geen berichten gevonden voor '{}'"

View File

@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "Henter"
no-broadcasts: "お知らせはありません"
@ -640,12 +659,12 @@ desktop/views/components/note-detail.vue:
location: "Lokasjon"
renote: "Renote"
add-reaction: "リアクション"
desktop/views/components/notes.note.vue:
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "Svar"
reply: "返信"
renote: "Renote"
add-reaction: "リアクション"
detail: "Vis detaljer"
detail: "詳細"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/components/notes.vue:
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "Avanserte innstillinger"
api-via-stream: "ストリームを経由したAPIリクエスト"
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。"
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "デザインと表示"
customize: "ホームをカスタマイズ"
wallpaper: "壁紙"
choose-wallpaper: "壁紙を選択"
delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-clock-on-header: "右上に時計を表示する"
show-reply-target: "リプライ先を表示する"
timeline: "タイムライン"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "Lyd"
enable-sounds: "サウンドを有効にする"
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。"
volume: "Volum"
test: "Test"
mobile: "Mobil"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
language: "Språk"
pick-language: "Velg språk"
recommended: "Anbefalt"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "Verktøy"
task-manager: "タスクマネージャ"
third-parties: "サードパーティ"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
detail: "Detaljer..."
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/settings.profile.vue:
avatar: "Avatar"
choice-avatar: "Velg et bilde"
name: "Navn"
location: "Lokasjon"
description: "Om meg"
birthday: "Bursdag"
save: "Lagre profilen"
locked-account: "アカウントの保護"
is-locked: "フォローを承認制にする"
other: "Annet"
is-bot: "このアカウントはBotです"
is-cat: "このアカウントはCatです"
profile-updated: "プロフィールを更新しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
edit: "オプション"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "{}がRenote"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "ハッシュ (md5)"
exif: "EXIF"
nsfw: "NSFW"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "NSFW"
click-to-show: "クリックして表示"
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?"
mobile/views/pages/games/reversi.vue:
reversi: "Reversi"
mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール"
name: "Navn"
account: "Konto"
location: "Lokasjon"
description: "Om meg"
birthday: "Bursdag"
avatar: "Avatar"
banner: "Banner"
is-cat: "このアカウントはCatです"
is-locked: "フォローを承認制にする"
advanced: "Avansert"
privacy: "プライバシー"
save: "Lagre profilen"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
mobile/views/pages/search.vue:
search: "Søk"
empty: "「{}」に関する投稿は見つかりませんでした。"

View File

@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "Sprawdzanie"
no-broadcasts: "Brak transmisji"
@ -640,14 +659,14 @@ desktop/views/components/note-detail.vue:
location: "Informacje o lokalizacji"
renote: "Udostępnienie"
add-reaction: "Dodaj reakcję"
desktop/views/components/notes.note.vue:
reposted-by: "Udostępniono przez {}"
reply: "Odpowiedz"
renote: "Udostępnij"
add-reaction: "Dodaj reakcję"
detail: "Pokaż szczegóły"
private: "ten wpis jest prywatny"
deleted: "ten wpis został usunięty"
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "返信"
renote: "Renote"
add-reaction: "リアクション"
detail: "詳細"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/components/notes.vue:
error: "Ładowanie nie powiodło się."
retry: "Spróbuj ponownie"
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "Ustawienia zaawansowane"
api-via-stream: "ストリームを経由したAPIリクエスト"
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。"
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "Wygląd i wyświetlanie"
customize: "Dostosuj stronę główną"
wallpaper: "壁紙"
choose-wallpaper: "Wybierz tło"
delete-wallpaper: "Usuń tło"
dark-mode: "Tryb ciemny"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-clock-on-header: "右上に時計を表示する"
show-reply-target: "Pokazuj cel odpowiedzi"
timeline: "タイムライン"
show-my-renotes: "Pokazuj moje udostępnienia na osi czasu"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Automatycznie pokazuj mapę"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "Dźwięk"
enable-sounds: "Włącz dźwięk"
enable-sounds-desc: "Odtwarzaj dźwięk przy wstawianiu wpisów, wysyłaniu lub otrzymywaniu wiadomości. Opcja ta jest zapamiętywana przez przeglądarkę."
volume: "Głośność"
test: "Test"
mobile: "Wersja mobilna"
disable-via-mobile: "Nie oznaczaj wpisów jako „wysłane z telefonu”"
language: "Język"
pick-language: "Wybierz język"
recommended: "Zalecane"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "Narzędzia"
task-manager: "Menedżer zadań"
third-parties: "Autorzy trzeci"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "Jeżeli skonfigurujesz uwierzytelnianie dwuetapowe, aby zablokować się będziesz potrzebować (oprócz hasła) kodu ze skonfigurowanego urządzenia (np. smartfonu), co zwiększy bezpieczeństwo."
detail: "Zobacz szczegóły…"
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "Wprowadź ponownie nowe hasło"
not-match: "Nowe hasła nie pasują do siebie"
changed: "Pomyślnie zmieniono hasło"
desktop/views/components/settings.profile.vue:
avatar: "Awatar"
choice-avatar: "Wybierz obraz"
name: "Nazwa"
location: "Lokalizacja"
description: "Opis"
birthday: "Data urodzenia"
save: "Aktualizuj profil"
locked-account: "Zabezpiecz swoje konto"
is-locked: "フォローを承認制にする"
other: "Inne"
is-bot: "To konto jest prowadzone przez bota"
is-cat: "To konto jest prowadzone przez kota"
profile-updated: "Zaktualizowano profil"
desktop/views/components/sub-note-content.vue:
private: "ten wpis jest prywatny"
deleted: "ten wpis został usunięty"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "Tylko wpisy z zawartością multimedialną"
is-media-view: "Widok multimediów"
edit: "Opcje"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "Udostępniono przez {}"
private: "ten wpis jest prywatny"
deleted: "ten wpis został usunięty"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "Hash (md5)"
exif: "EXIF"
nsfw: "閲覧注意"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "To jest zawartość NSFW"
click-to-show: "Naciśnij aby wyświetlić"
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "Czy na pewno chcesz oznaczyć wszystkie powiadomienia jako przeczytane?"
mobile/views/pages/games/reversi.vue:
reversi: "Reversi"
mobile/views/pages/settings/settings.profile.vue:
title: "Profil"
name: "Nazwa"
account: "Konto"
location: "Lokalizacja"
description: "Opis"
birthday: "Data urodzenia"
avatar: "Awatar"
banner: "Baner"
is-cat: "To konto jest prowadzone przez kota"
is-locked: "フォローを承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "Aktualizuj profil"
saved: "Pomyślnie zaktualizowano profil"
uploading: "Wysyłanie"
upload-failed: "Wysyłanie nie powiodło się"
mobile/views/pages/search.vue:
search: "Szukaj"
empty: "Nie znaleziono wpisów zawierających '{}'"

View File

@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "確認中"
no-broadcasts: "お知らせはありません"
@ -640,7 +659,7 @@ desktop/views/components/note-detail.vue:
location: "位置情報"
renote: "Renote"
add-reaction: "リアクション"
desktop/views/components/notes.note.vue:
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "返信"
renote: "Renote"
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "詳細設定"
api-via-stream: "ストリームを経由したAPIリクエスト"
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。"
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "デザインと表示"
customize: "ホームをカスタマイズ"
wallpaper: "壁紙"
choose-wallpaper: "壁紙を選択"
delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-clock-on-header: "右上に時計を表示する"
show-reply-target: "リプライ先を表示する"
timeline: "タイムライン"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。"
volume: "ボリューム"
test: "テスト"
mobile: "モバイル"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
language: "言語"
pick-language: "言語を選択"
recommended: "推奨"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "ツール"
task-manager: "タスクマネージャ"
third-parties: "サードパーティ"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
detail: "詳細..."
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/settings.profile.vue:
avatar: "アイコン"
choice-avatar: "画像を選択"
name: "名前"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
save: "保存"
locked-account: "アカウントの保護"
is-locked: "フォローを承認制にする"
other: "その他"
is-bot: "このアカウントはBotです"
is-cat: "このアカウントはCatです"
profile-updated: "プロフィールを更新しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
edit: "オプション"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "{}がRenote"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "ハッシュ (md5)"
exif: "EXIF"
nsfw: "閲覧注意"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "閲覧注意"
click-to-show: "クリックして表示"
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?"
mobile/views/pages/games/reversi.vue:
reversi: "リバーシ"
mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール"
name: "Nome"
account: "Conta"
location: "Lugar"
description: "Biografia"
birthday: "Data de nascimento"
avatar: "Avatar"
banner: "Capa"
is-cat: "Esta conta é gato"
is-locked: "Pedido para seguir precisa ser aprovado"
advanced: "Avançado"
privacy: "Provacidade"
save: "Atualizar perfil"
saved: "Perfil atualizado"
uploading: "Enviando"
upload-failed: "Falha ao enviar"
mobile/views/pages/search.vue:
search: "Pesquisar"
empty: "「{}」に関する投稿は見つかりませんでした。"

View File

@ -3,9 +3,9 @@ meta:
lang: "Русский язык"
divider: ""
common:
misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse."
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。"
misskey: "Мы — ⭐ fediverse"
about-title: "Мы — ⭐ fediverse"
about: "Спасибо, что нашли Misskey. Misskey — это <b>децентрализованная платформа для микроблоггинга</b> родом с планеты Земля. Поскольку она существует внутри Fediverse (вселенной различных социальных платформ), она связана с другими платформами. Отдохните от шума большого города — и познакомьтесь с новым интернетом."
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "確認中"
no-broadcasts: "お知らせはありません"
@ -640,7 +659,7 @@ desktop/views/components/note-detail.vue:
location: "位置情報"
renote: "Renote"
add-reaction: "リアクション"
desktop/views/components/notes.note.vue:
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "返信"
renote: "Renote"
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "詳細設定"
api-via-stream: "ストリームを経由したAPIリクエスト"
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。"
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "デザインと表示"
customize: "ホームをカスタマイズ"
wallpaper: "壁紙"
choose-wallpaper: "壁紙を選択"
delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-clock-on-header: "右上に時計を表示する"
show-reply-target: "リプライ先を表示する"
timeline: "タイムライン"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。"
volume: "ボリューム"
test: "テスト"
mobile: "モバイル"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
language: "言語"
pick-language: "言語を選択"
recommended: "推奨"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "ツール"
task-manager: "タスクマネージャ"
third-parties: "サードパーティ"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
detail: "詳細..."
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/settings.profile.vue:
avatar: "アイコン"
choice-avatar: "画像を選択"
name: "名前"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
save: "保存"
locked-account: "アカウントの保護"
is-locked: "フォローを承認制にする"
other: "その他"
is-bot: "このアカウントはBotです"
is-cat: "このアカウントはCatです"
profile-updated: "プロフィールを更新しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
edit: "オプション"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "{}がRenote"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "ハッシュ (md5)"
exif: "EXIF"
nsfw: "閲覧注意"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "閲覧注意"
click-to-show: "クリックして表示"
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?"
mobile/views/pages/games/reversi.vue:
reversi: "リバーシ"
mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-locked: "フォローを承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
mobile/views/pages/search.vue:
search: "検索"
empty: "「{}」に関する投稿は見つかりませんでした。"

View File

@ -416,6 +416,25 @@ common/views/components/visibility-chooser.vue:
common/views/components/trends.vue:
count: "{}人が投稿"
empty: "トレンドなし"
common/views/components/profile-editor.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-bot: "このアカウントはBotです"
is-locked: "フォローを承認制にする"
careful-bot: "Botからのフォローだけ承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
common/views/widgets/broadcast.vue:
fetching: "確認中"
no-broadcasts: "お知らせはありません"
@ -640,7 +659,7 @@ desktop/views/components/note-detail.vue:
location: "位置情報"
renote: "Renote"
add-reaction: "リアクション"
desktop/views/components/notes.note.vue:
desktop/views/components/note.vue:
reposted-by: "{}がRenote"
reply: "返信"
renote: "Renote"
@ -726,8 +745,12 @@ desktop/views/components/settings.vue:
advanced: "詳細設定"
api-via-stream: "ストリームを経由したAPIリクエスト"
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。"
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
display: "デザインと表示"
customize: "ホームをカスタマイズ"
wallpaper: "壁紙"
choose-wallpaper: "壁紙を選択"
delete-wallpaper: "壁紙を削除"
dark-mode: "ダークモード"
@ -739,17 +762,19 @@ desktop/views/components/settings.vue:
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
show-clock-on-header: "右上に時計を表示する"
show-reply-target: "リプライ先を表示する"
timeline: "タイムライン"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
deck-column-align: "デッキのカラムの位置"
deck-column-align-center: "中央"
deck-column-align-left: "左"
sound: "サウンド"
enable-sounds: "サウンドを有効にする"
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。"
volume: "ボリューム"
test: "テスト"
mobile: "モバイル"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
language: "言語"
pick-language: "言語を選択"
recommended: "推奨"
@ -785,6 +810,10 @@ desktop/views/components/settings.vue:
tools: "ツール"
task-manager: "タスクマネージャ"
third-parties: "サードパーティ"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: "上"
navbar-position-left: "左"
navbar-position-right: "右"
desktop/views/components/settings.2fa.vue:
intro: "二段階認証を設定すると、サインイン時にパスワードだけでなく、予め登録しておいた物理的なデバイス(例えばあなたのスマートフォンなど)も必要になり、よりセキュリティが向上します。"
detail: "詳細..."
@ -824,20 +853,6 @@ desktop/views/components/settings.password.vue:
enter-new-password-again: "もう一度新しいパスワードを入力してください"
not-match: "新しいパスワードが一致しません"
changed: "パスワードを変更しました"
desktop/views/components/settings.profile.vue:
avatar: "アイコン"
choice-avatar: "画像を選択"
name: "名前"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
save: "保存"
locked-account: "アカウントの保護"
is-locked: "フォローを承認制にする"
other: "その他"
is-bot: "このアカウントはBotです"
is-cat: "このアカウントはCatです"
profile-updated: "プロフィールを更新しました"
desktop/views/components/sub-note-content.vue:
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
@ -936,10 +951,8 @@ desktop/views/pages/deck/deck.tl-column.vue:
is-media-only: "メディア投稿のみ"
is-media-view: "メディアビュー"
edit: "オプション"
desktop/views/pages/deck/deck.note.vue:
reposted-by: "{}がRenote"
private: "この投稿は非公開です"
deleted: "この投稿は削除されました"
desktop/views/pages/deck/deck.user-column.vue:
pinned-notes: "ピン留めされた投稿"
desktop/views/pages/stats/stats.vue:
all-users: "全てのユーザー"
original-users: "このインスタンスのユーザー"
@ -1074,6 +1087,8 @@ mobile/views/components/drive.file-detail.vue:
hash: "ハッシュ (md5)"
exif: "EXIF"
nsfw: "閲覧注意"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
sensitive: "閲覧注意"
click-to-show: "クリックして表示"
@ -1214,23 +1229,6 @@ mobile/views/pages/notifications.vue:
read-all: "すべての通知を既読にしますか?"
mobile/views/pages/games/reversi.vue:
reversi: "リバーシ"
mobile/views/pages/settings/settings.profile.vue:
title: "プロフィール"
name: "名前"
account: "アカウント"
location: "場所"
description: "自己紹介"
birthday: "誕生日"
avatar: "アイコン"
banner: "バナー"
is-cat: "このアカウントはCatです"
is-locked: "フォローを承認制にする"
advanced: "その他"
privacy: "プライバシー"
save: "保存"
saved: "プロフィールを保存しました"
uploading: "アップロード中"
upload-failed: "アップロードに失敗しました"
mobile/views/pages/search.vue:
search: "検索"
empty: "「{}」に関する投稿は見つかりませんでした。"

View File

@ -1,8 +1,8 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "10.14.0",
"clientVersion": "1.0.10524",
"version": "10.26.0",
"clientVersion": "1.0.10762",
"codename": "nighthike",
"main": "./built/index.js",
"private": true,
@ -20,26 +20,27 @@
"format": "gulp format"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "1.2.4",
"@fortawesome/free-brands-svg-icons": "5.3.1",
"@fortawesome/free-regular-svg-icons": "5.3.1",
"@fortawesome/free-solid-svg-icons": "5.3.1",
"@fortawesome/fontawesome-svg-core": "1.2.6",
"@fortawesome/free-brands-svg-icons": "5.4.1",
"@fortawesome/free-regular-svg-icons": "5.4.1",
"@fortawesome/free-solid-svg-icons": "5.4.1",
"@koa/cors": "2.2.2",
"@prezzemolo/rap": "0.1.2",
"@prezzemolo/zip": "0.0.3",
"@types/bcryptjs": "2.4.2",
"@types/chai-http": "3.0.5",
"@types/dateformat": "1.0.1",
"@types/debug": "0.0.31",
"@types/deep-equal": "1.0.1",
"@types/double-ended-queue": "2.1.0",
"@types/elasticsearch": "5.0.27",
"@types/elasticsearch": "5.0.28",
"@types/file-type": "5.2.1",
"@types/gulp": "3.8.36",
"@types/gulp-htmlmin": "1.3.32",
"@types/gulp-mocha": "0.0.32",
"@types/gulp-rename": "0.0.33",
"@types/gulp-replace": "0.0.31",
"@types/gulp-uglify": "3.0.5",
"@types/gulp-uglify": "3.0.6",
"@types/gulp-util": "3.0.34",
"@types/is-root": "1.0.0",
"@types/is-url": "1.2.28",
@ -60,7 +61,7 @@
"@types/mocha": "5.2.3",
"@types/mongodb": "3.1.12",
"@types/ms": "0.7.30",
"@types/node": "10.11.7",
"@types/node": "10.12.0",
"@types/portscanner": "2.1.0",
"@types/pug": "2.0.4",
"@types/qrcode": "1.3.0",
@ -70,7 +71,7 @@
"@types/request-promise-native": "1.0.15",
"@types/rimraf": "2.0.2",
"@types/seedrandom": "2.4.27",
"@types/sharp": "0.17.10",
"@types/sharp": "0.21.0",
"@types/showdown": "1.7.5",
"@types/single-line-log": "1.1.0",
"@types/speakeasy": "2.0.2",
@ -78,7 +79,7 @@
"@types/tinycolor2": "1.4.1",
"@types/tmp": "0.0.33",
"@types/uuid": "3.4.4",
"@types/webpack": "4.4.16",
"@types/webpack": "4.4.17",
"@types/webpack-stream": "3.2.10",
"@types/websocket": "0.0.40",
"@types/ws": "6.0.1",
@ -90,8 +91,10 @@
"bee-queue": "1.2.2",
"bootstrap-vue": "2.0.0-rc.11",
"cafy": "11.3.0",
"chai": "4.2.0",
"chai-http": "4.2.0",
"chalk": "2.4.1",
"chart.js": "2.7.2",
"chart.js": "2.7.3",
"commander": "2.19.0",
"crc-32": "1.2.0",
"css-loader": "1.0.0",
@ -157,7 +160,7 @@
"mkdirp": "0.5.1",
"mocha": "5.2.0",
"moji": "0.5.1",
"mongodb": "3.1.1",
"mongodb": "3.1.8",
"monk": "6.0.6",
"ms": "2.1.1",
"nan": "2.11.1",
@ -176,7 +179,7 @@
"qrcode": "1.3.0",
"ratelimiter": "3.2.0",
"recaptcha-promise": "0.1.3",
"reconnecting-websocket": "4.1.8",
"reconnecting-websocket": "4.1.10",
"redis": "2.8.0",
"request": "2.88.0",
"request-promise-native": "1.0.5",
@ -187,7 +190,7 @@
"sass-loader": "7.1.0",
"seedrandom": "2.4.4",
"sharp": "0.21.0",
"showdown": "1.8.6",
"showdown": "1.8.7",
"showdown-highlightjs-extension": "0.1.2",
"single-line-log": "1.1.2",
"speakeasy": "2.0.0",
@ -220,8 +223,8 @@
"vue-loader": "15.4.2",
"vue-router": "3.0.1",
"vue-style-loader": "4.1.2",
"vue-svg-inline-loader": "1.2.0",
"vue-sweetalert2": "1.5.5",
"vue-svg-inline-loader": "1.2.1",
"vue-sweetalert2": "1.5.6",
"vue-template-compiler": "2.5.17",
"vuedraggable": "2.16.0",
"vuewordcloud": "18.7.11",
@ -229,7 +232,7 @@
"vuex-persistedstate": "2.5.4",
"web-push": "3.3.3",
"webfinger.js": "2.6.6",
"webpack": "4.20.2",
"webpack": "4.21.0",
"webpack-cli": "3.1.2",
"websocket": "1.0.28",
"ws": "6.1.0",

View File

@ -46,6 +46,16 @@ const getKeyMap = keymap => Object.entries(keymap).map(([patterns, callback]): a
const ignoreElemens = ['input', 'textarea'];
function match(e: KeyboardEvent, patterns: action['patterns']): boolean {
const key = e.code.toLowerCase();
return patterns.some(pattern => pattern.which.includes(key) &&
pattern.ctrl == e.ctrlKey &&
pattern.shift == e.shiftKey &&
pattern.alt == e.altKey &&
e.metaKey == false
);
}
export default {
install(Vue) {
Vue.directive('hotkey', {
@ -55,37 +65,27 @@ export default {
const actions = getKeyMap(binding.value);
// flatten
const reservedKeys = concat(concat(actions.map(a => a.patterns.map(p => p.which))));
const reservedKeys = concat(actions.map(a => a.patterns));
el.dataset.reservedKeys = reservedKeys.map(key => `'${key}'`).join(' ');
el.dataset.reservedKeys = JSON.stringify(reservedKeys);
el._keyHandler = (e: KeyboardEvent) => {
const key = e.code.toLowerCase();
const targetReservedKeys = document.activeElement ? ((document.activeElement as any).dataset || {}).reservedKeys || '' : '';
const targetReservedKeys = JSON.parse(document.activeElement ? ((document.activeElement as any).dataset || {}).reservedKeys || '[]' : '[]');
if (document.activeElement && ignoreElemens.some(el => document.activeElement.matches(el))) return;
for (const action of actions) {
if (el._hotkey_global && targetReservedKeys.includes(`'${key}'`)) break;
const matched = action.patterns.some(pattern => {
const matched = pattern.which.includes(key) &&
pattern.ctrl == e.ctrlKey &&
pattern.shift == e.shiftKey &&
pattern.alt == e.altKey &&
e.metaKey == false;
const matched = match(e, action.patterns);
if (matched) {
if (el._hotkey_global) {
if (match(e, targetReservedKeys)) {
return;
}
}
e.preventDefault();
e.stopPropagation();
action.callback(e);
return true;
} else {
return false;
}
});
if (matched) {
break;
}
}

View File

@ -29,14 +29,18 @@ export default (opts: Opts = {}) => ({
computed: {
keymap(): any {
return {
'r|left': () => this.reply(true),
'r': () => this.reply(true),
'e|a|plus': () => this.react(true),
'q|right': () => this.renote(true),
'q': () => this.renote(true),
'f|b': this.favorite,
'delete|ctrl+d': this.del,
'ctrl+q|ctrl+right': this.renoteDirectly,
'ctrl+q': this.renoteDirectly,
'up|k|shift+tab': this.focusBefore,
'down|j|tab': this.focusAfter,
'shift+up': () => this.$emit('parentFocus', 'up'),
'shift+down': () => this.$emit('parentFocus', 'down'),
'shift+left': () => this.$emit('parentFocus', 'left'),
'shift+right': () => this.$emit('parentFocus', 'right'),
'esc': this.blur,
'm|o': () => this.menu(true),
's': this.toggleShowContent,

View File

@ -1,5 +1,6 @@
import Vue from 'vue';
import profileEditor from './profile-editor.vue';
import noteSkeleton from './note-skeleton.vue';
import theme from './theme.vue';
import instance from './instance.vue';
@ -45,6 +46,7 @@ import uiSelect from './ui/select.vue';
import formButton from './ui/form/button.vue';
import formRadio from './ui/form/radio.vue';
Vue.component('mk-profile-editor', profileEditor);
Vue.component('mk-note-skeleton', noteSkeleton);
Vue.component('mk-theme', theme);
Vue.component('mk-instance', instance);

View File

@ -116,16 +116,16 @@ export default Vue.component('misskey-flavored-markdown', {
case 'mention': {
return (createElement as any)('a', {
attrs: {
href: `${url}/@${getAcct(token)}`,
href: `${url}/${token.canonical}`,
target: '_blank',
dataIsMe: (this as any).i && getAcct((this as any).i) == getAcct(token),
style: 'color:var(--mfmMention);'
},
directives: [{
name: 'user-preview',
value: token.content
value: token.canonical
}]
}, token.content);
}, token.canonical);
}
case 'hashtag': {

View File

@ -49,6 +49,7 @@
<div>
<ui-switch v-model="isCat" @change="save(false)">%i18n:@is-cat%</ui-switch>
<ui-switch v-model="isBot" @change="save(false)">%i18n:@is-bot%</ui-switch>
<ui-switch v-model="alwaysMarkNsfw">%i18n:common.always-mark-nsfw%</ui-switch>
</div>
</section>
@ -66,7 +67,7 @@
<script lang="ts">
import Vue from 'vue';
import { apiUrl, host } from '../../../../config';
import { apiUrl, host } from '../../../config';
export default Vue.extend({
data() {
@ -80,6 +81,7 @@ export default Vue.extend({
avatarId: null,
bannerId: null,
isCat: false,
isBot: false,
isLocked: false,
carefulBot: false,
saving: false,
@ -104,6 +106,7 @@ export default Vue.extend({
this.avatarId = this.$store.state.i.avatarId;
this.bannerId = this.$store.state.i.bannerId;
this.isCat = this.$store.state.i.isCat;
this.isBot = this.$store.state.i.isBot;
this.isLocked = this.$store.state.i.isLocked;
this.carefulBot = this.$store.state.i.carefulBot;
},
@ -164,6 +167,7 @@ export default Vue.extend({
avatarId: this.avatarId,
bannerId: this.bannerId,
isCat: this.isCat,
isBot: this.isBot,
isLocked: this.isLocked,
carefulBot: this.carefulBot
}).then(i => {

View File

@ -1,5 +1,5 @@
<template>
<div class="ui-card">
<div class="ui-card" :class="{ shadow: $store.state.settings.useShadow }">
<header>
<slot name="title"></slot>
</header>
@ -24,6 +24,9 @@ export default Vue.extend({
margin 16px
color var(--faceText)
background var(--face)
border-radius var(--round)
&.shadow
box-shadow 0 3px 1px -2px rgba(#000, 0.2), 0 2px 2px 0 rgba(#000, 0.14), 0 1px 5px 0 rgba(#000, 0.12)
> header

View File

@ -122,6 +122,7 @@ export default Vue.extend({
}
},
mounted() {
this.$nextTick(() => {
if (this.$refs.prefix) {
this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px';
if (this.$refs.prefix.offsetWidth) {
@ -133,6 +134,7 @@ export default Vue.extend({
this.$refs.input.style.paddingRight = this.$refs.suffix.offsetWidth + 'px';
}
}
});
},
methods: {
focus() {

View File

@ -1,6 +1,6 @@
import * as getCaretCoordinates from 'textarea-caret';
import MkAutocomplete from '../components/autocomplete.vue';
import renderAcct from '../../../../../misc/acct/render';
import { toASCII } from 'punycode';
export default {
bind(el, binding, vn) {
@ -188,7 +188,7 @@ class Autocomplete {
const trimmedBefore = before.substring(0, before.lastIndexOf('@'));
const after = source.substr(caret);
const acct = renderAcct(value);
const acct = value.host === null ? value.username : `${value.username}@${toASCII(value.host)}`;
// 挿入
this.text = `${trimmedBefore}@${acct} ${after}`;

View File

@ -73,9 +73,6 @@ export default define({
border-radius 8px
.stream
display -webkit-flex
display -moz-flex
display -ms-flex
display flex
justify-content center
flex-wrap wrap

View File

@ -44,7 +44,6 @@ export default define({
},
fetch() {
fetch(`https://api.rss2json.com/v1/api.json?rss_url=${this.props.url}`, {
cache: 'no-cache'
}).then(res => {
res.json().then(feed => {
this.items = feed.items;

View File

@ -21,6 +21,7 @@ import updateAvatar from './api/update-avatar';
import updateBanner from './api/update-banner';
import MkIndex from './views/pages/index.vue';
import MkHome from './views/pages/home.vue';
import MkDeck from './views/pages/deck/deck.vue';
import MkAdmin from './views/pages/admin/admin.vue';
import MkStats from './views/pages/stats/stats.vue';
@ -54,6 +55,7 @@ init(async (launch) => {
mode: 'history',
routes: [
{ path: '/', name: 'index', component: MkIndex },
{ path: '/home', name: 'home', component: MkHome },
{ path: '/deck', name: 'deck', component: MkDeck },
{ path: '/admin', name: 'admin', component: MkAdmin },
{ path: '/stats', name: 'stats', component: MkStats },
@ -67,8 +69,8 @@ init(async (launch) => {
{ path: '/tags/:tag', component: MkTag },
{ path: '/share', component: MkShare },
{ path: '/reversi/:game?', component: MkReversi },
{ path: '/@:user', component: MkUser },
{ path: '/notes/:note', component: MkNote },
{ path: '/@:user', name: 'user', component: MkUser },
{ path: '/notes/:note', name: 'note', component: MkNote },
{ path: '/authorize-follow', component: MkFollow }
]
});

View File

@ -38,7 +38,7 @@
</div>
</div>
</div>
<div class="main">
<div class="main" :class="{ side: widgets.left.length == 0 || widgets.right.length == 0 }">
<template v-if="customize">
<x-draggable v-for="place in ['left', 'right']"
:list="widgets[place]"
@ -359,12 +359,10 @@ export default Vue.extend({
box-shadow var(--shadow)
border-radius var(--round)
@media (max-width 700px)
padding 0
> .tl
border none
border-radius 0
&.side
> .main
width calc(100% - 280px)
max-width 680px
> *:not(.main)
width 280px
@ -381,12 +379,22 @@ export default Vue.extend({
padding-right 16px
order 3
@media (max-width 1100px)
&.side
@media (max-width 1000px)
> *:not(.main)
display none
> .main
width 100%
max-width 700px
margin 0 auto
&:not(.side)
@media (max-width 1200px)
> *:not(.main)
display none
> .main
float none
width 100%
max-width 700px
margin 0 auto

View File

@ -91,7 +91,7 @@ import MkPostFormWindow from './post-form-window.vue';
import MkRenoteFormWindow from './renote-form-window.vue';
import MkNoteMenu from '../../../common/views/components/note-menu.vue';
import MkReactionPicker from '../../../common/views/components/reaction-picker.vue';
import XSub from './notes.note.sub.vue';
import XSub from './note.sub.vue';
import { sum } from '../../../../../prelude/array';
import noteSubscriber from '../../../common/scripts/note-subscriber';

View File

@ -1,5 +1,5 @@
<template>
<div class="tkfdzaxtkdeianobciwadajxzbddorql" :title="title">
<div class="tkfdzaxtkdeianobciwadajxzbddorql" :class="{ mini }" :title="title">
<mk-avatar class="avatar" :user="note.user"/>
<div class="main">
<mk-note-header class="header" :note="note"/>
@ -24,6 +24,11 @@ export default Vue.extend({
note: {
type: Object,
required: true
},
mini: {
type: Boolean,
required: false,
default: false
}
},
@ -44,11 +49,19 @@ export default Vue.extend({
<style lang="stylus" scoped>
.tkfdzaxtkdeianobciwadajxzbddorql
display flex
margin 0
padding 16px 32px
font-size 0.9em
background var(--subNoteBg)
&.mini
padding 16px
font-size 10px
> .avatar
margin 0 8px 0 0
width 38px
height 38px
> .avatar
flex-shrink 0
display block

View File

@ -1,7 +1,17 @@
<template>
<div class="note" v-show="appearNote.deletedAt == null" :tabindex="appearNote.deletedAt == null ? '-1' : null" v-hotkey="keymap" :title="title">
<div
class="note"
:class="{ mini }"
v-show="appearNote.deletedAt == null"
:tabindex="appearNote.deletedAt == null ? '-1' : null"
v-hotkey="keymap"
:title="title"
>
<div class="conversation" v-if="detail && conversation.length > 0">
<x-sub v-for="note in conversation" :key="note.id" :note="note" :mini="mini"/>
</div>
<div class="reply-to" v-if="appearNote.reply && (!$store.getters.isSignedIn || $store.state.settings.showReplyTarget)">
<x-sub :note="appearNote.reply"/>
<x-sub :note="appearNote.reply" :mini="mini"/>
</div>
<div class="renote" v-if="isRenote">
<mk-avatar class="avatar" :user="note.user"/>
@ -32,8 +42,8 @@
</div>
<mk-poll v-if="appearNote.poll" :note="appearNote" ref="pollViewer"/>
<a class="location" v-if="appearNote.geo" :href="`https://maps.google.com/maps?q=${appearNote.geo.coordinates[1]},${appearNote.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a>
<div class="renote" v-if="appearNote.renote"><mk-note-preview :note="appearNote.renote"/></div>
<mk-url-preview v-for="url in urls" :url="url" :key="url"/>
<div class="renote" v-if="appearNote.renote"><mk-note-preview :note="appearNote.renote" :mini="mini"/></div>
<mk-url-preview v-for="url in urls" :url="url" :key="url" :mini="mini"/>
</div>
</div>
<footer>
@ -55,15 +65,16 @@
</footer>
</div>
</article>
<div class="replies" v-if="detail && replies.length > 0">
<x-sub v-for="note in replies" :key="note.id" :note="note" :mini="mini"/>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import MkPostFormWindow from './post-form-window.vue';
import MkRenoteFormWindow from './renote-form-window.vue';
import XSub from './notes.note.sub.vue';
import XSub from './note.sub.vue';
import noteMixin from '../../../common/scripts/note-mixin';
import noteSubscriber from '../../../common/scripts/note-subscriber';
@ -81,6 +92,40 @@ export default Vue.extend({
note: {
type: Object,
required: true
},
detail: {
type: Boolean,
required: false,
default: false
},
mini: {
type: Boolean,
required: false,
default: false
}
},
data() {
return {
conversation: [],
replies: []
};
},
created() {
if (this.detail) {
(this as any).api('notes/replies', {
noteId: this.appearNote.id,
limit: 8
}).then(replies => {
this.replies = replies;
});
(this as any).api('notes/conversation', {
noteId: this.appearNote.replyId
}).then(conversation => {
this.conversation = conversation.reverse();
});
}
}
});
@ -93,14 +138,23 @@ export default Vue.extend({
background var(--face)
border-bottom solid 1px var(--faceDivider)
&[data-round]
&:first-child
border-top-left-radius 6px
border-top-right-radius 6px
&.mini
font-size 13px
> .renote
border-top-left-radius 6px
border-top-right-radius 6px
padding 8px 16px 0 16px
.avatar
width 20px
height 20px
> article
padding 16px 16px 4px
> .avatar
margin 0 10px 8px 0
width 42px
height 42px
&:last-of-type
border-bottom none
@ -129,6 +183,7 @@ export default Vue.extend({
background linear-gradient(to bottom, var(--renoteGradient) 0%, var(--face) 100%)
.avatar
flex-shrink 0
display inline-block
width 28px
height 28px
@ -273,6 +328,9 @@ export default Vue.extend({
border none
cursor pointer
&:last-child
margin-right 0
&:hover
color var(--noteActionsHover)

View File

@ -9,7 +9,7 @@
<button @click="resolveInitPromise">%i18n:@retry%</button>
</div>
<div class="skeleton" v-if="fetching">
<div class="placeholder" v-if="fetching">
<template v-for="i in 10">
<mk-note-skeleton :key="i"/>
</template>
@ -38,9 +38,8 @@
<script lang="ts">
import Vue from 'vue';
import * as config from '../../../config';
import getNoteSummary from '../../../../../misc/get-note-summary';
import XNote from './notes.note.vue';
import XNote from './note.vue';
const displayLimit = 30;
@ -61,7 +60,6 @@ export default Vue.extend({
requestInitPromise: null as () => Promise<any[]>,
notes: [],
queue: [],
unreadCount: 0,
fetching: true,
moreFetching: false
};
@ -80,12 +78,10 @@ export default Vue.extend({
},
mounted() {
document.addEventListener('visibilitychange', this.onVisibilitychange, false);
window.addEventListener('scroll', this.onScroll, { passive: true });
},
beforeDestroy() {
document.removeEventListener('visibilitychange', this.onVisibilitychange);
window.removeEventListener('scroll', this.onScroll);
},
@ -147,10 +143,9 @@ export default Vue.extend({
}
//#endregion
// 投稿が自分のものではないかつ、タブが非表示またはスクロール位置が最上部ではないならタイトルで通知
if ((document.hidden || !this.isScrollTop()) && note.userId !== this.$store.state.i.id) {
this.unreadCount++;
document.title = `(${this.unreadCount}) ${getNoteSummary(note)}`;
// タブが非表示またはスクロール位置が最上部ではないならタイトルで通知
if (document.hidden || !this.isScrollTop()) {
this.$store.commit('pushBehindNote', note);
}
if (this.isScrollTop()) {
@ -195,21 +190,9 @@ export default Vue.extend({
this.moreFetching = false;
},
clearNotification() {
this.unreadCount = 0;
document.title = (this as any).os.instanceName;
},
onVisibilitychange() {
if (!document.hidden) {
this.clearNotification();
}
},
onScroll() {
if (this.isScrollTop()) {
this.releaseQueue();
this.clearNotification();
}
if (this.$store.state.settings.fetchOnScroll !== false) {
@ -232,7 +215,7 @@ export default Vue.extend({
> *
transition transform .3s ease, opacity .3s ease
> .skeleton
> .placeholder
padding 32px
opacity 0.3

View File

@ -1,6 +1,6 @@
<template>
<div class="mk-notifications">
<div class="skeleton" v-if="fetching">
<div class="placeholder" v-if="fetching">
<template v-for="i in 10">
<mk-note-skeleton :key="i"/>
</template>
@ -207,7 +207,7 @@ export default Vue.extend({
> *
transition transform .3s ease, opacity .3s ease
> .skeleton
> .placeholder
padding 16px
opacity 0.3
@ -307,7 +307,7 @@ export default Vue.extend({
display block
width 100%
padding 16px
color #555
color var(--text)
border-top solid 1px rgba(#000, 0.05)
&:hover
@ -326,6 +326,6 @@ export default Vue.extend({
margin 0
padding 16px
text-align center
color #aaa
color var(--text)
</style>

View File

@ -65,6 +65,7 @@ import { host } from '../../../config';
import { erase, unique } from '../../../../../prelude/array';
import { length } from 'stringz';
import parseAcct from '../../../../../misc/acct/parse';
import { toASCII } from 'punycode';
export default Vue.extend({
components: {
@ -158,14 +159,14 @@ export default Vue.extend({
}
if (this.reply && this.reply.user.host != null) {
this.text = `@${this.reply.user.username}@${this.reply.user.host} `;
this.text = `@${this.reply.user.username}@${toASCII(this.reply.user.host)} `;
}
if (this.reply && this.reply.text != null) {
const ast = parse(this.reply.text);
ast.filter(t => t.type == 'mention').forEach(x => {
const mention = x.host ? `@${x.username}@${x.host}` : `@${x.username}`;
const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`;
// 自分は除外
if (this.$store.state.i.username == x.username && x.host == null) return;

View File

@ -2,10 +2,10 @@
<div class="2fa">
<p>%i18n:@intro%<a href="%i18n:@url%" target="_blank">%i18n:@detail%</a></p>
<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:@caution%</p></div>
<p v-if="!data && !$store.state.i.twoFactorEnabled"><button @click="register" class="ui primary">%i18n:@register%</button></p>
<p v-if="!data && !$store.state.i.twoFactorEnabled"><ui-button @click="register">%i18n:@register%</ui-button></p>
<template v-if="$store.state.i.twoFactorEnabled">
<p>%i18n:@already-registered%</p>
<button @click="unregister" class="ui">%i18n:@unregister%</button>
<ui-button @click="unregister">%i18n:@unregister%</ui-button>
</template>
<div v-if="data">
<ol>
@ -13,7 +13,7 @@
<li>%i18n:@scan%<br><img :src="data.qr"></li>
<li>%i18n:@done%<br>
<input type="number" v-model="token" class="ui">
<button @click="submit" class="ui primary">%i18n:@submit%</button>
<ui-button primary @click="submit">%i18n:@submit%</ui-button>
</li>
</ol>
<div class="ui info"><p>%fa:info-circle%%i18n:@info%</p></div>

View File

@ -1,10 +1,12 @@
<template>
<div class="root api">
<p>%i18n:@token% <code>{{ $store.state.i.token }}</code></p>
<ui-input :value="$store.state.i.token" readonly>
<span>%i18n:@token%</span>
</ui-input>
<p>%i18n:@intro%</p>
<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:@caution%</p></div>
<p>%i18n:@regeneration-of-token%</p>
<button class="ui" @click="regenerateToken">%i18n:@regenerate-token%</button>
<ui-button @click="regenerateToken">%i18n:@regenerate-token%</ui-button>
</div>
</template>

View File

@ -1,6 +1,6 @@
<template>
<div>
<button @click="reset" class="ui primary">%i18n:@reset%</button>
<ui-button @click="reset">%i18n:@reset%</ui-button>
</div>
</template>

View File

@ -1,106 +0,0 @@
<template>
<div class="profile">
<label class="avatar ui from group">
<p>%i18n:@avatar%</p>
<img class="avatar" :src="$store.state.i.avatarUrl" alt="avatar"/>
<button class="ui" @click="updateAvatar">%i18n:@choice-avatar%</button>
</label>
<label class="ui from group">
<ui-input v-model="name" type="text">%i18n:@name%</ui-input>
</label>
<label class="ui from group">
<ui-input v-model="location" type="text">%i18n:@location%</ui-input>
</label>
<label class="ui from group">
<ui-textarea v-model="description">%i18n:@description%</ui-textarea>
</label>
<label class="ui from group">
<p>%i18n:@birthday%</p>
<input type="date" v-model="birthday"/>
</label>
<ui-button primary @click="save">%i18n:@save%</ui-button>
<section>
<h2>%i18n:@locked-account%</h2>
<ui-switch v-model="isLocked" @change="save(false)">%i18n:@is-locked%</ui-switch>
<ui-switch v-model="carefulBot" @change="save(false)">%i18n:@careful-bot%</ui-switch>
</section>
<section>
<h2>%i18n:@other%</h2>
<ui-switch v-model="isBot" @change="save(false)">%i18n:@is-bot%</ui-switch>
<ui-switch v-model="isCat" @change="save(false)">%i18n:@is-cat%</ui-switch>
<ui-switch v-model="alwaysMarkNsfw">%i18n:common.always-mark-nsfw%</ui-switch>
</section>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
data() {
return {
name: null,
location: null,
description: null,
birthday: null,
isBot: false,
isCat: false,
isLocked: false,
carefulBot: false,
};
},
computed: {
alwaysMarkNsfw: {
get() { return this.$store.state.i.settings.alwaysMarkNsfw; },
set(value) { (this as any).api('i/update', { alwaysMarkNsfw: value }); }
},
},
created() {
this.name = this.$store.state.i.name || '';
this.location = this.$store.state.i.profile.location;
this.description = this.$store.state.i.description;
this.birthday = this.$store.state.i.profile.birthday;
this.isCat = this.$store.state.i.isCat;
this.isBot = this.$store.state.i.isBot;
this.isLocked = this.$store.state.i.isLocked;
this.carefulBot = this.$store.state.i.carefulBot;
},
methods: {
updateAvatar() {
(this as any).apis.updateAvatar();
},
save(notify) {
(this as any).api('i/update', {
name: this.name || null,
location: this.location || null,
description: this.description || null,
birthday: this.birthday || null,
isCat: this.isCat,
isBot: this.isBot,
isLocked: this.isLocked,
carefulBot: this.carefulBot
}).then(() => {
if (notify) {
(this as any).apis.notify('%i18n:@profile-updated%');
}
});
}
}
});
</script>
<style lang="stylus" scoped>
.profile
> .avatar
> img
display inline-block
vertical-align top
width 64px
height 64px
border-radius 4px
> button
margin-left 8px
</style>

View File

@ -2,30 +2,41 @@
<div class="mk-settings">
<div class="nav">
<p :class="{ active: page == 'profile' }" @mousedown="page = 'profile'">%fa:user .fw%%i18n:@profile%</p>
<p :class="{ active: page == 'theme' }" @mousedown="page = 'theme'">%fa:palette .fw%%i18n:@theme%</p>
<p :class="{ active: page == 'web' }" @mousedown="page = 'web'">%fa:desktop .fw%Web</p>
<p :class="{ active: page == 'notification' }" @mousedown="page = 'notification'">%fa:R bell .fw%%i18n:@notification%</p>
<p :class="{ active: page == 'drive' }" @mousedown="page = 'drive'">%fa:cloud .fw%%i18n:@drive%</p>
<p :class="{ active: page == 'hashtags' }" @mousedown="page = 'hashtags'">%fa:hashtag .fw%%i18n:@tags%</p>
<p :class="{ active: page == 'mute' }" @mousedown="page = 'mute'">%fa:ban .fw%%i18n:@mute%</p>
<p :class="{ active: page == 'apps' }" @mousedown="page = 'apps'">%fa:puzzle-piece .fw%%i18n:@apps%</p>
<p :class="{ active: page == 'twitter' }" @mousedown="page = 'twitter'">%fa:B twitter .fw%Twitter</p>
<p :class="{ active: page == 'security' }" @mousedown="page = 'security'">%fa:unlock-alt .fw%%i18n:@security%</p>
<p :class="{ active: page == 'api' }" @mousedown="page = 'api'">%fa:key .fw%API</p>
<p :class="{ active: page == 'other' }" @mousedown="page = 'other'">%fa:cogs .fw%%i18n:@other%</p>
</div>
<div class="pages">
<section class="profile" v-show="page == 'profile'">
<h1>%i18n:@profile%</h1>
<x-profile/>
</section>
<div class="profile" v-show="page == 'profile'">
<mk-profile-editor/>
<section class="web" v-show="page == 'web'">
<h1>%i18n:@theme%</h1>
<ui-card>
<div slot="title">%fa:B twitter% %i18n:@twitter%</div>
<section>
<mk-twitter-setting/>
</section>
</ui-card>
</div>
<ui-card class="theme" v-show="page == 'theme'">
<div slot="title">%fa:palette% %i18n:@theme%</div>
<section>
<mk-theme/>
</section>
</ui-card>
<section class="web" v-show="page == 'web'">
<h1>%i18n:@behaviour%</h1>
<ui-card class="web" v-show="page == 'web'">
<div slot="title">%fa:sliders-h% %i18n:@behaviour%</div>
<section>
<ui-switch v-model="fetchOnScroll">
%i18n:@fetch-on-scroll%
<span slot="desc">%i18n:@fetch-on-scroll-desc%</span>
@ -34,6 +45,23 @@
%i18n:@auto-popout%
<span slot="desc">%i18n:@auto-popout-desc%</span>
</ui-switch>
<ui-switch v-model="deckNav">%i18n:@deck-nav%<span slot="desc">%i18n:@deck-nav-desc%</span></ui-switch>
<details>
<summary>%i18n:@advanced%</summary>
<ui-switch v-model="apiViaStream">
%i18n:@api-via-stream%
<span slot="desc">%i18n:@api-via-stream-desc%</span>
</ui-switch>
</details>
</section>
<section>
<header>%i18n:@timeline%</header>
<ui-switch v-model="showMyRenotes">%i18n:@show-my-renotes%</ui-switch>
<ui-switch v-model="showRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch>
<ui-switch v-model="showLocalRenotes">%i18n:@show-local-renotes%</ui-switch>
</section>
<section>
<header>%i18n:@note-visibility%</header>
@ -49,24 +77,30 @@
</ui-select>
</section>
</section>
</ui-card>
<details>
<summary>%i18n:@advanced%</summary>
<ui-switch v-model="apiViaStream">
%i18n:@api-via-stream%
<span slot="desc">%i18n:@api-via-stream-desc%</span>
</ui-switch>
</details>
<ui-card class="web" v-show="page == 'web'">
<div slot="title">%fa:desktop% %i18n:@display%</div>
<section>
<ui-switch v-model="showPostFormOnTopOfTl">%i18n:@post-form-on-timeline%</ui-switch>
<ui-button @click="customizeHome">%i18n:@customize%</ui-button>
</section>
<section class="web" v-show="page == 'web'">
<h1>%i18n:@display%</h1>
<div class="div">
<button class="ui button" @click="customizeHome" style="margin-bottom: 16px">%i18n:@customize%</button>
</div>
<div class="div">
<button class="ui" @click="updateWallpaper">%i18n:@choose-wallpaper%</button>
<button class="ui" @click="deleteWallpaper">%i18n:@delete-wallpaper%</button>
<section>
<header>%i18n:@wallpaper%</header>
<ui-button @click="updateWallpaper">%i18n:@choose-wallpaper%</ui-button>
<ui-button @click="deleteWallpaper">%i18n:@delete-wallpaper%</ui-button>
</section>
<section>
<header>%i18n:@navbar-position%</header>
<ui-radio v-model="navbar" value="top">%i18n:@navbar-position-top%</ui-radio>
<ui-radio v-model="navbar" value="left">%i18n:@navbar-position-left%</ui-radio>
<ui-radio v-model="navbar" value="right">%i18n:@navbar-position-right%</ui-radio>
</section>
<section>
<ui-switch v-model="deckDefault">%i18n:@deck-default%</ui-switch>
</section>
<section>
<ui-switch v-model="darkmode">%i18n:@dark-mode%</ui-switch>
<ui-switch v-model="useShadow">%i18n:@use-shadow%</ui-switch>
<ui-switch v-model="roundedCorners">%i18n:@rounded-corners%</ui-switch>
@ -75,23 +109,30 @@
<ui-switch v-model="contrastedAcct">%i18n:@contrasted-acct%</ui-switch>
<ui-switch v-model="showFullAcct">%i18n:common.show-full-acct%</ui-switch>
<ui-switch v-model="iLikeSushi">%i18n:common.i-like-sushi%</ui-switch>
</div>
<ui-switch v-model="showPostFormOnTopOfTl">%i18n:@post-form-on-timeline%</ui-switch>
</section>
<section>
<ui-switch v-model="suggestRecentHashtags">%i18n:@suggest-recent-hashtags%</ui-switch>
<ui-switch v-model="showClockOnHeader">%i18n:@show-clock-on-header%</ui-switch>
<ui-switch v-model="alwaysShowNsfw">%i18n:common.always-show-nsfw%</ui-switch>
<ui-switch v-model="showReplyTarget">%i18n:@show-reply-target%</ui-switch>
<ui-switch v-model="showMyRenotes">%i18n:@show-my-renotes%</ui-switch>
<ui-switch v-model="showRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch>
<ui-switch v-model="showLocalRenotes">%i18n:@show-local-renotes%</ui-switch>
<ui-switch v-model="showMaps">%i18n:@show-maps%</ui-switch>
<ui-switch v-model="disableAnimatedMfm">%i18n:common.disable-animated-mfm%</ui-switch>
</section>
<section>
<header>%i18n:@deck-column-align%</header>
<ui-radio v-model="deckColumnAlign" value="center">%i18n:@deck-column-align-center%</ui-radio>
<ui-radio v-model="deckColumnAlign" value="left">%i18n:@deck-column-align-left%</ui-radio>
</section>
<section>
<ui-switch v-model="games_reversi_showBoardLabels">%i18n:common.show-reversi-board-labels%</ui-switch>
<ui-switch v-model="games_reversi_useContrastStones">%i18n:common.use-contrast-reversi-stones%</ui-switch>
</section>
</ui-card>
<section class="web" v-show="page == 'web'">
<h1>%i18n:@sound%</h1>
<ui-card class="web" v-show="page == 'web'">
<div slot="title">%fa:volume-up% %i18n:@sound%</div>
<section>
<ui-switch v-model="enableSounds">
%i18n:@enable-sounds%
<span slot="desc">%i18n:@enable-sounds-desc%</span>
@ -103,17 +144,14 @@
max="1"
step="0.1"
/>
<button class="ui button" @click="soundTest">%fa:volume-up% %i18n:@test%</button>
<ui-button @click="soundTest">%fa:volume-up% %i18n:@test%</ui-button>
</section>
</ui-card>
<section class="web" v-show="page == 'web'">
<h1>%i18n:@mobile%</h1>
<ui-switch v-model="disableViaMobile">%i18n:@disable-via-mobile%</ui-switch>
</section>
<section class="web" v-show="page == 'web'">
<h1>%i18n:@language%</h1>
<select v-model="lang" placeholder="%i18n:@pick-language%">
<ui-card class="web" v-show="page == 'web'">
<div slot="title">%fa:language% %i18n:@language%</div>
<section class="fit-top">
<ui-select v-model="lang" placeholder="%i18n:@pick-language%">
<optgroup label="%i18n:@recommended%">
<option value="">%i18n:@auto%</option>
</optgroup>
@ -121,80 +159,102 @@
<optgroup label="%i18n:@specify-language%">
<option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</option>
</optgroup>
</select>
</ui-select>
<div class="none ui info">
<p>%fa:info-circle%%i18n:@language-desc%</p>
</div>
</section>
</ui-card>
<section class="web" v-show="page == 'web'">
<h1>%i18n:@cache%</h1>
<button class="ui button" @click="clean">%i18n:@clean-cache%</button>
<ui-card class="web" v-show="page == 'web'">
<div slot="title">%fa:trash-alt R% %i18n:@cache%</div>
<section>
<ui-button @click="clean">%i18n:@clean-cache%</ui-button>
<div class="none ui info warn">
<p>%fa:exclamation-triangle%%i18n:@cache-warn%</p>
</div>
</section>
</ui-card>
<section class="notification" v-show="page == 'notification'">
<h1>%i18n:@notification%</h1>
<ui-card class="notification" v-show="page == 'notification'">
<div slot="title">%fa:bell R% %i18n:@notification%</div>
<section>
<ui-switch v-model="$store.state.i.settings.autoWatch" @change="onChangeAutoWatch">
%i18n:@auto-watch%
<span slot="desc">%i18n:@auto-watch-desc%</span>
</ui-switch>
<section>
<ui-button @click="readAllUnreadNotes">%i18n:@mark-as-read-all-unread-notes%</ui-button>
</section>
</section>
</ui-card>
<section class="drive" v-show="page == 'drive'">
<h1>%i18n:@drive%</h1>
<ui-card class="drive" v-show="page == 'drive'">
<div slot="title">%fa:cloud% %i18n:@drive%</div>
<section>
<x-drive/>
</section>
</ui-card>
<section class="hashtags" v-show="page == 'hashtags'">
<h1>%i18n:@tags%</h1>
<ui-card class="hashtags" v-show="page == 'hashtags'">
<div slot="title">%fa:hashtag% %i18n:@tags%</div>
<section>
<x-tags/>
</section>
</ui-card>
<section class="mute" v-show="page == 'mute'">
<h1>%i18n:@mute%</h1>
<ui-card class="mute" v-show="page == 'mute'">
<div slot="title">%fa:ban% %i18n:@mute%</div>
<section>
<x-mute/>
</section>
</ui-card>
<section class="apps" v-show="page == 'apps'">
<h1>%i18n:@apps%</h1>
<ui-card class="apps" v-show="page == 'apps'">
<div slot="title">%fa:puzzle-piece% %i18n:@apps%</div>
<section>
<x-apps/>
</section>
</ui-card>
<section class="twitter" v-show="page == 'twitter'">
<h1>Twitter</h1>
<mk-twitter-setting/>
</section>
<section class="password" v-show="page == 'security'">
<h1>%i18n:@password%</h1>
<ui-card class="password" v-show="page == 'security'">
<div slot="title">%fa:unlock-alt% %i18n:@password%</div>
<section>
<x-password/>
</section>
</ui-card>
<section class="2fa" v-show="page == 'security'">
<h1>%i18n:@2fa%</h1>
<ui-card class="2fa" v-show="page == 'security'">
<div slot="title">%fa:mobile-alt% %i18n:@2fa%</div>
<section>
<x-2fa/>
</section>
</ui-card>
<section class="signin" v-show="page == 'security'">
<h1>%i18n:@signin%</h1>
<ui-card class="signin" v-show="page == 'security'">
<div slot="title">%fa:sign-in-alt% %i18n:@signin%</div>
<section>
<x-signins/>
</section>
</ui-card>
<section class="api" v-show="page == 'api'">
<h1>API</h1>
<ui-card class="api" v-show="page == 'api'">
<div slot="title">%fa:key% API</div>
<section class="fit-top">
<x-api/>
</section>
</ui-card>
<section class="other" v-show="page == 'other'">
<h1>%i18n:@about%</h1>
<ui-card class="other" v-show="page == 'other'">
<div slot="title">%fa:info-circle% %i18n:@about%</div>
<section>
<p v-if="meta">%i18n:@operator%: <i><a :href="meta.maintainer.url" target="_blank">{{ meta.maintainer.name }}</a></i></p>
</section>
</ui-card>
<section class="other" v-show="page == 'other'">
<h1>%i18n:@update%</h1>
<ui-card class="other" v-show="page == 'other'">
<div slot="title">%fa:sync-alt% %i18n:@update%</div>
<section>
<p>
<span>%i18n:@version% <i>{{ version }}</i></span>
<template v-if="latestVersion !== undefined">
@ -214,9 +274,11 @@
</ui-switch>
</details>
</section>
</ui-card>
<section class="other" v-show="page == 'other'">
<h1>%i18n:@advanced-settings%</h1>
<ui-card class="other" v-show="page == 'other'">
<div slot="title">%fa:cogs% %i18n:@advanced-settings%</div>
<section>
<ui-switch v-model="debug">
%i18n:@debug-mode%
<span slot="desc">%i18n:@debug-mode-desc%</span>
@ -226,13 +288,13 @@
<span slot="desc">%i18n:@experimental-desc%</span>
</ui-switch>
</section>
</ui-card>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import XProfile from './settings.profile.vue';
import XMute from './settings.mute.vue';
import XPassword from './settings.password.vue';
import X2fa from './settings.2fa.vue';
@ -246,7 +308,6 @@ import checkForUpdate from '../../../common/scripts/check-for-update';
export default Vue.extend({
components: {
XProfile,
XMute,
XPassword,
X2fa,
@ -288,11 +349,31 @@ export default Vue.extend({
set(value) { this.$store.commit('device/set', { key: 'autoPopout', value }); }
},
deckNav: {
get() { return this.$store.state.settings.deckNav; },
set(value) { this.$store.commit('settings/set', { key: 'deckNav', value }); }
},
darkmode: {
get() { return this.$store.state.device.darkmode; },
set(value) { this.$store.commit('device/set', { key: 'darkmode', value }); }
},
navbar: {
get() { return this.$store.state.device.navbar; },
set(value) { this.$store.commit('device/set', { key: 'navbar', value }); }
},
deckColumnAlign: {
get() { return this.$store.state.device.deckColumnAlign; },
set(value) { this.$store.commit('device/set', { key: 'deckColumnAlign', value }); }
},
deckDefault: {
get() { return this.$store.state.device.deckDefault; },
set(value) { this.$store.commit('device/set', { key: 'deckDefault', value }); }
},
enableSounds: {
get() { return this.$store.state.device.enableSounds; },
set(value) { this.$store.commit('device/set', { key: 'enableSounds', value }); }
@ -426,11 +507,6 @@ export default Vue.extend({
disableAnimatedMfm: {
get() { return this.$store.state.settings.disableAnimatedMfm; },
set(value) { this.$store.dispatch('settings/set', { key: 'disableAnimatedMfm', value }); }
},
disableViaMobile: {
get() { return this.$store.state.settings.disableViaMobile; },
set(value) { this.$store.dispatch('settings/set', { key: 'disableViaMobile', value }); }
}
},
created() {
@ -439,6 +515,9 @@ export default Vue.extend({
});
},
methods: {
readAllUnreadNotes() {
(this as any).api('i/read_all_unread_notes');
},
customizeHome() {
this.$router.push('/i/customize-home');
this.$emit('done');
@ -508,7 +587,8 @@ export default Vue.extend({
height 100%
padding 16px 0 0 0
overflow auto
border-right solid 1px var(--faceDivider)
box-shadow var(--shadowRight)
z-index 1
> p
display block
@ -534,34 +614,10 @@ export default Vue.extend({
height 100%
flex auto
overflow auto
background var(--bg)
> section
margin 32px
color var(--text)
> h1
margin 0 0 1em 0
padding 0 0 8px 0
font-size 1em
border-bottom solid 1px var(--faceDivider)
&, >>> *
.ui.button.block
margin 16px 0
> section
margin 32px 0
> h2
margin 0 0 1em 0
padding 0 0 8px 0
font-size 1em
color var(--text)
border-bottom solid 1px var(--faceDivider)
> .web
> .div
border-bottom solid 1px var(--faceDivider)
margin 16px 0
</style>

View File

@ -157,6 +157,9 @@ export default Vue.extend({
font-family Meiryo, sans-serif
text-decoration none
@media (max-width 1100px)
display none
[data-fa]
margin-left 8px
@ -171,6 +174,9 @@ export default Vue.extend({
border-radius 4px
transition filter 100ms ease
@media (max-width 1100px)
margin-left 8px
> .menu
$bgcolor = var(--face)
display block

View File

@ -2,18 +2,22 @@
<div class="nav">
<ul>
<template v-if="$store.getters.isSignedIn">
<li class="home" :class="{ active: $route.name == 'index' }" @click="goToTop">
<router-link to="/">
%fa:home%
<p>%i18n:@home%</p>
</router-link>
<template v-if="$store.state.device.deckDefault">
<li class="deck" :class="{ active: $route.name == 'deck' || $route.name == 'index' }" @click="goToTop">
<router-link to="/">%fa:columns%<p>%i18n:@deck%</p></router-link>
</li>
<li class="home" :class="{ active: $route.name == 'home' }" @click="goToTop">
<router-link to="/home">%fa:home%<p>%i18n:@home%</p></router-link>
</li>
</template>
<template v-else>
<li class="home" :class="{ active: $route.name == 'home' || $route.name == 'index' }" @click="goToTop">
<router-link to="/">%fa:home%<p>%i18n:@home%</p></router-link>
</li>
<li class="deck" :class="{ active: $route.name == 'deck' }" @click="goToTop">
<router-link to="/deck">
%fa:columns%
<p>%i18n:@deck%</p>
</router-link>
<router-link to="/deck">%fa:columns%<p>%i18n:@deck%</p></router-link>
</li>
</template>
<li class="messaging">
<a @click="messaging">
%fa:comments%

View File

@ -29,6 +29,9 @@ export default Vue.extend({
<style lang="stylus" scoped>
.search
@media (max-width 800px)
display none !important
> [data-fa]
display block
position absolute
@ -58,6 +61,9 @@ export default Vue.extend({
transition color 0.5s ease, border 0.5s ease
color var(--desktopHeaderSearchFg)
@media (max-width 1000px)
width 10em
&::placeholder
color var(--desktopHeaderFg)

View File

@ -0,0 +1,378 @@
<template>
<div class="header" :class="navbar">
<div class="body">
<div class="post">
<button @click="post" title="%i18n:@post%">%fa:pencil-alt%</button>
</div>
<div class="nav" v-if="$store.getters.isSignedIn">
<template v-if="$store.state.device.deckDefault">
<div class="deck" :class="{ active: $route.name == 'deck' || $route.name == 'index' }" @click="goToTop">
<router-link to="/">%fa:columns%</router-link>
</div>
<div class="home" :class="{ active: $route.name == 'home' }" @click="goToTop">
<router-link to="/home">%fa:home%</router-link>
</div>
</template>
<template v-else>
<div class="home" :class="{ active: $route.name == 'home' || $route.name == 'index' }" @click="goToTop">
<router-link to="/">%fa:home%</router-link>
</div>
<div class="deck" :class="{ active: $route.name == 'deck' }" @click="goToTop">
<router-link to="/deck">%fa:columns%</router-link>
</div>
</template>
<div class="messaging">
<a @click="messaging">%fa:comments%<template v-if="hasUnreadMessagingMessage">%fa:circle%</template></a>
</div>
<div class="game">
<a @click="game">%fa:gamepad%<template v-if="hasGameInvitations">%fa:circle%</template></a>
</div>
</div>
<div class="nav bottom" v-if="$store.getters.isSignedIn">
<div>
<a @click="drive">%fa:cloud%</a>
</div>
<div ref="notificationsButton" :class="{ active: showNotifications }">
<a @click="notifications">%fa:R bell%</a>
</div>
<div>
<a @click="settings">%fa:cog%</a>
</div>
</div>
<div class="account">
<router-link :to="`/@${ $store.state.i.username }`">
<mk-avatar class="avatar" :user="$store.state.i"/>
</router-link>
<div class="nav menu">
<div class="signout">
<a @click="signout">%fa:power-off%</a>
</div>
<div>
<router-link to="/i/favorites">%fa:star%</router-link>
</div>
<div v-if="($store.state.i.isLocked || $store.state.i.carefulBot)">
<a @click="followRequests">%fa:envelope R%<i v-if="$store.state.i.pendingReceivedFollowRequestsCount">{{ $store.state.i.pendingReceivedFollowRequestsCount }}</i></a>
</div>
</div>
</div>
<div class="nav dark">
<div>
<a @click="dark"><template v-if="$store.state.device.darkmode">%fa:moon%</template><template v-else>%fa:R moon%</template></a>
</div>
</div>
</div>
<transition :name="`slide-${navbar}`">
<div class="notifications" v-if="showNotifications" ref="notifications" :class="navbar">
<mk-notifications/>
</div>
</transition>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import MkUserListsWindow from './user-lists-window.vue';
import MkFollowRequestsWindow from './received-follow-requests-window.vue';
import MkSettingsWindow from './settings-window.vue';
import MkDriveWindow from './drive-window.vue';
import MkMessagingWindow from './messaging-window.vue';
import MkGameWindow from './game-window.vue';
import contains from '../../../common/scripts/contains';
export default Vue.extend({
data() {
return {
hasGameInvitations: false,
connection: null,
showNotifications: false
};
},
computed: {
hasUnreadMessagingMessage(): boolean {
return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadMessagingMessage;
},
navbar(): string {
return this.$store.state.device.navbar;
},
},
mounted() {
if (this.$store.getters.isSignedIn) {
this.connection = (this as any).os.stream.useSharedConnection('main');
this.connection.on('reversiInvited', this.onReversiInvited);
this.connection.on('reversi_no_invites', this.onReversiNoInvites);
}
},
beforeDestroy() {
if (this.$store.getters.isSignedIn) {
this.connection.dispose();
}
},
methods: {
onReversiInvited() {
this.hasGameInvitations = true;
},
onReversiNoInvites() {
this.hasGameInvitations = false;
},
messaging() {
(this as any).os.new(MkMessagingWindow);
},
game() {
(this as any).os.new(MkGameWindow);
},
post() {
(this as any).apis.post();
},
drive() {
(this as any).os.new(MkDriveWindow);
},
list() {
const w = (this as any).os.new(MkUserListsWindow);
w.$once('choosen', list => {
this.$router.push(`i/lists/${ list.id }`);
});
},
followRequests() {
(this as any).os.new(MkFollowRequestsWindow);
},
settings() {
(this as any).os.new(MkSettingsWindow);
},
signout() {
(this as any).os.signout();
},
notifications() {
this.showNotifications ? this.closeNotifications() : this.openNotifications();
},
openNotifications() {
this.showNotifications = true;
Array.from(document.querySelectorAll('body *')).forEach(el => {
el.addEventListener('mousedown', this.onMousedown);
});
},
closeNotifications() {
this.showNotifications = false;
Array.from(document.querySelectorAll('body *')).forEach(el => {
el.removeEventListener('mousedown', this.onMousedown);
});
},
onMousedown(e) {
e.preventDefault();
if (
!contains(this.$refs.notifications, e.target) &&
this.$refs.notifications != e.target &&
!contains(this.$refs.notificationsButton, e.target) &&
this.$refs.notificationsButton != e.target
) {
this.closeNotifications();
}
return false;
},
dark() {
this.$store.commit('device/set', {
key: 'darkmode',
value: !this.$store.state.device.darkmode
});
},
goToTop() {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}
}
});
</script>
<style lang="stylus" scoped>
.header
$width = 68px
position fixed
top 0
z-index 1000
width $width
height 100%
&.left
left 0
box-shadow var(--shadowRight)
&.right
right 0
box-shadow var(--shadowLeft)
> .body
position fixed
top 0
z-index 1
width $width
height 100%
background var(--desktopHeaderBg)
> .post
width $width
height $width
padding 12px
> button
display inline-block
margin 0
padding 0
height 100%
width 100%
font-size 1.2em
font-weight normal
text-decoration none
color var(--primaryForeground)
background var(--primary) !important
outline none
border none
border-radius 100%
transition background 0.1s ease
cursor pointer
*
pointer-events none
&:hover
background var(--primaryLighten10) !important
&:active
background var(--primaryDarken10) !important
transition background 0s ease
> .nav.bottom
position absolute
bottom 128px
left 0
> .account
position absolute
bottom 64px
left 0
width $width
height $width
padding 14px
> .menu
display none
position absolute
bottom 64px
left 0
background var(--desktopHeaderBg)
&:hover
> .menu
display block
> *:not(.menu)
display block
width 100%
height 100%
> .avatar
pointer-events none
width 100%
height 100%
> .dark
position absolute
bottom 0
left 0
width $width
height $width
> .notifications
position fixed
top 0
width 350px
height 100%
overflow auto
background var(--face)
&.left
left $width
box-shadow var(--shadowRight)
&.right
right $width
box-shadow var(--shadowLeft)
.nav
> *
> *
display block
width $width
line-height 52px
text-align center
font-size 18px
color var(--desktopHeaderFg)
&:hover
background rgba(0, 0, 0, 0.05)
color var(--desktopHeaderHoverFg)
text-decoration none
&:active
background rgba(0, 0, 0, 0.1)
&.left
.nav
> *
&.active
box-shadow -4px 0 var(--primary) inset
&.right
.nav
> *
&.active
box-shadow 4px 0 var(--primary) inset
.slide-left-enter-active,
.slide-left-leave-active {
transition: all 0.2s ease;
}
.slide-left-enter, .slide-left-leave-to {
transform: translateX(-16px);
opacity: 0;
}
.slide-right-enter-active,
.slide-right-leave-active {
transition: all 0.2s ease;
}
.slide-right-enter, .slide-right-leave-to {
transform: translateX(16px);
opacity: 0;
}
</style>

View File

@ -1,8 +1,9 @@
<template>
<div class="mk-ui" v-hotkey.global="keymap">
<div class="bg" v-if="$store.getters.isSignedIn && $store.state.i.wallpaperUrl" :style="style"></div>
<x-header class="header" v-show="!zenMode" ref="header"/>
<div class="content">
<x-header class="header" v-if="navbar == 'top'" v-show="!zenMode" ref="header"/>
<x-sidebar class="sidebar" v-if="navbar != 'top'" v-show="!zenMode" ref="sidebar"/>
<div class="content" :class="[{ sidebar: navbar != 'top', zen: zenMode }, navbar]">
<slot></slot>
</div>
<mk-stream-indicator v-if="$store.getters.isSignedIn"/>
@ -12,10 +13,12 @@
<script lang="ts">
import Vue from 'vue';
import XHeader from './ui.header.vue';
import XSidebar from './ui.sidebar.vue';
export default Vue.extend({
components: {
XHeader
XHeader,
XSidebar
},
data() {
@ -25,6 +28,10 @@ export default Vue.extend({
},
computed: {
navbar(): string {
return this.$store.state.device.navbar;
},
style(): any {
if (!this.$store.getters.isSignedIn || this.$store.state.i.wallpaperUrl == null) return {};
return {
@ -45,6 +52,12 @@ export default Vue.extend({
watch: {
'$store.state.uiHeaderHeight'() {
this.$el.style.paddingTop = this.$store.state.uiHeaderHeight + 'px';
},
navbar() {
if (this.navbar != 'top') {
this.$store.commit('setUiHeaderHeight', 0);
}
}
},
@ -60,7 +73,9 @@ export default Vue.extend({
toggleZenMode() {
this.zenMode = !this.zenMode;
this.$nextTick(() => {
if (this.$refs.header) {
this.$store.commit('setUiHeaderHeight', this.$refs.header.$el.offsetHeight);
}
});
}
}
@ -83,8 +98,13 @@ export default Vue.extend({
background-attachment fixed
opacity 0.3
> .header
@media (max-width 1000px)
display none
> .content.sidebar.left
padding-left 68px
> .content.sidebar.right
padding-right 68px
> .content.zen
padding 0 !important
</style>

View File

@ -1,14 +1,14 @@
<template>
<x-widgets-column v-if="column.type == 'widgets'" :column="column" :is-stacked="isStacked"/>
<x-notifications-column v-else-if="column.type == 'notifications'" :column="column" :is-stacked="isStacked"/>
<x-tl-column v-else-if="column.type == 'home'" :column="column" :is-stacked="isStacked"/>
<x-tl-column v-else-if="column.type == 'local'" :column="column" :is-stacked="isStacked"/>
<x-tl-column v-else-if="column.type == 'hybrid'" :column="column" :is-stacked="isStacked"/>
<x-tl-column v-else-if="column.type == 'global'" :column="column" :is-stacked="isStacked"/>
<x-tl-column v-else-if="column.type == 'list'" :column="column" :is-stacked="isStacked"/>
<x-tl-column v-else-if="column.type == 'hashtag'" :column="column" :is-stacked="isStacked"/>
<x-mentions-column v-else-if="column.type == 'mentions'" :column="column" :is-stacked="isStacked"/>
<x-direct-column v-else-if="column.type == 'direct'" :column="column" :is-stacked="isStacked"/>
<x-tl-column v-else-if="column.type == 'home'" :column="column" :is-stacked="isStacked" @parentFocus="parentFocus"/>
<x-tl-column v-else-if="column.type == 'local'" :column="column" :is-stacked="isStacked" @parentFocus="parentFocus"/>
<x-tl-column v-else-if="column.type == 'hybrid'" :column="column" :is-stacked="isStacked" @parentFocus="parentFocus"/>
<x-tl-column v-else-if="column.type == 'global'" :column="column" :is-stacked="isStacked" @parentFocus="parentFocus"/>
<x-tl-column v-else-if="column.type == 'list'" :column="column" :is-stacked="isStacked" @parentFocus="parentFocus"/>
<x-tl-column v-else-if="column.type == 'hashtag'" :column="column" :is-stacked="isStacked" @parentFocus="parentFocus"/>
<x-mentions-column v-else-if="column.type == 'mentions'" :column="column" :is-stacked="isStacked" @parentFocus="parentFocus"/>
<x-direct-column v-else-if="column.type == 'direct'" :column="column" :is-stacked="isStacked" @parentFocus="parentFocus"/>
</template>
<script lang="ts">
@ -38,6 +38,16 @@ export default Vue.extend({
required: false,
default: false
}
},
methods: {
focus() {
this.$children[0].focus();
},
parentFocus(direction) {
this.$emit('parentFocus', direction);
},
}
});
</script>

View File

@ -1,7 +1,6 @@
<template>
<div class="dnpfarvgbnfmyzbdquhhzyxcmstpdqzs" :class="{ naked, narrow, active, isStacked, draghover, dragging, dropready }"
@dragover.prevent.stop="onDragover"
@dragenter.prevent="onDragenter"
@dragleave="onDragleave"
@drop.prevent.stop="onDrop">
<header :class="{ indicate: count > 0 }"
@ -16,7 +15,8 @@
</button>
<slot name="header"></slot>
<span class="count" v-if="count > 0">({{ count }})</span>
<button class="menu" ref="menu" @click.stop="showMenu">%fa:caret-down%</button>
<button v-if="!isTemporaryColumn" class="menu" ref="menu" @click.stop="showMenu">%fa:caret-down%</button>
<button v-else class="close" @click.stop="close">%fa:times%</button>
</header>
<div ref="body" v-show="active">
<slot></slot>
@ -34,11 +34,13 @@ export default Vue.extend({
props: {
column: {
type: Object,
required: true
required: false,
default: null
},
isStacked: {
type: Boolean,
required: true
required: false,
default: false
},
name: {
type: String,
@ -61,6 +63,12 @@ export default Vue.extend({
}
},
computed: {
isTemporaryColumn(): boolean {
return this.column == null;
}
},
inject: {
getColumnVm: { from: 'getColumnVm' }
},
@ -96,14 +104,20 @@ export default Vue.extend({
mounted() {
this.$refs.body.addEventListener('scroll', this.onScroll, { passive: true });
if (!this.isTemporaryColumn) {
this.$root.$on('deck.column.dragStart', this.onOtherDragStart);
this.$root.$on('deck.column.dragEnd', this.onOtherDragEnd);
}
},
beforeDestroy() {
this.$refs.body.removeEventListener('scroll', this.onScroll);
if (!this.isTemporaryColumn) {
this.$root.$off('deck.column.dragStart', this.onOtherDragStart);
this.$root.$off('deck.column.dragEnd', this.onOtherDragEnd);
}
},
methods: {
@ -203,6 +217,7 @@ export default Vue.extend({
},
onContextmenu(e) {
if (this.isTemporaryColumn) return;
contextmenu((this as any).os)(e, this.getMenu());
},
@ -214,6 +229,13 @@ export default Vue.extend({
});
},
close() {
this.$store.commit('device/set', {
key: 'deckTemporaryColumn',
value: null
});
},
goTop() {
this.$refs.body.scrollTo({
top: 0,
@ -222,6 +244,12 @@ export default Vue.extend({
},
onDragstart(e) {
// テンポラリカラムはドラッグさせない
if (this.isTemporaryColumn) {
e.preventDefault();
return;
}
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('mk-deck-column', this.column.id);
this.dragging = true;
@ -232,6 +260,12 @@ export default Vue.extend({
},
onDragover(e) {
// テンポラリカラムにはドロップさせない
if (this.isTemporaryColumn) {
e.dataTransfer.dropEffect = 'none';
return;
}
// 自分自身がドラッグされている場合
if (this.dragging) {
// 自分自身にはドロップさせない
@ -242,9 +276,7 @@ export default Vue.extend({
const isDeckColumn = e.dataTransfer.types[0] == 'mk-deck-column';
e.dataTransfer.dropEffect = isDeckColumn ? 'move' : 'none';
},
onDragenter() {
if (!this.dragging) this.draghover = true;
},
@ -276,13 +308,24 @@ export default Vue.extend({
min-width 330px
height 100%
background var(--face)
border-radius 6px
//box-shadow 0 2px 16px rgba(#000, 0.1)
border-radius var(--round)
box-shadow var(--shadow)
overflow hidden
&.draghover
box-shadow 0 0 0 2px var(--primaryAlpha08)
&:after
content ""
display block
position absolute
z-index 1000
top 0
left 0
width 100%
height 100%
background var(--primaryAlpha02)
&.dragging
box-shadow 0 0 0 2px var(--primaryAlpha04)
@ -338,6 +381,8 @@ export default Vue.extend({
> .toggleActive
> .menu
> .close
padding 0
width $header-height
line-height $header-height
font-size 16px
@ -353,6 +398,7 @@ export default Vue.extend({
margin-left -16px
> .menu
> .close
margin-left auto
margin-right -16px

View File

@ -2,7 +2,7 @@
<x-column :name="name" :column="column" :is-stacked="isStacked">
<span slot="header">%fa:envelope R%{{ name }}</span>
<x-direct/>
<x-direct @parentFocus="parentFocus"/>
</x-column>
</template>
@ -34,5 +34,15 @@ export default Vue.extend({
return '%i18n:common.deck.direct%';
}
},
methods: {
focus() {
this.$refs.tl.focus();
},
parentFocus(direction) {
this.$emit('parentFocus', direction);
},
}
});
</script>

View File

@ -1,5 +1,5 @@
<template>
<x-notes ref="timeline" :more="existMore ? more : null"/>
<x-notes ref="timeline" :more="existMore ? more : null" @parentFocus="parentFocus"/>
</template>
<script lang="ts">
@ -58,6 +58,7 @@ export default Vue.extend({
}, rej);
}));
},
more() {
this.moreFetching = true;
@ -82,12 +83,21 @@ export default Vue.extend({
return promise;
},
onNote(note) {
// Prepend a note
if (note.visibility == 'specified') {
(this.$refs.timeline as any).prepend(note);
}
}
},
focus() {
this.$refs.timeline.focus();
},
parentFocus(direction) {
this.$emit('parentFocus', direction);
},
}
});
</script>

View File

@ -1,5 +1,5 @@
<template>
<x-notes ref="timeline" :more="existMore ? more : null" :media-view="mediaView"/>
<x-notes ref="timeline" :more="existMore ? more : null" :media-view="mediaView" @parentFocus="parentFocus"/>
</template>
<script lang="ts">
@ -80,6 +80,7 @@ export default Vue.extend({
}, rej);
}));
},
more() {
this.moreFetching = true;
@ -105,12 +106,21 @@ export default Vue.extend({
return promise;
},
onNote(note) {
if (this.mediaOnly && note.files.length == 0) return;
// Prepend a note
(this.$refs.timeline as any).prepend(note);
}
},
focus() {
this.$refs.timeline.focus();
},
parentFocus(direction) {
this.$emit('parentFocus', direction);
},
}
});
</script>

View File

@ -1,5 +1,5 @@
<template>
<x-notes ref="timeline" :more="existMore ? more : null" :media-view="mediaView"/>
<x-notes ref="timeline" :more="existMore ? more : null" :media-view="mediaView" @parentFocus="parentFocus"/>
</template>
<script lang="ts">
@ -84,6 +84,7 @@ export default Vue.extend({
}, rej);
}));
},
more() {
this.moreFetching = true;
@ -109,18 +110,29 @@ export default Vue.extend({
return promise;
},
onNote(note) {
if (this.mediaOnly && note.files.length == 0) return;
// Prepend a note
(this.$refs.timeline as any).prepend(note);
},
onUserAdded() {
this.fetch();
},
onUserRemoved() {
this.fetch();
}
},
focus() {
this.$refs.timeline.focus();
},
parentFocus(direction) {
this.$emit('parentFocus', direction);
},
}
});
</script>

View File

@ -2,7 +2,7 @@
<x-column :name="name" :column="column" :is-stacked="isStacked">
<span slot="header">%fa:at%{{ name }}</span>
<x-mentions/>
<x-mentions ref="tl" @parentFocus="parentFocus"/>
</x-column>
</template>
@ -34,5 +34,15 @@ export default Vue.extend({
return '%i18n:common.deck.mentions%';
}
},
methods: {
focus() {
this.$refs.tl.focus();
},
parentFocus(direction) {
this.$emit('parentFocus', direction);
},
}
});
</script>

View File

@ -1,5 +1,5 @@
<template>
<x-notes ref="timeline" :more="existMore ? more : null"/>
<x-notes ref="timeline" :more="existMore ? more : null" @parentFocus="parentFocus"/>
</template>
<script lang="ts">
@ -57,6 +57,7 @@ export default Vue.extend({
}, rej);
}));
},
more() {
this.moreFetching = true;
@ -80,10 +81,19 @@ export default Vue.extend({
return promise;
},
onNote(note) {
// Prepend a note
(this.$refs.timeline as any).prepend(note);
}
},
focus() {
this.$refs.timeline.focus();
},
parentFocus(direction) {
this.$emit('parentFocus', direction);
},
}
});
</script>

View File

@ -0,0 +1,69 @@
<template>
<x-column>
<span slot="header">
%fa:comment-alt R%<span>{{ title }}</span>
</span>
<div class="rvtscbadixhhbsczoorqoaygovdeecsx" v-if="note">
<div class="is-remote" v-if="note.user.host != null">%fa:exclamation-triangle% %i18n:@is-remote%<a :href="note.url || note.uri" target="_blank">%i18n:@view-remote%</a></div>
<x-note :note="note" :detail="true" :mini="true"/>
</div>
</x-column>
</template>
<script lang="ts">
import Vue from 'vue';
import XColumn from './deck.column.vue';
import XNotes from './deck.notes.vue';
import XNote from '../../components/note.vue';
export default Vue.extend({
components: {
XColumn,
XNotes,
XNote
},
props: {
noteId: {
type: String,
required: true
}
},
data() {
return {
note: null,
fetching: true
};
},
computed: {
title(): string {
return this.note ? Vue.filter('userName')(this.note.user) : '';
}
},
created() {
(this as any).api('notes/show', { noteId: this.noteId }).then(note => {
this.note = note;
this.fetching = false;
});
}
});
</script>
<style lang="stylus" scoped>
.rvtscbadixhhbsczoorqoaygovdeecsx
> .is-remote
padding 8px 16px
font-size 12px
&.is-remote
color var(--remoteInfoFg)
background var(--remoteInfoBg)
> a
font-weight bold
</style>

View File

@ -1,71 +0,0 @@
<template>
<div class="fnlfosztlhtptnongximhlbykxblytcq">
<mk-avatar class="avatar" :user="note.user"/>
<div class="main">
<mk-note-header class="header" :note="note" :mini="true"/>
<div class="body">
<mk-sub-note-content class="text" :note="note"/>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
props: {
note: {
type: Object,
required: true
},
// TODO
truncate: {
type: Boolean,
default: true
}
}
});
</script>
<style lang="stylus" scoped>
.fnlfosztlhtptnongximhlbykxblytcq
display flex
padding 16px
font-size 10px
background var(--subNoteBg)
&.smart
> .main
width 100%
> header
align-items center
> .avatar
flex-shrink 0
display block
margin 0 8px 0 0
width 38px
height 38px
border-radius 8px
> .main
flex 1
min-width 0
> .header
margin-bottom 2px
> .body
> .text
margin 0
padding 0
color var(--subNoteText)
pre
max-height 120px
font-size 80%
</style>

View File

@ -1,323 +0,0 @@
<template>
<div
v-if="!mediaView"
v-show="appearNote.deletedAt == null"
:tabindex="appearNote.deletedAt == null ? '-1' : null"
class="zyjjkidcqjnlegkqebitfviomuqmseqk"
:class="{ renote: isRenote }"
v-hotkey="keymap"
:title="title"
>
<div class="reply-to" v-if="appearNote.reply && (!$store.getters.isSignedIn || $store.state.settings.showReplyTarget)">
<x-sub :note="appearNote.reply"/>
</div>
<div class="renote" v-if="isRenote">
<mk-avatar class="avatar" :user="note.user"/>
%fa:retweet%
<span>{{ '%i18n:@reposted-by%'.substr(0, '%i18n:@reposted-by%'.indexOf('{')) }}</span>
<router-link class="name" :to="note.user | userPage">{{ note.user | userName }}</router-link>
<span>{{ '%i18n:@reposted-by%'.substr('%i18n:@reposted-by%'.indexOf('}') + 1) }}</span>
<mk-time :time="note.createdAt"/>
</div>
<article>
<mk-avatar class="avatar" :user="appearNote.user"/>
<div class="main">
<mk-note-header class="header" :note="appearNote" :mini="true"/>
<div class="body">
<p v-if="appearNote.cw != null" class="cw">
<span class="text" v-if="appearNote.cw != ''">{{ appearNote.cw }}</span>
<mk-cw-button v-model="showContent"/>
</p>
<div class="content" v-show="appearNote.cw == null || showContent">
<div class="text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">(%i18n:@private%)</span>
<a class="reply" v-if="appearNote.reply">%fa:reply%</a>
<misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i"/>
<a class="rp" v-if="appearNote.renote != null">RP:</a>
</div>
<div class="files" v-if="appearNote.files.length > 0">
<mk-media-list :media-list="appearNote.files"/>
</div>
<mk-poll v-if="appearNote.poll" :note="appearNote" ref="pollViewer"/>
<a class="location" v-if="appearNote.geo" :href="`https://maps.google.com/maps?q=${appearNote.geo.coordinates[1]},${appearNote.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a>
<div class="renote" v-if="appearNote.renote">
<mk-note-preview :note="appearNote.renote" :mini="true"/>
</div>
<mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="false" :mini="true"/>
</div>
<span class="app" v-if="appearNote.app">via <b>{{ appearNote.app.name }}</b></span>
</div>
<footer>
<mk-reactions-viewer :note="appearNote" ref="reactionsViewer"/>
<button @click="reply()">
<template v-if="appearNote.reply">%fa:reply-all%</template>
<template v-else>%fa:reply%</template>
</button>
<button @click="renote()" title="Renote">%fa:retweet%</button>
<button :class="{ reacted: appearNote.myReaction != null }" @click="react()" ref="reactButton">%fa:plus%</button>
<button class="menu" @click="menu()" ref="menuButton">%fa:ellipsis-h%</button>
</footer>
</div>
</article>
</div>
<div v-else class="srwrkujossgfuhrbnvqkybtzxpblgchi">
<div v-if="note.files.length > 0">
<mk-media-list :media-list="note.files"/>
</div>
<div v-if="note.renote && note.renote.files.length > 0">
<mk-media-list :media-list="note.renote.files"/>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import MkPostFormWindow from '../../components/post-form-window.vue';
import MkRenoteFormWindow from '../../components/renote-form-window.vue';
import XSub from './deck.note.sub.vue';
import noteMixin from '../../../../common/scripts/note-mixin';
import noteSubscriber from '../../../../common/scripts/note-subscriber';
export default Vue.extend({
components: {
XSub
},
mixins: [
noteMixin(),
noteSubscriber('note')
],
props: {
note: {
type: Object,
required: true
},
mediaView: {
type: Boolean,
required: false,
default: false
}
}
});
</script>
<style lang="stylus" scoped>
.srwrkujossgfuhrbnvqkybtzxpblgchi
font-size 13px
margin 4px 12px
&:first-child
margin-top 12px
&:last-child
margin-bottom 12px
.zyjjkidcqjnlegkqebitfviomuqmseqk
font-size 13px
border-bottom solid 1px var(--faceDivider)
&:focus
z-index 1
&:after
content ""
pointer-events none
position absolute
top 2px
right 2px
bottom 2px
left 2px
border 2px solid var(--primaryAlpha03)
border-radius 4px
&:last-of-type
border-bottom none
&.smart
> article
> .main
> header
align-items center
margin-bottom 4px
> .renote
display flex
align-items center
padding 8px 16px 0 16px
line-height 28px
white-space pre
color var(--renoteText)
background linear-gradient(to bottom, var(--renoteGradient) 0%, var(--face) 100%)
.avatar
flex-shrink 0
display inline-block
width 20px
height 20px
margin 0 8px 0 0
border-radius 6px
[data-fa]
margin-right 4px
> span
flex-shrink 0
&:last-of-type
margin-right 8px
.name
overflow hidden
flex-shrink 1
text-overflow ellipsis
white-space nowrap
font-weight bold
> .mk-time
display block
margin-left auto
flex-shrink 0
font-size 0.9em
& + article
padding-top 8px
> article
display flex
padding 16px 16px 4px
> .avatar
flex-shrink 0
display block
margin 0 10px 8px 0
width 42px
height 42px
border-radius 6px
//position -webkit-sticky
//position sticky
//top 62px
> .main
flex 1
min-width 0
> .body
> .cw
cursor default
display block
margin 0
padding 0
overflow-wrap break-word
color var(--noteText)
> .text
margin-right 8px
> .content
> .text
display block
margin 0
padding 0
overflow-wrap break-word
color var(--noteText)
>>> .title
display block
margin-bottom 4px
padding 4px
font-size 90%
text-align center
background var(--mfmTitleBg)
border-radius 4px
>>> .code
margin 8px 0
>>> .quote
margin 8px
padding 6px 12px
color var(--mfmQuote)
border-left solid 3px var(--mfmQuoteLine)
> .reply
margin-right 8px
color var(--noteText)
> .rp
margin-left 4px
font-style oblique
color var(--renoteText)
[data-is-me]:after
content "you"
padding 0 4px
margin-left 4px
font-size 80%
color var(--primaryForeground)
background var(--primary)
border-radius 4px
.mk-url-preview
margin-top 8px
> .files
> img
display block
max-width 100%
> .location
margin 4px 0
font-size 12px
color #ccc
> .map
width 100%
height 200px
&:empty
display none
> .mk-poll
font-size 80%
> .renote
margin 8px 0
> *
padding 16px
border dashed 1px var(--quoteBorder)
border-radius 8px
> .app
font-size 12px
color #ccc
> footer
> button
margin 0
padding 4px 8px 8px 8px
background transparent
border none
box-shadow none
font-size 1em
color var(--noteActions)
cursor pointer
&:not(:last-child)
margin-right 28px
&:hover
color var(--noteActionsHover)
> .count
display inline
margin 0 0 0 8px
color #999
&.reacted
color var(--primary)
</style>

View File

@ -2,16 +2,28 @@
<div class="eamppglmnmimdhrlzhplwpvyeaqmmhxu">
<slot name="empty" v-if="notes.length == 0 && !fetching && requestInitPromise == null"></slot>
<div class="placeholder" v-if="fetching">
<template v-for="i in 10">
<mk-note-skeleton :key="i"/>
</template>
</div>
<div v-if="!fetching && requestInitPromise != null">
<p>%i18n:@error%</p>
<button @click="resolveInitPromise">%i18n:@retry%</button>
</div>
<!-- トランジションを有効にするとなぜかメモリリークする -->
<!--<transition-group name="mk-notes" class="transition">-->
<div class="notes">
<!--<transition-group name="mk-notes" class="transition" ref="notes">-->
<div class="notes" ref="notes">
<template v-for="(note, i) in _notes">
<x-note :note="note" :key="note.id" @update:note="onNoteUpdated(i, $event)" :media-view="mediaView"/>
<x-note
:note="note"
:key="note.id"
@update:note="onNoteUpdated(i, $event)"
:media-view="mediaView"
:mini="true"
@parentFocus="parentFocus"/>
<p class="date" :key="note.id + '_date'" v-if="i != notes.length - 1 && note._date != _notes[i + 1]._date">
<span>%fa:angle-up%{{ note._datetext }}</span>
<span>%fa:angle-down%{{ _notes[i + 1]._datetext }}</span>
@ -32,7 +44,7 @@
<script lang="ts">
import Vue from 'vue';
import XNote from './deck.note.vue';
import XNote from '../../components/note.vue';
const displayLimit = 20;
@ -96,7 +108,11 @@ export default Vue.extend({
methods: {
focus() {
(this.$el as any).children[0].focus();
(this.$refs.notes as any).children[0].focus ? (this.$refs.notes as any).children[0].focus() : (this.$refs.notes as any).$el.children[0].focus();
},
parentFocus(direction) {
this.$emit('parentFocus', direction);
},
onNoteUpdated(i, note) {
@ -148,6 +164,11 @@ export default Vue.extend({
}
//#endregion
// タブが非表示またはスクロール位置が最上部ではないならタイトルで通知
if (document.hidden || !this.isScrollTop()) {
this.$store.commit('pushBehindNote', note);
}
if (this.isScrollTop()) {
// Prepend the note
this.notes.unshift(note);
@ -205,12 +226,16 @@ export default Vue.extend({
> *
transition transform .3s ease, opacity .3s ease
> .placeholder
padding 16px
opacity 0.3
> .notes
> .date
display block
margin 0
line-height 32px
font-size 14px
font-size 12px
text-align center
color var(--dateDividerFg)
background var(--dateDividerBg)

View File

@ -66,15 +66,15 @@
</div>
<template v-if="notification.type == 'quote'">
<x-note :note="notification.note" @update:note="onNoteUpdated"/>
<x-note :note="notification.note" @update:note="onNoteUpdated" :mini="true"/>
</template>
<template v-if="notification.type == 'reply'">
<x-note :note="notification.note" @update:note="onNoteUpdated"/>
<x-note :note="notification.note" @update:note="onNoteUpdated" :mini="true"/>
</template>
<template v-if="notification.type == 'mention'">
<x-note :note="notification.note" @update:note="onNoteUpdated"/>
<x-note :note="notification.note" @update:note="onNoteUpdated" :mini="true"/>
</template>
</div>
</template>
@ -82,7 +82,7 @@
<script lang="ts">
import Vue from 'vue';
import getNoteSummary from '../../../../../../misc/get-note-summary';
import XNote from './deck.note.vue';
import XNote from '../../components/note.vue';
export default Vue.extend({
components: {

View File

@ -1,5 +1,11 @@
<template>
<div class="oxynyeqmfvracxnglgulyqfgqxnxmehl">
<div class="placeholder" v-if="fetching">
<template v-for="i in 10">
<mk-note-skeleton :key="i"/>
</template>
</div>
<!-- トランジションを有効にするとなぜかメモリリークする -->
<component :is="!$store.state.device.reduceMotion ? 'transition-group' : 'div'" name="mk-notifications" class="transition notifications">
<template v-for="(notification, i) in _notifications">
@ -14,7 +20,6 @@
<template v-if="fetchingMoreNotifications">%fa:spinner .pulse .fw%</template>{{ fetchingMoreNotifications ? '%i18n:common.loading%' : '%i18n:@more%' }}
</button>
<p class="empty" v-if="notifications.length == 0 && !fetching">%i18n:@empty%</p>
<p class="loading" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
</div>
</template>
@ -161,6 +166,10 @@ export default Vue.extend({
> *
transition transform .3s ease, opacity .3s ease
> .placeholder
padding 16px
opacity 0.3
> .notifications
> .notification:not(:last-child)
@ -207,13 +216,4 @@ export default Vue.extend({
text-align center
color #aaa
> .loading
margin 0
padding 16px
text-align center
color #aaa
> [data-fa]
margin-right 4px
</style>

View File

@ -14,9 +14,28 @@
<ui-switch v-model="column.isMediaOnly" @change="onChangeSettings">%i18n:@is-media-only%</ui-switch>
<ui-switch v-model="column.isMediaView" @change="onChangeSettings">%i18n:@is-media-view%</ui-switch>
</div>
<x-list-tl v-if="column.type == 'list'" :list="column.list" :media-only="column.isMediaOnly" :media-view="column.isMediaView"/>
<x-hashtag-tl v-if="column.type == 'hashtag'" :tag-tl="$store.state.settings.tagTimelines.find(x => x.id == column.tagTlId)" :media-only="column.isMediaOnly" :media-view="column.isMediaView"/>
<x-tl v-else :src="column.type" :media-only="column.isMediaOnly" :media-view="column.isMediaView"/>
<x-list-tl v-if="column.type == 'list'"
:list="column.list"
:media-only="column.isMediaOnly"
:media-view="column.isMediaView"
ref="tl"
@parentFocus="parentFocus"
/>
<x-hashtag-tl v-else-if="column.type == 'hashtag'"
:tag-tl="$store.state.settings.tagTimelines.find(x => x.id == column.tagTlId)"
:media-only="column.isMediaOnly"
:media-view="column.isMediaView"
ref="tl"
@parentFocus="parentFocus"
/>
<x-tl v-else
:src="column.type"
:media-only="column.isMediaOnly"
:media-view="column.isMediaView"
ref="tl"
@parentFocus="parentFocus"
/>
</x-column>
</template>
@ -77,7 +96,15 @@ export default Vue.extend({
methods: {
onChangeSettings(v) {
this.$store.dispatch('settings/saveDeck');
}
},
focus() {
this.$refs.tl.focus();
},
parentFocus(direction) {
this.$emit('parentFocus', direction);
},
}
});
</script>

View File

@ -1,5 +1,5 @@
<template>
<x-notes ref="timeline" :more="existMore ? more : null" :media-view="mediaView"/>
<x-notes ref="timeline" :more="existMore ? more : null" :media-view="mediaView" @parentFocus="parentFocus"/>
</template>
<script lang="ts">
@ -143,7 +143,11 @@ export default Vue.extend({
focus() {
(this.$refs.timeline as any).focus();
}
},
parentFocus(direction) {
this.$emit('parentFocus', direction);
},
}
});
</script>

View File

@ -0,0 +1,269 @@
<template>
<x-column>
<span slot="header">
%fa:user%<span>{{ title }}</span>
</span>
<div class="zubukjlciycdsyynicqrnlsmdwmymzqu" v-if="user">
<div class="is-remote" v-if="user.host != null">%fa:exclamation-triangle% %i18n:@is-remote%<a :href="user.url || user.uri" target="_blank">%i18n:@view-remote%</a></div>
<header :style="bannerStyle">
<div>
<mk-follow-button v-if="$store.getters.isSignedIn && user.id != $store.state.i.id" :user="user" class="follow"/>
<mk-avatar class="avatar" :user="user" :disable-preview="true"/>
<span class="name">{{ user | userName }}</span>
<span class="acct">@{{ user | acct }}</span>
</div>
</header>
<div class="info">
<div class="description">
<misskey-flavored-markdown v-if="user.description" :text="user.description" :i="$store.state.i"/>
</div>
</div>
<div class="pinned" v-if="user.pinnedNotes && user.pinnedNotes.length > 0">
<p>%fa:thumbtack% %i18n:@pinned-notes%</p>
<div class="notes">
<x-note v-for="n in user.pinnedNotes" :key="n.id" :note="n" :mini="true"/>
</div>
</div>
<div class="images" v-if="images.length > 0">
<router-link v-for="image in images" :style="`background-image: url(${image.thumbnailUrl})`" :key="`${image.id}:${image._note.id}`" :to="image._note | notePage"></router-link>
</div>
<div class="tl">
<x-notes ref="timeline" :more="existMore ? fetchMoreNotes : null"/>
</div>
</div>
</x-column>
</template>
<script lang="ts">
import Vue from 'vue';
import parseAcct from '../../../../../../misc/acct/parse';
import XColumn from './deck.column.vue';
import XNotes from './deck.notes.vue';
import XNote from '../../components/note.vue';
import { concat } from '../../../../../../prelude/array';
const fetchLimit = 10;
export default Vue.extend({
components: {
XColumn,
XNotes,
XNote
},
props: {
acct: {
type: String,
required: true
}
},
data() {
return {
user: null,
fetching: true,
existMore: false,
moreFetching: false,
withFiles: false,
images: []
};
},
computed: {
title(): string {
return this.user ? Vue.filter('userName')(this.user) : '';
},
bannerStyle(): any {
if (this.user == null) return {};
if (this.user.bannerUrl == null) return {};
return {
backgroundColor: this.user.bannerColor && this.user.bannerColor.length == 3 ? `rgb(${ this.user.bannerColor.join(',') })` : null,
backgroundImage: `url(${ this.user.bannerUrl })`
};
},
},
created() {
(this as any).api('users/show', parseAcct(this.acct)).then(user => {
this.user = user;
this.fetching = false;
this.$nextTick(() => {
(this.$refs.timeline as any).init(() => this.initTl());
});
const image = [
'image/jpeg',
'image/png',
'image/gif'
];
(this as any).api('users/notes', {
userId: this.user.id,
fileType: image,
limit: 9
}).then(notes => {
notes.forEach(note => {
note.files.forEach(file => {
file._note = note;
});
});
const files = concat(notes.map((n: any): any[] => n.files));
this.images = files.filter(f => image.includes(f.type)).slice(0, 6);
});
});
},
methods: {
initTl() {
return new Promise((res, rej) => {
(this as any).api('users/notes', {
userId: this.user.id,
limit: fetchLimit + 1,
withFiles: this.withFiles,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
this.existMore = true;
}
res(notes);
}, rej);
});
},
fetchMoreNotes() {
this.moreFetching = true;
const promise = (this as any).api('users/notes', {
userId: this.user.id,
limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id,
withFiles: this.withFiles,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
});
promise.then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
} else {
this.existMore = false;
}
notes.forEach(n => (this.$refs.timeline as any).append(n));
this.moreFetching = false;
});
return promise;
},
}
});
</script>
<style lang="stylus" scoped>
.zubukjlciycdsyynicqrnlsmdwmymzqu
background var(--deckUserColumnBg)
> .is-remote
padding 8px 16px
font-size 12px
&.is-remote
color var(--remoteInfoFg)
background var(--remoteInfoBg)
> a
font-weight bold
> header
overflow hidden
background-size cover
background-position center
> div
padding 32px
background rgba(#000, 0.5)
color #fff
text-align center
> .follow
position absolute
top 16px
right 16px
> .avatar
display block
width 64px
height 64px
margin 0 auto
> .name
display block
margin-top 8px
font-weight bold
text-shadow 0 0 8px #000
> .acct
font-size 14px
opacity 0.7
text-shadow 0 0 8px #000
> .info
padding 16px
font-size 14px
color var(--text)
text-align center
background var(--face)
border-bottom solid 1px var(--faceDivider)
&:before
content ""
display blcok
position absolute
top -32px
left 0
right 0
width 0px
margin 0 auto
border-top solid 16px transparent
border-left solid 16px transparent
border-right solid 16px transparent
border-bottom solid 16px var(--face)
> .pinned
padding-bottom 16px
background var(--deckUserColumnBg)
> p
margin 0
padding 8px 16px
font-size 12px
color var(--text)
> .notes
background var(--face)
> .images
display grid
grid-template-rows 1fr 1fr 1fr
grid-template-columns 1fr 1fr 1fr
gap 4px
height 250px
padding 16px
margin-bottom 16px
background var(--face)
> *
background-position center center
background-size cover
background-clip content-box
> .tl
background var(--face)
</style>

View File

@ -1,13 +1,17 @@
<template>
<mk-ui :class="$style.root">
<div class="qlvquzbjribqcaozciifydkngcwtyzje" :style="style">
<div class="qlvquzbjribqcaozciifydkngcwtyzje" :style="style" :class="{ center: $store.state.device.deckColumnAlign == 'center' }" v-hotkey.global="keymap">
<template v-for="ids in layout">
<div v-if="ids.length > 1" class="folder">
<template v-for="id, i in ids">
<x-column-core :ref="id" :key="id" :column="columns.find(c => c.id == id)" :is-stacked="true"/>
<x-column-core :ref="id" :key="id" :column="columns.find(c => c.id == id)" :is-stacked="true" @parentFocus="moveFocus(id, $event)"/>
</template>
</div>
<x-column-core v-else :ref="ids[0]" :key="ids[0]" :column="columns.find(c => c.id == ids[0])"/>
<x-column-core v-else :ref="ids[0]" :key="ids[0]" :column="columns.find(c => c.id == ids[0])" @parentFocus="moveFocus(ids[0], $event)"/>
</template>
<template v-if="temporaryColumn">
<x-user-column v-if="temporaryColumn.type == 'user'" :acct="temporaryColumn.acct" :key="temporaryColumn.acct"/>
<x-note-column v-else-if="temporaryColumn.type == 'note'" :note-id="temporaryColumn.noteId" :key="temporaryColumn.noteId"/>
</template>
<button ref="add" @click="add" title="%i18n:common.deck.add-column%">%fa:plus%</button>
</div>
@ -19,11 +23,16 @@ import Vue from 'vue';
import XColumnCore from './deck.column-core.vue';
import Menu from '../../../../common/views/components/menu.vue';
import MkUserListsWindow from '../../components/user-lists-window.vue';
import XUserColumn from './deck.user-column.vue';
import XNoteColumn from './deck.note-column.vue';
import * as uuid from 'uuid';
export default Vue.extend({
components: {
XColumnCore
XColumnCore,
XUserColumn,
XNoteColumn
},
computed: {
@ -31,15 +40,27 @@ export default Vue.extend({
if (this.$store.state.settings.deck == null) return [];
return this.$store.state.settings.deck.columns;
},
layout(): any[] {
if (this.$store.state.settings.deck == null) return [];
if (this.$store.state.settings.deck.layout == null) return this.$store.state.settings.deck.columns.map(c => [c.id]);
return this.$store.state.settings.deck.layout;
},
style(): any {
return {
height: `calc(100vh - ${this.$store.state.uiHeaderHeight}px)`
};
},
temporaryColumn(): any {
return this.$store.state.device.deckTemporaryColumn;
},
keymap(): any {
return {
't': this.focus
};
}
},
@ -50,6 +71,8 @@ export default Vue.extend({
},
created() {
this.$store.commit('navHook', this.onNav);
if (this.$store.state.settings.deck == null) {
const deck = {
columns: [/*{
@ -95,6 +118,8 @@ export default Vue.extend({
},
beforeDestroy() {
this.$store.commit('navHook', null);
document.documentElement.style.overflow = 'auto';
},
@ -103,6 +128,30 @@ export default Vue.extend({
return this.$refs[id][0];
},
onNav(to) {
if (!this.$store.state.settings.deckNav) return false;
if (to.name == 'user') {
this.$store.commit('device/set', {
key: 'deckTemporaryColumn',
value: {
type: 'user',
acct: to.params.user
}
});
return true;
} else if (to.name == 'note') {
this.$store.commit('device/set', {
key: 'deckTemporaryColumn',
value: {
type: 'note',
noteId: to.params.note
}
});
return true;
}
},
add() {
this.os.new(Menu, {
source: this.$refs.add,
@ -210,6 +259,71 @@ export default Vue.extend({
}
}]
});
},
focus() {
// Flatten array of arrays
const ids = [].concat.apply([], this.layout);
const firstTl = ids.find(id => this.isTlColumn(id));
if (firstTl) {
this.$refs[firstTl][0].focus();
}
},
moveFocus(id, direction) {
let targetColumn;
if (direction == 'right') {
const currentColumnIndex = this.layout.findIndex(ids => ids.includes(id));
this.layout.some((ids, i) => {
if (i <= currentColumnIndex) return false;
const tl = ids.find(id => this.isTlColumn(id));
if (tl) {
targetColumn = tl;
return true;
}
});
} else if (direction == 'left') {
const currentColumnIndex = [...this.layout].reverse().findIndex(ids => ids.includes(id));
[...this.layout].reverse().some((ids, i) => {
if (i <= currentColumnIndex) return false;
const tl = ids.find(id => this.isTlColumn(id));
if (tl) {
targetColumn = tl;
return true;
}
});
} else if (direction == 'down') {
const currentColumn = this.layout.find(ids => ids.includes(id));
const currentIndex = currentColumn.indexOf(id);
currentColumn.some((_id, i) => {
if (i <= currentIndex) return false;
if (this.isTlColumn(_id)) {
targetColumn = _id;
return true;
}
});
} else if (direction == 'up') {
const currentColumn = [...this.layout.find(ids => ids.includes(id))].reverse();
const currentIndex = currentColumn.indexOf(id);
currentColumn.some((_id, i) => {
if (i <= currentIndex) return false;
if (this.isTlColumn(_id)) {
targetColumn = _id;
return true;
}
});
}
if (targetColumn) {
this.$refs[targetColumn][0].focus();
}
},
isTlColumn(id) {
const column = this.columns.find(c => c.id === id);
return ['home', 'local', 'hybrid', 'global', 'list', 'hashtag', 'mentions', 'direct'].includes(column.type);
}
}
});
@ -240,6 +354,7 @@ export default Vue.extend({
> *:not(:last-child)
margin-bottom 8px
&.center
> *
&:first-child
margin-left auto

View File

@ -1,16 +1,25 @@
<template>
<component :is="$store.getters.isSignedIn ? 'home' : 'welcome'"></component>
<component :is="page"></component>
</template>
<script lang="ts">
import Vue from 'vue';
import Home from './home.vue';
import Welcome from './welcome.vue';
import Deck from './deck/deck.vue';
export default Vue.extend({
components: {
Home,
Deck,
Welcome
},
computed: {
page(): string {
if (!this.$store.getters.isSignedIn) return 'welcome';
return this.$store.state.device.deckDefault ? 'deck' : 'home';
}
}
});
</script>

View File

@ -60,9 +60,6 @@ export default Vue.extend({
margin-right 4px
> .stream
display -webkit-flex
display -moz-flex
display -ms-flex
display flex
justify-content center
flex-wrap wrap

View File

@ -124,11 +124,17 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API)
//#region shadow
const shadow = '0 3px 8px rgba(0, 0, 0, 0.2)';
const shadowRight = '4px 0 4px rgba(0, 0, 0, 0.1)';
const shadowLeft = '-4px 0 4px rgba(0, 0, 0, 0.1)';
if (os.store.state.settings.useShadow) document.documentElement.style.setProperty('--shadow', shadow);
if (os.store.state.settings.useShadow) document.documentElement.style.setProperty('--shadowRight', shadowRight);
if (os.store.state.settings.useShadow) document.documentElement.style.setProperty('--shadowLeft', shadowLeft);
os.store.watch(s => {
return s.settings.useShadow;
}, v => {
document.documentElement.style.setProperty('--shadow', v ? shadow : 'none');
document.documentElement.style.setProperty('--shadowRight', v ? shadowRight : 'none');
document.documentElement.style.setProperty('--shadowLeft', v ? shadowLeft : 'none');
});
//#endregion
@ -142,6 +148,25 @@ export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API)
});
//#endregion
// Navigation hook
router.beforeEach((to, from, next) => {
if (os.store.state.navHook) {
if (os.store.state.navHook(to)) {
next(false);
} else {
next();
}
} else {
next();
}
});
document.addEventListener('visibilitychange', () => {
if (!document.hidden) {
os.store.commit('clearBehindNotes');
}
}, false);
Vue.mixin({
data() {
return {

View File

@ -41,6 +41,8 @@
<ui-button link :href="`${file.url}?download`" :download="file.name">%fa:download% %i18n:@download%</ui-button>
<ui-button @click="rename">%fa:pencil-alt% %i18n:@rename%</ui-button>
<ui-button @click="move">%fa:R folder-open% %i18n:@move%</ui-button>
<ui-button @click="toggleSensitive" v-if="file.isSensitive">%fa:R eye% %i18n:@unmark-as-sensitive%</ui-button>
<ui-button @click="toggleSensitive" v-else>%fa:R eye-slash% %i18n:@mark-as-sensitive%</ui-button>
<ui-button @click="del">%fa:trash-alt R% %i18n:@delete%</ui-button>
</div>
</div>
@ -71,25 +73,30 @@ import { gcd } from '../../../../../prelude/math';
export default Vue.extend({
props: ['file'],
data() {
return {
gcd,
exif: null
};
},
computed: {
browser(): any {
return this.$parent;
},
kind(): string {
return this.file.type.split('/')[0];
},
style(): any {
return this.file.properties.avgColor && this.file.properties.avgColor.length == 3 ? {
'background-color': `rgb(${ this.file.properties.avgColor.join(',') })`
} : {};
}
},
methods: {
rename() {
const name = window.prompt('%i18n:@rename%', this.file.name);
@ -101,6 +108,7 @@ export default Vue.extend({
this.browser.cf(this.file, true);
});
},
move() {
(this as any).apis.chooseDriveFolder().then(folder => {
(this as any).api('drive/files/update', {
@ -111,6 +119,7 @@ export default Vue.extend({
});
});
},
del() {
(this as any).api('drive/files/delete', {
fileId: this.file.id
@ -118,9 +127,20 @@ export default Vue.extend({
this.browser.cd(this.file.folderId, true);
});
},
toggleSensitive() {
(this as any).api('drive/files/update', {
fileId: this.file.id,
isSensitive: !this.file.isSensitive
});
this.file.isSensitive = !this.file.isSensitive;
},
showCreatedAt() {
alert(new Date(this.file.createdAt).toLocaleString());
},
onImageLoaded() {
const self = this;
EXIF.getData(this.$refs.img, function(this: any) {

View File

@ -4,7 +4,7 @@
<slot name="empty" v-if="notes.length == 0 && !fetching && requestInitPromise == null"></slot>
<div class="skeleton" v-if="fetching">
<div class="placeholder" v-if="fetching">
<template v-for="i in 10">
<mk-note-skeleton :key="i"/>
</template>
@ -37,7 +37,6 @@
<script lang="ts">
import Vue from 'vue';
import getNoteSummary from '../../../../../misc/get-note-summary';
const displayLimit = 30;
@ -54,7 +53,6 @@ export default Vue.extend({
requestInitPromise: null as () => Promise<any[]>,
notes: [],
queue: [],
unreadCount: 0,
fetching: true,
moreFetching: false
};
@ -83,12 +81,10 @@ export default Vue.extend({
},
mounted() {
document.addEventListener('visibilitychange', this.onVisibilitychange, false);
window.addEventListener('scroll', this.onScroll, { passive: true });
},
beforeDestroy() {
document.removeEventListener('visibilitychange', this.onVisibilitychange);
window.removeEventListener('scroll', this.onScroll);
},
@ -146,10 +142,9 @@ export default Vue.extend({
}
//#endregion
// 投稿が自分のものではないかつ、タブが非表示またはスクロール位置が最上部ではないならタイトルで通知
if ((document.hidden || !this.isScrollTop()) && note.userId !== this.$store.state.i.id) {
this.unreadCount++;
document.title = `(${this.unreadCount}) ${getNoteSummary(note)}`;
// タブが非表示またはスクロール位置が最上部ではないならタイトルで通知
if (document.hidden || !this.isScrollTop()) {
this.$store.commit('pushBehindNote', note);
}
if (this.isScrollTop()) {
@ -187,21 +182,9 @@ export default Vue.extend({
this.moreFetching = false;
},
clearNotification() {
this.unreadCount = 0;
document.title = (this as any).os.instanceName;
},
onVisibilitychange() {
if (!document.hidden) {
this.clearNotification();
}
},
onScroll() {
if (this.isScrollTop()) {
this.releaseQueue();
this.clearNotification();
}
if (this.$store.state.settings.fetchOnScroll !== false) {
@ -253,7 +236,7 @@ export default Vue.extend({
[data-fa]
margin-right 8px
> .skeleton
> .placeholder
padding 16px
opacity 0.3

View File

@ -1,6 +1,6 @@
<template>
<div class="mk-notifications">
<div class="skeleton" v-if="fetching">
<div class="placeholder" v-if="fetching">
<template v-for="i in 10">
<mk-note-skeleton :key="i"/>
</template>
@ -184,7 +184,7 @@ export default Vue.extend({
text-align center
color #aaa
> .skeleton
> .placeholder
padding 16px
opacity 0.3

View File

@ -62,6 +62,7 @@ import { host } from '../../../config';
import { erase, unique } from '../../../../../prelude/array';
import { length } from 'stringz';
import parseAcct from '../../../../../misc/acct/parse';
import { toASCII } from 'punycode';
export default Vue.extend({
components: {
@ -153,14 +154,14 @@ export default Vue.extend({
}
if (this.reply && this.reply.user.host != null) {
this.text = `@${this.reply.user.username}@${this.reply.user.host} `;
this.text = `@${this.reply.user.username}@${toASCII(this.reply.user.host)} `;
}
if (this.reply && this.reply.text != null) {
const ast = parse(this.reply.text);
ast.filter(t => t.type == 'mention').forEach(x => {
const mention = x.host ? `@${x.username}@${x.host}` : `@${x.username}`;
const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`;
// 自分は除外
if (this.$store.state.i.username == x.username && x.host == null) return;

View File

@ -5,7 +5,7 @@
<div class="signin-as" v-html="'%i18n:@signed-in-as%'.replace('{}', `<b>${name}</b>`)"></div>
<div>
<x-profile/>
<mk-profile-editor/>
<ui-card>
<div slot="title">%fa:palette% %i18n:@theme%</div>
@ -148,13 +148,7 @@ import Vue from 'vue';
import { apiUrl, version, codename, langs } from '../../../config';
import checkForUpdate from '../../../common/scripts/check-for-update';
import XProfile from './settings/settings.profile.vue';
export default Vue.extend({
components: {
XProfile
},
data() {
return {
apiUrl,

View File

@ -5,11 +5,13 @@ import * as nestedProperty from 'nested-property';
import MiOS from './mios';
import { hostname } from './config';
import { erase } from '../../prelude/array';
import getNoteSummary from '../../misc/get-note-summary';
const defaultSettings = {
home: null,
mobileHome: [],
deck: null,
deckNav: true,
tagTimelines: [],
fetchOnScroll: true,
showMaps: true,
@ -56,7 +58,11 @@ const defaultDeviceSettings = {
loadRawImages: false,
alwaysShowNsfw: false,
postStyle: 'standard',
mobileNotificationPosition: 'bottom'
navbar: 'top',
deckColumnAlign: 'center',
mobileNotificationPosition: 'bottom',
deckTemporaryColumn: null,
deckDefault: false
};
export default (os: MiOS) => new Vuex.Store({
@ -67,7 +73,9 @@ export default (os: MiOS) => new Vuex.Store({
state: {
i: null,
indicate: false,
uiHeaderHeight: 0
uiHeaderHeight: 0,
navHook: null,
behindNotes: []
},
getters: {
@ -89,6 +97,22 @@ export default (os: MiOS) => new Vuex.Store({
setUiHeaderHeight(state, height) {
state.uiHeaderHeight = height;
},
navHook(state, callback) {
state.navHook = callback;
},
pushBehindNote(state, note) {
if (note.userId === state.i.id) return;
if (state.behindNotes.some(n => n.id === note.id)) return;
state.behindNotes.push(note);
document.title = `(${state.behindNotes.length}) ${getNoteSummary(note)}`;
},
clearBehindNotes(state) {
state.behindNotes = [];
document.title = os.instanceName;
}
},

View File

@ -174,6 +174,7 @@
desktopSettingsNavItemHover: ':lighten<10<$text',
deckAcrylicColumnBg: 'rgba(0, 0, 0, 0.25)',
deckUserColumnBg: ':darken<3<@face',
mobileHeaderBg: ':lighten<5<$secondary',
mobileHeaderFg: '$text',

View File

@ -174,6 +174,7 @@
desktopSettingsNavItemHover: ':darken<10<$text',
deckAcrylicColumnBg: 'rgba(0, 0, 0, 0.1)',
deckUserColumnBg: ':darken<4<@face',
mobileHeaderBg: ':lighten<5<$secondary',
mobileHeaderFg: '$text',

View File

@ -23,6 +23,7 @@ export type Source = {
url: string;
port: number;
https?: { [x: string]: string };
disableHsts?: boolean;
mongodb: {
host: string;
port: number;

View File

@ -25,9 +25,9 @@
<tbody>
<tr><td><kbd class="key"></kbd>, <kbd class="key">K</kbd>, <kbd class="group"><kbd class="key">Shift</kbd> + <kbd class="key">Tab</kbd></kbd></td><td>上の投稿にフォーカスを移動</td><td>-</td></tr>
<tr><td><kbd class="key"></kbd>, <kbd class="key">J</kbd>, <kbd class="key">Tab</kbd></td><td>下の投稿にフォーカスを移動</td><td>-</td></tr>
<tr><td><kbd class="key"></kbd>, <kbd class="key">R</kbd></td><td>返信フォームを開く</td><td><b>R</b>eply</td></tr>
<tr><td><kbd class="key"></kbd>, <kbd class="key">Q</kbd></td><td>Renoteフォームを開く</td><td><b>Q</b>uote</td></tr>
<tr><td><kbd class="group"><kbd class="key">Ctrl</kbd> + <kbd class="key"></kbd></kbd>, <kbd class="group"><kbd class="key">Ctrl</kbd> + <kbd class="key">Q</kbd></kbd></td><td>即刻Renoteする(フォームを開かずに)</td><td>-</td></tr>
<tr><td><kbd class="key">R</kbd></td><td>返信フォームを開く</td><td><b>R</b>eply</td></tr>
<tr><td><kbd class="key">Q</kbd></td><td>Renoteフォームを開く</td><td><b>Q</b>uote</td></tr>
<tr><td><kbd class="group"><kbd class="key">Ctrl</kbd> + <kbd class="key">Q</kbd></kbd></td><td>即刻Renoteする(フォームを開かずに)</td><td>-</td></tr>
<tr><td><kbd class="key">E</kbd>, <kbd class="key">A</kbd>, <kbd class="key">+</kbd></td><td>リアクションフォームを開く</td><td><b>E</b>mote, re<b>A</b>ction</td></tr>
<tr><td><kbd class="key">0</kbd>~<kbd class="key">9</kbd></td><td>数字に対応したリアクションをする(対応については後述)</td><td>-</td></tr>
<tr><td><kbd class="key">F</kbd>, <kbd class="key">B</kbd></td><td>お気に入りに登録</td><td><b>F</b>avorite, <b>B</b>ookmark</td></tr>
@ -86,6 +86,19 @@
</tbody>
</table>
## デッキ
<table>
<thead>
<tr><th>ショートカット</th><th>効果</th><th>由来</th></tr>
</thead>
<tbody>
<tr><td>投稿にフォーカスした状態で<kbd class="group"><kbd class="key">Shift</kbd> + <kbd class="key"></kbd></kbd></td><td>上のカラムにフォーカス</td><td>-</td></tr>
<tr><td>投稿にフォーカスした状態で<kbd class="group"><kbd class="key">Shift</kbd> + <kbd class="key"></kbd></kbd></td><td>下のカラムにフォーカス</td><td>-</td></tr>
<tr><td>投稿にフォーカスした状態で<kbd class="group"><kbd class="key">Shift</kbd> + <kbd class="key"></kbd></kbd></td><td>右のカラムにフォーカス</td><td>-</td></tr>
<tr><td>投稿にフォーカスした状態で<kbd class="group"><kbd class="key">Shift</kbd> + <kbd class="key"></kbd></kbd></td><td>左のカラムにフォーカス</td><td>-</td></tr>
</tbody>
</table>
# 例
<table>
<thead>

View File

@ -2,10 +2,12 @@
* Mention
*/
import parseAcct from '../../../misc/acct/parse';
import { toUnicode } from 'punycode';
export type TextElementMention = {
type: 'mention'
content: string
canonical: string
username: string
host: string
};
@ -15,9 +17,11 @@ export default function(text: string) {
if (!match) return null;
const mention = match[0];
const { username, host } = parseAcct(mention.substr(1));
const canonical = host != null ? `@${username}@${toUnicode(host)}` : mention;
return {
type: 'mention',
content: mention,
canonical,
username,
host
} as TextElementMention;

View File

@ -1,5 +1,6 @@
import * as mongo from 'mongodb';
import { Context } from 'cafy';
import isObjectId from './is-objectid';
export const isAnId = (x: any) => mongo.ObjectID.isValid(x);
export const isNotAnId = (x: any) => !isAnId(x);
@ -12,7 +13,7 @@ export default class ID extends Context<mongo.ObjectID> {
super();
this.transform = v => {
if (isAnId(v) && !mongo.ObjectID.prototype.isPrototypeOf(v)) {
if (isAnId(v) && !isObjectId(v)) {
return new mongo.ObjectID(v);
} else {
return v;
@ -20,7 +21,7 @@ export default class ID extends Context<mongo.ObjectID> {
};
this.push(v => {
if (!mongo.ObjectID.prototype.isPrototypeOf(v) && isNotAnId(v)) {
if (!isObjectId(v) && isNotAnId(v)) {
return new Error('must-be-an-id');
}
return true;

3
src/misc/is-objectid.ts Normal file
View File

@ -0,0 +1,3 @@
export default function(x: any): boolean {
return x.hasOwnProperty('toHexString') || x.hasOwnProperty('_bsontype');
}

View File

@ -1,7 +1,8 @@
import * as mongo from 'mongodb';
import isObjectId from './is-objectid';
function toString(id: any) {
return mongo.ObjectID.prototype.isPrototypeOf(id) ? (id as mongo.ObjectID).toHexString() : id;
return isObjectId(id) ? (id as mongo.ObjectID).toHexString() : id;
}
export default function(note: any, mutedUserIds: string[]): boolean {

View File

@ -1,5 +1,6 @@
import * as mongo from 'mongodb';
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
const AccessToken = db.get<IAccessToken>('accessTokens');
AccessToken.createIndex('token');
@ -22,7 +23,7 @@ export async function deleteAccessToken(accessToken: string | mongo.ObjectID | I
let a: IAccessToken;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(accessToken)) {
if (isObjectId(accessToken)) {
a = await AccessToken.findOne({
_id: accessToken
});

View File

@ -2,6 +2,7 @@ import * as mongo from 'mongodb';
const deepcopy = require('deepcopy');
import AccessToken from './access-token';
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import config from '../config';
const App = db.get<IApp>('apps');
@ -43,7 +44,7 @@ export const pack = (
let _app: any;
// Populate the app if 'app' is ID
if (mongo.ObjectID.prototype.isPrototypeOf(app)) {
if (isObjectId(app)) {
_app = await App.findOne({
_id: app
});
@ -56,7 +57,7 @@ export const pack = (
}
// Me
if (me && !mongo.ObjectID.prototype.isPrototypeOf(me)) {
if (me && !isObjectId(me)) {
if (typeof me === 'string') {
me = new mongo.ObjectID(me);
} else {

View File

@ -1,6 +1,7 @@
import * as mongo from 'mongodb';
const deepcopy = require('deepcopy');
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import { pack as packApp } from './app';
const AuthSession = db.get<IAuthSession>('authSessions');
@ -31,7 +32,7 @@ export const pack = (
_session = deepcopy(session);
// Me
if (me && !mongo.ObjectID.prototype.isPrototypeOf(me)) {
if (me && !isObjectId(me)) {
if (typeof me === 'string') {
me = new mongo.ObjectID(me);
} else {

View File

@ -1,5 +1,6 @@
import * as mongo from 'mongodb';
import monkDb, { nativeDbConn } from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
const DriveFileThumbnail = monkDb.get<IDriveFileThumbnail>('driveFileThumbnails.files');
DriveFileThumbnail.createIndex('metadata.originalId', { sparse: true, unique: true });
@ -35,7 +36,7 @@ export async function deleteDriveFileThumbnail(driveFile: string | mongo.ObjectI
let d: IDriveFileThumbnail;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(driveFile)) {
if (isObjectId(driveFile)) {
d = await DriveFileThumbnail.findOne({
_id: driveFile
});

View File

@ -3,6 +3,7 @@ const deepcopy = require('deepcopy');
import { pack as packFolder } from './drive-folder';
import config from '../config';
import monkDb, { nativeDbConn } from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import Note, { deleteNote } from './note';
import MessagingMessage, { deleteMessagingMessage } from './messaging-message';
import User from './user';
@ -78,7 +79,7 @@ export async function deleteDriveFile(driveFile: string | mongo.ObjectID | IDriv
let d: IDriveFile;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(driveFile)) {
if (isObjectId(driveFile)) {
d = await DriveFile.findOne({
_id: driveFile
});
@ -154,7 +155,7 @@ export const pack = (
let _file: any;
// Populate the file if 'file' is ID
if (mongo.ObjectID.prototype.isPrototypeOf(file)) {
if (isObjectId(file)) {
_file = await DriveFile.findOne({
_id: file
});

View File

@ -1,6 +1,7 @@
import * as mongo from 'mongodb';
const deepcopy = require('deepcopy');
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import DriveFile from './drive-file';
const DriveFolder = db.get<IDriveFolder>('driveFolders');
@ -29,7 +30,7 @@ export async function deleteDriveFolder(driveFolder: string | mongo.ObjectID | I
let d: IDriveFolder;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(driveFolder)) {
if (isObjectId(driveFolder)) {
d = await DriveFolder.findOne({
_id: driveFolder
});
@ -83,7 +84,7 @@ export const pack = (
let _folder: any;
// Populate the folder if 'folder' is ID
if (mongo.ObjectID.prototype.isPrototypeOf(folder)) {
if (isObjectId(folder)) {
_folder = await DriveFolder.findOne({ _id: folder });
} else if (typeof folder === 'string') {
_folder = await DriveFolder.findOne({ _id: new mongo.ObjectID(folder) });

View File

@ -1,6 +1,7 @@
import * as mongo from 'mongodb';
const deepcopy = require('deepcopy');
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import { pack as packNote } from './note';
const Favorite = db.get<IFavorite>('favorites');
@ -21,7 +22,7 @@ export async function deleteFavorite(favorite: string | mongo.ObjectID | IFavori
let f: IFavorite;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(favorite)) {
if (isObjectId(favorite)) {
f = await Favorite.findOne({
_id: favorite
});
@ -58,7 +59,7 @@ export const pack = (
let _favorite: any;
// Populate the favorite if 'favorite' is ID
if (mongo.ObjectID.prototype.isPrototypeOf(favorite)) {
if (isObjectId(favorite)) {
_favorite = await Favorite.findOne({
_id: favorite
});

View File

@ -1,6 +1,7 @@
import * as mongo from 'mongodb';
const deepcopy = require('deepcopy');
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import { pack as packUser } from './user';
const FollowRequest = db.get<IFollowRequest>('followRequests');
@ -12,6 +13,7 @@ export type IFollowRequest = {
createdAt: Date;
followeeId: mongo.ObjectID;
followerId: mongo.ObjectID;
requestId?: string; // id of Follow Activity
// 非正規化
_followee: {
@ -33,7 +35,7 @@ export async function deleteFollowRequest(followRequest: string | mongo.ObjectID
let f: IFollowRequest;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(followRequest)) {
if (isObjectId(followRequest)) {
f = await FollowRequest.findOne({
_id: followRequest
});
@ -63,7 +65,7 @@ export const pack = (
let _request: any;
// Populate the request if 'request' is ID
if (mongo.ObjectID.prototype.isPrototypeOf(request)) {
if (isObjectId(request)) {
_request = await FollowRequest.findOne({
_id: request
});

View File

@ -1,5 +1,6 @@
import * as mongo from 'mongodb';
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
const FollowedLog = db.get<IFollowedLog>('followedLogs');
export default FollowedLog;
@ -18,7 +19,7 @@ export async function deleteFollowedLog(followedLog: string | mongo.ObjectID | I
let f: IFollowedLog;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(followedLog)) {
if (isObjectId(followedLog)) {
f = await FollowedLog.findOne({
_id: followedLog
});

View File

@ -1,5 +1,6 @@
import * as mongo from 'mongodb';
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
const FollowingLog = db.get<IFollowingLog>('followingLogs');
export default FollowingLog;
@ -18,7 +19,7 @@ export async function deleteFollowingLog(followingLog: string | mongo.ObjectID |
let f: IFollowingLog;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(followingLog)) {
if (isObjectId(followingLog)) {
f = await FollowingLog.findOne({
_id: followingLog
});

View File

@ -1,5 +1,6 @@
import * as mongo from 'mongodb';
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
const Following = db.get<IFollowing>('following');
Following.createIndex(['followerId', 'followeeId'], { unique: true });
@ -32,7 +33,7 @@ export async function deleteFollowing(following: string | mongo.ObjectID | IFoll
let f: IFollowing;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(following)) {
if (isObjectId(following)) {
f = await Following.findOne({
_id: following
});

View File

@ -1,6 +1,7 @@
import * as mongo from 'mongodb';
const deepcopy = require('deepcopy');
import db from '../../../db/mongodb';
import isObjectId from '../../../misc/is-objectid';
import { IUser, pack as packUser } from '../../user';
const ReversiGame = db.get<IReversiGame>('reversiGames');
@ -62,7 +63,7 @@ export const pack = (
let _game: any;
// Populate the game if 'game' is ID
if (mongo.ObjectID.prototype.isPrototypeOf(game)) {
if (isObjectId(game)) {
_game = await ReversiGame.findOne({
_id: game
});
@ -76,7 +77,7 @@ export const pack = (
// Me
const meId: mongo.ObjectID = me
? mongo.ObjectID.prototype.isPrototypeOf(me)
? isObjectId(me)
? me as mongo.ObjectID
: typeof me === 'string'
? new mongo.ObjectID(me)

View File

@ -1,6 +1,7 @@
import * as mongo from 'mongodb';
const deepcopy = require('deepcopy');
import db from '../../../db/mongodb';
import isObjectId from '../../../misc/is-objectid';
import { IUser, pack as packUser } from '../../user';
const Matching = db.get<IMatching>('reversiMatchings');
@ -23,7 +24,7 @@ export const pack = (
// Me
const meId: mongo.ObjectID = me
? mongo.ObjectID.prototype.isPrototypeOf(me)
? isObjectId(me)
? me as mongo.ObjectID
: typeof me === 'string'
? new mongo.ObjectID(me)

View File

@ -1,5 +1,6 @@
import * as mongo from 'mongodb';
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
const MessagingHistory = db.get<IMessagingHistory>('messagingHistories');
export default MessagingHistory;
@ -19,7 +20,7 @@ export async function deleteMessagingHistory(messagingHistory: string | mongo.Ob
let m: IMessagingHistory;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(messagingHistory)) {
if (isObjectId(messagingHistory)) {
m = await MessagingHistory.findOne({
_id: messagingHistory
});

View File

@ -3,6 +3,7 @@ const deepcopy = require('deepcopy');
import { pack as packUser } from './user';
import { pack as packFile } from './drive-file';
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import MessagingHistory, { deleteMessagingHistory } from './messaging-history';
import { length } from 'stringz';
@ -30,7 +31,7 @@ export async function deleteMessagingMessage(messagingMessage: string | mongo.Ob
let m: IMessagingMessage;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(messagingMessage)) {
if (isObjectId(messagingMessage)) {
m = await MessagingMessage.findOne({
_id: messagingMessage
});
@ -72,7 +73,7 @@ export const pack = (
let _message: any;
// Populate the message if 'message' is ID
if (mongo.ObjectID.prototype.isPrototypeOf(message)) {
if (isObjectId(message)) {
_message = await MessagingMessage.findOne({
_id: message
});

View File

@ -1,5 +1,6 @@
import * as mongo from 'mongodb';
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
const Mute = db.get<IMute>('mute');
Mute.createIndex(['muterId', 'muteeId'], { unique: true });
@ -19,7 +20,7 @@ export async function deleteMute(mute: string | mongo.ObjectID | IMute) {
let m: IMute;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(mute)) {
if (isObjectId(mute)) {
m = await Mute.findOne({
_id: mute
});

View File

@ -2,6 +2,7 @@ import * as mongo from 'mongodb';
import $ from 'cafy';
const deepcopy = require('deepcopy');
import db from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import Reaction from './note-reaction';
import { pack as packUser } from './user';
@ -37,7 +38,7 @@ export async function deleteNoteReaction(noteReaction: string | mongo.ObjectID |
let n: INoteReaction;
// Populate
if (mongo.ObjectID.prototype.isPrototypeOf(noteReaction)) {
if (isObjectId(noteReaction)) {
n = await NoteReaction.findOne({
_id: noteReaction
});
@ -67,7 +68,7 @@ export const pack = (
let _reaction: any;
// Populate the reaction if 'reaction' is ID
if (mongo.ObjectID.prototype.isPrototypeOf(reaction)) {
if (isObjectId(reaction)) {
_reaction = await Reaction.findOne({
_id: reaction
});

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