Compare commits

...

196 Commits

Author SHA1 Message Date
08293f368f 12.41.0 2020-07-12 00:46:43 +09:00
d5378dab27 New Crowdin updates (#6498)
* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Kabyle)

* New translations ja-JP.yml (Kabyle)

* New translations ja-JP.yml (Kabyle)

* New translations ja-JP.yml (Kabyle)

* New translations ja-JP.yml (Kabyle)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Kannada)

* New translations ja-JP.yml (Uyghur)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Portuguese)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Danish)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Kabyle)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Kabyle)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Spanish)
2020-07-12 00:45:06 +09:00
91648d1bd4 フォロワーではないリモートユーザーに削除通知が配信されない問題を修正 (#6475)
* フォロワーではないリモートユーザーに削除通知が配信されない問題を修正

* 同じ処理を一つにまとめた

* Inのエラー修正, Renote/Quote対応

Co-authored-by: mei23 <m@m544.net>
2020-07-12 00:44:31 +09:00
66d6e71f06 Fix style of input(type="search") on macOS Safari (#6484) 2020-07-12 00:43:17 +09:00
a0ea5776ab fix #6335 (#6507) 2020-07-12 00:39:45 +09:00
9b73e897df Plugin system (#6479)
* wip

* wip

* wip

* wip

* Update store.ts
2020-07-12 00:38:55 +09:00
debc0086fa feat(client): 無限にダイアログを出すように
Resolve #6525
2020-07-12 00:31:37 +09:00
065ec8e170 fix(client): Fix timeline widget setting definition 2020-07-12 00:19:47 +09:00
11f8d742eb fix(client): Fix style 2020-07-12 00:17:30 +09:00
adf4f5410a style: Fix linr 2020-07-12 00:14:34 +09:00
8ff2694cad feat(client): ミューテーション監視をやめてページリロードするように 2020-07-12 00:12:30 +09:00
191c064611 chore: Add TODO 2020-07-12 00:01:55 +09:00
d327bb8ff1 chore: Update dependencies 🚀 2020-07-11 23:53:29 +09:00
80bebea9e6 テーマエディターの実装 (#6482)
* テーマ機能の実装

* resolve #6478

* 定数を削除できるように

* 変更を破棄するか確認ダイアログを表示するように

* fix code

* Update theme.ts

* ✌️

* fix path

* wip

* wip

* wip

Co-authored-by: syuilo <syuilotan@yahoo.co.jp>
2020-07-11 12:12:35 +09:00
cf3fc97202 Deck (#6504)
* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip
2020-07-11 10:13:11 +09:00
5b28d7bf90 タイムライン上でTwitterウィジットを展開できるようになど (#6496)
* TL上でTwitterウィジットを展開できるようになど

* use iframe

* Twitterウィジットがはみ出すのを修正
2020-07-11 06:25:20 +09:00
5f8fb43cc9 AP Delate Activityの修正 (#6512) 2020-07-11 06:19:49 +09:00
6eff6ee451 Update resolutions (#6516)
* Fix SNYK-JS-LODASH-567746

* Fix SNYK-JS-YARGSPARSER-560381

* Fix SNYK-JS-SERIALIZEJAVASCRIPT-570062
2020-07-11 06:18:43 +09:00
c2ab3a15f4 Fix #6397 Mastodon v2.5.0未満からのActivityが受け取れない (#6518) 2020-07-11 06:18:14 +09:00
a100e13a18 Fix #6513 キャッシュされてないリモートファイルのURLが相対URLで返ってくる (#6514) 2020-07-10 03:52:20 +09:00
a591a334ed refactor 2020-07-10 00:20:26 +09:00
ca2e53bd6e 🎨 2020-07-09 21:18:46 +09:00
d4b4b61535 feat(client): Add sound 🎵 2020-07-08 23:29:35 +09:00
440deb4624 Update mios.ts 2020-07-08 23:27:35 +09:00
bbb0130522 Update CHANGELOG.md 2020-07-07 22:23:16 +09:00
b6a4061097 fix 非ログイン時に n または p キー押下で投稿フォームが出る (#6508)
* fix #5851

* post-formのスポーンを弾く場所を変更
2020-07-07 15:50:47 +09:00
48c94907c2 Increase download timeout to 60 sec (#6503) 2020-07-06 23:55:59 +09:00
4fd06369d3 🎨 2020-07-06 18:20:42 +09:00
27a17b467d 🎨 2020-07-06 17:26:18 +09:00
c25cf7f89a Resolve #6500 2020-07-06 16:08:30 +09:00
ade11aa447 🎨 2020-07-06 00:09:36 +09:00
3799708daf feat(client): ウィジェットを画面スクロールに連動させるオプション 2020-07-06 00:03:08 +09:00
462204e204 ダークテーマを利用中だとウィジェット編集画面が見づらい問題を修正 (#6497) 2020-07-05 23:36:41 +09:00
752669bf5e 🎨 2020-07-05 23:30:23 +09:00
b08e3f59d3 scrollbar-widthを設定するように (#6495)
* scrollbar-widthを設定するように

* fix
2020-07-05 11:37:45 +09:00
443b45e509 Fix SNYK-JS-THENIFY-571690 (CVE-2020-7677) (#6491) 2020-07-05 06:41:40 +09:00
b2bed61088 12.40.0 2020-07-05 04:29:30 +09:00
be516d3c1e New Crowdin translations (#6449)
* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)
2020-07-05 04:28:40 +09:00
f5b41e1fbf refactor 2020-07-05 03:55:34 +09:00
e9afc1d867 refactror 2020-07-05 03:49:58 +09:00
a891f7e862 🎨 2020-07-05 03:38:50 +09:00
b715ea4621 🎨 2020-07-05 03:11:39 +09:00
ea13efe495 Add welcome widget 2020-07-05 02:09:14 +09:00
37f862947b ✌️ 2020-07-04 22:53:56 +09:00
ecb0861be4 refactor 2020-07-04 22:43:17 +09:00
624c9f3418 feat(client): ウィジェットを左にも置けるように 2020-07-04 22:33:42 +09:00
1b75984046 wip 2020-07-04 21:47:54 +09:00
157f1c66dc wip 2020-07-04 21:33:50 +09:00
cb41391bae wip 2020-07-04 21:19:12 +09:00
acc88825fc wip 2020-07-04 21:07:45 +09:00
233a837e35 chore(cleint): vclean up code 2020-07-04 20:42:29 +09:00
9e4456ac1b wip 2020-07-04 20:38:39 +09:00
83e1068da3 wip 2020-07-04 18:28:57 +09:00
1fd345f563 chore(client): 🎨 2020-07-04 18:28:31 +09:00
37c16e5b45 「すべて既読にする」でグループメッセージが既読にならない問題を修正 (#6476) 2020-07-04 10:45:36 +09:00
ca25b9acc1 投稿詳細でTwitterウィジェットが表示されなくなっているのを修正 Fix #6487 (#6488) 2020-07-03 23:12:50 +09:00
c3022d38f7 three.jsをr117に巻き戻す (#6483) 2020-07-02 19:17:26 +09:00
3599f16d22 chore(deps): Update dependencies 🚀 2020-06-27 23:25:06 +09:00
3f78f6f6bb feat(client): Do not wrap widgets 2020-06-27 20:54:56 +09:00
41f66e4299 chore: Update webpack 2020-06-27 11:21:50 +09:00
0d36b144cf fix サイドバーの設定に不具合があるとページが表示できなくなる (#6473)
* fix #6460

* Update app.vue

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2020-06-21 23:01:10 +09:00
aa652aac8a タップ不可能なリアクションを押してもパーティクルが出るバグを修正 (#6472)
* resolve #6453

* リアクションビューワーのトグル可能判定にログインしているかどうかも反映
2020-06-21 22:34:28 +09:00
8dbdab4a47 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2020-06-21 16:37:43 +09:00
90c07a220f chore(client): Improve emoji picker usability 2020-06-21 16:37:30 +09:00
23e2a870cc プロフィールの「場所」「誕生日」を連合するように Resove #6461 (#6463)
* AP birthday, location

* unset is null

* isCatを検証対象に
2020-06-21 14:09:01 +09:00
dc8eb7d4fe Update english nyaize (#6456)
* Update english nyaize

* Update src/misc/nyaize.ts

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
2020-06-21 14:07:27 +09:00
fd363f5617 chore(client): 🎨 2020-06-14 13:23:19 +09:00
1726ff3977 AP向けのアンケートのfallbackリンクなどを削除 (#6466) 2020-06-14 10:26:13 +09:00
93aba74463 アカウント切り替え後にインスタンス設定の表示値が変わらないのを修正 Fix #6448 (#6454)
* Fix #6448

* Use nextTick
2020-06-07 14:01:40 +09:00
99955f0af9 Update .gitignore (#6459) 2020-06-07 11:03:29 +09:00
30cf154542 Update CHANGELOG.md 2020-06-05 13:52:17 +09:00
f2c33b06cf Update CHANGELOG.md 2020-06-05 13:18:32 +09:00
f12473e677 12.39.1 2020-06-05 08:41:36 +09:00
e845db01bf Merge pull request #6409 from syuilo/l10n_develop
New Crowdin translations
2020-06-05 08:40:40 +09:00
7f76a73eee Revert "Revert "chore(src/docs): Fix miauth check url""
This reverts commit d44fbf58c9.
2020-06-05 08:37:41 +09:00
3c2d94ace3 Revert "fix(api): Fix #6418 (#6442)"
This reverts commit 83ec906ee7.
2020-06-05 08:37:27 +09:00
1e2239f527 New translations ja-JP.yml (Spanish) 2020-06-04 22:45:23 +09:00
1851daf9fd New translations ja-JP.yml (English) 2020-06-04 22:25:30 +09:00
f378f26e5e New translations ja-JP.yml (German) 2020-06-04 22:25:28 +09:00
cda6bc3404 New translations ja-JP.yml (Chinese Simplified) 2020-06-04 22:25:27 +09:00
071c7e6a58 feat(theme): Add mentionMe property 2020-06-04 22:19:08 +09:00
010e1b3ba4 12.39.0 2020-06-04 22:09:50 +09:00
66de51c1ca feat: Observe notification read and fix #6406 (#6407)
* Resolve https://github.com/syuilo/misskey/pull/6406#issuecomment-633203670

* Improve typing

* Observe notification read

* capture readAllNotifications

* fix

* fix

* Refactor

* Update src/client/components/notification.vue

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>

* Update src/client/components/notification.vue

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>

* missing ;

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2020-06-04 22:07:39 +09:00
265d6bda15 ローカルのみボタンを公開範囲ピッカーに統合 (#6428)
* ローカルのみを公開範囲ピッカーに統合

* デザイン調整

* 🎨

Co-authored-by: syuilo <syuilotan@yahoo.co.jp>
2020-06-04 22:06:38 +09:00
fecb12bae1 missing ; 2020-06-04 19:13:24 +09:00
83ec906ee7 fix(api): Fix #6418 (#6442) 2020-06-04 16:17:36 +09:00
d44fbf58c9 Revert "chore(src/docs): Fix miauth check url"
This reverts commit ddf92c3e2c.
2020-06-04 09:10:38 +09:00
9c4a789a4e Use insert for creating Note (#6440) 2020-06-04 08:59:03 +09:00
bfa1705bad New translations ja-JP.yml (French) 2020-06-04 03:33:34 +09:00
2876f2188c New translations ja-JP.yml (Spanish) 2020-06-03 23:36:32 +09:00
579c0043c3 New translations ja-JP.yml (Arabic) 2020-06-03 22:26:01 +09:00
0fa57957a4 New translations ja-JP.yml (Arabic) 2020-06-03 22:14:27 +09:00
05cb0b0ec5 New translations ja-JP.yml (Chinese Simplified) 2020-06-03 21:53:19 +09:00
4b24e96dfb New translations ja-JP.yml (Chinese Simplified) 2020-06-03 21:44:53 +09:00
c7eab37177 New translations ja-JP.yml (French) 2020-06-03 18:23:57 +09:00
c7d0b6cb29 New translations ja-JP.yml (English) 2020-06-03 17:11:02 +09:00
22ee087bb9 New translations ja-JP.yml (German) 2020-06-03 16:47:29 +09:00
2480fcdc53 Update src/client/components/notification.vue
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2020-06-03 13:42:32 +09:00
7e093aee5e Update src/client/components/notification.vue
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2020-06-03 13:42:26 +09:00
dd8413a485 New translations ja-JP.yml (Uyghur) 2020-06-03 13:32:48 +09:00
925f2912a9 New translations ja-JP.yml (German) 2020-06-03 13:32:47 +09:00
ed00ea0865 New translations ja-JP.yml (Spanish) 2020-06-03 13:32:45 +09:00
3f19d221b7 New translations ja-JP.yml (Czech) 2020-06-03 13:32:43 +09:00
808271838b New translations ja-JP.yml (Danish) 2020-06-03 13:32:42 +09:00
ac0950fdef New translations ja-JP.yml (Korean) 2020-06-03 13:32:40 +09:00
38f306ba73 New translations ja-JP.yml (Dutch) 2020-06-03 13:32:38 +09:00
5c1748d63d New translations ja-JP.yml (Norwegian) 2020-06-03 13:32:37 +09:00
c00cddf5b0 New translations ja-JP.yml (French) 2020-06-03 13:32:35 +09:00
baf3274748 New translations ja-JP.yml (Polish) 2020-06-03 13:32:33 +09:00
9e0515e563 New translations ja-JP.yml (Russian) 2020-06-03 13:32:32 +09:00
9c0404c407 New translations ja-JP.yml (Chinese Traditional) 2020-06-03 13:32:30 +09:00
0b85177690 New translations ja-JP.yml (English) 2020-06-03 13:32:28 +09:00
7ec28ced40 New translations ja-JP.yml (Kannada) 2020-06-03 13:32:27 +09:00
19ae3b66ec New translations ja-JP.yml (Japanese, Kansai) 2020-06-03 13:32:25 +09:00
0118dee3e5 New translations ja-JP.yml (Arabic) 2020-06-03 13:32:23 +09:00
9201714313 New translations ja-JP.yml (Portuguese) 2020-06-03 13:32:22 +09:00
8b9c1efd7e New translations ja-JP.yml (Chinese Simplified) 2020-06-03 13:32:20 +09:00
111eb43fd9 feat(client): 投稿フォームのボタンの説明を表示するように (#6408)
* Add title attr with buttons on the post form

* fix

* tooltip

* missing ;

* remove title attr

* fix bug

* Update reactions-viewer.details.vue

* help wip

* ok!

* i18n

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2020-06-03 13:30:17 +09:00
f2964101d1 fix(server): Fix #6433 2020-06-03 13:20:54 +09:00
6b2c289029 fix(api): Fix #6419
Close #6434
2020-06-03 13:19:07 +09:00
fd2573c068 署名検証失敗はリトライしないように (#6437) 2020-06-03 09:12:54 +09:00
df0e9d75fe Update README.md [AUTOGEN] (#6339) 2020-06-02 09:27:42 +09:00
2bc86756c8 iOS Safari 上で アイコンおよびバナーのアップロードができない不具合を修正 (#6427)
* fix #6076

* 参考文献を明記
2020-05-31 22:19:28 +09:00
fb91ab4080 Merge branch 'develop' into notification-visibility-read-2 2020-05-31 21:53:56 +09:00
0b4d29ed1e New translations ja-JP.yml (English) 2020-05-31 17:22:15 +09:00
2a8c65e2c3 New translations ja-JP.yml (German) 2020-05-31 17:22:13 +09:00
ffc7f42efc fix(client): 全既読系ボタンのAPIの指定が間違っているのを修正 (#6424) 2020-05-31 15:48:37 +09:00
7c38cda8ee Refactor 2020-05-31 14:57:22 +09:00
d3f5001679 fix 2020-05-31 14:54:04 +09:00
83d9a4b6d9 chore(client):🎨 Make font-size of note-preview em (#6414) 2020-05-31 14:46:50 +09:00
9760e08af4 New translations ja-JP.yml (Chinese Simplified) 2020-05-31 13:12:19 +09:00
8d48e4c76e feat(client): Convert text mfm node to text (v)dom node instead of span tag (#6399)
* Convert text mfm node to text (v)dom node
instead of span tag

* Update mfm.ts

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2020-05-31 12:57:21 +09:00
a1e0c866aa feat(client): 自動でもっと見るオプション (#6403)
* wip

* ugokanai

* wip

* implement setting subscribing

* fix lint

* ✌️

* Update notifications.vue

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2020-05-31 12:53:06 +09:00
8380222baf New translations ja-JP.yml (English) 2020-05-31 05:06:59 +09:00
eda7d60c26 Resolve #6412 (#6416) 2020-05-30 08:00:02 +09:00
ddf92c3e2c chore(src/docs): Fix miauth check url
Fix #6418
2020-05-29 22:36:01 +09:00
9bb528eb6e New translations ja-JP.yml (Arabic) 2020-05-26 19:26:54 +09:00
9756957ac1 New translations ja-JP.yml (French) 2020-05-26 19:26:52 +09:00
af0205b77d New translations ja-JP.yml (Arabic) 2020-05-26 19:14:21 +09:00
3f0da5453d New translations ja-JP.yml (Arabic) 2020-05-26 19:05:54 +09:00
923c3071f0 New translations ja-JP.yml (Arabic) 2020-05-26 18:56:03 +09:00
a8584973e2 New translations ja-JP.yml (Arabic) 2020-05-26 18:54:43 +09:00
886766cca5 fix 2020-05-26 15:04:44 +09:00
974abbe826 capture readAllNotifications 2020-05-26 15:00:15 +09:00
61bdf51e90 Observe notification read 2020-05-26 14:34:49 +09:00
9bee9d20f7 Improve typing 2020-05-26 14:33:55 +09:00
7aee3b88eb New translations ja-JP.yml (French) 2020-05-26 05:16:23 +09:00
d08184f5fe New translations ja-JP.yml (Arabic) 2020-05-26 04:12:58 +09:00
ae08232bfb New translations ja-JP.yml (French) 2020-05-26 04:12:56 +09:00
2b5e4b57bd New translations ja-JP.yml (Arabic) 2020-05-26 04:02:44 +09:00
35ae13a490 New translations ja-JP.yml (Arabic) 2020-05-26 03:52:45 +09:00
74f55b4d3f New translations ja-JP.yml (Arabic) 2020-05-26 03:42:53 +09:00
abe9440021 New translations ja-JP.yml (Arabic) 2020-05-26 03:32:52 +09:00
6a95b94aaa New translations ja-JP.yml (Arabic) 2020-05-26 03:16:43 +09:00
21ee38d813 New translations ja-JP.yml (Arabic) 2020-05-26 03:03:21 +09:00
9681a906d5 New translations ja-JP.yml (Arabic) 2020-05-26 02:48:09 +09:00
2ca760bee6 New translations ja-JP.yml (French) 2020-05-26 02:48:08 +09:00
da9f916daa New translations ja-JP.yml (French) 2020-05-26 02:32:29 +09:00
bc05b83a24 New translations ja-JP.yml (Spanish) 2020-05-26 01:32:56 +09:00
620e0a9df6 New translations ja-JP.yml (Spanish) 2020-05-26 01:22:45 +09:00
38ad4f7098 New translations ja-JP.yml (Spanish) 2020-05-26 01:13:00 +09:00
05c7cacdd1 Resolve https://github.com/syuilo/misskey/pull/6406#issuecomment-633203670 2020-05-24 18:41:40 +09:00
baa49271df 12.38.1 2020-05-24 18:15:56 +09:00
e2cbe70966 New Crowdin translations (#6379)
* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Uyghur)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Uyghur)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Kannada)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)
2020-05-24 18:15:00 +09:00
6a98301cc9 chore(deps): Update dependencies 🚀 2020-05-24 17:48:24 +09:00
81f1df7472 Resolve #6405 (#6406) 2020-05-24 13:53:31 +09:00
abc296cdcc refactor: use Object.fromEntries() instead of in-house implementation (#6401)
* refactor: use Object.fromEntries()
instead of in-house implementation

* Remove extra type assertions
2020-05-23 23:21:09 +09:00
4df5ec82ce Drop support for Node v11, v13 (#6402) 2020-05-23 23:19:16 +09:00
3963ed8ff7 feat(client): 翻訳をIndexedDBに保存・プッシュ通知を翻訳 (#6396)
* wip

* tabun ok

* better msg

* oops

* fix lint

* Update gulpfile.ts

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>

* Update src/client/scripts/set-i18n-contexts.ts

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>

* refactor

Co-authored-by: acid-chicken <root@acid-chicken.com>

* 

* wip

* fix lint

* たぶんおk

* fix flush

* Translate Notification

* remove console.log

* fix

* add notifications

* remove san

* wip

* ok

* ✌️

* Update src/prelude/array.ts

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>

* wip

* i18n refactor

* Update init.ts

* ✌️

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
Co-authored-by: syuilo <syuilotan@yahoo.co.jp>
2020-05-23 13:19:31 +09:00
11141c878c fix(i18n): Fix missing translation 2020-05-20 11:16:10 +09:00
b1a2046a7f Update CHANGELOG.md 2020-05-18 14:26:55 +09:00
e44322c9bf Update CHANGELOG.md 2020-05-18 14:25:36 +09:00
2e6462bf1b Update CHANGELOG.md 2020-05-18 14:21:07 +09:00
667d9c2be3 12.38.0 2020-05-17 14:50:33 +09:00
34a86229db chore(deps): Update dependencies 🚀 2020-05-17 14:50:00 +09:00
7dd8dbeb5b feat(client): 💴 2020-05-17 14:43:25 +09:00
b5fb98f01a New Crowdin translations (#6342)
* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)
2020-05-17 14:02:10 +09:00
DW
f6cfa5cbb4 Fix CASCADE-related problems (#6374)
* Fix renotes remaining on remote when CASCADE is invoked

* Fix CASCADE-invoked deletion not being federated to relays

Co-authored-by: DW <chocological00@gitlab.com>
2020-05-17 00:49:46 +09:00
c1b95838f6 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2020-05-16 23:51:32 +09:00
6cee608c91 chore(locale): Add doll-ai translation 2020-05-16 23:51:28 +09:00
d979fb6dc0 Add Ai3Dstatic model for Room. (#6350)
* Add Ai3Dstatic model for Room.

* Update src/client/scripts/room/furnitures.json5

Co-authored-by: rinsuki <428rinsuki+git@gmail.com>

* Update src/client/scripts/room/furnitures.json5

Co-authored-by: rinsuki <428rinsuki+git@gmail.com>

* doll-Aiの大文字を小文字へ変更

* Update furnitures.json5

* マテリアルをBackgroundからPrincipled BSDFに変更

* a

* なんかファイルが二重にでてくるので削除

* テクスチャーファイルと3Dデータを再コミット

* Remove noodle

* Update doll-ai.glb

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Co-authored-by: rinsuki <428rinsuki+git@gmail.com>
2020-05-16 23:50:25 +09:00
ca2a33edc9 fix(client): Use router-link instead of a to avoid page refresh 2020-05-16 22:08:21 +09:00
DW
ea80d5eac2 Local only indicator (#6291)
* Add Local only & public indicator

* Add local only & public indicator on renotes


remove visibility conditional

* Cleaner Style

* ✌️

* Update note-header.vue

* Update note.vue

Co-authored-by: DW <chocological00@gitlab.com>
Co-authored-by: syuilo <syuilotan@yahoo.co.jp>
2020-05-16 22:06:39 +09:00
51cf0970b3 feat(client): ローカルのみボタンを公開範囲ボタンの横に移動 2020-05-16 21:50:16 +09:00
DW
9c8eb93446 Only show ellipsis if the button's interactable (#6373)
* Add an indicator to make the undo renote button look more interactable

* Use faEllipsisH :art

* Only show elipsis if it's interactable

* Update note.vue

Co-authored-by: DW <chocological00@gitlab.com>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2020-05-16 12:15:59 +09:00
3ac3a45aa5 nyaizeが適用されるとMFMのオプションが失われるのを修正 Fix #6370 (#6371) 2020-05-16 08:40:17 +09:00
36fcc0d5f6 Cache extra AP objects (#6349)
* Cache extra AP objects

* Cache nodeinfo
2020-05-15 21:37:09 +09:00
6667b86650 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2020-05-15 20:53:29 +09:00
9244efe351 fix(client): Mk:api関数にトークンを渡せない問題 2020-05-15 20:53:24 +09:00
538ca2a7c7 リレーに不正なURLは追加できないように (#6351)
* リレーに不正なURLは追加できないように

* lint
2020-05-15 20:51:16 +09:00
c5dd9439d5 Apply blocked instance to LD-Signature host (#6355) 2020-05-15 20:50:28 +09:00
2170c27b62 リレーのHTTP-Signatureは投稿者の鍵でするように (#6357) 2020-05-15 20:50:04 +09:00
61582a0a33 Supports Unicode 13.0 emoji (#6365)
* Supports Unicode 13.0 emoji

* fix
2020-05-15 20:49:01 +09:00
DW
65efe1f42c Add an indicator to make the undo renote button look more interactable (#6366)
* Add an indicator to make the undo renote button look more interactable

* Use faEllipsisH :art

Co-authored-by: DW <chocological00@gitlab.com>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2020-05-15 20:39:11 +09:00
b2d3d43c97 reCAPTCHAが動かなくなっているのを修正 (#6367) 2020-05-15 20:37:05 +09:00
4ce330c59e refactor(client): Add note 2020-05-11 22:43:50 +09:00
287 changed files with 8162 additions and 3436 deletions

View File

@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
node-version: [11.10.x, 12.x, 13.x, 14.x]
node-version: [12.x, 14.x]
services:
postgres:

2
.gitignore vendored
View File

@ -12,7 +12,7 @@ report.*.json
# config
/.config/*
!/.config/example.yml
!/.config/mongo_initdb_example.js
!/.config/docker_example.env
# misskey
/build

View File

@ -1 +1 @@
v12.11.1
v14.4.0

View File

@ -1,6 +1,79 @@
ChangeLog
=========
12.40.0 (2020/7/5)
-------------------
### ✨Improvements
- AP向けのアンケートのfallbackリンク`リモートで結果を表示`)、`番号を返信して投票``_misskey_fallback_content`を削除 [#6466](https://github.com/syuilo/misskey/pull/6466)
- 英語のNyaizeを改良 [#6456](https://github.com/syuilo/misskey/pull/6456)
- プロフィールの「場所」「誕生日」を連合するように [#6463](https://github.com/syuilo/misskey/pull/6463)
- リアクションピッカーの入力で空白を無視するように [90c07a2](https://github.com/syuilo/misskey/commit/90c07a220f1787cd25a17feefe2df667db5b630d)
- ウィジェットを左に置けるように [624c9f3](https://github.com/syuilo/misskey/commit/624c9f3418ce1c2597fbe2cb75caf01939e4d845)
- ウェルカムウィジェットの追加 [ea13efe](https://github.com/syuilo/misskey/commit/ea13efe495272fcfc9fb29c4f2127e4f908f9802)
- 全体的なデザインの変更
### 🐛Fixes
- アカウント切り替え後にインスタンス設定の表示値が変わらないのを修正 [#6454](https://github.com/syuilo/misskey/pull/6454)
- isCatがLD-Signatureの対象になってないのを修正 [#6463](https://github.com/syuilo/misskey/pull/6463)
- タップ不可能なリアクションを押してもパーティクルが出るのを修正 [#6472](https://github.com/syuilo/misskey/pull/6472)
- サイドバーの設定に不具合があるとページが表示できなくなる問題を修正 [#6473](https://github.com/syuilo/misskey/pull/6473)
- 投稿詳細でTwitterウィジェットが表示されなくなっているのを修正 [#6488](https://github.com/syuilo/misskey/pull/6488)
- 「すべて既読にする」でグループメッセージが既読にならない問題を修正 [#6476](https://github.com/syuilo/misskey/pull/6476)
12.39.1 (2020/6/5)
-------------------
### ✨Improvements
- メンションの色をテーマで指定できるように [071c7e6](https://github.com/syuilo/misskey/commit/071c7e6a581ca5d025d414869e03536011219370)
### 🐛Fixes
- リモートからのノートが受信できない問題を修正 [3c2d94ac](https://github.com/syuilo/misskey/commit/3c2d94ace31c0dbbbd18606d16828df60d0392eb), [7f76a73e](https://github.com/syuilo/misskey/commit/7f76a73eeef5df3b1fc02a00a0ca5710383a2429)
* MiAuthのレスポンスが返ってこない問題を修正を差し戻し
- ドキュメントのMiAuthのURLを現状利用できるものに修正 [ddf92c3e](https://github.com/syuilo/misskey/commit/ddf92c3e2c5bdfc89e5c223a3cc2794f6a023400), [7f76a73e](https://github.com/syuilo/misskey/commit/7f76a73eeef5df3b1fc02a00a0ca5710383a2429)
12.39.0 (2020/6/4)
-------------------
**12.39.0にはリモートからのノートが受信できないという重大なバグがありますので、使わないでください。**
**NEVER USE 12.39.0 because it has a serious bug that Misskey cannot recieve notes from remotes.**
### ✨Improvements
- アラビア語を追加 [#6416](https://github.com/syuilo/misskey/pull/6416)
- 自動でもっと見る [#6403](https://github.com/syuilo/misskey/pull/6403)
- MFMのテキストードは、HTMLではspanタグではなくテキストードに変換するように [#6399](https://github.com/syuilo/misskey/pull/6399)
- ローカルのみボタンを公開範囲ピッカーに統合 [#6428](https://github.com/syuilo/misskey/pull/6428)
- ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブではない時)は通知を既読にしないように [#6407](https://github.com/syuilo/misskey/pull/6407)
- 通知一覧で、通知が画面に表示されると既読にするように [#6407](https://github.com/syuilo/misskey/pull/6407)
- APIのNotificationでisRead既読かどうかを含めるように [#6407](https://github.com/syuilo/misskey/pull/6407)
### 🐛Fixes
- 引用ノートのフォントサイズがおかしいときがあるのを修正 [#6414](https://github.com/syuilo/misskey/pull/6414)
- iOS Safari 上で アイコンおよびバナーのアップロードができない不具合を修正 [#6427](https://github.com/syuilo/misskey/pull/6427)
- APで `HTTP-Signature検証失敗 かつ LD-Signatureなし` がキューに溜まってリトライし続けるのを修正 [#6437](https://github.com/syuilo/misskey/pull/6437)
- MiAuthでトークンが利用できない問題を修正 [6b2c2890](https://github.com/syuilo/misskey/commit/6b2c289029cbf01537c2a67a3e61d615aad30c34)
- Twitterのプレビューが利用できなくなっている問題を修正 [f296410](https://github.com/syuilo/misskey/commit/f2964101d162fb64ac9e7ad99123c5bb568ac52b)
- IDの重複が起きてしまう問題を修正 [#6440](https://github.com/syuilo/misskey/pull/6440)
- ※MiAuthのレスポンスが返ってこない問題を修正 [#6418](https://github.com/syuilo/misskey/issues/6418)
12.38.0 (2020/5/17)
-------------------
### ✨Improvements
* Renoteの削除をわかりやすく [#6366](https://github.com/syuilo/misskey/pull/6366), [#6373](https://github.com/syuilo/misskey/pull/6373)
* Unicode 13.0の絵文字に対応 [#6365](https://github.com/syuilo/misskey/pull/6365)
* リレーのHTTP-Signatureは投稿者の鍵でするように [#6357](https://github.com/syuilo/misskey/pull/6357)
* 追加のAPオブジェクトをキャッシュ出来るように [#6349](https://github.com/syuilo/misskey/pull/6349)
* ローカルのみボタンを公開範囲ボタンの横に移動 [51cf097](https://github.com/syuilo/misskey/commit/51cf0970b3b990cd67c94c5fcc5d7c1c3f7f13df)
* 公開範囲がローカルのみであることを表示するように [#6291](https://github.com/syuilo/misskey/pull/6291)
* Roomに藍ちゃん人形と札束を追加 [#6350](https://github.com/syuilo/misskey/pull/6350), [6cee608](https://github.com/syuilo/misskey/commit/6cee608c91850c035c35f605296410e72d1ef793), [7dd8dbe](https://github.com/syuilo/misskey/commit/7dd8dbeb5b2f33b679248ecc2138f556b72d9a06)
* ユーザーページの画像欄の画像をクリックしたとき、UIが再読み込みされないように [ca2a33e](https://github.com/syuilo/misskey/commit/ca2a33edc928c0dfe59f50502d3eedb9e97e88db)
### 🐛Fixes
* reCAPTCHAが動かなくなっているのを修正 [#6367](https://github.com/syuilo/misskey/pull/6367)
* インスタンスブロックがリレーに適用されない問題を修正 [#6355](https://github.com/syuilo/misskey/pull/6355)
* リレーに不正なURLを追加できてしまう問題を修正 [#6351](https://github.com/syuilo/misskey/pull/6351)
* Pages: Mk:api関数にトークンを渡せない問題を修正 [9244efe](https://github.com/syuilo/misskey/commit/9244efe3513dd72be04d7588dea8ec27509e96d1)
* nyaizeが適用されるとMFMのオプションが失われるのを修正 [#6371](https://github.com/syuilo/misskey/pull/6371)
* 上流ノートの削除に伴うノートの削除が連合リレーに伝達されない問題を修正 [#6374](https://github.com/syuilo/misskey/pull/6374)
* 引用元の削除に伴う引用RNの削除がリモートに伝達されない問題を修正 [#6374](https://github.com/syuilo/misskey/pull/6374)
12.37.0 (2020/5/10)
-------------------
### ✨Improvements

View File

@ -1,4 +1,4 @@
FROM node:14.2.0-alpine AS base
FROM node:14.4.0-alpine AS base
ENV NODE_ENV=production

View File

@ -114,6 +114,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/3.png?token-time=2145916800&token-hash=oH_i7gJjNT7Ot6j9JiVwy7ZJIBqACVnzLqlz4YrDAZA%3D" alt="weepjp " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/605366/c9dc408fdcbf412fb183ca5b06235f8d/1.jpeg?token-time=2145916800&token-hash=oaqsjLqOFjWN5I9hm2epOaTXaEtKwQUy5OW-EpAz6-g%3D" alt="Jon Leibowitz" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19045173/cb91c0f345c24d4ebfd05f19906d5e26/1.png?token-time=2145916800&token-hash=o_zKBytJs_AxHwSYw_5R8eD0eSJe3RoTR3kR3Q0syN0%3D" alt="kiritan " width="100"></td>
<td><img src="https://c8.patreon.com/2/200/27648259" alt="みなしま " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/24430516/b1964ac5b9f746d2a12ff53dbc9aa40a/1.jpg?token-time=2145916800&token-hash=bmEiMGYpp3bS7hCCbymjGGsHBZM3AXuBOFO3Kro37PU%3D" alt="Eduardo Quiros" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/user?u=20832595">Roujo </a></td>
@ -121,10 +122,12 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/weepjp">weepjp </a></td>
<td><a href="https://www.patreon.com/jonleibowitz">Jon Leibowitz</a></td>
<td><a href="https://www.patreon.com/user?u=19045173">kiritan </a></td>
<td><a href="https://www.patreon.com/user?u=27648259">みなしま </a></td>
<td><a href="https://www.patreon.com/user?u=24430516">Eduardo Quiros</a></td>
</tr></table>
<table><tr>
<td><img src="https://c8.patreon.com/2/200/776209" alt="Denshi " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/14215107/1cbe1912c26143919fa0faca16f12ce1/4.jpg?token-time=2145916800&token-hash=BslMqDjTjz8KYANLvxL87agHTugHa0dMPUzT-hwR6Vk%3D" alt="Nesakko" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/776209" alt="Demogrognard" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/3075183/c2ae575c604e420297f000ccc396e395/1.jpeg?token-time=2145916800&token-hash=O9qmPtpo6wWb0OuvnkEekhk_1WO2MTdytLr7ZgsAr80%3D" alt="Liaizon Wakest" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/557245" alt="mkatze " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/23915207/25428766ecd745478e600b3d7f871eb2/1.png?token-time=2145916800&token-hash=urCLLA4KjJZX92Y1CxcBP4d8bVTHGkiaPnQZp-Tqz68%3D" alt="kabo2468y " width="100"></td>
@ -133,9 +136,9 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5670915/ee175f0bfb6347ffa4ea101a8c097bff/1.jpg?token-time=2145916800&token-hash=mPLM9CA-riFHx-myr3bLZJuH2xBRHA9se5VbHhLIOuA%3D" alt="osapon " width="100"></td>
<td><img src="https://c8.patreon.com/2/200/16869916" alt="見当かなみ " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18899730/6a22797f68254034a854d69ea2445fc8/1.png?token-time=2145916800&token-hash=b_uj57yxo5VzkSOUS7oXE_762dyOTB_oxzbO6lFNG3k%3D" alt="YuzuRyo61 " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5788159/af42076ab3354bb49803cfba65f94bee/1.jpg?token-time=2145916800&token-hash=iSaxp_Yr2-ZiU2YVi9rcpZZj9mj3UvNSMrZr4CU4qtA%3D" alt="mewl hayabusa" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/user?u=776209">Denshi </a></td>
<td><a href="https://www.patreon.com/Nesakko">Nesakko</a></td>
<td><a href="https://www.patreon.com/user?u=776209">Demogrognard</a></td>
<td><a href="https://www.patreon.com/wakest">Liaizon Wakest</a></td>
<td><a href="https://www.patreon.com/user?u=557245">mkatze </a></td>
<td><a href="https://www.patreon.com/user?u=23915207">kabo2468y </a></td>
@ -144,9 +147,9 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/osapon">osapon </a></td>
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ </a></td>
<td><a href="https://www.patreon.com/Yuzulia">YuzuRyo61 </a></td>
<td><a href="https://www.patreon.com/hs_sh_net">mewl hayabusa</a></td>
</tr></table>
<table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5788159/af42076ab3354bb49803cfba65f94bee/1.jpg?token-time=2145916800&token-hash=iSaxp_Yr2-ZiU2YVi9rcpZZj9mj3UvNSMrZr4CU4qtA%3D" alt="mewl hayabusa" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/28779508/3cd4cb7f017f4ee0864341e3464d42f9/1.png?token-time=2145916800&token-hash=eGQtR15be44kgvh8fw2Jx8Db4Bv15YBp2ldxh0EKRxA%3D" alt="S Y" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/16542964" alt="Takumi Sugita" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/17866454" alt="sikyosyounin " width="100"></td>
@ -154,9 +157,8 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/26340354/08834cf767b3449e93098ef73a434e2f/2.png?token-time=2145916800&token-hash=nyM8DnKRL8hR47HQ619mUzsqVRpkWZjgtgBU9RY15Uc%3D" alt="totokoro " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19356899/496b4681d33b4520bd7688e0fd19c04d/2.jpeg?token-time=2145916800&token-hash=_sTj3dUBOhn9qwiJ7F19Qd-yWWfUqJC_0jG1h0agEqQ%3D" alt="sheeta.s " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5827393/59893c191dda408f9cabd0f20a3a5627/1.jpeg?token-time=2145916800&token-hash=i9N05vOph-eP1LTLb9_npATjYOpntL0ZsHNaZFSsPmE%3D" alt="motcha " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/20494440/540beaf2445f408ea6597bc61e077bb3/1.png?token-time=2145916800&token-hash=UJ0JQge64Bx9XmN_qYA1inMQhrWf4U91fqz7VAKJeSg%3D" alt="axtuki1 " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13737140/1adf7835017d479280d90fe8d30aade2/1.png?token-time=2145916800&token-hash=0pdle8h5pDZrww0BDOjdz6zO-HudeGTh36a3qi1biVU%3D" alt="Satsuki Yanagi" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/hs_sh_net">mewl hayabusa</a></td>
<td><a href="https://www.patreon.com/user?u=28779508">S Y</a></td>
<td><a href="https://www.patreon.com/user?u=16542964">Takumi Sugita</a></td>
<td><a href="https://www.patreon.com/user?u=17866454">sikyosyounin </a></td>
@ -164,10 +166,10 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/user?u=26340354">totokoro </a></td>
<td><a href="https://www.patreon.com/user?u=19356899">sheeta.s </a></td>
<td><a href="https://www.patreon.com/user?u=5827393">motcha </a></td>
<td><a href="https://www.patreon.com/user?u=20494440">axtuki1 </a></td>
<td><a href="https://www.patreon.com/user?u=13737140">Satsuki Yanagi</a></td>
</tr></table>
<table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/20494440/540beaf2445f408ea6597bc61e077bb3/1.png?token-time=2145916800&token-hash=UJ0JQge64Bx9XmN_qYA1inMQhrWf4U91fqz7VAKJeSg%3D" alt="axtuki1 " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13737140/1adf7835017d479280d90fe8d30aade2/1.png?token-time=2145916800&token-hash=0pdle8h5pDZrww0BDOjdz6zO-HudeGTh36a3qi1biVU%3D" alt="Satsuki Yanagi" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17880724/311738c8a48f4a6b9443c2445a75adde/1.jpg?token-time=2145916800&token-hash=nVAntpybQrznE0rg05keLrSE6ogPKJXB13rmrJng42c%3D" alt="takimura " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13100201/fc5be4fa90444f09a9c8a06f72385272/1.png?token-time=2145916800&token-hash=i8PjlgfOB2LPEdbtWyx8ZPsBKhGcNZqcw_FQmH71UGU%3D" alt="aqz tamaina" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/28295158/cd2451bfb94a449dbf705ef4718cd355/2.jpeg?token-time=2145916800&token-hash=MRv3BxufHPuCyiBSxU5UYmLGvD6YZlhtSFRfMWg2k4U%3D" alt="012 " width="100"></td>
@ -178,8 +180,9 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5923936/2a743cbfbff946c2af3f09026047c0da/2.png?token-time=2145916800&token-hash=h6yphW1qnM0n_NOWaf8qtszMRLXEwIxfk5beu4RxdT0%3D" alt="noellabo " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/2384390/5681180e1efb46a8b28e0e8d4c8b9037/1.jpg?token-time=2145916800&token-hash=SJcMy-Q1BcS940-LFUVOMfR7-5SgrzsEQGhYb3yowFk%3D" alt="CG " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18072312/98e894d960314fa7bc236a72a39488fe/1.jpg?token-time=2145916800&token-hash=7bkMqTwHPRsJPGAq42PYdDXDZBVGLqdgr1ZmBxX8GFQ%3D" alt="Hekovic " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/24641572/b4fd175424814f15b0ca9178d2d2d2e4/1.png?token-time=2145916800&token-hash=e2fyqdbuJbpCckHcwux7rbuW6OPkKdERcus0u2wIEWU%3D" alt="uroco @99" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/user?u=20494440">axtuki1 </a></td>
<td><a href="https://www.patreon.com/user?u=13737140">Satsuki Yanagi</a></td>
<td><a href="https://www.patreon.com/takimura">takimura </a></td>
<td><a href="https://www.patreon.com/aqz">aqz tamaina</a></td>
<td><a href="https://www.patreon.com/user?u=28295158">012 </a></td>
@ -190,21 +193,22 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/noellabo">noellabo </a></td>
<td><a href="https://www.patreon.com/Corset">CG </a></td>
<td><a href="https://www.patreon.com/hekovic">Hekovic </a></td>
<td><a href="https://www.patreon.com/user?u=24641572">uroco @99</a></td>
</tr></table>
<table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/24641572/b4fd175424814f15b0ca9178d2d2d2e4/1.png?token-time=2145916800&token-hash=e2fyqdbuJbpCckHcwux7rbuW6OPkKdERcus0u2wIEWU%3D" alt="uroco @99" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5731881/4b6038e6cda34c04b83a5fcce3806a93/1.png?token-time=2145916800&token-hash=hBayGfOmQH3kRMdNnDe4oCZD_9fsJWSt29xXR3KRMVk%3D" alt="Nokotaro Takeda" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/23932002" alt="nenohi " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/9481273/7fa89168e72943859c3d3c96e424ed31/4.jpeg?token-time=2145916800&token-hash=5w1QV1qXe-NdWbdFmp1H7O_-QBsSiV0haumk3XTHIEg%3D" alt="Efertone " width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1.jpeg?token-time=2145916800&token-hash=vGe7wXGqmA8Q7m-kDNb6fyGdwk-Dxk4F-ut8ZZu51RM%3D" alt="Takashi Shibuya" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/user?u=24641572">uroco @99</a></td>
<td><a href="https://www.patreon.com/takenoko">Nokotaro Takeda</a></td>
<td><a href="https://www.patreon.com/user?u=23932002">nenohi </a></td>
<td><a href="https://www.patreon.com/efertone">Efertone </a></td>
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
</tr></table>
**Last updated:** Thu, 07 May 2020 18:00:08 UTC
**Last updated:** Tue, 02 Jun 2020 00:00:08 UTC
<!-- PATREON_END -->
[backer-url]: #backers

View File

@ -53,7 +53,6 @@ server {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Accept-Encoding "";
proxy_http_version 1.1;
proxy_redirect off;

View File

@ -22,8 +22,8 @@ adduser --disabled-password --disabled-login misskey
Please install and setup these softwares:
#### Dependencies :package:
* **[Node.js](https://nodejs.org/en/)** >= 11.10.1
* **[PostgreSQL](https://www.postgresql.org/)** >= 10
* **[Node.js](https://nodejs.org/en/)** (12.x, 14.x)
* **[PostgreSQL](https://www.postgresql.org/)** (>= 10)
* **[Redis](https://redis.io/)**
##### Optional

View File

@ -22,8 +22,8 @@ adduser --disabled-password --disabled-login misskey
Installez les paquets suivants :
#### Dépendences :package:
* **[Node.js](https://nodejs.org/en/)** >= 11.10.1
* **[PostgreSQL](https://www.postgresql.org/)** >= 10
* **[Node.js](https://nodejs.org/en/)** (12.x, 14.x)
* **[PostgreSQL](https://www.postgresql.org/)** (>= 10)
* **[Redis](https://redis.io/)**
##### Optionnels

View File

@ -22,7 +22,7 @@ adduser --disabled-password --disabled-login misskey
これらのソフトウェアをインストール・設定してください:
#### 依存関係 :package:
* **[Node.js](https://nodejs.org/en/)** (11.10.1以上)
* **[Node.js](https://nodejs.org/en/)** (12.x, 14.x)
* **[PostgreSQL](https://www.postgresql.org/)** (10以上)
* **[Redis](https://redis.io/)**

View File

@ -11,7 +11,7 @@ const cleanCSS = require('gulp-clean-css');
const sass = require('gulp-dart-sass');
const fiber = require('fibers');
const locales = require('./locales');
const locales: { [x: string]: any } = require('./locales');
const meta = require('./package.json');
gulp.task('build:ts', () => {
@ -31,8 +31,10 @@ gulp.task('build:copy:views', () =>
gulp.task('build:copy:locales', cb => {
fs.mkdirSync('./built/client/assets/locales', { recursive: true });
const v = { '_version_': meta.version };
for (const [lang, locale] of Object.entries(locales)) {
fs.writeFileSync(`./built/client/assets/locales/${lang}.${meta.version}.json`, JSON.stringify(locale), 'utf-8');
fs.writeFileSync(`./built/client/assets/locales/${lang}.${meta.version}.json`, JSON.stringify({ ...locale, ...v }), 'utf-8');
}
cb();

464
locales/ar-SA.yml Normal file
View File

@ -0,0 +1,464 @@
---
_lang_: "العربية"
monthAndDay: "{day}/{month}"
search: "البحث"
notifications: "الإشعارات"
username: "اسم المستخدم"
password: "الكلمة السرية"
fetchingAsApObject: "جارٍ جلبه مِن الفديفرس…"
ok: " حسناً"
gotIt: "فهِمت"
cancel: " إلغاء"
enterUsername: "أدخِل إسم مسخدم"
noNotes: "لم يتم العثور على أية ملاحظات"
noNotifications: "ليس هناك أية اشعارات"
instance: "مثيل الخادم"
settings: "الاعدادات"
profile: "الملف التعريفي"
timeline: "الخيط الزمني"
login: "لِج"
loggingIn: "جارٍ تسجيل الدخول"
logout: "الخروج"
signup: "أنشئ حسابًا"
uploading: "عملية الإرسال جارية"
save: "حفظ"
users: "المستخدمون"
addUser: "اضافة مستخدم"
favorite: "إضافة إلى المفضلة"
favorites: "المفضلات"
unfavorite: "إزالة من المفضلة"
pin: "دبّسها على الصفحة الشخصية"
copyContent: "انسخ المحتوى"
copyLink: "انسخ الرابط"
delete: "حذف"
deleteAndEdit: "إزالة وإعادة الصياغة"
addToList: "أضفه إلى قائمة"
copyUsername: "انسخ اسم المستخدم"
reply: "رد"
loadMore: "عرض المزيد"
youGotNewFollower: "يتابعك"
mentions: "الإشارات"
directNotes: "الملاحظات المباشرة"
import: "استيراد"
export: "تصدير"
files: "الملفات"
download: "تنزيل"
lists: "القوائم"
noLists: "ليس لديك أية قائمة"
note: "ملاحظة"
notes: "الملاحظات"
following: "المتابَعون"
followers: "المتابِعين"
followsYou: "يتابعك"
createList: "إنشاء قائمة"
manageLists: "إدارة القوائم"
error: "حدث خطأ ما"
retry: "حاول مجددًا"
enterListName: "اسم القائمة"
privacy: "الخصوصية"
makeFollowManuallyApprove: "القبول يدويا طلبات الإشتراك"
follow: "تابِع"
followRequest: "طلب اشتراك"
followRequests: "طلبات الإشتراك"
unfollow: "إلغاء الاشتراك"
followRequestPending: "طلبات الإشتراك المعلّقة"
quote: "اقتبس"
pinnedNote: "ملاحظة مدبسة"
you: "أنت"
clickToShow: "اضغط للعرض"
sensitive: "محتوى حساس"
add: "إضافة"
enterFileName: "ادخل اسم الملف"
mute: "اكتم"
unmute: "إلغاء الكتم"
block: "احجب"
unblock: "إلغاء الحجب"
selectList: "اختر قائمة"
customEmojis: "إيموجي مخصص"
addEmoji: "إضافة إيموجي"
addAcount: "إضافة حساب"
showOnRemote: "رؤيته على مثيل الخادم البُعدي"
general: "الرئيسية"
wallpaper: "خلفية الشاشة"
setWallpaper: "استخدم خلفية الشاشة"
removeWallpaper: "إزالة خلفية الشاشة"
searchWith: "البحث: {q}"
youHaveNoLists: "لا تمتلك أية قائمة"
proxyAccount: "حساب وكيل البروكسي"
host: "المضيف"
selectUser: "حدّد مستخدمًا"
recipient: "المرسَل إليه·ها"
annotation: "التعليقات"
federation: "الفديرالية"
instances: "مثيل الخادم"
latestRequestSentAt: "آخر طلب أرسِل في"
charts: "المنحنيات البيانية"
perHour: "في الساعة"
perDay: "في اليوم"
stopActivityDelivery: "وقف إرسال النشاط"
blockThisInstance: "احجب مثيل الخادم هذا"
operations: "الإجراءات"
software: "البرنامج"
version: "الإصدار"
metadata: "البيانات الوصفية"
withNFiles: "{n} ملف (ملفات)"
monitor: "شاشة التحكم"
jobQueue: "قائمة الانتظار"
cpuAndMemory: "وحدة المعالجة المركزية والذاكرة"
network: "الشبكة"
disk: "قرص التخزين"
instanceInfo: "معلومات مثيل الخادم"
statistics: "الإحصائيات"
clearQueue: "تفريغ قائمة الإنتظار"
muteAndBlock: "تم كتمها / تم حجبها"
mutedUsers: "الحسابات التي تم كتمها"
blockedUsers: "الحسابات التي تم حظرها"
noUsers: "ليس هناك مستخدمون"
editProfile: "تعديل الملف التعريفي"
noteDeleteConfirm: "هل تريد حذف هذه الملاحظة؟"
pinLimitExceeded: "لا يمكنك تدبيس الملاحظات بعد الآن."
intro: "لقد انتهت عملية تنصيب Misskey. الرجاء إنشاء حساب إداري."
done: "تمّ"
processing: "المعالجة جارية"
preview: "معاينة"
default: "افتراضي"
noCustomEmojis: "ليس هناك إيموجيات"
customEmojisOfRemote: "الإيموجيات القادمة مِن مثيلات الخوادم الأخرى"
federating: "الفديرالية جارية"
blocked: "محجوب"
suspended: "مُعلّق"
all: "الكل"
notResponding: "لا يستجيب"
changePassword: "تغيير الكلمة السرية"
security: "الأمان"
more: "المزيد!"
featured: "المتداولة"
usernameOrUserId: "اسم المستخدم أو معرّفه"
noSuchUser: "لم يُعثَر على المستخدم"
lookup: "البحث"
announcements: "الإعلانات"
imageUrl: "عنوان URL للصورة"
remove: "حذف"
removed: "تم حذفه بنجاح"
removeAreYouSure: "متأكد من أنك تريد حذف {x}؟"
saved: "تم حفظه"
messaging: "الدردشة"
upload: "تحميل"
fromDrive: "من المخزن"
fromUrl: "من عنوان URL"
uploadFromUrl: "التحميل عبر URL"
explore: "استكشاف"
games: "ألعاب Misskey"
messageRead: "مقروءة"
startMessaging: "ابدأ الدردشة"
tos: "شروط الخدمة"
start: "البداية"
home: "الرئيسي"
activity: "النشاط"
images: "الصور"
birthday: "تاريخ الميلاد"
yearsOld: "{age} سنة"
registeredDate: "انظم في"
location: "المكان"
theme: "المظهر"
themeForLightMode: "الحلة في الوضع الفاتح"
themeForDarkMode: "الحلة في الوضع الداكن"
light: "فاتح"
dark: "داكن"
lightThemes: "الحلة الفاتحة"
darkThemes: "الحلة الداكنة"
drive: "قرص التخرين"
fileName: "اسم الملف"
selectFile: "اختر ملفًا"
selectFiles: "اختر ملفات"
selectFolder: "اختر مجلدًا"
selectFolders: "اختر مجلدات"
renameFile: "إعادة تسمية الملف"
folderName: "اسم المجلد"
createFolder: "أنشئ مجلدًا"
renameFolder: "إعادة تسمية المجلد"
deleteFolder: "احذف هذا المجلد"
addFile: "إضافة ملف"
emptyDrive: "قرص التخزين فارغ"
emptyFolder: "هذا المجلد فارغ"
unableToDelete: "لا يمكن حذفه"
inputNewFileName: "ادخل الإسم الجديد للملف"
inputNewFolderName: "ادخل الإسم الجديد للمجلد"
copyUrl: "انسخ عنوان URL"
rename: "إعادة التسمية"
avatar: "الصورة الرمزية"
banner: "الصورة الرأسية"
nsfw: "محتوى حساس"
reload: "انعش"
doNothing: "تجاهل"
watch: "راقب"
unwatch: "إلغاء المراقبة"
accept: "السماح"
reject: "رفض"
normal: "عادي"
instanceName: "اسم مثيل الخادم"
instanceDescription: "وصف مثيل الخادم"
maintainerName: "المدير"
maintainerEmail: "عنوان بريد المدير الإلكتروني"
tosUrl: "عنوان URL لشروط الخدمة"
thisYear: "هذا العام"
thisMonth: "هذا الشهر"
today: "اليوم"
dayX: "{day}"
monthX: "{month}"
yearX: "{year}"
pages: "الصفحات"
connectSerice: "أوصل"
disconnectSerice: "قطع الاتصال"
enableLocalTimeline: "تفعيل الخيط المحلي"
enableGlobalTimeline: "تفعيل الخيط الزمني الشامل"
registration: "إنشاء حساب"
enableRegistration: "تفعيل إنشاء الحسابات الجديدة"
invite: "دعوة"
basicInfo: "المعلومات الأساسية "
hcaptchaSiteKey: "مفتاح الموقع"
hcaptchaSecretKey: "المفتاح السري"
recaptcha: "reCAPTCHA"
enableRecaptcha: "تمكين reCAPTCHA"
recaptchaSiteKey: "مفتاح الموقع"
recaptchaSecretKey: "المفتاح السري"
antennas: "الهوائيات"
manageAntennas: "إدارة الهوائيات"
name: "الإسم"
antennaSource: "مصدر الهوائي"
antennaKeywords: "الكلمات المفتاحية للإستقبال"
notesAndReplies: "الملاحظات والردود"
withFiles: "بالمرفقات"
silence: "اكتم"
unsilence: "إلغاء الكتم"
popularUsers: "المستخدمون الشائعون"
exploreFediverse: "استكشف الفديفرس"
popularTags: "الوسوم الرائجة"
userList: "القوائم"
about: "عن"
aboutMisskey: "عن Misskey"
patrons: "الداعمون"
administrator: "المدير"
token: "الرمز المميز"
twoStepAuthentication: "الإستيثاق بعاملَيْن"
moderator: "مشرِف"
nUsersMentioned: "{n} مستخدمين تمت الإشارة إليهم"
securityKey: "مفتاح الأمان"
securityKeyName: "اسم المفتاح"
lastUsed: "آخر استخدام"
unregister: "إلغاء التسجيل"
passwordLessLogin: "لِج مِن دون كلمة سرية"
resetPassword: "أعد تعيين كلمتك السرية"
newPasswordIs: "كلمتك السرية الجديدة هي {password}"
share: "شارِك"
notFound: "غير موجود"
help: "المساعدة"
inputMessageHere: "اكتب رسالتك هنا"
close: "اغلق"
group: "الفريق"
groups: "الفِرَق"
createGroup: "انشئ فريقًا"
invites: "دعوة"
groupName: "اسم الفريق"
members: "الأعضاء"
transfer: "نقل"
messagingWithUser: "الدردشة مع مستخدم آخر"
messagingWithGroup: "دردشة جماعية"
title: "العنوان"
text: "النص"
enable: "تشغيل"
next: "التالية"
retype: "أعد الكتابة"
noteOf: "ملاحظات {user}"
inviteToGroup: "دعوة إلى فريق"
invitationCode: "رمز الدعوة"
checking: "التحقق جارٍ"
available: "متوفر"
unavailable: "غير متوفر"
tooShort: "قصير جدًا"
tooLong: "طويل جدًا"
weakPassword: "الكلمة السرية ضعيفة"
normalPassword: "الكلمة السرية جيدة"
strongPassword: "الكلمة السرية قوية"
passwordMatched: "التطابق صحيح!"
passwordNotMatched: "غير متطابقتان"
signinWith: "الولوج عبر {x}"
or: "أو"
uiLanguage: "لغة واجهة المستخدم"
aboutX: "عن {x}"
useOsNativeEmojis: "استخدم الإيموجيات الخاصة بنظام التشغيل"
youHaveNoGroups: "لا تمتلك أية فِرَق"
doing: "انتظر لحظة"
category: "الفئات"
tags: "الوسوم"
docSource: "مصدر هذا المستند"
createAccount: "أنشئ حسابًا"
existingAcount: "الحسابات الموجودة"
regenerate: "أعِد التوليد"
fontSize: "حجم الخط"
dashboard: "لوحة التحكم"
local: "المحلي"
remote: "بُعدي"
total: "المجموع"
weekOverWeekChanges: "أسبوعيا"
dayOverDayChanges: "يوميا"
clinetSettings: "إعدادات التطبيق"
accountSettings: "إعدادات الحساب"
promotion: "ترقية"
promote: "روِّج"
numberOfDays: "عدد الأيام"
hideThisNote: "إخفاء هذه الملاحظة"
deleteAll: "حذف الكل"
sounds: "الرنات"
listen: "استمع"
none: "لا شيء"
volume: "مستوى الصوت"
details: "التفاصيل"
chooseEmoji: "اختر إيموجي"
recentUsed: "المستخدمة مؤخرا"
install: "التثبيت"
uninstall: "إلغاء التثبيت"
installedApps: "التطبيقات المُخوّلة"
lastUsedDate: "آخر استخدام"
state: "الحالة"
sort: "ترتيب حسب"
output: "الخارجة"
updateRemoteUser: "تحديث المعلومات عن المستخدم البعيد"
sidebar: "الشريط الجانبي"
addItem: "إضافة عنصر"
rooms: "الغرفة"
relays: "المُرَحلات"
addRelay: "إضافة مُرحّل"
addedRelays: "المرحلات التي تم إضافتها"
_theme:
explore: "استكشف قوالب المظهر"
_sfx:
note: "الملاحظات"
notification: "الإشعارات"
chat: "الدردشة"
_ago:
unknown: "مجهول"
future: "المستقبَل"
justNow: "اللحظة"
secondsAgo: "منذ {n} ثوانٍ"
minutesAgo: "منذ {n} دقائق"
hoursAgo: "منذ {n} ساعة"
daysAgo: "منذ {n} أيام"
weeksAgo: "منذ {n} أسابيع"
monthsAgo: "منذ {n} أشهر"
yearsAgo: "منذ {n} سنوات"
_time:
second: "ثا"
minute: "د"
hour: "سا"
day: "ي"
_tutorial:
title: "كيف تستخدم Misskey"
step1_1: "مرحبًا!"
_2fa:
registerKey: "تسجيل مفتاح أمان جديد"
_permissions:
"write:account": "تعديل معلومات حسابك"
"read:notifications": "اظهر الإشعارات"
_weekday:
sunday: "الأحد"
monday: "الإثنين"
tuesday: "الثلاثاء"
wednesday: "الأربعاء"
thursday: "الخميس"
friday: "الجمعة"
saturday: "السبت"
_widgets:
memo: "ملاحظة لاصقة"
notifications: "الإشعارات"
timeline: "الخيط الزمني"
calendar: "التقويم"
trends: "المتداوَلة"
clock: "الساعة"
rss: "تدفق RSS"
activity: "النشاط"
photos: "الصور"
_cw:
hide: "إخفاء"
show: "عرض المزيد"
chars: "{count} أحرف"
files: "{count} ملفات"
_poll:
at: "تاريخ الإنتهاء"
deadlineDate: "تاريخ الانتهاء"
deadlineTime: "سا"
duration: "المدة"
vote: "قم بالتصويت"
showResult: "اعرض النتائج"
closed: "انتهى"
remainingDays: "{d} أيام و {h} ساعات متبقية"
remainingHours: "{h} ساعات و {m} دقائق متبقية"
remainingMinutes: "{m} دقائق و {s} ثوانٍ متبقية"
remainingSeconds: "{s} ثوانٍ متبقية"
_visibility:
public: "للعامة"
home: "الرئيسي"
followers: "المتابِعين"
specified: "مباشرة"
localOnly: "المحلي فقط"
_postForm:
replyPlaceholder: "رد على هذه الملاحظة…"
quotePlaceholder: "اقتبس هذه الملاحظة…"
_profile:
name: "الإسم"
username: "اسم المستخدم"
youCanIncludeHashtags: "يمكنك أيضًا إضافة وسوم إلى نبذتك التعريفية."
_exportOrImport:
followingList: "المتابَعون"
muteList: "اكتم"
blockingList: "احجب"
userLists: "القوائم"
_charts:
usersTotal: "مجموع عدد المستخدمين والمستخدمات"
activeUsers: "المستخدمون النشطون"
_timelines:
home: "الرئيسي"
local: "المحلي"
social: "الاجتماعي"
global: "الشامل"
_rooms:
_roomType:
default: "افتراضي"
_furnitures:
monitor: "شاشة التحكم"
_pages:
blocks:
image: "الصور"
script:
categories:
list: "القوائم"
blocks:
_strReplace:
arg1: "نص"
arg3: "استُبدِل بـ"
_join:
arg1: "القوائم"
arg2: "فاصل"
add: "إضافة"
_randomPick:
arg1: "القوائم"
_dailyRandomPick:
arg1: "القوائم"
_seedRandomPick:
arg2: "القوائم"
_pick:
arg1: "القوائم"
_listLen:
arg1: "القوائم"
types:
array: "القوائم"
_notification:
youWereFollowed: "يتابعك"
_deck:
_columns:
notifications: "الإشعارات"
tl: "الخيط الزمني"
antenna: "الهوائيات"
list: "القوائم"
mentions: "الإشارات"
direct: "مباشرة"

View File

@ -43,8 +43,9 @@ copyUsername: "Benutzernamen kopieren"
reply: "Antworten"
loadMore: "Mehr anzeigen"
youGotNewFollower: "Du hast einen neuen Follower"
receiveFollowRequest: "Follow-Anfrage erhalten."
receiveFollowRequest: "Follow-Anfrage erhalten"
followRequestAccepted: "Follow-Anfrage akzeptiert"
mention: "Erwähnung"
mentions: "Erwähnungen"
directNotes: "Direktnachrichten"
importAndExport: "Importieren und Exportieren"
@ -104,6 +105,7 @@ suspendConfirm: "Möchtest du diesen Benutzer wirklich sperren?"
unsuspendConfirm: "Möchtest du die Sperrung dieses Benutzers wirklich aufheben?"
selectList: "Wähle eine Liste aus"
customEmojis: "Benutzerdefinierte Emojis"
emoji: "Emoji"
emojiName: "Emojiname"
emojiUrl: "Emoji-URL"
addEmoji: "Emoji hinzufügen"
@ -203,7 +205,7 @@ remove: "Löschen"
removed: "Erfolgreich gelöscht"
removeAreYouSure: "Möchtest du \"{x}\" wirklich löschen?"
saved: "Gespeichert"
messaging: "Privatnachrichten"
messaging: "Chat"
upload: "Hochladen"
fromDrive: "Aus Drive"
fromUrl: "Von einer URL"
@ -215,7 +217,7 @@ explore: "Erkunden"
games: "Misskey Spiele"
messageRead: "Gelesen"
noMoreHistory: "Kein weiterer Verlauf vorhanden"
startMessaging: "Neue Privatnachricht erstellen"
startMessaging: "Neuen Chat erstellen"
nUsersRead: "Von {n} gelesen"
agreeTo: "Ich stimme {0} zu"
tos: "Nutzungsbedingungen"
@ -384,8 +386,8 @@ invites: "Einladungen"
groupName: "Gruppenname"
members: "Mitglieder"
transfer: "Übertragen"
messagingWithUser: "Privatnachrichten mit einem Benutzer"
messagingWithGroup: "Privatnachrichten mit einer Gruppe"
messagingWithUser: "Privatchat"
messagingWithGroup: "Gruppenchat"
title: "Betreff"
text: "Text"
enable: "Aktivieren"
@ -506,19 +508,99 @@ relays: "Relays"
addRelay: "Relay hinzufügen"
inboxUrl: "inbox-URL"
addedRelays: "Hinzugefügte Relays"
serviceworkerInfo: "Muss für Push-Benachrichtigungen aktiviert sein."
deletedNote: "Gelöschte Notiz"
invisibleNote: "Private Notiz"
enableInfiniteScroll: "Automatisch mehr Notizen laden"
visibility: "Sichtbarkeit"
poll: "Umfrage"
useCw: "Inhalt verstecken"
fixedWidgetsPosition: "Widgetposition fixieren"
enablePlayer: "Video-Player öffnen"
disablePlayer: "Video-Player schließen"
expandTweet: "Tweet ausklappen"
themeEditor: "Farbthemen-Editor"
description: "Beschreibung"
author: "Autor"
leaveConfirm: "Es gibt unspeicherte Änderungen. Möchtest du diese verwerfen?"
deck: "Deck"
undeck: "Deck verlassen"
_theme:
explore: "Themen erforschen"
install: "Thema installieren"
manage: "Themaverwaltung"
code: "Themencode"
code: "Themen-Code"
installed: "{name} wurde installiert"
alreadyInstalled: "Dieses Thema ist bereits installiert"
invalid: "Themenformat ist ungültig"
make: "Farbthema erstellen"
base: "Basis"
addConstant: "Konstante hinzufügen"
constant: "Konstante"
defaultValue: "Standardwert"
color: "Farbe"
refProp: "Eigenschaft referenzieren"
refConst: "Konstante referenzieren"
key: "Schlüssel"
func: "Funktionen"
funcKind: "Funktionstyp"
argument: "Parameter"
basedProp: "Name der referenzierten Eigenschaft"
alpha: "Transparenz"
darken: "Verdunkeln"
lighten: "Erhellen"
inputConstantName: "Name der Konstanten eingeben"
importInfo: "Du kannst hier Themen-Code einfügen, um ihn in den Editor zu importieren"
deleteConstantConfirm: "Die Konstante {const} wirklich löschen?"
keys:
accent: "Akzentfarbe"
bg: "Hintergrund"
fg: "Text"
focus: "Fokus"
indicator: "Indikator"
panel: "Panel"
shadow: "Schatten"
header: "Kopfzeile"
navBg: "Hintergrund der Seitenleiste"
navFg: "Text der Seitenleiste"
navHoverFg: "Text der Seitenleiste (Mouseover)"
navActive: "Text der Seitenleiste (Aktiv)"
navIndicator: "Indikator der Seitenleiste"
link: "Link"
hashtag: "Hashtag"
mention: "Erwähnungen"
mentionMe: "Erwähnungen (Ich)"
renote: "Renote"
modalBg: "Hintergrund des Modals"
divider: "Trenner"
scrollbarHandle: "Griff des Scrollbalkens"
scrollbarHandleHover: "Griff des Scrollbalkens (Mouseover)"
dateLabelFg: "Text von Datumsbeschriftungen"
infoBg: "Hintergrund von Informationen"
infoFg: "Text von Informationen"
infoWarnBg: "Hintergrund von Warnungen"
infoWarnFg: "Text von Informationen"
cwBg: "Hintergrund von versteckten Inhalten"
cwFg: "Text von versteckten Inhalten"
cwHoverBg: "Hintergrund von versteckten Inhalten (Mouseover)"
toastBg: "Hintergrund von Benachrichtigungen"
toastFg: "Text von Benachrichtigungen"
buttonBg: "Hintergrund von Schaltflächen"
buttonHoverBg: "Hintergrund von Schaltflächen (Mouseover)"
inputBorder: "Rahmen des Eingabefelds"
listItemHoverBg: "Hintergrund von Listeneinträgen (Mouseover)"
driveFolderBg: "Hintergrund von Drive-Ordnern"
wallpaperOverlay: "Hintergrundbild-Overlay"
badge: "Wappen"
messageBg: "Hintergrund von Chats"
accentDarken: "Akzent (Verdunkelt)"
accentLighten: "Akzent (Erhellt)"
fgHighlighted: "Hervorgehobener Text"
_sfx:
note: "Notizen"
noteMy: "Meine Notizen"
notification: "Benachrichtigungen"
chat: "Privatnachrichten"
chat: "Chat"
chatBg: "Nachrichten (Hintergrund)"
antenna: "Antennen"
_ago:
@ -580,8 +662,8 @@ _permissions:
"write:favorites": "Deine Favoriten-Liste bearbeiten"
"read:following": "Deine Follower-Liste lesen"
"write:following": "Anderen Benutzern folgen oder entfolgen"
"read:messaging": "Privatnachrichten lesen"
"write:messaging": "Privatnachrichten schicken oder löschen"
"read:messaging": "Chats lesen"
"write:messaging": "Chatnachrichten schicken oder löschen"
"read:mutes": "Stummschaltungen lesen"
"write:mutes": "Stummschaltungen bearbeiten"
"write:notes": "Notizen schreiben oder löschen"
@ -627,12 +709,12 @@ _widgets:
rss: "RSS-Reader"
activity: "Aktivität"
photos: "Fotos"
digitalClock: "Digitaluhr"
_cw:
hide: "Ausblenden"
show: "Mehr anzeigen"
chars: "{count} Zeichen"
files: "{count} Dateien"
poll: "Umfrage"
_poll:
noOnlyOneChoice: "Mindestens zwei Antwortmöglichkeiten werden benötigt."
choiceN: "Auswahl {n}"
@ -665,6 +747,7 @@ _visibility:
specified: "Direkt"
specifiedDescription: "Nur für bestimmte Benutzer sichtbar"
localOnly: "Nur Lokal"
localOnlyDescription: "Unsichtbar für Benutzer anderer Instanzen"
_postForm:
replyPlaceholder: "Dieser Notiz antworten..."
quotePlaceholder: "Diese Notiz zitieren..."
@ -761,11 +844,11 @@ _rooms:
moon: "Mond"
corkboard: "Pinnwand"
mousepad: "Mauspad"
monitor: "Beobachten"
monitor: "Monitor"
keyboard: "Tastatur"
carpet-stripe: "Gestreifter Teppich"
mat: "Matte"
color-box: "Farbige Box"
color-box: "Regal"
wall-clock: "Wanduhr"
photoframe: "Bilderrahmen"
cube: "Würfel"
@ -780,6 +863,8 @@ _rooms:
cup-noodle: "Instantnudeln"
holo-display: "Holographischer Bildschirm"
energy-drink: "Energy Drink"
doll-ai: "Ai-Puppe"
banknote: "Geldscheine"
_pages:
newPage: "Seite erstellen"
editPage: "Diese Seite bearbeiten"
@ -1065,3 +1150,27 @@ _relayStatus:
requesting: "Ausstehend"
accepted: "Akzeptiert"
rejected: "Abgelehnt"
_notification:
fileUploaded: "Datei erfolgreich hochgeladen"
youGotMention: "{name} hat dich erwähnt"
youGotReply: "{name} hat dir geantwortet"
youGotQuote: "{name} hat dich zitiert"
youRenoted: "Renote deiner Notiz von {name}"
youGotPoll: "{name} hat auf deiner Umfrage abgestimmt"
youGotMessagingMessageFromUser: "{name} hat dir eine Chatnachricht gesendet"
youGotMessagingMessageFromGroup: "In die Gruppe {name} wurde eine Chatnachricht gesendet"
youWereFollowed: "Du hast einen neuen Follower"
youReceivedFollowRequest: "Du hast eine Follow-Anfrage erhalten"
yourFollowRequestAccepted: "Deine Follow-Anfrage wurde akzeptiert"
youWereInvitedToGroup: "Du wurdest in eine Gruppe eingeladen"
_deck:
alwaysShowMainColumn: "Hauptspalte immer zeigen"
columnAlign: "Spalten ausrichten"
_columns:
widgets: "Widgets"
notifications: "Benachrichtigungen"
tl: "Chronik"
antenna: "Antennen"
list: "Listen"
mentions: "Erwähnungen"
direct: "Direkt"

View File

@ -45,6 +45,7 @@ loadMore: "Load more"
youGotNewFollower: "Followed you"
receiveFollowRequest: "Follow request received"
followRequestAccepted: "Follow request accepted"
mention: "Mention"
mentions: "Mentions"
directNotes: "Direct notes"
importAndExport: "Import / Export"
@ -104,6 +105,7 @@ suspendConfirm: "Are you sure that you want to suspend this account?"
unsuspendConfirm: "Are you sure you that want to unsuspend this account?"
selectList: "Select a list"
customEmojis: "Custom Emoji"
emoji: "Emoji"
emojiName: "Emoji name"
emojiUrl: "Emoji URL"
addEmoji: "Add an emoji"
@ -502,6 +504,27 @@ sidebar: "Sidebar"
divider: "Divider"
addItem: "Add Item"
rooms: "Room"
relays: "Relays"
addRelay: "Add Relay"
inboxUrl: "Inbox URL"
addedRelays: "Added Relays"
serviceworkerInfo: "Must be enabled for push notifications."
deletedNote: "Deleted note"
invisibleNote: "Invisible note"
enableInfiniteScroll: "Enable infinite scrolling"
visibility: "Visiblility"
poll: "Poll"
useCw: "Hide content"
fixedWidgetsPosition: "Make widget position fixed"
enablePlayer: "Open video player"
disablePlayer: "Close video player"
expandTweet: "Expand tweet"
themeEditor: "Theme editor"
description: "Description"
author: "Author"
leaveConfirm: "There are unsaved changes. Do you want to discard them?"
deck: "Deck"
undeck: "Leave Deck"
_theme:
explore: "Explore Themes"
install: "Install theme"
@ -510,6 +533,69 @@ _theme:
installed: "{name} has been installed"
alreadyInstalled: "The theme is already installed"
invalid: "Theme format is invalid"
make: "Make a theme"
base: "Base"
addConstant: "Add constant"
constant: "Constant"
defaultValue: "Default value"
color: "Color"
refProp: "Reference a property"
refConst: "Reference a constant"
key: "Key"
func: "Functions"
funcKind: "Function type"
argument: "Argument"
basedProp: "Name of the referenced property"
alpha: "Opacity"
darken: "Darken"
lighten: "Lighten"
inputConstantName: "Enter a name for the constant"
importInfo: "If you enter theme code here, you can import it to the theme editor"
deleteConstantConfirm: "Do you really want to delete the constant {const}?"
keys:
accent: "Accent"
bg: "Background"
fg: "Text"
focus: "Focus"
indicator: "Indicator"
panel: "Panel"
shadow: "Shadow"
header: "Header"
navBg: "Sidebar background"
navFg: "Sidebar text"
navHoverFg: "Sidebar text (Hover)"
navActive: "Sidebar text (Active)"
navIndicator: "Sidebar indicator"
link: "Link"
hashtag: "Hashtag"
mention: "Mention"
mentionMe: "Mentions (Me)"
renote: "Renote"
modalBg: "Modal background"
divider: "Divider"
scrollbarHandle: "Scrollbar handle"
scrollbarHandleHover: "Scrollbar handle (Hover)"
dateLabelFg: "Text of date labels"
infoBg: "Information background"
infoFg: "Information text"
infoWarnBg: "Warning background"
infoWarnFg: "Warning text"
cwBg: "CW background"
cwFg: "CW text"
cwHoverBg: "CW background (Hover)"
toastBg: "Notification background"
toastFg: "Notification text"
buttonBg: "Button background"
buttonHoverBg: "Button background (Hover)"
inputBorder: "Input field border"
listItemHoverBg: "List item background (Hover)"
driveFolderBg: "Drive folder background"
wallpaperOverlay: "Wallpaper overlay"
badge: "Badge"
messageBg: "Chat background"
accentDarken: "Accent (Darkened)"
accentLighten: "Accent (Lightened)"
fgHighlighted: "Highlighted Text"
_sfx:
note: "New note"
noteMy: "My note"
@ -623,12 +709,12 @@ _widgets:
rss: "RSS reader"
activity: "Activity"
photos: "Photos"
digitalClock: "Digital clock"
_cw:
hide: "Hide"
show: "Load more"
chars: "{count} characters"
files: "{count} file(s)"
poll: "Poll"
_poll:
noOnlyOneChoice: "At least two choices are needed"
choiceN: "Choice {n}"
@ -661,6 +747,7 @@ _visibility:
specified: "Direct"
specifiedDescription: "Post to specified users only"
localOnly: "Local only"
localOnlyDescription: "Not visible to remote users"
_postForm:
replyPlaceholder: "Reply to this note..."
quotePlaceholder: "Quote this note..."
@ -776,6 +863,8 @@ _rooms:
cup-noodle: "Cup noodle"
holo-display: "Holographic display"
energy-drink: "Energy drink"
doll-ai: "Ai doll"
banknote: "Pile of money"
_pages:
newPage: "Create a page"
editPage: "Edit this page"
@ -1057,3 +1146,31 @@ _pages:
enviromentVariables: "Environment variable"
pageVariables: "Page element"
argVariables: "Input slot"
_relayStatus:
requesting: "Pending"
accepted: "Accepted"
rejected: "Rejected"
_notification:
fileUploaded: "File successfully uploaded"
youGotMention: "{name} mentioned you"
youGotReply: "{name} replied to you"
youGotQuote: "{name} quoted you"
youRenoted: "{name} renoted you"
youGotPoll: "{name} voted on your poll"
youGotMessagingMessageFromUser: "{name} sent you a message"
youGotMessagingMessageFromGroup: "A message was sent to the {name} group"
youWereFollowed: "Followed you"
youReceivedFollowRequest: "You've received a follow request"
yourFollowRequestAccepted: "Your follow request was accepted"
youWereInvitedToGroup: "Invited to group"
_deck:
alwaysShowMainColumn: "Always show main column"
columnAlign: "Align columns"
_columns:
widgets: "Widgets"
notifications: "Notifications"
tl: "Timeline"
antenna: "Antennas"
list: "Lists"
mentions: "Mentions"
direct: "Direct"

View File

@ -26,7 +26,7 @@ signup: "Registrarse"
uploading: "Cargando"
save: "Guardar"
users: "Usuarios"
addUser: "Añadir usuario"
addUser: "Agregar usuario"
favorite: "Favorito"
favorites: "Favoritos"
unfavorite: "Quitar de favoritos"
@ -45,6 +45,7 @@ loadMore: "Ver más"
youGotNewFollower: "te ha seguido"
receiveFollowRequest: "Recibiste una solicitud de seguimiento"
followRequestAccepted: "La solicitud de seguimiento fue aceptada"
mention: "Menciones"
mentions: "Menciones"
directNotes: "Notas directas"
importAndExport: "Importar y Exportar"
@ -84,7 +85,7 @@ pinnedNote: "Nota fijada"
you: "Tú"
clickToShow: "Click para ver"
sensitive: "Marcado como sensible"
add: "Añadir"
add: "Agregar"
reaction: "Reacción"
reactionSettingDescription: "Asigne sus reacción favoritas que desean anclar en el selector de reacciones."
rememberNoteVisibility: "Recordar visibilidad"
@ -104,16 +105,17 @@ suspendConfirm: "¿Quiere suspender esta cuenta?"
unsuspendConfirm: "¿Quiere dejar de suspender esta cuenta?"
selectList: "Seleccione una lista"
customEmojis: "Emojis personalizados"
emoji: "Emoji"
emojiName: "Nombre del emoji"
emojiUrl: "URL de la imágen del emoji"
addEmoji: "Añadir emoji"
addEmoji: "Agregar emoji"
settingGuide: "Configuración sugerida"
cacheRemoteFiles: "Mantener en cache los archivos remotos"
cacheRemoteFilesDescription: "Si desactiva esta configuración, Los archivos remotos se cargarán desde el link directo sin usar la caché. Con eso se puede ahorrar almacenamiento del servidor, pero eso aumentará el tráfico al no crear miniaturas."
flagAsBot: "Esta cuenta es un bot"
flagAsCat: "Esta cuenta es un gato"
autoAcceptFollowed: "Aceptar automáticamente las solicitudes de seguimiento de los usuarios que sigues"
addAcount: "Añadir cuenta"
addAcount: "Agregar cuenta"
loginFailed: "Error al iniciar sesión."
showOnRemote: "Ver en una instancia remota"
general: "General"
@ -247,7 +249,7 @@ folderName: "Nombre de la carpeta"
createFolder: "Crear carpeta"
renameFolder: "Renombrar carpeta"
deleteFolder: "Borrar carpeta"
addFile: "Añadir archivo"
addFile: "Agregar archivo"
emptyDrive: "El drive está vacío"
emptyFolder: "La carpeta está vacía"
unableToDelete: "No se puede borrar"
@ -502,6 +504,25 @@ sidebar: "Barra lateral"
divider: "Divisor"
addItem: "Agregar elemento"
rooms: "Cuartos"
relays: "Relés"
addRelay: "Agregar relé"
inboxUrl: "Inbox URL"
addedRelays: "Relés añadidos"
serviceworkerInfo: "Se necesita activar para usar las notificaciones push"
deletedNote: "Nota eliminada"
invisibleNote: "Nota oculta"
enableInfiniteScroll: "Activar scroll infinito"
visibility: "Visibilidad"
poll: "Encuesta"
useCw: "Esconder contenidos"
fixedWidgetsPosition: "Fijar la posición de los widgets"
enablePlayer: "Abrir reproductor"
disablePlayer: "Cerrar reproductor"
expandTweet: "Expandir tweet"
themeEditor: "Editor de temas"
description: "Descripción"
author: "Autor"
leaveConfirm: "Hay modificaciones sin guardar. ¿Desea descartarlas?"
_theme:
explore: "Explorar temas"
install: "Instalar tema"
@ -510,6 +531,48 @@ _theme:
installed: "{name} ha sido instalado"
alreadyInstalled: "Este tema ya está instalado"
invalid: "El formato del tema no es válido"
make: "Crear tema"
base: "Base"
addConstant: "Agregar constante"
constant: "Constante"
defaultValue: "Valor predeterminado"
color: "Color"
refProp: "Hacer referencia a propiedad"
refConst: "Hacer referencia a constante"
key: "Clave"
func: "funciones"
funcKind: "Tipo de función"
argument: "Argumento"
basedProp: "Nombre de la propiedad referenciada"
alpha: "Opacidad"
darken: "Oscuridad"
lighten: "Brillo"
inputConstantName: "Por favor ingrese el nombre de la constante"
importInfo: "Pegando el código del tema aquí, puede importarlo al editor"
deleteConstantConfirm: "¿Desea borrar la constante {const}?"
keys:
accent: "Acento"
bg: "Fondo"
fg: "Texto"
focus: "Enfoque"
indicator: "Indicador"
panel: "Panel"
shadow: "Sombra"
header: "Cabezal"
navBg: "Fondo de la barra lateral"
navFg: "Texto de la barra lateral"
navHoverFg: "Texto de la barra lateral (hover)"
navActive: "Texto de la barra lateral (activo)"
navIndicator: "Indicador de la barra lateral"
link: "Vínculo"
hashtag: "Hashtag"
mention: "Menciones"
mentionMe: "Menciones (yo)"
renote: "Renotar"
modalBg: "Fondo modal"
divider: "Divisor"
scrollbarHandle: "Cuadro de la barra de desplazamiento"
scrollbarHandleHover: "Cuadro de la barra de desplazamiento (hover)"
_sfx:
note: "Notas"
noteMy: "Nota (a mí mismo)"
@ -628,7 +691,6 @@ _cw:
show: "Ver más"
chars: "{count} caracteres"
files: "{count} archivos"
poll: "Encuesta"
_poll:
noOnlyOneChoice: "Se necesitan al menos 2 opciones"
choiceN: "Opción {n}"
@ -661,6 +723,7 @@ _visibility:
specified: "Mensaje directo"
specifiedDescription: "Visible sólo para los usuarios elegidos"
localOnly: "Solo local"
localOnlyDescription: "Oculto para usuarios remotos"
_postForm:
replyPlaceholder: "Responder a esta nota"
quotePlaceholder: "Citar esta nota"
@ -776,6 +839,8 @@ _rooms:
cup-noodle: "Taza de sopa de fideos"
holo-display: "Poster holográfico"
energy-drink: "Bebida energética"
doll-ai: "Muñeca"
banknote: "Billetes"
_pages:
newPage: "Crear página"
editPage: "Editar página"
@ -1057,3 +1122,28 @@ _pages:
enviromentVariables: "Variables de entorno"
pageVariables: "Items de la página"
argVariables: "Slot de entrada"
_relayStatus:
requesting: "Pendiente"
accepted: "Aceptar"
rejected: "Rechazada"
_notification:
fileUploaded: "Archivo subido"
youGotMention: "Mención de {name}"
youGotReply: "Respuesta de {name}"
youGotQuote: "Citado por {name}"
youRenoted: "Renotado por {name}"
youGotPoll: "Encuestado por {name}"
youGotMessagingMessageFromUser: "{name} comenzó un chat contigo"
youGotMessagingMessageFromGroup: "Tienes un chat de {name}"
youWereFollowed: "te ha seguido"
youReceivedFollowRequest: "Has mandado una solicitud de seguimiento"
yourFollowRequestAccepted: "Tu solicitud de seguimiento fue aceptada"
youWereInvitedToGroup: "Invitado al grupo"
_deck:
_columns:
notifications: "Notificaciones"
tl: "Linea de tiempo"
antenna: "Antenas"
list: "Listas"
mentions: "Menciones"
direct: "Mensaje directo"

View File

@ -1,28 +1,28 @@
---
_lang_: "Français"
introMisskey: "Bienvenue ! Misskey est un service de microblogage décentralisé et open-source.\nÉcrivez des « notes » pour partager ce qui se passe, ou pour parler de vous à tout le monde 📡\nAvec la fonction « réactions », vous pouvez également ajouter une réaction rapide aux notes de chacun 👍\nExplorez un nouveau monde 🚀"
introMisskey: "Bienvenue ! Misskey est un service de microblogage décentralisé, libre et ouvert.\nÉcrivez des « notes » et partagez ce qui se passe à linstant présent, autour de vous avec les autres 📡\nLa fonction « réactions », vous permet également dajouter une réaction rapide aux notes des autres utilisateur·rice·s 👍\nExplorons un nouveau monde 🚀"
monthAndDay: "{day}/{month}"
search: "Rechercher"
notifications: "Notifications"
username: "Nom d'utilisateur·rice"
username: "Nom dutilisateur·rice"
password: "Mot de passe"
fetchingAsApObject: "Récupération depuis le Fediverse"
ok: "Soumettre"
gotIt: "J'ai compris !"
fetchingAsApObject: "Récupération depuis le diverse"
ok: "OK"
gotIt: "Jai compris !"
cancel: "Annuler"
enterUsername: "Entrer un nom d'utilisateur·rice"
enterUsername: "Entrer un nom dutilisateur·rice"
renotedBy: "Renoté par {user}"
noNotes: "Pas de notes"
noNotifications: "Pas de notifications"
noNotes: "Aucune note"
noNotifications: "Aucune notification"
instance: "Instance"
settings: "Paramètres"
profile: "Profil"
timeline: "Fil d'actualité"
noAccountDescription: "L'utilisateur·rice n'a pas encore renseigné de présentation sur son profil"
timeline: "Fil"
noAccountDescription: "Lutilisateur·rice na pas encore renseigné de biographie de présentation sur son profil."
login: "Se connecter"
loggingIn: "Connexion en cours"
logout: "Se déconnecter"
signup: "S'inscrire"
signup: "Sinscrire"
uploading: "Envoi en cours"
save: "Enregistrer"
users: "Utilisateur·rice·s"
@ -36,29 +36,30 @@ copyContent: "Copier le contenu"
copyLink: "Copier le lien"
delete: "Supprimer"
deleteAndEdit: "Supprimer et réécrire"
deleteAndEditConfirm: "Êtes-vous sûr·e de vouloir effacer cette note et la modifier ? Vous perdrez toutes les réactions, renotes et réponses."
deleteAndEditConfirm: "Êtes-vous sûr·e de vouloir supprimer cette note et la reformuler ? Vous perdrez toutes les réactions, renotes et réponses y afférentes."
addToList: "Ajouter à une liste"
sendMessage: "Envoyer un message"
copyUsername: "Copier le nom d'utilisateur"
copyUsername: "Copier le nom dutilisateur·rice"
reply: "Répondre"
loadMore: "Voir plus"
loadMore: "Afficher plus"
youGotNewFollower: "Vous suit"
receiveFollowRequest: "Demande de suivi reçue"
followRequestAccepted: "La demande d'abonnement a été acceptée"
receiveFollowRequest: "Demande dabonnement reçue"
followRequestAccepted: "La demande dabonnement a été acceptée"
mention: "Mentionner"
mentions: "Mentions"
directNotes: "Messages directs"
directNotes: "Notes directes"
importAndExport: "Import et export"
import: "Importer"
export: "Exporter"
files: "Fichiers"
download: "Télécharger"
driveFileDeleteConfirm: "Êtes-vous sûr·e de vouloir supprimer le fichier \"{name}\" ? Les notes avec ce fichier joint seront aussi supprimées."
unfollowConfirm: "Se désabonner de {name} ?"
exportRequested: "Vous avez demandé une exportation. Cela pourrait prendre un peu de temps. Une fois l'exportation terminée, le fichier résultant sera ajouté dans le Drive."
unfollowConfirm: "Désirez-vous vous désabonner de {name} ?"
exportRequested: "Vous avez demandé une exportation. Lopération pourrait prendre un peu de temps. Une terminée, le fichier résultant sera ajouté au Drive."
importRequested: "Vous avez initié un import. Cela pourrait prendre un peu de temps."
lists: "Listes"
noLists: "Aucune liste"
note: "Note"
noLists: "Vous navez aucune liste"
note: "Notes"
notes: "Notes"
following: "Abonnements"
followers: "Abonné·e·s"
@ -69,10 +70,10 @@ error: "Une erreur est survenue"
retry: "Réessayer"
enterListName: "Nom de la liste"
privacy: "Confidentialité"
makeFollowManuallyApprove: "Approuver manuellement les demandes de suivi"
makeFollowManuallyApprove: "Accepter manuellement les demandes dabonnement"
defaultNoteVisibility: "Visibilité par défaut"
follow: "S'abonner"
followRequest: "Demande de suivi"
follow: "Sabonner"
followRequest: "Demande dabonnement"
followRequests: "Demandes dabonnement"
unfollow: "Se désabonner"
followRequestPending: "En attente dapprobation"
@ -86,7 +87,7 @@ clickToShow: "Cliquer pour afficher"
sensitive: "Contenu sensible"
add: "Ajouter"
reaction: "Réactions"
reactionSettingDescription: "Choisissez vos réactions préférées que vous souhaitez épingler dans le sélecteur de réaction."
reactionSettingDescription: "Choisissez vos réactions préférées que vous souhaitez épingler dans le sélecteur de réactions."
rememberNoteVisibility: "Se souvenir de la visibilité des notes"
attachCancel: "Supprimer le fichier attaché"
markAsSensitive: "Marquer comme sensible"
@ -104,24 +105,25 @@ suspendConfirm: "Êtes-vous sûr·e de vouloir suspendre ce compte ?"
unsuspendConfirm: "Êtes-vous sûr·e de vouloir annuler la suspension de ce compte ?"
selectList: "Sélectionner une liste"
customEmojis: "Émojis personnalisés"
emoji: "Émoji"
emojiName: "Nom de lémoji"
emojiUrl: "URL de lémoji"
addEmoji: "Ajouter un émoji"
settingGuide: "Configuration suggérée"
settingGuide: "Configuration proposée"
cacheRemoteFiles: "Mise en cache des fichiers distants"
cacheRemoteFilesDescription: "Quand ce paramètre est désactivé, les fichiers distants sont chargés directement depuis l'instance distante. Désactiver cela diminuera l'utilisation du stockage, mais augmentera le trafic réseau, puisque les miniatures ne seront pas générées."
cacheRemoteFilesDescription: "Lorsque cette option est désactivée, les fichiers distants sont chargés directement depuis linstance distante. La désactiver diminuera certes lutilisation de lespace de stockage local mais augmentera le trafic réseau puisque les miniatures ne seront plus générées."
flagAsBot: "Ce compte est un robot"
flagAsCat: "Ce compte est un chat"
autoAcceptFollowed: "Approuver automatiquement les demandes de suivi venant d'utilisateur·rice·s que vous suivez"
autoAcceptFollowed: "Accepter automatiquement les demandes dabonnement venant dutilisateur·rice·s que vous suivez"
addAcount: "Ajouter un compte"
loginFailed: "Échec de la connexion"
showOnRemote: "Voir sur l'instance distante"
showOnRemote: "Voir sur linstance distante"
general: "Général"
wallpaper: "Fond d'écran"
setWallpaper: "Définir le fond d'écran"
removeWallpaper: "Supprimer le fond d'écran"
wallpaper: "Fond décran"
setWallpaper: "Définir le fond décran"
removeWallpaper: "Supprimer le fond décran"
searchWith: "Recherche : {q}"
youHaveNoLists: "Vous n'avez aucune liste"
youHaveNoLists: "Vous navez aucune liste"
followConfirm: "Êtes-vous sûr·e de vouloir suivre {name} ?"
proxyAccount: "Compte proxy"
proxyAccountDescription: "Un compte proxy se comporte, dans certaines conditions, comme un·e abonné·e distant·e pour les utilisateurs d'autres instances. Par exemple, quand un·e utilisateur·rice ajoute un·e utilisateur·rice distant·e à une liste, ses notes ne seront pas visibles sur l'instance si personne ne suit cet·te utilisateur·rice. Le compte proxy va donc suivre cet·te utilisateur·rice pour que ses notes soient acheminées."
@ -139,7 +141,7 @@ storageUsage: "Stockage utilisé"
charts: "Graphiques"
perHour: "par heure"
perDay: "par jour"
stopActivityDelivery: "Arrêter l'envoi d'activités"
stopActivityDelivery: "Arrêter lenvoi de lactivité"
blockThisInstance: "Bloquer cette instance"
operations: "Opérations"
software: "Logiciel"
@ -151,10 +153,10 @@ jobQueue: "File dattente"
cpuAndMemory: "Processeur et mémoire"
network: "Réseau"
disk: "Disque"
instanceInfo: "Informations sur l'instance"
instanceInfo: "Informations sur linstance"
statistics: "Statistiques"
clearQueue: "Vider la file d'attente"
clearQueueConfirmTitle: "Êtes-vous sûr·e de vouloir vider la file d'attente ?"
clearQueue: "Vider la file dattente"
clearQueueConfirmTitle: "Êtes-vous sûr·e de vouloir vider la file dattente ?"
clearQueueConfirmText: "Les notes non distribuées ne seront pas livrées. Normalement, vous n'avez PAS besoin d'effectuer cette opération."
clearCachedFiles: "Vider le cache"
clearCachedFilesConfirm: "Êtes-vous sûr·e de vouloir vider le cache de fichiers distants ?"
@ -163,18 +165,18 @@ blockedInstancesDescription: "Listez les instances que vous désirez bloquer, un
muteAndBlock: "Masqué·e·s / Bloqué·e·s"
mutedUsers: "Utilisateur·rice·s en sourdine"
blockedUsers: "Utilisateur·rice·s bloqué·e·s"
noUsers: "Il n'y a aucun utilisateur·rice"
noUsers: "Il ny a pas dutilisateur·rice·s"
editProfile: "Modifier votre profil"
noteDeleteConfirm: "Êtes-vous sûr·e de vouloir supprimer cette note ?"
pinLimitExceeded: "Vous ne pouvez plus épingler d'autres notes."
intro: "L'installation de Misskey est terminée ! Créons le compte administrateur."
pinLimitExceeded: "Vous ne pouvez plus épingler dautres notes."
intro: "Linstallation de Misskey est terminée ! Veuillez créer un compte administrateur."
done: "Terminé"
processing: "Traitement en cours"
preview: "Prévisualisation"
default: "Par défaut"
noCustomEmojis: "Il n'y a pas démoji"
customEmojisOfRemote: "Émojis d'autres instances"
noJobs: "Il n'y a aucune tâche planifiée"
customEmojisOfRemote: "Émojis provenant des autres instances"
noJobs: "Il ny a aucune tâche planifiée"
federating: "En cours de fédération"
blocked: "Bloqué·e"
suspended: "Suspendu·e"
@ -183,8 +185,8 @@ subscribing: "Abonné"
publishing: "Publié"
notResponding: "Ne répond pas"
instanceFollowing: "Abonnements une instance"
instanceFollowers: "Abonné·e·s de l'instance"
instanceUsers: "Utilisateur·rice·s de l'instance"
instanceFollowers: "Abonné·e·s de linstance"
instanceUsers: "Utilisateur·rice·s de cette linstance"
changePassword: "Modifier votre mot de passe"
security: "Sécurité"
retypedNotMatch: "Les saisies ne correspondent pas."
@ -194,7 +196,7 @@ newPasswordRetype: "Répéter le nouveau mot de passe"
attachFile: "Joindre un fichier"
more: "Plus !"
featured: "Tendances"
usernameOrUserId: "Nom d'utilisateur ou ID utilisateur"
usernameOrUserId: "Nom dutilisateur·rice ou ID utilisateur"
noSuchUser: "Utilisateur·rice non trouvé"
lookup: "Recherche"
announcements: "Annonces"
@ -214,15 +216,15 @@ uploadFromUrlMayTakeTime: "Le téléversement de votre fichier peut prendre un c
explore: "Découvrir"
games: "Jeux de Misskey"
messageRead: "Lus"
noMoreHistory: "Il n'y a plus d'historique"
noMoreHistory: "Il ny a plus dhistorique"
startMessaging: "Commencer à discuter"
nUsersRead: "Lu par {n} personnes"
agreeTo: "J'accepte {0}"
tos: "Conditions d'utilisation"
agreeTo: "Jaccepte {0}"
tos: "les conditions dutilisation"
start: "Commencer"
home: "Principal"
remoteUserCaution: "Les informations peuvent être incomplètes, parce que l'utilisateur·rice est d'une instance distante."
activity: "Activités"
remoteUserCaution: "Les informations de ce compte risqueraient dêtre incomplètes du fait que lutilisateur·rice provient dune instance distante."
activity: "Activité"
images: "Images"
birthday: "Date de naissance"
yearsOld: "{age} ans"
@ -271,12 +273,12 @@ reject: "Refuser"
normal: "Normal"
instanceName: "Nom de linstance"
instanceDescription: "Description de linstance"
maintainerName: "Nom de l'administrateur·rice"
maintainerEmail: "Email de l'administrateur·rice"
tosUrl: "URL des conditions d'utilisation"
maintainerName: "Ladministrateur·rice"
maintainerEmail: "Email de ladministrateur·rice"
tosUrl: "URL des conditions dutilisation"
thisYear: "Cette année"
thisMonth: "Ce mois-ci"
today: "Aujourd'hui"
today: "Aujourdhui"
dayX: "{day}"
monthX: "{month}"
yearX: "{year}"
@ -287,16 +289,16 @@ disconnectSerice: "Déconnecter"
enableLocalTimeline: "Activer le fil local"
enableGlobalTimeline: "Activer le fil global"
disablingTimelinesInfo: "Si vous désactivez ces fils, les administrateurs et les modérateurs pourront toujours y accéder."
registration: "S'inscrire"
enableRegistration: "Autoriser nimporte qui à sinscrire"
registration: "Sinscrire"
enableRegistration: "Autoriser les nouvelles inscriptions"
invite: "Inviter"
proxyRemoteFiles: "Proxy fichiers distants"
proxyRemoteFilesDescription: "Si vous activez ce paramètre, les fichiers distants non stockés ou supprimés en raison d'une capacité excédentaire seront affichés via un proxy local et généreront une miniature. Cela n'affectera pas le stockage du serveur."
driveCapacityPerLocalAccount: "Volume du Drive par utilisateur local"
driveCapacityPerRemoteAccount: "Volume du Drive par utilisateur distant"
inMb: "en mégaoctets"
iconUrl: "URL de l'image de l'icône"
bannerUrl: "URL de l'image de la bannière"
iconUrl: "URL de limage de lavatar"
bannerUrl: "URL de limage de la bannière"
basicInfo: "Informations basiques"
pinnedUsers: "Utilisateur·rice épinglé·e"
pinnedUsersDescription: "Listez les utilisateur·rice·s que vous souhaitez voir épinglé·e·s sur la page \"Découvrir\", un·e par ligne."
@ -308,26 +310,26 @@ recaptcha: "reCAPTCHA"
enableRecaptcha: "Activer reCAPTCHA"
recaptchaSiteKey: "Clé du site"
recaptchaSecretKey: "Clé secrète"
avoidMultiCaptchaConfirm: "L'utilisation de plusieurs Captchas peut provoquer des interférences. Souhaitez-vous désactiver l'autre Captcha? Vous pouvez laisser plusieurs Captcha activés en appuyant sur Annuler."
antennas: "Antenne"
manageAntennas: "Gestion d'antenne"
avoidMultiCaptchaConfirm: "Lutilisation de plusieurs Captchas peut provoquer des interférences. Souhaitez-vous désactiver lautre Captcha ? Vous pouvez laisser plusieurs Captcha activés en appuyant sur Annuler."
antennas: "Antennes"
manageAntennas: "Gestion des antennes"
name: "Nom"
antennaSource: "Recevoir la source"
antennaSource: "Source de lantenne"
antennaKeywords: "Mots clés à recevoir"
antennaExcludeKeywords: "Mots clés à exclure"
antennaKeywordsDescription: "Séparez avec des espaces pour une condition ET. Séparez avec un saut de ligne pour une condition OU."
notifyAntenna: "Notifier les nouvelles notes"
withFileAntenna: "Notes uniquement avec fichiers joints"
antennaKeywordsDescription: "Séparer avec des espaces pour la condition AND. Séparer avec un saut de ligne pour une condition OR."
notifyAntenna: "Me notifier pour les nouvelles notes"
withFileAntenna: "Notes ayant des attachements uniquement"
serviceworker: "ServiceWorker"
enableServiceworker: "Activer ServiceWorker"
antennaUsersDescription: "Spécifiez les noms d'utilisateurs séparés par des sauts de ligne"
antennaUsersDescription: "Saisissez un seul nom dutilisateur·rice par ligne"
caseSensitive: "Sensible à la casse"
withReplies: "Inclure les réponses"
connectedTo: "Vous êtes connectés aux services suivants"
notesAndReplies: "Notes et Réponses"
withFiles: "Avec fichiers joints"
silence: "Mettre en sourdine"
silenceConfirm: "Êtes-vous sûr·e de vouloir mettre l'utilisateur·rice en sourdine ?"
silenceConfirm: "Êtes-vous sûr·e de vouloir mettre lutilisateur·rice en sourdine ?"
unsilence: "Annuler la mise en sourdine"
unsilenceConfirm: "Êtes-vous sûr·e de vouloir annuler la mise en sourdine de cette utilisateur·rice ?"
popularUsers: "Utilisateur·rice·s populaires"
@ -340,10 +342,10 @@ popularTags: "Mots-clés populaires"
userList: "Listes"
about: "Informations"
aboutMisskey: "À propos de Misskey"
aboutMisskeyText: "Misskey est un logiciel open source, développé par syuilo depuis 2014."
aboutMisskeyText: "Misskey est un logiciel libre et ouvert, développé par syuilo depuis 2014."
misskeyMembers: "Il est développé et maintenu par les membres listés ci-dessous :"
misskeySource: "Le code source est disponible ici:"
misskeyTranslation: "Aidez-nous avec votre contribution à traduire Misskey:"
misskeyTranslation: "Aidez-nous en contribuant à traduire Misskey :"
misskeyDonate: "Vous pouvez contribuer au développement de Misskey en faisant un don ici:"
morePatrons: "Nous apprécions vraiment le soutien de nombreuses autres personnes non mentionnées ici. Merci à toutes et à tous ! 🥰"
patrons: "Supporteurs"
@ -361,12 +363,12 @@ passwordLessLogin: "Connectez-vous sans mot de passe"
resetPassword: "Réinitialiser mot de passe"
newPasswordIs: "Votre nouveau mot de passe est \"{password}\""
autoReloadWhenDisconnected: "Rechargement automatique lorsque le serveur se déconnecte"
autoNoteWatch: "Surveiller automatique pour les notes"
autoNoteWatch: "Surveiller les notes automatiquement"
autoNoteWatchDescription: "Soyez informé des notes auxquelles vous avez réagi ou répondu."
reduceUiAnimation: "Réduire l'animation de l'interface"
reduceUiAnimation: "Réduire les animations dans linterface"
share: "Partager"
notFound: "Non trouvé"
notFoundDescription: "Aucune page ne correspond à l'URL spécifiée."
notFoundDescription: "Aucune page ne correspond à lURL spécifiée."
uploadFolder: "Emplacement de téléversement par défaut"
cacheClear: "Vider le cache"
markAsReadAllNotifications: "Marquer toutes les notifications comme lues"
@ -398,7 +400,7 @@ quoteAttached: "Avec citation"
quoteQuestion: "Souhaitez-vous ajoutez une citation ?"
noMessagesYet: "Pas encore discuté"
newMessageExists: "Vous avez un nouveau message"
onlyOneFileCanBeAttached: "Vous ne pouvez joindre qu'un seul fichier au message"
onlyOneFileCanBeAttached: "Vous ne pouvez joindre quun seul fichier au message"
signinRequired: "Veuillez vous connecter"
invitationCode: "Code dinvitation"
checking: "Vérification"
@ -410,20 +412,20 @@ tooLong: "Est trop long"
weakPassword: "Faible mot de passe"
normalPassword: "Bon mot de passe"
strongPassword: "Fort mot de passe"
passwordMatched: "Correcte"
passwordMatched: "Combinaison correcte !"
passwordNotMatched: "Ne correspond pas"
signinWith: "Connectez-vous avec {x}"
signinFailed: "Échec dauthentification. Veuillez vérifier que votre nom dutilisateur et mot de passe sont corrects."
tapSecurityKey: "Touchez la clé de sécurité"
tapSecurityKey: "Appuyez sur votre clé de sécurité"
or: "OU"
uiLanguage: "Langue d'affichage de l'interface"
uiLanguage: "Langue daffichage de linterface"
groupInvited: "Invité au groupe"
aboutX: "À propos de {x}"
useOsNativeEmojis: "Utiliser les émojis natifs du système"
youHaveNoGroups: "Vous n'avez aucune groupe"
youHaveNoGroups: "Vous navez aucun groupe"
joinOrCreateGroup: "Soyez invité à rejoindre les groupes ou vous pouvez créer votre propre groupe."
noHistory: "Pas d'historique"
disableAnimatedMfm: "Désactiver MFM qui a des animations"
disableAnimatedMfm: "Désactiver MFM ayant des animations"
doing: "Attends une seconde"
category: "Catégories"
tags: "Étiquettes"
@ -433,7 +435,7 @@ existingAcount: "Comptes existants"
regenerate: "Régénérer"
fontSize: "Taille de la police"
noFollowRequests: "Vous navez aucune demande dabonnement en attente"
openImageInNewTab: "Ouvrir l'image dans un nouvel onglet"
openImageInNewTab: "Ouvrir les images dans un nouvel onglet"
dashboard: "Tableau de bord"
local: "Local"
remote: "Distant"
@ -451,7 +453,7 @@ showFeaturedNotesInTimeline: "Afficher les notes en vedette dans fil d'actualit
objectStorage: "Stockage d'objets"
useObjectStorage: "Utiliser le stockage d'objets"
objectStorageBaseUrl: "Base URL"
objectStorageBaseUrlDesc: "Préfixe d'URL utilisé pour construire l'URL vers le référencement d'objet (média). Spécifiez son URL si vous utilisez un CDN ou un proxy, sinon spécifiez l'adresse accessible au public selon le guide de service que vous allez utiliser. i.g 'https://<bucket>.s3.amazonaws.com' pour AWS S3 et 'https://storage.googleapis.com/<bucket>' pour GCS."
objectStorageBaseUrlDesc: "Préfixe dURL utilisé pour construire lURL vers le référencement dobjet (média). Spécifiez son URL si vous utilisez un CDN ou un proxy, sinon spécifiez ladresse accessible au public selon le guide de service que vous allez utiliser. P.ex. 'https://<bucket>.s3.amazonaws.com' pour AWS S3 et 'https://storage.googleapis.com/<bucket>' pour GCS."
objectStorageBucket: "Bucket"
objectStorageBucketDesc: "Veuillez spécifier le nom du compartiment utilisé sur le service configuré."
objectStoragePrefix: "Prefix"
@ -474,7 +476,7 @@ none: "Rien"
volume: "Volume"
details: "Détails"
chooseEmoji: "Choisissez un émoji"
unableToProcess: "L'opération n'a pas pu être complétée"
unableToProcess: "Lopération na pas pu être complétée."
recentUsed: "Récemment utilisé"
install: "Installation"
uninstall: "Désinstaller"
@ -495,13 +497,25 @@ updateRemoteUser: "Mettre à jour les informations de lutilisateur·rice dist
deleteAllFiles: "Supprimer tous les fichiers"
deleteAllFilesConfirm: "Êtes vous surs de vouloir supprimer tous les fichiers ?"
removeAllFollowing: "Retenir tous les abonnements"
removeAllFollowingDescription: "Se désabonner de tous les comptes de {host}. Exécutez cette commande si l'instance n'existe plus."
removeAllFollowingDescription: "Se désabonner de tous les comptes de {host}. Veuillez lancer cette action uniquement si linstance nexiste plus."
userSuspended: "Cette utilisateur·trice a été suspendue."
userSilenced: "Cette utilisateur·trice a été masquer."
sidebar: "Barre latérale"
divider: "Séparateur"
addItem: "Ajouter élément"
rooms: "Pièce"
rooms: "Chambre"
relays: "Relais"
addRelay: "Ajouter un relais"
inboxUrl: "Inbox URL"
addedRelays: "Relais ajoutés"
serviceworkerInfo: "Devrait être activé pour les notifications push."
deletedNote: "Note supprimée"
invisibleNote: "Note invisible"
enableInfiniteScroll: "Activer le défilement infini"
visibility: "Visibilité"
poll: "Sondage"
useCw: "Masquer le contenu"
fixedWidgetsPosition: "Rendre la position du widget fixe"
_theme:
explore: "Explorer les thèmes"
install: "Installer un thème"
@ -510,13 +524,19 @@ _theme:
installed: "{name} a été installé"
alreadyInstalled: "Ce thème est déjà installé"
invalid: "Le format du thème n'est pas valide"
defaultValue: "Valeur par défaut"
func: "Fonction"
keys:
mention: "Mentionner"
renote: "Renote"
divider: "Séparateur"
_sfx:
note: "Nouvelle note"
noteMy: "Ma note"
notification: "Notifications"
chat: "Discuter"
chatBg: "Discuter (De fond)"
antenna: "Réception d'antenne"
antenna: "Réception de lantenne"
_ago:
unknown: "Inconnu"
future: "Futur"
@ -536,33 +556,33 @@ _time:
_tutorial:
title: "Comment utiliser Misskey"
step1_1: "Bienvenue,"
step1_2: "Cette page est appelée \"fil d'actualité\". Elle montre les \"notes\" des personnes que vous \"abonne\" dans l'ordre chronologique."
step1_3: "Vous n'avez pas encore publier de notes et personne n'est encore abonnements, vous ne devriez donc rien voir dans fil d'actualité."
step2_1: "Finissons de créer votre profil avant d'écrire une note ou de abonne quelqu'un."
step2_2: "En fournissant quelques informations sur vous, il sera plus facile pour les autres de vous abonne."
step1_2: "Cette page est appelée « un fil ». Elle affiche les « notes » des personnes auxquelles vous êtes abonné dans un ordre chronologique."
step1_3: "Votre fil est actuellement vide vu que vous ne suivez aucun compte et que vous navez publié aucune note, pour linstant."
step2_1: "Procédons dabord à la préparation de votre profil avant décrire une note et/ou de vous abonner à un compte."
step2_2: "En fournissant quelques informations sur vous, il sera plus facile pour les autres de sabonner à votre compte."
step3_1: "Vous avez fini de créer votre profil ?"
step3_2: "Létape suivante consiste à créer une note. Vous pouvez commencer en cliquant sur licône crayon sur lécran."
step3_3: "Remplissez le cadran et cliquez sur le bouton en haut à droite pour envoyer."
step3_4: "Vous n'avez rien à dire ? Essayez de dire \"J'ai commencé à utiliser Misskey\"."
step4_1: "Avez-vous posté votre première notes ?"
step4_2: "Votre première note est maintenant affiché sur votre fil d'actualité."
step5_1: "Ensuite, abonnons-nous d'autres personnes et rendre la fil d'actualité en savoir plus vivante."
step5_2: "{featured} affiche les notes en tendance sur cette instance. {explore} vous permet de trouver les utilisateur·rice·s en tendance. Essayez de vous abonner aux gens que vous aimez !"
step5_3: "Pour abonne un utilisateur, cliquez sur l'icône de l'utilisateur pour afficher la page de l'utilisateur et appuyez sur le bouton \"Abonnement\"."
step5_4: "Selon l'utilisateur, il peut s'écouler un certain temps avant que la abonner ne soit approuvé."
step6_1: "Si vous voyez la notes d'un autre utilisateur sur fil d'actualité, c'était réussi."
step6_2: "Vous pouvez ajouter des \"réactions\" aux notes des autres afin de pouvoir facilement dire votre émotion."
step6_3: "Pour ajouter une réaction, cliquez sur la marque \"+\" sur la note et sélectionnez la réaction souhaitée."
step7_1: "Tu as bien travaillé ! Ceci conclut l'explication de l'utilisation de base de Misskey."
step7_2: "Pour plus d'informations sur Misskey, voir {help}."
step7_3: "Alors, profitez de Misskey 🚀"
step3_4: "Vous navez rien à dire ? Essayez décrire « Jai commencé à utiliser Misskey »."
step4_1: "Avez-vous publié votre première note ?"
step4_2: "Youpi ! Celle-ci est maintenant affiché sur votre fil dactualité."
step5_1: "Maintenant, essayons de nous abonner à dautres personnes afin de rendre votre fil plus vivant."
step5_2: "La page {featured} affiche les notes en tendance sur la présente instance et {explore} vous permet de trouver des utilisateur·rice·s en tendance. Essayez de vous abonner aux gens que vous aimez !"
step5_3: "Pour pouvoir suivre dautres utilisateur·rice, cliquez sur leur avatar afin dafficher la page du profil utilisateur ensuite appuyez sur le bouton « Sabonner »."
step5_4: "Si lautre utilisateur possède une icône sous forme dun cadenas à côté de son nom, il devra accepter votre demande dabonnement manuellement."
step6_1: "Maintenant, vous êtes en mesure de voir safficher les notes des autres utilisateur·rice·s sur votre propre fil."
step6_2: "Vous avez également la possibilité dintéragir rapidement avec les notes des autres utilisateur·rice·s en ajoutant des « réactions »."
step6_3: "Pour ajouter une réaction à une note, cliquez sur le signe « + » de celle-ci et sélectionnez lémoji souhaité."
step7_1: "Félicitations ! Vous avez atteint la fin du tutoriel de base pour lutilisation de Misskey."
step7_2: "Si vous désirez en savoir plus sur Misskey, jetez un œil sur la section {help}."
step7_3: "Bon courage et amusez-vous bien sur Misskey 🚀"
_2fa:
alreadyRegistered: "Cette étape à déjà été complétée"
registerDevice: "Ajouter un appareil"
registerDevice: "Ajouter un nouvel appareil"
registerKey: "Sinscrire la clé"
step1: "Tout d'abord, installez une application d'authentification, telle que {a} ou {b}, sur votre appareil."
step2: "Ensuite, scannez le code QR affiché avec l'application."
step3: "Entrez le jeton affiché sur l'application et vous avez terminé."
step2: "Ensuite, scannez le code QR affiché sur lécran."
step3: "Entrez le jeton affiché sur votre application pour compléter la configuration."
step4: "Lorsque vous vous connectez, entrez le jeton de la même manière."
securityKeyInfo: "Vous pouvez configurer l'authentification WebAuthN pour sécuriser davantage le processus de connexion avec non seulement la clé de sécurité matérielle qui prend en charge FIDO2, mais également l'authentification par empreinte digitale ou PIN sur votre appareil."
_permissions:
@ -574,7 +594,7 @@ _permissions:
"write:drive": "Écrire sur le Drive"
"read:favorites": "Afficher les favoris"
"write:favorites": "Écrire des favoris"
"read:following": "Voir les informations de l'abonné"
"read:following": "Voir les informations de vos abonnements"
"write:following": "Abonnements/Se désabonner"
"read:messaging": "Cherche à discuter"
"write:messaging": "Contrôler le discuter"
@ -588,23 +608,23 @@ _permissions:
"write:votes": "Voter"
"read:pages": "Afficher la page"
"write:pages": "Mettre à jour les Pages"
"read:page-likes": "Lire les favoris sur les Pages"
"read:page-likes": "Voir les favoris sur les Pages"
"write:page-likes": "Mettre à jour les favoris sur les Pages"
"read:user-groups": "Voir les groupes d'utilisateur·rice·s"
"write:user-groups": "Éditer les groupes des utilisateur·rice·s"
_auth:
shareAccess: "Autoriser \"{name}\" à accéder à votre compte ?"
shareAccessAsk: "Voulez-vous vraiment autoriser cette application à accéder à votre compte?"
permissionAsk: "Cette application nécessite les autorisations suivantes "
pleaseGoBack: "Veillez retourner à l'application"
permissionAsk: "Cette application nécessite les autorisations suivantes :"
pleaseGoBack: "Veuillez retourner à lapplication"
callback: "Retour vers lapplication"
denied: "Accès refusé"
_antennaSources:
all: "Toutes les notes"
homeTimeline: "Notes de l'utilisateur auquel je m'abonne"
users: "Notes des un ou plusieurs utilisateurs spécifiés"
userList: "Notes pour les utilisateurs de la liste spécifiée"
userGroup: "Notes pour les utilisateurs de la groupe spécifiée"
homeTimeline: "Notes venant des utilisateur·rice·s auxquel·les je suis abonné"
users: "Notes venant de la part dutilisateur·rice·s précis"
userList: "Notes venant dune liste spécifique"
userGroup: "Notes venant dutilisateur·rice·s du groupe spécifié"
_weekday:
sunday: "Dimanche"
monday: "Lundi"
@ -616,19 +636,18 @@ _weekday:
_widgets:
memo: "Note collante"
notifications: "Notifications"
timeline: "Fil d'actualité"
timeline: "Fil"
calendar: "Calendrier"
trends: "Tendances"
clock: "Horloge"
rss: "Lecteur de flux RSS"
activity: "Activités"
activity: "Activité"
photos: "Photos"
_cw:
hide: "Masquer"
show: "Voir plus"
show: "Afficher plus"
chars: "{count} caractères"
files: "{count} fichiers"
poll: "Sondage"
_poll:
noOnlyOneChoice: "Au moins 2 réponses nécéssaires"
choiceN: "Choix {n}"
@ -637,7 +656,7 @@ _poll:
expiration: "Fin du sondage"
infinite: "Illimité"
at: "Choisir une date"
after: "Chosir une durée"
after: "Choisir la durée"
deadlineDate: "Date de fin"
deadlineTime: "Heure de fin"
duration: "Durée"
@ -661,11 +680,12 @@ _visibility:
specified: "Direct"
specifiedDescription: "Publier uniquement aux utilisateur·rice·s mentionné·e·s"
localOnly: "Local seulement"
localOnlyDescription: "Caché pour les utilisateurs distant"
_postForm:
replyPlaceholder: "Répondre à cette note ..."
quotePlaceholder: "Citez cette note ..."
_placeholders:
a: "Qu'est-ce qu'il se passe ?"
a: "Quoi de neuf ?"
b: "Quoi de neuf ?"
c: "Quavez-vous en tête ?"
d: "Désirez-vous publier quelques mots ?"
@ -673,7 +693,7 @@ _postForm:
f: "En attente de vos écrits ..."
_profile:
name: "Nom"
username: "Nom d'utilisateur·rice"
username: "Nom dutilisateur·rice"
description: "À propos de moi"
youCanIncludeHashtags: "Vous pouvez également inclure des hashtags."
metadata: "Informations complémentaires"
@ -686,15 +706,15 @@ _exportOrImport:
blockingList: "Bloquer"
userLists: "Listes"
_charts:
federationInstancesIncDec: "Variation du nombre d'instances"
federationInstancesTotal: "Nombre d'instances au total"
federationInstancesIncDec: "Variation du nombre des instances fédérées"
federationInstancesTotal: "Nombre total des instances fédérées"
usersIncDec: "Variation du nombre d'utilisateur·rice·s"
usersTotal: "Nombre d'utilisateur·rice·s au total"
usersTotal: "Nombre des utilisateur·rice·s au total"
activeUsers: "Utilisateur·rice·s actif·ve·s"
notesIncDec: "Variation du nombre d'notes"
notesIncDec: "Variation du nombre des notes"
localNotesIncDec: "Variation du nombre de notes local"
remoteNotesIncDec: "Variation du nombre dnotes distant"
notesTotal: "Nombre d'notes au total"
notesTotal: "Nombre total des notes"
filesIncDec: "Variation du nombre de fichiers"
filesTotal: "Nombre de fichiers au total"
storageUsageIncDec: "Variation de l'utilisation du stockage"
@ -703,8 +723,8 @@ _instanceCharts:
requests: "Requêtes"
users: "Variation du nombre d'utilisateur·rice·s"
usersTotal: "Nombre d'utilisateur·rice·s au total cumulé"
notes: "Variation du nombre d'notes"
notesTotal: "Nombre d'notes au total cumulé"
notes: "Variation du nombre des notes"
notesTotal: "Nombre total cumulé des notes"
ff: "Variation des abonné·e·s"
ffTotal: "Nombre d'abonné·e·s au total cumulé"
cacheSize: "Variation de la taille du cache"
@ -717,7 +737,7 @@ _timelines:
social: "Social"
global: "Global"
_rooms:
roomOf: "Pièce de {user}"
roomOf: "Chambre de {user}"
addFurniture: "Placer des meubles"
translate: "Déplacer"
rotate: "Pivoter"
@ -727,7 +747,7 @@ _rooms:
clearConfirm: "Désirez-vous enlever tout les meubles de votre chambre ?"
leaveConfirm: "Vous avez des modifications non-sauvegardées. Voulez-vous vraiment quitter ?"
chooseImage: "Sélectionnez une image"
roomType: "Style de pièce"
roomType: "Type de chambre"
carpetColor: "Couleur du tapis"
_roomType:
default: "Par défaut"
@ -776,6 +796,8 @@ _rooms:
cup-noodle: "Bol de nouilles"
holo-display: "Affichage holographique"
energy-drink: "Boisson énergétique"
doll-ai: "Poupée Ai"
banknote: "Billets de banque"
_pages:
newPage: "Créer une page"
editPage: "Modifier une page"
@ -785,14 +807,14 @@ _pages:
deleted: "La page a bien été supprimée"
nameAlreadyExists: "La URL de page spécifiée existe déjà"
invalidNameTitle: "La URL de la page spécifiée nest pas valide"
invalidNameText: "Assurez-vous qu'il n'est pas vide"
invalidNameText: "Assurez-vous quil nest pas vide"
editThisPage: "Éditer cette page"
viewSource: "Afficher la source"
viewPage: "Afficher la page"
like: "Favori"
unlike: "Je nfavoris pas"
unlike: "Je naime pas"
my: "Mes pages"
liked: "Pages favoris"
liked: "Pages favorites"
inspector: "Inspecteur"
content: "Bloc de page"
variables: "Variables"
@ -808,7 +830,7 @@ _pages:
eyeCatchingImageRemove: "Supprimer une image attirante"
chooseBlock: "Ajouter un bloc"
selectType: "Choisir un type"
enterVariableName: "Veuillez entrer un nom de variable"
enterVariableName: "Veuillez entrer un nom pour votre variable"
variableNameIsAlreadyUsed: "Cette variable est déjà utilisée"
contentBlocks: "Contenu"
inputBlocks: "Entrée"
@ -868,7 +890,7 @@ _pages:
resetRandom: "Réinitialiser le nombre aléatoire"
pushEvent: "Envoyer un évènement"
_pushEvent:
event: "Nom de l'évènement"
event: "Nom de lévènement"
message: "Message à afficher lorsque appuyé"
variable: "Variable à envoyer"
no-variable: "Rien"
@ -898,8 +920,8 @@ _pages:
multiLineText: "Texte (Multi-lignes)"
textList: "Liste de texte"
_textList:
info: "Veuillez séparer chacun avec une nouvelle ligne"
strLen: "Longueur d'un texte"
info: "Veuillez séparer chaque entrée avec un saut de ligne"
strLen: "Longueur du texte"
_strLen:
arg1: "Texte"
strPick: "Extraire un caractère"
@ -1057,3 +1079,28 @@ _pages:
enviromentVariables: "Variables d'environnement"
pageVariables: "Élément de page"
argVariables: "Entrée slot"
_relayStatus:
requesting: "En attente"
accepted: "Accepté"
rejected: "Refusée"
_notification:
fileUploaded: "Le fichier a été téléversé !"
youGotMention: "{name} vous a mentionné"
youGotReply: "Réponse de {name}"
youGotQuote: "Cité·e par {name}"
youRenoted: "{name} vous a Renoté"
youGotPoll: "{name} a participé à votre sondage"
youGotMessagingMessageFromUser: "{name} vous envoyé un message"
youGotMessagingMessageFromGroup: "Un message a été envoyé au groupe {name}"
youWereFollowed: "Vous suit"
youReceivedFollowRequest: "Vous avez reçu une demande dabonnement"
yourFollowRequestAccepted: "Votre demande dabonnement a été accepté"
youWereInvitedToGroup: "Invité au groupe"
_deck:
_columns:
notifications: "Notifications"
tl: "Fil"
antenna: "Antennes"
list: "Listes"
mentions: "Mentions"
direct: "Direct"

View File

@ -14,6 +14,7 @@ const merge = (...args) => args.reduce((a, c) => ({
}), {});
const languages = [
'ar-SA',
//'cs-CZ',
//'da-DK',
'de-DE',

View File

@ -45,6 +45,7 @@ loadMore: "もっと見る"
youGotNewFollower: "フォローされました"
receiveFollowRequest: "フォローリクエストされました"
followRequestAccepted: "フォローが承認されました"
mention: "メンション"
mentions: "あなた宛て"
directNotes: "ダイレクト投稿"
importAndExport: "インポートとエクスポート"
@ -104,6 +105,7 @@ suspendConfirm: "凍結しますか?"
unsuspendConfirm: "解凍しますか?"
selectList: "リストを選択"
customEmojis: "カスタム絵文字"
emoji: "絵文字"
emojiName: "絵文字名"
emojiUrl: "絵文字画像URL"
addEmoji: "絵文字を追加"
@ -506,6 +508,26 @@ relays: "リレー"
addRelay: "リレーの追加"
inboxUrl: "inboxのURL"
addedRelays: "追加済みのリレー"
serviceworkerInfo: "プッシュ通知を行うには有効する必要があります。"
deletedNote: "削除された投稿"
invisibleNote: "非公開の投稿"
enableInfiniteScroll: "自動でもっと見る"
visibility: "公開範囲"
poll: "アンケート"
useCw: "内容を隠す"
fixedWidgetsPosition: "ウィジェットの位置を固定する"
enablePlayer: "プレイヤーを開く"
disablePlayer: "プレイヤーを閉じる"
expandTweet: "ツイートを展開する"
themeEditor: "テーマエディター"
description: "説明"
author: "作者"
leaveConfirm: "未保存の変更があります。破棄しますか?"
manage: "管理"
plugins: "プラグイン"
pluginInstallWarn: "信頼できないプラグインはインストールしないでください。"
deck: "デッキ"
undeck: "デッキ解除"
_theme:
explore: "テーマを探す"
@ -515,6 +537,70 @@ _theme:
installed: "{name}をインストールしました"
alreadyInstalled: "そのテーマは既にインストールされています"
invalid: "テーマの形式が間違っています"
make: "テーマを作る"
base: "ベース"
addConstant: "定数を追加"
constant: "定数"
defaultValue: "デフォルト値"
color: "色"
refProp: "プロパティを参照"
refConst: "定数を参照"
key: "キー"
func: "関数"
funcKind: "関数の種類"
argument: "引数"
basedProp: "元にするプロパティの名前"
alpha: "不透明度"
darken: "暗さ"
lighten: "明るさ"
inputConstantName: "定数名を入力してください"
importInfo: "ここにテーマコードを貼り付けて、エディターにインポートできます"
deleteConstantConfirm: "定数 {const} を削除しても良いですか?"
keys:
accent: "アクセント"
bg: "背景"
fg: "文字"
focus: "フォーカス"
indicator: "インジケーター"
panel: "パネル"
shadow: "影"
header: "ヘッダー"
navBg: "サイドバーの背景"
navFg: "サイドバーの文字"
navHoverFg: "サイドバー文字(ホバー)"
navActive: "サイドバー文字(アクティブ)"
navIndicator: "サイドバーのインジケーター"
link: "リンク"
hashtag: "ハッシュタグ"
mention: "メンション"
mentionMe: "あなた宛てメンション"
renote: "Renote"
modalBg: "モーダルの背景"
divider: "分割線"
scrollbarHandle: "スクロールバーの取っ手"
scrollbarHandleHover: "スクロールバーの取っ手(ホバー)"
dateLabelFg: "日付ラベルの文字"
infoBg: "情報の背景"
infoFg: "情報の文字"
infoWarnBg: "警告の背景"
infoWarnFg: "警告の文字"
cwBg: "CW ボタンの背景"
cwFg: "CW ボタンの文字"
cwHoverBg: "CW ボタンの背景 (ホバー)"
toastBg: "通知トーストの背景"
toastFg: "通知トーストの文字"
buttonBg: "ボタンの背景"
buttonHoverBg: "ボタンの背景 (ホバー)"
inputBorder: "入力ボックスの縁取り"
listItemHoverBg: "リスト項目の背景 (ホバー)"
driveFolderBg: "ドライブフォルダーの背景"
wallpaperOverlay: "壁紙のオーバーレイ"
badge: "バッジ"
messageBg: "チャットの背景"
accentDarken: "アクセント (暗め)"
accentLighten: "アクセント (明るめ)"
fgHighlighted: "強調された文字"
_sfx:
note: "ノート"
@ -638,13 +724,13 @@ _widgets:
rss: "RSSリーダー"
activity: "アクティビティ"
photos: "フォト"
digitalClock: "デジタル時計"
_cw:
hide: "隠す"
show: "もっと見る"
chars: "{count}文字"
files: "{count}ファイル"
poll: "アンケート"
_poll:
noOnlyOneChoice: "選択肢は最低2つ必要です"
@ -679,6 +765,7 @@ _visibility:
specified: "ダイレクト"
specifiedDescription: "指定したユーザーのみに公開"
localOnly: "ローカルのみ"
localOnlyDescription: "リモートユーザーには非公開"
_postForm:
replyPlaceholder: "このノートに返信..."
@ -801,6 +888,8 @@ _rooms:
cup-noodle: "カップ麺"
holo-display: "ホログラフィックディスプレイ"
energy-drink: "エナジードリンク"
doll-ai: "藍ちゃん人形"
banknote: "札束"
_pages:
newPage: "ページの作成"
@ -1099,3 +1188,30 @@ _relayStatus:
requesting: "承認待ち"
accepted: "承認済み"
rejected: "拒否済み"
_notification:
fileUploaded: "ファイルがアップロードされました"
youGotMention: "{name}からのメンション"
youGotReply: "{name}からのリプライ"
youGotQuote: "{name}による引用"
youRenoted: "{name}がRenoteしました"
youGotPoll: "{name}が投票しました"
youGotMessagingMessageFromUser: "{name}からのチャットがあります"
youGotMessagingMessageFromGroup: "{name}のチャットがあります"
youWereFollowed: "フォローされました"
youReceivedFollowRequest: "フォローリクエストが来ました"
yourFollowRequestAccepted: "フォローリクエストが承認されました"
youWereInvitedToGroup: "グループに招待されました"
_deck:
alwaysShowMainColumn: "常にメインカラムを表示"
columnAlign: "カラムの寄せ"
_columns:
widgets: "ウィジェット"
notifications: "通知"
tl: "タイムライン"
antenna: "アンテナ"
list: "リスト"
mentions: "あなた宛て"
direct: "ダイレクト"

View File

@ -38,6 +38,8 @@ delete: "ほかす"
deleteAndEdit: "ほかして直す"
deleteAndEditConfirm: "このートをほかしてもっかい直すこのートへのリアクション、Remote、返信も全部消えんで"
addToList: "リストに入れたる"
sendMessage: "メッセージを送る"
copyUsername: "ユーザー名をコピー"
reply: "返す"
loadMore: "もっとあるやろ!"
youGotNewFollower: "フォローされたで"
@ -45,14 +47,26 @@ receiveFollowRequest: "フォローリクエストされたで"
followRequestAccepted: "フォローが承認されたで"
mentions: "あんた宛て"
directNotes: "ダイレクト投稿"
importAndExport: "インポートとエクスポート"
import: "インポート"
export: "エクスポート"
files: "ファイル"
download: "ダウンロード"
driveFileDeleteConfirm: "ファイル「{name}」を消してしもうてええか?このファイルを添付したノートも消えてまうで。"
unfollowConfirm: "{name}のフォローを解除してもええんか?"
exportRequested: "エクスポートしてな、ってリクエストしたけど、これ多分めっちゃ時間かかるで。エクスポート終わったら「ドライブ」に突っ込んどくで。"
importRequested: "インポートしてな、ってリクエストしたけど、これ多分めっちゃ時間かかるで。"
lists: "リスト"
noLists: "リストはあらへん"
note: "ノート"
notes: "ノート"
following: "フォロー"
followers: "フォロワー"
followsYou: "フォローされとるで"
createList: "リスト作る"
manageLists: "リストの管理"
error: "問題が発生してん"
retry: "もっぺんやってみる"
enterListName: "リスト名を入れてや"
privacy: "プライバシーってなんや?オカンの年齢か?"
makeFollowManuallyApprove: "他人のフォローは許可してからや!"
@ -60,13 +74,20 @@ defaultNoteVisibility: "もとからの公開範囲"
follow: "フォロー"
followRequest: "フォロー許してくれや!言うてみる"
followRequests: "フォロー許してくれや!"
unfollow: "フォローやめる"
followRequestPending: "フォロー許してくれるん待っとる"
enterEmoji: "絵文字を入れてや"
renote: "Renote"
unrenote: "Renoteやめる"
quote: "引用"
pinnedNote: "ピン留めされたノート"
you: "あんた"
clickToShow: "押してみ、見せたるわ"
sensitive: "見たらあかんで"
add: "増やす"
reaction: "リアクション"
reactionSettingDescription: "リアクションピッカーに出しとくリアクションを選んでや。"
rememberNoteVisibility: "公開範囲覚えといて"
attachCancel: "くっつけるのやめよか"
markAsSensitive: "ちょっと見せられへんわ"
unmarkAsSensitive: "別にええんじゃね?"
@ -77,45 +98,267 @@ block: "ブロック"
unblock: "ブロックやめたる"
suspend: "凍結"
unsuspend: "溶かす"
blockConfirm: "ブロックしてしもうてええか?"
unblockConfirm: "ブロックすんのやめるけどええか?"
suspendConfirm: "凍結してしもうてええか?"
unsuspendConfirm: "解凍するけどええか?"
selectList: "リストを選ぶ"
customEmojis: "カスタム絵文字"
emojiName: "絵文字名"
emojiUrl: "絵文字画像URL"
addEmoji: "絵文字を追加"
settingGuide: "ええ感じの設定"
cacheRemoteFiles: "リモートのファイルをキャッシュする"
cacheRemoteFilesDescription: "この設定をチャラにすると、リモートファイルをキャッシュせず直リンクするようになります。サーバーのストレージを節約できますが、サムネイルが生成されへんので通信量が増加します。"
flagAsBot: "Botやでと言っとく"
flagAsCat: "Catやでと言っとく"
autoAcceptFollowed: "フォローしとるユーザーからのフォロリクは全部勝手にええでって言うで"
addAcount: "アカウント追加"
loginFailed: "ログインに失敗してん"
showOnRemote: "リモートで見る"
general: "全般"
wallpaper: "壁紙"
setWallpaper: "壁紙を設定"
removeWallpaper: "壁紙ほかす"
searchWith: "検索: {q}"
youHaveNoLists: "リストはあらへん"
followConfirm: "{name}をフォローしてええか?"
proxyAccount: "プロキシアカウント"
proxyAccountDescription: "プロキシアカウントは、代わりにフォローしてくれるアカウントや。例えば、551に豚まんが無いときやったり、ユーザーがリモートユーザーをアカウントに入れたとき、リストに入れられたユーザーが誰からもフォローされてないと寂しいやん。寂しいし、アクティビティも配達されへんから、プロキシアカウントがフォローしてくれるで。ええやつやん…"
host: "ホスト"
selectUser: "ユーザーを選ぶ"
recipient: "宛先"
annotation: "注釈"
federation: "連合"
instances: "インスタンス"
registeredAt: "一見さんになった日"
latestRequestSentAt: "ちょっと前のリクエスト送信"
latestRequestReceivedAt: "ちょっと前のリクエスト受信"
latestStatus: "ちょっと前のステータス"
storageUsage: "ストレージ使うた量"
charts: "チャート"
perHour: "1時間ごと"
perDay: "1日ごと"
stopActivityDelivery: "アクティビティの配送をやめる"
blockThisInstance: "このインスタンスをブロック"
operations: "操作"
software: "ソフトウェア"
version: "バージョン"
metadata: "メタデータ"
withNFiles: "{n}個のファイル"
monitor: "モニター"
jobQueue: "ジョブキュー"
cpuAndMemory: "CPUとメモリ"
network: "ネットワーク"
disk: "ディスク"
instanceInfo: "インスタンス情報"
statistics: "統計"
clearQueue: "キューにさいなら"
clearQueueConfirmTitle: "キューをクリアしまっか?"
clearQueueConfirmText: "未配達の投稿は配送されなくなるで。通常この操作を行う必要はあらへんや。"
clearCachedFiles: "キャッシュにさいなら"
clearCachedFilesConfirm: "キャッシュされとるリモートファイルを全部削除しまっか?"
blockedInstances: "インスタンスブロック"
blockedInstancesDescription: "ブロックしたいインスタンスのホストを改行で区切って設定してな。ブロックされてもうたインスタンスとはもう金輪際やり取りできひんくなるで。"
muteAndBlock: "ミュートとブロック"
mutedUsers: "ミュートしたユーザー"
blockedUsers: "ブロックしたユーザー"
noUsers: "ユーザーはおらへん"
editProfile: "プロフィールをいじる"
noteDeleteConfirm: "このノートを削除しまっか?"
pinLimitExceeded: "これ以上ピン留めできひん"
intro: "Misskeyのインストールが完了してん管理者アカウントを作ってや。"
done: "でけた"
processing: "処理しとる"
preview: "プレビュー"
default: "デフォルト"
noCustomEmojis: "絵文字はあらへん"
customEmojisOfRemote: "リモートの絵文字"
noJobs: "ジョブはあらへん"
federating: "連合しとる"
blocked: "ブロックしとる"
suspended: "配信せぇへん"
all: "みな"
subscribing: "購読しとる"
publishing: "配信しとる"
notResponding: "応答してへんで"
instanceFollowing: "インスタンスのフォロー"
instanceFollowers: "インスタンスのフォロワー\n"
instanceUsers: "インスタンスのユーザー"
changePassword: "パスワード変える"
security: "セキュリティ"
retypedNotMatch: "そやないねん。"
currentPassword: "今のパスワード"
newPassword: "今度のパスワード"
newPasswordRetype: "今度のパスワード(もっぺん入れて)"
attachFile: "ファイルくっつけて"
more: "他ないんか!"
featured: "ハイライト"
usernameOrUserId: "ユーザー名かユーザーID"
noSuchUser: "ユーザーが見つからへんで"
lookup: "見てきて"
announcements: "これ知っといてな"
imageUrl: "画像URL"
remove: "ほかす"
removed: "削除したで!"
removeAreYouSure: "「{x}」はなおしてしもてええか?"
saved: "保存したで!"
messaging: "チャット"
upload: "アップロード"
fromDrive: "ドライブから"
fromUrl: "URLから"
uploadFromUrl: "URLアップロード"
uploadFromUrlDescription: "このURLのファイルをアップロードしたいねん"
uploadFromUrlRequested: "アップロードしたい言うといたで"
uploadFromUrlMayTakeTime: "アップロード終わるんにちょい時間かかるかもしれへんわ。"
explore: "みつける"
games: "Misskey Games"
messageRead: "もう読んだ"
noMoreHistory: "これより過去の履歴はあらへんで"
startMessaging: "チャットやるで"
nUsersRead: "{n}人が読んでもうた"
agreeTo: "{0}はええで"
tos: "利用規約"
start: "始める"
home: "ホーム"
remoteUserCaution: "リモートユーザーやから、ちゃんとした情報とちゃうで。"
activity: "アクティビティ"
images: "画像"
birthday: "生まれた日"
yearsOld: "{age}歳"
registeredDate: "始めた日"
location: "場所"
theme: "テーマ"
themeForLightMode: "ライトモードではこのテーマつこて"
themeForDarkMode: "ダークモードではこのテーマつこて"
light: "ライト"
dark: "ダーク"
lightThemes: "デイゲーム"
darkThemes: "ナイトゲーム"
syncDeviceDarkMode: "試合開始時間はデバイスのダークモードと一緒や"
drive: "ドライブ"
fileName: "ファイル名"
selectFile: "ファイル選んでや"
selectFiles: "ファイル選んでや"
selectFolder: "フォルダ選んでや"
selectFolders: "フォルダ選んでや"
renameFile: "ファイル名をいらう"
folderName: "フォルダー名"
createFolder: "フォルダー作る"
renameFolder: "フォルダー名を変える"
deleteFolder: "フォルダーを消してまう"
addFile: "ファイルを追加"
emptyDrive: "ドライブにはなんも残っとらん"
emptyFolder: "ふぉろだーにはなんも残っとらん"
unableToDelete: "消そうおもってんけどな、あかんかったわ"
inputNewFileName: "今度のファイル名は何にするん?"
inputNewFolderName: "今度のフォルダ名は何にするん?"
circularReferenceFolder: "移動先のフォルダーは、移動するフォルダーのサブフォルダーや。"
hasChildFilesOrFolders: "このフォルダ、まだなんか入っとるから消されへん"
copyUrl: "URLをコピー"
rename: "名前を変えるで"
avatar: "アイコン"
banner: "バナー"
nsfw: "見たらあかんで"
disconnectedFromServer: "サーバーが機嫌悪いねん"
reload: "リロード"
doNothing: "何もせんとく"
reloadConfirm: "リロードしてええか?"
watch: "ウォッチ"
unwatch: "ウォッチやめる"
accept: "ええで"
reject: "あかん"
normal: "ええ感じ"
instanceName: "インスタンス名"
instanceDescription: "インスタンスの紹介"
maintainerName: "管理者の名前"
maintainerEmail: "管理者のメールアドレス"
tosUrl: "利用規約のURL"
thisYear: "今年"
thisMonth: "今月"
today: "今日"
dayX: "{day}日"
monthX: "{month}月"
yearX: "{year}年"
pages: "ページ"
integration: "つないで"
connectSerice: "つなげる"
disconnectSerice: "切ってまう"
enableLocalTimeline: "ローカルタイムラインを使えるようにする"
enableGlobalTimeline: "グローバルタイムラインを使えるようにする"
disablingTimelinesInfo: "ここらへんのタイムラインを使えんようにしてしもても、管理者とモデレーターは使えるままになってるで、そうやなかったら不便やからな。"
registration: "登録"
enableRegistration: "一見さんでも誰でもいらっしゃ~い"
invite: "来てや"
proxyRemoteFiles: "リモートのファイルをプロキシする"
proxyRemoteFilesDescription: "この設定を入れると、保存しとらんかったり、お腹いっぱいになってしもたせいで保存できんかったリモートファイルをローカルでプロキシして、サムネイル作ってもらうことができるで。サーバーの腹具合には影響せんけどな。"
driveCapacityPerLocalAccount: "ローカルユーザーひとりあたりのドライブ容量"
driveCapacityPerRemoteAccount: "リモートユーザーひとりあたりのドライブ容量"
inMb: "メガバイト単位"
avoidMultiCaptchaConfirm: "ぎょうさんのCaptchaをつこてしまうと、仲良うせんことがあるんや。他のCaptchaをなおしとこか別にキャンセルしてもろうたらCaptchaは消されへんで済むけど知らんで。"
antennas: "アンテナ"
manageAntennas: "アンテナいじる"
name: "名前"
antennaSource: "受信ソース(このソースは食われへん)"
antennaKeywords: "受信キーワード"
antennaExcludeKeywords: "除外キーワード"
antennaKeywordsDescription: "スペースで区切ったるとAND指定で、改行で区切ったるとOR指定や"
notifyAntenna: "新しいノートを追加すんで"
withFileAntenna: "なんか添付されたノートだけ"
serviceworker: "ServiceWorker"
enableServiceworker: "ServiceWorkerをつこて"
antennaUsersDescription: "ユーザー名を改行で区切ったってな"
caseSensitive: "大文字と小文字は別もんや"
withReplies: "返信も入れたって"
connectedTo: "次のアカウントに繋がっとるで"
notesAndReplies: "投稿と返信"
withFiles: "ファイル付いとる"
silence: "サイレンス"
silenceConfirm: "サイレンスしよか?"
unsilence: "サイレンスやめるで"
unsilenceConfirm: "サイレンスやめよか?"
popularUsers: "人気のユーザー"
recentlyUpdatedUsers: "ちょっと前に投稿したばっかりのユーザー"
recentlyRegisteredUsers: "ちょっと前に始めたばっかりのユーザー"
recentlyDiscoveredUsers: "最近見っけたユーザー"
exploreUsersCount: "{count}もユーザーおるで"
exploreFediverse: "Fediverseを探ってみる"
popularTags: "人気のタグ"
userList: "リスト"
about: "情報"
aboutMisskey: "Misskeyってなんや"
aboutMisskeyText: "Misskeyはsyuiloいう人が2014年からずっと作ってはる、オープンソースなソフトウェアや。"
misskeyMembers: "今んとここんだけのメンバーが作って、メンテナンスしてはる:"
misskeySource: "ソースコードはこっから見てな:"
misskeyTranslation: "Misskeyの翻訳手伝うてくれへん:"
misskeyDonate: "Misskeyにお金あげたら開発のサポートになるで:"
morePatrons: "他にもぎょうさんの人からサポートしてもろてんねん。ほんまおおきに🥰"
patrons: "支援者"
administrator: "管理者"
token: "トークン"
twoStepAuthentication: "二段階認証"
moderator: "モデレーター"
nUsersMentioned: "{n}人が投稿"
securityKey: "セキュリティキー"
securityKeyName: "キーの名前"
registerSecurityKey: "セキュリティキーを登録するで"
lastUsed: "最後につこうた日"
unregister: "登録やめる"
passwordLessLogin: "パスワード無くてもログインできるようにする"
resetPassword: "パスワードをリセット"
newPasswordIs: "今度のパスワードは「{password}」や"
autoReloadWhenDisconnected: "サーバーが調子悪いときには自動でリロードしたる"
notFoundDescription: "指定されたURLに該当するページはあらへんやった。"
close: "さいなら"
joinedGroups: "参加しとるグループ"
invites: "来てや"
_theme:
keys:
renote: "Renote"
_sfx:
note: "ノート"
notification: "通知"
chat: "チャット"
_ago:
unknown: "謎"
future: "未来"
@ -142,6 +385,7 @@ _antennaSources:
_widgets:
notifications: "通知"
timeline: "タイムライン"
activity: "アクティビティ"
_cw:
show: "もっとあるやろ!"
_poll:
@ -149,14 +393,27 @@ _poll:
deadlineTime: "時間"
_visibility:
publicDescription: "みなのユーザーに公開"
home: "ホーム"
followers: "フォロワー"
_profile:
name: "名前"
username: "ユーザー名"
_exportOrImport:
allNotes: "全てのノート"
followingList: "フォロー"
muteList: "ミュート"
blockingList: "ブロック"
userLists: "リスト"
_timelines:
home: "ホーム"
_rooms:
_roomType:
default: "デフォルト"
_furnitures:
monitor: "モニター"
_pages:
blocks:
image: "画像"
script:
categories:
list: "リスト"
@ -175,3 +432,12 @@ _pages:
arg1: "リスト"
types:
array: "リスト"
_notification:
youWereFollowed: "フォローされたで"
_deck:
_columns:
notifications: "通知"
tl: "タイムライン"
antenna: "アンテナ"
list: "リスト"
mentions: "あんた宛て"

86
locales/kab-KAB.yml Normal file
View File

@ -0,0 +1,86 @@
---
_lang_: "Taqbaylit"
monthAndDay: "{day}/{month}"
search: "Nadi"
notifications: "Ilɣuyen"
username: "Isem n umseqdac"
password: "Awal uffir"
ok: "IH"
settings: "Iɣewwaṛen"
profile: "Amaɣnu"
save: "Sekles"
delete: "Kkes"
addToList: "Rnu ɣer tebdart"
reply: "Err"
loadMore: "Wali ugar"
youGotNewFollower: "Yeṭṭafaṛ-ik·em-id"
mention: "Bder"
import: "Kter"
export: "Sifeḍ"
files: "Ifuyla"
download: "Sider"
lists: "Tibdarin"
noLists: "Ulac ɣur-k·m ula d yiwet n tabdart"
following: "Ig ṭṭafaṛ"
followers: "Imeḍfaṛen"
followsYou: "Yeṭṭafaṛ-ik·em-id"
createList: "Snulfu-d tabdart"
enterListName: "Isem n tebdart"
follow: "Ḍfeṛ"
you: "Kečči·mmi"
selectList: "Fren tabdart"
youHaveNoLists: "Ulac ɣur-k·m ula d yiwet n tabdart"
remove: "Kkes"
userList: "Tibdarin"
uiLanguage: "Tutlayt n wegrudem"
_theme:
keys:
mention: "Bder"
_sfx:
notification: "Ilɣuyen"
_widgets:
notifications: "Ilɣuyen"
_cw:
show: "Wali ugar"
_visibility:
followers: "Imeḍfaṛen"
_profile:
username: "Isem n umseqdac"
_exportOrImport:
followingList: "Ig ṭṭafaṛ"
muteList: "Sgugem"
blockingList: "Seḥbes"
userLists: "Tibdarin"
_pages:
font: "Tasefsit"
fontSerif: "Serif"
fontSansSerif: "Sans Serif"
eyeCatchingImageRemove: "Kkes tugna i d-ijebden"
selectType: "Fren anaw"
contentBlocks: "Agbur"
inputBlocks: "Anekcum"
specialBlocks: "Uzzig"
script:
categories:
list: "Tibdarin"
blocks:
_join:
arg1: "Tibdarin"
_randomPick:
arg1: "Tibdarin"
_dailyRandomPick:
arg1: "Tibdarin"
_seedRandomPick:
arg2: "Tibdarin"
_pick:
arg1: "Tibdarin"
_listLen:
arg1: "Tibdarin"
types:
array: "Tibdarin"
_notification:
youWereFollowed: "Yeṭṭafaṛ-ik·em-id"
_deck:
_columns:
notifications: "Ilɣuyen"
list: "Tibdarin"

View File

@ -63,3 +63,10 @@ _cw:
show: "ಇನ್ನಷ್ಟು ನೋಡು"
_profile:
username: "ಬಳಕೆಹೆಸರು"
_notification:
youWereFollowed: "ಹಿಂಬಾಲಿಸಿದರು"
_deck:
_columns:
notifications: "ಅಧಿಸೂಚನೆಗಳು"
tl: "ಸಮಯಸಾಲು"
mentions: "ಹೆಸರಿಸಿದ"

View File

@ -45,6 +45,7 @@ loadMore: "더 보기"
youGotNewFollower: "새로운 팔로워가 있습니다"
receiveFollowRequest: "새로운 팔로우 요청이 있습니다"
followRequestAccepted: "팔로우가 수락되었습니다"
mention: "멘션"
mentions: "받은 멘션"
directNotes: "다이렉트 노트"
importAndExport: "가져오기와 내보내기"
@ -104,6 +105,7 @@ suspendConfirm: "이 계정을 정지하시겠습니까?"
unsuspendConfirm: "이 계정의 정지를 해제하시겠습니까?"
selectList: "리스트 선택"
customEmojis: "커스텀 이모지"
emoji: "이모지"
emojiName: "이모지 이름"
emojiUrl: "이모지 URL"
addEmoji: "이모지 추가"
@ -499,9 +501,19 @@ removeAllFollowingDescription: "{host}(으)로부터 모든 팔로잉을 해제
userSuspended: "이 계정은 정지된 상태입니다."
userSilenced: "이 계정은 사일런스된 상태입니다."
sidebar: "사이드바"
divider: "분선"
divider: "분선"
addItem: "항목 추가"
rooms: "방"
relays: "릴레이"
addRelay: "릴레이 추가"
inboxUrl: "Inbox 주소"
addedRelays: "추가된 릴레이"
serviceworkerInfo: "푸시 알림을 수행하려면 활성화해야 합니다."
deletedNote: "삭제된 노트"
invisibleNote: "비공개 노트"
visibility: "공개 범위"
poll: "투표"
useCw: "내용 숨기기"
_theme:
explore: "테마 찾아보기"
install: "테마 설치"
@ -510,6 +522,12 @@ _theme:
installed: "{name} 테마가 설치되었습니다"
alreadyInstalled: "이미 설치된 테마입니다"
invalid: "테마 형식이 올바르지 않습니다"
defaultValue: "기본값"
func: "함수"
keys:
mention: "멘션"
renote: "Renote"
divider: "구분선"
_sfx:
note: "새 노트"
noteMy: "내 노트"
@ -628,7 +646,6 @@ _cw:
show: "더 보기"
chars: "{count} 문자"
files: "{count} 파일"
poll: "투표"
_poll:
noOnlyOneChoice: "투표 항목이 최소 2개 필요합니다"
choiceN: "선택지 {n}"
@ -661,6 +678,7 @@ _visibility:
specified: "다이렉트"
specifiedDescription: "지정한 유저에게만 공개"
localOnly: "로컬에만"
localOnlyDescription: "리모트 유저에게 보이지 않기"
_postForm:
replyPlaceholder: "이 노트에 답글..."
quotePlaceholder: "이 노트를 인용..."
@ -776,6 +794,8 @@ _rooms:
cup-noodle: "컵라면"
holo-display: "홀로그램"
energy-drink: "에너지 드링크"
doll-ai: "아이쨩 인형"
banknote: "지폐뭉치"
_pages:
newPage: "페이지 만들기"
editPage: "페이지 수정"
@ -1057,3 +1077,26 @@ _pages:
enviromentVariables: "환경 변수"
pageVariables: "페이지 요소"
argVariables: "입력 슬롯"
_relayStatus:
requesting: "대기 중"
accepted: "승인됨"
rejected: "거절됨"
_notification:
fileUploaded: "파일이 업로드되었습니다"
youGotMention: "{name}님이 멘션함"
youGotReply: "{name}님이 답글함"
youGotQuote: "{name}님이 인용함"
youRenoted: "{name}님이 Renote"
youGotPoll: "{name}님이 투표함"
youWereFollowed: "새로운 팔로워가 있습니다"
youReceivedFollowRequest: "새로운 팔로우 요청이 있습니다"
yourFollowRequestAccepted: "팔로우 요청이 수락되었습니다"
youWereInvitedToGroup: "그룹에 초대되었습니다"
_deck:
_columns:
notifications: "알림"
tl: "타임라인"
antenna: "안테나"
list: "리스트"
mentions: "받은 멘션"
direct: "다이렉트"

View File

@ -1,9 +1,13 @@
---
_lang_: "Русский язык"
introMisskey: "Добро пожаловать! Misskey - это децентрализованный сервис микроблогов с открытым исходным кодом.\nСоздавайте «записи», чтобы поделиться происходящим или рассказать всем о себе 📡\nТакже Вы можете добавить быструю реакцию на все записи с помощью функции «реакция» 👍\nОткройте для себя новый мир 🚀"
monthAndDay: "{day}.{month}"
search: "Поиск"
notifications: "Уведомления"
password: "Пароль"
fetchingAsApObject: "Запрос на федерацию"
ok: "Окей"
gotIt: "Отлично"
cancel: "Отмена"
instance: "Экземпляр"
settings: "Настройки"
@ -34,3 +38,7 @@ _widgets:
timeline: "Лента"
_cw:
show: "Показать еще"
_deck:
_columns:
notifications: "Уведомления"
tl: "Лента"

3
locales/ug-CN.yml Normal file
View File

@ -0,0 +1,3 @@
---
_lang_: "ياپونچە"
search: "ئىزدەش"

View File

@ -1,6 +1,6 @@
---
_lang_: "中文(简体)"
introMisskey: "欢迎Misskey是一个开源的分散型SNS服务。\n通过「帖」来分享现在发生的事情吧!📡\n「反应」功能,可以让你快速对大家的「帖子」来表达感情👍\n一起来探索新的世界吧!🚀"
introMisskey: "欢迎Misskey是一个开源的、去中心化的“微博客”服务。\n通过编写「帖」来和大家分享你的以及你周围的事情吧!📡\n通过「回应」功能,可以让你快速对大家的帖文表达反馈👍\n来探索新的世界吧🚀"
monthAndDay: "{month}月 {day}日"
search: "搜索"
notifications: "通知"
@ -11,8 +11,8 @@ ok: "OK"
gotIt: "我明白了"
cancel: "取消"
enterUsername: "输入用户名"
renotedBy: "{user} 转贴"
noNotes: "没有投稿"
renotedBy: "{user} 转贴"
noNotes: "没有帖文"
noNotifications: "无通知"
instance: "实例"
settings: "设置"
@ -35,18 +35,19 @@ unpin: "取消置顶"
copyContent: "复制内容"
copyLink: "复制链接"
delete: "删除"
deleteAndEdit: "删除编辑"
deleteAndEditConfirm: "要删除此帖并再次编辑吗?对此帖的所有回应,转推和回复也将被删除。"
deleteAndEdit: "删除编辑"
deleteAndEditConfirm: "要删除此帖并再次编辑吗?对此帖的所有回应、转发和回复也将被删除。"
addToList: "添加至列表"
sendMessage: "发送"
copyUsername: "复制用户名"
reply: "回复"
loadMore: "查看更多"
youGotNewFollower: "你有新的关注者"
receiveFollowRequest: "收到关注请求"
followRequestAccepted: "同意关注请求"
mentions: "提及"
directNotes: "指定用户可见"
receiveFollowRequest: "收到关注请求"
followRequestAccepted: "您的关注请求被通过了"
mention: "提及"
mentions: "提到我的"
directNotes: "私信"
importAndExport: "导入和导出"
import: "导入"
export: "导出"
@ -104,6 +105,7 @@ suspendConfirm: "要冻结吗?"
unsuspendConfirm: "要解除冻结吗?"
selectList: "选择列表"
customEmojis: "自定义Emoji"
emoji: "表情符号"
emojiName: "Emoji 名称"
emojiUrl: "emoji 地址"
addEmoji: "添加Emoji"
@ -235,7 +237,7 @@ light: "浅色"
dark: "深色"
lightThemes: "亮色主题"
darkThemes: "暗色主题"
syncDeviceDarkMode: "将深色模式与系统设置同步"
syncDeviceDarkMode: "将深色模式与设备设置同步"
drive: "网盘"
fileName: "文件名称"
selectFile: "选择文件"
@ -502,6 +504,27 @@ sidebar: "侧边栏"
divider: "分割线"
addItem: "添加项"
rooms: "房间"
relays: "中继"
addRelay: "添加中继"
inboxUrl: "Inbox URL"
addedRelays: "已添加的中继"
serviceworkerInfo: "您需要启用推送通知"
deletedNote: "已删除的帖子"
invisibleNote: "隐藏的帖子"
enableInfiniteScroll: "启用自动滚动页面模式"
visibility: "可见性"
poll: "调查问卷"
useCw: "隐藏内容"
fixedWidgetsPosition: "固定小工具的位置"
enablePlayer: "打开播放器"
disablePlayer: "关闭播放器"
expandTweet: "展开推文"
themeEditor: "主题编辑器"
description: "描述"
author: "作者"
leaveConfirm: "存在未保存的更改。要放弃更改吗?"
deck: "Deck"
undeck: "取消Deck"
_theme:
explore: "寻找主题"
install: "安装主题"
@ -510,6 +533,18 @@ _theme:
installed: "{name} 已安装"
alreadyInstalled: "此主题已经安装"
invalid: "主题格式错误"
make: "主题制作"
constant: "常量"
defaultValue: "默认值"
color: "颜色"
func: "函数"
alpha: "不透明度"
keys:
header: "页眉"
navBg: "侧边栏背景"
mention: "提及"
renote: "转发"
divider: "分割线"
_sfx:
note: "帖子"
noteMy: "我的帖子"
@ -538,7 +573,7 @@ _tutorial:
step1_1: "欢迎!"
step1_2: "这个页面叫做「时间线」,它会按照时间顺序显示所有你「关注」的人所发的「帖子」。"
step1_3: "如果你并没有发布任何帖子,也没有关注其他的人,你的时间线页面应当什么都没有显示。"
step2_1: "在你想发布一些帖子之前,让我们先进行一下个人资料设置。"
step2_1: "在您想要发帖或关注其他人之前,请先设置一下个人资料。"
step2_2: "如果别人能够更加的了解你,关注你的概率也会得到提升。"
step3_1: "已经设置完个人资料了吗?"
step3_2: "那么接下来,试着写一些什么东西来发布吧。你可以通过点击屏幕上的铅笔图标来打开投稿页面。"
@ -623,12 +658,12 @@ _widgets:
rss: "RSS阅读器"
activity: "活动"
photos: "照片"
digitalClock: "数字时钟"
_cw:
hide: "隐藏"
show: "查看更多"
chars: "{count}个字符"
files: "{count} 个文件"
poll: "投票"
_poll:
noOnlyOneChoice: "需要至少两个选项"
choiceN: "选择{n}"
@ -661,6 +696,7 @@ _visibility:
specified: "指定用户"
specifiedDescription: "仅发送至指定用户"
localOnly: "仅限本地"
localOnlyDescription: "对远程用户不可见"
_postForm:
replyPlaceholder: "回复这个帖子..."
quotePlaceholder: "引用这个帖子..."
@ -776,6 +812,8 @@ _rooms:
cup-noodle: "杯面"
holo-display: "全息显示器"
energy-drink: "能量饮料"
doll-ai: "小蓝的玩偶"
banknote: "钞票"
_pages:
newPage: "创建页面"
editPage: "编辑页面"
@ -1057,3 +1095,31 @@ _pages:
enviromentVariables: "环境变量"
pageVariables: "页面元素"
argVariables: "输入变量"
_relayStatus:
requesting: "待批准"
accepted: "已批准"
rejected: "已拒绝"
_notification:
fileUploaded: "文件已上传"
youGotMention: "来自{name}的提及"
youGotReply: "来自{name}的回复"
youGotQuote: "来自{name}的引用"
youRenoted: "来自{name}的转发"
youGotPoll: "来自{name}的投票"
youGotMessagingMessageFromUser: "来自{name}的聊天"
youGotMessagingMessageFromGroup: "来自{name}的群聊"
youWereFollowed: "关注了你。"
youReceivedFollowRequest: "您有新的关注请求"
yourFollowRequestAccepted: "您的关注请求已通过"
youWereInvitedToGroup: "您有新的群组邀请"
_deck:
alwaysShowMainColumn: "总是显示主列"
columnAlign: "列对齐"
_columns:
widgets: "小部件"
notifications: "通知"
tl: "时间线"
antenna: "天线"
list: "列表"
mentions: "提到我的"
direct: "指定用户"

View File

@ -1,5 +1,6 @@
---
_lang_: "中文(繁体)"
_lang_: "中文(繁體)"
introMisskey: "歡迎! Misskey是一個開源的去中心化的社群網站。\n通過「貼文」來分享現在發生的事情吧 📡\n「反應」功能可以讓你快速的對大家的「帖子」來表達感情👍\n一起來探索新的世界吧 🚀"
monthAndDay: "{month}月 {day}日"
search: "搜尋"
notifications: "通知"
@ -11,8 +12,9 @@ gotIt: "知道了"
cancel: "取消"
enterUsername: "輸入用戶名"
renotedBy: "由{user}轉發"
noNotes: "沒有筆記"
noNotes: "貼文不可用。"
noNotifications: "沒有通知"
instance: "實例"
settings: "設定"
profile: "個人檔案"
timeline: "時間軸"
@ -33,29 +35,32 @@ unpin: "取消置頂"
copyContent: "複製內容"
copyLink: "複製連結"
delete: "刪除"
deleteAndEdit: "刪除並編輯"
deleteAndEditConfirm: "要刪除並再次編輯嗎?此貼文的所有反應,轉發和回覆也將會消失。"
addToList: "添加至清單"
sendMessage: "發送訊息"
copyUsername: "複製用戶名"
reply: "回覆"
loadMore: "載入更多"
loadMore: "瀏覽更多"
youGotNewFollower: "您有新的追隨者"
receiveFollowRequest: "收到追隨請求"
followRequestAccepted: "追隨請求已接受"
mention: "提及"
mentions: "提及"
importAndExport: "匯入 / 匯出"
import: "匯入"
export: "匯出"
files: "檔案"
download: "下載"
driveFileDeleteConfirm: "確定要刪除檔案「{name}」嗎?附加此檔案的筆記也會跟著不見。"
driveFileDeleteConfirm: "確定要刪除檔案「{name}」嗎?使用此附件的貼文也會跟著消失。"
unfollowConfirm: "確定要取消對{name}的追隨嗎?"
exportRequested: "已請求匯出。這可能會花一點時間。結束後檔案將會被放到雲端裡。"
importRequested: "已請求匯入。這可能會花一點時間"
lists: "清單"
noLists: "沒有清單"
note: "筆記"
note: "貼文"
notes: "筆記"
following: "關注中"
following: "追隨中"
followers: "追隨者"
followsYou: "追隨你的人"
createList: "建立清單"
@ -72,15 +77,16 @@ followRequests: "追隨請求"
unfollow: "取消追隨"
followRequestPending: "追隨許可批准中"
enterEmoji: "輸入表情符號"
renote: "轉發筆記"
unrenote: "取消轉發筆記"
renote: "轉發貼文"
unrenote: "取消轉發貼文"
quote: "引用"
pinnedNote: "已置頂筆記"
pinnedNote: "已置頂的貼文"
you: "您"
clickToShow: "點擊查看"
sensitive: "敏感內容"
add: "新增"
reaction: "反應"
reactionSettingDescription: "置頂「反應」表情符號\n"
rememberNoteVisibility: "記住筆記隱私設定"
attachCancel: "移除附件"
markAsSensitive: "標記為敏感內容"
@ -98,25 +104,29 @@ suspendConfirm: "確定凍結此帳號?"
unsuspendConfirm: "確定解凍此帳號?"
selectList: "選擇清單"
customEmojis: "自訂表情符號"
emoji: "表情符號"
emojiName: "表情符號名稱"
emojiUrl: "表情符號URL"
addEmoji: "新增表情符號"
settingGuide: "推介設定"
flagAsBot: "此帳戶是Bot"
flagAsCat: "此帳戶是Cat"
autoAcceptFollowed: "自動許可關注"
autoAcceptFollowed: "自動許可追隨"
addAcount: "新增帳戶"
loginFailed: "登入失敗"
general: "一般"
wallpaper: "壁紙"
setWallpaper: "設定桌布"
removeWallpaper: "移除壁紙"
searchWith: "搜尋: {q}"
youHaveNoLists: "你沒有任何清單"
followConfirm: "你真的要關注{name}嗎?"
followConfirm: "你真的要追隨{name}嗎?"
host: "主機"
selectUser: "選擇用戶"
recipient: "收件人"
annotation: "註解"
federation: "整合"
instances: "實例"
latestStatus: "最後狀態"
storageUsage: "已使用容量"
charts: "圖表"
@ -127,29 +137,39 @@ software: "軟體"
version: "版本"
withNFiles: "{n}個檔案"
monitor: "監視器"
cpuAndMemory: "CPU及記憶體用量"
network: "網路"
instanceInfo: "實例資訊"
statistics: "統計"
clearQueue: "清除佇列"
clearQueueConfirmTitle: "確定要清除佇列嗎?"
clearCachedFiles: "清除快取資料"
blockedInstances: "已封鎖的實例"
blockedInstancesDescription: "請逐行輸入需要封鎖的實例。已封鎖的實例將無法與本實例進行通訊。"
muteAndBlock: "禁言 / 封鎖"
mutedUsers: "已禁言用戶"
blockedUsers: "已封鎖用戶"
noUsers: "無用戶"
editProfile: "編輯個人檔案"
noteDeleteConfirm: "確定刪除此筆記嗎?"
pinLimitExceeded: "不能再置頂更多筆記了"
noteDeleteConfirm: "確定刪除此貼文嗎?"
pinLimitExceeded: "不能再置頂更多的貼文了"
intro: "Misskey安裝作業完成請創立管理員用戶"
done: "完成"
processing: "處理中"
preview: "預覽"
default: "預設"
noCustomEmojis: "沒有表情符號"
customEmojisOfRemote: "來自其他實例的表情符號"
federating: "整合檢索中"
blocked: "已封鎖"
suspended: "已凍結"
all: "全部"
subscribing: "訂閱中"
publishing: "現正直播"
notResponding: "沒有回應"
instanceFollowing: "追蹤實例"
instanceFollowers: "追蹤實例"
instanceUsers: "用戶"
changePassword: "修改密碼"
security: "安全性"
retypedNotMatch: "不相符的輸入內容"
@ -171,6 +191,8 @@ messaging: "傳送訊息"
upload: "上傳"
fromDrive: "從雲端"
fromUrl: "從URL"
uploadFromUrl: "從網址上傳"
uploadFromUrlMayTakeTime: "還需要一些時間才能完成上傳。"
explore: "探索"
games: "Misskey 遊戲"
messageRead: "已讀"
@ -181,23 +203,33 @@ tos: "使用條款"
start: "開始"
home: "首頁"
activity: "動態"
images: "圖片"
birthday: "生日"
yearsOld: "{age}歲"
registeredDate: "註冊日期"
location: "位置"
theme: "外觀主題"
light: "淺色"
dark: "灰暗"
lightThemes: "明亮主題"
darkThemes: "灰暗主題"
drive: "雲端硬碟"
fileName: "檔案名稱"
selectFile: "選擇檔案"
selectFiles: "選擇檔案"
selectFolder: "選擇資料夾"
selectFolders: "選擇資料夾"
renameFile: "重新命名檔案"
folderName: "資料夾名稱"
createFolder: "新增資料夾"
renameFolder: "重新命名資料夾"
deleteFolder: "刪除資料夾"
addFile: "添加檔案"
emptyDrive: "雲端硬碟為空"
emptyFolder: "空的資料夾"
unableToDelete: "無法刪除"
inputNewFileName: "輸入檔案名稱"
inputNewFolderName: "輸入新資料夾的名稱"
copyUrl: "複製URL"
rename: "重新命名"
avatar: "頭像"
@ -208,9 +240,12 @@ reload: "重新載入"
doNothing: "無視"
reloadConfirm: "確定要重新嘗試嗎?"
watch: "關注"
unwatch: "取消關注"
unwatch: "取消追隨"
accept: "接受"
reject: "拒絕"
normal: "正常"
instanceName: "實例名稱"
instanceDescription: "實例描述"
maintainerName: "管理員名稱"
maintainerEmail: "管理員信箱"
tosUrl: "服務條款URL"
@ -221,6 +256,7 @@ dayX: "{day}天"
monthX: "{month}月"
yearX: "{year}年"
pages: "頁面"
integration: "整合"
connectSerice: "連線"
disconnectSerice: "中斷連線"
enableLocalTimeline: "開啟本地時間軸"
@ -230,11 +266,14 @@ enableRegistration: "開啟新用戶註冊"
invite: "邀請"
proxyRemoteFiles: "代理遠程檔案"
driveCapacityPerLocalAccount: "每個本地用戶的雲端容量"
driveCapacityPerRemoteAccount: "每個非本地用戶的雲端容量"
inMb: "以Mbps為單位"
iconUrl: "圖像URL"
bannerUrl: "橫幅圖片URL"
basicInfo: "基本資訊"
pinnedUsers: "置頂用戶"
hcaptcha: "hCaptcha"
enableHcaptcha: "啟用 hCaptcha"
hcaptchaSiteKey: "網站金鑰"
hcaptchaSecretKey: "金鑰"
recaptcha: "reCAPTCHA"
@ -242,6 +281,9 @@ enableRecaptcha: "啟用 reCAPTCHA"
recaptchaSiteKey: "網站金鑰"
recaptchaSecretKey: "金鑰"
name: "名稱"
antennaKeywords: "包含的關鍵字"
antennaExcludeKeywords: "排除關鍵字"
notifyAntenna: "通知我有新的貼文"
serviceworker: "ServiceWorker"
enableServiceworker: "開啟 ServiceWorker"
caseSensitive: "區分大小寫"
@ -249,26 +291,46 @@ notesAndReplies: "貼文與回覆"
withFiles: "附件"
silence: "禁言"
silenceConfirm: "確定要禁言此用戶嗎?"
unsilence: "解除禁言"
unsilenceConfirm: "確定要解除禁言嗎?"
popularUsers: "熱門用戶"
recentlyUpdatedUsers: "最近發文的用戶"
recentlyRegisteredUsers: "新加入用戶"
recentlyDiscoveredUsers: "最近發現的用戶"
exploreUsersCount: "有{count}個用戶"
exploreFediverse: "探索聯邦世界"
popularTags: "熱門標籤"
userList: "清單"
about: "資訊"
aboutMisskey: "關於 Misskey"
misskeyTranslation: "幫助我們為Misskey的翻譯工作出一分力"
misskeyDonate: "向Misskey捐款以支援我們開發工作"
morePatrons: "感激你們的支持、 幫助。 🥰"
patrons: "贊助者"
administrator: "管理員"
token: "令牌"
twoStepAuthentication: "雙重身份驗證"
moderator: "板主"
nUsersMentioned: "提到了{n}"
securityKey: "安全金鑰"
securityKeyName: "金鑰名稱"
registerSecurityKey: "註冊安全金鑰"
lastUsed: "最後活躍時間"
unregister: "刪除賬戶"
passwordLessLogin: "設置無密碼登入"
resetPassword: "重置密碼"
newPasswordIs: "新密碼為「{password}」"
autoReloadWhenDisconnected: "和伺服器斷線時自動重新載入"
autoNoteWatch: "自動關注筆記"
autoNoteWatchDescription: "收到反應或回覆過的筆記的通知"
autoNoteWatch: "自動追隨貼文"
autoNoteWatchDescription: "收到反應或回覆過的貼文的通知"
reduceUiAnimation: "減少介面的動態視覺"
share: "分享"
notFound: "找不到"
notFoundDescription: "找不到與指定URL回應的頁面"
uploadFolder: "預設上傳資料夾"
cacheClear: "清除暫存"
cacheClear: "清除快取"
markAsReadAllNotifications: "標記所有通知為已讀"
markAsReadAllUnreadNotes: "標記所有筆記為已讀"
markAsReadAllUnreadNotes: "標記所有貼文為已讀"
markAsReadAllTalkMessages: "標記所有訊息為已讀"
help: "幫助"
inputMessageHere: "在此輸入訊息"
@ -288,9 +350,9 @@ text: "文字"
enable: "啟用"
next: "下一步"
retype: "重新輸入"
noteOf: "{user}的筆記"
noteOf: "{user}的貼文"
inviteToGroup: "邀請至群組"
maxNoteTextLength: "筆記的字數限制"
maxNoteTextLength: "貼文的字數限制"
quoteAttached: "引用"
quoteQuestion: "是否要引用?"
noMessagesYet: "沒有訊息"
@ -303,12 +365,43 @@ available: "可用的"
unavailable: "不可用的"
usernameInvalidFormat: "可使用大小寫英文字母、數字和底線"
tooShort: "過短"
tooLong: "過長"
weakPassword: "密碼強度過弱"
normalPassword: "密碼強度普通"
strongPassword: "密碼強度堅強"
passwordMatched: "密碼一致"
passwordNotMatched: "密碼不一致"
signinFailed: "登入失敗。 請檢查用戶名和密碼。"
uiLanguage: "介面語言"
tags: "標籤"
fontSize: "字體大小"
total: "合計"
clinetSettings: "用戶端設定"
serverLogs: "伺服器日誌"
deleteAll: "刪除所有記錄"
none: "無"
volume: "音量"
details: "詳細資訊"
chooseEmoji: "選擇您的表情符號\n"
unableToProcess: "操作無法完成"
recentUsed: "最近使用"
install: "安裝"
uninstall: "解除安裝"
lastUsedDate: "最後上線日期"
state: "狀態"
output: "輸出"
deleteAllFiles: "刪除所有檔案"
deleteAllFilesConfirm: "要删除所有檔案吗?"
userSilenced: "該用戶已被禁言。"
deletedNote: "已删除的貼文"
_theme:
func: "函数"
keys:
mention: "提及"
renote: "轉發貼文"
_sfx:
note: "筆記"
noteMy: "我的筆記"
note: "貼文"
noteMy: "我的貼文"
notification: "通知"
chat: "傳送訊息"
_ago:
@ -330,7 +423,7 @@ _time:
_tutorial:
title: "Misskey使用方法"
step1_1: "歡迎!"
step1_2: "此為「時間軸」頁面,它會按照時間順序顯示你「追隨」的人的「筆記」"
step1_2: "此為「時間軸」頁面,它會按照時間順序顯示你「追隨」的人的「貼文」"
step1_3: "由於你沒有發布任何筆記,也沒有追隨任何人,所以你的時間軸目前是空的。"
step2_1: "在發文或追隨其他人之前先讓我們設定一下個人資料吧。"
step2_2: "提供一些關於自己的資訊來讓其他人更有追隨你的意願。"
@ -339,7 +432,7 @@ _tutorial:
step3_3: "輸入完內容後,按視窗右上角的按鈕來發文"
step3_4: "不知道該寫什麼內容嗎試試看「開始使用Misskey了」如何。"
step4_1: "筆記發出去了嗎?"
step4_2: "如果你的筆記有顯示在時間軸上,就代表已經發文成功。"
step4_2: "如果你的貼文有顯示在時間軸上,就代表已經發文成功。"
step5_1: "現在試試看追隨其他人來讓你的時間軸變得更生動吧。"
step5_3: "想要追隨其他人,只要點擊他們的頭像並按「追隨」即可。"
step5_4: "如果使用者的名字旁有鎖頭的圖示,代表他們需要手動核准你的追隨請求。"
@ -348,14 +441,41 @@ _tutorial:
step6_3: "在他人的貼文按下「+」的圖示即可選擇想要的表情符號來進行「反應」。"
step7_1: "以上為Misskey的基本操作說明教學在此告一段落。辛苦了。"
step7_2: "歡迎到{help}來瞭解更多Misskey相關介紹。"
_permissions:
"read:blocks": "已封鎖用戶名單"
"write:blocks": "編輯已封鎖用戶名單"
"read:drive": "存取雲端硬碟\n"
"write:drive": "編輯雲端硬碟的檔案"
"read:favorites": "瀏覽已收藏"
"write:favorites": "編輯收藏清單"
"write:following": "追隨/解除追隨"
"write:notes": "撰寫或刪除貼文"
"read:notifications": "查看通知"
"read:reactions": "查看反應"
"write:reactions": "編輯反應"
"write:votes": "投票"
_weekday:
sunday: "週日"
monday: "週一"
tuesday: "週二"
wednesday: "週三"
thursday: "週四"
friday: "週五"
saturday: "週六"
_widgets:
notifications: "通知"
timeline: "時間軸"
clock: "時鐘"
rss: "RSS閱讀器"
activity: "動態"
photos: "照片"
_cw:
show: "載入更多"
show: "瀏覽更多"
files: "{count} 個檔案"
_poll:
deadlineTime: "小時"
vote: "投票"
voted: "已投票"
_visibility:
home: "首頁"
followers: "追隨者"
@ -363,31 +483,183 @@ _profile:
name: "名稱"
username: "用戶名"
_exportOrImport:
followingList: "關注中"
followingList: "追隨中"
muteList: "禁言"
blockingList: "封鎖"
userLists: "清單"
_instanceCharts:
cacheSize: "增加或減少快取用量"
cacheSizeTotal: "快取大小總計"
_timelines:
home: "首頁"
_rooms:
_roomType:
default: "預設"
_furnitures:
monitor: "監視器"
keyboard: "鍵盤"
_pages:
deleted: "頁面已被刪除"
like: "喜歡"
unlike: "收回喜歡"
blocks:
image: "圖片"
_textareaInput:
name: "變數名稱"
numberInput: "輸入數值"
_numberInput:
name: "變數名稱"
_canvas:
width: "寬度"
_counter:
text: "標題"
_button:
text: "標題"
script:
categories:
value: "數值 "
fn: "函数"
text: "文本操作"
convert: "轉換"
list: "清單"
blocks:
text: "文本"
multiLineText: "文本 (多行)"
textList: "文本列表"
_strPick:
arg1: "文本"
arg2: "字元位置"
_strReplace:
arg1: "文本"
_strReverse:
arg1: "本文"
_join:
arg1: "清單"
add: "加"
_add:
arg1: "A"
arg2: "B"
_subtract:
arg1: "A"
arg2: "B"
_multiply:
arg1: "A"
arg2: "B"
_divide:
arg1: "A"
arg2: "B"
_mod:
arg1: "A"
arg2: "B"
_round:
arg1: "數值"
eq: "A和B相等"
_eq:
arg1: "A"
arg2: "B"
notEq: "A和B不等"
_notEq:
arg1: "A"
arg2: "B"
and: "A和B"
_and:
arg1: "A"
arg2: "B"
or: "A或B"
_or:
arg1: "A"
arg2: "B"
lt: "< A小於B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A大於B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A小於或等於B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A大於或等於B"
_gtEq:
arg1: "A"
arg2: "B"
if: "分支"
_if:
arg1: "如果"
arg2: "如果"
not: "否"
_not:
arg1: "否"
_random:
arg1: "機率"
rannum: "亂數"
_rannum:
arg1: "下限"
arg2: "上限"
_randomPick:
arg1: "清單"
_dailyRandom:
arg1: "機率"
_dailyRannum:
arg1: "下限"
arg2: "上限"
_dailyRandomPick:
arg1: "清單"
seedRandom: "隨機抽選種子碼"
_seedRandom:
arg1: "種子"
arg2: "機率"
seedRannum: "亂數 (種子)"
_seedRannum:
arg1: "種子"
arg2: "最小值"
arg3: "最大值"
seedRandomPick: "從列表中隨機選擇 (種子)"
_seedRandomPick:
arg1: "種子"
arg2: "清單"
_DRPWPM:
arg1: "文本列表"
pick: "從清單中選取"
_pick:
arg1: "清單"
arg2: "位置"
listLen: "取得清單長度"
_listLen:
arg1: "清單"
number: "數值"
_stringToNumber:
arg1: "文字"
_numberToString:
arg1: "數值"
ref: "變數"
aiScriptVar: "AiScript的變數"
fn: "函数"
_fn:
slots: "欄位"
arg1: "輸出"
_for:
arg1: "重複次數"
arg2: "處理"
types:
string: "文字"
number: "数值"
array: "清單"
stringArray: "文本列表"
enviromentVariables: "環境變數"
_relayStatus:
requesting: "等待核准"
accepted: "已通過核准"
rejected: "已拒絕"
_notification:
youGotPoll: "{name}已投票"
youWereFollowed: "您有新的追隨者"
yourFollowRequestAccepted: "您的追隨請求已通過"
_deck:
_columns:
notifications: "通知"
tl: "時間軸"
list: "清單"
mentions: "提及"

View File

@ -1,7 +1,7 @@
{
"name": "misskey",
"author": "syuilo <syuilotan@yahoo.co.jp>",
"version": "12.37.0",
"version": "12.41.0",
"codename": "indigo",
"repository": {
"type": "git",
@ -31,36 +31,37 @@
"chokidar": "^3.3.1",
"constantinople": "^4.0.1",
"core-js": "^3.6.5",
"lodash": "^4.17.15",
"mocha": "^7.1.1"
"gulp/gulp-cli/yargs/yargs-parser": "5.0.0-security.0",
"lodash": "^4.17.19",
"mocha/serialize-javascript": "^3.1.0"
},
"dependencies": {
"@babel/plugin-transform-runtime": "7.9.6",
"@elastic/elasticsearch": "7.6.1",
"@fortawesome/fontawesome-svg-core": "1.2.28",
"@fortawesome/free-brands-svg-icons": "5.13.0",
"@fortawesome/free-regular-svg-icons": "5.13.0",
"@fortawesome/free-solid-svg-icons": "5.13.0",
"@fortawesome/vue-fontawesome": "0.1.9",
"@juggle/resize-observer": "3.1.3",
"@koa/cors": "3.0.0",
"@koa/multer": "2.0.2",
"@koa/router": "8.0.8",
"@babel/plugin-transform-runtime": "7.10.3",
"@elastic/elasticsearch": "7.8.0",
"@fortawesome/fontawesome-svg-core": "1.2.29",
"@fortawesome/free-brands-svg-icons": "5.13.1",
"@fortawesome/free-regular-svg-icons": "5.13.1",
"@fortawesome/free-solid-svg-icons": "5.13.1",
"@fortawesome/vue-fontawesome": "0.1.10",
"@juggle/resize-observer": "3.2.0",
"@koa/cors": "3.1.0",
"@koa/multer": "3.0.0",
"@koa/router": "9.3.1",
"@sinonjs/fake-timers": "6.0.1",
"@syuilo/aiscript": "0.6.1",
"@syuilo/aiscript": "0.7.2",
"@types/bcryptjs": "2.4.2",
"@types/bull": "3.12.2",
"@types/bull": "3.14.0",
"@types/cbor": "5.0.0",
"@types/dateformat": "3.0.1",
"@types/double-ended-queue": "2.1.1",
"@types/escape-regexp": "0.0.0",
"@types/glob": "7.1.1",
"@types/glob": "7.1.3",
"@types/gulp": "4.0.6",
"@types/gulp-rename": "0.0.33",
"@types/gulp-replace": "0.0.31",
"@types/is-url": "1.2.28",
"@types/js-yaml": "3.12.3",
"@types/jsdom": "16.2.1",
"@types/js-yaml": "3.12.5",
"@types/jsdom": "16.2.3",
"@types/jsonld": "1.5.1",
"@types/katex": "0.11.0",
"@types/koa": "2.11.3",
@ -76,19 +77,19 @@
"@types/koa__router": "8.0.2",
"@types/markdown-it": "10.0.1",
"@types/mocha": "7.0.2",
"@types/node": "13.13.5",
"@types/node": "14.0.22",
"@types/node-fetch": "2.5.7",
"@types/nodemailer": "6.4.0",
"@types/nprogress": "0.2.0",
"@types/oauth": "0.9.1",
"@types/parse5": "5.0.2",
"@types/parsimmon": "1.10.1",
"@types/parse5": "5.0.3",
"@types/parsimmon": "1.10.2",
"@types/portscanner": "2.1.0",
"@types/pug": "2.0.4",
"@types/qrcode": "1.3.4",
"@types/random-seed": "0.3.3",
"@types/ratelimiter": "2.1.28",
"@types/redis": "2.8.20",
"@types/redis": "2.8.25",
"@types/rename": "1.0.1",
"@types/request-stats": "3.0.0",
"@types/rimraf": "3.0.0",
@ -98,42 +99,43 @@
"@types/speakeasy": "2.0.5",
"@types/tinycolor2": "1.4.2",
"@types/tmp": "0.2.0",
"@types/uuid": "7.0.3",
"@types/uuid": "8.0.0",
"@types/web-push": "3.3.0",
"@types/webpack": "4.41.12",
"@types/webpack-stream": "3.2.10",
"@types/websocket": "1.0.0",
"@types/ws": "7.2.4",
"@typescript-eslint/parser": "2.31.0",
"@types/webpack": "4.41.18",
"@types/webpack-stream": "3.2.11",
"@types/websocket": "1.0.1",
"@types/ws": "7.2.6",
"@typescript-eslint/parser": "3.6.0",
"abort-controller": "3.0.0",
"apexcharts": "3.19.0",
"apexcharts": "3.19.3",
"autobind-decorator": "2.4.0",
"autosize": "4.0.2",
"autwh": "0.1.0",
"aws-sdk": "2.673.0",
"aws-sdk": "2.713.0",
"bcryptjs": "2.4.3",
"bull": "3.14.0",
"bull": "3.15.0",
"cafy": "15.2.1",
"cbor": "5.0.2",
"chalk": "4.0.0",
"chalk": "4.1.0",
"chart.js": "2.9.3",
"cli-highlight": "2.1.4",
"commander": "4.1.1",
"content-disposition": "0.5.3",
"core-js": "3.6.5",
"crc-32": "1.2.0",
"css-loader": "3.5.3",
"css-loader": "3.6.0",
"cssnano": "4.1.10",
"dateformat": "3.0.3",
"deep-entries": "3.1.0",
"diskusage": "1.1.3",
"double-ended-queue": "2.1.0-0",
"escape-regexp": "0.0.1",
"eslint": "6.8.0",
"eslint": "7.4.0",
"eslint-plugin-vue": "6.2.2",
"eventemitter3": "4.0.0",
"feed": "4.1.0",
"eventemitter3": "4.0.4",
"feed": "4.2.1",
"fibers": "5.0.0",
"file-type": "14.3.0",
"file-type": "14.6.2",
"fluent-ffmpeg": "2.1.2",
"glob": "7.1.6",
"gulp": "4.0.2",
@ -146,47 +148,48 @@
"gulp-tslint": "8.1.4",
"gulp-typescript": "6.0.0-alpha.1",
"hard-source-webpack-plugin": "0.13.1",
"hcaptcha": "0.0.1",
"hcaptcha": "0.0.2",
"html-minifier": "4.0.0",
"http-proxy-agent": "4.0.1",
"http-signature": "1.3.4",
"https-proxy-agent": "5.0.0",
"idb-keyval": "3.2.0",
"insert-text-at-cursor": "0.3.0",
"is-root": "2.1.0",
"is-svg": "4.2.1",
"js-yaml": "3.13.1",
"jsdom": "16.2.2",
"js-yaml": "3.14.0",
"jsdom": "16.3.0",
"json5": "2.1.3",
"json5-loader": "4.0.0",
"jsonld": "3.1.0",
"jsrsasign": "8.0.15",
"jsonld": "3.1.1",
"jsrsasign": "8.0.20",
"katex": "0.11.1",
"koa": "2.11.0",
"koa": "2.13.0",
"koa-bodyparser": "4.3.0",
"koa-favicon": "2.1.0",
"koa-json-body": "5.3.0",
"koa-logger": "3.2.1",
"koa-mount": "4.0.0",
"koa-send": "5.0.0",
"koa-send": "5.0.1",
"koa-slow": "2.1.0",
"koa-views": "6.2.1",
"koa-views": "6.3.0",
"langmap": "0.0.16",
"lookup-dns-cache": "2.1.0",
"markdown-it": "10.0.0",
"markdown-it-anchor": "5.2.7",
"mocha": "7.1.2",
"markdown-it": "11.0.0",
"markdown-it-anchor": "5.3.0",
"mocha": "8.0.1",
"moji": "0.5.1",
"ms": "2.1.2",
"multer": "1.4.2",
"nested-property": "2.0.0",
"nested-property": "2.0.1",
"node-fetch": "2.6.0",
"nodemailer": "6.4.6",
"nodemailer": "6.4.10",
"nprogress": "0.2.0",
"object-assign-deep": "0.4.0",
"os-utils": "0.0.14",
"parse5": "6.0.0",
"parsimmon": "1.13.0",
"pg": "8.1.0",
"parsimmon": "1.14.0",
"pg": "8.3.0",
"portal-vue": "2.1.7",
"portscanner": "2.2.0",
"postcss-loader": "3.0.0",
@ -213,55 +216,55 @@
"rimraf": "3.0.2",
"rndstr": "1.0.0",
"s-age": "1.1.2",
"sass": "1.26.5",
"sass-loader": "8.0.2",
"sass": "1.26.10",
"sass-loader": "9.0.2",
"seedrandom": "3.0.5",
"sharp": "0.25.2",
"sharp": "0.25.4",
"speakeasy": "2.0.0",
"stringz": "2.1.0",
"style-loader": "1.2.1",
"summaly": "2.3.1",
"summaly": "2.4.0",
"syslog-pro": "1.0.0",
"systeminformation": "4.25.1",
"systeminformation": "4.26.9",
"syuilo-password-strength": "0.0.1",
"textarea-caret": "3.1.0",
"three": "0.116.1",
"three": "0.117.1",
"tinycolor2": "1.4.1",
"tmp": "0.2.1",
"ts-loader": "7.0.3",
"ts-node": "8.10.1",
"ts-loader": "8.0.0",
"ts-node": "8.10.2",
"tslint": "6.1.2",
"tslint-sonarts": "1.9.0",
"typeorm": "0.2.24",
"typescript": "3.9.1-rc",
"typeorm": "0.2.25",
"typescript": "3.9.6",
"ulid": "2.3.0",
"url-loader": "4.1.0",
"uuid": "8.0.0",
"uuid": "8.2.0",
"v-animate-css": "0.0.3",
"v-debounce": "0.1.2",
"vue": "2.6.11",
"vue-color": "2.7.1",
"vue-content-loading": "1.6.0",
"vue-cropperjs": "4.1.0",
"vue-i18n": "8.17.4",
"vue-json-pretty": "1.6.3",
"vue-loader": "15.9.2",
"vue-i18n": "8.18.2",
"vue-json-pretty": "1.6.5",
"vue-loader": "15.9.3",
"vue-marquee-text-component": "1.1.1",
"vue-meta": "2.3.3",
"vue-meta": "2.4.0",
"vue-prism-component": "1.2.0",
"vue-prism-editor": "0.6.1",
"vue-router": "3.1.6",
"vue-router": "3.3.4",
"vue-style-loader": "4.1.2",
"vue-svg-inline-loader-corejs3": "1.5.0",
"vue-template-compiler": "2.6.11",
"vuedraggable": "2.23.2",
"vuex": "3.3.0",
"vuedraggable": "2.24.0",
"vuex": "3.5.1",
"vuex-persistedstate": "3.0.1",
"web-push": "3.4.3",
"webpack": "5.0.0-beta.16",
"webpack-cli": "3.3.11",
"web-push": "3.4.4",
"webpack": "5.0.0-beta.22",
"webpack-cli": "3.3.12",
"websocket": "1.0.31",
"ws": "7.2.5",
"ws": "7.3.1",
"xev": "2.0.1"
},
"devDependencies": {

View File

@ -29,47 +29,7 @@
</div>
</header>
<transition name="nav-back">
<div class="nav-back"
v-if="showNav"
@click="showNav = false"
@touchstart="showNav = false"
></div>
</transition>
<transition name="nav">
<nav class="nav" ref="nav" v-show="showNav">
<div>
<button class="item _button account" @click="openAccountMenu" v-if="$store.getters.isSignedIn">
<mk-avatar :user="$store.state.i" class="avatar"/><mk-acct class="text" :user="$store.state.i"/>
</button>
<button class="item _button index active" @click="top()" v-if="$route.name === 'index'">
<fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
</button>
<router-link class="item index" active-class="active" to="/" exact v-else>
<fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
</router-link>
<template v-for="item in menu">
<div v-if="item === '-'" class="divider"></div>
<component v-else-if="menuDef[item].show !== false" :is="menuDef[item].to ? 'router-link' : 'button'" class="item _button" :class="item" active-class="active" @click="() => { if (menuDef[item].action) menuDef[item].action() }" :to="menuDef[item].to">
<fa :icon="menuDef[item].icon" fixed-width/><span class="text">{{ $t(menuDef[item].title) }}</span>
<i v-if="menuDef[item].indicated"><fa :icon="faCircle"/></i>
</component>
</template>
<div class="divider"></div>
<button class="item _button" :class="{ active: $route.path === '/instance' || $route.path.startsWith('/instance/') }" v-if="$store.getters.isSignedIn && ($store.state.i.isAdmin || $store.state.i.isModerator)" @click="oepnInstanceMenu">
<fa :icon="faServer" fixed-width/><span class="text">{{ $t('instance') }}</span>
</button>
<button class="item _button" @click="more">
<fa :icon="faEllipsisH" fixed-width/><span class="text">{{ $t('more') }}</span>
<i v-if="otherNavItemIndicated"><fa :icon="faCircle"/></i>
</button>
<router-link class="item" active-class="active" to="/preferences">
<fa :icon="faCog" fixed-width/><span class="text">{{ $t('settings') }}</span>
</router-link>
</div>
</nav>
</transition>
<x-sidebar ref="nav"/>
<div class="contents" ref="contents" :class="{ wallpaper }">
<main ref="main">
@ -86,38 +46,37 @@
</div>
</main>
<div class="widgets">
<div ref="widgets" :class="{ edit: widgetsEditMode }">
<template v-if="isDesktop && $store.getters.isSignedIn">
<template v-if="widgetsEditMode">
<mk-button primary @click="addWidget" class="add"><fa :icon="faPlus"/></mk-button>
<x-draggable
:list="widgets"
handle=".handle"
animation="150"
class="sortable"
@sort="onWidgetSort"
>
<div v-for="widget in widgets" class="customize-container _panel" :key="widget.id">
<header>
<span class="handle"><fa :icon="faBars"/></span>{{ $t('_widgets.' + widget.name) }}<button class="remove _button" @click="removeWidget(widget)"><fa :icon="faTimes"/></button>
</header>
<div @click="widgetFunc(widget.id)">
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true"/>
</div>
<template v-if="isDesktop">
<div v-for="place in ['left', 'right']" ref="widgets" class="widgets" :class="{ edit: widgetsEditMode, fixed: $store.state.device.fixedWidgetsPosition, empty: widgets[place].length === 0 && !widgetsEditMode }" :key="place">
<div class="spacer"></div>
<div class="container" v-if="widgetsEditMode">
<mk-button primary @click="addWidget(place)" class="add"><fa :icon="faPlus"/></mk-button>
<x-draggable
:list="widgets[place]"
handle=".handle"
animation="150"
class="sortable"
@sort="onWidgetSort"
>
<div v-for="widget in widgets[place]" class="customize-container _panel" :key="widget.id">
<header>
<span class="handle"><fa :icon="faBars"/></span>{{ $t('_widgets.' + widget.name) }}<button class="remove _button" @click="removeWidget(widget)"><fa :icon="faTimes"/></button>
</header>
<div @click="widgetFunc(widget.id)">
<component class="_close_ _forceContainerFull_" :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true"/>
</div>
</x-draggable>
</template>
<template v-else>
<component class="widget" v-for="widget in widgets" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget"/>
</template>
</template>
</div>
</x-draggable>
</div>
<div class="container" v-else>
<component v-for="widget in widgets[place]" class="_close_ _forceContainerFull_" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget"/>
</div>
</div>
</div>
</template>
</div>
<div class="buttons">
<button class="button nav _button" @click="showNav = true" ref="navButton"><fa :icon="faBars"/><i v-if="navIndicated"><fa :icon="faCircle"/></i></button>
<button class="button nav _button" @click="showNav" ref="navButton"><fa :icon="faBars"/><i v-if="navIndicated"><fa :icon="faCircle"/></i></button>
<button v-if="$route.name === 'index'" class="button home _button" @click="top()"><fa :icon="faHome"/></button>
<button v-else class="button home _button" @click="$router.push('/')"><fa :icon="faHome"/></button>
<button v-if="$store.getters.isSignedIn" class="button notifications _button" @click="$router.push('/my/notifications')"><fa :icon="faBell"/><i v-if="$store.state.i.hasUnreadNotification"><fa :icon="faCircle"/></i></button>
@ -136,16 +95,17 @@ import { faGripVertical, faChevronLeft, faHashtag, faBroadcastTower, faFireAlt,
import { faBell, faEnvelope, faLaugh, faComments } from '@fortawesome/free-regular-svg-icons';
import { ResizeObserver } from '@juggle/resize-observer';
import { v4 as uuid } from 'uuid';
import i18n from './i18n';
import { host, instanceName } from './config';
import { host } from './config';
import { search } from './scripts/search';
import { StickySidebar } from './scripts/sticky-sidebar';
import { widgets } from './widgets';
import XSidebar from './components/sidebar.vue';
const DESKTOP_THRESHOLD = 1100;
export default Vue.extend({
i18n,
components: {
XSidebar,
XClock: () => import('./components/header-clock.vue').then(m => m.default),
MkButton: () => import('./components/ui/button.vue').then(m => m.default),
XDraggable: () => import('vuedraggable'),
@ -155,19 +115,14 @@ export default Vue.extend({
return {
host: host,
pageKey: 0,
showNav: false,
searching: false,
accounts: [],
lists: [],
connection: null,
searchQuery: '',
searchWait: false,
widgetsEditMode: false,
menuDef: this.$store.getters.nav({
search: this.search
}),
isDesktop: window.innerWidth >= DESKTOP_THRESHOLD,
canBack: false,
menuDef: this.$store.getters.nav({}),
wallpaper: localStorage.getItem('wallpaper') != null,
faGripVertical, faChevronLeft, faComments, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faBell, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faEnvelope, faListUl, faPlus, faUserClock, faLaugh, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faProjectDiagram
};
@ -176,6 +131,10 @@ export default Vue.extend({
computed: {
keymap(): any {
return {
'd': () => {
if (this.$store.state.device.syncDeviceDarkMode) return;
this.$store.commit('device/set', { key: 'darkMode', value: !this.$store.state.device.darkMode });
},
'p': this.post,
'n': this.post,
's': this.search,
@ -184,70 +143,83 @@ export default Vue.extend({
},
widgets(): any[] {
return this.$store.state.deviceUser.widgets;
if (this.$store.getters.isSignedIn) {
const widgets = this.$store.state.deviceUser.widgets;
return {
left: widgets.filter(x => x.place === 'left'),
right: widgets.filter(x => x.place == null || x.place === 'right'),
mobile: widgets.filter(x => x.place === 'mobile'),
};
} else {
return {
left: [],
right: [{
name: 'welcome',
id: 'a', place: 'right', data: {}
}, {
name: 'calendar',
id: 'b', place: 'right', data: {}
}, {
name: 'trends',
id: 'c', place: 'right', data: {}
}],
mobile: [],
};
}
},
menu(): string[] {
return this.$store.state.deviceUser.menu;
},
otherNavItemIndicated(): boolean {
if (!this.$store.getters.isSignedIn) return false;
for (const def in this.menuDef) {
if (this.menu.includes(def)) continue;
if (this.menuDef[def].indicated) return true;
}
return false;
},
navIndicated(): boolean {
if (!this.$store.getters.isSignedIn) return false;
for (const def in this.menuDef) {
if (def === 'timeline') continue;
if (def === 'notifications') continue;
if (def === 'notifications') continue; // 通知は下にボタンとして表示されてるから
if (this.menuDef[def].indicated) return true;
}
return false;
}
},
watch:{
watch: {
$route(to, from) {
this.pageKey++;
this.showNav = false;
this.canBack = (window.history.length > 0 && !['index'].includes(to.name));
},
isDesktop() {
if (this.isDesktop) this.adjustWidgetsWidth();
this.$nextTick(() => {
this.attachSticky();
});
}
},
created() {
document.documentElement.style.overflowY = 'scroll';
if (this.$store.getters.isSignedIn) {
this.connection = this.$root.stream.useSharedConnection('main');
this.connection.on('notification', this.onNotification);
if (this.widgets.length === 0) {
if (this.$store.state.deviceUser.widgets.length === 0) {
this.$store.commit('deviceUser/setWidgets', [{
name: 'calendar',
id: 'a', data: {}
id: 'a', place: 'right', data: {}
}, {
name: 'notifications',
id: 'b', data: {}
id: 'b', place: 'right', data: {}
}, {
name: 'trends',
id: 'c', data: {}
id: 'c', place: 'right', data: {}
}]);
}
}
},
mounted() {
if (this.isDesktop) this.adjustWidgetsWidth();
const adjustTitlePosition = () => {
const left = this.$refs.main.getBoundingClientRect().left - this.$refs.nav.offsetWidth;
const left = this.$refs.main.getBoundingClientRect().left - this.$refs.nav.$el.offsetWidth;
if (left >= 0) {
this.$refs.title.style.left = left + 'px';
}
@ -268,20 +240,26 @@ export default Vue.extend({
if (window.innerWidth >= DESKTOP_THRESHOLD) this.isDesktop = true;
}, { passive: true });
}
// widget follow
this.attachSticky();
},
methods: {
adjustWidgetsWidth() {
// https://stackoverflow.com/questions/33891709/when-flexbox-items-wrap-in-column-mode-container-does-not-grow-its-width
const adjust = () => {
const lastChild = this.$refs.widgets.children[this.$refs.widgets.children.length - 1];
if (lastChild == null) return;
showNav() {
this.$refs.nav.show();
},
const width = lastChild.offsetLeft + 300 + 16;
this.$refs.widgets.style.width = width + 'px';
};
setInterval(adjust, 1000);
setTimeout(adjust, 100);
attachSticky() {
if (!this.isDesktop) return;
if (this.$store.state.device.fixedWidgetsPosition) return;
const stickyWidgetColumns = this.$refs.widgets.map(w => new StickySidebar(w.children[1], w.children[0], w.offsetTop));
window.addEventListener('scroll', () => {
for (const stickyWidgetColumn of stickyWidgetColumns) {
stickyWidgetColumn.calc(window.scrollY);
}
}, { passive: true });
},
top() {
@ -330,181 +308,8 @@ export default Vue.extend({
}
},
async openAccountMenu(ev) {
const accounts = (await this.$root.api('users/show', { userIds: this.$store.state.device.accounts.map(x => x.id) })).filter(x => x.id !== this.$store.state.i.id);
const accountItems = accounts.map(account => ({
type: 'user',
user: account,
action: () => { this.switchAccount(account); }
}));
this.$root.menu({
items: [...[{
type: 'link',
text: this.$t('profile'),
to: `/@${ this.$store.state.i.username }`,
avatar: this.$store.state.i,
}, {
type: 'link',
text: this.$t('accountSettings'),
to: '/my/settings',
icon: faCog,
}, null, ...accountItems, {
icon: faPlus,
text: this.$t('addAcount'),
action: () => {
this.$root.menu({
items: [{
text: this.$t('existingAcount'),
action: () => { this.addAcount(); },
}, {
text: this.$t('createAccount'),
action: () => { this.createAccount(); },
}],
align: 'left',
fixed: true,
width: 240,
source: ev.currentTarget || ev.target,
});
},
}]],
align: 'left',
fixed: true,
width: 240,
source: ev.currentTarget || ev.target,
});
},
oepnInstanceMenu(ev) {
this.$root.menu({
items: [{
type: 'link',
text: this.$t('dashboard'),
to: '/instance',
icon: faTachometerAlt,
}, null, {
type: 'link',
text: this.$t('settings'),
to: '/instance/settings',
icon: faCog,
}, {
type: 'link',
text: this.$t('customEmojis'),
to: '/instance/emojis',
icon: faLaugh,
}, {
type: 'link',
text: this.$t('users'),
to: '/instance/users',
icon: faUsers,
}, {
type: 'link',
text: this.$t('files'),
to: '/instance/files',
icon: faCloud,
}, {
type: 'link',
text: this.$t('jobQueue'),
to: '/instance/queue',
icon: faExchangeAlt,
}, {
type: 'link',
text: this.$t('federation'),
to: '/instance/federation',
icon: faGlobe,
}, {
type: 'link',
text: this.$t('relays'),
to: '/instance/relays',
icon: faProjectDiagram,
}, {
type: 'link',
text: this.$t('announcements'),
to: '/instance/announcements',
icon: faBroadcastTower,
}],
align: 'left',
fixed: true,
width: 200,
source: ev.currentTarget || ev.target,
});
},
more(ev) {
const items = Object.keys(this.menuDef).filter(k => !this.menu.includes(k)).map(k => this.menuDef[k]).filter(def => def.show == null ? true : def.show).map(def => ({
type: def.to ? 'link' : 'button',
text: this.$t(def.title),
icon: def.icon,
to: def.to,
action: def.action,
indicate: def.indicated,
}));
this.$root.menu({
items: [...items, null, {
type: 'link',
text: this.$t('help'),
to: '/docs',
icon: faQuestionCircle,
}, {
type: 'link',
text: this.$t('aboutX', { x: instanceName || host }),
to: '/about',
icon: faInfoCircle,
}, {
type: 'link',
text: this.$t('aboutMisskey'),
to: '/about-misskey',
icon: faInfoCircle,
}],
align: 'left',
fixed: true,
width: 200,
source: ev.currentTarget || ev.target,
});
},
async addAcount() {
this.$root.new(await import('./components/signin-dialog.vue').then(m => m.default)).$once('login', res => {
this.$store.dispatch('addAcount', res);
this.$root.dialog({
type: 'success',
iconOnly: true, autoClose: true
});
});
},
async createAccount() {
this.$root.new(await import('./components/signup-dialog.vue').then(m => m.default)).$once('signup', res => {
this.$store.dispatch('addAcount', res);
this.switchAccountWithToken(res.i);
});
},
async switchAccount(account: any) {
const token = this.$store.state.device.accounts.find((x: any) => x.id === account.id).token;
this.switchAccountWithToken(token);
},
switchAccountWithToken(token: string) {
this.$root.dialog({
type: 'waiting',
iconOnly: true
});
this.$root.api('i', {}, token).then((i: any) => {
this.$store.dispatch('switchAccount', {
...i,
token: token
}).then(() => {
location.reload();
});
});
},
async onNotification(notification) {
// TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない
if (true) {
if (document.visibilityState === 'visible') {
this.$root.stream.send('readNotification', {
id: notification.id
});
@ -518,39 +323,32 @@ export default Vue.extend({
},
widgetFunc(id) {
const w = this.$refs[id][0];
if (w.func) w.func();
this.$refs[id][0].setting();
},
onWidgetSort() {
this.saveHome();
},
addWidget(ev) {
const widgets = [
'memo',
'notifications',
'timeline',
'calendar',
'rss',
'trends',
'clock',
'activity',
'photos',
];
async addWidget(place) {
const { canceled, result: widget } = await this.$root.dialog({
type: null,
title: this.$t('chooseWidget'),
select: {
items: widgets.map(widget => ({
value: widget,
text: this.$t('_widgets.' + widget),
}))
},
showCancelButton: true
});
if (canceled) return;
this.$root.menu({
items: widgets.map(widget => ({
text: this.$t('_widgets.' + widget),
action: () => {
this.$store.commit('deviceUser/addWidget', {
name: widget,
id: uuid(),
data: {}
});
}
})),
source: ev.currentTarget || ev.target,
this.$store.commit('deviceUser/addWidget', {
name: widget,
id: uuid(),
place: place,
data: {}
});
},
@ -559,44 +357,24 @@ export default Vue.extend({
},
saveHome() {
this.$store.commit('deviceUser/setWidgets', this.widgets);
this.$store.commit('deviceUser/setWidgets', [...this.widgets.left, ...this.widgets.right, ...this.widgets.mobile]);
}
}
});
</script>
<style lang="scss" scoped>
.nav-enter-active,
.nav-leave-active {
opacity: 1;
transform: translateX(0);
transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.nav-enter,
.nav-leave-active {
opacity: 0;
transform: translateX(-240px);
}
.nav-back-enter-active,
.nav-back-leave-active {
opacity: 1;
transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.nav-back-enter,
.nav-back-leave-active {
opacity: 0;
}
.mk-app {
$header-height: 60px;
$nav-width: 250px;
$nav-icon-only-width: 80px;
$main-width: 650px;
$ui-font-size: 1em;
$nav-icon-only-threshold: 1300px;
$nav-hide-threshold: 650px;
$side-hide-threshold: 1070px;
$nav-width: 250px; // TODO: どこかに集約したい
$nav-icon-only-width: 80px; // TODO: どこかに集約したい
$main-width: 670px;
$ui-font-size: 1em; // TODO: どこかに集約したい
$nav-icon-only-threshold: 1279px; // TODO: どこかに集約したい
$nav-hide-threshold: 650px; // TODO: どこかに集約したい
$header-sub-hide-threshold: 1090px;
$left-widgets-hide-threshold: 1600px;
$right-widgets-hide-threshold: 1090px;
min-height: 100vh;
box-sizing: border-box;
@ -694,7 +472,7 @@ export default Vue.extend({
right: 16px;
height: $header-height;
@media (max-width: $side-hide-threshold) {
@media (max-width: $header-sub-hide-threshold) {
display: none;
}
@ -720,6 +498,7 @@ export default Vue.extend({
border-radius: 38px;
color: var(--fg);
background: var(--bg);
-webkit-appearance: textfield;
&:focus {
outline: none;
@ -750,176 +529,6 @@ export default Vue.extend({
}
}
> .nav-back {
position: fixed;
top: 0;
left: 0;
z-index: 1001;
width: 100%;
height: 100%;
background: var(--modalBg);
}
> .nav {
$avatar-size: 32px;
$avatar-margin: ($header-height - $avatar-size) / 2;
flex: 0 0 $nav-width;
width: $nav-width;
box-sizing: border-box;
@media (max-width: $nav-icon-only-threshold) {
flex: 0 0 $nav-icon-only-width;
width: $nav-icon-only-width;
}
@media (max-width: $nav-hide-threshold) {
position: fixed;
top: 0;
left: 0;
z-index: 1001;
}
@media (min-width: $nav-hide-threshold + 1px) {
display: block !important;
}
> div {
position: fixed;
top: 0;
left: 0;
z-index: 1001;
width: $nav-width;
height: 100vh;
box-sizing: border-box;
overflow: auto;
background: var(--navBg);
border-right: solid 1px var(--divider);
> .divider {
margin: 16px 0;
border-top: solid 1px var(--divider);
}
@media (max-width: $nav-icon-only-threshold) and (min-width: $nav-hide-threshold + 1px) {
width: $nav-icon-only-width;
> .divider {
margin: 8px auto;
width: calc(100% - 32px);
}
> .item {
&:first-child {
margin-bottom: 8px;
}
&:last-child {
margin-top: 8px;
}
}
}
> .item {
position: relative;
display: block;
padding-left: 32px;
font-size: $ui-font-size;
line-height: 3.2rem;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
text-align: left;
box-sizing: border-box;
color: var(--navFg);
> [data-icon] {
width: ($header-height - ($avatar-margin * 2));
}
> [data-icon],
> .avatar {
margin-right: $avatar-margin;
}
> .avatar {
width: $avatar-size;
height: $avatar-size;
vertical-align: middle;
}
> i {
position: absolute;
top: 0;
left: 20px;
color: var(--navIndicator);
font-size: 8px;
animation: blink 1s infinite;
}
&:hover {
text-decoration: none;
color: var(--navHoverFg);
}
&.active {
color: var(--navActive);
}
&:first-child, &:last-child {
position: sticky;
z-index: 1;
padding-top: 8px;
padding-bottom: 8px;
background: var(--wboyroyc);
-webkit-backdrop-filter: blur(8px);
backdrop-filter: blur(8px);
}
&:first-child {
top: 0;
margin-bottom: 16px;
border-bottom: solid 1px var(--divider);
}
&:last-child {
bottom: 0;
margin-top: 16px;
border-top: solid 1px var(--divider);
}
@media (max-width: $nav-icon-only-threshold) and (min-width: $nav-hide-threshold + 1px) {
padding-left: 0;
width: 100%;
text-align: center;
font-size: $ui-font-size * 1.2;
line-height: 3.7rem;
> [data-icon],
> .avatar {
margin-right: 0;
}
> i {
left: 10px;
}
> .text {
display: none;
}
}
}
@media (max-width: $nav-hide-threshold) {
> .index,
> .notifications {
display: none;
}
}
}
}
> .contents {
display: flex;
margin: 0 auto;
@ -927,25 +536,21 @@ export default Vue.extend({
&.wallpaper {
background: var(--wallpaperOverlay);
backdrop-filter: blur(4px);
}
> main {
width: $main-width;
min-width: $main-width;
box-shadow: 1px 0 0 0 var(--divider), -1px 0 0 0 var(--divider);
@media (max-width: $side-hide-threshold) {
min-width: 0;
}
min-width: 0;
> .content {
> * {
&:not(.full) {
padding: var(--margin) 0;
}
min-height: calc(100vh - #{$header-height});
box-sizing: border-box;
padding: var(--margin);
&:not(.naked) {
background: var(--pageBg);
&.full {
padding: 0 var(--margin);
}
&.naked {
@ -987,67 +592,83 @@ export default Vue.extend({
}
> .widgets {
box-sizing: border-box;
margin-left: var(--margin);
padding: 0 var(--margin);
box-shadow: 1px 0 0 0 var(--divider), -1px 0 0 0 var(--divider);
@media (max-width: $side-hide-threshold) {
&.fixed {
position: sticky;
overflow: auto;
height: calc(100vh - #{$header-height});
top: $header-height;
}
&:first-of-type {
order: -1;
@media (max-width: $left-widgets-hide-threshold) {
display: none;
}
}
&.empty {
display: none;
}
> div {
@media (max-width: $right-widgets-hide-threshold) {
display: none;
}
> .container {
position: sticky;
top: calc(#{$header-height} + var(--margin));
height: calc(100vh - #{$header-height} - var(--margin));
&.edit {
overflow: auto;
width: auto !important;
}
&:not(.edit) {
display: inline-flex;
flex-wrap: wrap;
flex-direction: column;
place-content: flex-start;
}
height: min-content;
min-height: calc(100vh - #{$header-height});
padding: var(--margin) 0;
box-sizing: border-box;
> * {
margin: 0 var(--margin) var(--margin) 0;
margin: var(--margin) 0;
width: 300px;
}
> .add {
margin: 0 auto;
}
.customize-container {
margin: 8px 0;
background: #fff;
> header {
position: relative;
line-height: 32px;
> .handle {
padding: 0 8px;
cursor: move;
}
> .remove {
position: absolute;
top: 0;
right: 0;
padding: 0 8px;
line-height: 32px;
}
&:first-child {
margin-top: 0;
}
> div {
padding: 8px;
&:last-child {
margin-bottom: 0;
}
}
}
> * {
pointer-events: none;
}
> .add {
margin: 0 auto;
}
.customize-container {
margin: 8px 0;
> header {
position: relative;
line-height: 32px;
> .handle {
padding: 0 8px;
cursor: move;
}
> .remove {
position: absolute;
top: 0;
right: 0;
padding: 0 8px;
line-height: 32px;
}
}
> div {
padding: 8px;
> * {
pointer-events: none;
}
}
}
@ -1070,7 +691,7 @@ export default Vue.extend({
display: block;
}
@media (min-width: ($side-hide-threshold + 1px)) {
@media (min-width: ($header-sub-hide-threshold + 1px)) {
display: none;
}
}
@ -1083,7 +704,7 @@ export default Vue.extend({
display: flex;
width: 100%;
box-sizing: border-box;
background: linear-gradient(0deg, var(--bg), var(--bonzsgfz));
background: linear-gradient(0deg, var(--bg), var(--X1));
@media (max-width: 500px) {
padding: 0 16px 16px 16px;
@ -1127,7 +748,7 @@ export default Vue.extend({
color: var(--fg);
&:hover {
background: var(--pcncwizz);
background: var(--X2);
}
> i {

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

View File

@ -426,7 +426,7 @@ export default Vue.extend({
}
&:hover {
background: var(--yrnqrguo);
background: var(--X3);
}
&[data-selected='true'] {

View File

@ -7,7 +7,6 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
type Captcha = {
render(container: string | Node, options: {
@ -31,7 +30,6 @@ declare global {
}
export default Vue.extend({
i18n,
props: {
provider: {
type: String,

View File

@ -7,13 +7,10 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import { length } from 'stringz';
import { concat } from '../../prelude/array';
export default Vue.extend({
i18n,
props: {
value: {
type: Boolean,
@ -30,7 +27,7 @@ export default Vue.extend({
return concat([
this.note.text ? [this.$t('_cw.chars', { count: length(this.note.text) })] : [],
this.note.files && this.note.files.length !== 0 ? [this.$t('_cw.files', { count: this.note.files.length }) ] : [],
this.note.poll != null ? [this.$t('_cw.poll')] : []
this.note.poll != null ? [this.$t('poll')] : []
] as string[][]).join(' / ');
}
},

View File

@ -1,5 +1,5 @@
<template>
<component :is="$store.state.device.animation ? 'transition-group' : 'div'" class="sqadhkmv" name="list" tag="div" :data-direction="direction" :data-reversed="reversed ? 'true' : 'false'">
<component :is="$store.state.device.animation ? 'transition-group' : 'div'" class="sqadhkmv _list_" name="list" tag="div" :data-direction="direction" :data-reversed="reversed ? 'true' : 'false'">
<template v-for="(item, i) in items">
<slot :item="item"></slot>
<div class="separator" v-if="showDate(i, item)" :key="item.id + '_date'">
@ -15,11 +15,8 @@
<script lang="ts">
import Vue from 'vue';
import { faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons';
import i18n from '../i18n';
export default Vue.extend({
i18n,
props: {
items: {
type: Array,
@ -72,6 +69,10 @@ export default Vue.extend({
<style lang="scss">
.sqadhkmv {
> *:not(:last-child) {
margin-bottom: var(--margin);
}
> .list-move {
transition: transform 0.7s cubic-bezier(0.23, 1, 0.32, 1);
}

View File

@ -0,0 +1,80 @@
<template>
<x-column :menu="menu" :column="column" :is-stacked="isStacked">
<template #header>
<fa :icon="faSatellite"/><span style="margin-left: 8px;">{{ column.name }}</span>
</template>
<x-timeline ref="timeline" src="antenna" :antenna="column.antennaId" @after="() => $emit('loaded')"/>
</x-column>
</template>
<script lang="ts">
import Vue from 'vue';
import { faSatellite, faCog } from '@fortawesome/free-solid-svg-icons';
import XColumn from './column.vue';
import XTimeline from '../timeline.vue';
export default Vue.extend({
components: {
XColumn,
XTimeline,
},
props: {
column: {
type: Object,
required: true
},
isStacked: {
type: Boolean,
required: true
}
},
data() {
return {
menu: null,
faSatellite
};
},
watch: {
mediaOnly() {
(this.$refs.timeline as any).reload();
}
},
created() {
this.menu = [{
icon: faCog,
text: this.$t('antenna'),
action: async () => {
const antennas = await this.$root.api('antennas/list');
this.$root.dialog({
title: this.$t('antenna'),
type: null,
select: {
items: antennas.map(x => ({
value: x, text: x.name
}))
},
showCancelButton: true
}).then(({ canceled, result: antenna }) => {
if (canceled) return;
this.column.antennaId = antenna.id;
this.$store.commit('deviceUser/updateDeckColumn', this.column);
});
}
}];
},
methods: {
focus() {
(this.$refs.timeline as any).focus();
}
}
});
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,50 @@
<template>
<!-- TODO: リファクタの余地がありそう -->
<x-widgets-column v-if="column.type === 'widgets'" :column="column" :is-stacked="isStacked" v-on="$listeners"/>
<x-notifications-column v-else-if="column.type === 'notifications'" :column="column" :is-stacked="isStacked" v-on="$listeners"/>
<x-tl-column v-else-if="column.type === 'tl'" :column="column" :is-stacked="isStacked" v-on="$listeners"/>
<x-list-column v-else-if="column.type === 'list'" :column="column" :is-stacked="isStacked" v-on="$listeners"/>
<x-antenna-column v-else-if="column.type === 'antenna'" :column="column" :is-stacked="isStacked" v-on="$listeners"/>
<!-- TODO: <x-tl-column v-else-if="column.type === 'hashtag'" :column="column" :is-stacked="isStacked" v-on="$listeners"/> -->
<x-mentions-column v-else-if="column.type === 'mentions'" :column="column" :is-stacked="isStacked" v-on="$listeners"/>
<x-direct-column v-else-if="column.type === 'direct'" :column="column" :is-stacked="isStacked" v-on="$listeners"/>
</template>
<script lang="ts">
import Vue from 'vue';
import XTlColumn from './tl-column.vue';
import XAntennaColumn from './antenna-column.vue';
import XListColumn from './list-column.vue';
import XNotificationsColumn from './notifications-column.vue';
import XWidgetsColumn from './widgets-column.vue';
import XMentionsColumn from './mentions-column.vue';
import XDirectColumn from './direct-column.vue';
export default Vue.extend({
components: {
XTlColumn,
XAntennaColumn,
XListColumn,
XNotificationsColumn,
XWidgetsColumn,
XMentionsColumn,
XDirectColumn
},
props: {
column: {
type: Object,
required: true
},
isStacked: {
type: Boolean,
required: false,
default: false
}
},
methods: {
focus() {
this.$children[0].focus();
}
}
});
</script>

View File

@ -0,0 +1,426 @@
<template>
<!-- sectionを利用しているのはdeck.vue側でcolumnに対してfirst-of-typeを効かせるため -->
<section class="dnpfarvg _panel _narrow_" :class="{ naked, paged: isMainColumn, _close_: !isMainColumn, active, isStacked, draghover, dragging, dropready }"
@dragover.prevent.stop="onDragover"
@dragleave="onDragleave"
@drop.prevent.stop="onDrop"
v-hotkey="keymap"
:style="{ width: `${width}px` }"
>
<header :class="{ indicated }"
draggable="true"
@click="goTop"
@dragstart="onDragstart"
@dragend="onDragend"
@contextmenu.prevent.stop="onContextmenu"
>
<button class="toggleActive _button" @click="toggleActive" v-if="isStacked">
<template v-if="active"><fa :icon="faAngleUp"/></template>
<template v-else><fa :icon="faAngleDown"/></template>
</button>
<div class="action">
<slot name="action"></slot>
</div>
<span class="header"><slot name="header"></slot></span>
<button v-if="!isMainColumn" class="menu _button" ref="menu" @click.stop="showMenu"><fa :icon="faCaretDown"/></button>
<button v-else-if="$route.name !== 'index'" class="close _button" @click.stop="close"><fa :icon="faTimes"/></button>
</header>
<div ref="body" v-show="active">
<slot></slot>
</div>
</section>
</template>
<script lang="ts">
import Vue from 'vue';
import { faArrowUp, faArrowDown, faAngleUp, faAngleDown, faCaretDown, faTimes, faArrowRight, faArrowLeft, faPencilAlt } from '@fortawesome/free-solid-svg-icons';
import { faWindowMaximize, faTrashAlt, faWindowRestore } from '@fortawesome/free-regular-svg-icons';
export default Vue.extend({
props: {
column: {
type: Object,
required: false,
default: null
},
isStacked: {
type: Boolean,
required: false,
default: false
},
menu: {
type: Array,
required: false,
default: null
},
naked: {
type: Boolean,
required: false,
default: false
},
indicated: {
type: Boolean,
required: false,
default: false
},
},
data() {
return {
active: true,
dragging: false,
draghover: false,
dropready: false,
faArrowUp, faArrowDown, faAngleUp, faAngleDown, faCaretDown, faTimes,
};
},
computed: {
isMainColumn(): boolean {
return this.column == null;
},
width(): number {
return this.isMainColumn ? 350 : this.column.width;
},
keymap(): any {
return {
'shift+up': () => this.$parent.$emit('parentFocus', 'up'),
'shift+down': () => this.$parent.$emit('parentFocus', 'down'),
'shift+left': () => this.$parent.$emit('parentFocus', 'left'),
'shift+right': () => this.$parent.$emit('parentFocus', 'right'),
};
}
},
watch: {
active(v) {
this.$emit('change-active-state', v);
},
dragging(v) {
this.$root.$emit(v ? 'deck.column.dragStart' : 'deck.column.dragEnd');
}
},
mounted() {
if (!this.isMainColumn) {
this.$root.$on('deck.column.dragStart', this.onOtherDragStart);
this.$root.$on('deck.column.dragEnd', this.onOtherDragEnd);
}
},
beforeDestroy() {
if (!this.isMainColumn) {
this.$root.$off('deck.column.dragStart', this.onOtherDragStart);
this.$root.$off('deck.column.dragEnd', this.onOtherDragEnd);
}
},
methods: {
onOtherDragStart() {
this.dropready = true;
},
onOtherDragEnd() {
this.dropready = false;
},
toggleActive() {
if (!this.isStacked) return;
this.active = !this.active;
},
getMenu() {
const items = [{
icon: faPencilAlt,
text: this.$t('rename'),
action: () => {
this.$root.dialog({
title: this.$t('rename'),
input: {
default: this.column.name,
allowEmpty: false
}
}).then(({ canceled, result: name }) => {
if (canceled) return;
this.$store.commit('deviceUser/renameDeckColumn', { id: this.column.id, name });
});
}
}, null, {
icon: faArrowLeft,
text: this.$t('swap-left'),
action: () => {
this.$store.commit('deviceUser/swapLeftDeckColumn', this.column.id);
}
}, {
icon: faArrowRight,
text: this.$t('swap-right'),
action: () => {
this.$store.commit('deviceUser/swapRightDeckColumn', this.column.id);
}
}, this.isStacked ? {
icon: faArrowUp,
text: this.$t('swap-up'),
action: () => {
this.$store.commit('deviceUser/swapUpDeckColumn', this.column.id);
}
} : undefined, this.isStacked ? {
icon: faArrowDown,
text: this.$t('swap-down'),
action: () => {
this.$store.commit('deviceUser/swapDownDeckColumn', this.column.id);
}
} : undefined, null, {
icon: faWindowRestore,
text: this.$t('stack-left'),
action: () => {
this.$store.commit('deviceUser/stackLeftDeckColumn', this.column.id);
}
}, this.isStacked ? {
icon: faWindowMaximize,
text: this.$t('pop-right'),
action: () => {
this.$store.commit('deviceUser/popRightDeckColumn', this.column.id);
}
} : undefined, null, {
icon: faTrashAlt,
text: this.$t('remove'),
action: () => {
this.$store.commit('deviceUser/removeDeckColumn', this.column.id);
}
}];
if (this.menu) {
for (const i of this.menu.reverse()) {
items.unshift(i);
}
}
return items;
},
onContextmenu(e) {
if (this.isMainColumn) return;
this.showMenu();
},
showMenu() {
this.$root.menu({
items: this.getMenu(),
source: this.$refs.menu,
});
},
close() {
this.$router.push('/');
},
goTop() {
this.$refs.body.scrollTo({
top: 0,
behavior: 'smooth'
});
},
onDragstart(e) {
// メインカラムはドラッグさせない
if (this.isMainColumn) {
e.preventDefault();
return;
}
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('mk-deck-column', this.column.id);
this.dragging = true;
},
onDragend(e) {
this.dragging = false;
},
onDragover(e) {
// メインカラムにはドロップさせない
if (this.isMainColumn) {
e.dataTransfer.dropEffect = 'none';
return;
}
// 自分自身がドラッグされている場合
if (this.dragging) {
// 自分自身にはドロップさせない
e.dataTransfer.dropEffect = 'none';
return;
}
const isDeckColumn = e.dataTransfer.types[0] == 'mk-deck-column';
e.dataTransfer.dropEffect = isDeckColumn ? 'move' : 'none';
if (!this.dragging && isDeckColumn) this.draghover = true;
},
onDragleave() {
this.draghover = false;
},
onDrop(e) {
this.draghover = false;
this.$root.$emit('deck.column.dragEnd');
const id = e.dataTransfer.getData('mk-deck-column');
if (id != null && id != '') {
this.$store.commit('deviceUser/swapDeckColumn', {
a: this.column.id,
b: id
});
}
}
}
});
</script>
<style lang="scss" scoped>
.dnpfarvg {
$header-height: 42px;
height: 100%;
overflow: hidden;
box-shadow: 0 0 0 1px var(--deckColumnBorder);
&.draghover {
box-shadow: 0 0 0 2px var(--focus);
&:after {
content: "";
display: block;
position: absolute;
z-index: 1000;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--focus);
}
}
&.dragging {
box-shadow: 0 0 0 2px var(--focus);
}
&.dropready {
* {
pointer-events: none;
}
}
&:not(.active) {
flex-basis: $header-height;
min-height: $header-height;
> header.indicated {
box-shadow: 4px 0px var(--accent) inset;
}
}
&.naked {
//background: var(--deckAcrylicColumnBg);
background: transparent !important;
> header {
background: transparent;
box-shadow: none;
> button {
color: var(--fg);
}
}
}
&.paged {
> div {
background: var(--bg);
padding: var(--margin);
}
}
> header {
position: relative;
display: flex;
z-index: 2;
line-height: $header-height;
padding: 0 16px;
font-size: 0.9em;
color: var(--panelHeaderFg);
background: var(--panelHeaderBg);
box-shadow: 0 1px 0 0 var(--panelHeaderDivider);
cursor: pointer;
&, * {
user-select: none;
}
&.indicated {
box-shadow: 0 3px 0 0 var(--accent);
}
> .header {
display: inline-block;
align-items: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
> span:only-of-type {
width: 100%;
}
> .toggleActive,
> .action > *,
> .menu,
> .close {
z-index: 1;
width: $header-height;
line-height: $header-height;
font-size: 16px;
color: var(--faceTextButton);
&:hover {
color: var(--faceTextButtonHover);
}
&:active {
color: var(--faceTextButtonActive);
}
}
> .toggleActive, > .action {
margin-left: -16px;
}
> .action {
z-index: 1;
}
> .action:empty {
display: none;
}
> .menu,
> .close {
margin-left: auto;
margin-right: -16px;
}
}
> div {
height: calc(100% - #{$header-height});
overflow: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
box-sizing: border-box;
}
}
</style>

View File

@ -0,0 +1,39 @@
<template>
<x-column :name="name" :column="column" :is-stacked="isStacked" :menu="menu">
<template #header><fa :icon="faEnvelope" style="margin-right: 8px;"/>{{ column.name }}</template>
<x-direct/>
</x-column>
</template>
<script lang="ts">
import Vue from 'vue';
import { faEnvelope } from '@fortawesome/free-solid-svg-icons';
import XColumn from './column.vue';
import XDirect from '../../pages/messages.vue';
export default Vue.extend({
components: {
XColumn,
XDirect
},
props: {
column: {
type: Object,
required: true
},
isStacked: {
type: Boolean,
required: true
}
},
data() {
return {
menu: null,
faEnvelope
}
},
});
</script>

View File

@ -0,0 +1,87 @@
<template>
<x-column :menu="menu" :column="column" :is-stacked="isStacked">
<template #header>
<fa :icon="faListUl"/><span style="margin-left: 8px;">{{ column.name }}</span>
</template>
<x-timeline v-if="column.listId" ref="timeline" src="list" :list="column.listId" @after="() => $emit('loaded')"/>
</x-column>
</template>
<script lang="ts">
import Vue from 'vue';
import { faListUl, faCog } from '@fortawesome/free-solid-svg-icons';
import XColumn from './column.vue';
import XTimeline from '../timeline.vue';
export default Vue.extend({
components: {
XColumn,
XTimeline,
},
props: {
column: {
type: Object,
required: true
},
isStacked: {
type: Boolean,
required: true
}
},
data() {
return {
faListUl
};
},
watch: {
mediaOnly() {
(this.$refs.timeline as any).reload();
}
},
created() {
this.menu = [{
icon: faCog,
text: this.$t('list'),
action: this.setList
}];
},
mounted() {
if (this.column.listId == null) {
this.setList();
}
},
methods: {
async setList() {
const lists = await this.$root.api('users/lists/list');
const { canceled, result: list } = await this.$root.dialog({
title: this.$t('list'),
type: null,
select: {
items: lists.map(x => ({
value: x, text: x.name
})),
default: this.column.listId
},
showCancelButton: true
});
if (canceled) return;
Vue.set(this.column, 'listId', list.id);
this.$store.commit('deviceUser/updateDeckColumn', this.column);
},
focus() {
(this.$refs.timeline as any).focus();
}
}
});
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,39 @@
<template>
<x-column :column="column" :is-stacked="isStacked" :menu="menu">
<template #header><fa :icon="faAt" style="margin-right: 8px;"/>{{ column.name }}</template>
<x-mentions/>
</x-column>
</template>
<script lang="ts">
import Vue from 'vue';
import { faAt } from '@fortawesome/free-solid-svg-icons';
import XColumn from './column.vue';
import XMentions from '../../pages/mentions.vue';
export default Vue.extend({
components: {
XColumn,
XMentions
},
props: {
column: {
type: Object,
required: true
},
isStacked: {
type: Boolean,
required: true
}
},
data() {
return {
menu: null,
faAt
}
},
});
</script>

View File

@ -0,0 +1,69 @@
<template>
<x-column :column="column" :is-stacked="isStacked" :menu="menu">
<template #header><fa :icon="faBell" style="margin-right: 8px;"/>{{ column.name }}</template>
<x-notifications/>
</x-column>
</template>
<script lang="ts">
import Vue from 'vue';
import { faCog } from '@fortawesome/free-solid-svg-icons';
import { faBell } from '@fortawesome/free-regular-svg-icons';
import XColumn from './column.vue';
import XNotifications from '../notifications.vue';
export default Vue.extend({
components: {
XColumn,
XNotifications
},
props: {
column: {
type: Object,
required: true
},
isStacked: {
type: Boolean,
required: true
}
},
data() {
return {
menu: null,
faBell
}
},
created() {
if (this.column.notificationType == null) {
this.column.notificationType = 'all';
this.$store.commit('deviceUser/updateDeckColumn', this.column);
}
this.menu = [{
icon: faCog,
text: this.$t('@.notification-type'),
action: () => {
this.$root.dialog({
title: this.$t('@.notification-type'),
type: null,
select: {
items: ['all', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest'].map(x => ({
value: x, text: this.$t('@.notification-types.' + x)
}))
default: this.column.notificationType,
},
showCancelButton: true
}).then(({ canceled, result: type }) => {
if (canceled) return;
this.column.notificationType = type;
this.$store.commit('deviceUser/updateDeckColumn', this.column);
});
}
}];
},
});
</script>

View File

@ -0,0 +1,145 @@
<template>
<x-column :menu="menu" :column="column" :is-stacked="isStacked" :indicated="indicated" @change-active-state="onChangeActiveState">
<template #header>
<fa v-if="column.tl === 'home'" :icon="faHome"/>
<fa v-else-if="column.tl === 'local'" :icon="faComments"/>
<fa v-else-if="column.tl === 'social'" :icon="faShareAlt"/>
<fa v-else-if="column.tl === 'global'" :icon="faGlobe"/>
<span style="margin-left: 8px;">{{ column.name }}</span>
</template>
<div class="iwaalbte" v-if="disabled">
<p>
<fa :icon="faMinusCircle"/>
{{ $t('disabled-timeline.title') }}
</p>
<p class="desc">{{ $t('disabled-timeline.description') }}</p>
</div>
<x-timeline v-else-if="column.tl" ref="timeline" :src="column.tl" @after="() => $emit('loaded')" @queue="queueUpdated" @note="onNote" :key="column.tl"/>
</x-column>
</template>
<script lang="ts">
import Vue from 'vue';
import { faMinusCircle, faHome, faComments, faShareAlt, faGlobe, faCog } from '@fortawesome/free-solid-svg-icons';
import XColumn from './column.vue';
import XTimeline from '../timeline.vue';
export default Vue.extend({
components: {
XColumn,
XTimeline,
},
props: {
column: {
type: Object,
required: true
},
isStacked: {
type: Boolean,
required: true
}
},
data() {
return {
menu: null,
disabled: false,
indicated: false,
columnActive: true,
faMinusCircle, faHome, faComments, faShareAlt, faGlobe,
};
},
watch: {
mediaOnly() {
(this.$refs.timeline as any).reload();
}
},
created() {
this.menu = [{
icon: faCog,
text: this.$t('timeline'),
action: this.setType
}];
},
mounted() {
if (this.column.tl == null) {
this.setType();
} else {
this.disabled = !this.$store.state.i.isModerator && !this.$store.state.i.isAdmin && (
this.$store.state.instance.meta.disableLocalTimeline && ['local', 'social'].includes(this.column.tl) ||
this.$store.state.instance.meta.disableGlobalTimeline && ['global'].includes(this.column.tl));
}
},
methods: {
async setType() {
const { canceled, result: src } = await this.$root.dialog({
title: this.$t('timeline'),
type: null,
select: {
items: [{
value: 'home', text: this.$t('_timelines.home')
}, {
value: 'local', text: this.$t('_timelines.local')
}, {
value: 'social', text: this.$t('_timelines.social')
}, {
value: 'global', text: this.$t('_timelines.global')
}]
},
});
if (canceled) {
if (this.column.tl == null) {
this.setType();
}
return;
}
Vue.set(this.column, 'tl', src);
this.$store.commit('deviceUser/updateDeckColumn', this.column);
},
queueUpdated(q) {
if (this.columnActive) {
this.indicated = q !== 0;
}
},
onNote() {
if (!this.columnActive) {
this.indicated = true;
}
},
onChangeActiveState(state) {
this.columnActive = state;
if (this.columnActive) {
this.indicated = false;
}
},
focus() {
(this.$refs.timeline as any).focus();
}
}
});
</script>
<style lang="scss" scoped>
.iwaalbte {
text-align: center;
> p {
margin: 16px;
&.desc {
font-size: 14px;
}
}
}
</style>

View File

@ -0,0 +1,151 @@
<template>
<x-column :menu="menu" :naked="true" :column="column" :is-stacked="isStacked">
<template #header><fa :icon="faWindowMaximize" style="margin-right: 8px;"/>{{ column.name }}</template>
<div class="wtdtxvec">
<template v-if="edit">
<header>
<select v-model="widgetAdderSelected" @change="addWidget">
<option v-for="widget in widgets" :value="widget" :key="widget">{{ widget }}</option>
</select>
</header>
<x-draggable
:list="column.widgets"
animation="150"
@sort="onWidgetSort"
>
<div v-for="widget in column.widgets" class="customize-container" :key="widget.id" @click="widgetFunc(widget.id)">
<button class="remove _button" @click="removeWidget(widget)"><fa :icon="faTimes"/></button>
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" :column="column"/>
</div>
</x-draggable>
</template>
<component v-else class="widget" v-for="widget in column.widgets" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" :column="column"/>
</div>
</x-column>
</template>
<script lang="ts">
import Vue from 'vue';
import * as XDraggable from 'vuedraggable';
import { v4 as uuid } from 'uuid';
import { faWindowMaximize, faTimes } from '@fortawesome/free-solid-svg-icons';
import XColumn from './column.vue';
import { widgets } from '../../widgets';
export default Vue.extend({
components: {
XColumn,
XDraggable,
},
props: {
column: {
type: Object,
required: true,
},
isStacked: {
type: Boolean,
required: true,
},
},
data() {
return {
edit: false,
menu: null,
widgetAdderSelected: null,
widgets,
faWindowMaximize, faTimes
};
},
created() {
this.menu = [{
icon: 'cog',
text: this.$t('edit'),
action: () => {
this.edit = !this.edit;
}
}];
},
methods: {
widgetFunc(id) {
this.$refs[id][0].setting();
},
onWidgetSort() {
this.saveWidgets();
},
addWidget() {
this.$store.commit('deviceUser/addDeckWidget', {
id: this.column.id,
widget: {
name: this.widgetAdderSelected,
id: uuid(),
data: {}
}
});
this.widgetAdderSelected = null;
},
removeWidget(widget) {
this.$store.commit('deviceUser/removeDeckWidget', {
id: this.column.id,
widget
});
},
saveWidgets() {
this.$store.commit('deviceUser/updateDeckColumn', this.column);
}
}
});
</script>
<style lang="scss" scoped>
.wtdtxvec {
padding-top: 1px; // ウィジェットのbox-shadowを利用した1px borderを隠さないようにするため
> header {
padding: 16px;
> * {
width: 100%;
padding: 4px;
}
}
> .widget, .customize-container {
margin: 8px;
&:first-of-type {
margin-top: 0;
}
}
.customize-container {
position: relative;
cursor: move;
> *:not(.remove) {
pointer-events: none;
}
> .remove {
position: absolute;
z-index: 2;
top: 8px;
right: 8px;
width: 32px;
height: 32px;
color: #fff;
background: rgba(#000, 0.7);
border-radius: 4px;
}
}
}
</style>

View File

@ -57,11 +57,8 @@ import MkInput from './ui/input.vue';
import MkSelect from './ui/select.vue';
import MkSignin from './signin.vue';
import parseAcct from '../../misc/acct/parse';
import i18n from '../i18n';
export default Vue.extend({
i18n,
components: {
MkButton,
MkInput,

View File

@ -12,13 +12,10 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import XDrive from './drive.vue';
import XWindow from './window.vue';
export default Vue.extend({
i18n,
components: {
XDrive,
XWindow,

View File

@ -32,7 +32,6 @@
<script lang="ts">
import Vue from 'vue';
import { faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons';
import i18n from '../i18n';
import copyToClipboard from '../scripts/copy-to-clipboard';
//import updateAvatar from '../api/update-avatar';
//import updateBanner from '../api/update-banner';
@ -40,8 +39,6 @@ import XFileThumbnail from './drive-file-thumbnail.vue';
import { faDownload, faLink, faICursor, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
export default Vue.extend({
i18n,
components: {
XFileThumbnail
},

View File

@ -28,11 +28,8 @@
<script lang="ts">
import Vue from 'vue';
import { faFolder, faFolderOpen } from '@fortawesome/free-regular-svg-icons';
import i18n from '../i18n';
export default Vue.extend({
i18n,
props: {
folder: {
type: Object,

View File

@ -15,11 +15,8 @@
<script lang="ts">
import Vue from 'vue';
import { faCloud } from '@fortawesome/free-solid-svg-icons';
import i18n from '../i18n';
export default Vue.extend({
i18n,
props: {
folder: {
type: Object,

View File

@ -19,17 +19,17 @@
@drop.prevent.stop="onDrop"
>
<div class="contents" ref="contents">
<div class="folders" ref="foldersContainer" v-if="folders.length > 0">
<div class="folders" ref="foldersContainer" v-show="folders.length > 0">
<x-folder v-for="f in folders" :key="f.id" class="folder" :folder="f" :select-mode="select === 'folder'" :is-selected="selectedFolders.some(x => x.id === f.id)" @chosen="chooseFolder"/>
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
<div class="padding" v-for="(n, i) in 16" :key="i"></div>
<mk-button v-if="moreFolders">{{ $t('loadMore') }}</mk-button>
<mk-button ref="moreFolders" v-if="moreFolders">{{ $t('loadMore') }}</mk-button>
</div>
<div class="files" ref="filesContainer" v-if="files.length > 0">
<div class="files" ref="filesContainer" v-show="files.length > 0">
<x-file v-for="file in files" :key="file.id" class="file" :file="file" :select-mode="select === 'file'" :is-selected="selectedFiles.some(x => x.id === file.id)" @chosen="chooseFile"/>
<!-- SEE: https://stackoverflow.com/questions/18744164/flex-box-align-last-row-to-grid -->
<div class="padding" v-for="(n, i) in 16" :key="i"></div>
<mk-button v-if="moreFiles" @click="fetchMoreFiles">{{ $t('loadMore') }}</mk-button>
<mk-button ref="loadMoreFiles" @click="fetchMoreFiles" v-show="moreFiles">{{ $t('loadMore') }}</mk-button>
</div>
<div class="empty" v-if="files.length == 0 && folders.length == 0 && !fetching">
<p v-if="draghover">{{ $t('empty-draghover') }}</p>
@ -48,7 +48,6 @@
<script lang="ts">
import Vue from 'vue';
import { faAngleRight } from '@fortawesome/free-solid-svg-icons';
import i18n from '../i18n';
import XNavFolder from './drive.nav-folder.vue';
import XFolder from './drive.folder.vue';
import XFile from './drive.file.vue';
@ -56,8 +55,6 @@ import XUploader from './uploader.vue';
import MkButton from './ui/button.vue';
export default Vue.extend({
i18n,
components: {
XNavFolder,
XFolder,
@ -119,6 +116,13 @@ export default Vue.extend({
fetching: true,
ilFilesObserver: new IntersectionObserver(
(entries) => entries.some((entry) => entry.isIntersecting)
&& !this.fetching && this.moreFiles &&
this.fetchMoreFiles()
),
moreFilesElement: null as Element,
faAngleRight
};
},
@ -130,6 +134,12 @@ export default Vue.extend({
},
mounted() {
if (this.$store.state.device.enableInfiniteScroll && this.$refs.loadMoreFiles) {
this.$nextTick(() => {
this.ilFilesObserver.observe((this.$refs.loadMoreFiles as Vue).$el)
});
}
this.connection = this.$root.stream.useSharedConnection('drive');
this.connection.on('fileCreated', this.onStreamDriveFileCreated);
@ -146,8 +156,17 @@ export default Vue.extend({
}
},
activated() {
if (this.$store.state.device.enableInfiniteScroll) {
this.$nextTick(() => {
this.ilFilesObserver.observe((this.$refs.loadMoreFiles as Vue).$el)
});
}
},
beforeDestroy() {
this.connection.dispose();
this.ilFilesObserver.disconnect();
},
methods: {

View File

@ -64,17 +64,14 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import { emojilist } from '../../misc/emojilist';
import { getStaticImageUrl } from '../scripts/get-static-image-url';
import { faAsterisk, faLeaf, faUtensils, faFutbol, faCity, faDice, faGlobe, faHistory } from '@fortawesome/free-solid-svg-icons';
import { faAsterisk, faLeaf, faUtensils, faFutbol, faCity, faDice, faGlobe, faHistory, faUser } from '@fortawesome/free-solid-svg-icons';
import { faHeart, faFlag, faLaugh } from '@fortawesome/free-regular-svg-icons';
import { groupByX } from '../../prelude/array';
import XPopup from './popup.vue';
export default Vue.extend({
i18n,
components: {
XPopup,
},
@ -95,9 +92,13 @@ export default Vue.extend({
icon: faAsterisk,
isActive: true
}, {
name: 'people',
name: 'face',
icon: faLaugh,
isActive: false
}, {
name: 'people',
icon: faUser,
isActive: false
}, {
name: 'animals_and_nature',
icon: faLeaf,

View File

@ -1,19 +1,19 @@
<template>
<div class="mjndxjcg _panel">
<img src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/>
<p><fa :icon="faExclamationTriangle"/> {{ $t('error') }}</p>
<mk-button @click="() => $emit('retry')" class="button">{{ $t('retry') }}</mk-button>
</div>
<transition :name="$store.state.device.animation ? 'zoom' : ''" appear>
<div class="mjndxjcg _panel">
<img src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/>
<p><fa :icon="faExclamationTriangle"/> {{ $t('error') }}</p>
<mk-button @click="() => $emit('retry')" class="button">{{ $t('retry') }}</mk-button>
</div>
</transition>
</template>
<script lang="ts">
import Vue from 'vue';
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import i18n from '../i18n';
import MkButton from './ui/button.vue';
export default Vue.extend({
i18n,
components: {
MkButton,
},
@ -40,7 +40,7 @@ export default Vue.extend({
> img {
vertical-align: bottom;
height: 150px;
height: 128px;
margin-bottom: 16px;
border-radius: 16px;
}

View File

@ -30,12 +30,9 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import { faSpinner, faPlus, faMinus, faHourglassHalf } from '@fortawesome/free-solid-svg-icons';
export default Vue.extend({
i18n,
props: {
user: {
type: Object,

View File

@ -0,0 +1,71 @@
<template>
<x-window ref="window" :width="400" :height="450" :no-padding="true" @closed="() => { $emit('closed'); destroyDom(); }" :with-ok-button="true" :ok-button-disabled="false" @ok="ok()" :can-close="false">
<template #header>
{{ title }}
</template>
<div class="xkpnjxcv">
<label v-for="item in Object.keys(form).filter(item => !form[item].hidden)" :key="item">
<mk-input v-if="form[item].type === 'number'" v-model="values[item]" type="number" :step="form[item].step || 1"><span v-text="form[item].label || item"></span></mk-input>
<mk-input v-else-if="form[item].type === 'string' && !item.multiline" v-model="values[item]" type="text"><span v-text="form[item].label || item"></span></mk-input>
<mk-textarea v-else-if="form[item].type === 'string' && item.multiline" v-model="values[item]"><span v-text="form[item].label || item"></span></mk-textarea>
<mk-switch v-else-if="form[item].type === 'boolean'" v-model="values[item]"><span v-text="form[item].label || item"></span></mk-switch>
</label>
</div>
</x-window>
</template>
<script lang="ts">
import Vue from 'vue';
import XWindow from './window.vue';
import MkInput from './ui/input.vue';
import MkTextarea from './ui/textarea.vue';
import MkSwitch from './ui/switch.vue';
export default Vue.extend({
components: {
XWindow,
MkInput,
MkTextarea,
MkSwitch,
},
props: {
title: {
type: String,
required: true,
},
form: {
type: Object,
required: true,
},
},
data() {
return {
values: {}
};
},
created() {
for (const item in this.form) {
Vue.set(this.values, item, this.form[item].default || null);
}
},
methods: {
ok() {
this.$emit('ok', this.values);
this.$refs.window.close();
},
}
});
</script>
<style lang="scss" scoped>
.xkpnjxcv {
> label {
display: block;
padding: 16px 24px;
}
}
</style>

View File

@ -8,10 +8,8 @@
<script lang="ts">
import Vue from 'vue';
import { faSearch } from '@fortawesome/free-solid-svg-icons';
import i18n from '../i18n';
export default Vue.extend({
i18n,
props: ['q'],
data() {
return {
@ -46,10 +44,12 @@ export default Vue.extend({
font-size: 16px;
border: solid 1px var(--divider);
border-radius: 4px 0 0 4px;
-webkit-appearance: textfield;
}
> button {
flex-shrink: 0;
margin: 0;
padding: 0 16px;
border: solid 1px var(--divider);
border-left: none;

View File

@ -6,12 +6,9 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import XModal from './modal.vue';
export default Vue.extend({
i18n,
components: {
XModal,
},

View File

@ -125,7 +125,6 @@
import Vue from 'vue';
import { faChartBar, faUser, faPencilAlt } from '@fortawesome/free-solid-svg-icons';
import Chart from 'chart.js';
import i18n from '../i18n';
import MkSelect from './ui/select.vue';
const chartLimit = 90;
@ -140,8 +139,6 @@ const alpha = (hex, a) => {
};
export default Vue.extend({
i18n,
components: {
MkSelect
},

View File

@ -62,13 +62,13 @@ export default Vue.extend({
}
},
onMouseover() {
if (isDeviceTouch()) return;
if (isDeviceTouch) return;
clearTimeout(this.showTimer);
clearTimeout(this.hideTimer);
this.showTimer = setTimeout(this.showPreview, 500);
},
onMouseleave() {
if (isDeviceTouch()) return;
if (isDeviceTouch) return;
clearTimeout(this.showTimer);
clearTimeout(this.hideTimer);
this.hideTimer = setTimeout(this.closePreview, 500);

View File

@ -28,10 +28,8 @@
<script lang="ts">
import Vue from 'vue';
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import i18n from '../i18n';
export default Vue.extend({
i18n,
props: {
media: {
type: Object,

View File

@ -21,12 +21,10 @@
<script lang="ts">
import Vue from 'vue';
import { faExclamationTriangle, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import i18n from '../i18n';
import { getStaticImageUrl } from '../scripts/get-static-image-url';
import ImageViewer from './image-viewer.vue';
export default Vue.extend({
i18n,
props: {
image: {
type: Object,

View File

@ -23,10 +23,8 @@
import Vue from 'vue';
import { faPlayCircle } from '@fortawesome/free-regular-svg-icons';
import { faExclamationTriangle, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import i18n from '../i18n';
export default Vue.extend({
i18n,
props: {
video: {
type: Object,

View File

@ -1,5 +1,5 @@
<template>
<router-link class="ldlomzub" :to="url" v-user-preview="canonical" v-if="url.startsWith('/')">
<router-link class="ldlomzub" :class="{ isMe }" :to="url" v-user-preview="canonical" v-if="url.startsWith('/')">
<span class="me" v-if="isMe">{{ $t('you') }}</span>
<span class="main">
<span class="username">@{{ username }}</span>
@ -16,12 +16,10 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import { toUnicode } from 'punycode';
import { host as localHost } from '../config';
export default Vue.extend({
i18n,
props: {
username: {
type: String,
@ -65,6 +63,10 @@ export default Vue.extend({
<style lang="scss" scoped>
.ldlomzub {
color: var(--mention);
&.isMe {
color: var(--mentionMe);
}
> .me {
pointer-events: none;

View File

@ -1,5 +1,5 @@
import Vue, { VNode } from 'vue';
import { MfmForest } from '../../mfm/types';
import { MfmForest } from '../../mfm/prelude';
import { parse, parsePlain } from '../../mfm/parse';
import MkUrl from './url.vue';
import MkLink from './link.vue';
@ -53,11 +53,11 @@ export default Vue.component('misskey-flavored-markdown', {
if (!this.plain) {
const x = text.split('\n')
.map(t => t == '' ? [createElement('br')] : [createElement('span', t), createElement('br')]);
.map(t => t == '' ? [createElement('br')] : [this._v(t), createElement('br')]); // NOTE: this._vはHACK SEE: https://github.com/syuilo/misskey/pull/6399#issuecomment-632820283
x[x.length - 1].pop();
return x;
} else {
return [createElement('span', text.replace(/\n/g, ' '))];
return [this._v(text.replace(/\n/g, ' '))];
}
}

View File

@ -1,10 +1,10 @@
<template>
<div class="mk-modal" v-hotkey.global="keymap">
<transition :name="$store.state.device.animation ? 'bg-fade' : ''" appear>
<div class="bg" ref="bg" v-if="show" @click="close()"></div>
<div class="bg" ref="bg" v-if="show" @click="canClose ? close() : () => {}"></div>
</transition>
<transition :name="$store.state.device.animation ? 'modal' : ''" appear @after-leave="() => { $emit('closed'); destroyDom(); }">
<div class="content" ref="content" v-if="show" @click.self="close()"><slot></slot></div>
<div class="content" ref="content" v-if="show" @click.self="canClose ? close() : () => {}"><slot></slot></div>
</transition>
</div>
</template>
@ -14,6 +14,11 @@ import Vue from 'vue';
export default Vue.extend({
props: {
canClose: {
type: Boolean,
required: false,
default: true,
},
},
data() {
return {

View File

@ -12,18 +12,19 @@
<router-link class="created-at" :to="note | notePage">
<mk-time :time="note.createdAt"/>
</router-link>
<span class="visibility" v-if="note.visibility != 'public'">
<fa v-if="note.visibility == 'home'" :icon="faHome"/>
<fa v-if="note.visibility == 'followers'" :icon="faUnlock"/>
<fa v-if="note.visibility == 'specified'" :icon="faEnvelope"/>
<span class="visibility" v-if="note.visibility !== 'public'">
<fa v-if="note.visibility === 'home'" :icon="faHome"/>
<fa v-if="note.visibility === 'followers'" :icon="faUnlock"/>
<fa v-if="note.visibility === 'specified'" :icon="faEnvelope"/>
</span>
<span class="localOnly" v-if="note.localOnly"><fa :icon="faBiohazard"/></span>
</div>
</header>
</template>
<script lang="ts">
import Vue from 'vue';
import { faHome, faUnlock, faEnvelope, faMobileAlt, faBookmark } from '@fortawesome/free-solid-svg-icons';
import { faHome, faUnlock, faEnvelope, faMobileAlt, faBookmark, faBiohazard } from '@fortawesome/free-solid-svg-icons';
import { faBookmark as farBookmark } from '@fortawesome/free-regular-svg-icons';
export default Vue.extend({
@ -36,7 +37,7 @@ export default Vue.extend({
data() {
return {
faHome, faUnlock, faEnvelope, faMobileAlt, faBookmark, farBookmark
faHome, faUnlock, faEnvelope, faMobileAlt, faBookmark, farBookmark, faBiohazard
};
}
});
@ -53,7 +54,6 @@ export default Vue.extend({
margin: 0 .5em 0 0;
padding: 0;
overflow: hidden;
color: var(--noteHeaderName);
font-size: 1em;
font-weight: bold;
text-decoration: none;
@ -97,6 +97,10 @@ export default Vue.extend({
> .visibility {
margin-left: 8px;
}
> .localOnly {
margin-left: 8px;
}
}
}
</style>

View File

@ -50,15 +50,7 @@ export default Vue.extend({
margin: 0;
padding: 0;
overflow: hidden;
font-size: 10px;
@media (min-width: 350px) {
font-size: 12px;
}
@media (min-width: 500px) {
font-size: 14px;
}
font-size: 0.95em;
> .avatar {

View File

@ -21,12 +21,16 @@
</router-link>
</i18n>
<div class="info">
<button class="_button time" @click="showRenoteMenu()" ref="renoteTime"><mk-time :time="note.createdAt"/></button>
<button class="_button time" @click="showRenoteMenu()" ref="renoteTime">
<fa class="dropdownIcon" v-if="isMyRenote" :icon="faEllipsisH"/>
<mk-time :time="note.createdAt"/>
</button>
<span class="visibility" v-if="note.visibility !== 'public'">
<fa v-if="note.visibility === 'home'" :icon="faHome"/>
<fa v-if="note.visibility === 'followers'" :icon="faUnlock"/>
<fa v-if="note.visibility === 'specified'" :icon="faEnvelope"/>
</span>
<span class="localOnly" v-if="note.localOnly"><fa :icon="faBiohazard"/></span>
</div>
</div>
<article class="article">
@ -49,7 +53,7 @@
<x-media-list :media-list="appearNote.files" :parent-element="noteBody"/>
</div>
<x-poll v-if="appearNote.poll" :note="appearNote" ref="pollViewer" class="poll"/>
<mk-url-preview v-for="url in urls" :url="url" :key="url" :compact="true" class="url-preview"/>
<mk-url-preview v-for="url in urls" :url="url" :key="url" :compact="true" :detail="detail" class="url-preview"/>
<div class="renote" v-if="appearNote.renote"><x-note-preview :note="appearNote.renote"/></div>
</div>
</div>
@ -85,11 +89,10 @@
<script lang="ts">
import Vue from 'vue';
import { faBolt, faTimes, faBullhorn, faStar, faLink, faExternalLinkSquareAlt, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faQuoteRight, faInfoCircle } from '@fortawesome/free-solid-svg-icons';
import { faBolt, faTimes, faBullhorn, faStar, faLink, faExternalLinkSquareAlt, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faQuoteRight, faInfoCircle, faBiohazard, faPlug } from '@fortawesome/free-solid-svg-icons';
import { faCopy, faTrashAlt, faEdit, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons';
import { parse } from '../../mfm/parse';
import { sum, unique } from '../../prelude/array';
import i18n from '../i18n';
import XSub from './note.sub.vue';
import XNoteHeader from './note-header.vue';
import XNotePreview from './note-preview.vue';
@ -105,8 +108,6 @@ import { url } from '../config';
import copyToClipboard from '../scripts/copy-to-clipboard';
export default Vue.extend({
i18n,
components: {
XSub,
XNoteHeader,
@ -143,7 +144,7 @@ export default Vue.extend({
showContent: false,
hideThisNote: false,
noteBody: this.$refs.noteBody,
faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan
faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faBiohazard, faPlug
};
},
@ -193,6 +194,10 @@ export default Vue.extend({
return this.$store.getters.isSignedIn && (this.$store.state.i.id === this.appearNote.userId);
},
isMyRenote(): boolean {
return this.$store.getters.isSignedIn && (this.$store.state.i.id === this.note.userId);
},
canRenote(): boolean {
return ['public', 'home'].includes(this.appearNote.visibility) || this.isMyNote;
},
@ -606,6 +611,16 @@ export default Vue.extend({
.filter(x => x !== undefined);
}
if (this.$store.state.noteActions.length > 0) {
menu = menu.concat([null, ...this.$store.state.noteActions.map(action => ({
icon: faPlug,
text: action.title,
action: () => {
action.handler(this.appearNote);
}
}))]);
}
this.$root.menu({
items: menu,
source: this.$refs.menuButton,
@ -614,7 +629,7 @@ export default Vue.extend({
},
showRenoteMenu(viaKeyboard = false) {
if (!this.$store.getters.isSignedIn || (this.$store.state.i.id !== this.note.userId)) return;
if (!this.isMyRenote) return;
this.$root.menu({
items: [{
text: this.$t('unrenote'),
@ -718,61 +733,6 @@ export default Vue.extend({
transition: box-shadow 0.1s ease;
overflow: hidden;
&.max-width_500px {
font-size: 0.9em;
}
&.max-width_450px {
> .renote {
padding: 8px 16px 0 16px;
}
> .article {
padding: 14px 16px 9px;
> .avatar {
margin: 0 10px 8px 0;
width: 50px;
height: 50px;
}
}
}
&.max-width_350px {
> .article {
> .main {
> .footer {
> .button {
&:not(:last-child) {
margin-right: 18px;
}
}
}
}
}
}
&.max-width_300px {
font-size: 0.825em;
> .article {
> .avatar {
width: 44px;
height: 44px;
}
> .main {
> .footer {
> .button {
&:not(:last-child) {
margin-right: 12px;
}
}
}
}
}
}
&:focus {
outline: none;
box-shadow: 0 0 0 3px var(--focus);
@ -791,10 +751,6 @@ export default Vue.extend({
white-space: pre;
color: #d28a3f;
@media (max-width: 450px) {
padding: 8px 16px 0 16px;
}
> [data-icon] {
margin-right: 4px;
}
@ -857,14 +813,18 @@ export default Vue.extend({
> .time {
flex-shrink: 0;
color: inherit;
> .dropdownIcon {
margin-right: 4px;
}
}
> .visibility {
margin-left: 8px;
}
[data-icon] {
margin-right: 0;
}
> .localOnly {
margin-left: 8px;
}
}
}
@ -975,5 +935,64 @@ export default Vue.extend({
> .reply {
border-top: solid 1px var(--divider);
}
&.max-width_500px {
font-size: 0.9em;
}
&.max-width_450px {
> .renote {
padding: 8px 16px 0 16px;
}
> .info {
padding: 8px 16px 0 16px;
}
> .article {
padding: 14px 16px 9px;
> .avatar {
margin: 0 10px 8px 0;
width: 50px;
height: 50px;
}
}
}
&.max-width_350px {
> .article {
> .main {
> .footer {
> .button {
&:not(:last-child) {
margin-right: 18px;
}
}
}
}
}
}
&.max-width_300px {
font-size: 0.825em;
> .article {
> .avatar {
width: 44px;
height: 44px;
}
> .main {
> .footer {
> .button {
&:not(:last-child) {
margin-right: 12px;
}
}
}
}
}
}
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<div class="mk-notes" v-size="[{ max: 500 }]">
<div class="mk-notes">
<div class="_fullinfo" v-if="empty">
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
<div>{{ $t('noNotes') }}</div>
@ -7,19 +7,19 @@
<mk-error v-if="error" @retry="init()"/>
<div v-if="more && reversed" style="margin-bottom: var(--margin);">
<button class="_panel _button" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" @click="fetchMore()">
<div v-show="more && reversed" style="margin-bottom: var(--margin);">
<button class="_panel _button" ref="loadMore" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
<template v-if="!moreFetching">{{ $t('loadMore') }}</template>
<template v-if="moreFetching"><mk-loading inline/></template>
</button>
</div>
<x-list ref="notes" class="notes" :items="notes" v-slot="{ item: note }" :direction="reversed ? 'up' : 'down'" :reversed="reversed">
<x-list ref="notes" :items="notes" v-slot="{ item: note }" :direction="reversed ? 'up' : 'down'" :reversed="reversed">
<x-note :note="note" :detail="detail" :key="note._featuredId_ || note._prId_ || note.id"/>
</x-list>
<div v-if="more && !reversed" style="margin-top: var(--margin);">
<button class="_panel _button" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" @click="fetchMore()">
<div v-show="more && !reversed" style="margin-top: var(--margin);">
<button class="_panel _button" ref="loadMore" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
<template v-if="!moreFetching">{{ $t('loadMore') }}</template>
<template v-if="moreFetching"><mk-loading inline/></template>
</button>
@ -29,15 +29,12 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import paging from '../scripts/paging';
import XNote from './note.vue';
import XList from './date-separated-list.vue';
import MkButton from './ui/button.vue';
export default Vue.extend({
i18n,
components: {
XNote, XList, MkButton
},
@ -88,21 +85,3 @@ export default Vue.extend({
});
</script>
<style lang="scss" scoped>
.mk-notes {
> .notes {
> ::v-deep *:not(:last-child) {
margin-bottom: var(--marginFull);
}
}
&.max-width_500px {
> .notes {
> ::v-deep *:not(:last-child) {
//margin-bottom: var(--marginHalf);
margin-bottom: 0;
}
}
}
}
</style>

View File

@ -61,13 +61,11 @@
import Vue from 'vue';
import { faIdCardAlt, faPlus, faQuoteLeft, faQuoteRight, faRetweet, faReply, faAt, faCheck, faPollH } from '@fortawesome/free-solid-svg-icons';
import { faClock } from '@fortawesome/free-regular-svg-icons';
import getNoteSummary from '../../misc/get-note-summary';
import noteSummary from '../../misc/get-note-summary';
import XReactionIcon from './reaction-icon.vue';
import MkFollowButton from './follow-button.vue';
import i18n from '../i18n';
export default Vue.extend({
i18n,
components: {
XReactionIcon, MkFollowButton
},
@ -89,12 +87,39 @@ export default Vue.extend({
},
data() {
return {
getNoteSummary,
getNoteSummary: (text: string) => noteSummary(text, this.$root.i18n.messages[this.$root.i18n.locale]),
followRequestDone: false,
groupInviteDone: false,
connection: null,
readObserver: null,
faIdCardAlt, faPlus, faQuoteLeft, faQuoteRight, faRetweet, faReply, faAt, faClock, faCheck, faPollH
};
},
mounted() {
if (!this.notification.isRead) {
this.readObserver = new IntersectionObserver((entries, observer) => {
if (!entries.some(entry => entry.isIntersecting)) return;
this.$root.stream.send('readNotification', {
id: this.notification.id
});
entries.map(({ target }) => observer.unobserve(target));
});
this.readObserver.observe(this.$el);
this.connection = this.$root.stream.useSharedConnection('main');
this.connection.on('readAllNotifications', () => this.readObserver.unobserve(this.$el));
}
},
beforeDestroy() {
if (!this.notification.isRead) {
this.readObserver.unobserve(this.$el);
this.connection.dispose();
}
},
methods: {
acceptFollowRequest() {
this.followRequestDone = true;

View File

@ -5,7 +5,7 @@
<x-notification v-else :notification="notification" :with-time="true" :full="true" class="_panel notification" :key="notification.id"/>
</x-list>
<button class="_panel _button" v-if="more" @click="fetchMore" :disabled="moreFetching">
<button class="_panel _button" ref="loadMore" v-show="more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
<template v-if="!moreFetching">{{ $t('loadMore') }}</template>
<template v-if="moreFetching"><mk-loading inline/></template>
</button>
@ -18,15 +18,12 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import paging from '../scripts/paging';
import XNotification from './notification.vue';
import XList from './date-separated-list.vue';
import XNote from './note.vue';
export default Vue.extend({
i18n,
components: {
XNotification,
XList,
@ -74,10 +71,13 @@ export default Vue.extend({
methods: {
onNotification(notification) {
// TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない
this.$root.stream.send('readNotification', {
id: notification.id
});
if (document.visibilityState === 'visible') {
this.$root.stream.send('readNotification', {
id: notification.id
});
notification.isRead = true;
}
this.prepend(notification);
},
@ -87,13 +87,6 @@ export default Vue.extend({
<style lang="scss" scoped>
.mfcuwfyp {
> .notifications {
> ::v-deep * {
//margin-bottom: var(--margin);
margin-bottom: 0;
}
}
> .empty {
margin: 0;
padding: 16px;

View File

@ -8,13 +8,11 @@
<script lang="ts">
import Vue from 'vue';
import { faCheck, faPaperPlane } from '@fortawesome/free-solid-svg-icons';
import i18n from '../../i18n';
import MkTextarea from '../ui/textarea.vue';
import MkButton from '../ui/button.vue';
import { apiUrl } from '../../config';
export default Vue.extend({
i18n,
components: {
MkTextarea,
MkButton,

View File

@ -9,14 +9,11 @@ import Vue from 'vue';
import { parse } from '@syuilo/aiscript';
import { faHeart as faHeartS } from '@fortawesome/free-solid-svg-icons';
import { faHeart } from '@fortawesome/free-regular-svg-icons';
import i18n from '../../i18n';
import XBlock from './page.block.vue';
import { Hpml } from '../../scripts/hpml/evaluator';
import { url } from '../../config';
export default Vue.extend({
i18n,
components: {
XBlock
},

View File

@ -51,7 +51,6 @@
<script lang="ts">
import Vue from 'vue';
import { faExclamationTriangle, faTimes } from '@fortawesome/free-solid-svg-icons';
import i18n from '../i18n';
import { erase } from '../../prelude/array';
import { addTime } from '../../prelude/time';
import { formatDateTimeString } from '../../misc/format-time-string';
@ -61,7 +60,6 @@ import MkSwitch from './ui/switch.vue';
import MkButton from './ui/button.vue';
export default Vue.extend({
i18n,
components: {
MkInput,
MkSelect,

View File

@ -24,11 +24,9 @@
<script lang="ts">
import Vue from 'vue';
import { faCheck } from '@fortawesome/free-solid-svg-icons';
import i18n from '../i18n';
import { sum } from '../../prelude/array';
export default Vue.extend({
i18n,
props: {
note: {
type: Object,

View File

@ -14,15 +14,12 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import * as XDraggable from 'vuedraggable';
import { faTimesCircle, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons';
import { faExclamationTriangle, faICursor } from '@fortawesome/free-solid-svg-icons';
import XFileThumbnail from './drive-file-thumbnail.vue'
export default Vue.extend({
i18n,
components: {
XDraggable,
XFileThumbnail

View File

@ -8,8 +8,9 @@
<header>
<button v-if="!fixed" class="cancel _button" @click="cancel"><fa :icon="faTimes"/></button>
<div>
<span class="local-only" v-if="localOnly" v-text="$t('_visibility.localOnly')" />
<span class="text-count" :class="{ over: trimmedLength(text) > max }">{{ max - trimmedLength(text) }}</span>
<button class="_button visibility" @click="setVisibility" ref="visibilityButton">
<button class="_button visibility" @click="setVisibility" ref="visibilityButton" v-tooltip="$t('visibility')">
<span v-if="visibility === 'public'"><fa :icon="faGlobe"/></span>
<span v-if="visibility === 'home'"><fa :icon="faHome"/></span>
<span v-if="visibility === 'followers'"><fa :icon="faUnlock"/></span>
@ -25,7 +26,7 @@
<div v-if="visibility === 'specified'" class="to-specified">
<span style="margin-right: 8px;">{{ $t('recipient') }}</span>
<div class="visibleUsers">
<span v-for="u in visibleUsers">
<span v-for="u in visibleUsers" :key="u.id">
<mk-acct :user="u"/>
<button class="_button" @click="removeVisibleUser(u)"><fa :icon="faTimes"/></button>
</span>
@ -38,12 +39,12 @@
<x-poll-editor v-if="poll" ref="poll" @destroyed="poll = false" @updated="onPollUpdate()"/>
<x-uploader ref="uploader" @uploaded="attachMedia" @change="onChangeUploadings"/>
<footer>
<button class="_button" @click="chooseFileFrom"><fa :icon="faPhotoVideo"/></button>
<button class="_button" @click="poll = !poll" :class="{ active: poll }"><fa :icon="faPollH"/></button>
<button class="_button" @click="useCw = !useCw" :class="{ active: useCw }"><fa :icon="faEyeSlash"/></button>
<button class="_button" @click="insertMention"><fa :icon="faAt"/></button>
<button class="_button" @click="insertEmoji"><fa :icon="faLaughSquint"/></button>
<button class="_button" v-if="visibility !== 'specified'" @click="localOnly = !localOnly" :class="{ active: localOnly }"><fa :icon="faBiohazard"/></button>
<button class="_button" @click="chooseFileFrom" v-tooltip="$t('attachFile')"><fa :icon="faPhotoVideo"/></button>
<button class="_button" @click="poll = !poll" :class="{ active: poll }" v-tooltip="$t('poll')"><fa :icon="faPollH"/></button>
<button class="_button" @click="useCw = !useCw" :class="{ active: useCw }" v-tooltip="$t('useCw')"><fa :icon="faEyeSlash"/></button>
<button class="_button" @click="insertMention" v-tooltip="$t('mention')"><fa :icon="faAt"/></button>
<button class="_button" @click="insertEmoji" v-tooltip="$t('emoji')"><fa :icon="faLaughSquint"/></button>
<button class="_button" @click="showActions" v-tooltip="$t('plugin')" v-if="$store.state.postFormActions.length > 0"><fa :icon="faPlug"/></button>
</footer>
<input ref="file" class="file _button" type="file" multiple="multiple" @change="onChangeFile"/>
</div>
@ -52,12 +53,11 @@
<script lang="ts">
import Vue from 'vue';
import { faReply, faQuoteRight, faPaperPlane, faTimes, faUpload, faPollH, faGlobe, faHome, faUnlock, faEnvelope, faPlus, faPhotoVideo, faCloud, faLink, faAt, faBiohazard } from '@fortawesome/free-solid-svg-icons';
import { faReply, faQuoteRight, faPaperPlane, faTimes, faUpload, faPollH, faGlobe, faHome, faUnlock, faEnvelope, faPlus, faPhotoVideo, faCloud, faLink, faAt, faBiohazard, faPlug } from '@fortawesome/free-solid-svg-icons';
import { faEyeSlash, faLaughSquint } from '@fortawesome/free-regular-svg-icons';
import insertTextAtCursor from 'insert-text-at-cursor';
import { length } from 'stringz';
import { toASCII } from 'punycode';
import i18n from '../i18n';
import MkVisibilityChooser from './visibility-chooser.vue';
import MkUserSelect from './user-select.vue';
import XNotePreview from './note-preview.vue';
@ -68,10 +68,9 @@ import extractMentions from '../../misc/extract-mentions';
import getAcct from '../../misc/acct/render';
import { formatTimeString } from '../../misc/format-time-string';
import { selectDriveFile } from '../scripts/select-drive-file';
import { noteVisibilities } from '../../types';
export default Vue.extend({
i18n,
components: {
XNotePreview,
XUploader: () => import('./uploader.vue').then(m => m.default),
@ -135,7 +134,7 @@ export default Vue.extend({
draghover: false,
quoteId: null,
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'),
faReply, faQuoteRight, faPaperPlane, faTimes, faUpload, faPollH, faGlobe, faHome, faUnlock, faEnvelope, faEyeSlash, faLaughSquint, faPlus, faPhotoVideo, faCloud, faLink, faAt, faBiohazard
faReply, faQuoteRight, faPaperPlane, faTimes, faUpload, faPollH, faGlobe, faHome, faUnlock, faEnvelope, faEyeSlash, faLaughSquint, faPlus, faPhotoVideo, faCloud, faLink, faAt, faBiohazard, faPlug
};
},
@ -400,15 +399,17 @@ export default Vue.extend({
setVisibility() {
const w = this.$root.new(MkVisibilityChooser, {
source: this.$refs.visibilityButton,
currentVisibility: this.visibility
currentVisibility: this.visibility,
currentLocalOnly: this.localOnly
});
w.$once('chosen', v => {
this.applyVisibility(v);
w.$once('chosen', ({ visibility, localOnly }) => {
this.applyVisibility(visibility);
this.localOnly = localOnly;
});
},
applyVisibility(v: string) {
this.visibility = ['public', 'home', 'followers', 'specified'].includes(v) ? v : 'public'; // v11互換性のため
this.visibility = (noteVisibilities as unknown as string[]).includes(v) ? v : 'public'; // v11互換性のため
},
addVisibleUser() {
@ -579,6 +580,22 @@ export default Vue.extend({
insertTextAtCursor(this.$refs.text, emoji);
vm.close();
});
},
showActions(ev) {
this.$root.menu({
items: this.$store.state.postFormActions.map(action => ({
text: action.title,
action: () => {
action.handler({
text: this.text
}, (key, value) => {
if (key === 'text') { this.text = value; }
});
}
})),
source: ev.currentTarget || ev.target,
});
}
}
});
@ -626,6 +643,14 @@ export default Vue.extend({
height: 34px;
width: 34px;
margin: 0 8px;
& + .localOnly {
margin-left: 0 !important;
}
}
.local-only {
margin: 0 8px;
}
> .submit {
@ -705,7 +730,7 @@ export default Vue.extend({
margin-right: 14px;
padding: 8px 0 8px 8px;
border-radius: 8px;
background: var(--nwjktjjq);
background: var(--X4);
> button {
padding: 4px 8px;
@ -787,7 +812,7 @@ export default Vue.extend({
border-radius: 6px;
&:hover {
background: var(--geavgsxy);
background: var(--X5);
}
&.active {

View File

@ -4,9 +4,7 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
export default Vue.extend({
i18n,
props: {
reaction: {
type: String,

View File

@ -4,21 +4,18 @@
<div class="buttons" ref="buttons" :class="{ showFocus }">
<button class="_button" v-for="(reaction, i) in rs" :key="reaction" @click="react(reaction)" :tabindex="i + 1" :title="reaction" v-particle><x-reaction-icon :reaction="reaction"/></button>
</div>
<input class="text" v-model="text" :placeholder="$t('enterEmoji')" @keyup.enter="reactText" @input="tryReactText" v-autocomplete="{ model: 'text' }">
<input class="text" v-model.trim="text" :placeholder="$t('enterEmoji')" @keyup.enter="reactText" @input="tryReactText" v-autocomplete="{ model: 'text' }">
</div>
</x-popup>
</template>
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import { emojiRegex } from '../../misc/emoji-regex';
import XReactionIcon from './reaction-icon.vue';
import XPopup from './popup.vue';
export default Vue.extend({
i18n,
components: {
XPopup,
XReactionIcon,

View File

@ -1,29 +1,29 @@
<template>
<transition name="zoom-in-top">
<div class="buebdbiu" ref="popover" v-if="show">
<template v-if="users.length <= 10">
<b v-for="u in users" :key="u.id" style="margin-right: 12px;">
<mk-avatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/>
<mk-user-name :user="u" :nowrap="false" style="line-height: 24px;"/>
</b>
</template>
<template v-if="10 < users.length">
<b v-for="u in users" :key="u.id" style="margin-right: 12px;">
<mk-avatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/>
<mk-user-name :user="u" :nowrap="false" style="line-height: 24px;"/>
</b>
<span slot="omitted">+{{ count - 10 }}</span>
</template>
</div>
</transition>
<mk-tooltip :source="source" ref="tooltip">
<template v-if="users.length <= 10">
<b v-for="u in users" :key="u.id" style="margin-right: 12px;">
<mk-avatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/>
<mk-user-name :user="u" :nowrap="false" style="line-height: 24px;"/>
</b>
</template>
<template v-if="10 < users.length">
<b v-for="u in users" :key="u.id" style="margin-right: 12px;">
<mk-avatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/>
<mk-user-name :user="u" :nowrap="false" style="line-height: 24px;"/>
</b>
<span slot="omitted">+{{ count - 10 }}</span>
</template>
</mk-tooltip>
</template>
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import MkTooltip from './ui/tooltip.vue';
export default Vue.extend({
i18n,
components: {
MkTooltip
},
props: {
reaction: {
type: String,
@ -41,77 +41,11 @@ export default Vue.extend({
required: true,
}
},
data() {
return {
show: false
};
},
mounted() {
this.show = true;
this.$nextTick(() => {
const popover = this.$refs.popover as any;
if (this.source == null) {
this.destroyDom();
return;
}
const rect = this.source.getBoundingClientRect();
const x = rect.left + window.pageXOffset + (this.source.offsetWidth / 2);
const y = rect.top + window.pageYOffset + this.source.offsetHeight;
popover.style.left = (x - 28) + 'px';
popover.style.top = (y + 16) + 'px';
});
}
methods: {
close() {
this.show = false;
setTimeout(this.destroyDom, 300);
this.$refs.tooltip.close();
}
}
})
</script>
<style lang="scss" scoped>
.buebdbiu {
z-index: 10000;
display: block;
position: absolute;
max-width: 240px;
font-size: 0.8em;
padding: 6px 8px;
background: var(--panel);
text-align: center;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0,0,0,0.25);
pointer-events: none;
transform-origin: center -16px;
&:before {
content: "";
pointer-events: none;
display: block;
position: absolute;
top: -28px;
left: 12px;
border-top: solid 14px transparent;
border-right: solid 14px transparent;
border-bottom: solid 14px rgba(0,0,0,0.1);
border-left: solid 14px transparent;
}
&:after {
content: "";
pointer-events: none;
display: block;
position: absolute;
top: -27px;
left: 12px;
border-top: solid 14px transparent;
border-right: solid 14px transparent;
border-bottom: solid 14px var(--panel);
border-left: solid 14px transparent;
}
}
</style>

View File

@ -4,12 +4,14 @@
:class="{ reacted: note.myReaction == reaction, canToggle }"
@click="toggleReaction(reaction)"
v-if="count > 0"
@touchstart="onMouseover"
@mouseover="onMouseover"
@mouseleave="onMouseleave"
@touchend="onMouseleave"
ref="reaction"
v-particle
v-particle="canToggle"
>
<x-reaction-icon :reaction="reaction" :customEmojis="note.emojis" ref="icon"/>
<x-reaction-icon :reaction="reaction" :custom-emojis="note.emojis" ref="icon"/>
<span>{{ count }}</span>
</button>
</template>
@ -53,21 +55,20 @@ export default Vue.extend({
return this.$store.getters.isSignedIn && this.$store.state.i.id === this.note.userId;
},
canToggle(): boolean {
return !this.reaction.match(/@\w/);
return !this.reaction.match(/@\w/) && !this.isMe && this.$store.getters.isSignedIn;
},
},
mounted() {
if (!this.isInitial) this.anime();
},
watch: {
count(newCount, oldCount) {
if (oldCount < newCount) this.anime();
if (this.details != null) this.openDetails();
},
},
mounted() {
if (!this.isInitial) this.anime();
},
methods: {
toggleReaction() {
if (this.isMe) return;
if (!this.canToggle) return;
const oldReaction = this.note.myReaction;
@ -90,16 +91,17 @@ export default Vue.extend({
}
},
onMouseover() {
if (this.isHovering) return;
this.isHovering = true;
this.detailsTimeoutId = setTimeout(this.openDetails, 300);
},
onMouseleave() {
if (!this.isHovering) return;
this.isHovering = false;
clearTimeout(this.detailsTimeoutId);
this.closeDetails();
},
openDetails() {
if (this.$root.isMobile) return;
this.$root.api('notes/reactions', {
noteId: this.note.id,
type: this.reaction,

View File

@ -5,10 +5,8 @@
<script lang="ts">
import Vue from 'vue';
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import i18n from '../i18n';
export default Vue.extend({
i18n,
props: {
href: {
type: String,

View File

@ -0,0 +1,488 @@
<template>
<div class="mvcprjjd">
<transition name="nav-back">
<div class="nav-back"
v-if="showing"
@click="showing = false"
@touchstart="showing = false"
></div>
</transition>
<transition name="nav">
<nav class="nav" v-show="showing">
<div>
<button class="item _button account" @click="openAccountMenu" v-if="$store.getters.isSignedIn">
<mk-avatar :user="$store.state.i" class="avatar"/><mk-acct class="text" :user="$store.state.i"/>
</button>
<button class="item _button index active" @click="top()" v-if="$route.name === 'index'">
<fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
</button>
<router-link class="item index" active-class="active" to="/" exact v-else>
<fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
</router-link>
<template v-for="item in menu">
<div v-if="item === '-'" class="divider"></div>
<component v-else-if="menuDef[item] && (menuDef[item].show !== false)" :is="menuDef[item].to ? 'router-link' : 'button'" class="item _button" :class="item" active-class="active" @click="() => { if (menuDef[item].action) menuDef[item].action() }" :to="menuDef[item].to">
<fa :icon="menuDef[item].icon" fixed-width/><span class="text">{{ $t(menuDef[item].title) }}</span>
<i v-if="menuDef[item].indicated"><fa :icon="faCircle"/></i>
</component>
</template>
<div class="divider"></div>
<button class="item _button" :class="{ active: $route.path === '/instance' || $route.path.startsWith('/instance/') }" v-if="$store.getters.isSignedIn && ($store.state.i.isAdmin || $store.state.i.isModerator)" @click="oepnInstanceMenu">
<fa :icon="faServer" fixed-width/><span class="text">{{ $t('instance') }}</span>
</button>
<button class="item _button" @click="more">
<fa :icon="faEllipsisH" fixed-width/><span class="text">{{ $t('more') }}</span>
<i v-if="otherNavItemIndicated"><fa :icon="faCircle"/></i>
</button>
<router-link class="item" active-class="active" to="/preferences">
<fa :icon="faCog" fixed-width/><span class="text">{{ $t('settings') }}</span>
</router-link>
</div>
</nav>
</transition>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import { faGripVertical, faChevronLeft, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faListUl, faPlus, faUserClock, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faInfoCircle, faQuestionCircle, faProjectDiagram } from '@fortawesome/free-solid-svg-icons';
import { faBell, faEnvelope, faLaugh, faComments } from '@fortawesome/free-regular-svg-icons';
import { host, instanceName } from '../config';
import { search } from '../scripts/search';
export default Vue.extend({
data() {
return {
host: host,
showing: false,
searching: false,
accounts: [],
connection: null,
menuDef: this.$store.getters.nav({
search: this.search
}),
faGripVertical, faChevronLeft, faComments, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faBell, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faEnvelope, faListUl, faPlus, faUserClock, faLaugh, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faProjectDiagram
};
},
computed: {
menu(): string[] {
return this.$store.state.deviceUser.menu;
},
otherNavItemIndicated(): boolean {
if (!this.$store.getters.isSignedIn) return false;
for (const def in this.menuDef) {
if (this.menu.includes(def)) continue;
if (this.menuDef[def].indicated) return true;
}
return false;
},
},
watch: {
$route(to, from) {
this.showing = false;
},
},
methods: {
show() {
this.showing = true;
},
search() {
if (this.searching) return;
this.$root.dialog({
title: this.$t('search'),
input: true
}).then(async ({ canceled, result: query }) => {
if (canceled || query == null || query === '') return;
this.searching = true;
search(this, query).finally(() => {
this.searching = false;
});
});
},
async openAccountMenu(ev) {
const accounts = (await this.$root.api('users/show', { userIds: this.$store.state.device.accounts.map(x => x.id) })).filter(x => x.id !== this.$store.state.i.id);
const accountItems = accounts.map(account => ({
type: 'user',
user: account,
action: () => { this.switchAccount(account); }
}));
this.$root.menu({
items: [...[{
type: 'link',
text: this.$t('profile'),
to: `/@${ this.$store.state.i.username }`,
avatar: this.$store.state.i,
}, {
type: 'link',
text: this.$t('accountSettings'),
to: '/my/settings',
icon: faCog,
}, null, ...accountItems, {
icon: faPlus,
text: this.$t('addAcount'),
action: () => {
this.$root.menu({
items: [{
text: this.$t('existingAcount'),
action: () => { this.addAcount(); },
}, {
text: this.$t('createAccount'),
action: () => { this.createAccount(); },
}],
align: 'left',
fixed: true,
width: 240,
source: ev.currentTarget || ev.target,
});
},
}]],
align: 'left',
fixed: true,
width: 240,
source: ev.currentTarget || ev.target,
});
},
oepnInstanceMenu(ev) {
this.$root.menu({
items: [{
type: 'link',
text: this.$t('dashboard'),
to: '/instance',
icon: faTachometerAlt,
}, null, {
type: 'link',
text: this.$t('settings'),
to: '/instance/settings',
icon: faCog,
}, {
type: 'link',
text: this.$t('customEmojis'),
to: '/instance/emojis',
icon: faLaugh,
}, {
type: 'link',
text: this.$t('users'),
to: '/instance/users',
icon: faUsers,
}, {
type: 'link',
text: this.$t('files'),
to: '/instance/files',
icon: faCloud,
}, {
type: 'link',
text: this.$t('jobQueue'),
to: '/instance/queue',
icon: faExchangeAlt,
}, {
type: 'link',
text: this.$t('federation'),
to: '/instance/federation',
icon: faGlobe,
}, {
type: 'link',
text: this.$t('relays'),
to: '/instance/relays',
icon: faProjectDiagram,
}, {
type: 'link',
text: this.$t('announcements'),
to: '/instance/announcements',
icon: faBroadcastTower,
}],
align: 'left',
fixed: true,
width: 200,
source: ev.currentTarget || ev.target,
});
},
more(ev) {
const items = Object.keys(this.menuDef).filter(k => !this.menu.includes(k)).map(k => this.menuDef[k]).filter(def => def.show == null ? true : def.show).map(def => ({
type: def.to ? 'link' : 'button',
text: this.$t(def.title),
icon: def.icon,
to: def.to,
action: def.action,
indicate: def.indicated,
}));
this.$root.menu({
items: [...items, null, {
type: 'link',
text: this.$t('help'),
to: '/docs',
icon: faQuestionCircle,
}, {
type: 'link',
text: this.$t('aboutX', { x: instanceName || host }),
to: '/about',
icon: faInfoCircle,
}, {
type: 'link',
text: this.$t('aboutMisskey'),
to: '/about-misskey',
icon: faInfoCircle,
}],
align: 'left',
fixed: true,
width: 200,
source: ev.currentTarget || ev.target,
});
},
async addAcount() {
this.$root.new(await import('./signin-dialog.vue').then(m => m.default)).$once('login', res => {
this.$store.dispatch('addAcount', res);
this.$root.dialog({
type: 'success',
iconOnly: true, autoClose: true
});
});
},
async createAccount() {
this.$root.new(await import('./signup-dialog.vue').then(m => m.default)).$once('signup', res => {
this.$store.dispatch('addAcount', res);
this.switchAccountWithToken(res.i);
});
},
async switchAccount(account: any) {
const token = this.$store.state.device.accounts.find((x: any) => x.id === account.id).token;
this.switchAccountWithToken(token);
},
switchAccountWithToken(token: string) {
this.$root.dialog({
type: 'waiting',
iconOnly: true
});
this.$root.api('i', {}, token).then((i: any) => {
this.$store.dispatch('switchAccount', {
...i,
token: token
}).then(() => {
this.$nextTick(() => {
location.reload();
});
});
});
},
}
});
</script>
<style lang="scss" scoped>
.nav-enter-active,
.nav-leave-active {
opacity: 1;
transform: translateX(0);
transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.nav-enter,
.nav-leave-active {
opacity: 0;
transform: translateX(-240px);
}
.nav-back-enter-active,
.nav-back-leave-active {
opacity: 1;
transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.nav-back-enter,
.nav-back-leave-active {
opacity: 0;
}
.mvcprjjd {
$ui-font-size: 1em; // TODO: どこかに集約したい
$nav-width: 250px; // TODO: どこかに集約したい
$nav-icon-only-width: 80px; // TODO: どこかに集約したい
$nav-icon-only-threshold: 1279px; // TODO: どこかに集約したい
$nav-hide-threshold: 650px; // TODO: どこかに集約したい
> .nav-back {
position: fixed;
top: 0;
left: 0;
z-index: 1001;
width: 100%;
height: 100%;
background: var(--modalBg);
}
> .nav {
$avatar-size: 32px;
$avatar-margin: 8px;
flex: 0 0 $nav-width;
width: $nav-width;
box-sizing: border-box;
@media (max-width: $nav-icon-only-threshold) {
flex: 0 0 $nav-icon-only-width;
width: $nav-icon-only-width;
}
@media (max-width: $nav-hide-threshold) {
position: fixed;
top: 0;
left: 0;
z-index: 1001;
}
@media (min-width: $nav-hide-threshold + 1px) {
display: block !important;
}
> div {
position: fixed;
top: 0;
left: 0;
z-index: 1001;
width: $nav-width;
height: 100vh;
box-sizing: border-box;
overflow: auto;
background: var(--navBg);
border-right: solid 1px var(--divider);
> .divider {
margin: 16px 0;
border-top: solid 1px var(--divider);
}
@media (max-width: $nav-icon-only-threshold) and (min-width: $nav-hide-threshold + 1px) {
width: $nav-icon-only-width;
> .divider {
margin: 8px auto;
width: calc(100% - 32px);
}
> .item {
&:first-child {
margin-bottom: 8px;
}
&:last-child {
margin-top: 8px;
}
}
}
> .item {
position: relative;
display: block;
padding-left: 32px;
font-size: $ui-font-size;
line-height: 3.2rem;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
text-align: left;
box-sizing: border-box;
color: var(--navFg);
> [data-icon] {
width: 32px;
}
> [data-icon],
> .avatar {
margin-right: $avatar-margin;
}
> .avatar {
width: $avatar-size;
height: $avatar-size;
vertical-align: middle;
}
> i {
position: absolute;
top: 0;
left: 20px;
color: var(--navIndicator);
font-size: 8px;
animation: blink 1s infinite;
}
&:hover {
text-decoration: none;
color: var(--navHoverFg);
}
&.active {
color: var(--navActive);
}
&:first-child, &:last-child {
position: sticky;
z-index: 1;
padding-top: 8px;
padding-bottom: 8px;
background: var(--X14);
-webkit-backdrop-filter: blur(8px);
backdrop-filter: blur(8px);
}
&:first-child {
top: 0;
margin-bottom: 16px;
border-bottom: solid 1px var(--divider);
}
&:last-child {
bottom: 0;
margin-top: 16px;
border-top: solid 1px var(--divider);
}
@media (max-width: $nav-icon-only-threshold) and (min-width: $nav-hide-threshold + 1px) {
padding-left: 0;
width: 100%;
text-align: center;
font-size: $ui-font-size * 1.2;
line-height: 3.7rem;
> [data-icon],
> .avatar {
margin-right: 0;
}
> i {
left: 10px;
}
> .text {
display: none;
}
}
}
@media (max-width: $nav-hide-threshold) {
> .index,
> .notifications {
display: none;
}
}
}
}
}
</style>

View File

@ -7,13 +7,10 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import XWindow from './window.vue';
import MkSignin from './signin.vue';
export default Vue.extend({
i18n,
components: {
MkSignin,
XWindow,

View File

@ -49,13 +49,10 @@ import { faLock, faGavel } from '@fortawesome/free-solid-svg-icons';
import { faTwitter, faDiscord, faGithub } from '@fortawesome/free-brands-svg-icons';
import MkButton from './ui/button.vue';
import MkInput from './ui/input.vue';
import i18n from '../i18n';
import { apiUrl, host } from '../config';
import { byteify, hexify } from '../scripts/2fa';
export default Vue.extend({
i18n,
components: {
MkButton,
MkInput,

View File

@ -7,13 +7,10 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
import XWindow from './window.vue';
import XSignup from './signup.vue';
export default Vue.extend({
i18n,
components: {
XSignup,
XWindow,

View File

@ -53,15 +53,12 @@ import Vue from 'vue';
import { faLock, faExclamationTriangle, faSpinner, faCheck, faKey } from '@fortawesome/free-solid-svg-icons';
const getPasswordStrength = require('syuilo-password-strength');
import { toUnicode } from 'punycode';
import i18n from '../i18n';
import { host, url } from '../config';
import MkButton from './ui/button.vue';
import MkInput from './ui/input.vue';
import MkSwitch from './ui/switch.vue';
export default Vue.extend({
i18n,
components: {
MkButton,
MkInput,
@ -183,7 +180,7 @@ export default Vue.extend({
password: this.password,
invitationCode: this.invitationCode,
'hcaptcha-response': this.hCaptchaResponse,
'g-recaptcha-response': this.meta.reCaptchaResponse,
'g-recaptcha-response': this.reCaptchaResponse,
}).then(() => {
this.$root.api('signin', {
username: this.username,

View File

@ -10,10 +10,8 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
export default Vue.extend({
i18n,
data() {
return {
hasDisconnected: false,

View File

@ -21,12 +21,10 @@
<script lang="ts">
import Vue from 'vue';
import { faReply } from '@fortawesome/free-solid-svg-icons';
import i18n from '../i18n';
import XPoll from './poll.vue';
import XMediaList from './media-list.vue';
export default Vue.extend({
i18n,
components: {
XPoll,
XMediaList,

View File

@ -8,10 +8,8 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../i18n';
export default Vue.extend({
i18n,
props: {
time: {
type: [Date, String],

View File

@ -17,9 +17,11 @@ export default Vue.extend({
required: true
},
list: {
type: String,
required: false
},
antenna: {
type: String,
required: false
},
sound: {
@ -53,6 +55,8 @@ export default Vue.extend({
const _note = JSON.parse(JSON.stringify(note)); // deepcopy
(this.$refs.tl as any).prepend(_note);
this.$emit('note');
if (this.sound) {
this.$root.sound(note.userId === this.$store.state.i.id ? 'noteMy' : 'note');
}
@ -77,10 +81,10 @@ export default Vue.extend({
if (this.src == 'antenna') {
endpoint = 'antennas/notes';
this.query = {
antennaId: this.antenna.id
antennaId: this.antenna
};
this.connection = this.$root.stream.connectToChannel('antenna', {
antennaId: this.antenna.id
antennaId: this.antenna
});
this.connection.on('note', prepend);
} else if (this.src == 'home') {
@ -106,10 +110,10 @@ export default Vue.extend({
} else if (this.src == 'list') {
endpoint = 'notes/user-list-timeline';
this.query = {
listId: this.list.id
listId: this.list
};
this.connection = this.$root.stream.connectToChannel('userList', {
listId: this.list.id
listId: this.list
});
this.connection.on('note', prepend);
this.connection.on('userAdded', onUserAdded);

View File

@ -126,11 +126,11 @@ export default Vue.extend({
background: var(--accent);
&:not(:disabled):hover {
background: var(--jkhztclx);
background: var(--X8);
}
&:not(:disabled):active {
background: var(--jkhztclx);
background: var(--X8);
}
}

View File

@ -1,5 +1,5 @@
<template>
<div class="ukygtjoj _panel" :class="{ naked, hideHeader: !showHeader }">
<div class="ukygtjoj _panel" :class="{ naked, hideHeader: !showHeader, scrollable }" v-size="[{ max: 500 }]">
<header v-if="showHeader">
<div class="title"><slot name="header"></slot></div>
<slot name="func"></slot>
@ -47,6 +47,11 @@ export default Vue.extend({
required: false,
default: true
},
scrollable: {
type: Boolean,
required: false,
default: false
},
},
data() {
return {
@ -107,19 +112,26 @@ export default Vue.extend({
box-shadow: none !important;
}
&.scrollable {
display: flex;
flex-direction: column;
> div {
overflow: auto;
}
}
> header {
position: relative;
box-shadow: 0 1px 0 0 var(--divider);
z-index: 1;
box-shadow: 0 1px 0 0 var(--panelHeaderDivider);
z-index: 2;
background: var(--panelHeaderBg);
color: var(--panelHeaderFg);
> .title {
margin: 0;
padding: 12px 16px;
@media (max-width: 500px) {
padding: 8px 10px;
}
> [data-icon] {
margin-right: 6px;
}
@ -139,5 +151,21 @@ export default Vue.extend({
height: 100%;
}
}
&.max-width_500px {
> header {
> .title {
padding: 8px 10px;
}
}
}
}
._forceContainerFull_ .ukygtjoj {
> header {
> .title {
padding: 12px 16px !important;
}
}
}
</style>

View File

@ -20,6 +20,7 @@
:pattern="pattern"
:autocomplete="autocomplete"
:spellcheck="spellcheck"
:step="step"
@focus="focused = true"
@blur="focused = false"
@keydown="$emit('keydown', $event)"
@ -36,6 +37,7 @@
:pattern="pattern"
:autocomplete="autocomplete"
:spellcheck="spellcheck"
:step="step"
@focus="focused = true"
@blur="focused = false"
@keydown="$emit('keydown', $event)"
@ -114,6 +116,9 @@ export default Vue.extend({
spellcheck: {
required: false
},
step: {
required: false
},
debounce: {
required: false
},
@ -164,7 +169,7 @@ export default Vue.extend({
},
v(v) {
if (this.type === 'number') {
this.$emit('input', parseInt(v, 10));
this.$emit('input', parseFloat(v));
} else {
this.$emit('input', v);
}
@ -297,7 +302,7 @@ export default Vue.extend({
pointer-events: none;
transition: 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition-duration: 0.3s;
font-size: 16px;
font-size: 1em;
line-height: 32px;
color: var(--inputLabel);
pointer-events: none;
@ -312,7 +317,7 @@ export default Vue.extend({
top: -17px;
left: 0 !important;
pointer-events: none;
font-size: 16px;
font-size: 1em;
line-height: 32px;
color: var(--inputLabel);
pointer-events: none;
@ -343,7 +348,7 @@ export default Vue.extend({
padding: 0;
font: inherit;
font-weight: normal;
font-size: 16px;
font-size: 1em;
line-height: $height;
color: var(--inputText);
background: transparent;
@ -364,7 +369,7 @@ export default Vue.extend({
position: absolute;
z-index: 1;
top: 0;
font-size: 16px;
font-size: 1em;
line-height: 32px;
color: var(--inputLabel);
pointer-events: none;

View File

@ -4,8 +4,8 @@
<div class="empty" v-if="empty" key="_empty_">
<slot name="empty"></slot>
</div>
<div class="more" v-if="more" key="_more_">
<mk-button class="button" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" @click="fetchMore()" primary>
<div class="more" v-show="more" key="_more_">
<mk-button class="button" ref="loadMore" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary>
<template v-if="!moreFetching">{{ $t('loadMore') }}</template>
<template v-if="moreFetching"><mk-loading inline/></template>
</mk-button>

View File

@ -95,7 +95,7 @@ export default Vue.extend({
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: var(--xxubwiul);
background: var(--X10);
height: 7px;
margin: 0 8px;
outline: 0;

View File

@ -135,7 +135,7 @@ export default Vue.extend({
pointer-events: none;
transition: 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
transition-duration: 0.3s;
font-size: 16px;
font-size: 1em;
line-height: 32px;
pointer-events: none;
//will-change transform
@ -150,7 +150,7 @@ export default Vue.extend({
padding: 0;
font: inherit;
font-weight: normal;
font-size: 16px;
font-size: 1em;
height: 32px;
background: none;
border: none;
@ -170,7 +170,7 @@ export default Vue.extend({
display: block;
align-self: center;
justify-self: center;
font-size: 16px;
font-size: 1em;
line-height: 32px;
color: rgba(#000, 0.54);
pointer-events: none;

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