Compare commits

...

92 Commits

Author SHA1 Message Date
syuilo
c3c885de47 8.35.0 2018-09-13 02:52:29 +09:00
syuilo
8a8c079b2f Improve following/followers view
Closes #2235
2018-09-13 02:08:17 +09:00
syuilo
b4a30e2a25 Refactor: remove needless await 2018-09-13 02:07:03 +09:00
syuilo
f19f92c538 Clean up: Remove unused import 2018-09-13 01:50:36 +09:00
syuilo
e1a946ab45 Fix bug 2018-09-13 01:50:21 +09:00
syuilo
aa1817737e Fix glitch 2018-09-13 01:06:18 +09:00
syuilo
25ec5a24ab Add toLowerCase 2018-09-12 06:33:02 +09:00
Aya Morisawa
2118fadc48 Add toUpperCase function (#2697) 2018-09-12 03:51:33 +09:00
syuilo
ca2230f690 Refactor 2018-09-12 03:32:47 +09:00
Aya Morisawa
0ed197d4d9 Use unique (#2695) 2018-09-12 03:02:14 +09:00
syuilo
046976dffc Resolve #2691 2018-09-12 02:48:19 +09:00
syuilo
bb8139196e Fix wrong indentation 2018-09-12 01:48:30 +09:00
syuilo
1fea2cdcbe Fix bug 2018-09-11 20:57:25 +09:00
syuilo
fe3dd25bc3 8.34.4 2018-09-10 21:40:14 +09:00
syuilo
5b09209ef9 Fix bug 2018-09-10 21:36:43 +09:00
syuilo
62db650e3c Revert "Fix bug"
This reverts commit f3ab8199a5.
2018-09-10 21:17:49 +09:00
rinsuki
b847886254 fix docs (#2678) 2018-09-10 18:32:51 +09:00
syuilo
c6e69ffae4 8.34.3 2018-09-10 18:07:38 +09:00
Acid Chicken (硫酸鶏)
b24f368d3f サロゲートペアを字数にカウントしないようにする (#2661)
* Update post-form.vue

* Update messaging-message.ts

* Update post-form.vue

* Update note.ts

* Update post-form.vue

refs: https://github.com/syuilo/misskey/pull/2661#issuecomment-419579444

* Update post-form.vue

refs: https://github.com/syuilo/misskey/pull/2661#issuecomment-419579444

* Update messaging-message.ts

refs: https://github.com/syuilo/misskey/pull/2661#issuecomment-419579444

* Update note.ts

refs: https://github.com/syuilo/misskey/pull/2661#issuecomment-419579444

* Update post-form.vue

refs: https://github.com/syuilo/misskey/pull/2661#discussion_r216175581

* Update post-form.vue

* Update post-form.vue

refs: https://github.com/syuilo/misskey/pull/2661#discussion_r216242002

* Update post-form.vue

refs: https://github.com/syuilo/misskey/pull/2661#discussion_r216242105
2018-09-10 18:02:46 +09:00
syuilo
4dc8351f56 Optimize booting script 2018-09-10 17:50:34 +09:00
syuilo
f3ab8199a5 Fix bug 2018-09-10 17:40:41 +09:00
syuilo
28d953933a Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-09-10 15:07:52 +09:00
syuilo
77d9ae92f6 8.34.2 2018-09-10 15:07:37 +09:00
syuilo
7d00754587 Merge pull request #2676 from syuilo/l10n_develop
New Crowdin translations
2018-09-10 14:51:16 +09:00
syuilo
982b5eb698 New translations ja-JP.yml (English) 2018-09-10 14:50:54 +09:00
syuilo
20a9c25d70 Fix #2677 2018-09-10 14:48:19 +09:00
syuilo
eebed9944c 8.34.1 2018-09-10 05:45:59 +09:00
syuilo
507a192489 Fix bug 2018-09-10 05:45:29 +09:00
syuilo
689dc3b9d5 New translations ja-JP.yml (French) 2018-09-10 05:20:52 +09:00
syuilo
d765803b83 New translations ja-JP.yml (French) 2018-09-10 05:11:20 +09:00
syuilo
0fabb6a057 8.34.0 2018-09-10 03:40:01 +09:00
syuilo
23efaae85e lint 2018-09-10 03:39:00 +09:00
syuilo
5b2f15726f Fix #2675 2018-09-10 03:15:46 +09:00
syuilo
bc3a5f3512 Fix #2596 2018-09-10 03:02:06 +09:00
syuilo
ba05f236bd Resolve #2101 2018-09-10 02:47:34 +09:00
syuilo
6ac92ac4b8 Fix #2321 2018-09-10 02:43:16 +09:00
syuilo
d9a1cd082c #2623 2018-09-10 02:21:16 +09:00
syuilo
a32071541a Clean up 2018-09-10 02:20:09 +09:00
syuilo
eb4f625bbd Fix #2096 2018-09-10 02:09:33 +09:00
syuilo
e36d45507a Fix #2513 2018-09-10 02:07:13 +09:00
syuilo
e32884f07f Fix #1740 2018-09-10 01:57:19 +09:00
syuilo
1344ffa67d 削除された投稿にリアクションできないように
Closes #1778
2018-09-10 01:55:14 +09:00
syuilo
e07210524f Refactor: Add comments 2018-09-10 01:54:08 +09:00
syuilo
6f3996c061 Update theme color 2018-09-10 01:51:57 +09:00
syuilo
fd06fd4dc1 Resolve #2560 2018-09-10 01:51:46 +09:00
syuilo
d86d5feae3 Merge pull request #2660 from syuilo/l10n_develop
New Crowdin translations
2018-09-09 22:01:03 +09:00
syuilo
0e20a8f07b New translations ja-JP.yml (English) 2018-09-09 17:31:05 +09:00
syuilo
a40d784e3a New translations ja-JP.yml (English) 2018-09-09 17:10:50 +09:00
syuilo
e145131b95 New translations ja-JP.yml (English) 2018-09-09 17:00:56 +09:00
syuilo
92873b8bb5 New translations ja-JP.yml (English) 2018-09-09 03:41:10 +09:00
syuilo
d359b71c81 New translations ja-JP.yml (English) 2018-09-09 03:30:40 +09:00
syuilo
f1a0bf4257 New translations ja-JP.yml (English) 2018-09-09 03:01:16 +09:00
MeiMei
ea4e2da58d Fix AP Announce detection (#2672) 2018-09-09 02:59:14 +09:00
syuilo
1301b3b49e New translations ja-JP.yml (English) 2018-09-09 02:51:10 +09:00
syuilo
424625846e Merge branch 'master' into develop 2018-09-09 02:46:54 +09:00
syuilo
0790dd7a2c 8.33.1 2018-09-09 02:45:29 +09:00
syuilo
b238d7b934 New translations ja-JP.yml (French) 2018-09-09 00:01:22 +09:00
syuilo
011e4fded2 New translations ja-JP.yml (French) 2018-09-08 23:51:17 +09:00
syuilo
2fe872a9c9 Update README.md 2018-09-08 23:34:51 +09:00
syuilo
02c1515a0f Update README.md 2018-09-08 23:30:29 +09:00
syuilo
5e9d2d079d New translations ja-JP.yml (French) 2018-09-08 18:31:00 +09:00
syuilo
fdc16253d1 New translations ja-JP.yml (Norwegian) 2018-09-08 15:21:38 +09:00
syuilo
7e83cd2d74 New translations ja-JP.yml (Dutch) 2018-09-08 15:21:35 +09:00
syuilo
083eb75eff New translations ja-JP.yml (Japanese, Kansai) 2018-09-08 15:21:33 +09:00
syuilo
f50afa768f New translations ja-JP.yml (Spanish) 2018-09-08 15:21:31 +09:00
syuilo
1a80fe91ce New translations ja-JP.yml (Russian) 2018-09-08 15:21:29 +09:00
syuilo
4de1a5ef6c New translations ja-JP.yml (Portuguese) 2018-09-08 15:21:26 +09:00
syuilo
d0d389299b New translations ja-JP.yml (Polish) 2018-09-08 15:21:24 +09:00
syuilo
dc70804350 New translations ja-JP.yml (Korean) 2018-09-08 15:21:22 +09:00
syuilo
78d691571b New translations ja-JP.yml (Italian) 2018-09-08 15:21:20 +09:00
syuilo
b7cbf4a42a New translations ja-JP.yml (German) 2018-09-08 15:21:17 +09:00
syuilo
87ca7c50b4 New translations ja-JP.yml (French) 2018-09-08 15:21:14 +09:00
syuilo
6c7550b3f3 New translations ja-JP.yml (English) 2018-09-08 15:21:12 +09:00
syuilo
4239ffa13f New translations ja-JP.yml (Chinese Simplified) 2018-09-08 15:21:09 +09:00
syuilo
c6cfb0df76 New translations ja-JP.yml (Catalan) 2018-09-08 15:21:06 +09:00
syuilo
dc174ca759 New translations ja-JP.yml (French) 2018-09-08 00:52:35 +09:00
syuilo
b61cfd0407 New translations ja-JP.yml (English) 2018-09-07 23:22:01 +09:00
syuilo
53405e54a8 New translations ja-JP.yml (English) 2018-09-07 21:33:04 +09:00
syuilo
c7ef7531a9 New translations ja-JP.yml (Norwegian) 2018-09-07 21:22:27 +09:00
syuilo
626b4bf314 New translations ja-JP.yml (Dutch) 2018-09-07 21:22:24 +09:00
syuilo
323d0e0154 New translations ja-JP.yml (Japanese, Kansai) 2018-09-07 21:22:21 +09:00
syuilo
6d1338317b New translations ja-JP.yml (Spanish) 2018-09-07 21:22:18 +09:00
syuilo
1ce26d8aec New translations ja-JP.yml (Russian) 2018-09-07 21:22:16 +09:00
syuilo
7ba3d3ec98 New translations ja-JP.yml (Portuguese) 2018-09-07 21:22:14 +09:00
syuilo
24f58b3ecb New translations ja-JP.yml (Polish) 2018-09-07 21:22:11 +09:00
syuilo
d1d8587096 New translations ja-JP.yml (Korean) 2018-09-07 21:22:09 +09:00
syuilo
96db630f5e New translations ja-JP.yml (Italian) 2018-09-07 21:22:07 +09:00
syuilo
91fae0ae8b New translations ja-JP.yml (German) 2018-09-07 21:22:05 +09:00
syuilo
bfa1235b48 New translations ja-JP.yml (French) 2018-09-07 21:22:02 +09:00
syuilo
95d324a413 New translations ja-JP.yml (English) 2018-09-07 21:22:00 +09:00
syuilo
ef3535319b New translations ja-JP.yml (Chinese Simplified) 2018-09-07 21:21:57 +09:00
syuilo
e9c04f4fa0 New translations ja-JP.yml (Catalan) 2018-09-07 21:21:55 +09:00
57 changed files with 956 additions and 429 deletions

View File

@@ -1,4 +1,4 @@
<img src="https://github.com/syuilo/misskey/blob/b3f42e62af698a67c2250533c437569559f1fdf9/src/himasaku/resources/himasaku.png?raw=true" align="right" width="320px"/> <img src="https://github.com/syuilo/misskey/blob/develop/assets/ai-orig.png?raw=true" align="right" height="320px"/>
[![Misskey](/assets/title.png)](https://misskey.xyz/) [![Misskey](/assets/title.png)](https://misskey.xyz/)
================================================================ ================================================================
@@ -7,7 +7,7 @@
[![][dependencies-badge]][dependencies-link] [![][dependencies-badge]][dependencies-link]
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![Greenkeeper badge](https://badges.greenkeeper.io/syuilo/misskey.svg)](https://greenkeeper.io/) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![Greenkeeper badge](https://badges.greenkeeper.io/syuilo/misskey.svg)](https://greenkeeper.io/)
Sophisticated microblogging platform, evolving forever. **Sophisticated microblogging platform, evolving forever.**
[Misskey](https://misskey.xyz) is a decentralized microblogging platform born on Earth. [Misskey](https://misskey.xyz) is a decentralized microblogging platform born on Earth.
Since it exists within the Fediverse (a universe where various social media platforms are organized), Since it exists within the Fediverse (a universe where various social media platforms are organized),

View File

@@ -10,7 +10,7 @@ Misskeyサーバーの構築にご関心をお寄せいただきありがとう
*1.* Misskeyユーザーの作成 *1.* Misskeyユーザーの作成
---------------------------------------------------------------- ----------------------------------------------------------------
Misskeyrootで実行しない方がよいため、代わりにユーザーを作成します。 Misskeyrootユーザーで実行しない方がよいため、代わりにユーザーを作成します。
Debianの例: Debianの例:
``` ```

View File

@@ -6,6 +6,19 @@ common:
misskey: "A ⭐ of fediverse" misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse." about-title: "A ⭐ of fediverse."
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。" about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。"
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "広告ブロッカーを無効にしてください" detected: "広告ブロッカーを無効にしてください"
warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。" warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。"
@@ -68,6 +81,15 @@ common:
confused: "こまこまのこまり" confused: "こまこまのこまり"
rip: "RIP" rip: "RIP"
pudding: "Pudding" pudding: "Pudding"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "今どうしてる?" a: "今どうしてる?"
b: "何かありましたか?" b: "何かありましたか?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "動作" behaviour: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "ウィンドウの自動ポップアウト" auto-popout: "ウィンドウの自動ポップアウト"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
advanced: "詳細設定" advanced: "詳細設定"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "上" notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
load-raw-images: "添付された画像を高画質で表示する" load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する" load-remote-media: "リモートサーバーのメディアを表示する"

View File

@@ -6,6 +6,19 @@ common:
misskey: "A ⭐ of fediverse" misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse." about-title: "A ⭐ of fediverse."
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。" about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。"
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "広告ブロッカーを無効にしてください" detected: "広告ブロッカーを無効にしてください"
warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。" warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。"
@@ -68,6 +81,15 @@ common:
confused: "Verwirrt" confused: "Verwirrt"
rip: "RIP" rip: "RIP"
pudding: "Pudding" pudding: "Pudding"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "Was machst du gerade?" a: "Was machst du gerade?"
b: "Was ist so passiert?" b: "Was ist so passiert?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "Verhalten" behaviour: "Verhalten"
fetch-on-scroll: "Aktualisieren beim scrollen" fetch-on-scroll: "Aktualisieren beim scrollen"
fetch-on-scroll-desc: "Wenn du runterscrollst empfängt die Seite automatisch zusätzliche Inhalte." fetch-on-scroll-desc: "Wenn du runterscrollst empfängt die Seite automatisch zusätzliche Inhalte."
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "Automatische Pop-out Fenster" auto-popout: "Automatische Pop-out Fenster"
auto-popout-desc: "Pop-out ein offenes Fenster wenn möglich. Diese Einstellung wird im Browser gespeichert." auto-popout-desc: "Pop-out ein offenes Fenster wenn möglich. Diese Einstellung wird im Browser gespeichert."
advanced: "Erweiterte Einstellungen" advanced: "Erweiterte Einstellungen"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "上" notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
load-raw-images: "添付された画像を高画質で表示する" load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する" load-remote-media: "リモートサーバーのメディアを表示する"

View File

@@ -6,6 +6,19 @@ common:
misskey: "A ⭐ of the fediverse" misskey: "A ⭐ of the fediverse"
about-title: "A ⭐ of the fediverse." about-title: "A ⭐ of the fediverse."
about: "Thank you for finding Misskey. Misskey is a <b>decentralized microblogging platform</b> born on Earth. Since it exists within the Fediverse (a universe where various social media platforms are organized), it is mutually linked with other social media platforms. Why don't you take a short break from the hustle and bustle of the city, and dive into a new Internet?" about: "Thank you for finding Misskey. Misskey is a <b>decentralized microblogging platform</b> born on Earth. Since it exists within the Fediverse (a universe where various social media platforms are organized), it is mutually linked with other social media platforms. Why don't you take a short break from the hustle and bustle of the city, and dive into a new Internet?"
intro:
title: "What is Misskey?"
about: "Misskey is a open-source <b>decentralized microblogging service</b>. Sophisticated fully customizable Ui, varieties of reaction for posts, free file storage providing integrated management system and other advancing functions are available. Also, network system called “Fediverse” enables us to communicate with users on other SNSs. Like, if you post something, then your posts will sent not only to Misskey but also mastodon. Just imagine that the planet is sending a microwave to other planet to communication."
features: "Features"
rich-contents: "Post"
rich-contents-desc: "Just post your idea, hot topics and anything you want to share. You may want to decorate your words, attach your favorite pictures, send files including movies and create a poll - those are the things you can do on Misskey!"
reaction: "Reactions"
reaction-desc: "Easiest way to tell your emotions. Misskey allows you to add various type of reactions to others post. The emotional experience on Misskey will never be on other SNSs which only able to push “likes”."
ui: "Interface"
ui-desc: "No UI fits for everyone. Therefore, Misskey has a highly customizable UI for your taste. You can edit layouts of your timeline, place selectable widgets you can easily move and create your unique home as this place will be your home."
drive: "Misskey Drive"
drive-desc: "Wanna post a picture you have already uploaded? Wish to organize, name and create a folder for your uploaded files? Misskey Drive is the best solution for you. Very easy to share your files online."
outro: "Check further Misskey-unique features on your eyes! Feeling like this is not for you, try other instances as Misskey is a decentralized SNS so that you can easily find your mates. Then, GLHF!"
adblock: adblock:
detected: "Please disable ad blocker." detected: "Please disable ad blocker."
warning: "Some features may be unavailable or cause malfunctions if ad blocking features are enabled. <strong>Misskey is not running ads</strong>." warning: "Some features may be unavailable or cause malfunctions if ad blocking features are enabled. <strong>Misskey is not running ads</strong>."
@@ -68,6 +81,15 @@ common:
confused: "Confused" confused: "Confused"
rip: "RIP" rip: "RIP"
pudding: "Pudding" pudding: "Pudding"
note-visibility:
public: "Public"
home: "Home"
home-desc: "Post to the home timeline only"
followers: "Followers"
followers-desc: "Post to followers only"
specified: "Direct"
specified-desc: "Post to specified users only"
private: "Private"
note-placeholders: note-placeholders:
a: "What are you doing?" a: "What are you doing?"
b: "What's happening?" b: "What's happening?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "Behavior" behaviour: "Behavior"
fetch-on-scroll: "Endless loading on scroll" fetch-on-scroll: "Endless loading on scroll"
fetch-on-scroll-desc: "When you scroll down the page, it automatically fetches additional content." fetch-on-scroll-desc: "When you scroll down the page, it automatically fetches additional content."
note-visibility: "Post visibility"
default-note-visibility: "Default visibility"
remember-note-visibility: "Remember post visibility"
auto-popout: "Auto pop-out window" auto-popout: "Auto pop-out window"
auto-popout-desc: "If it's possible, pop-out display will be used instead of opening a new window. This setting is stored in your browser." auto-popout-desc: "If it's possible, pop-out display will be used instead of opening a new window. This setting is stored in your browser."
advanced: "Advanced settings" advanced: "Advanced settings"
@@ -905,7 +930,7 @@ desktop/views/pages/user/user.friends.vue:
no-users: "No frequent mentions" no-users: "No frequent mentions"
desktop/views/pages/user/user.vue: desktop/views/pages/user/user.vue:
is-suspended: "This account has been suspended." is-suspended: "This account has been suspended."
is-remote: "The user is a remote user. The profile that you see here may not complete." is-remote: "This profile belongs to a remote user. The profile that you see here may not be complete. "
view-remote: "See their complete profile" view-remote: "See their complete profile"
desktop/views/pages/user/user.home.vue: desktop/views/pages/user/user.home.vue:
last-used-at: "Last active:" last-used-at: "Last active:"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "Top" notification-position-top: "Top"
behavior: "Behavior" behavior: "Behavior"
fetch-on-scroll: "Endless loading on scroll" fetch-on-scroll: "Endless loading on scroll"
note-visibility: "Post visibility"
default-note-visibility: "Default visibility"
remember-note-visibility: "Remember post visibility"
disable-via-mobile: "Don't mark the post as 'from mobile'" disable-via-mobile: "Don't mark the post as 'from mobile'"
load-raw-images: "Show attached images in original quality" load-raw-images: "Show attached images in original quality"
load-remote-media: "Show media from a remote server" load-remote-media: "Show media from a remote server"

View File

@@ -6,6 +6,19 @@ common:
misskey: "Una ⭐️ del fediverso" misskey: "Una ⭐️ del fediverso"
about-title: "Una ⭐️ del fediverso" about-title: "Una ⭐️ del fediverso"
about: "Gracias por encontrae Misskey. Misskey es una <b>plataforma descentralizada de microblogging</b> nacida en la Tierra. Gracias a existir dentro del Fediverso (un universo donde se organizan varias plataformas sociales) se encuentra enlazada mutuamente con otras plataformas sociales. ¿Por què no te tomas un respiro del caos de la ciudad y te sumerges es una nueva manera de entender Internet?" about: "Gracias por encontrae Misskey. Misskey es una <b>plataforma descentralizada de microblogging</b> nacida en la Tierra. Gracias a existir dentro del Fediverso (un universo donde se organizan varias plataformas sociales) se encuentra enlazada mutuamente con otras plataformas sociales. ¿Por què no te tomas un respiro del caos de la ciudad y te sumerges es una nueva manera de entender Internet?"
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "Por favor, desactive el bloqueador de publicidad." detected: "Por favor, desactive el bloqueador de publicidad."
warning: "<strong>Misskey no tiene anuncios publicitarios.</strong> Sin embargo, algunas características podrían no estar disponibles si el bloqueador de publicidad está habilitado." warning: "<strong>Misskey no tiene anuncios publicitarios.</strong> Sin embargo, algunas características podrían no estar disponibles si el bloqueador de publicidad está habilitado."
@@ -68,6 +81,15 @@ common:
confused: "confundido" confused: "confundido"
rip: "RIP" rip: "RIP"
pudding: "Chafado" pudding: "Chafado"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "¿Qué haces?" a: "¿Qué haces?"
b: "¿Qué está pasando?" b: "¿Qué está pasando?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "Acciones" behaviour: "Acciones"
fetch-on-scroll: "Desplazamiento infinito" fetch-on-scroll: "Desplazamiento infinito"
fetch-on-scroll-desc: "Cuando te deslizas al final de la página nuevo contenido se carga automáticamente." fetch-on-scroll-desc: "Cuando te deslizas al final de la página nuevo contenido se carga automáticamente."
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "Ventana emergente automática" auto-popout: "Ventana emergente automática"
auto-popout-desc: "Muestra una ventana emergente si es posible. Esta configuración depende del navegador." auto-popout-desc: "Muestra una ventana emergente si es posible. Esta configuración depende del navegador."
advanced: "Configuración avanzada" advanced: "Configuración avanzada"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "上" notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
load-raw-images: "添付された画像を高画質で表示する" load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する" load-remote-media: "リモートサーバーのメディアを表示する"

View File

@@ -6,6 +6,19 @@ common:
misskey: "Une ⭐ du fédiverse" misskey: "Une ⭐ du fédiverse"
about-title: "Une ⭐ du fédivers." about-title: "Une ⭐ du fédivers."
about: "Merci d'avoir découvert Misskey. Misskey est une <b>plateforme de microblogage distribuée</b> née sur Terre. Parce qu'il fait partie du Fédivers (un univers composé de diverses plateformes de réseaux sociaux organisées), il est mutuellement connecté avec d'autres plateformes de réseaux sociaux. Désirez-vous prendre une pause, pendant un instant, loin de l'agitation de la ville et plonger dans un nouvel Internet ?" about: "Merci d'avoir découvert Misskey. Misskey est une <b>plateforme de microblogage distribuée</b> née sur Terre. Parce qu'il fait partie du Fédivers (un univers composé de diverses plateformes de réseaux sociaux organisées), il est mutuellement connecté avec d'autres plateformes de réseaux sociaux. Désirez-vous prendre une pause, pendant un instant, loin de l'agitation de la ville et plonger dans un nouvel Internet ?"
intro:
title: "Cest quoi Misskey ?"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "Fonctionnalités"
rich-contents: "Notes"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "Réactions"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "Interface utilisateur"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "Drive"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "Veuillez désactiver votre bloqueur de publicités" detected: "Veuillez désactiver votre bloqueur de publicités"
warning: "<strong>Misskey n'utilise pas de publicités</strong>, mais quelques options peuvent être non disponibles ou fonctionneraient mal si un bloqueur de publicités est activé." warning: "<strong>Misskey n'utilise pas de publicités</strong>, mais quelques options peuvent être non disponibles ou fonctionneraient mal si un bloqueur de publicités est activé."
@@ -68,6 +81,15 @@ common:
confused: "Confus" confused: "Confus"
rip: "RIP" rip: "RIP"
pudding: "Pudding" pudding: "Pudding"
note-visibility:
public: "Public"
home: "Accueil"
home-desc: "Publier sur le fil local uniquement"
followers: "Abonnés·es"
followers-desc: "Publier à vos abonnés·es uniquement"
specified: "Direct"
specified-desc: "Publier aux utilisateurs·trices mentionnés·es"
private: "Privé"
note-placeholders: note-placeholders:
a: "Que faites-vous maintenant ?" a: "Que faites-vous maintenant ?"
b: "Quoi de neuf ?" b: "Quoi de neuf ?"
@@ -173,7 +195,7 @@ common/views/components/games/reversi/reversi.game.vue:
surrendered: "Par abandon" surrendered: "Par abandon"
is-llotheo: "石の少ない方が勝ち(ロセオ)" is-llotheo: "石の少ない方が勝ち(ロセオ)"
looped-map: "Carte en boucle" looped-map: "Carte en boucle"
can-put-everywhere: "どこでも置けるモード" can-put-everywhere: "Peut poser partout"
common/views/components/games/reversi/reversi.index.vue: common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi" title: "Misskey Reversi"
sub-title: "Jouer à Reversi avec vos ami·e·s !" sub-title: "Jouer à Reversi avec vos ami·e·s !"
@@ -261,8 +283,8 @@ common/views/components/nav.vue:
develop: "Développeur·se·s" develop: "Développeur·se·s"
feedback: "Remarques" feedback: "Remarques"
common/views/components/note-menu.vue: common/views/components/note-menu.vue:
detail: "詳細" detail: "Détails"
copy-link: "リンクをコピー" copy-link: "Copier le lien"
favorite: "Mettre cette note en favoris" favorite: "Mettre cette note en favoris"
pin: "Épingler sur votre profil" pin: "Épingler sur votre profil"
delete: "Supprimer" delete: "Supprimer"
@@ -341,8 +363,8 @@ common/views/components/visibility-chooser.vue:
specified-desc: "Publier aux utilisateur·rice·s mentionné·e·s" specified-desc: "Publier aux utilisateur·rice·s mentionné·e·s"
private: "Privé" private: "Privé"
common/views/components/trends.vue: common/views/components/trends.vue:
count: "{}人が投稿" count: "{} utilisateurs·trices mentionnés·es"
empty: "トレンドなし" empty: "Aucune tendance"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "Récupération" fetching: "Récupération"
no-broadcasts: "Aucune annonce" no-broadcasts: "Aucune annonce"
@@ -395,7 +417,7 @@ common/views/widgets/tips.vue:
tips-line19: "いくつかのウィンドウはブラウザの外に切り離すことができます" tips-line19: "いくつかのウィンドウはブラウザの外に切り離すことができます"
tips-line20: "カレンダーウィジェットのパーセンテージは、経過の割合を示しています" tips-line20: "カレンダーウィジェットのパーセンテージは、経過の割合を示しています"
tips-line21: "Vous pouvez aussi utiliser l'API pour développer des Bots." tips-line21: "Vous pouvez aussi utiliser l'API pour développer des Bots."
tips-line23: "まゆかわいいよまゆ" tips-line23: "Mayu est mignone avec ses sourcils."
tips-line24: "Misskey a vu le jour en 2014" tips-line24: "Misskey a vu le jour en 2014"
tips-line25: "対応ブラウザではMisskeyを開いていなくても通知を受け取れます" tips-line25: "対応ブラウザではMisskeyを開いていなくても通知を受け取れます"
common/views/pages/follow.vue: common/views/pages/follow.vue:
@@ -441,8 +463,8 @@ desktop/views/components/charts.vue:
local-notes: "投稿の増減 (ローカル)" local-notes: "投稿の増減 (ローカル)"
remote-notes: "投稿の増減 (リモート)" remote-notes: "投稿の増減 (リモート)"
notes-total: "投稿の累計" notes-total: "投稿の累計"
users: "ユーザーの増減" users: "Nombre dutilisateurs·trices : augmentation/diminution"
users-total: "ユーザーの累計" users-total: "Nombre total dutilisateurs·trices : total cumulé"
drive: "ドライブ使用量の増減" drive: "ドライブ使用量の増減"
drive-total: "ドライブ使用量の累計" drive-total: "ドライブ使用量の累計"
drive-files: "ドライブのファイル数の増減" drive-files: "ドライブのファイル数の増減"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "Comportement" behaviour: "Comportement"
fetch-on-scroll: "Chargement lors du défilement" fetch-on-scroll: "Chargement lors du défilement"
fetch-on-scroll-desc: "Chargement automatique du contenu lors du défilement de la page." fetch-on-scroll-desc: "Chargement automatique du contenu lors du défilement de la page."
note-visibility: "Visibilité de la publication"
default-note-visibility: "Visibilité par défaut"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "Fenêtre contextuelle automatique" auto-popout: "Fenêtre contextuelle automatique"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
advanced: "Paramètres avancés" advanced: "Paramètres avancés"
@@ -651,9 +676,9 @@ desktop/views/components/settings.vue:
delete-wallpaper: "Supprimer le fond d'écran" delete-wallpaper: "Supprimer le fond d'écran"
dark-mode: "Mode nuit" dark-mode: "Mode nuit"
circle-icons: "Utiliser des icônes circulaires" circle-icons: "Utiliser des icônes circulaires"
contrasted-acct: "ユーザー名にコントラストを付ける" contrasted-acct: "Nom dutilisateur contrasté"
gradient-window-header: "Utiliser les dégradés sur la barre de titre de la fenêtre" gradient-window-header: "Utiliser les dégradés sur la barre de titre de la fenêtre"
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" post-form-on-timeline: "Afficher le formulaire en haut du fil"
suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie" suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie"
show-clock-on-header: "Afficher l'horloge à droite sur le coté supérieur" show-clock-on-header: "Afficher l'horloge à droite sur le coté supérieur"
show-reply-target: "Afficher les réponses" show-reply-target: "Afficher les réponses"
@@ -866,10 +891,10 @@ desktop/views/pages/welcome.vue:
signin-button: "Se connecter" signin-button: "Se connecter"
signup-button: "S'inscrire" signup-button: "S'inscrire"
timeline: "Fil d'actualité" timeline: "Fil d'actualité"
announcements: "お知らせ" announcements: "Notices"
photos: "最近の画像" photos: "Images récentes"
powered-by-misskey: "Propulsé par <b>Misskey</b>." powered-by-misskey: "Propulsé par <b>Misskey</b>."
info: "情報" info: "Informations"
desktop/views/pages/drive.vue: desktop/views/pages/drive.vue:
title: "Lecteur de Misskey" title: "Lecteur de Misskey"
desktop/views/pages/favorites.vue: desktop/views/pages/favorites.vue:
@@ -979,14 +1004,14 @@ mobile/views/components/drive-file-chooser.vue:
mobile/views/components/drive-folder-chooser.vue: mobile/views/components/drive-folder-chooser.vue:
select-folder: "Choisissez un dossier" select-folder: "Choisissez un dossier"
mobile/views/components/drive.file.vue: mobile/views/components/drive.file.vue:
nsfw: "閲覧注意" nsfw: "CW"
mobile/views/components/drive.file-detail.vue: mobile/views/components/drive.file-detail.vue:
download: "Télécharger" download: "Télécharger"
rename: "Renommer" rename: "Renommer"
move: "Déplacer" move: "Déplacer"
hash: "Hash (md5)" hash: "Hash (md5)"
exif: "EXIF" exif: "EXIF"
nsfw: "閲覧注意" nsfw: "CW"
mobile/views/components/media-image.vue: mobile/views/components/media-image.vue:
sensitive: "Le contenu est NSFW" sensitive: "Le contenu est NSFW"
click-to-show: "Cliquer pour afficher" click-to-show: "Cliquer pour afficher"
@@ -1053,7 +1078,7 @@ mobile/views/components/timeline.vue:
load-more: "Afficher plus" load-more: "Afficher plus"
mobile/views/components/ui.header.vue: mobile/views/components/ui.header.vue:
welcome-back: "Content de vous revoir ! " welcome-back: "Content de vous revoir ! "
adjective: "さん" adjective: "M."
mobile/views/components/ui.nav.vue: mobile/views/components/ui.nav.vue:
timeline: "Fil d'actualité" timeline: "Fil d'actualité"
notifications: "Notifications" notifications: "Notifications"
@@ -1166,11 +1191,14 @@ mobile/views/pages/settings.vue:
post-style: "Style de la publication" post-style: "Style de la publication"
post-style-standard: "Standard" post-style-standard: "Standard"
post-style-smart: "Intelligent" post-style-smart: "Intelligent"
notification-position: "通知の表示" notification-position: "Style de notification"
notification-position-bottom: "" notification-position-bottom: "en bas"
notification-position-top: "" notification-position-top: "en haut"
behavior: "Comportement" behavior: "Comportement"
fetch-on-scroll: "Chargement lors du défilement" fetch-on-scroll: "Chargement lors du défilement"
note-visibility: "Visibilité de la publication"
default-note-visibility: "Visibilité par défaut"
remember-note-visibility: "Se souvenir du mode de visibilité de la publication"
disable-via-mobile: "Ne pas mentionner que ma publication provient d'un 'périphérique mobile'" disable-via-mobile: "Ne pas mentionner que ma publication provient d'un 'périphérique mobile'"
load-raw-images: "Afficher les photos jointes en haute qualité" load-raw-images: "Afficher les photos jointes en haute qualité"
load-remote-media: "Afficher les médias sur le serveur distant" load-remote-media: "Afficher les médias sur le serveur distant"
@@ -1190,7 +1218,7 @@ mobile/views/pages/settings.vue:
settings: "Réglages" settings: "Réglages"
signout: "Déconnexion" signout: "Déconnexion"
sound: "Sons" sound: "Sons"
enable-sounds: "サウンドを有効にする" enable-sounds: "Activer les sons"
mobile/views/pages/user.vue: mobile/views/pages/user.vue:
follows-you: "vous suit" follows-you: "vous suit"
following: "Abonnements" following: "Abonnements"
@@ -1235,7 +1263,7 @@ docs:
res: "Réponse" res: "Réponse"
require-credential: "Ce point de communication nécessite une authentification." require-credential: "Ce point de communication nécessite une authentification."
require-permission: "Ce point de communication nécessite la permission {permission}." require-permission: "Ce point de communication nécessite la permission {permission}."
has-limit: "レートリミットがあります。" has-limit: "Il ya un taux limite."
duration-limit: "直近{duration}ミリ秒の間のこのエンドポイントへのリクエスト数の合計が{max}を超える場合はリクエストできません。" duration-limit: "直近{duration}ミリ秒の間のこのエンドポイントへのリクエスト数の合計が{max}を超える場合はリクエストできません。"
min-interval-limit: "前回のリクエストから{interval}ミリ秒経っていない場合はリクエストできません。" min-interval-limit: "前回のリクエストから{interval}ミリ秒経っていない場合はリクエストできません。"
show-src: "Vous pouvez voir le code source ce point de communication." show-src: "Vous pouvez voir le code source ce point de communication."

View File

@@ -6,6 +6,19 @@ common:
misskey: "A ⭐ of fediverse" misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse." about-title: "A ⭐ of fediverse."
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。" about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。"
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "広告ブロッカーを無効にしてください" detected: "広告ブロッカーを無効にしてください"
warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。" warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。"
@@ -68,6 +81,15 @@ common:
confused: "こまこまのこまり" confused: "こまこまのこまり"
rip: "RIP" rip: "RIP"
pudding: "Pudding" pudding: "Pudding"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "今どうしてる?" a: "今どうしてる?"
b: "何かありましたか?" b: "何かありましたか?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "動作" behaviour: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "ウィンドウの自動ポップアウト" auto-popout: "ウィンドウの自動ポップアウト"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
advanced: "詳細設定" advanced: "詳細設定"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "上" notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
load-raw-images: "添付された画像を高画質で表示する" load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する" load-remote-media: "リモートサーバーのメディアを表示する"

View File

@@ -6,6 +6,19 @@ common:
misskey: "A ⭐ of fediverse" misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse." about-title: "A ⭐ of fediverse."
about: "ようMisskeyを見つけてくれて、おおきにやで。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>やねん。Fediverse(ぎょうさんのSNSで構成されとる宇宙)っちゅうもんの中におるから、お隣さんのSNSとも仲良うさせてもろてんねん。ちょいとやかましい心斎橋から離れて、新しいインターネットにダイブしてみぃひん" about: "ようMisskeyを見つけてくれて、おおきにやで。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>やねん。Fediverse(ぎょうさんのSNSで構成されとる宇宙)っちゅうもんの中におるから、お隣さんのSNSとも仲良うさせてもろてんねん。ちょいとやかましい心斎橋から離れて、新しいインターネットにダイブしてみぃひん"
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "広告ブロッカーを無効にしてや" detected: "広告ブロッカーを無効にしてや"
warning: "<strong>Misskeyは広告を掲載してへん</strong>けど、広告をブロックしはる機能がおると一部の機能が利用できんくなったり、不具合が発生するかも分からん。知らんけど。" warning: "<strong>Misskeyは広告を掲載してへん</strong>けど、広告をブロックしはる機能がおると一部の機能が利用できんくなったり、不具合が発生するかも分からん。知らんけど。"
@@ -68,6 +81,15 @@ common:
confused: "こまこまのこまりやわぁ" confused: "こまこまのこまりやわぁ"
rip: "RIP" rip: "RIP"
pudding: "アメちゃんちゃうんちゃう?" pudding: "アメちゃんちゃうんちゃう?"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "今なにしてん?" a: "今なにしてん?"
b: "何かあったんか?" b: "何かあったんか?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "動作" behaviour: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "ウィンドウの自動ポップアウト" auto-popout: "ウィンドウの自動ポップアウト"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
advanced: "詳細設定" advanced: "詳細設定"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "上" notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
load-raw-images: "添付された画像を高画質で表示する" load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する" load-remote-media: "リモートサーバーのメディアを表示する"

View File

@@ -6,6 +6,19 @@ common:
misskey: "A ⭐ of fediverse" misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse." about-title: "A ⭐ of fediverse."
about: "Misskey를 찾아 주셔서 감사합니다. Misskey은 지구에서 태어난 <b>분산 마이크로 블로그 SNS </b> 입니다. Fediverse (다양한 SNS로 구성되는 우주)에 존재하는 다른 SNS와 상호 연결되어 있습니다. 잠시 도시의 번잡함에서 벗어나 새로운 인터넷에 다이브 해 보지 않겠습니까." about: "Misskey를 찾아 주셔서 감사합니다. Misskey은 지구에서 태어난 <b>분산 마이크로 블로그 SNS </b> 입니다. Fediverse (다양한 SNS로 구성되는 우주)에 존재하는 다른 SNS와 상호 연결되어 있습니다. 잠시 도시의 번잡함에서 벗어나 새로운 인터넷에 다이브 해 보지 않겠습니까."
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "광고 차단기를 해제하십시오" detected: "광고 차단기를 해제하십시오"
warning: "<strong>Misskey는 광고를 게재하지 않습니다</strong> 그러나 광고를 차단하는 기능 기능을 사용할 경우 일부 기능을 사용할 수 없게 될 가능성이나 결함이 발생하는 경우가 있습니다." warning: "<strong>Misskey는 광고를 게재하지 않습니다</strong> 그러나 광고를 차단하는 기능 기능을 사용할 경우 일부 기능을 사용할 수 없게 될 가능성이나 결함이 발생하는 경우가 있습니다."
@@ -68,6 +81,15 @@ common:
confused: "곤란하고 있어" confused: "곤란하고 있어"
rip: "RIP" rip: "RIP"
pudding: "Pudding" pudding: "Pudding"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "지금 어떻게하고있어?" a: "지금 어떻게하고있어?"
b: "뭔가 있었습니까?" b: "뭔가 있었습니까?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "動作" behaviour: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "ウィンドウの自動ポップアウト" auto-popout: "ウィンドウの自動ポップアウト"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
advanced: "詳細設定" advanced: "詳細設定"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "上" notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
load-raw-images: "添付された画像を高画質で表示する" load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する" load-remote-media: "リモートサーバーのメディアを表示する"

View File

@@ -6,6 +6,19 @@ common:
misskey: "Deel alles met anderen die ook Misskey gebruiken." misskey: "Deel alles met anderen die ook Misskey gebruiken."
about-title: "A ⭐ of fediverse." about-title: "A ⭐ of fediverse."
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。" about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。"
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "広告ブロッカーを無効にしてください" detected: "広告ブロッカーを無効にしてください"
warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。" warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。"
@@ -68,6 +81,15 @@ common:
confused: "Verward" confused: "Verward"
rip: "RIP" rip: "RIP"
pudding: "Pudding" pudding: "Pudding"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "今どうしてる?" a: "今どうしてる?"
b: "何かありましたか?" b: "何かありましたか?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "Gedrag" behaviour: "Gedrag"
fetch-on-scroll: "Ophalen bij scrollen" fetch-on-scroll: "Ophalen bij scrollen"
fetch-on-scroll-desc: "Als je omlaag scrolt, wordt de rest van de inhoud automatisch opgehaald." fetch-on-scroll-desc: "Als je omlaag scrolt, wordt de rest van de inhoud automatisch opgehaald."
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "Venster automatisch uitvouwen" auto-popout: "Venster automatisch uitvouwen"
auto-popout-desc: "Venster uitvouwen, indien mogelijk. Deze instelling wordt opgeslagen in je browser." auto-popout-desc: "Venster uitvouwen, indien mogelijk. Deze instelling wordt opgeslagen in je browser."
advanced: "Geavanceerde instellingen" advanced: "Geavanceerde instellingen"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "上" notification-position-top: "上"
behavior: "Gedrag" behavior: "Gedrag"
fetch-on-scroll: "Ophalen bij scrollen" fetch-on-scroll: "Ophalen bij scrollen"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "Zonder 'mobiele berichten'" disable-via-mobile: "Zonder 'mobiele berichten'"
load-raw-images: "添付された画像を高画質で表示する" load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する" load-remote-media: "リモートサーバーのメディアを表示する"

View File

@@ -6,6 +6,19 @@ common:
misskey: "A ⭐ of fediverse" misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse." about-title: "A ⭐ of fediverse."
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。" about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。"
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "広告ブロッカーを無効にしてください" detected: "広告ブロッカーを無効にしてください"
warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。" warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。"
@@ -68,6 +81,15 @@ common:
confused: "Forvirret" confused: "Forvirret"
rip: "RIP" rip: "RIP"
pudding: "Pudding" pudding: "Pudding"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "今どうしてる?" a: "今どうしてる?"
b: "何かありましたか?" b: "何かありましたか?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "動作" behaviour: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "ウィンドウの自動ポップアウト" auto-popout: "ウィンドウの自動ポップアウト"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
advanced: "詳細設定" advanced: "詳細設定"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "上" notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
load-raw-images: "添付された画像を高画質で表示する" load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する" load-remote-media: "リモートサーバーのメディアを表示する"

View File

@@ -6,6 +6,19 @@ common:
misskey: "⭐ Fediwersum" misskey: "⭐ Fediwersum"
about-title: "⭐ Fediwersum" about-title: "⭐ Fediwersum"
about: "Dziękujemy za znalezienie Misskey. Misskey jest <b>zdecentralizowaną platformą mikroblogową</b> powstałą na Ziemi. Ponieważ działa ona w Fediwersum (uniwersum, w którego skład wchodzi wiele sieci społecznościowych), jest ona połączona z innymi platformami społecznościowymi. Spróbujesz odpocząć od zatłoczoneo miasta i zanurzyć się w nowym Internecie?" about: "Dziękujemy za znalezienie Misskey. Misskey jest <b>zdecentralizowaną platformą mikroblogową</b> powstałą na Ziemi. Ponieważ działa ona w Fediwersum (uniwersum, w którego skład wchodzi wiele sieci społecznościowych), jest ona połączona z innymi platformami społecznościowymi. Spróbujesz odpocząć od zatłoczoneo miasta i zanurzyć się w nowym Internecie?"
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "Spróbuj wyłączyć blokadę reklam." detected: "Spróbuj wyłączyć blokadę reklam."
warning: "<strong>Misskey nie zawiera reklam</strong>, ale część funkcji może nie działać prawidłowo z włączonym blokowaniem reklam." warning: "<strong>Misskey nie zawiera reklam</strong>, ale część funkcji może nie działać prawidłowo z włączonym blokowaniem reklam."
@@ -68,6 +81,15 @@ common:
confused: "Zmieszany" confused: "Zmieszany"
rip: "RIP" rip: "RIP"
pudding: "Pudding" pudding: "Pudding"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "Co robisz?" a: "Co robisz?"
b: "Co się wydarzyło?" b: "Co się wydarzyło?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "Zachowanie" behaviour: "Zachowanie"
fetch-on-scroll: "Automatycznie ładuj po przeciągnięciu w dół" fetch-on-scroll: "Automatycznie ładuj po przeciągnięciu w dół"
fetch-on-scroll-desc: "Po przewinięciu na dół strony automatycznie zostaną załadowane nowe treści." fetch-on-scroll-desc: "Po przewinięciu na dół strony automatycznie zostaną załadowane nowe treści."
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "Automatycznie pojawiające się okna" auto-popout: "Automatycznie pojawiające się okna"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
advanced: "Ustawienia zaawansowane" advanced: "Ustawienia zaawansowane"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "上" notification-position-top: "上"
behavior: "Zachowanie" behavior: "Zachowanie"
fetch-on-scroll: "Automatycznie ładuj po przeciągnięciu w dół" fetch-on-scroll: "Automatycznie ładuj po przeciągnięciu w dół"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "Nie oznaczaj wpisów jako „wysłane z telefonu”" disable-via-mobile: "Nie oznaczaj wpisów jako „wysłane z telefonu”"
load-raw-images: "Wyświetlaj załączone zdjęcia w wysokiej jakości" load-raw-images: "Wyświetlaj załączone zdjęcia w wysokiej jakości"
load-remote-media: "Wyświetlaj zawartość multimedialną ze zdalnych serwerów" load-remote-media: "Wyświetlaj zawartość multimedialną ze zdalnych serwerów"

View File

@@ -6,6 +6,19 @@ common:
misskey: "Uma ⭐ do fediverso" misskey: "Uma ⭐ do fediverso"
about-title: "Uma ⭐ do fediverso." about-title: "Uma ⭐ do fediverso."
about: "Obrigado por encontrar Misskey. Uma <b>plataforma descentralizada de microblog</b> nascida na Terra. Já que ela existe no Fediverso (um universo onde várias plataformas de mídia social são organizadas), ela é ligada com outras plataformas.Por que você não tira uma folga do agito e confusão da cidade, e mergulha em uma nova internet?" about: "Obrigado por encontrar Misskey. Uma <b>plataforma descentralizada de microblog</b> nascida na Terra. Já que ela existe no Fediverso (um universo onde várias plataformas de mídia social são organizadas), ela é ligada com outras plataformas.Por que você não tira uma folga do agito e confusão da cidade, e mergulha em uma nova internet?"
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "Por favor, desative o bloqueador de anúncios." detected: "Por favor, desative o bloqueador de anúncios."
warning: "Alguns recursos podem não estar disponíveis ou apresentar mal funcionamento se o bloqueio de anúncios estiver ativado. <strong>Misskey não está usando anúncios</strong>" warning: "Alguns recursos podem não estar disponíveis ou apresentar mal funcionamento se o bloqueio de anúncios estiver ativado. <strong>Misskey não está usando anúncios</strong>"
@@ -68,6 +81,15 @@ common:
confused: "Confuso" confused: "Confuso"
rip: "RIP" rip: "RIP"
pudding: "Pudim" pudding: "Pudim"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "O que está fazendo?" a: "O que está fazendo?"
b: "O que está acontecendo?" b: "O que está acontecendo?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "動作" behaviour: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "ウィンドウの自動ポップアウト" auto-popout: "ウィンドウの自動ポップアウト"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
advanced: "詳細設定" advanced: "詳細設定"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "上" notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
load-raw-images: "添付された画像を高画質で表示する" load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する" load-remote-media: "リモートサーバーのメディアを表示する"

View File

@@ -6,6 +6,19 @@ common:
misskey: "A ⭐ of fediverse" misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse." about-title: "A ⭐ of fediverse."
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。" about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。"
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "広告ブロッカーを無効にしてください" detected: "広告ブロッカーを無効にしてください"
warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。" warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。"
@@ -68,6 +81,15 @@ common:
confused: "こまこまのこまり" confused: "こまこまのこまり"
rip: "RIP" rip: "RIP"
pudding: "Pudding" pudding: "Pudding"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "今どうしてる?" a: "今どうしてる?"
b: "何かありましたか?" b: "何かありましたか?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "動作" behaviour: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "ウィンドウの自動ポップアウト" auto-popout: "ウィンドウの自動ポップアウト"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
advanced: "詳細設定" advanced: "詳細設定"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "上" notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
load-raw-images: "添付された画像を高画質で表示する" load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する" load-remote-media: "リモートサーバーのメディアを表示する"

View File

@@ -6,6 +6,19 @@ common:
misskey: "A ⭐ of fediverse" misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse." about-title: "A ⭐ of fediverse."
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。" about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。"
intro:
title: "Misskeyって"
about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。"
features: "特徴"
rich-contents: "投稿"
rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。"
reaction: "リアクション"
reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。"
ui: "インターフェース"
ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。"
drive: "ドライブ"
drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんかもしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんかMisskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。"
outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!"
adblock: adblock:
detected: "広告ブロッカーを無効にしてください" detected: "広告ブロッカーを無効にしてください"
warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。" warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。"
@@ -68,6 +81,15 @@ common:
confused: "こまこまのこまり" confused: "こまこまのこまり"
rip: "RIP" rip: "RIP"
pudding: "Pudding" pudding: "Pudding"
note-visibility:
public: "公開"
home: "ホーム"
home-desc: "ホームタイムラインにのみ公開"
followers: "フォロワー"
followers-desc: "自分のフォロワーにのみ公開"
specified: "ダイレクト"
specified-desc: "指定したユーザーにのみ公開"
private: "非公開"
note-placeholders: note-placeholders:
a: "今どうしてる?" a: "今どうしてる?"
b: "何かありましたか?" b: "何かありましたか?"
@@ -640,6 +662,9 @@ desktop/views/components/settings.vue:
behaviour: "動作" behaviour: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
auto-popout: "ウィンドウの自動ポップアウト" auto-popout: "ウィンドウの自動ポップアウト"
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
advanced: "詳細設定" advanced: "詳細設定"
@@ -1171,6 +1196,9 @@ mobile/views/pages/settings.vue:
notification-position-top: "上" notification-position-top: "上"
behavior: "動作" behavior: "動作"
fetch-on-scroll: "スクロールで自動読み込み" fetch-on-scroll: "スクロールで自動読み込み"
note-visibility: "投稿の公開範囲"
default-note-visibility: "デフォルトの公開範囲"
remember-note-visibility: "投稿の公開範囲を記憶する"
disable-via-mobile: "「モバイルからの投稿」フラグを付けない" disable-via-mobile: "「モバイルからの投稿」フラグを付けない"
load-raw-images: "添付された画像を高画質で表示する" load-raw-images: "添付された画像を高画質で表示する"
load-remote-media: "リモートサーバーのメディアを表示する" load-remote-media: "リモートサーバーのメディアを表示する"

View File

@@ -1,8 +1,8 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "8.33.0", "version": "8.35.0",
"clientVersion": "1.0.9497", "clientVersion": "1.0.9589",
"codename": "nighthike", "codename": "nighthike",
"main": "./built/index.js", "main": "./built/index.js",
"private": true, "private": true,

View File

@@ -18,6 +18,8 @@
return; return;
} }
const langs = LANGS;
//#region Load settings //#region Load settings
let settings = null; let settings = null;
const vuex = localStorage.getItem('vuex'); const vuex = localStorage.getItem('vuex');
@@ -40,10 +42,10 @@
//#region Detect the user language //#region Detect the user language
let lang = null; let lang = null;
if (LANGS.includes(navigator.language)) { if (langs.includes(navigator.language)) {
lang = navigator.language; lang = navigator.language;
} else { } else {
lang = LANGS.find(x => x.split('-')[0] == navigator.language); lang = langs.find(x => x.split('-')[0] == navigator.language);
if (lang == null) { if (lang == null) {
// Fallback // Fallback
@@ -52,7 +54,7 @@
} }
if (settings && settings.device.lang && if (settings && settings.device.lang &&
LANGS.includes(settings.device.lang)) { langs.includes(settings.device.lang)) {
lang = settings.device.lang; lang = settings.device.lang;
} }
//#endregion //#endregion

View File

@@ -1,15 +1,15 @@
<template> <template>
<span class="mk-avatar" :class="{ cat }" :title="user | acct" v-if="disableLink && !disablePreview" v-user-preview="user.id" @click="onClick"> <span class="mk-avatar" :style="style" :class="{ cat }" :title="user | acct" v-if="disableLink && !disablePreview" v-user-preview="user.id" @click="onClick">
<span class="inner" :style="style"></span> <span class="inner" :style="icon"></span>
</span> </span>
<span class="mk-avatar" :class="{ cat }" :title="user | acct" v-else-if="disableLink && disablePreview" @click="onClick"> <span class="mk-avatar" :style="style" :class="{ cat }" :title="user | acct" v-else-if="disableLink && disablePreview" @click="onClick">
<span class="inner" :style="style"></span> <span class="inner" :style="icon"></span>
</span> </span>
<router-link class="mk-avatar" :class="{ cat }" :to="user | userPage" :title="user | acct" :target="target" v-else-if="!disableLink && !disablePreview" v-user-preview="user.id"> <router-link class="mk-avatar" :style="style" :class="{ cat }" :to="user | userPage" :title="user | acct" :target="target" v-else-if="!disableLink && !disablePreview" v-user-preview="user.id">
<span class="inner" :style="style"></span> <span class="inner" :style="icon"></span>
</router-link> </router-link>
<router-link class="mk-avatar" :class="{ cat }" :to="user | userPage" :title="user | acct" :target="target" v-else-if="!disableLink && disablePreview"> <router-link class="mk-avatar" :style="style" :class="{ cat }" :to="user | userPage" :title="user | acct" :target="target" v-else-if="!disableLink && disablePreview">
<span class="inner" :style="style"></span> <span class="inner" :style="icon"></span>
</router-link> </router-link>
</template> </template>
@@ -42,6 +42,11 @@ export default Vue.extend({
return this.user.isCat && this.$store.state.settings.circleIcons; return this.user.isCat && this.$store.state.settings.circleIcons;
}, },
style(): any { style(): any {
return {
borderRadius: this.$store.state.settings.circleIcons ? '100%' : null
};
},
icon(): any {
return { return {
backgroundColor: this.lightmode backgroundColor: this.lightmode
? `rgb(${this.user.avatarColor.slice(0, 3).join(',')})` ? `rgb(${this.user.avatarColor.slice(0, 3).join(',')})`

View File

@@ -1,4 +1,4 @@
import Vue from 'vue'; import Vue, { VNode } from 'vue';
import * as emojilib from 'emojilib'; import * as emojilib from 'emojilib';
import { length } from 'stringz'; import { length } from 'stringz';
import parse from '../../../../../mfm/parse'; import parse from '../../../../../mfm/parse';
@@ -6,10 +6,7 @@ import getAcct from '../../../../../misc/acct/render';
import { url } from '../../../config'; import { url } from '../../../config';
import MkUrl from './url.vue'; import MkUrl from './url.vue';
import MkGoogle from './google.vue'; import MkGoogle from './google.vue';
import { concat } from '../../../../../prelude/array';
const flatten = list => list.reduce(
(a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
);
export default Vue.component('misskey-flavored-markdown', { export default Vue.component('misskey-flavored-markdown', {
props: { props: {
@@ -32,20 +29,20 @@ export default Vue.component('misskey-flavored-markdown', {
}, },
render(createElement) { render(createElement) {
let ast; let ast: any[];
if (this.ast == null) { if (this.ast == null) {
// Parse text to ast // Parse text to ast
ast = parse(this.text); ast = parse(this.text);
} else { } else {
ast = this.ast; ast = this.ast as any[];
} }
let bigCount = 0; let bigCount = 0;
let motionCount = 0; let motionCount = 0;
// Parse ast to DOM // Parse ast to DOM
const els = flatten(ast.map(token => { const els = concat(ast.map((token): VNode[] => {
switch (token.type) { switch (token.type) {
case 'text': { case 'text': {
const text = token.content.replace(/(\r\n|\n|\r)/g, '\n'); const text = token.content.replace(/(\r\n|\n|\r)/g, '\n');
@@ -56,12 +53,12 @@ export default Vue.component('misskey-flavored-markdown', {
x[x.length - 1].pop(); x[x.length - 1].pop();
return x; return x;
} else { } else {
return createElement('span', text.replace(/\n/g, ' ')); return [createElement('span', text.replace(/\n/g, ' '))];
} }
} }
case 'bold': { case 'bold': {
return createElement('b', token.bold); return [createElement('b', token.bold)];
} }
case 'big': { case 'big': {
@@ -95,23 +92,23 @@ export default Vue.component('misskey-flavored-markdown', {
} }
case 'url': { case 'url': {
return createElement(MkUrl, { return [createElement(MkUrl, {
props: { props: {
url: token.content, url: token.content,
target: '_blank' target: '_blank'
} }
}); })];
} }
case 'link': { case 'link': {
return createElement('a', { return [createElement('a', {
attrs: { attrs: {
class: 'link', class: 'link',
href: token.url, href: token.url,
target: '_blank', target: '_blank',
title: token.url title: token.url
} }
}, token.title); }, token.title)];
} }
case 'mention': { case 'mention': {
@@ -129,16 +126,16 @@ export default Vue.component('misskey-flavored-markdown', {
} }
case 'hashtag': { case 'hashtag': {
return createElement('a', { return [createElement('a', {
attrs: { attrs: {
href: `${url}/tags/${encodeURIComponent(token.hashtag)}`, href: `${url}/tags/${encodeURIComponent(token.hashtag)}`,
target: '_blank' target: '_blank'
} }
}, token.content); }, token.content)];
} }
case 'code': { case 'code': {
return createElement('pre', { return [createElement('pre', {
class: 'code' class: 'code'
}, [ }, [
createElement('code', { createElement('code', {
@@ -146,15 +143,15 @@ export default Vue.component('misskey-flavored-markdown', {
innerHTML: token.html innerHTML: token.html
} }
}) })
]); ])];
} }
case 'inline-code': { case 'inline-code': {
return createElement('code', { return [createElement('code', {
domProps: { domProps: {
innerHTML: token.html innerHTML: token.html
} }
}); })];
} }
case 'quote': { case 'quote': {
@@ -164,43 +161,45 @@ export default Vue.component('misskey-flavored-markdown', {
const x = text2.split('\n') const x = text2.split('\n')
.map(t => [createElement('span', t), createElement('br')]); .map(t => [createElement('span', t), createElement('br')]);
x[x.length - 1].pop(); x[x.length - 1].pop();
return createElement('div', { return [createElement('div', {
attrs: { attrs: {
class: 'quote' class: 'quote'
} }
}, x); }, x)];
} else { } else {
return createElement('span', { return [createElement('span', {
attrs: { attrs: {
class: 'quote' class: 'quote'
} }
}, text2.replace(/\n/g, ' ')); }, text2.replace(/\n/g, ' '))];
} }
} }
case 'title': { case 'title': {
return createElement('div', { return [createElement('div', {
attrs: { attrs: {
class: 'title' class: 'title'
} }
}, token.title); }, token.title)];
} }
case 'emoji': { case 'emoji': {
const emoji = emojilib.lib[token.emoji]; const emoji = emojilib.lib[token.emoji];
return createElement('span', emoji ? emoji.char : token.content); return [createElement('span', emoji ? emoji.char : token.content)];
} }
case 'search': { case 'search': {
return createElement(MkGoogle, { return [createElement(MkGoogle, {
props: { props: {
q: token.query q: token.query
} }
}); })];
} }
default: { default: {
console.log('unknown ast type:', token.type); console.log('unknown ast type:', token.type);
return [];
} }
} }
})); }));

View File

@@ -32,7 +32,6 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import parseAcct from '../../../../../misc/acct/parse'; import parseAcct from '../../../../../misc/acct/parse';
import getUserName from '../../../../../misc/get-user-name';
import Progress from '../../../common/scripts/loading'; import Progress from '../../../common/scripts/loading';
export default Vue.extend({ export default Vue.extend({

View File

@@ -45,7 +45,7 @@
<span v-if="visibility === 'specified'">%fa:envelope%</span> <span v-if="visibility === 'specified'">%fa:envelope%</span>
<span v-if="visibility === 'private'">%fa:lock%</span> <span v-if="visibility === 'private'">%fa:lock%</span>
</button> </button>
<p class="text-count" :class="{ over: text.length > 1000 }">{{ 1000 - text.length }}</p> <p class="text-count" :class="{ over: this.trimmedLength(text) > 1000 }">{{ 1000 - this.trimmedLength(text) }}</p>
<button :class="{ posting }" class="submit" :disabled="!canPost" @click="post"> <button :class="{ posting }" class="submit" :disabled="!canPost" @click="post">
{{ posting ? '%i18n:@posting%' : submitText }}<mk-ellipsis v-if="posting"/> {{ posting ? '%i18n:@posting%' : submitText }}<mk-ellipsis v-if="posting"/>
</button> </button>
@@ -62,7 +62,9 @@ import getFace from '../../../common/scripts/get-face';
import MkVisibilityChooser from '../../../common/views/components/visibility-chooser.vue'; import MkVisibilityChooser from '../../../common/views/components/visibility-chooser.vue';
import parse from '../../../../../mfm/parse'; import parse from '../../../../../mfm/parse';
import { host } from '../../../config'; import { host } from '../../../config';
import { erase } from '../../../../../prelude/array'; import { erase, unique } from '../../../../../prelude/array';
import { length } from 'stringz';
import parseAcct from '../../../../../misc/acct/parse';
export default Vue.extend({ export default Vue.extend({
components: { components: {
@@ -146,7 +148,7 @@ export default Vue.extend({
canPost(): boolean { canPost(): boolean {
return !this.posting && return !this.posting &&
(1 <= this.text.length || 1 <= this.files.length || this.poll || this.renote) && (1 <= this.text.length || 1 <= this.files.length || this.poll || this.renote) &&
(this.text.trim().length <= 1000); (length(this.text.trim()) <= 1000);
} }
}, },
@@ -198,6 +200,10 @@ export default Vue.extend({
}, },
methods: { methods: {
trimmedLength(text: string) {
return length(text.trim());
},
addTag(tag: string) { addTag(tag: string) {
insertTextAtCursor(this.$refs.text, ` #${tag} `); insertTextAtCursor(this.$refs.text, ` #${tag} `);
}, },
@@ -337,10 +343,9 @@ export default Vue.extend({
addVisibleUser() { addVisibleUser() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:@enter-username%' title: '%i18n:@enter-username%'
}).then(username => { }).then(acct => {
(this as any).api('users/show', { if (acct.startsWith('@')) acct = acct.substr(1);
username (this as any).api('users/show', parseAcct(acct)).then(user => {
}).then(user => {
this.visibleUsers.push(user); this.visibleUsers.push(user);
}); });
}); });
@@ -392,7 +397,7 @@ export default Vue.extend({
if (this.text && this.text != '') { if (this.text && this.text != '') {
const hashtags = parse(this.text).filter(x => x.type == 'hashtag').map(x => x.hashtag); const hashtags = parse(this.text).filter(x => x.type == 'hashtag').map(x => x.hashtag);
const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[]; const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[];
localStorage.setItem('hashtags', JSON.stringify(hashtags.concat(history).reduce((a, c) => a.includes(c) ? a : [...a, c], []))); localStorage.setItem('hashtags', JSON.stringify(unique(hashtags.concat(history))));
} }
}, },

View File

@@ -2,8 +2,8 @@
<div class="mk-timeline"> <div class="mk-timeline">
<header> <header>
<span :data-active="src == 'home'" @click="src = 'home'">%fa:home% %i18n:@home%</span> <span :data-active="src == 'home'" @click="src = 'home'">%fa:home% %i18n:@home%</span>
<span :data-active="src == 'local'" @click="src = 'local'">%fa:R comments% %i18n:@local%</span> <span :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline">%fa:R comments% %i18n:@local%</span>
<span :data-active="src == 'hybrid'" @click="src = 'hybrid'">%fa:share-alt% %i18n:@hybrid%</span> <span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline">%fa:share-alt% %i18n:@hybrid%</span>
<span :data-active="src == 'global'" @click="src = 'global'">%fa:globe% %i18n:@global%</span> <span :data-active="src == 'global'" @click="src = 'global'">%fa:globe% %i18n:@global%</span>
<span :data-active="src == 'list'" @click="src = 'list'" v-if="list">%fa:list% {{ list.title }}</span> <span :data-active="src == 'list'" @click="src = 'list'" v-if="list">%fa:list% {{ list.title }}</span>
<button @click="chooseList" title="%i18n:@list%">%fa:list%</button> <button @click="chooseList" title="%i18n:@list%">%fa:list%</button>
@@ -29,7 +29,8 @@ export default Vue.extend({
data() { data() {
return { return {
src: 'home', src: 'home',
list: null list: null,
enableLocalTimeline: false
}; };
}, },
@@ -44,6 +45,10 @@ export default Vue.extend({
}, },
created() { created() {
(this as any).os.getMeta().then(meta => {
this.enableLocalTimeline = !meta.disableLocalTimeline;
});
if (this.$store.state.device.tl) { if (this.$store.state.device.tl) {
this.src = this.$store.state.device.tl.src; this.src = this.$store.state.device.tl.src;
if (this.src == 'list') { if (this.src == 'list') {

View File

@@ -1,17 +1,16 @@
<template> <template>
<div class="root item"> <div class="zvdbznxvfixtmujpsigoccczftvpiwqh">
<mk-avatar class="avatar" :user="user"/> <div class="banner" :style="bannerStyle"></div>
<div class="main"> <mk-avatar class="avatar" :user="user" :disable-preview="true"/>
<header> <div class="body">
<router-link class="name" :to="user | userPage" v-user-preview="user.id">{{ user | userName }}</router-link> <router-link :to="user | userPage" class="name">{{ user | userName }}</router-link>
<span class="username">@{{ user | acct }}</span> <span class="username">@{{ user | acct }}</span>
</header> <div class="description">
<div class="body"> <misskey-flavored-markdown v-if="user.description" :text="user.description" :i="$store.state.i"/>
<p class="followed" v-if="user.isFollowed">%i18n:@followed%</p>
<div class="description">{{ user.description }}</div>
</div> </div>
<p class="followed" v-if="user.isFollowed">%i18n:@followed%</p>
<mk-follow-button :user="user" :size="'big'"/>
</div> </div>
<mk-follow-button :user="user"/>
</div> </div>
</template> </template>
@@ -19,76 +18,69 @@
import Vue from 'vue'; import Vue from 'vue';
export default Vue.extend({ export default Vue.extend({
props: ['user'] props: ['user'],
computed: {
bannerStyle(): any {
if (this.user.bannerUrl == null) return {};
return {
backgroundColor: this.user.bannerColor && this.user.bannerColor.length == 3 ? `rgb(${ this.user.bannerColor.join(',') })` : null,
backgroundImage: `url(${ this.user.bannerUrl })`
};
}
},
}); });
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.root.item .zvdbznxvfixtmujpsigoccczftvpiwqh
padding 16px $bg = #fff
font-size 16px
&:after margin 16px auto
content "" max-width calc(100% - 32px)
display block font-size 16px
clear both text-align center
background $bg
box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
> .banner
height 100px
background-color #f9f4f4
background-position center
background-size cover
> .avatar > .avatar
display block display block
float left margin -40px auto 0 auto
margin 0 16px 0 0 width 80px
width 58px height 80px
height 58px border-radius 100%
border-radius 8px border solid 4px $bg
> .main > .body
float left padding 4px 32px 32px 32px
width calc(100% - 74px)
> header @media (max-width 400px)
margin-bottom 2px padding 4px 16px 16px 16px
> .name > .name
display inline font-size 20px
margin 0 font-weight bold
padding 0
color #777
font-size 1em
font-weight 700
text-align left
text-decoration none
&:hover > .username
text-decoration underline display block
opacity 0.7
> .username > .description
text-align left margin 16px 0
margin 0 0 0 8px
color #ccc
> .body > .followed
> .followed margin 0 0 16px 0
display inline-block padding 0
margin 0 0 4px 0 line-height 24px
padding 2px 8px font-size 0.8em
vertical-align top color #71afc7
font-size 10px background #eefaff
color #71afc7 border-radius 4px
background #eefaff
border-radius 4px
> .description
cursor default
display block
margin 0
padding 0
overflow-wrap break-word
font-size 1.1em
color #717171
> .mk-follow-button
position absolute
top 16px
right 16px
</style> </style>

View File

@@ -33,7 +33,7 @@ export default Vue.extend({
props: ['fetch', 'count', 'youKnowCount'], props: ['fetch', 'count', 'youKnowCount'],
data() { data() {
return { return {
limit: 30, limit: 20,
mode: 'all', mode: 'all',
fetching: true, fetching: true,
moreFetching: false, moreFetching: false,
@@ -73,10 +73,14 @@ export default Vue.extend({
.mk-users-list .mk-users-list
height 100% height 100%
background #fff overflow auto
background #eee
> nav > nav
z-index 1 z-index 10
position sticky
top 0
background #fff
box-shadow 0 1px 0 rgba(#000, 0.1) box-shadow 0 1px 0 rgba(#000, 0.1)
> div > div
@@ -114,16 +118,14 @@ export default Vue.extend({
background #eee background #eee
border-radius 20px border-radius 20px
> .users > button
height calc(100% - 54px) display block
overflow auto width calc(100% - 32px)
margin 16px
padding 16px
> * &:hover
border-bottom solid 1px rgba(#000, 0.05) background rgba(#000, 0.1)
> *
max-width 600px
margin 0 auto
> .no > .no
margin 0 margin 0

View File

@@ -1,22 +1,34 @@
<template> <template>
<div class="obdskegsannmntldydackcpzezagxqfy mk-admin-card"> <div class="obdskegsannmntldydackcpzezagxqfy mk-admin-card">
<header>%i18n:@dashboard%</header> <header>%i18n:@dashboard%</header>
<div v-if="stats" class="stats"> <div v-if="stats" class="stats">
<div><b>%fa:user% {{ stats.originalUsersCount | number }}</b><span>%i18n:@original-users%</span></div> <div><b>%fa:user% {{ stats.originalUsersCount | number }}</b><span>%i18n:@original-users%</span></div>
<div><span>%fa:user% {{ stats.usersCount | number }}</span><span>%i18n:@all-users%</span></div> <div><span>%fa:user% {{ stats.usersCount | number }}</span><span>%i18n:@all-users%</span></div>
<div><b>%fa:pencil-alt% {{ stats.originalNotesCount | number }}</b><span>%i18n:@original-notes%</span></div> <div><b>%fa:pencil-alt% {{ stats.originalNotesCount | number }}</b><span>%i18n:@original-notes%</span></div>
<div><span>%fa:pencil-alt% {{ stats.notesCount | number }}</span><span>%i18n:@all-notes%</span></div> <div><span>%fa:pencil-alt% {{ stats.notesCount | number }}</span><span>%i18n:@all-notes%</span></div>
</div> </div>
<div class="cpu-memory"> <div class="cpu-memory">
<x-cpu-memory :connection="connection"/> <x-cpu-memory :connection="connection"/>
</div> </div>
<div>
<label> <div class="form">
<input type="checkbox" v-model="disableRegistration" @change="updateMeta"> <div>
<span>disableRegistration</span> <label>
</label> <input type="checkbox" v-model="disableRegistration" @change="updateMeta">
<button class="ui" @click="invite">%i18n:@invite%</button> <span>%i18n:@disableRegistration%</span>
<p v-if="inviteCode">Code: <code>{{ inviteCode }}</code></p> </label>
<button class="ui" @click="invite">%i18n:@invite%</button>
<p v-if="inviteCode">Code: <code>{{ inviteCode }}</code></p>
</div>
<div>
<label>
<input type="checkbox" v-model="disableLocalTimeline" @change="updateMeta">
<span>%i18n:@disableLocalTimeline%</span>
</label>
</div>
</div> </div>
</div> </div>
</template> </template>
@@ -33,6 +45,7 @@ export default Vue.extend({
return { return {
stats: null, stats: null,
disableRegistration: false, disableRegistration: false,
disableLocalTimeline: false,
inviteCode: null, inviteCode: null,
connection: null, connection: null,
connectionId: null connectionId: null
@@ -44,6 +57,7 @@ export default Vue.extend({
(this as any).os.getMeta().then(meta => { (this as any).os.getMeta().then(meta => {
this.disableRegistration = meta.disableRegistration; this.disableRegistration = meta.disableRegistration;
this.disableLocalTimeline = meta.disableLocalTimeline;
}); });
(this as any).api('stats').then(stats => { (this as any).api('stats').then(stats => {
@@ -61,7 +75,8 @@ export default Vue.extend({
}, },
updateMeta() { updateMeta() {
(this as any).api('admin/update-meta', { (this as any).api('admin/update-meta', {
disableRegistration: this.disableRegistration disableRegistration: this.disableRegistration,
disableLocalTimeline: this.disableLocalTimeline
}); });
} }
} }
@@ -97,4 +112,8 @@ export default Vue.extend({
border solid 1px #eee border solid 1px #eee
border-radius: 8px border-radius: 8px
> .form
> div
border-bottom solid 1px #eee
</style> </style>

View File

@@ -4,7 +4,7 @@
<header> <header>
<button class="cancel" @click="cancel">%fa:times%</button> <button class="cancel" @click="cancel">%fa:times%</button>
<div> <div>
<span class="text-count" :class="{ over: text.length > 1000 }">{{ 1000 - text.length }}</span> <span class="text-count" :class="{ over: trimmedLength(text) > 1000 }">{{ 1000 - trimmedLength(text) }}</span>
<span class="geo" v-if="geo">%fa:map-marker-alt%</span> <span class="geo" v-if="geo">%fa:map-marker-alt%</span>
<button class="submit" :disabled="!canPost" @click="post">{{ submitText }}</button> <button class="submit" :disabled="!canPost" @click="post">{{ submitText }}</button>
</div> </div>
@@ -60,6 +60,8 @@ import getFace from '../../../common/scripts/get-face';
import parse from '../../../../../mfm/parse'; import parse from '../../../../../mfm/parse';
import { host } from '../../../config'; import { host } from '../../../config';
import { erase } from '../../../../../prelude/array'; import { erase } from '../../../../../prelude/array';
import { length } from 'stringz';
import parseAcct from '../../../../../misc/acct/parse';
export default Vue.extend({ export default Vue.extend({
components: { components: {
@@ -179,6 +181,10 @@ export default Vue.extend({
}, },
methods: { methods: {
trimmedLength(text: string) {
return length(text.trim());
},
addTag(tag: string) { addTag(tag: string) {
insertTextAtCursor(this.$refs.text, ` #${tag} `); insertTextAtCursor(this.$refs.text, ` #${tag} `);
}, },
@@ -253,10 +259,9 @@ export default Vue.extend({
addVisibleUser() { addVisibleUser() {
(this as any).apis.input({ (this as any).apis.input({
title: '%i18n:@username-prompt%' title: '%i18n:@username-prompt%'
}).then(username => { }).then(acct => {
(this as any).api('users/show', { if (acct.startsWith('@')) acct = acct.substr(1);
username (this as any).api('users/show', parseAcct(acct)).then(user => {
}).then(user => {
this.visibleUsers.push(user); this.visibleUsers.push(user);
}); });
}); });
@@ -303,7 +308,7 @@ export default Vue.extend({
if (this.text && this.text != '') { if (this.text && this.text != '') {
const hashtags = parse(this.text).filter(x => x.type == 'hashtag').map(x => x.hashtag); const hashtags = parse(this.text).filter(x => x.type == 'hashtag').map(x => x.hashtag);
const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[]; const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[];
localStorage.setItem('hashtags', JSON.stringify(hashtags.concat(history).reduce((a, c) => a.includes(c) ? a : [...a, c], []))); localStorage.setItem('hashtags', JSON.stringify(unique(hashtags.concat(history))));
} }
}, },

View File

@@ -24,8 +24,8 @@
<div class="body"> <div class="body">
<div> <div>
<span :data-active="src == 'home'" @click="src = 'home'">%fa:home% %i18n:@home%</span> <span :data-active="src == 'home'" @click="src = 'home'">%fa:home% %i18n:@home%</span>
<span :data-active="src == 'local'" @click="src = 'local'">%fa:R comments% %i18n:@local%</span> <span :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline">%fa:R comments% %i18n:@local%</span>
<span :data-active="src == 'hybrid'" @click="src = 'hybrid'">%fa:share-alt% %i18n:@hybrid%</span> <span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline">%fa:share-alt% %i18n:@hybrid%</span>
<span :data-active="src == 'global'" @click="src = 'global'">%fa:globe% %i18n:@global%</span> <span :data-active="src == 'global'" @click="src = 'global'">%fa:globe% %i18n:@global%</span>
<template v-if="lists"> <template v-if="lists">
<span v-for="l in lists" :data-active="src == 'list' && list == l" @click="src = 'list'; list = l" :key="l.id">%fa:list% {{ l.title }}</span> <span v-for="l in lists" :data-active="src == 'list' && list == l" @click="src = 'list'; list = l" :key="l.id">%fa:list% {{ l.title }}</span>
@@ -60,7 +60,8 @@ export default Vue.extend({
src: 'home', src: 'home',
list: null, list: null,
lists: null, lists: null,
showNav: false showNav: false,
enableLocalTimeline: false
}; };
}, },
@@ -85,6 +86,10 @@ export default Vue.extend({
}, },
created() { created() {
(this as any).os.getMeta().then(meta => {
this.enableLocalTimeline = !meta.disableLocalTimeline;
});
if (this.$store.state.device.tl) { if (this.$store.state.device.tl) {
this.src = this.$store.state.device.tl.src; this.src = this.$store.state.device.tl.src;
if (this.src == 'list') { if (this.src == 'list') {

View File

@@ -1,5 +1,5 @@
{ {
"copyright": "Copyright (c) 2014-2018 syuilo", "copyright": "Copyright (c) 2014-2018 syuilo",
"themeColor": "#f6584f", "themeColor": "#fb4e4e",
"themeColorForeground": "#fff" "themeColorForeground": "#fff"
} }

View File

@@ -1,4 +1,4 @@
import { capitalize } from "../../../prelude/string"; import { capitalize, toUpperCase } from "../../../prelude/string";
function escape(text: string) { function escape(text: string) {
return text return text
@@ -92,7 +92,7 @@ const _keywords = [
const keywords = _keywords const keywords = _keywords
.concat(_keywords.map(capitalize)) .concat(_keywords.map(capitalize))
.concat(_keywords.map(k => k.toUpperCase())) .concat(_keywords.map(toUpperCase))
.sort((a, b) => b.length - a.length); .sort((a, b) => b.length - a.length);
const symbols = [ const symbols = [

View File

@@ -4,6 +4,7 @@ import { pack as packUser } from './user';
import { pack as packFile } from './drive-file'; import { pack as packFile } from './drive-file';
import db from '../db/mongodb'; import db from '../db/mongodb';
import MessagingHistory, { deleteMessagingHistory } from './messaging-history'; import MessagingHistory, { deleteMessagingHistory } from './messaging-history';
import { length } from 'stringz';
const MessagingMessage = db.get<IMessagingMessage>('messagingMessages'); const MessagingMessage = db.get<IMessagingMessage>('messagingMessages');
export default MessagingMessage; export default MessagingMessage;
@@ -19,7 +20,7 @@ export interface IMessagingMessage {
} }
export function isValidText(text: string): boolean { export function isValidText(text: string): boolean {
return text.length <= 1000 && text.trim() != ''; return length(text.trim()) <= 1000 && text.trim() != '';
} }
/** /**

View File

@@ -12,5 +12,6 @@ export type IMeta = {
originalUsersCount: number; originalUsersCount: number;
}; };
disableRegistration?: boolean; disableRegistration?: boolean;
disableLocalTimeline?: boolean;
hidedTags?: string[]; hidedTags?: string[];
}; };

View File

@@ -2,6 +2,7 @@ import * as mongo from 'mongodb';
const deepcopy = require('deepcopy'); const deepcopy = require('deepcopy');
import rap from '@prezzemolo/rap'; import rap from '@prezzemolo/rap';
import db from '../db/mongodb'; import db from '../db/mongodb';
import { length } from 'stringz';
import { IUser, pack as packUser } from './user'; import { IUser, pack as packUser } from './user';
import { pack as packApp } from './app'; import { pack as packApp } from './app';
import PollVote, { deletePollVote } from './poll-vote'; import PollVote, { deletePollVote } from './poll-vote';
@@ -21,24 +22,14 @@ Note.createIndex('_files.contentType');
Note.createIndex({ Note.createIndex({
createdAt: -1 createdAt: -1
}); });
// 後方互換性のため
Note.update({}, {
$rename: {
mediaIds: 'fileIds'
}
}, {
multi: true
});
export default Note; export default Note;
export function isValidText(text: string): boolean { export function isValidText(text: string): boolean {
return text.length <= 1000 && text.trim() != ''; return length(text.trim()) <= 1000 && text.trim() != '';
} }
export function isValidCw(text: string): boolean { export function isValidCw(text: string): boolean {
return text.length <= 100; return length(text.trim()) <= 100;
} }
export type INote = { export type INote = {
@@ -172,6 +163,66 @@ export async function deleteNote(note: string | mongo.ObjectID | INote) {
console.log(`Note: deleted ${n._id}`); console.log(`Note: deleted ${n._id}`);
} }
export const hideNote = async (packedNote: any, meId: mongo.ObjectID) => {
let hide = false;
// visibility が private かつ投稿者のIDが自分のIDではなかったら非表示
if (packedNote.visibility == 'private' && (meId == null || !meId.equals(packedNote.userId))) {
hide = true;
}
// visibility が specified かつ自分が指定されていなかったら非表示
if (packedNote.visibility == 'specified') {
if (meId == null) {
hide = true;
} else if (meId.equals(packedNote.userId)) {
hide = false;
} else {
// 指定されているかどうか
const specified = packedNote.visibleUserIds.some((id: mongo.ObjectID) => id.equals(meId));
if (specified) {
hide = false;
} else {
hide = true;
}
}
}
// visibility が followers かつ自分が投稿者のフォロワーでなかったら非表示
if (packedNote.visibility == 'followers') {
if (meId == null) {
hide = true;
} else if (meId.equals(packedNote.userId)) {
hide = false;
} else {
// フォロワーかどうか
const following = await Following.findOne({
followeeId: packedNote.userId,
followerId: meId
});
if (following == null) {
hide = true;
} else {
hide = false;
}
}
}
if (hide) {
packedNote.fileIds = [];
packedNote.files = [];
packedNote.text = null;
packedNote.poll = null;
packedNote.cw = null;
packedNote.tags = [];
packedNote.tagsLower = [];
packedNote.geo = null;
packedNote.isHidden = true;
}
};
/** /**
* Pack a note for API response * Pack a note for API response
* *
@@ -184,11 +235,13 @@ export const pack = async (
note: string | mongo.ObjectID | INote, note: string | mongo.ObjectID | INote,
me?: string | mongo.ObjectID | IUser, me?: string | mongo.ObjectID | IUser,
options?: { options?: {
detail: boolean detail?: boolean;
skipHide?: boolean;
} }
) => { ) => {
const opts = Object.assign({ const opts = Object.assign({
detail: true detail: true,
skipHide: false
}, options); }, options);
// Me // Me
@@ -217,52 +270,6 @@ export const pack = async (
if (!_note) throw `invalid note arg ${note}`; if (!_note) throw `invalid note arg ${note}`;
let hide = false;
// visibility が private かつ投稿者のIDが自分のIDではなかったら非表示
if (_note.visibility == 'private' && (meId == null || !meId.equals(_note.userId))) {
hide = true;
}
// visibility が specified かつ自分が指定されていなかったら非表示
if (_note.visibility == 'specified') {
if (meId == null) {
hide = true;
} else if (meId.equals(_note.userId)) {
hide = false;
} else {
// 指定されているかどうか
const specified = _note.visibleUserIds.some((id: mongo.ObjectID) => id.equals(meId));
if (specified) {
hide = false;
} else {
hide = true;
}
}
}
// visibility が followers かつ自分が投稿者のフォロワーでなかったら非表示
if (_note.visibility == 'followers') {
if (meId == null) {
hide = true;
} else if (meId.equals(_note.userId)) {
hide = false;
} else {
// フォロワーかどうか
const following = await Following.findOne({
followeeId: _note.userId,
followerId: meId
});
if (following == null) {
hide = true;
} else {
hide = false;
}
}
}
const id = _note._id; const id = _note._id;
// Rename _id to id // Rename _id to id
@@ -284,7 +291,7 @@ export const pack = async (
} }
// Populate files // Populate files
_note.files = hide ? [] : Promise.all(_note.fileIds.map((fileId: mongo.ObjectID) => _note.files = Promise.all(_note.fileIds.map((fileId: mongo.ObjectID) =>
packFile(fileId) packFile(fileId)
)); ));
@@ -314,7 +321,7 @@ export const pack = async (
} }
// Poll // Poll
if (meId && _note.poll && !hide) { if (meId && _note.poll) {
_note.poll = (async poll => { _note.poll = (async poll => {
const vote = await PollVote const vote = await PollVote
.findOne({ .findOne({
@@ -359,15 +366,8 @@ export const pack = async (
_note.text = _note.text.replace(/な/g, 'にゃ').replace(/ナ/g, 'ニャ').replace(/ナ/g, 'ニャ'); _note.text = _note.text.replace(/な/g, 'にゃ').replace(/ナ/g, 'ニャ').replace(/ナ/g, 'ニャ');
} }
if (hide) { if (!opts.skipHide) {
_note.fileIds = []; await hideNote(_note, meId);
_note.text = null;
_note.poll = null;
_note.cw = null;
_note.tags = [];
_note.tagsLower = [];
_note.geo = null;
_note.isHidden = true;
} }
return _note; return _note;

View File

@@ -1,3 +1,11 @@
export function capitalize(s: string): string { export function capitalize(s: string): string {
return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase(); return toUpperCase(s.charAt(0)) + toLowerCase(s.slice(1));
}
export function toUpperCase(s: string): string {
return s.toUpperCase();
}
export function toLowerCase(s: string): string {
return s.toLowerCase();
} }

View File

@@ -4,9 +4,8 @@ import parse from '../../../mfm/parse';
import config from '../../../config'; import config from '../../../config';
export default function(note: INote) { export default function(note: INote) {
if (note.text == null) return null;
let html = toHtml(parse(note.text), note.mentionedRemoteUsers); let html = toHtml(parse(note.text), note.mentionedRemoteUsers);
if (html == null) html = '';
if (note.poll != null) { if (note.poll != null) {
const url = `${config.url}/notes/${note._id}`; const url = `${config.url}/notes/${note._id}`;

View File

@@ -91,7 +91,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
const reply = note.inReplyTo ? await resolveNote(note.inReplyTo, resolver) : null; const reply = note.inReplyTo ? await resolveNote(note.inReplyTo, resolver) : null;
// テキストのパース // テキストのパース
const text = htmlToMFM(note.content); const text = note._misskey_content ? note._misskey_content : htmlToMFM(note.content);
// ユーザーの情報が古かったらついでに更新しておく // ユーザーの情報が古かったらついでに更新しておく
if (actor.updatedAt == null || Date.now() - actor.updatedAt.getTime() > 1000 * 60 * 60 * 24) { if (actor.updatedAt == null || Date.now() - actor.updatedAt.getTime() > 1000 * 60 * 60 * 24) {

View File

@@ -87,6 +87,7 @@ export default async function renderNote(note: INote, dive = true): Promise<any>
attributedTo, attributedTo,
summary: note.cw, summary: note.cw,
content: toHtml(note), content: toHtml(note),
_misskey_content_: note.text,
published: note.createdAt.toISOString(), published: note.createdAt.toISOString(),
to, to,
cc, cc,

View File

@@ -40,6 +40,7 @@ export interface IOrderedCollection extends IObject {
export interface INote extends IObject { export interface INote extends IObject {
type: 'Note'; type: 'Note';
_misskey_content: string;
} }
export interface IPerson extends IObject { export interface IPerson extends IObject {

View File

@@ -105,7 +105,7 @@ export default async (ctx: Router.IRouterContext) => {
* @param note Note * @param note Note
*/ */
export async function packActivity(note: INote): Promise<object> { export async function packActivity(note: INote): Promise<object> {
if (note.renoteId && note.text == null) { if (note.renoteId && note.text == null && note.poll == null && (note.fileIds == null || note.fileIds.length == 0)) {
const renote = await Note.findOne(note.renoteId); const renote = await Note.findOne(note.renoteId);
return renderAnnounce(renote.uri ? renote.uri : `${config.url}/notes/${renote._id}`, note); return renderAnnounce(renote.uri ? renote.uri : `${config.url}/notes/${renote._id}`, note);
} }

View File

@@ -23,6 +23,12 @@ export const meta = {
} }
}), }),
disableLocalTimeline: $.bool.optional.nullable.note({
desc: {
'ja-JP': 'ローカルタイムライン(とソーシャルタイムライン)を無効にするか否か'
}
}),
hidedTags: $.arr($.str).optional.nullable.note({ hidedTags: $.arr($.str).optional.nullable.note({
desc: { desc: {
'ja-JP': '統計などで無視するハッシュタグ' 'ja-JP': '統計などで無視するハッシュタグ'
@@ -45,6 +51,10 @@ export default (params: any) => new Promise(async (res, rej) => {
set.disableRegistration = ps.disableRegistration; set.disableRegistration = ps.disableRegistration;
} }
if (typeof ps.disableLocalTimeline === 'boolean') {
set.disableLocalTimeline = ps.disableLocalTimeline;
}
if (Array.isArray(ps.hidedTags)) { if (Array.isArray(ps.hidedTags)) {
set.hidedTags = ps.hidedTags; set.hidedTags = ps.hidedTags;
} }

View File

@@ -57,7 +57,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
} }
// Create following // Create following
create(follower, followee); await create(follower, followee);
// Send response // Send response
res(await pack(followee._id, user)); res(await pack(followee._id, user));

View File

@@ -57,7 +57,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
} }
// Delete following // Delete following
deleteFollowing(follower, followee); await deleteFollowing(follower, followee);
// Send response // Send response
res(await pack(followee._id, user)); res(await pack(followee._id, user));

View File

@@ -6,6 +6,7 @@ import acceptAllFollowRequests from '../../../../services/following/requests/acc
import { IApp } from '../../../../models/app'; import { IApp } from '../../../../models/app';
import config from '../../../../config'; import config from '../../../../config';
import { publishToFollowers } from '../../../../services/i/update'; import { publishToFollowers } from '../../../../services/i/update';
import getParams from '../../get-params';
export const meta = { export const meta = {
desc: { desc: {
@@ -15,75 +16,104 @@ export const meta = {
requireCredential: true, requireCredential: true,
kind: 'account-write' kind: 'account-write',
params: {
name: $.str.optional.nullable.pipe(isValidName).note({
desc: {
'ja-JP': '名前(ハンドルネームやニックネーム)'
}
}),
description: $.str.optional.nullable.pipe(isValidDescription).note({
desc: {
'ja-JP': 'アカウントの説明や自己紹介'
}
}),
location: $.str.optional.nullable.pipe(isValidLocation).note({
desc: {
'ja-JP': '住んでいる地域、所在'
}
}),
birthday: $.str.optional.nullable.pipe(isValidBirthday).note({
desc: {
'ja-JP': '誕生日 (YYYY-MM-DD形式)'
}
}),
avatarId: $.type(ID).optional.nullable.note({
desc: {
'ja-JP': 'アイコンに設定する画像のドライブファイルID'
}
}),
bannerId: $.type(ID).optional.nullable.note({
desc: {
'ja-JP': 'バナーに設定する画像のドライブファイルID'
}
}),
wallpaperId: $.type(ID).optional.nullable.note({
desc: {
'ja-JP': '壁紙に設定する画像のドライブファイルID'
}
}),
isLocked: $.bool.optional.note({
desc: {
'ja-JP': '鍵アカウントか否か'
}
}),
isBot: $.bool.optional.note({
desc: {
'ja-JP': 'Botか否か'
}
}),
isCat: $.bool.optional.note({
desc: {
'ja-JP': '猫か否か'
}
}),
autoWatch: $.bool.optional.note({
desc: {
'ja-JP': '投稿の自動ウォッチをするか否か'
}
}),
}
}; };
export default async (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => { export default async (params: any, user: ILocalUser, app: IApp) => new Promise(async (res, rej) => {
const [ps, psErr] = getParams(meta, params);
if (psErr) throw psErr;
const isSecure = user != null && app == null; const isSecure = user != null && app == null;
const updates = {} as any; const updates = {} as any;
// Get 'name' parameter if (ps.name !== undefined) updates.name = ps.name;
const [name, nameErr] = $.str.optional.nullable.pipe(isValidName).get(params.name); if (ps.description !== undefined) updates.description = ps.description;
if (nameErr) return rej('invalid name param'); if (ps.location !== undefined) updates['profile.location'] = ps.location;
if (name) updates.name = name; if (ps.birthday !== undefined) updates['profile.birthday'] = ps.birthday;
if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId;
if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId;
if (ps.wallpaperId !== undefined) updates.wallpaperId = ps.wallpaperId;
if (typeof ps.isLocked == 'boolean') updates.isLocked = ps.isLocked;
if (typeof ps.isBot == 'boolean') updates.isBot = ps.isBot;
if (typeof ps.isCat == 'boolean') updates.isCat = ps.isCat;
if (typeof ps.autoWatch == 'boolean') updates['settings.autoWatch'] = ps.autoWatch;
// Get 'description' parameter if (ps.avatarId) {
const [description, descriptionErr] = $.str.optional.nullable.pipe(isValidDescription).get(params.description);
if (descriptionErr) return rej('invalid description param');
if (description !== undefined) updates.description = description;
// Get 'location' parameter
const [location, locationErr] = $.str.optional.nullable.pipe(isValidLocation).get(params.location);
if (locationErr) return rej('invalid location param');
if (location !== undefined) updates['profile.location'] = location;
// Get 'birthday' parameter
const [birthday, birthdayErr] = $.str.optional.nullable.pipe(isValidBirthday).get(params.birthday);
if (birthdayErr) return rej('invalid birthday param');
if (birthday !== undefined) updates['profile.birthday'] = birthday;
// Get 'avatarId' parameter
const [avatarId, avatarIdErr] = $.type(ID).optional.nullable.get(params.avatarId);
if (avatarIdErr) return rej('invalid avatarId param');
if (avatarId !== undefined) updates.avatarId = avatarId;
// Get 'bannerId' parameter
const [bannerId, bannerIdErr] = $.type(ID).optional.nullable.get(params.bannerId);
if (bannerIdErr) return rej('invalid bannerId param');
if (bannerId !== undefined) updates.bannerId = bannerId;
// Get 'wallpaperId' parameter
const [wallpaperId, wallpaperIdErr] = $.type(ID).optional.nullable.get(params.wallpaperId);
if (wallpaperIdErr) return rej('invalid wallpaperId param');
if (wallpaperId !== undefined) updates.wallpaperId = wallpaperId;
// Get 'isLocked' parameter
const [isLocked, isLockedErr] = $.bool.optional.get(params.isLocked);
if (isLockedErr) return rej('invalid isLocked param');
if (isLocked != null) updates.isLocked = isLocked;
// Get 'isBot' parameter
const [isBot, isBotErr] = $.bool.optional.get(params.isBot);
if (isBotErr) return rej('invalid isBot param');
if (isBot != null) updates.isBot = isBot;
// Get 'isCat' parameter
const [isCat, isCatErr] = $.bool.optional.get(params.isCat);
if (isCatErr) return rej('invalid isCat param');
if (isCat != null) updates.isCat = isCat;
// Get 'autoWatch' parameter
const [autoWatch, autoWatchErr] = $.bool.optional.get(params.autoWatch);
if (autoWatchErr) return rej('invalid autoWatch param');
if (autoWatch != null) updates['settings.autoWatch'] = autoWatch;
if (avatarId) {
const avatar = await DriveFile.findOne({ const avatar = await DriveFile.findOne({
_id: avatarId _id: ps.avatarId
}); });
if (avatar == null) return rej('avatar not found'); if (avatar == null) return rej('avatar not found');
if (!avatar.contentType.startsWith('image/')) return rej('avatar not an image');
updates.avatarUrl = avatar.metadata.thumbnailUrl || avatar.metadata.url || `${config.drive_url}/${avatar._id}`; updates.avatarUrl = avatar.metadata.thumbnailUrl || avatar.metadata.url || `${config.drive_url}/${avatar._id}`;
@@ -92,12 +122,13 @@ export default async (params: any, user: ILocalUser, app: IApp) => new Promise(a
} }
} }
if (bannerId) { if (ps.bannerId) {
const banner = await DriveFile.findOne({ const banner = await DriveFile.findOne({
_id: bannerId _id: ps.bannerId
}); });
if (banner == null) return rej('banner not found'); if (banner == null) return rej('banner not found');
if (!banner.contentType.startsWith('image/')) return rej('banner not an image');
updates.bannerUrl = banner.metadata.url || `${config.drive_url}/${banner._id}`; updates.bannerUrl = banner.metadata.url || `${config.drive_url}/${banner._id}`;
@@ -106,13 +137,13 @@ export default async (params: any, user: ILocalUser, app: IApp) => new Promise(a
} }
} }
if (wallpaperId !== undefined) { if (ps.wallpaperId !== undefined) {
if (wallpaperId === null) { if (ps.wallpaperId === null) {
updates.wallpaperUrl = null; updates.wallpaperUrl = null;
updates.wallpaperColor = null; updates.wallpaperColor = null;
} else { } else {
const wallpaper = await DriveFile.findOne({ const wallpaper = await DriveFile.findOne({
_id: wallpaperId _id: ps.wallpaperId
}); });
if (wallpaper == null) return rej('wallpaper not found'); if (wallpaper == null) return rej('wallpaper not found');
@@ -142,7 +173,7 @@ export default async (params: any, user: ILocalUser, app: IApp) => new Promise(a
publishUserStream(user._id, 'meUpdated', iObj); publishUserStream(user._id, 'meUpdated', iObj);
// 鍵垢を解除したとき、溜まっていたフォローリクエストがあるならすべて承認 // 鍵垢を解除したとき、溜まっていたフォローリクエストがあるならすべて承認
if (user.isLocked && isLocked === false) { if (user.isLocked && ps.isLocked === false) {
acceptAllFollowRequests(user); acceptAllFollowRequests(user);
} }

View File

@@ -34,6 +34,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
}, },
broadcasts: meta.broadcasts, broadcasts: meta.broadcasts,
disableRegistration: meta.disableRegistration, disableRegistration: meta.disableRegistration,
disableLocalTimeline: meta.disableLocalTimeline,
driveCapacityPerLocalUserMb: config.localDriveCapacityMb, driveCapacityPerLocalUserMb: config.localDriveCapacityMb,
recaptchaSitekey: config.recaptcha ? config.recaptcha.site_key : null, recaptchaSitekey: config.recaptcha ? config.recaptcha.site_key : null,
swPublickey: config.sw ? config.sw.public_key : null, swPublickey: config.sw ? config.sw.public_key : null,

View File

@@ -132,25 +132,14 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (
let files: IDriveFile[] = []; let files: IDriveFile[] = [];
const fileIds = ps.fileIds != null ? ps.fileIds : ps.mediaIds != null ? ps.mediaIds : null; const fileIds = ps.fileIds != null ? ps.fileIds : ps.mediaIds != null ? ps.mediaIds : null;
if (fileIds != null) { if (fileIds != null) {
// Fetch files files = await Promise.all(fileIds.map(fileId => {
// forEach だと途中でエラーなどがあっても return できないので return DriveFile.findOne({
// 敢えて for を使っています。
for (const fileId of fileIds) {
// Fetch file
// SELECT _id
const entity = await DriveFile.findOne({
_id: fileId, _id: fileId,
'metadata.userId': user._id 'metadata.userId': user._id
}); });
}));
if (entity === null) { files = files.filter(file => file != null);
return rej('file not found');
} else {
files.push(entity);
}
}
} else {
files = null;
} }
let renote: INote = null; let renote: INote = null;

View File

@@ -79,9 +79,6 @@ export const meta = {
} }
}; };
/**
* Get hybrid timeline of myself
*/
export default async (params: any, user: ILocalUser) => { export default async (params: any, user: ILocalUser) => {
const [ps, psErr] = getParams(meta, params); const [ps, psErr] = getParams(meta, params);
if (psErr) throw psErr; if (psErr) throw psErr;

View File

@@ -43,6 +43,10 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
return rej('note not found'); return rej('note not found');
} }
if (note.deletedAt != null) {
return rej('this not is already deleted');
}
try { try {
await create(user, note, ps.reaction); await create(user, note, ps.reaction);
} catch (e) { } catch (e) {

View File

@@ -125,10 +125,11 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
ids.forEach(id => ps.excludeUserIds.push(id)); ids.forEach(id => ps.excludeUserIds.push(id));
} }
let q: any = { const q: any = {
$and: [{ $and: [{
tagsLower: ps.tag.toLowerCase() tagsLower: ps.tag.toLowerCase()
}] }],
deletedAt: { $exists: false }
}; };
const push = (x: any) => q.$and.push(x); const push = (x: any) => q.$and.push(x);
@@ -339,7 +340,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
} }
if (q.$and.length == 0) { if (q.$and.length == 0) {
q = {}; delete q.$and;
} }
// Search notes // Search notes

View File

@@ -73,8 +73,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
} }
// Serialize // Serialize
const users = await Promise.all(following.map(async f => const users = await Promise.all(following.map(f => pack(f.followerId, me, { detail: true })));
await pack(f.followerId, me, { detail: true })));
// Response // Response
res({ res({

View File

@@ -73,8 +73,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
} }
// Serialize // Serialize
const users = await Promise.all(following.map(async f => const users = await Promise.all(following.map(f => pack(f.followeeId, me, { detail: true })));
await pack(f.followeeId, me, { detail: true })));
// Response // Response
res({ res({

View File

@@ -36,6 +36,13 @@ export default async function(
// Subscribe Home stream channel // Subscribe Home stream channel
subscriber.on(`user-stream:${user._id}`, async x => { subscriber.on(`user-stream:${user._id}`, async x => {
// Renoteなら再pack
if (x.type == 'note' && x.body.renoteId != null) {
x.body.renote = await pack(x.body.renoteId, user, {
detail: true
});
}
//#region 流れてきたメッセージがミュートしているユーザーが関わるものだったら無視する //#region 流れてきたメッセージがミュートしているユーザーが関わるものだったら無視する
if (x.type == 'note') { if (x.type == 'note') {
if (mutedUserIds.includes(x.body.userId)) { if (mutedUserIds.includes(x.body.userId)) {
@@ -54,13 +61,6 @@ export default async function(
} }
//#endregion //#endregion
// Renoteなら再pack
if (x.type == 'note' && x.body.renoteId != null) {
x.body.renote = await pack(x.body.renoteId, user, {
detail: true
});
}
connection.send(JSON.stringify(x)); connection.send(JSON.stringify(x));
}); });

View File

@@ -19,6 +19,13 @@ export default async function(
subscriber.on(`hybrid-timeline:${user._id}`, onEvent); subscriber.on(`hybrid-timeline:${user._id}`, onEvent);
async function onEvent(note: any) { async function onEvent(note: any) {
// Renoteなら再pack
if (note.renoteId != null) {
note.renote = await pack(note.renoteId, user, {
detail: true
});
}
//#region 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する //#region 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する
if (mutedUserIds.indexOf(note.userId) != -1) { if (mutedUserIds.indexOf(note.userId) != -1) {
return; return;
@@ -31,13 +38,6 @@ export default async function(
} }
//#endregion //#endregion
// Renoteなら再pack
if (note.renoteId != null) {
note.renote = await pack(note.renoteId, user, {
detail: true
});
}
connection.send(JSON.stringify({ connection.send(JSON.stringify({
type: 'note', type: 'note',
body: note body: note

View File

@@ -16,6 +16,13 @@ export default async function(
// Subscribe stream // Subscribe stream
subscriber.on('local-timeline', async note => { subscriber.on('local-timeline', async note => {
// Renoteなら再pack
if (note.renoteId != null) {
note.renote = await pack(note.renoteId, user, {
detail: true
});
}
//#region 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する //#region 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する
if (mutedUserIds.indexOf(note.userId) != -1) { if (mutedUserIds.indexOf(note.userId) != -1) {
return; return;
@@ -28,13 +35,6 @@ export default async function(
} }
//#endregion //#endregion
// Renoteなら再pack
if (note.renoteId != null) {
note.renote = await pack(note.renoteId, user, {
detail: true
});
}
connection.send(JSON.stringify({ connection.send(JSON.stringify({
type: 'note', type: 'note',
body: note body: note

View File

@@ -36,8 +36,11 @@ async function save(path: string, name: string, type: string, hash: string, size
if (config.drive && config.drive.storage == 'minio') { if (config.drive && config.drive.storage == 'minio') {
const minio = new Minio.Client(config.drive.config); const minio = new Minio.Client(config.drive.config);
const key = `${config.drive.prefix}/${uuid.v4()}/${name}`;
const thumbnailKey = `${config.drive.prefix}/${uuid.v4()}/${name}.thumbnail.jpg`; const keyDir = `${config.drive.prefix}/${uuid.v4()}`;
const key = `${keyDir}/${name}`;
const thumbnailKeyDir = `${config.drive.prefix}/${uuid.v4()}`;
const thumbnailKey = `${thumbnailKeyDir}/${name}.thumbnail.jpg`;
const baseUrl = config.drive.baseUrl const baseUrl = config.drive.baseUrl
|| `${ config.drive.config.useSSL ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? `:${config.drive.config.port}` : '' }/${ config.drive.bucket }`; || `${ config.drive.config.useSSL ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? `:${config.drive.config.port}` : '' }/${ config.drive.bucket }`;
@@ -61,8 +64,8 @@ async function save(path: string, name: string, type: string, hash: string, size
key: key, key: key,
thumbnailKey: thumbnailKey thumbnailKey: thumbnailKey
}, },
url: `${ baseUrl }/${ key }`, url: `${ baseUrl }/${ keyDir }/${ encodeURIComponent(name) }`,
thumbnailUrl: thumbnail ? `${ baseUrl }/${ thumbnailKey }` : null thumbnailUrl: thumbnail ? `${ baseUrl }/${ thumbnailKeyDir }/${ encodeURIComponent(name) }.thumbnail.jpg` : null
}); });
const file = await DriveFile.insert({ const file = await DriveFile.insert({

View File

@@ -107,20 +107,22 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
data.visibleUsers = erase(null, data.visibleUsers); data.visibleUsers = erase(null, data.visibleUsers);
} }
// リプライ対象が削除された投稿だったらreject
if (data.reply && data.reply.deletedAt != null) { if (data.reply && data.reply.deletedAt != null) {
return rej(); return rej();
} }
// Renote対象が削除された投稿だったらreject
if (data.renote && data.renote.deletedAt != null) { if (data.renote && data.renote.deletedAt != null) {
return rej(); return rej();
} }
// リプライが自分以外の非公開の投稿なら禁止 // リプライ対象が自分以外の非公開の投稿なら禁止
if (data.reply && data.reply.visibility == 'private' && !data.reply.userId.equals(user._id)) { if (data.reply && data.reply.visibility == 'private' && !data.reply.userId.equals(user._id)) {
return rej(); return rej();
} }
// Renoteが自分以外の非公開の投稿なら禁止 // Renote対象が自分以外の非公開の投稿なら禁止
if (data.renote && data.renote.visibility == 'private' && !data.renote.userId.equals(user._id)) { if (data.renote && data.renote.visibility == 'private' && !data.renote.userId.equals(user._id)) {
return rej(); return rej();
} }
@@ -182,7 +184,7 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
const noteActivity = await renderActivity(data, note); const noteActivity = await renderActivity(data, note);
if (isLocalUser(user)) { if (isLocalUser(user) && note.visibility != 'private') {
deliverNoteToMentionedRemoteUsers(mentionedUsers, user, noteActivity); deliverNoteToMentionedRemoteUsers(mentionedUsers, user, noteActivity);
} }
@@ -239,7 +241,7 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
}); });
async function renderActivity(data: Option, note: INote) { async function renderActivity(data: Option, note: INote) {
const content = data.renote && data.text == null const content = data.renote && data.text == null && data.poll == null && (data.files == null || data.files.length == 0)
? renderAnnounce(data.renote.uri ? data.renote.uri : `${config.url}/notes/${data.renote._id}`, note) ? renderAnnounce(data.renote.uri ? data.renote.uri : `${config.url}/notes/${data.renote._id}`, note)
: renderCreate(await renderNote(note, false), note); : renderCreate(await renderNote(note, false), note);
@@ -267,10 +269,12 @@ async function publish(user: IUser, note: INote, noteObj: any, reply: INote, ren
} }
if (['private', 'followers', 'specified'].includes(note.visibility)) { if (['private', 'followers', 'specified'].includes(note.visibility)) {
// Publish event to myself's stream const detailPackedNote = await pack(note, user, {
publishUserStream(note.userId, 'note', await pack(note, user, {
detail: true detail: true
})); });
// Publish event to myself's stream
publishUserStream(note.userId, 'note', detailPackedNote);
publishHybridTimelineStream(note.userId, detailPackedNote);
} else { } else {
// Publish event to myself's stream // Publish event to myself's stream
publishUserStream(note.userId, 'note', noteObj); publishUserStream(note.userId, 'note', noteObj);
@@ -282,6 +286,9 @@ async function publish(user: IUser, note: INote, noteObj: any, reply: INote, ren
if (note.visibility == 'public') { if (note.visibility == 'public') {
publishHybridTimelineStream(null, noteObj); publishHybridTimelineStream(null, noteObj);
} else {
// Publish event to myself's stream
publishHybridTimelineStream(note.userId, noteObj);
} }
} }
} }
@@ -442,6 +449,11 @@ async function publishToUserLists(note: INote, noteObj: any) {
} }
async function publishToFollowers(note: INote, noteObj: any, user: IUser, noteActivity: any) { async function publishToFollowers(note: INote, noteObj: any, user: IUser, noteActivity: any) {
const detailPackedNote = await pack(note, null, {
detail: true,
skipHide: true
});
const followers = await Following.find({ const followers = await Following.find({
followeeId: note.userId followeeId: note.userId
}); });
@@ -460,10 +472,10 @@ async function publishToFollowers(note: INote, noteObj: any, user: IUser, noteAc
} }
// Publish event to followers stream // Publish event to followers stream
publishUserStream(following.followerId, 'note', noteObj); publishUserStream(following.followerId, 'note', detailPackedNote);
if (isRemoteUser(user) || note.visibility != 'public') { if (isRemoteUser(user) || note.visibility != 'public') {
publishHybridTimelineStream(following.followerId, noteObj); publishHybridTimelineStream(following.followerId, detailPackedNote);
} }
} else { } else {
// フォロワーがリモートユーザーかつ投稿者がローカルユーザーなら投稿を配信 // フォロワーがリモートユーザーかつ投稿者がローカルユーザーなら投稿を配信

View File

@@ -25,7 +25,8 @@ export default async function(user: IUser, note: INote) {
tags: [], tags: [],
fileIds: [], fileIds: [],
poll: null, poll: null,
geo: null geo: null,
cw: null
} }
}); });

View File

@@ -1,58 +1,97 @@
import * as mongo from 'mongodb'; import * as mongo from 'mongodb';
import Xev from 'xev'; import Xev from 'xev';
import Meta, { IMeta } from './models/meta';
const ev = new Xev();
type ID = string | mongo.ObjectID; type ID = string | mongo.ObjectID;
function publish(channel: string, type: string, value?: any): void { class Publisher {
const message = type == null ? value : value == null ? private ev: Xev;
{ type: type } : private meta: IMeta;
{ type: type, body: value };
ev.emit(channel, message); constructor() {
this.ev = new Xev();
setInterval(async () => {
this.meta = await Meta.findOne({});
}, 5000);
}
public getMeta = async () => {
if (this.meta != null) return this.meta;
this.meta = await Meta.findOne({});
return this.meta;
}
private publish = (channel: string, type: string, value?: any): void => {
const message = type == null ? value : value == null ?
{ type: type } :
{ type: type, body: value };
this.ev.emit(channel, message);
}
public publishUserStream = (userId: ID, type: string, value?: any): void => {
this.publish(`user-stream:${userId}`, type, typeof value === 'undefined' ? null : value);
}
public publishDriveStream = (userId: ID, type: string, value?: any): void => {
this.publish(`drive-stream:${userId}`, type, typeof value === 'undefined' ? null : value);
}
public publishNoteStream = (noteId: ID, type: string): void => {
this.publish(`note-stream:${noteId}`, null, noteId);
}
public publishUserListStream = (listId: ID, type: string, value?: any): void => {
this.publish(`user-list-stream:${listId}`, type, typeof value === 'undefined' ? null : value);
}
public publishMessagingStream = (userId: ID, otherpartyId: ID, type: string, value?: any): void => {
this.publish(`messaging-stream:${userId}-${otherpartyId}`, type, typeof value === 'undefined' ? null : value);
}
public publishMessagingIndexStream = (userId: ID, type: string, value?: any): void => {
this.publish(`messaging-index-stream:${userId}`, type, typeof value === 'undefined' ? null : value);
}
public publishReversiStream = (userId: ID, type: string, value?: any): void => {
this.publish(`reversi-stream:${userId}`, type, typeof value === 'undefined' ? null : value);
}
public publishReversiGameStream = (gameId: ID, type: string, value?: any): void => {
this.publish(`reversi-game-stream:${gameId}`, type, typeof value === 'undefined' ? null : value);
}
public publishLocalTimelineStream = async (note: any): Promise<void> => {
const meta = await this.getMeta();
if (meta.disableLocalTimeline) return;
this.publish('local-timeline', null, note);
}
public publishHybridTimelineStream = async (userId: ID, note: any): Promise<void> => {
const meta = await this.getMeta();
if (meta.disableLocalTimeline) return;
this.publish(userId ? `hybrid-timeline:${userId}` : 'hybrid-timeline', null, note);
}
public publishGlobalTimelineStream = (note: any): void => {
this.publish('global-timeline', null, note);
}
} }
export function publishUserStream(userId: ID, type: string, value?: any): void { const publisher = new Publisher();
publish(`user-stream:${userId}`, type, typeof value === 'undefined' ? null : value);
}
export function publishDriveStream(userId: ID, type: string, value?: any): void { export default publisher;
publish(`drive-stream:${userId}`, type, typeof value === 'undefined' ? null : value);
}
export function publishNoteStream(noteId: ID, type: string): void { export const publishUserStream = publisher.publishUserStream;
publish(`note-stream:${noteId}`, null, noteId); export const publishDriveStream = publisher.publishDriveStream;
} export const publishNoteStream = publisher.publishNoteStream;
export const publishUserListStream = publisher.publishUserListStream;
export function publishUserListStream(listId: ID, type: string, value?: any): void { export const publishMessagingStream = publisher.publishMessagingStream;
publish(`user-list-stream:${listId}`, type, typeof value === 'undefined' ? null : value); export const publishMessagingIndexStream = publisher.publishMessagingIndexStream;
} export const publishReversiStream = publisher.publishReversiStream;
export const publishReversiGameStream = publisher.publishReversiGameStream;
export function publishMessagingStream(userId: ID, otherpartyId: ID, type: string, value?: any): void { export const publishLocalTimelineStream = publisher.publishLocalTimelineStream;
publish(`messaging-stream:${userId}-${otherpartyId}`, type, typeof value === 'undefined' ? null : value); export const publishHybridTimelineStream = publisher.publishHybridTimelineStream;
} export const publishGlobalTimelineStream = publisher.publishGlobalTimelineStream;
export function publishMessagingIndexStream(userId: ID, type: string, value?: any): void {
publish(`messaging-index-stream:${userId}`, type, typeof value === 'undefined' ? null : value);
}
export function publishReversiStream(userId: ID, type: string, value?: any): void {
publish(`reversi-stream:${userId}`, type, typeof value === 'undefined' ? null : value);
}
export function publishReversiGameStream(gameId: ID, type: string, value?: any): void {
publish(`reversi-game-stream:${gameId}`, type, typeof value === 'undefined' ? null : value);
}
export function publishLocalTimelineStream(note: any): void {
publish('local-timeline', null, note);
}
export function publishHybridTimelineStream(userId: ID, note: any): void {
publish(userId ? `hybrid-timeline:${userId}` : 'hybrid-timeline', null, note);
}
export function publishGlobalTimelineStream(note: any): void {
publish('global-timeline', null, note);
}