Compare commits
140 Commits
Author | SHA1 | Date | |
---|---|---|---|
80d8af84dd | |||
aac519bf80 | |||
d64dffbdda | |||
4015ccef2f | |||
b6f985abaf | |||
2dac8d3d1f | |||
4f284e1bc0 | |||
b0280355e8 | |||
048d88b784 | |||
bb52ebdc3e | |||
5f2fda85ba | |||
1331f0b953 | |||
736fdabc1d | |||
7096c0ca49 | |||
1a984de8e8 | |||
285d0d13f9 | |||
63c659bc8f | |||
af60b45ee7 | |||
e7effd606d | |||
5042d23bc4 | |||
b134467bd3 | |||
5cc1aab530 | |||
49d57ce049 | |||
f1feceaf1a | |||
1204e1c5e4 | |||
96cf4c30cf | |||
a3853611ad | |||
ef7eaaabfa | |||
a4a96710b0 | |||
6d08909b2f | |||
2615368b1e | |||
2bd03ca725 | |||
67dda01fcb | |||
e9dc54c4d9 | |||
fde9fc2891 | |||
6e59798e82 | |||
5e3cc0a3c6 | |||
cfb35324d0 | |||
9bfbc12afa | |||
b41cddaf5a | |||
1432a7193d | |||
20630cb3a0 | |||
2eb02ae581 | |||
801f9027aa | |||
802739a2df | |||
95b1e1a21d | |||
b8060a522a | |||
fe2191a491 | |||
2891f52817 | |||
5bdc44c672 | |||
65d359b57a | |||
7b6e717e23 | |||
2820f6a621 | |||
6f96e05fec | |||
4c2c762b87 | |||
81fadfa4ff | |||
c227641d50 | |||
dacc713f99 | |||
a1f794ee05 | |||
8b2098fc89 | |||
4436852de0 | |||
a8ff1e19dc | |||
d559aa8e6d | |||
83fedcff3b | |||
9969cf8816 | |||
dee48fff12 | |||
aff80199e5 | |||
b9f1a55190 | |||
07d5bce61a | |||
834edd216c | |||
4670a3d886 | |||
78952df364 | |||
d69df60da4 | |||
6ca69f6f2e | |||
8e8428b667 | |||
5dbe1d448b | |||
85d8e6f220 | |||
72fb23f4d5 | |||
9403ee6495 | |||
94ce4fa780 | |||
911f5c1455 | |||
a6a88af513 | |||
fad1352d51 | |||
41cdae07c3 | |||
3b0daeac3c | |||
99e4b06468 | |||
c88576e3e6 | |||
4de709fe51 | |||
37e4226c70 | |||
1a6ed61b91 | |||
ac641da49c | |||
933a79af93 | |||
f36e3c69b4 | |||
c46bfcc768 | |||
c65ccd5eb0 | |||
162a740295 | |||
9192e98e3f | |||
fad84203c0 | |||
622266d200 | |||
0f6cd3c125 | |||
0dfc1fcf13 | |||
efeebd2165 | |||
69a916d506 | |||
114803a86a | |||
7f54c8fa2a | |||
0af3e15e82 | |||
f9afebc12e | |||
fc7268fd12 | |||
7e7f94d685 | |||
3ea7a49c1c | |||
f596a847c2 | |||
312ba501a3 | |||
c6531e8609 | |||
36c2d0082f | |||
358bb0fc06 | |||
5a4f6b4ada | |||
03136caac4 | |||
e6f78a73ab | |||
bcdab799d0 | |||
50251955cd | |||
2270fbf3ee | |||
deb6485cc2 | |||
6de08d07a3 | |||
f54cd10a04 | |||
dda7b0c80e | |||
3ed9e1ff3f | |||
9c8d26affa | |||
1e1a7ee858 | |||
9cfb72810c | |||
14a774c723 | |||
8509adf961 | |||
9d75ec799b | |||
eed9266ecb | |||
4a88cb5968 | |||
50d4de19f0 | |||
c7456224af | |||
c1524d9bef | |||
aa1d2545b3 | |||
1092818203 | |||
155da0c6a3 |
@ -62,6 +62,13 @@ db:
|
||||
user: example-misskey-user
|
||||
pass: example-misskey-pass
|
||||
|
||||
# Whether disable Caching queries
|
||||
#disableCache: true
|
||||
|
||||
# Extra Connection options
|
||||
#extra:
|
||||
# ssl: true
|
||||
|
||||
# ┌─────────────────────┐
|
||||
#───┘ Redis configuration └─────────────────────────────────────
|
||||
|
||||
|
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
patreon: syuilo
|
163
CHANGELOG.md
163
CHANGELOG.md
@ -17,42 +17,104 @@ npm i -g ts-node
|
||||
npm run migrate
|
||||
```
|
||||
|
||||
How to migrate to v11 from v10
|
||||
------------------------------
|
||||
### 移行の注意点
|
||||
**以下のデータは引き継がれません**
|
||||
* 通知
|
||||
* リモートの投稿
|
||||
* リバーシの対局
|
||||
11.22.0 (2019/06/18)
|
||||
--------------------
|
||||
### ✨Improvements
|
||||
* 管理画面でデータベースの各テーブルのレコード数やサイズを確認できるように
|
||||
* サーバー情報にPostgreSQLのバージョンを追加
|
||||
|
||||
### 手順
|
||||
1. v11をインストールしたい場所に syuilo/misskey をクローン
|
||||
2. config を設定する
|
||||
* PostgreSQL(`db`)の設定とは別に、v10からMongoDBの設定をコピペしてくる(例は下にあります)
|
||||
* `id`の設定を`meid`または`objectid`にする
|
||||
### 🐛Fixes
|
||||
* リモートファイルのダウンロードに失敗することがある問題を修正
|
||||
* アンケートの期間を日時指定で選択すると日時がUTCになってしまう問題を修正
|
||||
* MFMのパースを修正
|
||||
|
||||
``` yml
|
||||
db:
|
||||
host: localhost
|
||||
port: 5432
|
||||
db: misskey
|
||||
user: x
|
||||
pass: x
|
||||
11.21.0 (2019/06/16)
|
||||
--------------------
|
||||
### ✨Improvements
|
||||
* Unicode 12.0 の絵文字に対応
|
||||
* 閉鎖しているホストにはAP deliverしないように
|
||||
* image以外はproxyしないように
|
||||
|
||||
mongodb:
|
||||
user: x
|
||||
pass: x
|
||||
host: localhost
|
||||
port: 27017
|
||||
db: misskey
|
||||
```
|
||||
3. migration ブランチに切り替え
|
||||
4. `npm i`
|
||||
5. `npm run build`
|
||||
6. `npm run init`
|
||||
7. `npm run migrate`
|
||||
8. master ブランチに戻す
|
||||
9. enjoy
|
||||
### 🐛Fixes
|
||||
* サムネイル生成でエラーになるとファイルのアップロードに失敗する問題を修正
|
||||
* オートコンプリートにアニメーション停止が効かない問題を修正
|
||||
|
||||
11.20.4 (2019/06/13)
|
||||
--------------------
|
||||
### 🐛Fixes
|
||||
* 検索結果がループする問題を修正
|
||||
* 設定でPostgreSQLのクエリー結果のキャッシュを無効できるように
|
||||
* 「投稿内の動きのあるテキストを無効にする」だけ反応しない問題を修正
|
||||
* 特定の操作のデータベースのパフォーマンス調整
|
||||
|
||||
11.20.3 (2019/06/10)
|
||||
--------------------
|
||||
### 🐛Fixes
|
||||
* 絵文字サジェストが動作しなくなっていた問題を修正
|
||||
|
||||
11.20.2 (2019/06/10)
|
||||
--------------------
|
||||
### 🐛Fixes
|
||||
* Redisにパスワードを設定している場合接続できない問題を修正
|
||||
* i18n
|
||||
* など
|
||||
|
||||
11.20.1 (2019/06/07)
|
||||
--------------------
|
||||
### 🐛Fixes
|
||||
* リモートファイルのキャッシュをすべて削除するときの動作を修正
|
||||
* ストリームのハッシュタグチャンネルが死んでいる問題を修正
|
||||
* Pagesから他の同一インスタンス内のPagesのページへのリンクができない問題を修正
|
||||
* /api/notes/create 公開範囲private を渡すとタイムアウトする問題を修正
|
||||
* パスワードの確認が完了しなくてもユーザー登録できる問題を修正
|
||||
* 依存関係の更新
|
||||
* i18n
|
||||
|
||||
11.20.0 (2019/05/27)
|
||||
--------------------
|
||||
### ✨Improvements
|
||||
* 管理画面からリモートファイルのキャッシュをすべて削除できるように
|
||||
* 投稿フォームに投稿のURLをペーストしようとすると引用RNにできるように
|
||||
* モバイル版の投稿フォームにファイルをドロップできるように
|
||||
* モバイル版でも投稿の下書き自動保存ができるように
|
||||
* リモートファイルのキャッシュが期限切れになったときにサムネイルが無くならないように
|
||||
* ジョブキュー管理画面を強化
|
||||
|
||||
### 🐛Fixes
|
||||
* 投稿内のローカルなURLプレビューをクリックしたとき not found になることがある問題を修正
|
||||
* デスクトップでユーザーページに遷移するときページが再度読み込みされることがある問題を修正
|
||||
* フォロー申請自動承認オプションが常にオフで表示される問題を修正
|
||||
* ポートを設定せずに起動したときに適切なエラーメッセージが表示されない問題を修正
|
||||
* i18n
|
||||
|
||||
11.19.1 (2019/05/26)
|
||||
--------------------
|
||||
### 🐛Fixes
|
||||
* タグページを遷移してもタイムラインが変わらない問題を修正
|
||||
* インスタンス名を空にしてもMisskeyロゴが表示されない問題を修正
|
||||
* 投稿内のローカルなURLをクリックしたとき not found になることがある問題を修正
|
||||
* npm run init がプロセス終了しない問題を修正
|
||||
|
||||
11.19.0 (2019/05/25)
|
||||
--------------------
|
||||
### ✨Improvements
|
||||
* グループのオーナーを変えられるように
|
||||
* PagesでURLプレビューを表示するように
|
||||
* サーバーログを削除できるように
|
||||
* リンク先が同じインスタンスの投稿内のURLをクリックしたときは新しいタブで開かないように
|
||||
* PostgreSQLの接続オプションを設定ファイルで設定できるように
|
||||
* いくつかのAPIでのパフォーマンスを向上
|
||||
* ユーザビリティの向上
|
||||
* デザインの調整
|
||||
|
||||
### 🐛Fixes
|
||||
* デッキでユーザーページを遷移したときに前のユーザーのタイムラインが残り続ける問題を修正
|
||||
* デッキでフォロー申請が見れない問題を修正
|
||||
* グループ情報が更新できない問題を修正
|
||||
* Firefoxでトークの下が隠れてしまう問題を修正
|
||||
* トーク履歴がないと履歴が読み込み中のままになる問題を修正
|
||||
* 通知で長い名前のユーザーがいると横スクロールが発生する問題を修正
|
||||
* iOSでの選択ダイアログの動作を修正
|
||||
|
||||
11.18.1 (2019/05/21)
|
||||
--------------------
|
||||
@ -476,7 +538,40 @@ mongodb:
|
||||
* 依存ライブラリの問題と思わるため、対応が難しい
|
||||
|
||||
### Migration
|
||||
coming soon...
|
||||
#### 移行の注意点
|
||||
**以下のデータは引き継がれません**
|
||||
* 通知
|
||||
* リモートの投稿
|
||||
* リバーシの対局
|
||||
|
||||
#### 手順
|
||||
1. v11をインストールしたい場所に syuilo/misskey をクローン
|
||||
2. config を設定する
|
||||
* PostgreSQL(`db`)の設定とは別に、v10からMongoDBの設定をコピペしてくる(例は下にあります)
|
||||
* `id`の設定を`meid`または`objectid`にする
|
||||
|
||||
``` yml
|
||||
db:
|
||||
host: localhost
|
||||
port: 5432
|
||||
db: misskey
|
||||
user: x
|
||||
pass: x
|
||||
|
||||
mongodb:
|
||||
user: x
|
||||
pass: x
|
||||
host: localhost
|
||||
port: 27017
|
||||
db: misskey
|
||||
```
|
||||
3. migration ブランチに切り替え
|
||||
4. `npm i`
|
||||
5. `npm run build`
|
||||
6. `npm run init`
|
||||
7. `npm run migrate`
|
||||
8. master ブランチに戻す
|
||||
9. enjoy
|
||||
|
||||
10.100.0
|
||||
----------
|
||||
|
@ -3,11 +3,17 @@
|
||||
|
||||
## Issues
|
||||
Feature suggestions and bug reports are filed in https://github.com/syuilo/misskey/issues .
|
||||
Before creating a new issue, please search existing issues to avoid duplication.
|
||||
If you find the existing issue, please add your reaction or comment to the issue.
|
||||
|
||||
* Please search existing issues to avoid duplication. If your issue is already filed, please add your reaction or comment to the existing one.
|
||||
* If you have multiple independent issues, please submit them separately.
|
||||
|
||||
|
||||
## Localization (l10n)
|
||||
Please use [Crowdin](https://crowdin.com/project/misskey) for localization.
|
||||
Misskey uses [Crowdin](https://crowdin.com/project/misskey) for localization management.
|
||||
You can improve our translations with your Crowdin account.
|
||||
Changes you make in Crowdin will be merged into develop branch.
|
||||
|
||||
If you can't find the language you want to contribute with, please open an issue.
|
||||
|
||||

|
||||
|
||||
@ -15,16 +21,16 @@ Please use [Crowdin](https://crowdin.com/project/misskey) for localization.
|
||||
Misskey uses [vue-i18n](https://github.com/kazupon/vue-i18n).
|
||||
|
||||
## Documentation
|
||||
* Documents for contributors are located in `/docs`.
|
||||
* Documents for instance admins are located in `/docs`.
|
||||
* Documents for end users are located in `src/docs`.
|
||||
* Documents for contributors are located in [`/docs`](/docs).
|
||||
* Documents for instance admins are located in [`/docs`](/docs).
|
||||
* Documents for end users are located in [`/src/docs`](/src/docs).
|
||||
|
||||
## Test
|
||||
* Test codes are located in `/test`.
|
||||
* Test codes are located in [`/test`](/test).
|
||||
|
||||
## Continuous integration
|
||||
Misskey uses CircleCI for automated test.
|
||||
Configuration files are located in `/.circleci`.
|
||||
Configuration files are located in [`/.circleci`](/.circleci).
|
||||
|
||||
## Glossary
|
||||
### AP
|
||||
|
16
README.md
16
README.md
@ -106,22 +106,24 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5888816/36da0f7c15954df0ab13f9abdf227f66/1.jpeg?token-time=2145916800&token-hash=at8QpJXJ8C0zINY_NmoMKv-MhXVoUK-YzTgaJPJzJYU%3D" alt="Hiroshi Seki" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/3.png?token-time=2145916800&token-hash=oH_i7gJjNT7Ot6j9JiVwy7ZJIBqACVnzLqlz4YrDAZA%3D" alt="weepjp" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19045173/cb91c0f345c24d4ebfd05f19906d5e26/1.png?token-time=2145916800&token-hash=o_zKBytJs_AxHwSYw_5R8eD0eSJe3RoTR3kR3Q0syN0%3D" alt="kiritan" width="100"></td>
|
||||
<td><img src="https://c8.patreon.com/2/200/776209" alt="Denshi" width="100"></td>
|
||||
<td><img src="https://c8.patreon.com/2/200/557245" alt="mkatze" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13099460/43cecdbaa63a40d79bf50a96b9910b9d/1.jpe?token-time=2145916800&token-hash=bqwLTk0Wo0hUJJ8J5y7ii05bLzz-_CDA7Bo0Mp4RFU0%3D" alt="ne_moni" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/4.jpe?token-time=2145916800&token-hash=zEyJqVM7u9d8Ri-65fJYSJcWF1jBH1nJ5a3taRzrTmw%3D" alt="Melilot" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5670915/ee175f0bfb6347ffa4ea101a8c097bff/1.jpg?token-time=2145916800&token-hash=mPLM9CA-riFHx-myr3bLZJuH2xBRHA9se5VbHhLIOuA%3D" alt="osapon" width="100"></td>
|
||||
<td><img src="https://c8.patreon.com/2/200/16869916" alt="見当かなみ" width="100"></td>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/rane_hs">Hiroshi Seki</a></td>
|
||||
<td><a href="https://www.patreon.com/weepjp">weepjp</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=19045173">kiritan</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=776209">Denshi</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=557245">mkatze</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=13099460">ne_moni</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td>
|
||||
<td><a href="https://www.patreon.com/osapon">osapon</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ</a></td>
|
||||
</tr></table>
|
||||
<table><tr>
|
||||
<td><img src="https://c8.patreon.com/2/200/16869916" alt="見当かなみ" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18899730/6a22797f68254034a854d69ea2445fc8/1.png?token-time=2145916800&token-hash=b_uj57yxo5VzkSOUS7oXE_762dyOTB_oxzbO6lFNG3k%3D" alt="YuzuRyo61" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1.png?token-time=2145916800&token-hash=FMV7cPKBD1TU2WTbl1jg6AcdKSvTb2BSFcDhgc-EO8w%3D" alt="gutfuckllc" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/11357794/923ce94cd8c44ba788ee931907881839/1.png?token-time=2145916800&token-hash=9nEQje_eMvUjq9a7L3uBqW-MQbS-rRMaMgd7UYVoFNM%3D" alt="mydarkstar" width="100"></td>
|
||||
<td><img src="https://c8.patreon.com/2/200/12718187" alt="Peter G." width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1.jpe?token-time=2145916800&token-hash=UQRWf01TwHDV4Cls1K0YAOAjM29ssif7hLVq0ESQ0hs%3D" alt="nemu" width="100"></td>
|
||||
@ -130,8 +132,8 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
||||
<td><img src="https://c8.patreon.com/2/200/17463605" alt="Sampot" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19356899/496b4681d33b4520bd7688e0fd19c04d/2.jpeg?token-time=2145916800&token-hash=_sTj3dUBOhn9qwiJ7F19Qd-yWWfUqJC_0jG1h0agEqQ%3D" alt="sheeta.s" width="100"></td>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ</a></td>
|
||||
<td><a href="https://www.patreon.com/Yuzulia">YuzuRyo61</a></td>
|
||||
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
|
||||
<td><a href="https://www.patreon.com/mydarkstar">mydarkstar</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12718187">Peter G.</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=13039004">nemu</a></td>
|
||||
@ -151,7 +153,6 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/2384390/5681180e1efb46a8b28e0e8d4c8b9037/1.jpg?token-time=2145916800&token-hash=SJcMy-Q1BcS940-LFUVOMfR7-5SgrzsEQGhYb3yowFk%3D" alt="CG" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18072312/98e894d960314fa7bc236a72a39488fe/1.jpe?token-time=2145916800&token-hash=qA8j97lIZNc-74AuZ0p4F3ms6sKPeKjtNt2vEuwpsyo%3D" alt="Hekovic" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/10789744/97175095d8f04c0f86225ff47cb98d40/1.jpeg?token-time=2145916800&token-hash=l4AoMR7Nj7K4yAHrkrk2hAoggPkbSPm12m1nmbe9Pb8%3D" alt="Naoki Hirayama" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1.jpeg?token-time=2145916800&token-hash=L55UhJ0rcuNAH3w_ryeeGN4hC6taoOixyAhraEi0bzw%3D" alt="dansup" width="100"></td>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/user?u=13737140">Satsuki Yanagi</a></td>
|
||||
<td><a href="https://www.patreon.com/takimura">takimura</a></td>
|
||||
@ -163,19 +164,20 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
||||
<td><a href="https://www.patreon.com/Corset">CG</a></td>
|
||||
<td><a href="https://www.patreon.com/hekovic">Hekovic</a></td>
|
||||
<td><a href="https://www.patreon.com/spinlock">Naoki Hirayama</a></td>
|
||||
<td><a href="https://www.patreon.com/dansup">dansup</a></td>
|
||||
</tr></table>
|
||||
<table><tr>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1.jpeg?token-time=2145916800&token-hash=L55UhJ0rcuNAH3w_ryeeGN4hC6taoOixyAhraEi0bzw%3D" alt="dansup" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1.jpeg?token-time=2145916800&token-hash=d8jBQLMOHD87KtXs5C9fk1o58DMF73pQ-dYH3uZJPBE%3D" alt="Gargron" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5731881/4b6038e6cda34c04b83a5fcce3806a93/1.png?token-time=2145916800&token-hash=hBayGfOmQH3kRMdNnDe4oCZD_9fsJWSt29xXR3KRMVk%3D" alt="Nokotaro Takeda" width="100"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1.jpeg?token-time=2145916800&token-hash=vGe7wXGqmA8Q7m-kDNb6fyGdwk-Dxk4F-ut8ZZu51RM%3D" alt="Takashi Shibuya" width="100"></td>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/dansup">dansup</a></td>
|
||||
<td><a href="https://www.patreon.com/mastodon">Gargron</a></td>
|
||||
<td><a href="https://www.patreon.com/takenoko">Nokotaro Takeda</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
||||
</tr></table>
|
||||
|
||||
**Last updated:** Sun, 19 May 2019 02:37:06 UTC
|
||||
**Last updated:** Tue, 11 Jun 2019 01:46:06 UTC
|
||||
<!-- PATREON_END -->
|
||||
|
||||
:four_leaf_clover: Copyright
|
||||
|
@ -93,6 +93,25 @@ common:
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "Poznámky sledujících se zobrazí ve vaší časové ose"
|
||||
explore: "Najít uživatele"
|
||||
post-form:
|
||||
attach-location-information: "Přidat informace o lokaci"
|
||||
hide-contents: "Schovat obsah"
|
||||
reply-placeholder: "Odpovědět na tento příspěvek"
|
||||
quote-placeholder: "Citovat tento příspěvek"
|
||||
submit: "Odeslat"
|
||||
reply: "Odpovědět"
|
||||
renote: "Renotovat"
|
||||
attach-media-from-local: "Uplodovat soubor z vašeho zařízení"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "Vytvořit anketu"
|
||||
text-remain: "zbývá ještě {} znaků"
|
||||
recent-tags: "Nejnovější"
|
||||
visibility: "Viditelnost"
|
||||
geolocation-alert: "Vaše zařízení nedalo k dispozici lokaci"
|
||||
error: "Chyba"
|
||||
enter-username: "Zadejte své uživatelské jméno"
|
||||
add-visible-user: "Přidat uživatele"
|
||||
username-prompt: "Zadejte své uživatelské jméno"
|
||||
weekday-short:
|
||||
sunday: "Ne"
|
||||
monday: "Po"
|
||||
@ -251,7 +270,7 @@ common:
|
||||
my-token-regenerated: "Váš token byl regenerován, proto budete odhlášen/a."
|
||||
hide-password: "Skrýt heslo"
|
||||
show-password: "Zobrazit heslo"
|
||||
enter-username: "Zadejte uživatelské jméno"
|
||||
enter-username: "Zadejte své uživatelské jméno"
|
||||
do-not-use-in-production: "Tohle je vývojářský build. Nepoužívejte v produkci."
|
||||
user-suspended: "Tomuto uživateli byl pozastaven účet."
|
||||
is-remote-user: "Informace o tomto uživateli nemusí být kompletní."
|
||||
@ -308,7 +327,10 @@ auth/views/form.vue:
|
||||
accept: "Povolit přístup"
|
||||
auth/views/index.vue:
|
||||
loading: "Načítám..."
|
||||
denied-paragraph: "Tato aplikace nebude mít přístup k Vašemu účtu."
|
||||
already-authorized: "Tato aplikace byla již autorizována."
|
||||
callback-url: "Zpátky do aplikace."
|
||||
please-go-back: "Prosím vraťte se zpátky do aplikace."
|
||||
error: "Taková relace neexistuje."
|
||||
sign-in: "Prosím přihlaste se."
|
||||
common/views/pages/explore.vue:
|
||||
@ -358,23 +380,30 @@ common/views/components/games/reversi/reversi.room.vue:
|
||||
waiting-for-both: "Připravuji"
|
||||
cancel: "Zrušit"
|
||||
ready: "Připraveno"
|
||||
cancel-ready: "Pokračovat v přípravě"
|
||||
common/views/components/connect-failed.vue:
|
||||
title: "Nelze se připojit k serveru"
|
||||
description: "Nastal problém s Vaším připojením k internetu, nebo server není dostupný nebo zrovna probíhá údržba. Prosím {zkuste to znova} za pár minut."
|
||||
thanks: "Děkujeme že jste použili Misskey."
|
||||
common/views/components/connect-failed.troubleshooter.vue:
|
||||
title: "Poradce při potížích"
|
||||
network: "Síťové připojení"
|
||||
checking-network: "Prověřit síťové připojení"
|
||||
internet: "Připojení k internetu"
|
||||
checking-internet: "Ověřuji připojení k internetu."
|
||||
server: "Připojení k serveru"
|
||||
checking-server: "Spojuji se se serverem"
|
||||
no-network-desc: "Ujistěte se že jste připojeni k Internetu."
|
||||
no-internet: "Nejste připojeni k internetu"
|
||||
no-internet-desc: "Jste připojen k síti, ale zdá se že stále chybí připojení k Internetu. Prosím zkontrolujte Vaše připojení k Internetu."
|
||||
no-server: "Nelze se připojit k serveru Misskey"
|
||||
success: "Úspěšně se podařilo spojit s Misskey serverem"
|
||||
flush: "Vyčistit mezipaměť"
|
||||
common/views/components/media-banner.vue:
|
||||
sensitive: "Choulostivý obsah"
|
||||
click-to-show: "Klikněte pro zobrazení"
|
||||
common/views/components/theme.vue:
|
||||
theme: "Vzhled"
|
||||
light-theme: "Motiv pro použití ve světlém vzhledu"
|
||||
dark-theme: "Motiv pro použití v tmavém vzhledu"
|
||||
light-themes: "Světlý vzhled"
|
||||
@ -385,6 +414,7 @@ common/views/components/theme.vue:
|
||||
installed: "\"{}\" byl nainstalován"
|
||||
create-a-theme: "Vytvořit motiv"
|
||||
save-created-theme: "Uložit motiv"
|
||||
primary-color: "Základní barva"
|
||||
text-color: "Barva textu"
|
||||
base-theme: "Základní vzhled"
|
||||
base-theme-light: "Světlý"
|
||||
@ -392,8 +422,10 @@ common/views/components/theme.vue:
|
||||
find-more-theme: "Najít další vzhledy"
|
||||
theme-name: "Jméno vzhledu"
|
||||
preview-created-theme: "Náhled"
|
||||
invalid-theme: "Vzhled není validní"
|
||||
already-installed: "Tento vzhled je již nainstalován."
|
||||
saved: "Uloženo"
|
||||
manage-themes: "Správa vzhledů"
|
||||
builtin-themes: "Standardní vzhledy"
|
||||
my-themes: "Moje vzhledy"
|
||||
installed-themes: "Nainstalované vzhledy"
|
||||
@ -404,6 +436,7 @@ common/views/components/theme.vue:
|
||||
desc: "Popis"
|
||||
export: "Exportovat"
|
||||
import: "Importovat"
|
||||
import-by-code: "nebo zkopírujte kód"
|
||||
theme-name-required: "Jméno vzhledu je povinné"
|
||||
common/views/components/cw-button.vue:
|
||||
hide: "Skrýt"
|
||||
@ -476,10 +509,13 @@ common/views/components/poll-editor.vue:
|
||||
remove: "Odstranit tuto možnost"
|
||||
add: "+ Přidat možnost"
|
||||
destroy: "Zahodit dotazník"
|
||||
multiple: "Více odpovědí je povoleno"
|
||||
expiration: "Termín"
|
||||
infinite: "Nekonečne"
|
||||
at: "Výběr data a času"
|
||||
no-more: "Více už přidat nemůžete"
|
||||
deadline-date: "Termín ukončení"
|
||||
deadline-time: "Doba trvání"
|
||||
interval: "Trvání"
|
||||
second: "Sekunda"
|
||||
minute: "Minuta"
|
||||
@ -487,6 +523,7 @@ common/views/components/poll-editor.vue:
|
||||
day: "Ne"
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "Vyberte svoji reakci"
|
||||
input-reaction-placeholder: "nebo vložte Emoji"
|
||||
common/views/components/emoji-picker.vue:
|
||||
custom-emoji: "Emoji"
|
||||
people: "Lidé"
|
||||
@ -500,6 +537,7 @@ common/views/components/emoji-picker.vue:
|
||||
common/views/components/signin.vue:
|
||||
username: "Přezdívka"
|
||||
password: "Heslo"
|
||||
token: "Token"
|
||||
signing-in: "Přihlašování..."
|
||||
or: "Nebo"
|
||||
signin-with-twitter: "Přihlásit se pomocí účtu Twitter"
|
||||
@ -527,6 +565,7 @@ common/views/components/signup.vue:
|
||||
password-matched: "OK"
|
||||
password-not-matched: "Neshodují se"
|
||||
recaptcha: "Potvrzení"
|
||||
tos: "Podmínky užívání"
|
||||
create: "Vytvořit účet"
|
||||
some-error: "Pokus o vytvoření účtu selhal. Prosím zkuste to znovu."
|
||||
common/views/components/special-message.vue:
|
||||
@ -565,6 +604,7 @@ common/views/components/visibility-chooser.vue:
|
||||
home: "Domů"
|
||||
specified-desc: "Poslat pouze zmíněným uživatelům"
|
||||
local-public: "Veřejná (pouze místní)"
|
||||
local-public-desc: "Nepublikovat na vzdálených serverech"
|
||||
local-home: "Domovská (pouze místní)"
|
||||
local-followers: "Pro sledující (pouze místní)"
|
||||
common/views/components/trends.vue:
|
||||
@ -574,6 +614,8 @@ common/views/components/language-settings.vue:
|
||||
title: "Zobrazit jazyky"
|
||||
pick-language: "Zvolte jazyk"
|
||||
recommended: "Doporučené"
|
||||
auto: "Automaticky"
|
||||
specify-language: "Vyberte jazyk"
|
||||
info: "Pro aktivování změn musíte znovu načíst stránky."
|
||||
common/views/components/profile-editor.vue:
|
||||
title: "Profil"
|
||||
@ -600,6 +642,7 @@ common/views/components/profile-editor.vue:
|
||||
email-not-verified: "Váš email není potvrzen. Prosím zkontrolujte si svou schránku."
|
||||
export: "Exportovat"
|
||||
import: "Importovat"
|
||||
export-and-import: "Import / Export"
|
||||
export-targets:
|
||||
following-list: "Seznam sledujících"
|
||||
mute-list: "Seznam ztlumených uživatelů"
|
||||
@ -618,15 +661,32 @@ common/views/components/user-list-editor.vue:
|
||||
deleted: "Smazáno"
|
||||
add-user: "Přidat uživatele"
|
||||
common/views/components/user-group-editor.vue:
|
||||
users: "Členové"
|
||||
rename: "Přejmenovat skupinu"
|
||||
delete: "Odstranit skupinu"
|
||||
transfer: "Přesunout skupinu"
|
||||
transfer-are-you-sure: "Jste si jistí že chcete přidat @$2 do skupiny: $1?"
|
||||
transferred: "Skupina přesunuta"
|
||||
remove-user: "Odebrat uživatele z této skupiny"
|
||||
delete-are-you-sure: "Jste si jistí že chcete smazat skupinu \"$1\"?"
|
||||
deleted: "Smazáno"
|
||||
invite: "Pozvat"
|
||||
invited: "Pozvánka byla úspěšně odeslána"
|
||||
common/views/components/user-lists.vue:
|
||||
user-lists: "Seznamy"
|
||||
create-list: "Vytvořit seznam"
|
||||
list-name: "Název seznamu"
|
||||
common/views/components/user-groups.vue:
|
||||
user-groups: "Skupiny"
|
||||
create-group: "Vytvořit skupinu"
|
||||
group-name: "Název skupiny"
|
||||
owned-groups: "Moje skupiny"
|
||||
invites: "Pozvat"
|
||||
reject-invite: "Odmítnout"
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "Načítám"
|
||||
no-broadcasts: "Žádná nová oznámení"
|
||||
have-a-nice-day: "Přejeme Vám příjemný den!"
|
||||
next: "Další"
|
||||
common/views/widgets/calendar.vue:
|
||||
year: "Rok {}"
|
||||
@ -653,6 +713,12 @@ common/views/widgets/slideshow.vue:
|
||||
no-image: "V této složce nebyly nalezeny žádné fotky."
|
||||
common/views/pages/not-found.vue:
|
||||
page-not-found: "Stránka nenalezena"
|
||||
common/views/pages/follow.vue:
|
||||
following: "Sledování"
|
||||
follow: "Sledovat"
|
||||
common/views/pages/follow-requests.vue:
|
||||
accept: "Přijmout"
|
||||
reject: "Odmítnout"
|
||||
desktop:
|
||||
banner: "Baner"
|
||||
avatar-crop-title: "Vyberte část, která se zobrazí jako avatar"
|
||||
@ -755,27 +821,11 @@ desktop/views/components/notes.vue:
|
||||
error: "Načítání selhalo."
|
||||
retry: "Opakovat"
|
||||
desktop/views/components/post-form.vue:
|
||||
add-visible-user: "+Přidat uživatele"
|
||||
attach-location-information: "Přidat informace o lokaci"
|
||||
hide-contents: "Schovat obsah"
|
||||
reply-placeholder: "Odpovědět na tento příspěvěk"
|
||||
quote-placeholder: "Citovat tento příspěvek"
|
||||
submit: "Příspěvek"
|
||||
reply: "Odpovědět"
|
||||
renote: "Renotovat"
|
||||
posted: "Odesláno!"
|
||||
replied: "Odpověděno!"
|
||||
reposted: "Renotováno!"
|
||||
note-failed: "Nepodařilo se přidat příspěvek"
|
||||
renote-failed: "Renotování neuspělo"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "Vytvořit anketu"
|
||||
text-remain: "{0} znaků zbývá"
|
||||
recent-tags: "Nejnovější"
|
||||
visibility: "Viditelnost"
|
||||
geolocation-alert: "Vaše zařízení nepodporuje lokační službu"
|
||||
error: "Chyba"
|
||||
enter-username: "Zadejte své uživatelské jméno..."
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "Nový příspěvek"
|
||||
reply: "Odpovědět"
|
||||
@ -794,6 +844,7 @@ desktop/views/components/renote-form-window.vue:
|
||||
desktop/views/components/settings.2fa.vue:
|
||||
detail: "Více…"
|
||||
url: "https://www.google.cz/landing/2step/"
|
||||
token: "Token"
|
||||
common/views/components/media-image.vue:
|
||||
click-to-show: "Klikněte pro zobrazení"
|
||||
common/views/components/api-settings.vue:
|
||||
@ -850,6 +901,7 @@ desktop/views/components/ui.header.vue:
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "Váš profil"
|
||||
lists: "Seznamy"
|
||||
groups: "Skupiny"
|
||||
admin: "Administrace"
|
||||
desktop/views/components/ui.header.nav.vue:
|
||||
game: "Hry"
|
||||
@ -884,6 +936,11 @@ admin/views/dashboard.vue:
|
||||
instances: "Instance"
|
||||
this-instance: "Tato instance"
|
||||
federated: "Z fedivesmíru"
|
||||
admin/views/logs.vue:
|
||||
logs: "Logy"
|
||||
levels:
|
||||
info: "Informace"
|
||||
error: "Chyba"
|
||||
admin/views/abuse.vue:
|
||||
details: "Popis"
|
||||
remove-report: "Odstranit"
|
||||
@ -1026,6 +1083,7 @@ admin/views/federation.vue:
|
||||
host: "Hostitel"
|
||||
notes: "Poznámky"
|
||||
users: "Uživatelé"
|
||||
following: "Sledování"
|
||||
caught-at: "Vytvořeno"
|
||||
status: "Status"
|
||||
latest-request-received-at: "Poslední požadavek přijat"
|
||||
@ -1045,6 +1103,7 @@ admin/views/federation.vue:
|
||||
hour: "za hodinu"
|
||||
day: "za den"
|
||||
blocked-hosts: "Blokován"
|
||||
save: "Uložit"
|
||||
desktop/views/pages/welcome.vue:
|
||||
about: "O Misskey"
|
||||
timeline: "Časová osa"
|
||||
@ -1083,6 +1142,8 @@ desktop/views/pages/user/user.photos.vue:
|
||||
no-photos: "Žádné obrázky"
|
||||
desktop/views/pages/user/user.header.vue:
|
||||
posts: "Poznámky"
|
||||
following: "Sledovaní"
|
||||
followers: "Sledující"
|
||||
month: "Po"
|
||||
day: "Ne"
|
||||
desktop/views/widgets/notifications.vue:
|
||||
@ -1111,6 +1172,7 @@ mobile/views/components/drive.file-detail.vue:
|
||||
mobile/views/components/media-video.vue:
|
||||
click-to-show: "Klikněte pro zobrazení"
|
||||
common/views/components/follow-button.vue:
|
||||
following: "Sledování"
|
||||
follow-processing: "Zpracovávám"
|
||||
mobile/views/components/note.vue:
|
||||
private: "Tento příspěvek je soukromý"
|
||||
@ -1130,15 +1192,6 @@ mobile/views/components/note-sub.vue:
|
||||
admin: "admin"
|
||||
bot: "bot"
|
||||
cat: "kočka"
|
||||
mobile/views/components/post-form.vue:
|
||||
add-visible-user: "Přidat uživatele"
|
||||
submit: "Příspěvek"
|
||||
reply: "Odpovědět"
|
||||
renote: "Renotovat"
|
||||
reply-placeholder: "Odpovědět na tento příspěvěk"
|
||||
geolocation-alert: "Vaše zařízení nepodporuje lokační službu"
|
||||
error: "Chyba"
|
||||
username-prompt: "Zadejte uživatelské jméno"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
private: "Tento příspěvek je soukromý"
|
||||
deleted: "Tento příspěvek byl odstraněn"
|
||||
@ -1151,6 +1204,7 @@ mobile/views/components/ui.nav.vue:
|
||||
notifications: "Oznámení"
|
||||
search: "Vyhledávání"
|
||||
user-lists: "Seznamy"
|
||||
user-groups: "Skupiny"
|
||||
widgets: "Widgety"
|
||||
game: "Hry"
|
||||
admin: "Administrace"
|
||||
|
@ -95,6 +95,14 @@ common:
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "Følgende brugere vil få vist deres poster på tidslinjen."
|
||||
explore: "Find brugere"
|
||||
post-form:
|
||||
submit: "Post"
|
||||
reply: "Svar"
|
||||
renote: "Gen-postering"
|
||||
error: "Fejl"
|
||||
enter-username: "Angiv brugernavn"
|
||||
add-visible-user: "Tilføj en bruger"
|
||||
username-prompt: "Angiv brugernavn"
|
||||
weekday-short:
|
||||
sunday: "Søn"
|
||||
monday: "Man"
|
||||
@ -918,34 +926,12 @@ desktop/views/components/notes.vue:
|
||||
desktop/views/components/notifications.vue:
|
||||
empty: "Der er ingen notifikationer!"
|
||||
desktop/views/components/post-form.vue:
|
||||
add-visible-user: "+Tilføj bruger"
|
||||
attach-location-information: "Vedhæft oplysninger om placering"
|
||||
hide-contents: "Skjul indhold"
|
||||
reply-placeholder: "Svar på denne post"
|
||||
quote-placeholder: "Citer denne post"
|
||||
submit: "Post"
|
||||
reply: "Svar"
|
||||
renote: "Gen-postering"
|
||||
posted: "Afsendt!"
|
||||
replied: "Besvaret!"
|
||||
reposted: "Gen-posteret!"
|
||||
note-failed: "Fejl under afsendelse"
|
||||
reply-failed: "Fejl under besvarelse"
|
||||
renote-failed: "Fejl under gen-postering"
|
||||
posting: "Afsender"
|
||||
attach-media-from-local: "Vedhæft medie fra din enhed"
|
||||
attach-media-from-drive: "Vedhæft medie fra dit drev"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "Opret en afstemning"
|
||||
text-remain: "Der mangler {} tegn"
|
||||
recent-tags: "Seneste"
|
||||
local-only-message: "Denne post vil kun blive offentliggjort lokalt"
|
||||
click-to-tagging: "Klik for at tagge"
|
||||
visibility: "Synlighed"
|
||||
geolocation-alert: "Din enhed giver ikke mulighed for at benytte placeringstjenester"
|
||||
error: "Fejl"
|
||||
enter-username: "Angiv brugernavn"
|
||||
annotations: "Kommentarer til posten (frivillige)"
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "Ny post"
|
||||
reply: "Svar"
|
||||
@ -1106,6 +1092,13 @@ admin/views/dashboard.vue:
|
||||
admin/views/queue.vue:
|
||||
title: "Kø"
|
||||
remove-all-jobs: "Ryd alle job køer"
|
||||
queue: "Kø"
|
||||
state: "Sorter efter"
|
||||
admin/views/logs.vue:
|
||||
logs: "Logs"
|
||||
levels:
|
||||
info: "Information"
|
||||
error: "Fejl"
|
||||
admin/views/abuse.vue:
|
||||
title: "Misbrug"
|
||||
target: "Mål"
|
||||
@ -1402,6 +1395,7 @@ admin/views/federation.vue:
|
||||
day: "pr. dag"
|
||||
blocked-hosts: "Bloker"
|
||||
blocked-hosts-info: "Beskrivelse af værterne du vil blokere, adskilt af linjeskift."
|
||||
save: "Gem"
|
||||
desktop/views/pages/welcome.vue:
|
||||
about: "Mere info..."
|
||||
timeline: "Tidslinje"
|
||||
@ -1533,17 +1527,6 @@ mobile/views/components/note-sub.vue:
|
||||
cat: "cat"
|
||||
mobile/views/components/notifications.vue:
|
||||
empty: "Der er ingen notifikationer!"
|
||||
mobile/views/components/post-form.vue:
|
||||
add-visible-user: "Tilføj en bruger"
|
||||
submit: "Post"
|
||||
reply: "Svar"
|
||||
renote: "Gen-postering"
|
||||
quote-placeholder: "Citer denne post... (valgfrit)"
|
||||
reply-placeholder: "Svar på denne post"
|
||||
cw-placeholder: "Kommentar til indholdet (valgfrit)"
|
||||
geolocation-alert: "Din enhed giver ikke mulighed for at benytte placeringstjenester"
|
||||
error: "Fejl"
|
||||
username-prompt: "Angiv brugernavn"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
private: "Posten er privat"
|
||||
deleted: "Posten er blevet fjernet"
|
||||
@ -1778,8 +1761,7 @@ pages:
|
||||
_divide:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
remind: "÷ Tomo"
|
||||
_remind:
|
||||
_mod:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
eq: "A og B er ens"
|
||||
|
@ -10,26 +10,35 @@ common:
|
||||
about: "Misskey ist eine Quelloffene, <b>dezentralisierte microblogging Software</b>. Es bietet eine erweiterbare Benutzeroberfläche, verschiedenste Möglichkeiten auf Beiträge zu reagieren, kostenlosen Datenspeicher, und andere fortschrittliche Funktionen. Zusätzlich ist Misskey dazu in der Lage, sich mittels des Fediverse mit beliebig vielen anderen ActivityPub-kompatiblen Diensten zu verbinden. Wenn du zum Beispiel einen Betrag mit Misskey abschickst, wird dieser auch für Nutzer von Mastodon oder Pleroma sichtbar sein. So ähnlich wie eine Radioübertragung zwischen Planeten."
|
||||
features: "Funktionen"
|
||||
rich-contents: "Notizen"
|
||||
rich-contents-desc: "Poste einfach deine Ideen, Interessen und alles, was du teilen möchtest. Gestalte deine Nachrichten, teile deine Lieblingsbilder, sende Dateien und Videos und erstelle Umfragen – das und mehr kann Misskey!"
|
||||
reaction: "Reaktionen"
|
||||
reaction-desc: "Der einfachste Weg, deine Gefühle mit anderen zu teilen. Mit Misskey kannst du auf verschiedenste Arten auf Beiträge reagieren, statt nur zu „liken“."
|
||||
ui: "Benutzeroberfläche"
|
||||
ui-desc: "Geschmäcker sind verschieden. Deswegen ist Misskeys Oberfläche hochanpassbar und modular. Mache die Startseite zu deiner Startseite, indem du das Layout deiner Timeline änderst und mit Widgets staffierst."
|
||||
drive: "Drive"
|
||||
drive-desc: "Du willst ein hochgeladenes Foto nochmal posten? Deine Dateien benennen und in Ordnern sortieren? Misskeys Drive ist der beste Ort dafür. Damit wird das Teilen zum Kinderspiel!"
|
||||
outro: "Probiere Misskey aus und entdecke Misskeys einzigartige Funktionen. Wenn dir diese Instanz nicht zusagt, nimm einfach eine andere. Dank Misskeys dezentralem System kannst du dich überall mit deinen Freunden verbinden. Also dann, GLHF!"
|
||||
adblock:
|
||||
detected: "Bitte deaktiviere den Werbeblocker."
|
||||
warning: "<strong>Misskey hat keine Werbung.</strong> Allerdings können Werbeblocker für unerwartete Probleme und fehlende Funktionen sorgen."
|
||||
application-authorization: "Autorisierte Anwendungen"
|
||||
close: "Schließen"
|
||||
do-not-copy-paste: "Bitte keinen Code einfügen. Ihr Account könnte gefährdet werden."
|
||||
load-more: "Mehr laden"
|
||||
enter-password: "Bitte Passwort eingeben"
|
||||
2fa: "Zwei-Faktor-Authentifizierung"
|
||||
customize-home: "Layout Anpassen"
|
||||
featured-notes: "Hervorgehobene Beiträge"
|
||||
featured-notes: "Beliebt"
|
||||
dark-mode: "Dunkler Modus"
|
||||
signin: "Einloggen"
|
||||
signup: "Registrieren"
|
||||
signout: "Ausloggen"
|
||||
reload-to-apply-the-setting: "Die Seite muss zum Übernehmen dieser Einstellung aktualisiert werden. Soll die Seite jetzt neu geladen werden?"
|
||||
fetching-as-ap-object: "Hole Daten…"
|
||||
got-it: "Verstanden!"
|
||||
customization-tips:
|
||||
title: "Anpassung-Tipps"
|
||||
paragraph: "<p>Du kannst deine Startseite anpassen, indem du Widgets hinzufügst und verschiebst.</p><p><strong>Klicke <strong>rechts</strong></strong> auf ein Widget, um dessen Aussehen zu verändern.</p><p>Um ein Widget zu löschen, klicke und ziehe es auf den <strong>Papierkorb</strong> am Kopfende der Seite.</p><p>Wenn du fertig bist, drücke auf den Beenden-Knopf oben rechts.</p>"
|
||||
gotit: "Verstanden!"
|
||||
notification:
|
||||
file-uploaded: "Datei hochgeladen!"
|
||||
@ -56,25 +65,41 @@ common:
|
||||
pages: "Seite"
|
||||
messaging: "Unterhaltungen"
|
||||
home: "Home"
|
||||
deck: "Stapel"
|
||||
deck: "Deck"
|
||||
timeline: "Zeitleiste"
|
||||
explore: "Entdecken"
|
||||
following: "Folgt"
|
||||
followers: "Folgende"
|
||||
favorites: "Diesen Beitrag favorisieren"
|
||||
favorites: "Favoriten"
|
||||
permissions:
|
||||
"read:account": "Accountinformationen anzeigen."
|
||||
"write:account": "Accountinformationen bearbeiten."
|
||||
"read:blocks": "Blöcke anzeigen"
|
||||
"write:blocks": "Auf Sperrungen zugreifen"
|
||||
"read:drive": "Dateien anzeigen"
|
||||
"write:drive": "Dateien bearbeiten"
|
||||
"read:favorites": "Favoriten anzeigen"
|
||||
"write:favorites": "Auf Favoriten zugreifen"
|
||||
"read:following": "Follower-Daten lesen"
|
||||
"write:following": "Folgestatus bearbeiten"
|
||||
"read:messaging": "Unterhaltung anzeigen"
|
||||
"write:messaging": "Unterhaltung bearbeiten"
|
||||
"read:mutes": "Stummschaltungen lesen"
|
||||
"write:mutes": "Stummschaltungen bearbeiten"
|
||||
"write:notes": "Beiträge löschen und verfassen"
|
||||
"read:notifications": "Benachrichtigungen lesen"
|
||||
"write:notifications": "Benachrichtigungen bearbeiten"
|
||||
"read:reactions": "Reaktionen sehen"
|
||||
"write:reactions": "Reaktionen hinzufügen und bearbeiten"
|
||||
"write:votes": "Abstimmen"
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "Beiträge von Benutzern, denen du folgst, werden in der Zeitleiste angezeigt."
|
||||
explore: "Benutzer finden"
|
||||
post-form:
|
||||
reply: "Antworten"
|
||||
renote: "Anmerkung"
|
||||
enter-username: "Bitte gib einen Benutzernamen ein"
|
||||
username-prompt: "Bitte gib einen Benutzernamen ein"
|
||||
weekday-short:
|
||||
sunday: "So"
|
||||
monday: "Mo"
|
||||
@ -147,22 +172,116 @@ common:
|
||||
show-reversi-board-labels: "Zeige Reihen- und Spaltenbeschreibungen in Reversi an"
|
||||
use-avatar-reversi-stones: "Avatar als Stein in Reversi anzeigen"
|
||||
disable-animated-mfm: "Animierten Text in Beiträgen deaktivieren"
|
||||
disable-showing-animated-images: "Animierte Grafiken deaktivieren"
|
||||
suggest-recent-hashtags: "Beim Verfassen von Beiträgen letzte Hashtags anzeigen"
|
||||
always-show-nsfw: "Sensible Inhalte (NSFW) immer anzeigen"
|
||||
always-mark-nsfw: "Meine Anhänge immer als NSFW markieren"
|
||||
show-full-acct: "Servername bei Benutzernamen immer anzeigen"
|
||||
show-via: "„via“ anzeigen"
|
||||
reduce-motion: "Animationen der Benutzeroberfläche reduzieren"
|
||||
this-setting-is-this-device-only: "Nur auf diesem Gerät"
|
||||
use-os-default-emojis: "Betriebssystem-Emojis nutzen"
|
||||
line-width: "Linienstärke"
|
||||
line-width-thin: "Dünn"
|
||||
line-width-normal: "Normal"
|
||||
line-width-thick: "Dick"
|
||||
font-size: "Schriftgröße"
|
||||
font-size-x-small: "Sehr klein"
|
||||
font-size-small: "Klein"
|
||||
font-size-medium: "Normal"
|
||||
font-size-large: "Groß"
|
||||
font-size-x-large: "Sehr groß"
|
||||
deck-column-align: "Spaltenaufteilung der Deck-Ansicht"
|
||||
deck-column-align-center: "Mitte"
|
||||
deck-column-align-left: "Links"
|
||||
deck-column-align-flexible: "Flexibel"
|
||||
deck-column-width: "Spaltenbreite des Decks"
|
||||
deck-column-width-narrow: "Sehr eng"
|
||||
deck-column-width-narrower: "Eng"
|
||||
deck-column-width-normal: "Normal"
|
||||
deck-column-width-wider: "Breit"
|
||||
deck-column-width-wide: "Sehr breit"
|
||||
use-shadow: "Nutze Schatten"
|
||||
rounded-corners: "Abgerundete Ecken"
|
||||
circle-icons: "Kreisförmige Icons"
|
||||
contrasted-acct: "Nutzernamen kontrastreicher darstellen"
|
||||
wallpaper: "Hintergrund"
|
||||
choose-wallpaper: "Hintergrund auswählen"
|
||||
delete-wallpaper: "Hintergrund entfernen"
|
||||
post-form-on-timeline: "Beitragsformular über Timeline anzeigen"
|
||||
show-clock-on-header: "Uhr am oberen rechten Rand anzeigen"
|
||||
show-reply-target: "Zeige bei einer Antwort die ursprüngliche Nachricht"
|
||||
timeline: "Timeline"
|
||||
show-my-renotes: "Zeige eigene Renotes in der Timeline"
|
||||
show-renoted-my-notes: "Zeige Renotes deiner Posts in der Timeline"
|
||||
show-local-renotes: "Zeige Renotes lokaler Posts in der Timeline"
|
||||
remain-deleted-note: "Gelöschte Beiträge weiterhin anzeigen"
|
||||
sound: "Töne"
|
||||
enable-sounds: "Töne aktivieren"
|
||||
enable-sounds-desc: "Spiel einen Ton ab beim Erhalten eines Beitrags bzw. einer Nachricht. Diese Einstellung wird im Browser gespeichert."
|
||||
volume: "Lautstärke"
|
||||
test: "Test"
|
||||
update: "Misskey-Update"
|
||||
version: "Version:"
|
||||
latest-version: "Neuste Version:"
|
||||
update-checking: "Suche nach Updates"
|
||||
do-update: "Nach Updates suchen"
|
||||
update-settings: "Erweiterte Einstellungen"
|
||||
no-updates: "Kein Update verfügbar"
|
||||
no-updates-desc: "Misskey ist aktuell."
|
||||
update-available: "Eine neue Version ist verfügbar!"
|
||||
update-available-desc: "Änderungen werden beim Neuladen der Seite angewendet."
|
||||
advanced-settings: "Erweiterte Einstellungen"
|
||||
debug-mode: "Debug-Modus einschalten"
|
||||
debug-mode-desc: "Diese Einstellung wird im Browser gespeichert."
|
||||
navbar-position: "Postion der Navigationsleiste"
|
||||
navbar-position-top: "Oben"
|
||||
navbar-position-left: "Links"
|
||||
navbar-position-right: "Rechts"
|
||||
i-am-under-limited-internet: "Ich möchte Datenvolumen sparen"
|
||||
post-style: "Beitrags-Anzeigestil"
|
||||
post-style-standard: "Standard"
|
||||
post-style-smart: "Smart"
|
||||
notification-position: "Benachrichtigungen anzeigen"
|
||||
notification-position-bottom: "Unten"
|
||||
notification-position-top: "Oben"
|
||||
disable-via-mobile: "Beitrag nicht als „vom Handy“ markieren"
|
||||
load-raw-images: "Anhänge in voller Größe laden"
|
||||
load-remote-media: "Zeige Inhalte von fremden Servern"
|
||||
search: "Suche"
|
||||
delete: "Löschen"
|
||||
loading: "Laden"
|
||||
ok: "Okay"
|
||||
cancel: "Abbrechen"
|
||||
update-available-title: "Aktualisierung verfügbar"
|
||||
update-available: "Eine neue Version von Misskey ist verfügbar ({newer}, aktuell ist {current}). Lade die Seite neu um die aktuelle Version zu laden"
|
||||
my-token-regenerated: "Dein Token wurde generiert. Du wirst jetzt abgemeldet."
|
||||
hide-password: "Passwort verbergen"
|
||||
show-password: "Passwort zeigen"
|
||||
enter-username: "Kontonamen eingeben"
|
||||
do-not-use-in-production: "Dies ist eine Entwicklungsversion. Nicht in einer Produktivumgebung verwenden."
|
||||
user-suspended: "Dieser Nutzer wurde gesperrt."
|
||||
is-remote-user: "Diese Nutzerinformationen können unvollständig sein."
|
||||
is-remote-post: "Dies ist ein entfernter Post."
|
||||
view-on-remote: "Vollständige Infos auf Ursprungsserver anzeigen"
|
||||
renoted-by: "Renote von {user}"
|
||||
no-notes: "Keine Beiträge"
|
||||
turn-on-darkmode: "Dunkles Design"
|
||||
turn-off-darkmode: "Helles Design"
|
||||
error:
|
||||
title: "Allgemeiner Fehler"
|
||||
retry: "Erneut versuchen"
|
||||
reversi:
|
||||
drawn: "Unentschieden"
|
||||
my-turn: "Du bist am Zug"
|
||||
opponent-turn: "Dein Gegner ist an der Reihe"
|
||||
turn-of: "{name}s Zug"
|
||||
past-turn-of: "Zug von {name}"
|
||||
won: "{name} hat gewonnen"
|
||||
black: "Schwarz"
|
||||
white: "Weiß"
|
||||
total: "Gesamt"
|
||||
this-turn: "{count}. Zug"
|
||||
widgets:
|
||||
analog-clock: "Analoge Uhr"
|
||||
profile: "Profil"
|
||||
@ -173,8 +292,10 @@ common:
|
||||
memo: "Notizen"
|
||||
trends: "Trends"
|
||||
photo-stream: "Bilder"
|
||||
posts-monitor: "Beitrags-Aktivität"
|
||||
slideshow: "Diashow"
|
||||
version: "Version"
|
||||
broadcast: "Ankündigungen"
|
||||
notifications: "Benachrichtigungen"
|
||||
users: "Empfohlene Benutzer"
|
||||
polls: "Umfrage"
|
||||
@ -183,7 +304,9 @@ common:
|
||||
nav: "Navigation"
|
||||
tips: "Tipps"
|
||||
hashtags: "Hashtags"
|
||||
queue: "Warteschlange"
|
||||
dev: "Fehler beim Erstellen der Applikation. Bitte versuche es erneut."
|
||||
ai-chan-kawaii: "Ai-chan kawaii!"
|
||||
you: "Du"
|
||||
auth/views/form.vue:
|
||||
share-access: "Erlaubst Du <i>{name}</i> auf deinen Account zuzugreifen?"
|
||||
@ -193,17 +316,37 @@ auth/views/form.vue:
|
||||
auth/views/index.vue:
|
||||
loading: "Lädt"
|
||||
denied: "Autorisierung der Anwendung wurde verweigert."
|
||||
denied-paragraph: "Diese App kann nicht auf deinen Account zugreifen."
|
||||
already-authorized: "Diese Anwendung ist bereits autorisiert."
|
||||
allowed: "Autorisierung der Anwendung wurde erlaubt."
|
||||
callback-url: "Zur App zurückkehren"
|
||||
please-go-back: "Bitte gehe zurück zur Anwendung."
|
||||
error: "Sitzung ist nicht vorhanden."
|
||||
sign-in: "Bitte melde dich an."
|
||||
common/views/pages/explore.vue:
|
||||
pinned-users: "Vorgeschlagen"
|
||||
popular-users: "Beliebt"
|
||||
recently-updated-users: "Kürzlich aktiv"
|
||||
recently-registered-users: "Neue Benutzer"
|
||||
popular-tags: "Beliebte Tags"
|
||||
federated: "Aus dem Fediverse"
|
||||
explore: "{host} erkunden"
|
||||
users-info: "Momentan sind {users} Nutzer hier registriert"
|
||||
common/views/components/url-preview.vue:
|
||||
enable-player: "Player öffnen"
|
||||
disable-player: "Player schließen"
|
||||
common/views/components/user-list.vue:
|
||||
no-users: "Keine Benutzer"
|
||||
common/views/components/games/reversi/reversi.vue:
|
||||
matching:
|
||||
waiting-for: "Warten auf {}"
|
||||
cancel: "Abbrechen"
|
||||
common/views/components/games/reversi/reversi.game.vue:
|
||||
surrender: "Aufgeben"
|
||||
surrendered: "durch Aufgabe"
|
||||
is-llotheo: "Der niedrigere gewinnt (Llotheo)"
|
||||
looped-map: "Spielbrettenden verbinden"
|
||||
can-put-everywhere: "Setzen ist überall erlaubt"
|
||||
common/views/components/games/reversi/reversi.index.vue:
|
||||
title: "Misskey Reversi"
|
||||
sub-title: "Spiele Reversi mit deinen Freunden!"
|
||||
@ -221,7 +364,14 @@ common/views/components/games/reversi/reversi.room.vue:
|
||||
black-or-white: "Schwarz/Weiß"
|
||||
black-is: "Schwarz ist {}"
|
||||
rules: "Regeln"
|
||||
is-llotheo: "Der niedrigere gewinnt (Llotheo)"
|
||||
looped-map: "Spielbrettenden verbinden"
|
||||
can-put-everywhere: "Setzen ist überall erlaubt"
|
||||
settings-of-the-bot: "Bot-Einstellungen"
|
||||
this-game-is-started-soon: "Spiel beginnt gleich"
|
||||
waiting-for-other: "Warte auf den Gegner"
|
||||
waiting-for-me: "Warten, bis du bereit bist"
|
||||
waiting-for-both: "Vorbereiten…"
|
||||
cancel: "Abbrechen"
|
||||
ready: "Bereit"
|
||||
common/views/components/connect-failed.vue:
|
||||
@ -252,10 +402,13 @@ common/views/components/media-banner.vue:
|
||||
sensitive: "Dieser Inhalt ist NSFW"
|
||||
click-to-show: "Klicke zum den Inhalt anzusehen"
|
||||
common/views/components/theme.vue:
|
||||
theme: "Design"
|
||||
light-theme: "Thema"
|
||||
dark-theme: "Thema während des Nachtmodus"
|
||||
light-themes: "Helles Thema"
|
||||
dark-themes: "Dunkles Thema"
|
||||
install-a-theme: "Design wird installiert"
|
||||
theme-code: "Design-Quelltext"
|
||||
install: "Anwenden"
|
||||
installed: "\"{}\" wurde installiert"
|
||||
create-a-theme: "Thema erstellen"
|
||||
@ -266,20 +419,37 @@ common/views/components/theme.vue:
|
||||
base-theme: "Basisthema"
|
||||
base-theme-light: "Hell"
|
||||
base-theme-dark: "Dunkel"
|
||||
find-more-theme: "Mehr Designs finden"
|
||||
theme-name: "Name des Themas"
|
||||
preview-created-theme: "Vorschau"
|
||||
invalid-theme: "Thema ist ungültig"
|
||||
already-installed: "Thema ist bereits installiert"
|
||||
saved: "Gespeichert"
|
||||
manage-themes: "Designs verwalten"
|
||||
builtin-themes: "Standard-Designs"
|
||||
my-themes: "Meine Designs"
|
||||
installed-themes: "Installierte Designs"
|
||||
select-theme: "Design wählen"
|
||||
uninstall: "Deinstallieren"
|
||||
uninstalled: "„{}“ wurde deinstalliert"
|
||||
author: "Autor"
|
||||
desc: "Beschreibung"
|
||||
export: "Exportieren"
|
||||
import: "Importieren"
|
||||
import-by-code: "oder Quelltext einfügen"
|
||||
theme-name-required: "Design-Name ist erforderlich"
|
||||
common/views/components/cw-button.vue:
|
||||
hide: "Ausblenden"
|
||||
show: "Mehr"
|
||||
chars: "{count} Zeichen"
|
||||
files: "{count} Dateien"
|
||||
poll: "Umfrage"
|
||||
common/views/components/messaging.vue:
|
||||
search-user: "Einen Nutzer suchen"
|
||||
you: "Du"
|
||||
no-history: "Keine Chronik"
|
||||
user: "Benutzer"
|
||||
group: "Gruppen"
|
||||
common/views/components/messaging-room.vue:
|
||||
no-history: "Keine weitere Chronik vorhanden"
|
||||
new-message: "Neue Nachricht"
|
||||
@ -301,12 +471,28 @@ common/views/components/nav.vue:
|
||||
develop: "Entwickler"
|
||||
feedback: "Feedback"
|
||||
common/views/components/note-menu.vue:
|
||||
mention: "Erwähnungen"
|
||||
detail: "Details"
|
||||
copy-content: "Inhalt kopieren"
|
||||
copy-link: "Link kopieren"
|
||||
favorite: "Diesen Beitrag favorisieren"
|
||||
unfavorite: "Aus Favoriten entfernen"
|
||||
watch: "Beobachten"
|
||||
unwatch: "Nicht mehr beobachten"
|
||||
pin: "An die Profilseite pinnen"
|
||||
unpin: "Lösen"
|
||||
delete: "Löschen"
|
||||
delete-confirm: "Diesen Beitrag löschen?"
|
||||
remote: "Auf Quelle anzeigen"
|
||||
common/views/components/user-menu.vue:
|
||||
mention: "Erwähnungen"
|
||||
mute: "Stummschalten"
|
||||
unmute: "Stummschaltung aufheben"
|
||||
mute-confirm: "Bist du sicher, dass du diesen Nutzer stummschalten möchtest?"
|
||||
unmute-confirm: "Stummschaltung für diesen Nutzer aufheben?"
|
||||
block: "Sperren"
|
||||
unblock: "Sperrung aufheben"
|
||||
block-confirm: "Diesen Nutzer wirklich sperren?"
|
||||
common/views/components/poll.vue:
|
||||
vote-to: "Stimme für '{}'"
|
||||
vote-count: "{} Stimmen"
|
||||
@ -389,6 +575,8 @@ common/views/components/user-group-editor.vue:
|
||||
common/views/components/user-lists.vue:
|
||||
user-lists: "Listen"
|
||||
common/views/components/user-groups.vue:
|
||||
user-groups: "Gruppen"
|
||||
owned-groups: "Meine Gruppen"
|
||||
invites: "Einladen"
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "Laden"
|
||||
@ -399,6 +587,7 @@ common/views/widgets/photo-stream.vue:
|
||||
title: "Fotostream"
|
||||
no-photos: "Keine Fotos"
|
||||
common/views/widgets/posts-monitor.vue:
|
||||
title: "Beitrags-Aktivität"
|
||||
toggle: "Sicht umschalten"
|
||||
common/views/widgets/server.vue:
|
||||
title: "Serverinformationen"
|
||||
@ -486,7 +675,7 @@ desktop/views/components/followers.vue:
|
||||
desktop/views/components/following.vue:
|
||||
empty: "Du folgst niemanden"
|
||||
desktop/views/components/home.vue:
|
||||
done: "Verbunden"
|
||||
done: "Beenden"
|
||||
add-widget: "Widget hinzufügen:"
|
||||
add: "Hinzufügen"
|
||||
desktop/views/input-dialog.vue:
|
||||
@ -500,7 +689,8 @@ desktop/views/components/note-detail.vue:
|
||||
add-reaction: "Reaktion hinzufügen"
|
||||
desktop/views/components/note.vue:
|
||||
reply: "Antworten"
|
||||
renote: "Anmerken"
|
||||
renote: "Anmerkung"
|
||||
detail: "Details"
|
||||
private: "Dieser Beitrag ist privat"
|
||||
deleted: "Dieser Beitrag wurde entfernt"
|
||||
desktop/views/components/notes.vue:
|
||||
@ -509,27 +699,12 @@ desktop/views/components/notes.vue:
|
||||
desktop/views/components/notifications.vue:
|
||||
empty: "Keine Benachrichtigungen"
|
||||
desktop/views/components/post-form.vue:
|
||||
add-visible-user: "+Nutzer hinzufügen"
|
||||
hide-contents: "Inhalt verstecken"
|
||||
reply-placeholder: "Antworte auf diese Anmerkung..."
|
||||
quote-placeholder: "Zitiere diese Anmerkung..."
|
||||
submit: "Abschicken"
|
||||
reply: "Antworten"
|
||||
renote: "Anmerken"
|
||||
posted: "Gepostet!"
|
||||
replied: "Geantwortet!"
|
||||
reposted: "Weitergesagt!"
|
||||
note-failed: "Anmerkung fehlgeschlagen"
|
||||
reply-failed: "Antwort fehlgeschlagen"
|
||||
renote-failed: "Anmerkung fehlgeschlagen"
|
||||
posting: "Posting"
|
||||
attach-media-from-local: "Medien von deinem PC hinzufügen"
|
||||
attach-media-from-drive: "Medien von deinem Speicher hinzufügen"
|
||||
create-poll: "Eine Abstimmung erstellen"
|
||||
text-remain: "{} Zeichen verbleibend"
|
||||
visibility: "Sichtbarkeit"
|
||||
error: "Fehler"
|
||||
enter-username: "Bitte gib einen Benutzernamen ein..."
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "Neuer Beitrag"
|
||||
reply: "Antworten"
|
||||
@ -579,6 +754,7 @@ desktop/views/components/timeline.vue:
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "Dein Profil"
|
||||
lists: "Listen"
|
||||
groups: "Gruppen"
|
||||
desktop/views/components/ui.header.nav.vue:
|
||||
game: "Spielen"
|
||||
desktop/views/components/ui.header.notifications.vue:
|
||||
@ -592,11 +768,13 @@ desktop/views/components/users-list.vue:
|
||||
admin/views/dashboard.vue:
|
||||
drive: "Drive"
|
||||
admin/views/abuse.vue:
|
||||
details: "Details"
|
||||
remove-report: "Löschen"
|
||||
admin/views/instance.vue:
|
||||
recaptcha-preview: "Vorschau"
|
||||
invite: "Einladen"
|
||||
save: "Speichern"
|
||||
saved: "Gespeichert"
|
||||
admin/views/charts.vue:
|
||||
drive: "Drive"
|
||||
admin/views/drive.vue:
|
||||
@ -616,8 +794,10 @@ admin/views/announcements.vue:
|
||||
save: "Speichern"
|
||||
remove: "Löschen"
|
||||
add: "Hinzufügen"
|
||||
saved: "Gespeichert"
|
||||
admin/views/federation.vue:
|
||||
status: "Status"
|
||||
save: "Speichern"
|
||||
desktop/views/pages/note.vue:
|
||||
prev: "Vorheriger Kommentar"
|
||||
next: "Nächster Kommentar"
|
||||
@ -662,10 +842,6 @@ mobile/views/components/note-detail.vue:
|
||||
location: "Ort"
|
||||
mobile/views/components/notifications.vue:
|
||||
empty: "Keine Benachrichtigungen"
|
||||
mobile/views/components/post-form.vue:
|
||||
reply: "Antworten"
|
||||
renote: "Anmerken"
|
||||
reply-placeholder: "Antworte auf diese Anmerkung..."
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
private: "Dieser Beitrag ist privat"
|
||||
deleted: "Dieser Beitrag wurde entfernt"
|
||||
@ -674,6 +850,7 @@ mobile/views/components/ui.nav.vue:
|
||||
notifications: "Benachrichtigungen"
|
||||
search: "Suchen"
|
||||
user-lists: "Listen"
|
||||
user-groups: "Gruppen"
|
||||
game: "Spielen"
|
||||
about: "Über"
|
||||
mobile/views/pages/drive.vue:
|
||||
|
@ -95,6 +95,33 @@ common:
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "Following users will show their posts in your timeline."
|
||||
explore: "Find users"
|
||||
post-form:
|
||||
attach-location-information: "Attach location information"
|
||||
hide-contents: "Hide contents"
|
||||
reply-placeholder: "Reply to this post..."
|
||||
quote-placeholder: "Quote this Post..."
|
||||
option-quote-placeholder: "Quote this post... (optional)"
|
||||
quote-attached: "Quoted"
|
||||
quote-question: "Do you want to append a quote?"
|
||||
submit: "Post"
|
||||
reply: "Reply"
|
||||
renote: "Renote"
|
||||
posting: "Posting"
|
||||
attach-media-from-local: "Attach media from your device"
|
||||
attach-media-from-drive: "Attach media from your Drive"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "Create a poll"
|
||||
text-remain: "{} characters remaining"
|
||||
recent-tags: "Recent"
|
||||
local-only-message: "This post will only be published locally"
|
||||
click-to-tagging: "Click to tagging"
|
||||
visibility: "Visibility"
|
||||
geolocation-alert: "Your device does not provide location services"
|
||||
error: "Error"
|
||||
enter-username: "Please enter username"
|
||||
add-visible-user: "Add a user"
|
||||
cw-placeholder: "Comments for the post (optional)"
|
||||
username-prompt: "Please enter username"
|
||||
weekday-short:
|
||||
sunday: "S"
|
||||
monday: "M"
|
||||
@ -253,7 +280,7 @@ common:
|
||||
my-token-regenerated: "Your token has been regenerated, so you will be signed out."
|
||||
hide-password: "Hide Password"
|
||||
show-password: "Show Password"
|
||||
enter-username: "Enter user name"
|
||||
enter-username: "Please enter username"
|
||||
do-not-use-in-production: "This is a development build. Do not use in production."
|
||||
user-suspended: "This user has been suspended."
|
||||
is-remote-user: "The information about this user may not be entirely complete."
|
||||
@ -319,7 +346,7 @@ auth/views/index.vue:
|
||||
error: "Session does not exist."
|
||||
sign-in: "Please sign in."
|
||||
common/views/pages/explore.vue:
|
||||
pinned-users: "Higlighted users"
|
||||
pinned-users: "Pinned users"
|
||||
popular-users: "Popular users"
|
||||
recently-updated-users: "Recently active users"
|
||||
recently-registered-users: "Users who joined recently"
|
||||
@ -450,14 +477,22 @@ common/views/components/messaging.vue:
|
||||
you: "You"
|
||||
no-history: "Without history"
|
||||
user: "User"
|
||||
group: "Group"
|
||||
start-with-user: "Start chatting with a user"
|
||||
start-with-group: "Start a group and chat"
|
||||
select-group: "Select a group"
|
||||
common/views/components/messaging-room.vue:
|
||||
not-talked-user: "You have not talked to this user yet"
|
||||
not-talked-group: "There is no conversation in this group"
|
||||
no-history: "There is no further history"
|
||||
new-message: "New message"
|
||||
only-one-file-attached: "You can only attach one file to a message"
|
||||
common/views/components/messaging-room.form.vue:
|
||||
input-message-here: "Enter message here"
|
||||
send: "Send"
|
||||
attach-from-local: "Attach files from your device"
|
||||
attach-from-drive: "Attach files from your Drive"
|
||||
only-one-file-attached: "You can only attach one file to a message"
|
||||
common/views/components/messaging-room.message.vue:
|
||||
is-read: "Read"
|
||||
deleted: "This message has been deleted"
|
||||
@ -542,6 +577,7 @@ common/views/components/poll-editor.vue:
|
||||
day: "S"
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "Send a reaction"
|
||||
input-reaction-placeholder: "or input Emoji"
|
||||
common/views/components/emoji-picker.vue:
|
||||
custom-emoji: "Custom Emoji"
|
||||
people: "People"
|
||||
@ -694,14 +730,30 @@ common/views/components/user-list-editor.vue:
|
||||
deleted: "Deleted successfully"
|
||||
add-user: "Add a user"
|
||||
common/views/components/user-group-editor.vue:
|
||||
users: "Members"
|
||||
rename: "Rename group"
|
||||
delete: "Delete group"
|
||||
transfer: "transfer group"
|
||||
transfer-are-you-sure: "Are you sure you want to add @$2 to the group $1?"
|
||||
transferred: "Group transferred"
|
||||
remove-user: "Remove a user from this group"
|
||||
delete-are-you-sure: "Are you sure to delete group \"$1\"?"
|
||||
deleted: "Deleted"
|
||||
invite: "Invite"
|
||||
invited: "The invitation was successfully sent"
|
||||
common/views/components/user-lists.vue:
|
||||
user-lists: "Lists"
|
||||
create-list: "Create a list"
|
||||
list-name: "List name"
|
||||
common/views/components/user-groups.vue:
|
||||
user-groups: "Groups"
|
||||
create-group: "Create a group"
|
||||
group-name: "Group name"
|
||||
owned-groups: "My groups"
|
||||
joined-groups: "Membership in groups"
|
||||
invites: "Invite"
|
||||
accept-invite: "Join"
|
||||
reject-invite: "Decline"
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "Checking"
|
||||
no-broadcasts: "No announcements"
|
||||
@ -765,6 +817,8 @@ common/views/pages/follow.vue:
|
||||
follow-request: "Follow request"
|
||||
common/views/pages/follow-requests.vue:
|
||||
received-follow-requests: "Follow requests"
|
||||
accept: "Accept"
|
||||
reject: "Reject"
|
||||
desktop:
|
||||
banner-crop-title: "Crop the part that appears as a banner"
|
||||
banner: "Banner"
|
||||
@ -781,7 +835,7 @@ desktop/views/components/activity.chart.vue:
|
||||
total: "Black ... Total"
|
||||
notes: "Blue ... Notes"
|
||||
replies: "Red ... Replies"
|
||||
renotes: "Green ... Repost"
|
||||
renotes: "Green ... Renotes"
|
||||
desktop/views/components/activity.vue:
|
||||
title: "Activity"
|
||||
toggle: "Toggle views"
|
||||
@ -878,7 +932,7 @@ desktop/views/components/note-detail.vue:
|
||||
private: "Post is private"
|
||||
deleted: "Post has been removed"
|
||||
location: "Location"
|
||||
renote: "Repost"
|
||||
renote: "Renote"
|
||||
add-reaction: "Add a reaction"
|
||||
undo-reaction: "Reverse reaction"
|
||||
desktop/views/components/note.vue:
|
||||
@ -895,34 +949,12 @@ desktop/views/components/notes.vue:
|
||||
desktop/views/components/notifications.vue:
|
||||
empty: "No notifications!"
|
||||
desktop/views/components/post-form.vue:
|
||||
add-visible-user: "+Add a user"
|
||||
attach-location-information: "Attach location information"
|
||||
hide-contents: "Hide contents"
|
||||
reply-placeholder: "Reply to this post..."
|
||||
quote-placeholder: "Quote this Post..."
|
||||
submit: "Post"
|
||||
reply: "Reply"
|
||||
renote: "Repost"
|
||||
posted: "Posted!"
|
||||
replied: "Replied!"
|
||||
reposted: "Reposted!"
|
||||
reposted: "Renoted!"
|
||||
note-failed: "Failed to post"
|
||||
reply-failed: "Failed to reply"
|
||||
renote-failed: "Failed to Renote"
|
||||
posting: "Posting"
|
||||
attach-media-from-local: "Attach media from your device"
|
||||
attach-media-from-drive: "Attach media from your Drive"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "Create a poll"
|
||||
text-remain: "{} characters remaining"
|
||||
recent-tags: "Recent"
|
||||
local-only-message: "This post will only be published locally"
|
||||
click-to-tagging: "Click to tagging"
|
||||
visibility: "Visibility"
|
||||
geolocation-alert: "Your device does not provide location services."
|
||||
error: "Error"
|
||||
enter-username: "Please enter a username..."
|
||||
annotations: "Annotations for the post (optional)"
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "New Post"
|
||||
reply: "Reply"
|
||||
@ -933,13 +965,13 @@ desktop/views/components/progress-dialog.vue:
|
||||
desktop/views/components/renote-form.vue:
|
||||
quote: "Quote..."
|
||||
cancel: "Cancel"
|
||||
renote: "Repost"
|
||||
renote: "Renote"
|
||||
renote-home: "Renote (Home)"
|
||||
reposting: "Renoting..."
|
||||
success: "Reposted!"
|
||||
failure: "Failed to Repost"
|
||||
success: "Renoted!"
|
||||
failure: "Failed to Renote"
|
||||
desktop/views/components/renote-form-window.vue:
|
||||
title: "Do you want to Renote it?"
|
||||
title: "Do you want to renote it?"
|
||||
desktop/views/pages/user-following-or-followers.vue:
|
||||
following: "{user}'s following"
|
||||
followers: "{user}'s follower"
|
||||
@ -1036,6 +1068,7 @@ desktop/views/components/ui.header.vue:
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "Your profile"
|
||||
lists: "Lists"
|
||||
groups: "Groups"
|
||||
follow-requests: "Follow requests"
|
||||
admin: "Admin"
|
||||
desktop/views/components/ui.header.nav.vue:
|
||||
@ -1082,6 +1115,32 @@ admin/views/dashboard.vue:
|
||||
admin/views/queue.vue:
|
||||
title: "Queue"
|
||||
remove-all-jobs: "Clear all queued jobs"
|
||||
jobs: "Jobs"
|
||||
queue: "Queue"
|
||||
domains:
|
||||
deliver: "Delivers"
|
||||
inbox: "Received"
|
||||
db: "Database"
|
||||
objectStorage: "Object Storage"
|
||||
state: "Sort"
|
||||
states:
|
||||
active: "Running"
|
||||
delayed: "Scheduled"
|
||||
waiting: "Queued"
|
||||
result-is-truncated: "Result is truncated"
|
||||
other-queues: "Other queues"
|
||||
admin/views/logs.vue:
|
||||
logs: "Logs"
|
||||
domain: "Domain"
|
||||
level: "Level"
|
||||
levels:
|
||||
all: "All"
|
||||
info: "Information"
|
||||
success: "Success"
|
||||
warning: "Warning"
|
||||
error: "Error"
|
||||
debug: "Debug"
|
||||
delete-all: "Remove All"
|
||||
admin/views/abuse.vue:
|
||||
title: "Abuse"
|
||||
target: "Target"
|
||||
@ -1106,9 +1165,21 @@ admin/views/instance.vue:
|
||||
maintainer-name: "Administrator name"
|
||||
maintainer-email: "Contact Administrator"
|
||||
advanced-config: "Other settings"
|
||||
note-and-tl: "Notes and timelines"
|
||||
drive-config: "Drive settings"
|
||||
use-object-storage: "Use Object Storage"
|
||||
object-storage-base-url: "URL"
|
||||
object-storage-bucket: "Bucket Name"
|
||||
object-storage-prefix: "Prefix"
|
||||
object-storage-endpoint: "Endpoint"
|
||||
object-storage-region: "Region"
|
||||
object-storage-port: "Port"
|
||||
object-storage-access-key: "Access Key"
|
||||
object-storage-secret-key: "Secret Key"
|
||||
object-storage-use-ssl: "Use SSL"
|
||||
object-storage-s3-info: "If you are going to use Amazon S3 as Object Storage, Please refer {0} to configure 'Endpoint' and 'Region'."
|
||||
object-storage-s3-info-here: "here"
|
||||
object-storage-gcs-info: "If you are going to use Google Cloud Storage as Object Storage, Set the 'Endpoint' as storage.googleapis.com, and keep the 'Region' is blank."
|
||||
cache-remote-files: "Cache remote files"
|
||||
cache-remote-files-desc: "Without this parameter, all remote files are linked to their host server directly. This will be an effective solution to save your server storage, however make remote files invisible to users who set direct-link disabled, since no thumbnail will be generated, increase traffic. It is recommended that this parameter set enabled."
|
||||
local-drive-capacity-mb: "Volume of Drive per user"
|
||||
@ -1116,8 +1187,14 @@ admin/views/instance.vue:
|
||||
mb: "In megabytes"
|
||||
recaptcha-config: "the reCAPTCHA settings"
|
||||
recaptcha-info: "reCAPTCHA token is required. Please get it on https://www.google.com/recaptcha/intro/"
|
||||
recaptcha-info2: "v3 is not supported. Please use v2."
|
||||
enable-recaptcha: "enable reCAPTCHA"
|
||||
recaptcha-site-key: "Site key"
|
||||
recaptcha-secret-key: "Secret Key"
|
||||
recaptcha-preview: "Preview"
|
||||
hidden-tags: "Hidden hashtags"
|
||||
hidden-tags-info: "List up the hashtags delimited by line breaks that you want exclude from statistics."
|
||||
external-service-integration-config: "Connect an external service"
|
||||
twitter-integration-config: "Settings of connecting to Twitter"
|
||||
twitter-integration-info: "The callback URL is set on {url}."
|
||||
enable-twitter-integration: "Enable connection to Twitter"
|
||||
@ -1148,7 +1225,8 @@ admin/views/instance.vue:
|
||||
invite: "Invite"
|
||||
save: "Save"
|
||||
saved: "Saved"
|
||||
pinned-users: "Higlighted user"
|
||||
pinned-users: "Pinned user"
|
||||
pinned-users-info: "List up the users delimited by line breaks that you want to show as 'Pinned Users'."
|
||||
email-config: "Email server settings"
|
||||
email-config-info: "Used to confirm email and password reset etc."
|
||||
enable-email: "Enable email delivery"
|
||||
@ -1214,6 +1292,9 @@ admin/views/drive.vue:
|
||||
unmark-as-sensitive: "Unmark as 'sensitive'"
|
||||
marked-as-sensitive: "Set a sensitive content notice"
|
||||
unmarked-as-sensitive: "Remove the sensitive content notice"
|
||||
clean-remote-files: "Clear the remote files cache"
|
||||
clean-remote-files-are-you-sure: "Are you sure you want to remove all cached files from remote?"
|
||||
clean-up: "Clean up"
|
||||
admin/views/users.vue:
|
||||
operation: "Operations"
|
||||
username-or-userid: "Username or user ID"
|
||||
@ -1234,6 +1315,8 @@ admin/views/users.vue:
|
||||
unsilence-confirm: "Are you certain that you want to stop silencing this user?"
|
||||
update-remote-user: "Update information about remote user"
|
||||
remote-user-updated: "The information regarding the remote user has been updated."
|
||||
delete-all-files: "Delete all files"
|
||||
delete-all-files-confirm: "Are you sure that you want to delete all files?"
|
||||
users:
|
||||
title: "Users"
|
||||
sort:
|
||||
@ -1309,6 +1392,7 @@ admin/views/federation.vue:
|
||||
latest-request-received-at: "Last request received at"
|
||||
remove-all-following: "Withold all followers"
|
||||
remove-all-following-info: "Unfollow all accounts from {host}. Please run this if the instance no longer exists."
|
||||
delete-all-files: "Remove all files"
|
||||
block: "Block"
|
||||
marked-as-closed: "Marked as closed"
|
||||
lookup: "Look up"
|
||||
@ -1356,6 +1440,8 @@ admin/views/federation.vue:
|
||||
hour: "Hourly"
|
||||
day: "Daily"
|
||||
blocked-hosts: "Blocking"
|
||||
blocked-hosts-info: "List up the hosts delimited by line breaks that you want to block."
|
||||
save: "Save"
|
||||
desktop/views/pages/welcome.vue:
|
||||
about: "More details..."
|
||||
timeline: "Timeline"
|
||||
@ -1487,17 +1573,6 @@ mobile/views/components/note-sub.vue:
|
||||
cat: "cat"
|
||||
mobile/views/components/notifications.vue:
|
||||
empty: "No notifications"
|
||||
mobile/views/components/post-form.vue:
|
||||
add-visible-user: "Add a user"
|
||||
submit: "Post"
|
||||
reply: "Reply"
|
||||
renote: "Renote"
|
||||
quote-placeholder: "Quote this post... (optional)"
|
||||
reply-placeholder: "Reply to this note..."
|
||||
cw-placeholder: "Comments for the post (optional)"
|
||||
geolocation-alert: "Your device does not provide location services."
|
||||
error: "Error"
|
||||
username-prompt: "Enter user name"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
private: "This post is private"
|
||||
deleted: "This post has been deleted"
|
||||
@ -1512,6 +1587,7 @@ mobile/views/components/ui.nav.vue:
|
||||
follow-requests: "Follow requests"
|
||||
search: "Search"
|
||||
user-lists: "Lists"
|
||||
user-groups: "Groups"
|
||||
widgets: "Widgets"
|
||||
game: "Games"
|
||||
admin: "Admin"
|
||||
@ -1654,9 +1730,16 @@ pages:
|
||||
view-source: "View Source"
|
||||
view-page: "View page"
|
||||
like: "Like"
|
||||
unlike: "Unlike"
|
||||
liked-pages: "Favorite pages"
|
||||
my-pages: "My pages"
|
||||
inspector: "Inspector"
|
||||
content: "Page block"
|
||||
variables: "Variables"
|
||||
variables-info: "You can make your page more dynamic by using variables. If you write down <b>{ variable name }</b> in the text, you can embed the value of the variable there. For example, if the source text is <b>Hello { thing } world!</b> and the value of variable 'thing' is <b> ai </b>, that text becomes to <b>Hello ai world!</b>."
|
||||
variables-info2: "Because the evaluation(=calculating) of variables are performed from top to bottom, the variable cannot refer another variable which exists on later line. For example, when defining three variables <b>A</b>, <b>B</b> and <b>C</b>, variable <b>C</b> <i>can</i> refer the variable <b>A</b> and <b>B</b> in its expression, but variable <b>A</b> <i>cannot</i> refer the variable <b>B</b> or <b>C</b> in its expression."
|
||||
variables-info3: "If you want to get some input from the user, place a 'User Input' block on the page and set the variable name as which you want to store that input in 'variable name' (variables are created automatically). You can use that variable to perform actions in response to user's input."
|
||||
variables-info4: "Function allows make your processing logic as group in a reusable way. To create a function, create a variable of type 'Function'. A function can have a slot (Argument) whose value is available as a variable in the function. There are also functions that take functions as arguments in the AiScript standard (called the higher-order function.). In addition to the predefined functions, you can also set them in the slots of such higher-order functions on the fly."
|
||||
more-details: "Description"
|
||||
title: "Title"
|
||||
url: "Page URL"
|
||||
@ -1754,6 +1837,7 @@ pages:
|
||||
strReverse: "Flip text"
|
||||
_strReverse:
|
||||
arg1: "Text"
|
||||
join: "Text Concatenation"
|
||||
_join:
|
||||
arg1: "Lists"
|
||||
arg2: "Separator"
|
||||
@ -1773,7 +1857,8 @@ pages:
|
||||
_divide:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
_remind:
|
||||
mod: "÷ Remaindering"
|
||||
_mod:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
eq: "A and B are equal"
|
||||
@ -1836,18 +1921,23 @@ pages:
|
||||
dailyRandomPick: "Choose at random from the list (Daily for each user)"
|
||||
_dailyRandomPick:
|
||||
arg1: "Lists"
|
||||
seedRandom: "Random (Seed)"
|
||||
_seedRandom:
|
||||
arg1: "Seed"
|
||||
arg2: "Probability"
|
||||
seedRannum: "Random number (Seed)"
|
||||
_seedRannum:
|
||||
arg1: "Seed"
|
||||
arg2: "Minimum"
|
||||
arg3: "Maximum"
|
||||
seedRandomPick: "Randomly selected from list (Seed)"
|
||||
_seedRandomPick:
|
||||
arg1: "Seed"
|
||||
arg2: "Lists"
|
||||
DRPWPM: "Randomly selected from weighted list (Daily updated per user)"
|
||||
_DRPWPM:
|
||||
arg1: "List of text"
|
||||
pick: "Select from list"
|
||||
_pick:
|
||||
arg1: "Lists"
|
||||
arg2: "Position"
|
||||
@ -1865,8 +1955,13 @@ pages:
|
||||
fn: "Function"
|
||||
_fn:
|
||||
slots: "Slots"
|
||||
slots-info: "Please delimit each slot with a line break"
|
||||
arg1: "Output"
|
||||
for: "Repeat"
|
||||
_for:
|
||||
arg1: "Count"
|
||||
arg2: "Action"
|
||||
typeError: "Slot {slot} accepts \"{expect}\" type, but It actually contains \"{actual}\" type!"
|
||||
thereIsEmptySlot: "Slot {slot} is empty!"
|
||||
types:
|
||||
string: "Text"
|
||||
|
@ -80,6 +80,11 @@ common:
|
||||
"read:notifications": "Ver notificaciones"
|
||||
"read:reactions": "Ver reacciones"
|
||||
"write:votes": "Vota"
|
||||
post-form:
|
||||
reply: "Responder"
|
||||
renote: "Volver a publicar"
|
||||
enter-username: "Ingresar nombre de usuario"
|
||||
username-prompt: "Ingresar nombre de usuario"
|
||||
weekday-short:
|
||||
sunday: "domingo"
|
||||
monday: "lunes"
|
||||
@ -202,6 +207,7 @@ common:
|
||||
my-token-regenerated: "Tu token se ha regenerado vas a ser desconectado."
|
||||
hide-password: "Ocultar contraseña"
|
||||
show-password: "Mostrar contraseña"
|
||||
enter-username: "Ingresar nombre de usuario"
|
||||
do-not-use-in-production: "Esto está en desarrollo, no usarlo para producción."
|
||||
user-suspended: "Este usuario ha sido suspendido"
|
||||
is-remote-user: "La información sobre este usuario puede no estar completa"
|
||||
@ -766,7 +772,7 @@ desktop/views/components/note-detail.vue:
|
||||
add-reaction: "Agregar una reacción"
|
||||
desktop/views/components/note.vue:
|
||||
reply: "Responder"
|
||||
renote: "Republicar"
|
||||
renote: "Volver a publicar"
|
||||
add-reaction: "Reacción"
|
||||
detail: "Detalles"
|
||||
private: "Esta publicación es privada"
|
||||
@ -777,32 +783,12 @@ desktop/views/components/notes.vue:
|
||||
desktop/views/components/notifications.vue:
|
||||
empty: "No hay notificaciones"
|
||||
desktop/views/components/post-form.vue:
|
||||
add-visible-user: "+Agregar usuario"
|
||||
attach-location-information: "Agregar localización"
|
||||
hide-contents: "Esconder contenidos"
|
||||
reply-placeholder: "Responder a esta nota..."
|
||||
quote-placeholder: "Citar esta nota..."
|
||||
submit: "Publicar"
|
||||
reply: "Responder"
|
||||
renote: "Republicar"
|
||||
posted: "¡Publicado!"
|
||||
replied: "¡Respondido!"
|
||||
reposted: "¡Republicado!"
|
||||
note-failed: "Error al publicar nota"
|
||||
reply-failed: "Error al responder"
|
||||
renote-failed: "Error al republicar"
|
||||
posting: "Publicando"
|
||||
attach-media-from-local: "Agregar medios de tu dispositivo"
|
||||
attach-media-from-drive: "Adjunta multimedia desde tu Disco"
|
||||
create-poll: "Crea una encuesta"
|
||||
text-remain: "quedan {} caracteres"
|
||||
recent-tags: "Reciente"
|
||||
click-to-tagging: "Click para etiquetar"
|
||||
visibility: "Visibilidad"
|
||||
geolocation-alert: "Tu dispositivo no tiene soporte de geolocalización."
|
||||
error: "Error"
|
||||
enter-username: "Por favor escribe un nombre de usuario..."
|
||||
annotations: "Anotaciones a la publicación (opcional)"
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "Nota nueva"
|
||||
reply: "Responder"
|
||||
@ -921,6 +907,9 @@ admin/views/dashboard.vue:
|
||||
admin/views/queue.vue:
|
||||
title: "Cola"
|
||||
remove-all-jobs: "Limpiar todos los trabajos pendientes"
|
||||
queue: "Cola"
|
||||
admin/views/logs.vue:
|
||||
logs: "Registros"
|
||||
admin/views/abuse.vue:
|
||||
title: "Abuso"
|
||||
target: "Destinatario"
|
||||
@ -1000,6 +989,7 @@ admin/views/federation.vue:
|
||||
hour: "Por hora"
|
||||
day: "Por día"
|
||||
blocked-hosts: "Bloquear"
|
||||
save: "Guardar"
|
||||
desktop/views/pages/selectdrive.vue:
|
||||
cancel: "Cancelar"
|
||||
desktop/views/pages/user-list.users.vue:
|
||||
@ -1052,11 +1042,6 @@ mobile/views/components/note-detail.vue:
|
||||
location: "Localización"
|
||||
mobile/views/components/notifications.vue:
|
||||
empty: "No hay notificaciones"
|
||||
mobile/views/components/post-form.vue:
|
||||
reply: "Responder"
|
||||
renote: "Republicar"
|
||||
reply-placeholder: "Responder a esta nota..."
|
||||
geolocation-alert: "Tu dispositivo no tiene soporte de geolocalización."
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
private: "Esta publicación es privada"
|
||||
deleted: "Esta publicación ha sido removida"
|
||||
|
@ -12,7 +12,7 @@ common:
|
||||
rich-contents: "Notes"
|
||||
rich-contents-desc: "Partagez vos idées, les événements et les sujets qui vous tiennent à cœur ainsi que tout autre chose que vous souhaitez partager avec les autres. Si vous le désirez, vous pouvez décorer vos messages en utilisant une syntaxe différente ou en y joignant des sondages et des fichiers, tels que les photos ou les vidéos que vous aimez."
|
||||
reaction: "Réactions"
|
||||
reaction-desc: "Une manière simple d'exprimer vos émotions. Misskey peut attacher diverses réactions aux publications des autres utilisateurs. Si vous essayez les réactions sur Misskey, vous ne pourrez plus retourner sur une autre plateforme de réseaux sociaux n'offrant que des « J'aime »."
|
||||
reaction-desc: "Une manière simple d'exprimer vos émotions. Misskey peut attacher diverses réactions aux publications des autres utilisateur·rice·s. Si vous essayez les réactions sur Misskey, vous ne pourrez plus retourner sur une autre plateforme de réseaux sociaux n'offrant que des « J'aime »."
|
||||
ui: "Interface"
|
||||
ui-desc: "Aucune interface graphique ne peut plaire à tout le monde. Par conséquent, Misskey possède une interface utilisateur hautement personnalisable selon vos goûts. Vous pouvez rendre votre page d'accueil originale en modifiant la mise en page de votre fil et en déplaçant les widgets que vous pouvez facilement ajuster pour vous approprier cet espace."
|
||||
drive: "Drive"
|
||||
@ -78,7 +78,10 @@ common:
|
||||
"write:drive": "Écrire sur le Drive"
|
||||
"read:favorites": "Afficher les favoris"
|
||||
"write:favorites": "Écrire des favoris"
|
||||
"read:following": "Voir les informations de l'abonné"
|
||||
"read:messaging": "Lire les conversations"
|
||||
"write:messaging": "Utiliser la messagerie"
|
||||
"read:mutes": "Voir les comptes masqués"
|
||||
"write:notes": "Créer ou supprimer des publications"
|
||||
"read:notifications": "Afficher les notifications"
|
||||
"write:notifications": "Gérer vos notifications"
|
||||
@ -86,8 +89,34 @@ common:
|
||||
"write:reactions": "Gérer vos réactions"
|
||||
"write:votes": "Vote"
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "Les utilisateurs suivants afficheront leurs publications sur votre fil."
|
||||
explore: "Trouver des utilisateurs"
|
||||
follow-users-to-make-your-timeline: "Les utilisateur·rice·s suivant·e·s afficheront leurs publications sur votre fil."
|
||||
explore: "Trouver des utilisateur·rice·s"
|
||||
post-form:
|
||||
attach-location-information: "Joindre des informations de localisation"
|
||||
hide-contents: "Masquer les contenus"
|
||||
reply-placeholder: "Répondre à cette note …"
|
||||
quote-placeholder: "Citer cette note …"
|
||||
option-quote-placeholder: "Citer ce billet ... (Facultatif)"
|
||||
quote-attached: "Cité"
|
||||
submit: "Publication"
|
||||
reply: "Répondre"
|
||||
renote: "Republier"
|
||||
posting: "Publication …"
|
||||
attach-media-from-local: "Joindre un média depuis votre appareil"
|
||||
attach-media-from-drive: "Joindre un média depuis votre Drive"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "Créer un sondage"
|
||||
text-remain: "{} caractères restants"
|
||||
recent-tags: "Récent"
|
||||
local-only-message: "Ce message sera publié uniquement sur le fil local"
|
||||
click-to-tagging: "Cliquer pour taguer"
|
||||
visibility: "Visibilité"
|
||||
geolocation-alert: "Votre appareil ne prend pas en charge les services de localisation"
|
||||
error: "Erreur"
|
||||
enter-username: "Saisir un nom d'utilisateur"
|
||||
add-visible-user: "Ajouter un utilisateur"
|
||||
cw-placeholder: "Commenter le contenu (optionnel)"
|
||||
username-prompt: "Saisir un nom d'utilisateur"
|
||||
weekday-short:
|
||||
sunday: "D"
|
||||
monday: "L"
|
||||
@ -119,13 +148,13 @@ common:
|
||||
public: "Public"
|
||||
home: "Principal"
|
||||
home-desc: "Publier sur le fil principal uniquement"
|
||||
followers: "Abonnés"
|
||||
followers-desc: "Publier à vos abonnés uniquement"
|
||||
followers: "Abonné·e·s"
|
||||
followers-desc: "Publier à vos abonné·e·s uniquement"
|
||||
specified: "Direct"
|
||||
specified-desc: "Publier uniquement aux utilisateurs mentionnés"
|
||||
specified-desc: "Publier uniquement aux utilisateur·rice·s mentionné·e·s"
|
||||
local-public: "Local (Public)"
|
||||
local-home: "Accueil (local uniquement)"
|
||||
local-followers: "Local (Abonnés)"
|
||||
local-followers: "Abonné·e·s (Local uniquement)"
|
||||
note-placeholders:
|
||||
a: "Que faites-vous maintenant ?"
|
||||
b: "Quoi de neuf ?"
|
||||
@ -155,6 +184,7 @@ common:
|
||||
web-search-engine: "Moteur de recherche Web"
|
||||
web-search-engine-desc: "Exemple : https://www.google.com/?#q={{query}}"
|
||||
keep-cw: "Maintenir l'avertissement de contenu"
|
||||
keep-cw-desc: "Lorsque vous répondez à un message, le même avertissement de contenu est reprit par défaut dans la réponse, le même que celui qui a été défini dans le message original."
|
||||
i-like-sushi: "Je préfère les sushis plutôt que le pudding"
|
||||
show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi"
|
||||
use-avatar-reversi-stones: "Utiliser l’avatar comme pion dans Reversi"
|
||||
@ -197,9 +227,11 @@ common:
|
||||
delete-wallpaper: "Supprimer le fond d'écran"
|
||||
post-form-on-timeline: "Afficher le champs de saisie en haut du fil"
|
||||
show-clock-on-header: "Afficher l'horloge sur le coté supérieur droit"
|
||||
show-reply-target: "Afficher les réponses"
|
||||
timeline: "Fil d’actualité"
|
||||
show-my-renotes: "Afficher mes republications dans le fil"
|
||||
show-renoted-my-notes: "Afficher les partages de mes propres notes sur le fil"
|
||||
show-local-renotes: "Afficher les partages locaux sur les fils"
|
||||
remain-deleted-note: "Continuer à afficher les notes supprimées"
|
||||
sound: "Son"
|
||||
enable-sounds: "Activer les sons"
|
||||
@ -282,7 +314,7 @@ common:
|
||||
version: "Version"
|
||||
broadcast: "Diffusion"
|
||||
notifications: "Notifications"
|
||||
users: "Utilisateurs recommandés"
|
||||
users: "Utilisateur·rice·s recommandé·e·s"
|
||||
polls: "Sondages"
|
||||
post-form: "Champs de publication"
|
||||
server: "Infos sur le serveur"
|
||||
@ -309,13 +341,14 @@ auth/views/index.vue:
|
||||
error: "La session n’existe pas."
|
||||
sign-in: "Veuillez vous connecter"
|
||||
common/views/pages/explore.vue:
|
||||
popular-users: "Utilisateurs populaires"
|
||||
recently-updated-users: "Utilisateurs actifs récemment"
|
||||
pinned-users: "Utilisateur·rice·s épinglé·e·s"
|
||||
popular-users: "Utilisateur·rice·s populaires"
|
||||
recently-updated-users: "Utilisateur·rice·s actif·ve·s récemment"
|
||||
recently-registered-users: "Les nouveaux inscrits"
|
||||
popular-tags: "Mots-clés populaires"
|
||||
federated: "Du Fédiverse"
|
||||
explore: "Explorer {host}"
|
||||
users-info: "Actuellement, {users} utilisateurs se sont inscrit ici"
|
||||
users-info: "Actuellement, {users} utilisateur·rice·s se sont inscrit ici"
|
||||
common/views/components/url-preview.vue:
|
||||
enable-player: "Activer la lecture"
|
||||
disable-player: "Fermer le lecteur"
|
||||
@ -438,14 +471,22 @@ common/views/components/messaging.vue:
|
||||
you: "Vous"
|
||||
no-history: "Pas d'historique"
|
||||
user: "Utilisateur·rice·s"
|
||||
group: "Groupe"
|
||||
start-with-user: "Initier une discussion avec un·e utilisateur·rice"
|
||||
start-with-group: "Démarrer un groupe et converser"
|
||||
select-group: "Sélectionner un groupe"
|
||||
common/views/components/messaging-room.vue:
|
||||
not-talked-user: "Vous n'avez pas encore discuté avec cet·te utilisateur·rice"
|
||||
not-talked-group: "Il n y a aucune conversation dans ce groupe"
|
||||
no-history: "Aucun historique"
|
||||
new-message: "Nouveau message"
|
||||
only-one-file-attached: "Vous ne pouvez joindre qu'un seul fichier au message"
|
||||
common/views/components/messaging-room.form.vue:
|
||||
input-message-here: "Tapez ici votre message"
|
||||
send: "Envoyer"
|
||||
attach-from-local: "Joindre un fichier depuis votre ordinateur"
|
||||
attach-from-drive: "Joindre un fichier depuis votre Drive"
|
||||
only-one-file-attached: "Vous ne pouvez joindre qu'un seul fichier au message"
|
||||
common/views/components/messaging-room.message.vue:
|
||||
is-read: "Lu"
|
||||
deleted: "Ce message a été supprimé"
|
||||
@ -524,6 +565,7 @@ common/views/components/poll-editor.vue:
|
||||
day: "D"
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "Choisissez votre réaction"
|
||||
input-reaction-placeholder: "ou insérez un émoji"
|
||||
common/views/components/emoji-picker.vue:
|
||||
custom-emoji: "Émoji personnalisé"
|
||||
people: "Personnes"
|
||||
@ -565,6 +607,7 @@ common/views/components/signup.vue:
|
||||
password-matched: "OK"
|
||||
password-not-matched: "Les mots de passe ne correspondent pas."
|
||||
recaptcha: "Vérifier"
|
||||
agree-to: "Accepter {0}."
|
||||
tos: "Conditions d'utilisation"
|
||||
create: "Créer un compte"
|
||||
some-error: "La création du compte a échoué. Veuillez réessayer."
|
||||
@ -610,13 +653,13 @@ common/views/components/visibility-chooser.vue:
|
||||
followers: "Abonné·e·s"
|
||||
followers-desc: "Publier à vos abonné·e·s uniquement"
|
||||
specified: "Direct"
|
||||
specified-desc: "Publier uniquement aux utilisateurs mentionnés"
|
||||
specified-desc: "Publier uniquement aux utilisateur·rice·s mentionné·e·s"
|
||||
local-public: "Local (Public)"
|
||||
local-public-desc: "Ne pas publier pour les distants"
|
||||
local-home: "Accueil (local uniquement)"
|
||||
local-followers: "Local (Abonnés)"
|
||||
local-followers: "Abonné·e·s (Local uniquement)"
|
||||
common/views/components/trends.vue:
|
||||
count: "{} utilisateurs mentionnés"
|
||||
count: "{} utilisateur·rice·s mentionné·e·s"
|
||||
empty: "Aucune tendance"
|
||||
common/views/components/language-settings.vue:
|
||||
title: "Langue "
|
||||
@ -675,17 +718,27 @@ common/views/components/user-list-editor.vue:
|
||||
deleted: "Supprimé"
|
||||
add-user: "Ajouter un utilisateur"
|
||||
common/views/components/user-group-editor.vue:
|
||||
users: "Membres"
|
||||
rename: "Renommer le groupe"
|
||||
delete: "Supprimer le groupe"
|
||||
transfer: "Transférer de groupe"
|
||||
transferred: "Groupe transféré"
|
||||
remove-user: "Enlever un utilisateur de ce groupe"
|
||||
deleted: "Supprimé"
|
||||
invite: "Inviter"
|
||||
invited: "Invitation envoyée avec succès"
|
||||
common/views/components/user-lists.vue:
|
||||
user-lists: "Listes"
|
||||
create-list: "Créer une liste"
|
||||
list-name: "Nom de la liste"
|
||||
common/views/components/user-groups.vue:
|
||||
user-groups: "Groupe"
|
||||
create-group: "Créer un groupe"
|
||||
group-name: "Nom du groupe"
|
||||
owned-groups: "Mes groupes"
|
||||
joined-groups: "Membre dans les groupes"
|
||||
invites: "Inviter"
|
||||
accept-invite: "Participer"
|
||||
reject-invite: "Refuser"
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "Récupération"
|
||||
@ -844,7 +897,7 @@ desktop/views/components/media-video.vue:
|
||||
sensitive: "Le contenu est NSFW"
|
||||
click-to-show: "Cliquer pour afficher"
|
||||
desktop/views/components/followers-window.vue:
|
||||
followers: "{} abonné·e·s"
|
||||
followers: "Abonné·e·s de {}"
|
||||
desktop/views/components/followers.vue:
|
||||
empty: "Il semble que vous n’avez pas encore d’abonné·e·s."
|
||||
desktop/views/components/following-window.vue:
|
||||
@ -881,34 +934,12 @@ desktop/views/components/notes.vue:
|
||||
desktop/views/components/notifications.vue:
|
||||
empty: "Aucune de notification !"
|
||||
desktop/views/components/post-form.vue:
|
||||
add-visible-user: "+Ajouter un·e utilisateur·rice"
|
||||
attach-location-information: "Attacher des informations de localisation"
|
||||
hide-contents: "Masquer les contenus"
|
||||
reply-placeholder: "Répondre à cette note …"
|
||||
quote-placeholder: "Citer cette note …"
|
||||
submit: "Publier"
|
||||
reply: "Répondre"
|
||||
renote: "Republier"
|
||||
posted: "Publié !"
|
||||
replied: "Répondu !"
|
||||
reposted: "Reposté !"
|
||||
note-failed: "La note à échoué"
|
||||
reply-failed: "La réponse a échoué"
|
||||
renote-failed: "Échec lors de la republication"
|
||||
posting: "Publication …"
|
||||
attach-media-from-local: "Joindre un média depuis votre appareil"
|
||||
attach-media-from-drive: "Joindre un média depuis votre Drive"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "Créer un sondage"
|
||||
text-remain: "{} caractères restants"
|
||||
recent-tags: "Récent"
|
||||
local-only-message: "Ce message sera publié uniquement sur le fil local"
|
||||
click-to-tagging: "Cliquer pour taguer"
|
||||
visibility: "Visibilité"
|
||||
geolocation-alert: "Votre appareil ne prend pas en charge les services de localisation"
|
||||
error: "Erreur"
|
||||
enter-username: "Saisir un nom d'utilisateur …"
|
||||
annotations: "Commenter le contenu (optionnel)"
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "Nouvelle note"
|
||||
reply: "Répondre"
|
||||
@ -1051,7 +1082,7 @@ admin/views/index.vue:
|
||||
instance: "Instance"
|
||||
emoji: "Émoji"
|
||||
moderators: "Modérateurs"
|
||||
users: "Utilisateurs"
|
||||
users: "Utilisateur·rice·s"
|
||||
federation: "Fédération"
|
||||
announcements: "Annonces"
|
||||
abuse: "Abus"
|
||||
@ -1069,6 +1100,30 @@ admin/views/dashboard.vue:
|
||||
admin/views/queue.vue:
|
||||
title: "File d'attente"
|
||||
remove-all-jobs: "Enlever toutes les tâches en attente"
|
||||
jobs: "Tâches"
|
||||
queue: "File d'attente"
|
||||
domains:
|
||||
deliver: "Délivrées"
|
||||
inbox: "Reçues"
|
||||
db: "Base de données"
|
||||
state: "État"
|
||||
states:
|
||||
active: "en cours"
|
||||
delayed: "Programmé"
|
||||
waiting: "En file d'attente"
|
||||
other-queues: "Autres files d’attente"
|
||||
admin/views/logs.vue:
|
||||
logs: "Journaux"
|
||||
domain: "Domaine"
|
||||
level: "Niveau"
|
||||
levels:
|
||||
all: "Tous"
|
||||
info: "Informations"
|
||||
success: "Succès"
|
||||
warning: "Avertissement"
|
||||
error: "Erreur"
|
||||
debug: "Débogage"
|
||||
delete-all: "Effacer tout"
|
||||
admin/views/abuse.vue:
|
||||
title: "Abus"
|
||||
target: "Cible"
|
||||
@ -1092,20 +1147,30 @@ admin/views/instance.vue:
|
||||
maintainer-name: "Nom de l’administrateur"
|
||||
maintainer-email: "Contact administratif"
|
||||
advanced-config: "Autres réglages"
|
||||
note-and-tl: "Notes et fils"
|
||||
drive-config: "Paramètres du lecteur"
|
||||
object-storage-base-url: "URL"
|
||||
object-storage-prefix: "Préfixe"
|
||||
object-storage-endpoint: "Point de terminaison"
|
||||
object-storage-region: "Région"
|
||||
object-storage-port: "Port"
|
||||
object-storage-access-key: "Clé d'accès"
|
||||
object-storage-secret-key: "Clé secrète"
|
||||
object-storage-use-ssl: "Utiliser SSL"
|
||||
object-storage-s3-info-here: "ici"
|
||||
cache-remote-files: "Mettre en cache des fichiers distants"
|
||||
local-drive-capacity-mb: "Volume du lecteur par utilisateur"
|
||||
remote-drive-capacity-mb: "Volume du lecteur par utilisateur distant"
|
||||
mb: "en mégaoctets"
|
||||
recaptcha-config: "Paramètres de reCAPTCHA"
|
||||
recaptcha-info: "Si activé, un jeton reCAPTCHA est requis. Vous pouvez en obtenir un sur https://www.google.com/recaptcha/intro/"
|
||||
recaptcha-info2: "v3 n'est pas supportée. Veuillez utiliser v2."
|
||||
enable-recaptcha: "Activation de reCAPTCHA"
|
||||
recaptcha-site-key: "Clé du site"
|
||||
recaptcha-secret-key: "Clé secrète"
|
||||
recaptcha-preview: "Prévisualisation"
|
||||
hidden-tags: "Tags cachés"
|
||||
external-service-integration-config: "Services connectés"
|
||||
twitter-integration-config: "Paramètres de connexion à Twitter"
|
||||
twitter-integration-info: "L'URL de callback est {url}."
|
||||
enable-twitter-integration: "Activer la connexion à Twitter"
|
||||
@ -1130,9 +1195,12 @@ admin/views/instance.vue:
|
||||
disable-local-timeline: "Désactiver le fil local"
|
||||
disable-global-timeline: "Désactiver le fil global"
|
||||
disabling-timelines-info: "Même si vous désactivez ces fils, l'administrateur et les modérateurs peuvent continuer à les utiliser."
|
||||
enable-emoji-reaction: "Activer les pictogrammes dans les réactions"
|
||||
use-star-for-reaction-fallback: "Utiliser une étoile si une réaction est inconnue"
|
||||
invite: "Inviter"
|
||||
save: "Sauvegarder"
|
||||
saved: "Enregistré"
|
||||
pinned-users: "Utilisateur·rice épinglé·e"
|
||||
email-config: "Paramètres du serveur de messagerie"
|
||||
email-config-info: "Utilisé pour confirmer votre adresse de courrier électronique et la réinitialisation de votre mot de passe."
|
||||
enable-email: "Activation de la distribution du courrier"
|
||||
@ -1156,7 +1224,7 @@ admin/views/charts.vue:
|
||||
per-hour: "par heure"
|
||||
federation: "Fédération"
|
||||
notes: "Publications"
|
||||
users: "Utilisateurs"
|
||||
users: "Utilisateur·rice·s"
|
||||
drive: "Lecteur"
|
||||
network: "Réseau"
|
||||
charts:
|
||||
@ -1166,8 +1234,8 @@ admin/views/charts.vue:
|
||||
local-notes: "Nombre des publications : augmentation/diminution (Local)"
|
||||
remote-notes: "Nombre de publications : augmentation/diminution (distants)"
|
||||
notes-total: "Total des notes"
|
||||
users: "Nombre d’utilisateurs : augmentation/diminution"
|
||||
users-total: "Nombre total des utilisateurs"
|
||||
users: "Nombre d’utilisateur·rice·s : augmentation/diminution"
|
||||
users-total: "Nombre total des utilisateur·rice·s"
|
||||
active-users: "Utilisateur·rice·s actif·ve·s"
|
||||
drive: "Capacité utilisée comme stockage : augmentation/diminution"
|
||||
drive-total: "Utilisation totale du lecteur"
|
||||
@ -1198,6 +1266,8 @@ admin/views/drive.vue:
|
||||
unmark-as-sensitive: "Ne pas marquer comme sensible"
|
||||
marked-as-sensitive: "Marqué comme sensible"
|
||||
unmarked-as-sensitive: "Marqué comme non sensible"
|
||||
clean-remote-files: "Nettoyer le cache des fichiers distants"
|
||||
clean-up: "Nettoyage"
|
||||
admin/views/users.vue:
|
||||
operation: "Actions"
|
||||
username-or-userid: "Nom d’utilisateur·rice ou ID utilisateur"
|
||||
@ -1217,8 +1287,9 @@ admin/views/users.vue:
|
||||
unmake-silence: "Enlever la sourdine"
|
||||
update-remote-user: "Mettre à jour les informations de l’utilisateur·rice distant·e"
|
||||
remote-user-updated: "Les informations de l’utilisateur·rice distant·e ont étés mis à jour"
|
||||
delete-all-files: "Supprimer tous les fichiers"
|
||||
users:
|
||||
title: "Utilisateurs"
|
||||
title: "Utilisateur·rice·s"
|
||||
sort:
|
||||
title: "Trier par"
|
||||
createdAtAsc: "Date d’inscription (Ascendant)"
|
||||
@ -1291,6 +1362,7 @@ admin/views/federation.vue:
|
||||
latest-request-sent-at: "Dernière requête envoyée"
|
||||
latest-request-received-at: "Dernière requête reçue"
|
||||
remove-all-following-info: "Se désabonner de tous les comptes de {host}. Exécutez cette commande si l'instance n'existe plus."
|
||||
delete-all-files: "Supprimer tous les fichiers"
|
||||
block: "Bloquer"
|
||||
marked-as-closed: "Marquées comme fermées"
|
||||
lookup: "Recherche"
|
||||
@ -1303,7 +1375,7 @@ admin/views/federation.vue:
|
||||
lastCommunicatedAtAsc: "La date et l'heure des interactions plus anciennes"
|
||||
lastCommunicatedAtDesc: "La date et l'heure des nouvelles interactions"
|
||||
notesDesc: "Description des notes"
|
||||
usersAsc: "Peu d'abonnés"
|
||||
usersAsc: "Peu d'abonné·e·s"
|
||||
followingAsc: "Les moins suivies"
|
||||
followingDesc: "Ayant le plus d'abonné·e·s"
|
||||
followersAsc: "Ayant le moins d'abonné·e·s"
|
||||
@ -1318,7 +1390,7 @@ admin/views/federation.vue:
|
||||
charts: "Graphs"
|
||||
chart-srcs:
|
||||
requests: "Requêtes"
|
||||
users: "Nombre d’utilisateurs·trices : augmentation/diminution"
|
||||
users: "Nombre d’utilisateur·trice·s : augmentation/diminution"
|
||||
users-total: "Nombre total des utilisateur·rice·s"
|
||||
notes: "Augmentation/diminution du nombre des notes"
|
||||
notes-total: "Nombre total des notes"
|
||||
@ -1330,6 +1402,7 @@ admin/views/federation.vue:
|
||||
hour: "Par heure"
|
||||
day: "Par jour"
|
||||
blocked-hosts: "En cours blocage"
|
||||
save: "Enregistrer"
|
||||
desktop/views/pages/welcome.vue:
|
||||
about: "à propos"
|
||||
timeline: "Fil d’actualité"
|
||||
@ -1359,7 +1432,7 @@ desktop/views/pages/user-list.users.vue:
|
||||
desktop/views/pages/user/user.followers-you-know.vue:
|
||||
title: "Abonné·e·s que vous connaissez"
|
||||
loading: "Chargement en cours"
|
||||
no-users: "Aucun abonné connu"
|
||||
no-users: "Aucun·e abonné·e connu·e"
|
||||
desktop/views/pages/user/user.friends.vue:
|
||||
title: "Mentions fréquentes"
|
||||
loading: "Chargement en cours"
|
||||
@ -1412,8 +1485,10 @@ mobile/views/components/drive.vue:
|
||||
nothing-in-drive: "Rien"
|
||||
folder-is-empty: "Ce dossier est vide"
|
||||
folder-name: "Nom du dossier"
|
||||
here-is-root: "Actuellement, vous êtes dans la racine et non pas dans un dossier."
|
||||
url-prompt: "URL du fichier que vous souhaitez téléverser"
|
||||
uploading: "Envoi demandé. Le téléversement pourrait prendre un certain temps avant de s'achever."
|
||||
folder-name-cannot-empty: "Le nom du dossier ne peut être laissé vide."
|
||||
mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "Choisissez un fichier"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
@ -1433,7 +1508,7 @@ mobile/views/components/media-video.vue:
|
||||
sensitive: "Le contenu est NSFW"
|
||||
click-to-show: "Cliquer pour afficher"
|
||||
common/views/components/follow-button.vue:
|
||||
following: "Abonné"
|
||||
following: "Abonné·e"
|
||||
follow: " Suivre"
|
||||
request-pending: "Demande en attente"
|
||||
follow-processing: "En cours d’abonnement"
|
||||
@ -1458,17 +1533,6 @@ mobile/views/components/note-sub.vue:
|
||||
cat: "chat"
|
||||
mobile/views/components/notifications.vue:
|
||||
empty: "Aucune de notification !"
|
||||
mobile/views/components/post-form.vue:
|
||||
add-visible-user: "Ajouter un·e utilisateur·rice"
|
||||
submit: "Publier"
|
||||
reply: "Répondre"
|
||||
renote: "Republier"
|
||||
quote-placeholder: "Citer ce billet ... (Facultatif)"
|
||||
reply-placeholder: "Répondre à cette note"
|
||||
cw-placeholder: "Commenter le contenu (optionnel)"
|
||||
geolocation-alert: "Votre appareil ne prend pas en charge les services de localisation"
|
||||
error: "Erreur"
|
||||
username-prompt: "Saisir un nom d'utilisateur"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
private: "cette publication est privée"
|
||||
deleted: "cette publication a été supprimée"
|
||||
@ -1483,6 +1547,7 @@ mobile/views/components/ui.nav.vue:
|
||||
follow-requests: "Demandes d’abonnement"
|
||||
search: "Rechercher"
|
||||
user-lists: "Listes"
|
||||
user-groups: "Groupe"
|
||||
widgets: "Modules"
|
||||
game: "Jeux"
|
||||
admin: "Admin"
|
||||
@ -1498,9 +1563,9 @@ mobile/views/pages/drive.vue:
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "Votre compte est prêt ! 📦"
|
||||
mobile/views/pages/followers.vue:
|
||||
followers-of: "Abonnés de {name}"
|
||||
followers-of: "Abonné·e·s de {name}"
|
||||
mobile/views/pages/following.vue:
|
||||
following-of: "Abonnés de {name}"
|
||||
following-of: "Abonné·e·s de {name}"
|
||||
mobile/views/pages/home.vue:
|
||||
home: "Accueil"
|
||||
local: "Local"
|
||||
@ -1570,7 +1635,7 @@ deck:
|
||||
remove: "Supprimer la colonne"
|
||||
add-column: "Ajouter une colonne"
|
||||
rename: "Renommer"
|
||||
stack-left: "Vers la gauche"
|
||||
stack-left: "Empiler à gauche"
|
||||
pop-right: "Vers la droite"
|
||||
disabled-timeline:
|
||||
title: "Le fil été désactivé"
|
||||
@ -1582,7 +1647,7 @@ deck/deck.user-column.vue:
|
||||
follows-you: "Vous suit"
|
||||
posts: "Notes"
|
||||
following: "Suit"
|
||||
followers: "Abonnés"
|
||||
followers: "Abonné·e·s"
|
||||
images: "Images"
|
||||
activity: "Activité"
|
||||
timeline: "Fil d’actualité"
|
||||
@ -1598,23 +1663,34 @@ dev/views/apps.vue:
|
||||
app-missing: "Aucune application"
|
||||
dev/views/new-app.vue:
|
||||
new-app: "Nouvelle application"
|
||||
new-app-info: "Vous pouvez aussi créer une application avec l'API. (app/create)"
|
||||
create-app: "Création d’une application"
|
||||
app-name: "Nom de l’application"
|
||||
app-name-placeholder: "p. ex. Misskey pour iOS"
|
||||
app-name-desc: "Le nom de votre application"
|
||||
app-overview: "Description courte de l’application"
|
||||
app-overview-placeholder: "p. ex. Misskey pour iOS"
|
||||
app-overview-desc: "Brève description introductive à votre application."
|
||||
callback-url: "L’Url de callback (facultatif)"
|
||||
callback-url-placeholder: "p. ex. https://votre.app.example.com/callback.php"
|
||||
callback-url-desc: "Vous pouvez définir l’URL de redirection lorsque l’utilisateur s’est authentifié via formulaire d’authentification."
|
||||
authority: "Autorisations "
|
||||
authority-desc: "Sont accessibles via l’API, uniquement les fonctionnalités demandées ici."
|
||||
authority-warning: "Vous pouvez le changer même après avoir créé l'application, mais si vous attribuez une nouvelle permission, toutes les clés utilisateur associées seront dès lors invalides."
|
||||
pages:
|
||||
new-page: "Créer une page"
|
||||
edit-page: "Modifier une page"
|
||||
read-page: "Voir la source"
|
||||
page-created: "Page a été créée !"
|
||||
page-updated: "A mis à jour la page"
|
||||
are-you-sure-delete: "Confirmez-vous la suppression de cette page ?"
|
||||
page-deleted: "La page a bien été supprimée."
|
||||
edit-this-page: "Éditer cette page"
|
||||
view-source: "Afficher la source"
|
||||
view-page: "Afficher la page"
|
||||
like: "Bien"
|
||||
liked-pages: "Pages favorites"
|
||||
my-pages: "Mes pages"
|
||||
inspector: "Inspecteur"
|
||||
content: "Bloc de page"
|
||||
variables: "Variables"
|
||||
@ -1626,6 +1702,8 @@ pages:
|
||||
font: "Police de caractères"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
set-eye-catching-image: "Définir une image attirante"
|
||||
remove-eye-catching-image: "Supprimer une image attirante"
|
||||
choose-block: "Ajouter un bloc"
|
||||
select-type: "Choisir un type"
|
||||
enter-variable-name: "Veuillez choisir un nom de variable"
|
||||
@ -1688,9 +1766,11 @@ pages:
|
||||
random: "Aléatoire"
|
||||
value: "Valeur"
|
||||
fn: "Fonction"
|
||||
text: "Actions texte"
|
||||
list: "Listes"
|
||||
blocks:
|
||||
text: "Texte"
|
||||
textList: "Liste de texte"
|
||||
strLen: "Longueur du texte"
|
||||
_strLen:
|
||||
arg1: "Texte"
|
||||
@ -1723,7 +1803,7 @@ pages:
|
||||
_divide:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
_remind:
|
||||
_mod:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
eq: "A et B sont équivalents"
|
||||
@ -1734,34 +1814,63 @@ pages:
|
||||
_notEq:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
and: "A et B"
|
||||
_and:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
or: "A ou B"
|
||||
_or:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
lt: "A est plus petit que B"
|
||||
_lt:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
gt: "A est supérieur à B"
|
||||
_gt:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
ltEq: "A est plus petit ou égal à B"
|
||||
_ltEq:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
gtEq: "A est supérieur ou égal à B"
|
||||
_gtEq:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
_if:
|
||||
arg1: "Si"
|
||||
arg2: "donc"
|
||||
arg3: "sinon"
|
||||
not: "négation"
|
||||
_not:
|
||||
arg1: "négation"
|
||||
random: "Aléatoire"
|
||||
_random:
|
||||
arg1: "Probabilité"
|
||||
rannum: "Nombre aléatoire"
|
||||
_rannum:
|
||||
arg1: "Minimum"
|
||||
arg2: "Maximum"
|
||||
randomPick: "Choisir aléatoirement depuis la liste"
|
||||
_randomPick:
|
||||
arg1: "Listes"
|
||||
_dailyRandom:
|
||||
arg1: "Probabilité"
|
||||
_dailyRannum:
|
||||
arg1: "Minimum"
|
||||
arg2: "Maximum"
|
||||
_dailyRandomPick:
|
||||
arg1: "Listes"
|
||||
_seedRandom:
|
||||
arg2: "Probabilité"
|
||||
_seedRannum:
|
||||
arg2: "Min"
|
||||
arg3: "Max"
|
||||
_seedRandomPick:
|
||||
arg2: "Listes"
|
||||
_DRPWPM:
|
||||
arg1: "Liste de texte"
|
||||
pick: "Sélectionner dans la liste"
|
||||
_pick:
|
||||
arg1: "Listes"
|
||||
@ -1781,9 +1890,16 @@ pages:
|
||||
slots: "Emplacement"
|
||||
arg1: "Sortie"
|
||||
for: "Répéter"
|
||||
_for:
|
||||
arg1: "Compter"
|
||||
arg2: "Action"
|
||||
thereIsEmptySlot: "Slot {slot} est vide !"
|
||||
types:
|
||||
string: "Texte"
|
||||
number: "Numérique"
|
||||
boolean: "Marqueur"
|
||||
array: "Listes"
|
||||
stringArray: "Liste de texte"
|
||||
emptySlot: "Slot vide"
|
||||
enviromentVariables: "Variables d'environnement"
|
||||
pageVariables: "Élément de page"
|
||||
|
@ -101,6 +101,34 @@ common:
|
||||
follow-users-to-make-your-timeline: "ユーザーをフォローすると投稿がタイムラインに表示されます。"
|
||||
explore: "ユーザーを探索する"
|
||||
|
||||
post-form:
|
||||
attach-location-information: "位置情報を添付する"
|
||||
hide-contents: "内容を隠す"
|
||||
reply-placeholder: "この投稿への返信..."
|
||||
quote-placeholder: "この投稿を引用..."
|
||||
option-quote-placeholder: "この投稿を引用... (オプション)"
|
||||
quote-attached: "引用付き"
|
||||
quote-question: "引用として添付しますか?"
|
||||
submit: "投稿"
|
||||
reply: "返信"
|
||||
renote: "Renote"
|
||||
posting: "投稿中"
|
||||
attach-media-from-local: "PCからメディアを添付"
|
||||
attach-media-from-drive: "ドライブからメディアを添付"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "アンケートを作成"
|
||||
text-remain: "残り{}文字"
|
||||
recent-tags: "最近"
|
||||
local-only-message: "この投稿はローカルにのみ公開されます"
|
||||
click-to-tagging: "クリックでタグ付け"
|
||||
visibility: "公開範囲"
|
||||
geolocation-alert: "お使いの端末は位置情報に対応していません"
|
||||
error: "エラー"
|
||||
enter-username: "ユーザー名を入力してください"
|
||||
add-visible-user: "ユーザーを追加"
|
||||
cw-placeholder: "内容への注釈 (オプション)"
|
||||
username-prompt: "ユーザー名を入力してください"
|
||||
|
||||
weekday-short:
|
||||
sunday: "日"
|
||||
monday: "月"
|
||||
@ -591,6 +619,7 @@ common/views/components/poll-editor.vue:
|
||||
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "リアクションを選択"
|
||||
input-reaction-placeholder: "または絵文字を入力"
|
||||
|
||||
common/views/components/emoji-picker.vue:
|
||||
custom-emoji: "カスタム絵文字"
|
||||
@ -762,6 +791,9 @@ common/views/components/user-group-editor.vue:
|
||||
users: "メンバー"
|
||||
rename: "グループ名を変更"
|
||||
delete: "グループを削除"
|
||||
transfer: "グループを譲渡"
|
||||
transfer-are-you-sure: "グループ「$1」を「@$2」さんに譲渡しますか?"
|
||||
transferred: "グループを譲渡しました"
|
||||
remove-user: "このグループから削除"
|
||||
delete-are-you-sure: "グループ「$1」を削除しますか?"
|
||||
deleted: "削除しました"
|
||||
@ -1013,34 +1045,12 @@ desktop/views/components/notifications.vue:
|
||||
empty: "ありません!"
|
||||
|
||||
desktop/views/components/post-form.vue:
|
||||
add-visible-user: "+ユーザーを追加"
|
||||
attach-location-information: "位置情報を添付する"
|
||||
hide-contents: "内容を隠す"
|
||||
reply-placeholder: "この投稿への返信..."
|
||||
quote-placeholder: "この投稿を引用..."
|
||||
submit: "投稿"
|
||||
reply: "返信"
|
||||
renote: "Renote"
|
||||
posted: "投稿しました!"
|
||||
replied: "返信しました!"
|
||||
reposted: "Renoteしました!"
|
||||
note-failed: "投稿に失敗しました"
|
||||
reply-failed: "返信に失敗しました"
|
||||
renote-failed: "Renoteに失敗しました"
|
||||
posting: "投稿中"
|
||||
attach-media-from-local: "PCからメディアを添付"
|
||||
attach-media-from-drive: "ドライブからメディアを添付"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "アンケートを作成"
|
||||
text-remain: "残り{}文字"
|
||||
recent-tags: "最近"
|
||||
local-only-message: "この投稿はローカルにのみ公開されます"
|
||||
click-to-tagging: "クリックでタグ付け"
|
||||
visibility: "公開範囲"
|
||||
geolocation-alert: "お使いの端末は位置情報に対応していません"
|
||||
error: "エラー"
|
||||
enter-username: "ユーザー名を入力してください"
|
||||
annotations: "内容への注釈 (オプション)"
|
||||
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "新規投稿"
|
||||
@ -1216,8 +1226,12 @@ admin/views/index.vue:
|
||||
abuse: "スパム報告"
|
||||
queue: "ジョブキュー"
|
||||
logs: "ログ"
|
||||
db: "データベース"
|
||||
back-to-misskey: "Misskeyに戻る"
|
||||
|
||||
admin/views/db.vue:
|
||||
tables: "テーブル"
|
||||
|
||||
admin/views/dashboard.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
accounts: "アカウント"
|
||||
@ -1230,6 +1244,33 @@ admin/views/dashboard.vue:
|
||||
admin/views/queue.vue:
|
||||
title: "キュー"
|
||||
remove-all-jobs: "すべてのジョブをクリア"
|
||||
jobs: "ジョブ"
|
||||
queue: "キュー"
|
||||
domains:
|
||||
deliver: "配送"
|
||||
inbox: "受信"
|
||||
db: "データベース"
|
||||
objectStorage: "オブジェクトストレージ"
|
||||
state: "状態"
|
||||
states:
|
||||
active: "処理中"
|
||||
delayed: "予約済み"
|
||||
waiting: "順番待ち"
|
||||
result-is-truncated: "結果は省略されています"
|
||||
other-queues: "その他のキュー"
|
||||
|
||||
admin/views/logs.vue:
|
||||
logs: "ログ"
|
||||
domain: "ドメイン"
|
||||
level: "レベル"
|
||||
levels:
|
||||
all: "全て"
|
||||
info: "情報"
|
||||
success: "成功"
|
||||
warning: "警告"
|
||||
error: "エラー"
|
||||
debug: "デバッグ"
|
||||
delete-all: "全て削除"
|
||||
|
||||
admin/views/abuse.vue:
|
||||
title: "スパム報告"
|
||||
@ -1278,6 +1319,7 @@ admin/views/instance.vue:
|
||||
mb: "メガバイト単位"
|
||||
recaptcha-config: "reCAPTCHAの設定"
|
||||
recaptcha-info: "reCAPTCHAを有効にする場合、reCAPTCHAトークンを取得する必要があります。https://www.google.com/recaptcha/intro/ にアクセスしてトークンを取得してください。"
|
||||
recaptcha-info2: "v3は非対応です。v2を使用してください。"
|
||||
enable-recaptcha: "reCAPTCHAを有効にする"
|
||||
recaptcha-site-key: "サイトキー"
|
||||
recaptcha-secret-key: "シークレットキー"
|
||||
@ -1384,6 +1426,9 @@ admin/views/drive.vue:
|
||||
unmark-as-sensitive: "閲覧注意を解除"
|
||||
marked-as-sensitive: "閲覧注意に設定しました"
|
||||
unmarked-as-sensitive: "閲覧注意を解除しました"
|
||||
clean-remote-files: "リモートファイルのキャッシュを削除"
|
||||
clean-remote-files-are-you-sure: "すべてのリモートファイルのキャッシュを削除してもよろしいですか?"
|
||||
clean-up: "クリーンアップ"
|
||||
|
||||
admin/views/users.vue:
|
||||
operation: "操作"
|
||||
@ -1536,6 +1581,7 @@ admin/views/federation.vue:
|
||||
day: "1日ごと"
|
||||
blocked-hosts: "ブロック"
|
||||
blocked-hosts-info: "ブロックしたいホストを改行で区切って記述します。"
|
||||
save: "保存"
|
||||
|
||||
desktop/views/pages/welcome.vue:
|
||||
about: "詳しく..."
|
||||
@ -1698,18 +1744,6 @@ mobile/views/components/note-sub.vue:
|
||||
mobile/views/components/notifications.vue:
|
||||
empty: "ありません!"
|
||||
|
||||
mobile/views/components/post-form.vue:
|
||||
add-visible-user: "ユーザーを追加"
|
||||
submit: "投稿"
|
||||
reply: "返信"
|
||||
renote: "Renote"
|
||||
quote-placeholder: "この投稿を引用... (オプション)"
|
||||
reply-placeholder: "この投稿への返信..."
|
||||
cw-placeholder: "内容への注釈 (オプション)"
|
||||
geolocation-alert: "お使いの端末は位置情報に対応していません"
|
||||
error: "エラー"
|
||||
username-prompt: "ユーザー名を入力してください"
|
||||
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
private: "この投稿は非公開です"
|
||||
deleted: "この投稿は削除されました"
|
||||
@ -2030,8 +2064,8 @@ pages:
|
||||
_divide:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
remind: "÷ 割った余り"
|
||||
_remind:
|
||||
mod: "÷ 割った余り"
|
||||
_mod:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
eq: "AとBが同じ"
|
||||
|
@ -62,6 +62,14 @@ common:
|
||||
favorites: "お気に入り"
|
||||
permissions:
|
||||
"write:votes": "投票するで"
|
||||
post-form:
|
||||
submit: "投稿"
|
||||
reply: "返す"
|
||||
renote: "Renote"
|
||||
error: "エラー"
|
||||
enter-username: "ユーザー名を入力してや"
|
||||
add-visible-user: "ユーザー増やす"
|
||||
username-prompt: "ユーザー名を入力してや"
|
||||
weekday-short:
|
||||
sunday: "日"
|
||||
monday: "月"
|
||||
@ -670,33 +678,12 @@ desktop/views/components/notes.vue:
|
||||
desktop/views/components/notifications.vue:
|
||||
empty: "あらへん!"
|
||||
desktop/views/components/post-form.vue:
|
||||
add-visible-user: "+ユーザー増やす"
|
||||
attach-location-information: "いる場所くっつけるで"
|
||||
hide-contents: "内容を隠す"
|
||||
reply-placeholder: "この投稿への返信..."
|
||||
quote-placeholder: "この投稿を引用..."
|
||||
submit: "投稿"
|
||||
reply: "返信"
|
||||
renote: "Renote"
|
||||
posted: "投稿したで!"
|
||||
replied: "返信したで!"
|
||||
reposted: "Renoteしたで!"
|
||||
note-failed: "投稿に失敗したで"
|
||||
reply-failed: "返信に失敗したで"
|
||||
renote-failed: "Renoteでけへん"
|
||||
posting: "投稿中"
|
||||
attach-media-from-local: "PCからメディア持ってくる"
|
||||
attach-media-from-drive: "ドライブからメディア持ってくる"
|
||||
create-poll: "アンケートを作成"
|
||||
text-remain: "残り{}文字"
|
||||
recent-tags: "最近のタグ"
|
||||
local-only-message: "この投稿はローカルだけ公開されるで"
|
||||
click-to-tagging: "クリックでタグ付け"
|
||||
visibility: "公開範囲"
|
||||
geolocation-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。"
|
||||
error: "エラー"
|
||||
enter-username: "ユーザー名を入力してや"
|
||||
annotations: "もっと教えてな(別にええけど)"
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "新規投稿"
|
||||
reply: "返す"
|
||||
@ -845,6 +832,10 @@ admin/views/dashboard.vue:
|
||||
instances: "インスタンス"
|
||||
this-instance: "ワイのインスタンス"
|
||||
federated: "連合"
|
||||
admin/views/logs.vue:
|
||||
levels:
|
||||
info: "情報"
|
||||
error: "エラー"
|
||||
admin/views/abuse.vue:
|
||||
details: "もっと"
|
||||
remove-report: "削除"
|
||||
@ -991,6 +982,7 @@ admin/views/federation.vue:
|
||||
hour: "1時間ごと"
|
||||
day: "1日ごと"
|
||||
blocked-hosts: "ブロック"
|
||||
save: "保存"
|
||||
desktop/views/pages/welcome.vue:
|
||||
about: "もうちょい……"
|
||||
timeline: "タイムライン"
|
||||
@ -1114,17 +1106,6 @@ mobile/views/components/note-sub.vue:
|
||||
cat: "cat"
|
||||
mobile/views/components/notifications.vue:
|
||||
empty: "あらへん!"
|
||||
mobile/views/components/post-form.vue:
|
||||
add-visible-user: "ユーザー増やす"
|
||||
submit: "投稿"
|
||||
reply: "返す"
|
||||
renote: "Renote"
|
||||
quote-placeholder: "この投稿を持ってくる(オプション)"
|
||||
reply-placeholder: "この投稿への返信..."
|
||||
cw-placeholder: "内容への注釈 (オプション)"
|
||||
geolocation-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。"
|
||||
error: "エラー"
|
||||
username-prompt: "ユーザー名を入力してや"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
private: "この投稿は見せられへんわ"
|
||||
deleted: "この投稿なんか無くなってもうたわ"
|
||||
|
@ -4,7 +4,7 @@ meta:
|
||||
common:
|
||||
misskey: "연합우주의 ⭐"
|
||||
about-title: "연합우주의 ⭐."
|
||||
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에도 전해집니다. 살짝 어떤 행성에서 다른 행성으로 전파를 발신하고 있는 모습을 상상해주세요."
|
||||
@ -20,7 +20,7 @@ common:
|
||||
outro: "이외에도 Misskey에만 있는 기능이 아직도 더 있으니 부디 여러분 자신의 눈으로 확인해보시기 바랍니다. Misskey는 분산형 SNS라서 이 인스턴스가 마음에 들지 않으신다면 다른 인스턴스를 시도해보실 수도 있습니다. 그럼, GLHF!"
|
||||
adblock:
|
||||
detected: "광고 차단기를 해제하십시오"
|
||||
warning: "<strong>Misskey는 광고를 게재하지 않습니다</strong>. 그러나 광고 차단 기능을 사용할 경우 일부 기능을 사용할 수 없게 될 가능성이나 결함이 발생하는 경우가 있습니다."
|
||||
warning: "<strong>Misskey는 광고를 게재하지 않습니다</strong>. 하지만 광고 차단 기능을 사용할 경우 일부 기능을 사용할 수 없거나 문제가 발생할 수 있습니다."
|
||||
application-authorization: "앱 연계"
|
||||
close: "닫기"
|
||||
do-not-copy-paste: "여기에 코드를 입력하거나 붙여넣지 마십시오. 계정이 무단으로 사용될 수 있습니다."
|
||||
@ -42,7 +42,7 @@ common:
|
||||
gotit: "Got it!"
|
||||
notification:
|
||||
file-uploaded: "파일이 업로드되었습니다"
|
||||
message-from: "{}님으로부터 메시지:"
|
||||
message-from: "{}님의 메시지:"
|
||||
reversi-invited: "게임 초대가 있습니다"
|
||||
reversi-invited-by: "{}님으로부터"
|
||||
notified-by: "{}님으로부터"
|
||||
@ -51,7 +51,7 @@ common:
|
||||
time:
|
||||
unknown: "알 수 없는 시간"
|
||||
future: "미래"
|
||||
just_now: "방금"
|
||||
just_now: "방금 전"
|
||||
seconds_ago: "{}초 전"
|
||||
minutes_ago: "{}분 전"
|
||||
hours_ago: "{}시간 전"
|
||||
@ -67,19 +67,19 @@ common:
|
||||
home: "홈"
|
||||
deck: "덱"
|
||||
timeline: "타임라인"
|
||||
explore: "발견"
|
||||
explore: "발견하기"
|
||||
following: "팔로우 중"
|
||||
followers: "팔로워"
|
||||
favorites: "즐겨찾기"
|
||||
permissions:
|
||||
"read:account": "계정 정보 보기"
|
||||
"write:account": "계정 정보 변경"
|
||||
"read:blocks": "차단 보기"
|
||||
"write:blocks": "차단 수정"
|
||||
"read:drive": "드라이브 보기"
|
||||
"write:drive": "드라이브 수정"
|
||||
"read:favorites": "즐겨찾기 보기"
|
||||
"write:favorites": "즐겨찾기 수정"
|
||||
"read:account": "계정의 정보를 볼 수 있습니다."
|
||||
"write:account": "계정의 정보를 변경할 수 있습니다."
|
||||
"read:blocks": "차단 목록을 볼 수 있습니다."
|
||||
"write:blocks": "차단 목록을 조작할 수 있습니다."
|
||||
"read:drive": "드라이브의 파일들을 볼 수 있습니다."
|
||||
"write:drive": "드라이브의 파일들을 조작할 수 있습니다."
|
||||
"read:favorites": "즐겨찾기 목록을 볼 수 있습니다."
|
||||
"write:favorites": "즐겨찾기 목록을 조작할 수 있습니다."
|
||||
"read:following": "팔로우 정보 보기"
|
||||
"write:following": "팔로잉, 팔로우 수정"
|
||||
"read:messaging": "대화 보기"
|
||||
@ -95,6 +95,33 @@ common:
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "사용자를 팔로우하면 글이 타임라인에 표시됩니다."
|
||||
explore: "사용자 탐색"
|
||||
post-form:
|
||||
attach-location-information: "위치 정보를 첨부합니다"
|
||||
hide-contents: "내용 숨기기"
|
||||
reply-placeholder: "이 글에 답글..."
|
||||
quote-placeholder: "이 글을 인용..."
|
||||
option-quote-placeholder: "이 글을 인용... (옵션)"
|
||||
quote-attached: "인용함"
|
||||
quote-question: "인용해서 작성하시겠습니까?"
|
||||
submit: "글쓰기"
|
||||
reply: "답글 달기"
|
||||
renote: "리노트"
|
||||
posting: "게시중"
|
||||
attach-media-from-local: "PC에서 미디어 첨부"
|
||||
attach-media-from-drive: "드라이브에서 미디어 첨부"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "투표 만들기"
|
||||
text-remain: "{}문자 남음"
|
||||
recent-tags: "최근"
|
||||
local-only-message: "이 글은 로컬에만 공개되어 있습니다"
|
||||
click-to-tagging: "클릭하여 태그 넣기"
|
||||
visibility: "공개 범위"
|
||||
geolocation-alert: "사용 중인 장치에서는 위치 정보를 사용할 수 없습니다"
|
||||
error: "오류"
|
||||
enter-username: "사용자명을 입력해주세요"
|
||||
add-visible-user: "사용자 추가"
|
||||
cw-placeholder: "내용에 대한 주석 (옵션)"
|
||||
username-prompt: "사용자명을 입력해주세요"
|
||||
weekday-short:
|
||||
sunday: "일"
|
||||
monday: "월"
|
||||
@ -253,7 +280,7 @@ common:
|
||||
my-token-regenerated: "당신의 토큰이 업데이트되었으므로 로그아웃합니다."
|
||||
hide-password: "비밀번호 숨기기"
|
||||
show-password: "비밀번호 표시"
|
||||
enter-username: "사용자명을 입력하여 주십시오"
|
||||
enter-username: "사용자명을 입력해주세요"
|
||||
do-not-use-in-production: "이것은 개발 빌드입니다. 프로덕션 환경에서 사용하지 마십시오."
|
||||
user-suspended: "이 사용자는 정지된 상태입니다."
|
||||
is-remote-user: "이 사용자 정보는 정확하지 않을 수 있습니다."
|
||||
@ -550,6 +577,7 @@ common/views/components/poll-editor.vue:
|
||||
day: "일"
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "리액션 선택"
|
||||
input-reaction-placeholder: "또는 이모지 입력"
|
||||
common/views/components/emoji-picker.vue:
|
||||
custom-emoji: "커스텀 이모지"
|
||||
people: "사람들"
|
||||
@ -705,6 +733,9 @@ common/views/components/user-group-editor.vue:
|
||||
users: "멤버"
|
||||
rename: "그룹명을 변경"
|
||||
delete: "그룹을 삭제"
|
||||
transfer: "그룹을 양도"
|
||||
transfer-are-you-sure: "그룹 「$1」을 「@$2」 님에게 양도하시겠습니까?"
|
||||
transferred: "그룹을 양도하였습니다"
|
||||
remove-user: "이 그룹에서 삭제"
|
||||
delete-are-you-sure: "그룹 「$1」을 삭제하시겠습니까?"
|
||||
deleted: "삭제하였습니다"
|
||||
@ -918,34 +949,12 @@ desktop/views/components/notes.vue:
|
||||
desktop/views/components/notifications.vue:
|
||||
empty: "비었습니다!"
|
||||
desktop/views/components/post-form.vue:
|
||||
add-visible-user: "+사용자 추가"
|
||||
attach-location-information: "위치정보를 첨부하기"
|
||||
hide-contents: "내용 숨기기"
|
||||
reply-placeholder: "이 글에 답글..."
|
||||
quote-placeholder: "이 글을 인용..."
|
||||
submit: "글쓰기"
|
||||
reply: "답글 달기"
|
||||
renote: "리노트"
|
||||
posted: "게시하였습니다!"
|
||||
replied: "답글을 달았습니다!"
|
||||
reposted: "리노트 하였습니다!"
|
||||
note-failed: "게시에 실패하였습니다"
|
||||
reply-failed: "답글을 달지 못했습니다"
|
||||
renote-failed: "리노트에 실패하였습니다"
|
||||
posting: "게시중"
|
||||
attach-media-from-local: "PC에서 미디어 첨부"
|
||||
attach-media-from-drive: "드라이브에서 미디어 첨부"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "투표 만들기"
|
||||
text-remain: "{}문자 남음"
|
||||
recent-tags: "최근"
|
||||
local-only-message: "이 글은 로컬에만 공개되어 있습니다"
|
||||
click-to-tagging: "클릭하여 태그 넣기"
|
||||
visibility: "공개설정"
|
||||
geolocation-alert: "사용하시는 장치가 위치정보 기능에 대응하지 않습니다"
|
||||
error: "오류"
|
||||
enter-username: "사용자명을 입력해주세요"
|
||||
annotations: "내용 주석 (선택적)"
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "새 글"
|
||||
reply: "답글 달기"
|
||||
@ -1106,6 +1115,32 @@ admin/views/dashboard.vue:
|
||||
admin/views/queue.vue:
|
||||
title: "큐"
|
||||
remove-all-jobs: "모든 작업 제거"
|
||||
jobs: "작업"
|
||||
queue: "큐"
|
||||
domains:
|
||||
deliver: "전송"
|
||||
inbox: "수신"
|
||||
db: "데이터베이스"
|
||||
objectStorage: "오브젝트 스토리지"
|
||||
state: "상태"
|
||||
states:
|
||||
active: "처리중"
|
||||
delayed: "지연됨"
|
||||
waiting: "대기열에 들어감"
|
||||
result-is-truncated: "결과는 생략되었습니다"
|
||||
other-queues: "기타 큐"
|
||||
admin/views/logs.vue:
|
||||
logs: "로그"
|
||||
domain: "도메인"
|
||||
level: "수준"
|
||||
levels:
|
||||
all: "전체"
|
||||
info: "정보"
|
||||
success: "성공"
|
||||
warning: "경고"
|
||||
error: "오류"
|
||||
debug: "디버그"
|
||||
delete-all: "모두 삭제"
|
||||
admin/views/abuse.vue:
|
||||
title: "스팸 신고"
|
||||
target: "대상"
|
||||
@ -1152,6 +1187,7 @@ admin/views/instance.vue:
|
||||
mb: "메가바이트 단위"
|
||||
recaptcha-config: "reCAPCHA 설정"
|
||||
recaptcha-info: "reCAPCHA를 사용하도록 설정하는 경우 reCAPCHA 토큰을 확보해야 합니다. https://www.google.com/recaptcha/intro/ 에 접속하여 토큰을 가져와주십시오."
|
||||
recaptcha-info2: "v3는지원하지 않습니다. v2를 사용하여 주십시오."
|
||||
enable-recaptcha: "reCAPCHA 활성화"
|
||||
recaptcha-site-key: "사이트 키"
|
||||
recaptcha-secret-key: "시크릿 키"
|
||||
@ -1256,6 +1292,9 @@ admin/views/drive.vue:
|
||||
unmark-as-sensitive: "열람주의 해제"
|
||||
marked-as-sensitive: "열람주의로 설정하였습니다"
|
||||
unmarked-as-sensitive: "열람주의를 제거하였습니다"
|
||||
clean-remote-files: "리모트 파일 캐시를 삭제"
|
||||
clean-remote-files-are-you-sure: "정말 모든 리모트 파일의 캐시를 삭제하시겠습니까?"
|
||||
clean-up: "청소"
|
||||
admin/views/users.vue:
|
||||
operation: "작업"
|
||||
username-or-userid: "사용자명 혹은 사용자 ID"
|
||||
@ -1402,6 +1441,7 @@ admin/views/federation.vue:
|
||||
day: "1일마다"
|
||||
blocked-hosts: "차단"
|
||||
blocked-hosts-info: "차단할 호스트를 줄바꿈으로 구분하여 기술합니다."
|
||||
save: "저장"
|
||||
desktop/views/pages/welcome.vue:
|
||||
about: "자세히..."
|
||||
timeline: "타임라인"
|
||||
@ -1533,17 +1573,6 @@ mobile/views/components/note-sub.vue:
|
||||
cat: "cat"
|
||||
mobile/views/components/notifications.vue:
|
||||
empty: "없습니다!"
|
||||
mobile/views/components/post-form.vue:
|
||||
add-visible-user: "사용자 추가"
|
||||
submit: "글쓰기"
|
||||
reply: "답글 달기"
|
||||
renote: "리노트"
|
||||
quote-placeholder: "이 글을 인용... (선택적)"
|
||||
reply-placeholder: "이 글에 답글..."
|
||||
cw-placeholder: "내용 주석 (선택적)"
|
||||
geolocation-alert: "사용하시는 장치가 위치정보 기능에 대응하지 않습니다"
|
||||
error: "오류"
|
||||
username-prompt: "사용자명을 입력하여 주십시오"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
private: "이 글은 비공개입니다"
|
||||
deleted: "이 글은 삭제되었습니다"
|
||||
@ -1828,8 +1857,8 @@ pages:
|
||||
_divide:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
remind: "÷ 나눈 나머지"
|
||||
_remind:
|
||||
mod: "÷ 나눈 나머지"
|
||||
_mod:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
eq: "A와 B가 동일"
|
||||
|
@ -25,6 +25,10 @@ common:
|
||||
favorites: "Deze notitie toevoegen aan favorieten"
|
||||
permissions:
|
||||
"write:votes": "Stemmen"
|
||||
post-form:
|
||||
submit: "Bericht"
|
||||
reply: "Beantwoorden"
|
||||
add-visible-user: "Gebruiker toevoegen"
|
||||
weekday-short:
|
||||
sunday: "Z"
|
||||
monday: "M"
|
||||
@ -325,21 +329,12 @@ desktop/views/components/notes.vue:
|
||||
desktop/views/components/notifications.vue:
|
||||
empty: "Geen meldingen"
|
||||
desktop/views/components/post-form.vue:
|
||||
reply-placeholder: "Deze notitie beantwoorden..."
|
||||
quote-placeholder: "Deze notitie citeren..."
|
||||
submit: "Bericht"
|
||||
reply: "Beantwoorden"
|
||||
posted: "Geplaatst!"
|
||||
replied: "Beantwoord!"
|
||||
reposted: "Hergeplaatst!"
|
||||
note-failed: "Noteren mislukt"
|
||||
reply-failed: "Beantwoorden mislukt"
|
||||
renote-failed: "Renote mislukt"
|
||||
posting: "Bezig met plaatsen"
|
||||
attach-media-from-local: "Media bijvoegen van je computer"
|
||||
attach-media-from-drive: "Media bijvoegen uit je Drive"
|
||||
create-poll: "Peiling creëren"
|
||||
text-remain: "{} resterende tekens"
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "Nieuwe notitie"
|
||||
reply: "Beantwoorden"
|
||||
@ -538,11 +533,6 @@ mobile/views/components/note-detail.vue:
|
||||
location: "Locatie"
|
||||
mobile/views/components/notifications.vue:
|
||||
empty: "Geen meldingen"
|
||||
mobile/views/components/post-form.vue:
|
||||
add-visible-user: "Gebruiker toevoegen"
|
||||
submit: "Plaatsen"
|
||||
reply: "Antwoord"
|
||||
reply-placeholder: "Deze notitie beantwoorden..."
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
private: "(dit bericht is privé)"
|
||||
media-count: "{} media"
|
||||
|
@ -39,6 +39,10 @@ common:
|
||||
favorites: "Merket som favoritt"
|
||||
permissions:
|
||||
"write:votes": "Stem"
|
||||
post-form:
|
||||
submit: "Innlegg"
|
||||
reply: "Svar"
|
||||
error: "Feil"
|
||||
weekday-short:
|
||||
sunday: "S"
|
||||
monday: "M"
|
||||
@ -261,13 +265,6 @@ desktop/views/components/note.vue:
|
||||
detail: "Detaljer"
|
||||
desktop/views/components/notes.vue:
|
||||
retry: "Prøv på nytt"
|
||||
desktop/views/components/post-form.vue:
|
||||
submit: "Send"
|
||||
reply: "Svar"
|
||||
posting: "Publiserer"
|
||||
recent-tags: "Nylig"
|
||||
visibility: "Synlighet"
|
||||
error: "Feil"
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "Nytt innlegg"
|
||||
reply: "Svar"
|
||||
@ -328,6 +325,10 @@ admin/views/index.vue:
|
||||
admin/views/dashboard.vue:
|
||||
notes: "Innlegg"
|
||||
drive: "Disk"
|
||||
admin/views/logs.vue:
|
||||
levels:
|
||||
info: "Informasjon"
|
||||
error: "Feil"
|
||||
admin/views/abuse.vue:
|
||||
details: "Detaljer"
|
||||
remove-report: "Slett"
|
||||
@ -366,6 +367,7 @@ admin/views/federation.vue:
|
||||
status: "Status"
|
||||
states:
|
||||
all: "Alle"
|
||||
save: "Lagre"
|
||||
desktop/views/pages/welcome.vue:
|
||||
announcements: "Kunngjøringer"
|
||||
info: "Informasjon"
|
||||
@ -437,10 +439,6 @@ mobile/views/components/note-sub.vue:
|
||||
admin: "admin"
|
||||
bot: "bot"
|
||||
cat: "katt"
|
||||
mobile/views/components/post-form.vue:
|
||||
submit: "Send"
|
||||
reply: "Svar"
|
||||
error: "Feil"
|
||||
mobile/views/components/ui.header.vue:
|
||||
adjective: "Mr."
|
||||
mobile/views/components/ui.nav.vue:
|
||||
|
@ -68,6 +68,24 @@ common:
|
||||
"write:votes": "Zagłosuj"
|
||||
empty-timeline-info:
|
||||
explore: "Poznaj"
|
||||
post-form:
|
||||
hide-contents: "Ukryj zawartość"
|
||||
reply-placeholder: "Odpowiedź na ten wpis…"
|
||||
quote-placeholder: "Zacytuj ten wpis…"
|
||||
submit: "Wpis"
|
||||
reply: "Odpowiedz"
|
||||
renote: "Udostępnij"
|
||||
posting: "Wysyłanie"
|
||||
attach-media-from-local: "Załącz zawartość multimedialną z komputera"
|
||||
attach-media-from-drive: "Załącz zawartość multimedialną z dysku"
|
||||
create-poll: "Utwórz ankietę"
|
||||
text-remain: "pozostałe znaki: {}"
|
||||
recent-tags: "Ostatnie"
|
||||
visibility: "Widoczność"
|
||||
error: "Błąd"
|
||||
enter-username: "Wprowadź nazwę użytkownika"
|
||||
add-visible-user: "Dodaj użytkownika"
|
||||
username-prompt: "Wprowadź nazwę użytkownika"
|
||||
weekday-short:
|
||||
sunday: "N"
|
||||
monday: "Pn"
|
||||
@ -218,6 +236,9 @@ auth/views/index.vue:
|
||||
please-go-back: "Wróć do aplikacji."
|
||||
error: "Sesja nie istnieje."
|
||||
sign-in: "Proszę zalogować się."
|
||||
common/views/pages/explore.vue:
|
||||
popular-users: "Popularni użytkownicy"
|
||||
popular-tags: "Popularne tagi"
|
||||
common/views/components/games/reversi/reversi.vue:
|
||||
matching:
|
||||
waiting-for: "Oczekiwanie na {}"
|
||||
@ -701,33 +722,12 @@ desktop/views/components/notes.vue:
|
||||
desktop/views/components/notifications.vue:
|
||||
empty: "Brak powiadomień"
|
||||
desktop/views/components/post-form.vue:
|
||||
add-visible-user: "+Dodaj użytkownika"
|
||||
attach-location-information: "Załącz informacje o lokalizacji"
|
||||
hide-contents: "Ukryj zawartość"
|
||||
reply-placeholder: "Odpowiedz na ten wpis…"
|
||||
quote-placeholder: "Zacytuj ten wpis…"
|
||||
submit: "Wyślij"
|
||||
reply: "Odpowiedz"
|
||||
renote: "Udostępnienie"
|
||||
posted: "Opublikowano!"
|
||||
replied: "Odpowiedziano!"
|
||||
reposted: "Udostępniono!"
|
||||
note-failed: "Nie udało się wysłać"
|
||||
reply-failed: "Nie udało się odpowiedzieć"
|
||||
renote-failed: "Nie udało się udostępnić"
|
||||
posting: "Wysyłanie"
|
||||
attach-media-from-local: "Załącz zawartość multimedialną z komputera"
|
||||
attach-media-from-drive: "Załącz zawartość multimedialną z dysku"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "Utwórz ankietę"
|
||||
text-remain: "pozostałe znaki: {}"
|
||||
recent-tags: "Ostatnie"
|
||||
click-to-tagging: "Naciśnij aby oznaczyć"
|
||||
visibility: "Widoczność"
|
||||
geolocation-alert: "Twoje urządzenie nie obsługuje geolokalizacji."
|
||||
error: "Bład"
|
||||
enter-username: "Wprowadź nazwę użytkownika…"
|
||||
annotations: "Treść ostrzeżenia (opcjonalnie)"
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "Nowy wpis"
|
||||
reply: "Odpowiedz"
|
||||
@ -862,6 +862,10 @@ admin/views/dashboard.vue:
|
||||
notes: "Wpisy"
|
||||
drive: "Dysk"
|
||||
instances: "Instancja"
|
||||
admin/views/logs.vue:
|
||||
levels:
|
||||
info: "Informacje"
|
||||
error: "Błąd"
|
||||
admin/views/abuse.vue:
|
||||
details: "Szczegóły"
|
||||
remove-report: "Usuń"
|
||||
@ -950,6 +954,7 @@ admin/views/federation.vue:
|
||||
chart-srcs:
|
||||
requests: "Żądania"
|
||||
blocked-hosts: "Zablokuj"
|
||||
save: "Zapisz"
|
||||
desktop/views/pages/welcome.vue:
|
||||
about: "O Misskey"
|
||||
timeline: "Oś czasu"
|
||||
@ -1072,17 +1077,6 @@ mobile/views/components/note-sub.vue:
|
||||
cat: "kot"
|
||||
mobile/views/components/notifications.vue:
|
||||
empty: "Brak powiadomień"
|
||||
mobile/views/components/post-form.vue:
|
||||
add-visible-user: "Dodaj użytkownika"
|
||||
submit: "Wyślij"
|
||||
reply: "Odpowiedz"
|
||||
renote: "Udostępnij"
|
||||
quote-placeholder: "Zacytuj ten wpis… (nieobowiązkowe)"
|
||||
reply-placeholder: "Odpowiedź na ten wpis…"
|
||||
cw-placeholder: "Treść ostrzeżenia (opcjonalnie)"
|
||||
geolocation-alert: "Twoje urządzenie nie obsługuje geolokalizacji."
|
||||
error: "Błąd"
|
||||
username-prompt: "Wprowadź nazwę użytkownika"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
private: "ten wpis jest prywatny"
|
||||
deleted: "ten wpis został usunięty"
|
||||
|
@ -45,6 +45,9 @@ common:
|
||||
trash: "Lixo"
|
||||
timeline: "Linha do tempo"
|
||||
followers: "Seguidores"
|
||||
post-form:
|
||||
enter-username: "Digite o nome de usuário."
|
||||
username-prompt: "Digite o nome de usuário."
|
||||
weekday-short:
|
||||
sunday: "Dom"
|
||||
monday: "Seg"
|
||||
@ -89,6 +92,7 @@ common:
|
||||
update-available-title: "Atualização disponível"
|
||||
update-available: "Uma nova versão de Misskey está disponível ({newer}). A versão atual é {current}. Recarregue a página para atualizar."
|
||||
my-token-regenerated: "Seu token foi recriado, portanto você foi deslogado."
|
||||
enter-username: "Digite o nome de usuário."
|
||||
reversi:
|
||||
drawn: "Empatado"
|
||||
my-turn: "Seu turno"
|
||||
|
@ -95,6 +95,33 @@ common:
|
||||
empty-timeline-info:
|
||||
follow-users-to-make-your-timeline: "关注其他用户时,帖子将显示在时间线中。"
|
||||
explore: "查找用户"
|
||||
post-form:
|
||||
attach-location-information: "添加位置信息"
|
||||
hide-contents: "隐藏内容"
|
||||
reply-placeholder: "回复此贴..."
|
||||
quote-placeholder: "引用此帖…"
|
||||
option-quote-placeholder: "引用此帖…(可选)"
|
||||
quote-attached: "已引用"
|
||||
quote-question: "是否将其作为引用附上?"
|
||||
submit: "帖子"
|
||||
reply: "回复"
|
||||
renote: "转推"
|
||||
posting: "发送中"
|
||||
attach-media-from-local: "从PC中添加媒体文件"
|
||||
attach-media-from-drive: "从网盘中添加媒体文件"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "创建一个投票"
|
||||
text-remain: "还剩{}个字符"
|
||||
recent-tags: "最近"
|
||||
local-only-message: "这篇文章只会在本地发布"
|
||||
click-to-tagging: "点击添加标签"
|
||||
visibility: "可见性"
|
||||
geolocation-alert: "您的设备不支持定位服务"
|
||||
error: "错误"
|
||||
enter-username: "输入用户名"
|
||||
add-visible-user: "添加用户"
|
||||
cw-placeholder: "评论帖子(可选)"
|
||||
username-prompt: "输入用户名"
|
||||
weekday-short:
|
||||
sunday: "日"
|
||||
monday: "一"
|
||||
@ -253,7 +280,7 @@ common:
|
||||
my-token-regenerated: "您的 Token 已被重置, 您将自动登出。"
|
||||
hide-password: "隐藏密码"
|
||||
show-password: "显示密码"
|
||||
enter-username: "请输入用户名"
|
||||
enter-username: "输入用户名"
|
||||
do-not-use-in-production: "这是一个开发者测试版. 请勿在生产环境中使用."
|
||||
user-suspended: "该用户已被冻结。"
|
||||
is-remote-user: "此用户信息可能不准确。"
|
||||
@ -453,6 +480,7 @@ common/views/components/messaging.vue:
|
||||
group: "群组"
|
||||
start-with-user: "开始用户聊天"
|
||||
start-with-group: "开始群组聊天"
|
||||
select-group: "请选择群组"
|
||||
common/views/components/messaging-room.vue:
|
||||
not-talked-user: "没有用户的会话记录"
|
||||
not-talked-group: "没有群组的会话记录"
|
||||
@ -549,6 +577,7 @@ common/views/components/poll-editor.vue:
|
||||
day: "日"
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "选择回应"
|
||||
input-reaction-placeholder: "表情符号输入"
|
||||
common/views/components/emoji-picker.vue:
|
||||
custom-emoji: "自定义表情符号"
|
||||
people: "人"
|
||||
@ -704,10 +733,14 @@ common/views/components/user-group-editor.vue:
|
||||
users: "成员"
|
||||
rename: "更改群组名"
|
||||
delete: "删除群组"
|
||||
transfer: "群组转让"
|
||||
transfer-are-you-sure: "将群组「$1」转让给「@$2」吗?"
|
||||
transferred: "群组已转让"
|
||||
remove-user: "从本群组中删除"
|
||||
delete-are-you-sure: "确定要删除「$1」组?"
|
||||
deleted: "已删除"
|
||||
invite: "邀请"
|
||||
invited: "邀请已发送"
|
||||
common/views/components/user-lists.vue:
|
||||
user-lists: "列表"
|
||||
create-list: "创建列表"
|
||||
@ -716,7 +749,10 @@ common/views/components/user-groups.vue:
|
||||
user-groups: "群组"
|
||||
create-group: "创建群组"
|
||||
group-name: "群组名"
|
||||
owned-groups: "我的群组"
|
||||
joined-groups: "加入群组"
|
||||
invites: "邀请"
|
||||
accept-invite: "加入"
|
||||
reject-invite: "拒绝"
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "确认中"
|
||||
@ -913,34 +949,12 @@ desktop/views/components/notes.vue:
|
||||
desktop/views/components/notifications.vue:
|
||||
empty: "没有通知哦!"
|
||||
desktop/views/components/post-form.vue:
|
||||
add-visible-user: "+添加用户"
|
||||
attach-location-information: "添加位置信息"
|
||||
hide-contents: "隐藏内容"
|
||||
reply-placeholder: "回复这个帖子"
|
||||
quote-placeholder: "引用这个帖子…"
|
||||
submit: "投稿"
|
||||
reply: "回复"
|
||||
renote: "转推"
|
||||
posted: "已发送投稿!"
|
||||
replied: "已回复!"
|
||||
reposted: "已转推!"
|
||||
note-failed: "发帖失败"
|
||||
reply-failed: "回复失败"
|
||||
renote-failed: "转推失败"
|
||||
posting: "发送中"
|
||||
attach-media-from-local: "从设备中添加媒体文件"
|
||||
attach-media-from-drive: "从网盘中添加媒体文件"
|
||||
insert-a-kao: "v('ω')v"
|
||||
create-poll: "创建一个投票"
|
||||
text-remain: "还剩{}字"
|
||||
recent-tags: "最近"
|
||||
local-only-message: "这篇文章只会在本地发表"
|
||||
click-to-tagging: "点击添加标签"
|
||||
visibility: "可见性"
|
||||
geolocation-alert: "您的设备不提供位置服务"
|
||||
error: "错误"
|
||||
enter-username: "请填写一个用户名"
|
||||
annotations: "注释帖子(可选)"
|
||||
desktop/views/components/post-form-window.vue:
|
||||
note: "新建帖子"
|
||||
reply: "回复"
|
||||
@ -1101,6 +1115,32 @@ admin/views/dashboard.vue:
|
||||
admin/views/queue.vue:
|
||||
title: "队列"
|
||||
remove-all-jobs: "清除所有作业"
|
||||
jobs: "任务"
|
||||
queue: "队列"
|
||||
domains:
|
||||
deliver: "交付"
|
||||
inbox: "收件箱"
|
||||
db: "数据库"
|
||||
objectStorage: "对象存储"
|
||||
state: "状态"
|
||||
states:
|
||||
active: "处理中"
|
||||
delayed: "已预订"
|
||||
waiting: "队列等待中"
|
||||
result-is-truncated: "结果已省略"
|
||||
other-queues: "其他队列"
|
||||
admin/views/logs.vue:
|
||||
logs: "登录"
|
||||
domain: "域"
|
||||
level: "级别"
|
||||
levels:
|
||||
all: "所有"
|
||||
info: "信息"
|
||||
success: "成功"
|
||||
warning: "警告"
|
||||
error: "错误"
|
||||
debug: "调试"
|
||||
delete-all: "全部删除"
|
||||
admin/views/abuse.vue:
|
||||
title: "举报垃圾信息"
|
||||
target: "目标"
|
||||
@ -1147,6 +1187,7 @@ admin/views/instance.vue:
|
||||
mb: "以兆字节(Mbps)为单位"
|
||||
recaptcha-config: "reCAPTCHA设置"
|
||||
recaptcha-info: "reCAPTCHA token是必要的. 请从 https://www.google.com/recaptcha/intro/ 获取。\n请注意, 该功能在中国大陆不可用。"
|
||||
recaptcha-info2: "不支持v3。请使用v2。"
|
||||
enable-recaptcha: "启用 reCAPTCHA\n(请注意, 此功能在中国大陆不可用. 如果启用, 可能导致无法正常使用登录或注册等功能)"
|
||||
recaptcha-site-key: "网站密钥"
|
||||
recaptcha-secret-key: "密钥"
|
||||
@ -1251,6 +1292,9 @@ admin/views/drive.vue:
|
||||
unmark-as-sensitive: "取消标记为“敏感”"
|
||||
marked-as-sensitive: "标记为“敏感”"
|
||||
unmarked-as-sensitive: "取消标记为“敏感”"
|
||||
clean-remote-files: "删除远程文件缓存"
|
||||
clean-remote-files-are-you-sure: "确定要删除所有远程文件缓存吗?"
|
||||
clean-up: "清除缓存"
|
||||
admin/views/users.vue:
|
||||
operation: "操作"
|
||||
username-or-userid: "用户名或用户ID"
|
||||
@ -1397,6 +1441,7 @@ admin/views/federation.vue:
|
||||
day: "每天"
|
||||
blocked-hosts: "拉黑"
|
||||
blocked-hosts-info: "描述您要阻止的主机,以换行符分隔。"
|
||||
save: "保存"
|
||||
desktop/views/pages/welcome.vue:
|
||||
about: "更多信息..."
|
||||
timeline: "时间线"
|
||||
@ -1528,17 +1573,6 @@ mobile/views/components/note-sub.vue:
|
||||
cat: "cat"
|
||||
mobile/views/components/notifications.vue:
|
||||
empty: "没有通知哦!"
|
||||
mobile/views/components/post-form.vue:
|
||||
add-visible-user: "添加用户"
|
||||
submit: "帖子"
|
||||
reply: "回复"
|
||||
renote: "转推"
|
||||
quote-placeholder: "引用这个帖子t... (可选)"
|
||||
reply-placeholder: "回复这个帖子"
|
||||
cw-placeholder: "评论帖子(可选)"
|
||||
geolocation-alert: "您的设备不提供位置服务"
|
||||
error: "错误"
|
||||
username-prompt: "请输入用户名"
|
||||
mobile/views/components/sub-note-content.vue:
|
||||
private: "私密帖子"
|
||||
deleted: "帖子已删除"
|
||||
@ -1823,8 +1857,8 @@ pages:
|
||||
_divide:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
remind: "÷ 取模"
|
||||
_remind:
|
||||
mod: "÷ 取模"
|
||||
_mod:
|
||||
arg1: "A"
|
||||
arg2: "B"
|
||||
eq: "A和B相等"
|
||||
|
@ -3,21 +3,14 @@ import {MigrationInterface, QueryRunner} from "typeorm";
|
||||
export class UserProfile1556746559567 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<any> {
|
||||
await queryRunner.query(`UPDATE "user_profile" SET github = FALSE`);
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "githubId"`);
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" ADD COLUMN "githubId" VARCHAR(64)`);
|
||||
await queryRunner.query(`UPDATE "user_profile" SET discord = FALSE`);
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "discordExpiresDate"`);
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" ADD COLUMN "discordExpiresDate" VARCHAR(64)`);
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "githubId" TYPE VARCHAR(64) USING "githubId"::VARCHAR(64)`);
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "discordExpiresDate" TYPE VARCHAR(64) USING "discordExpiresDate"::VARCHAR(64)`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<any> {
|
||||
await queryRunner.query(`UPDATE "user_profile" SET github = FALSE`);
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "githubId"`);
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" ADD COLUMN "githubId" INTEGER`);
|
||||
await queryRunner.query(`UPDATE "user_profile" SET discord = FALSE`);
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "discordExpiresDate"`);
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" ADD COLUMN "discordExpiresDate" INTEGER`);
|
||||
await queryRunner.query(`UPDATE "user_profile" SET github = FALSE, discord = FALSE`);
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "githubId" TYPE INTEGER USING NULL`);
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "discordExpiresDate" TYPE INTEGER USING NULL`);
|
||||
}
|
||||
|
||||
}
|
||||
|
36
package.json
36
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <i@syuilo.com>",
|
||||
"version": "11.18.1",
|
||||
"version": "11.22.0",
|
||||
"codename": "daybreak",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -25,6 +25,10 @@
|
||||
"test": "gulp test",
|
||||
"format": "gulp format"
|
||||
},
|
||||
"resolutions": {
|
||||
"gulp-cssnano/cssnano/postcss-svgo/svgo/js-yaml": "^3.13.1",
|
||||
"video-thumbnail-generator/lodash": "^4.17.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"@elastic/elasticsearch": "7.0.0-rc.2",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.15",
|
||||
@ -33,13 +37,11 @@
|
||||
"@fortawesome/free-solid-svg-icons": "5.7.2",
|
||||
"@fortawesome/vue-fontawesome": "0.1.5",
|
||||
"@koa/cors": "2.2.3",
|
||||
"@prezzemolo/zip": "0.0.3",
|
||||
"@types/bcryptjs": "2.4.2",
|
||||
"@types/bull": "3.5.11",
|
||||
"@types/dateformat": "3.0.0",
|
||||
"@types/deep-equal": "1.0.1",
|
||||
"@types/double-ended-queue": "2.1.0",
|
||||
"@types/file-type": "10.9.1",
|
||||
"@types/gulp": "4.0.6",
|
||||
"@types/gulp-mocha": "0.0.32",
|
||||
"@types/gulp-rename": "0.0.33",
|
||||
@ -97,13 +99,13 @@
|
||||
"@types/websocket": "0.0.40",
|
||||
"@types/ws": "6.0.1",
|
||||
"animejs": "3.0.1",
|
||||
"apexcharts": "3.6.12",
|
||||
"apexcharts": "3.8.0",
|
||||
"autobind-decorator": "2.4.0",
|
||||
"autosize": "4.0.2",
|
||||
"autwh": "0.1.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"bootstrap-vue": "2.0.0-rc.13",
|
||||
"bull": "3.9.1",
|
||||
"bull": "3.10.0",
|
||||
"cafy": "15.1.1",
|
||||
"chai": "4.2.0",
|
||||
"chalk": "2.4.2",
|
||||
@ -141,12 +143,12 @@
|
||||
"http-signature": "1.2.0",
|
||||
"insert-text-at-cursor": "0.2.0",
|
||||
"is-root": "2.1.0",
|
||||
"is-svg": "4.1.0",
|
||||
"is-svg": "4.2.0",
|
||||
"js-yaml": "3.13.1",
|
||||
"jsdom": "15.1.0",
|
||||
"jsdom": "15.1.1",
|
||||
"json5": "2.1.0",
|
||||
"json5-loader": "2.0.0",
|
||||
"katex": "0.10.1",
|
||||
"katex": "0.10.2",
|
||||
"koa": "2.7.0",
|
||||
"koa-bodyparser": "4.2.1",
|
||||
"koa-compress": "3.0.0",
|
||||
@ -163,14 +165,14 @@
|
||||
"loader-utils": "1.2.3",
|
||||
"lolex": "3.1.0",
|
||||
"lookup-dns-cache": "2.1.0",
|
||||
"minio": "7.0.8",
|
||||
"minio": "7.0.10",
|
||||
"mocha": "6.1.4",
|
||||
"moji": "0.5.1",
|
||||
"moment": "2.24.0",
|
||||
"ms": "2.1.1",
|
||||
"ms": "2.1.2",
|
||||
"nested-property": "0.0.7",
|
||||
"node-fetch": "2.5.0",
|
||||
"nodemailer": "6.1.1",
|
||||
"node-fetch": "2.6.0",
|
||||
"nodemailer": "6.2.1",
|
||||
"nprogress": "0.2.0",
|
||||
"object-assign-deep": "0.4.0",
|
||||
"os-utils": "0.0.14",
|
||||
@ -212,10 +214,10 @@
|
||||
"style-loader": "0.23.1",
|
||||
"stylus": "0.54.5",
|
||||
"stylus-loader": "3.0.2",
|
||||
"summaly": "2.2.0",
|
||||
"systeminformation": "4.1.6",
|
||||
"summaly": "2.3.0",
|
||||
"systeminformation": "4.11.1",
|
||||
"syuilo-password-strength": "0.0.1",
|
||||
"terser-webpack-plugin": "1.2.4",
|
||||
"terser-webpack-plugin": "1.3.0",
|
||||
"textarea-caret": "3.1.0",
|
||||
"tinycolor2": "1.4.1",
|
||||
"tmp": "0.1.0",
|
||||
@ -253,8 +255,8 @@
|
||||
"vuex": "3.1.1",
|
||||
"vuex-persistedstate": "2.5.4",
|
||||
"web-push": "3.3.5",
|
||||
"webpack": "4.32.0",
|
||||
"webpack-cli": "3.3.2",
|
||||
"webpack": "4.34.0",
|
||||
"webpack-cli": "3.3.4",
|
||||
"websocket": "1.0.28",
|
||||
"ws": "7.0.0",
|
||||
"xev": "2.0.1"
|
||||
|
@ -50,7 +50,7 @@ export async function masterMain() {
|
||||
// initialize app
|
||||
config = await init();
|
||||
|
||||
if (config.port == null) {
|
||||
if (config.port == null || Number.isNaN(config.port)) {
|
||||
bootLogger.error('The port is not configured. Please configure port.', null, true);
|
||||
process.exit(1);
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ export default Vue.extend({
|
||||
this.connection = this.$root.stream.useSharedConnection('serverStats');
|
||||
|
||||
this.updateStats();
|
||||
this.clock = setInterval(this.updateStats, 1000);
|
||||
this.clock = setInterval(this.updateStats, 3000);
|
||||
|
||||
this.$root.getMeta().then(meta => {
|
||||
this.meta = meta;
|
||||
|
39
src/client/app/admin/views/db.vue
Normal file
39
src/client/app/admin/views/db.vue
Normal file
@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div>
|
||||
<ui-card>
|
||||
<template #title><fa :icon="faDatabase"/> {{ $t('tables') }}</template>
|
||||
<section v-if="tables">
|
||||
<div v-for="table in Object.keys(tables)"><b>{{ table }}</b> {{ tables[table].count | number }} {{ tables[table].size | bytes }}</div>
|
||||
</section>
|
||||
</ui-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../i18n';
|
||||
import { faDatabase } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('admin/views/db.vue'),
|
||||
|
||||
data() {
|
||||
return {
|
||||
tables: null,
|
||||
faDatabase
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.fetch();
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetch() {
|
||||
this.$root.api('admin/get-table-stats').then(tables => {
|
||||
this.tables = tables;
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
@ -14,6 +14,10 @@
|
||||
<ui-button @click="show()"><fa :icon="faSearch"/> {{ $t('lookup') }}</ui-button>
|
||||
<ui-textarea v-if="file" :value="file | json5" readonly tall style="margin-top:16px;"></ui-textarea>
|
||||
</section>
|
||||
<section>
|
||||
<ui-button @click="cleanUp()"><fa :icon="faTrashAlt"/> {{ $t('clean-up') }}</ui-button>
|
||||
<ui-button @click="cleanRemoteFiles()"><fa :icon="faTrashAlt"/> {{ $t('clean-remote-files') }}</ui-button>
|
||||
</section>
|
||||
</ui-card>
|
||||
|
||||
<ui-card>
|
||||
@ -227,6 +231,29 @@ export default Vue.extend({
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
cleanRemoteFiles() {
|
||||
this.$root.dialog({
|
||||
type: 'warning',
|
||||
text: this.$t('clean-remote-files-are-you-sure'),
|
||||
showCancelButton: true
|
||||
}).then(({ canceled }) => {
|
||||
if (canceled) return;
|
||||
this.$root.api('admin/drive/clean-remote-files');
|
||||
this.$root.dialog({
|
||||
type: 'success',
|
||||
splash: true
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
cleanUp() {
|
||||
this.$root.api('admin/drive/cleanup');
|
||||
this.$root.dialog({
|
||||
type: 'success',
|
||||
splash: true
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -22,6 +22,7 @@
|
||||
<li @click="nav('instance')" :class="{ active: page == 'instance' }"><fa icon="cog" fixed-width/>{{ $t('instance') }}</li>
|
||||
<li @click="nav('queue')" :class="{ active: page == 'queue' }"><fa :icon="faTasks" fixed-width/>{{ $t('queue') }}</li>
|
||||
<li @click="nav('logs')" :class="{ active: page == 'logs' }"><fa :icon="faStream" fixed-width/>{{ $t('logs') }}</li>
|
||||
<li @click="nav('db')" :class="{ active: page == 'db' }"><fa :icon="faDatabase" fixed-width/>{{ $t('db') }}</li>
|
||||
<li @click="nav('moderators')" :class="{ active: page == 'moderators' }"><fa :icon="faHeadset" fixed-width/>{{ $t('moderators') }}</li>
|
||||
<li @click="nav('users')" :class="{ active: page == 'users' }"><fa icon="users" fixed-width/>{{ $t('users') }}</li>
|
||||
<li @click="nav('drive')" :class="{ active: page == 'drive' }"><fa icon="cloud" fixed-width/>{{ $t('@.drive') }}</li>
|
||||
@ -43,6 +44,7 @@
|
||||
<div v-if="page == 'instance'"><x-instance/></div>
|
||||
<div v-if="page == 'queue'"><x-queue/></div>
|
||||
<div v-if="page == 'logs'"><x-logs/></div>
|
||||
<div v-if="page == 'db'"><x-db/></div>
|
||||
<div v-if="page == 'moderators'"><x-moderators/></div>
|
||||
<div v-if="page == 'users'"><x-users/></div>
|
||||
<div v-if="page == 'emoji'"><x-emoji/></div>
|
||||
@ -59,19 +61,20 @@
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../i18n';
|
||||
import { version } from '../../config';
|
||||
import XDashboard from "./dashboard.vue";
|
||||
import XInstance from "./instance.vue";
|
||||
import XQueue from "./queue.vue";
|
||||
import XLogs from "./logs.vue";
|
||||
import XModerators from "./moderators.vue";
|
||||
import XEmoji from "./emoji.vue";
|
||||
import XAnnouncements from "./announcements.vue";
|
||||
import XUsers from "./users.vue";
|
||||
import XDrive from "./drive.vue";
|
||||
import XAbuse from "./abuse.vue";
|
||||
import XFederation from "./federation.vue";
|
||||
import XDashboard from './dashboard.vue';
|
||||
import XInstance from './instance.vue';
|
||||
import XQueue from './queue.vue';
|
||||
import XLogs from './logs.vue';
|
||||
import XDb from './db.vue';
|
||||
import XModerators from './moderators.vue';
|
||||
import XEmoji from './emoji.vue';
|
||||
import XAnnouncements from './announcements.vue';
|
||||
import XUsers from './users.vue';
|
||||
import XDrive from './drive.vue';
|
||||
import XAbuse from './abuse.vue';
|
||||
import XFederation from './federation.vue';
|
||||
|
||||
import { faHeadset, faArrowLeft, faGlobe, faExclamationCircle, faTasks, faStream } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faHeadset, faArrowLeft, faGlobe, faExclamationCircle, faTasks, faStream, faDatabase } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faGrin } from '@fortawesome/free-regular-svg-icons';
|
||||
|
||||
// Detect the user agent
|
||||
@ -85,6 +88,7 @@ export default Vue.extend({
|
||||
XInstance,
|
||||
XQueue,
|
||||
XLogs,
|
||||
XDb,
|
||||
XModerators,
|
||||
XEmoji,
|
||||
XAnnouncements,
|
||||
@ -108,7 +112,8 @@ export default Vue.extend({
|
||||
faGlobe,
|
||||
faExclamationCircle,
|
||||
faTasks,
|
||||
faStream
|
||||
faStream,
|
||||
faDatabase,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
@ -9,11 +9,11 @@
|
||||
<ui-input v-model="iconUrl"><template #icon><fa icon="link"/></template>{{ $t('icon-url') }}</ui-input>
|
||||
<ui-input v-model="mascotImageUrl"><template #icon><fa icon="link"/></template>{{ $t('logo-url') }}</ui-input>
|
||||
<ui-input v-model="bannerUrl"><template #icon><fa icon="link"/></template>{{ $t('banner-url') }}</ui-input>
|
||||
<ui-input v-model="errorImageUrl"><template #icon><fa icon="link"/></template>{{ $t('error-image-url') }}</ui-input>
|
||||
<ui-input v-model="ToSUrl"><template #icon><fa icon="link"/></template>{{ $t('tos-url') }}</ui-input>
|
||||
<ui-input v-model="languages"><template #icon><fa icon="language"/></template>{{ $t('languages') }}<template #desc>{{ $t('languages-desc') }}</template></ui-input>
|
||||
<details>
|
||||
<summary>{{ $t('advanced-config') }}</summary>
|
||||
<ui-input v-model="errorImageUrl"><template #icon><fa icon="link"/></template>{{ $t('error-image-url') }}</ui-input>
|
||||
<ui-input v-model="languages"><template #icon><fa icon="language"/></template>{{ $t('languages') }}<template #desc>{{ $t('languages-desc') }}</template></ui-input>
|
||||
<ui-input v-model="repositoryUrl"><template #icon><fa icon="link"/></template>{{ $t('repository-url') }}</ui-input>
|
||||
<ui-input v-model="feedbackUrl"><template #icon><fa icon="link"/></template>{{ $t('feedback-url') }}</ui-input>
|
||||
</details>
|
||||
@ -159,6 +159,7 @@
|
||||
<ui-switch v-model="enableRecaptcha">{{ $t('enable-recaptcha') }}</ui-switch>
|
||||
<template v-if="enableRecaptcha">
|
||||
<ui-info>{{ $t('recaptcha-info') }}</ui-info>
|
||||
<ui-info warn>{{ $t('recaptcha-info2') }}</ui-info>
|
||||
<ui-horizon-group inputs>
|
||||
<ui-input v-model="recaptchaSiteKey" :disabled="!enableRecaptcha"><template #icon><fa icon="key"/></template>{{ $t('recaptcha-site-key') }}</ui-input>
|
||||
<ui-input v-model="recaptchaSecretKey" :disabled="!enableRecaptcha"><template #icon><fa icon="key"/></template>{{ $t('recaptcha-secret-key') }}</ui-input>
|
||||
|
@ -26,6 +26,8 @@
|
||||
</details>
|
||||
</code>
|
||||
</div>
|
||||
|
||||
<ui-button @click="deleteAll()">{{ $t('delete-all') }}</ui-button>
|
||||
</section>
|
||||
</ui-card>
|
||||
</div>
|
||||
@ -78,6 +80,15 @@ export default Vue.extend({
|
||||
}).then(logs => {
|
||||
this.logs = logs.reverse();
|
||||
});
|
||||
},
|
||||
|
||||
deleteAll() {
|
||||
this.$root.api('admin/delete-logs').then(() => {
|
||||
this.$root.dialog({
|
||||
type: 'success',
|
||||
splash: true
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
181
src/client/app/admin/views/queue.chart.vue
Normal file
181
src/client/app/admin/views/queue.chart.vue
Normal file
@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div>
|
||||
<ui-info warn v-if="latestStats && latestStats.waiting > 0">The queue is jammed.</ui-info>
|
||||
<ui-horizon-group inputs v-if="latestStats" class="fit-bottom">
|
||||
<ui-input :value="latestStats.activeSincePrevTick | number" type="text" readonly>
|
||||
<span>Process</span>
|
||||
<template #prefix><fa :icon="fasPlayCircle"/></template>
|
||||
<template #suffix>jobs/tick</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.active | number" type="text" readonly>
|
||||
<span>Active</span>
|
||||
<template #prefix><fa :icon="farPlayCircle"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.waiting | number" type="text" readonly>
|
||||
<span>Waiting</span>
|
||||
<template #prefix><fa :icon="faStopCircle"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.delayed | number" type="text" readonly>
|
||||
<span>Delayed</span>
|
||||
<template #prefix><fa :icon="faStopwatch"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
</ui-horizon-group>
|
||||
<div ref="chart" class="wptihjuy"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../i18n';
|
||||
import ApexCharts from 'apexcharts';
|
||||
import * as tinycolor from 'tinycolor2';
|
||||
import { faStopwatch, faPlayCircle as fasPlayCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faStopCircle, faPlayCircle as farPlayCircle } from '@fortawesome/free-regular-svg-icons';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('admin/views/queue.vue'),
|
||||
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
connection: {
|
||||
required: true
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
stats: [],
|
||||
chart: null,
|
||||
faStopwatch, faStopCircle, farPlayCircle, fasPlayCircle
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
latestStats(): any {
|
||||
return this.stats.length > 0 ? this.stats[this.stats.length - 1][this.type] : null;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
stats(stats) {
|
||||
this.chart.updateSeries([{
|
||||
name: 'Process',
|
||||
type: 'area',
|
||||
data: stats.map((x, i) => ({ x: i, y: x[this.type].activeSincePrevTick }))
|
||||
}, {
|
||||
name: 'Active',
|
||||
type: 'area',
|
||||
data: stats.map((x, i) => ({ x: i, y: x[this.type].active }))
|
||||
}, {
|
||||
name: 'Waiting',
|
||||
type: 'line',
|
||||
data: stats.map((x, i) => ({ x: i, y: x[this.type].waiting }))
|
||||
}, {
|
||||
name: 'Delayed',
|
||||
type: 'line',
|
||||
data: stats.map((x, i) => ({ x: i, y: x[this.type].delayed }))
|
||||
}]);
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.chart = new ApexCharts(this.$refs.chart, {
|
||||
chart: {
|
||||
id: this.type,
|
||||
group: 'queue',
|
||||
type: 'area',
|
||||
height: 200,
|
||||
animations: {
|
||||
dynamicAnimation: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
toolbar: {
|
||||
show: false
|
||||
},
|
||||
zoom: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
grid: {
|
||||
clipMarkers: false,
|
||||
borderColor: 'rgba(0, 0, 0, 0.1)',
|
||||
xaxis: {
|
||||
lines: {
|
||||
show: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
stroke: {
|
||||
curve: 'straight',
|
||||
width: 2
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false
|
||||
},
|
||||
legend: {
|
||||
labels: {
|
||||
colors: tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--text')).toRgbString()
|
||||
},
|
||||
},
|
||||
series: [] as any,
|
||||
colors: ['#00E396', '#00BCD4', '#FFB300', '#e53935'],
|
||||
xaxis: {
|
||||
type: 'numeric',
|
||||
labels: {
|
||||
show: false
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
show: false,
|
||||
min: 0,
|
||||
}
|
||||
});
|
||||
|
||||
this.chart.render();
|
||||
|
||||
this.connection.on('stats', this.onStats);
|
||||
this.connection.on('statsLog', this.onStatsLog);
|
||||
|
||||
this.$once('hook:beforeDestroy', () => {
|
||||
if (this.chart) this.chart.destroy();
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
onStats(stats) {
|
||||
this.stats.push(stats);
|
||||
if (this.stats.length > this.limit) this.stats.shift();
|
||||
},
|
||||
|
||||
onStatsLog(statsLog) {
|
||||
for (const stats of statsLog.reverse()) {
|
||||
this.onStats(stats);
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.wptihjuy
|
||||
min-height 200px !important
|
||||
margin -8px
|
||||
|
||||
</style>
|
@ -2,59 +2,27 @@
|
||||
<div>
|
||||
<ui-card>
|
||||
<template #title><fa :icon="faChartBar"/> {{ $t('title') }}</template>
|
||||
<section class="wptihjuy">
|
||||
<header><fa :icon="faPaperPlane"/> Deliver</header>
|
||||
<ui-info warn v-if="latestStats && latestStats.deliver.waiting > 0">The queue is jammed.</ui-info>
|
||||
<ui-horizon-group inputs v-if="latestStats" class="fit-bottom">
|
||||
<ui-input :value="latestStats.deliver.activeSincePrevTick | number" type="text" readonly>
|
||||
<span>Process</span>
|
||||
<template #prefix><fa :icon="fasPlayCircle"/></template>
|
||||
<template #suffix>jobs/tick</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.deliver.active | number" type="text" readonly>
|
||||
<span>Active</span>
|
||||
<template #prefix><fa :icon="farPlayCircle"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.deliver.waiting | number" type="text" readonly>
|
||||
<span>Waiting</span>
|
||||
<template #prefix><fa :icon="faStopCircle"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.deliver.delayed | number" type="text" readonly>
|
||||
<span>Delayed</span>
|
||||
<template #prefix><fa :icon="faStopwatch"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
</ui-horizon-group>
|
||||
<div ref="deliverChart" class="chart"></div>
|
||||
<section>
|
||||
<header><fa :icon="faPaperPlane"/> {{ $t('domains.deliver') }}</header>
|
||||
<x-chart v-if="connection" :connection="connection" :limit="chartLimit" type="deliver"/>
|
||||
</section>
|
||||
<section class="wptihjuy">
|
||||
<header><fa :icon="faInbox"/> Inbox</header>
|
||||
<ui-info warn v-if="latestStats && latestStats.inbox.waiting > 0">The queue is jammed.</ui-info>
|
||||
<ui-horizon-group inputs v-if="latestStats" class="fit-bottom">
|
||||
<ui-input :value="latestStats.inbox.activeSincePrevTick | number" type="text" readonly>
|
||||
<span>Process</span>
|
||||
<template #prefix><fa :icon="fasPlayCircle"/></template>
|
||||
<template #suffix>jobs/tick</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.inbox.active | number" type="text" readonly>
|
||||
<span>Active</span>
|
||||
<template #prefix><fa :icon="farPlayCircle"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.inbox.waiting | number" type="text" readonly>
|
||||
<span>Waiting</span>
|
||||
<template #prefix><fa :icon="faStopCircle"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
<ui-input :value="latestStats.inbox.delayed | number" type="text" readonly>
|
||||
<span>Delayed</span>
|
||||
<template #prefix><fa :icon="faStopwatch"/></template>
|
||||
<template #suffix>jobs</template>
|
||||
</ui-input>
|
||||
</ui-horizon-group>
|
||||
<div ref="inboxChart" class="chart"></div>
|
||||
<section>
|
||||
<header><fa :icon="faInbox"/> {{ $t('domains.inbox') }}</header>
|
||||
<x-chart v-if="connection" :connection="connection" :limit="chartLimit" type="inbox"/>
|
||||
</section>
|
||||
<section>
|
||||
<details>
|
||||
<summary>{{ $t('other-queues') }}</summary>
|
||||
<section>
|
||||
<header><fa :icon="faDatabase"/> {{ $t('domains.db') }}</header>
|
||||
<x-chart v-if="connection" :connection="connection" :limit="chartLimit" type="db"/>
|
||||
</section>
|
||||
<ui-hr/>
|
||||
<section>
|
||||
<header><fa :icon="faCloud"/> {{ $t('domains.objectStorage') }}</header>
|
||||
<x-chart v-if="connection" :connection="connection" :limit="chartLimit" type="objectStorage"/>
|
||||
</section>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
<ui-button @click="removeAllJobs">{{ $t('remove-all-jobs') }}</ui-button>
|
||||
@ -69,9 +37,13 @@
|
||||
<template #label>{{ $t('queue') }}</template>
|
||||
<option value="deliver">{{ $t('domains.deliver') }}</option>
|
||||
<option value="inbox">{{ $t('domains.inbox') }}</option>
|
||||
<option value="db">{{ $t('domains.db') }}</option>
|
||||
<option value="objectStorage">{{ $t('domains.objectStorage') }}</option>
|
||||
</ui-select>
|
||||
<ui-select v-model="state">
|
||||
<template #label>{{ $t('state') }}</template>
|
||||
<option value="active">{{ $t('states.active') }}</option>
|
||||
<option value="waiting">{{ $t('states.waiting') }}</option>
|
||||
<option value="delayed">{{ $t('states.delayed') }}</option>
|
||||
</ui-select>
|
||||
</ui-horizon-group>
|
||||
@ -94,74 +66,31 @@
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import { faTasks, faInbox, faDatabase, faCloud } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faPaperPlane, faChartBar } from '@fortawesome/free-regular-svg-icons';
|
||||
import i18n from '../../i18n';
|
||||
import ApexCharts from 'apexcharts';
|
||||
import * as tinycolor from 'tinycolor2';
|
||||
import { faTasks, faInbox, faStopwatch, faPlayCircle as fasPlayCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faPaperPlane, faStopCircle, faPlayCircle as farPlayCircle, faChartBar } from '@fortawesome/free-regular-svg-icons';
|
||||
|
||||
const limit = 200;
|
||||
import XChart from './queue.chart.vue';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('admin/views/queue.vue'),
|
||||
|
||||
components: {
|
||||
XChart
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
stats: [],
|
||||
deliverChart: null,
|
||||
inboxChart: null,
|
||||
connection: null,
|
||||
chartLimit: 200,
|
||||
jobs: [],
|
||||
jobsLimit: 50,
|
||||
domain: 'deliver',
|
||||
state: 'delayed',
|
||||
faTasks, faPaperPlane, faInbox, faStopwatch, faStopCircle, farPlayCircle, fasPlayCircle, faChartBar
|
||||
faTasks, faPaperPlane, faInbox, faChartBar, faDatabase, faCloud
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
latestStats(): any {
|
||||
return this.stats[this.stats.length - 1];
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
stats(stats) {
|
||||
this.inboxChart.updateSeries([{
|
||||
name: 'Process',
|
||||
type: 'area',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.inbox.activeSincePrevTick }))
|
||||
}, {
|
||||
name: 'Active',
|
||||
type: 'area',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.inbox.active }))
|
||||
}, {
|
||||
name: 'Waiting',
|
||||
type: 'line',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.inbox.waiting }))
|
||||
}, {
|
||||
name: 'Delayed',
|
||||
type: 'line',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.inbox.delayed }))
|
||||
}]);
|
||||
this.deliverChart.updateSeries([{
|
||||
name: 'Process',
|
||||
type: 'area',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.deliver.activeSincePrevTick }))
|
||||
}, {
|
||||
name: 'Active',
|
||||
type: 'area',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.deliver.active }))
|
||||
}, {
|
||||
name: 'Waiting',
|
||||
type: 'line',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.deliver.waiting }))
|
||||
}, {
|
||||
name: 'Delayed',
|
||||
type: 'line',
|
||||
data: stats.map((x, i) => ({ x: i, y: x.deliver.delayed }))
|
||||
}]);
|
||||
},
|
||||
|
||||
domain() {
|
||||
this.jobs = [];
|
||||
this.fetchJobs();
|
||||
@ -176,83 +105,14 @@ export default Vue.extend({
|
||||
mounted() {
|
||||
this.fetchJobs();
|
||||
|
||||
const chartOpts = id => ({
|
||||
chart: {
|
||||
id,
|
||||
group: 'queue',
|
||||
type: 'area',
|
||||
height: 200,
|
||||
animations: {
|
||||
dynamicAnimation: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
toolbar: {
|
||||
show: false
|
||||
},
|
||||
zoom: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
grid: {
|
||||
clipMarkers: false,
|
||||
borderColor: 'rgba(0, 0, 0, 0.1)',
|
||||
xaxis: {
|
||||
lines: {
|
||||
show: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
stroke: {
|
||||
curve: 'straight',
|
||||
width: 2
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false
|
||||
},
|
||||
legend: {
|
||||
labels: {
|
||||
colors: tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--text')).toRgbString()
|
||||
},
|
||||
},
|
||||
series: [] as any,
|
||||
colors: ['#00E396', '#00BCD4', '#FFB300', '#e53935'],
|
||||
xaxis: {
|
||||
type: 'numeric',
|
||||
labels: {
|
||||
show: false
|
||||
},
|
||||
tooltip: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
show: false,
|
||||
min: 0,
|
||||
}
|
||||
});
|
||||
|
||||
this.inboxChart = new ApexCharts(this.$refs.inboxChart, chartOpts('a'));
|
||||
this.deliverChart = new ApexCharts(this.$refs.deliverChart, chartOpts('b'));
|
||||
|
||||
this.inboxChart.render();
|
||||
this.deliverChart.render();
|
||||
|
||||
const connection = this.$root.stream.useSharedConnection('queueStats');
|
||||
connection.on('stats', this.onStats);
|
||||
connection.on('statsLog', this.onStatsLog);
|
||||
connection.send('requestLog', {
|
||||
this.connection = this.$root.stream.useSharedConnection('queueStats');
|
||||
this.connection.send('requestLog', {
|
||||
id: Math.random().toString().substr(2, 8),
|
||||
length: limit
|
||||
length: this.chartLimit
|
||||
});
|
||||
|
||||
this.$once('hook:beforeDestroy', () => {
|
||||
connection.dispose();
|
||||
this.inboxChart.destroy();
|
||||
this.deliverChart.destroy();
|
||||
this.connection.dispose();
|
||||
});
|
||||
},
|
||||
|
||||
@ -274,17 +134,6 @@ export default Vue.extend({
|
||||
});
|
||||
},
|
||||
|
||||
onStats(stats) {
|
||||
this.stats.push(stats);
|
||||
if (this.stats.length > limit) this.stats.shift();
|
||||
},
|
||||
|
||||
onStatsLog(statsLog) {
|
||||
for (const stats of statsLog.reverse()) {
|
||||
this.onStats(stats);
|
||||
}
|
||||
},
|
||||
|
||||
fetchJobs() {
|
||||
this.$root.api('admin/queue/jobs', {
|
||||
domain: this.domain,
|
||||
@ -299,11 +148,6 @@ export default Vue.extend({
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.wptihjuy
|
||||
> .chart
|
||||
min-height 200px !important
|
||||
margin 0 -8px
|
||||
|
||||
.xvvuvgsv
|
||||
> b
|
||||
margin-right 16px
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="form">
|
||||
<header>
|
||||
<h1 v-html="$t('share-access', { name: app.name })"></h1>
|
||||
<h1 v-html="$t('share-access', { name })"></h1>
|
||||
<img :src="app.iconUrl"/>
|
||||
</header>
|
||||
<div class="app">
|
||||
@ -34,6 +34,11 @@ export default Vue.extend({
|
||||
i18n: i18n('auth/views/form.vue'),
|
||||
props: ['session'],
|
||||
computed: {
|
||||
name(): string {
|
||||
const el = document.createElement('div');
|
||||
el.textContent = this.app.name
|
||||
return el.innerHTML;
|
||||
},
|
||||
app(): any {
|
||||
return this.session.app;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ export default (opts) => ({
|
||||
return {
|
||||
items: [],
|
||||
queue: [],
|
||||
offset: 0,
|
||||
fetching: true,
|
||||
moreFetching: false,
|
||||
inited: false,
|
||||
@ -80,6 +81,7 @@ export default (opts) => ({
|
||||
this.items = x;
|
||||
this.more = false;
|
||||
}
|
||||
this.offset = x.length;
|
||||
this.inited = true;
|
||||
this.fetching = false;
|
||||
if (opts.onInited) opts.onInited(this);
|
||||
@ -96,7 +98,11 @@ export default (opts) => ({
|
||||
if (params && params.then) params = await params;
|
||||
await this.$root.api(this.pagination.endpoint, {
|
||||
limit: (this.pagination.limit || 10) + 1,
|
||||
untilId: this.items[this.items.length - 1].id,
|
||||
...(this.pagination.endpoint === 'notes/search' ? {
|
||||
offset: this.offset,
|
||||
} : {
|
||||
untilId: this.items[this.items.length - 1].id,
|
||||
}),
|
||||
...params
|
||||
}).then(x => {
|
||||
if (x.length == (this.pagination.limit || 10) + 1) {
|
||||
@ -107,6 +113,7 @@ export default (opts) => ({
|
||||
this.items = this.items.concat(x);
|
||||
this.more = false;
|
||||
}
|
||||
this.offset += x.length;
|
||||
this.moreFetching = false;
|
||||
}, e => {
|
||||
this.moreFetching = false;
|
||||
|
478
src/client/app/common/scripts/post-form.ts
Normal file
478
src/client/app/common/scripts/post-form.ts
Normal file
@ -0,0 +1,478 @@
|
||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||
import { length } from 'stringz';
|
||||
import { toASCII } from 'punycode';
|
||||
import MkVisibilityChooser from '../views/components/visibility-chooser.vue';
|
||||
import getFace from './get-face';
|
||||
import { parse } from '../../../../mfm/parse';
|
||||
import { host, url } from '../../config';
|
||||
import i18n from '../../i18n';
|
||||
import { erase, unique } from '../../../../prelude/array';
|
||||
import extractMentions from '../../../../misc/extract-mentions';
|
||||
|
||||
export default (opts) => ({
|
||||
i18n: i18n(),
|
||||
|
||||
components: {
|
||||
XPostFormAttaches: () => import('../views/components/post-form-attaches.vue').then(m => m.default),
|
||||
XPollEditor: () => import('../views/components/poll-editor.vue').then(m => m.default)
|
||||
},
|
||||
|
||||
props: {
|
||||
reply: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
renote: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
mention: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
initialText: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
instant: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
posting: false,
|
||||
text: '',
|
||||
files: [],
|
||||
uploadings: [],
|
||||
poll: false,
|
||||
pollChoices: [],
|
||||
pollMultiple: false,
|
||||
pollExpiration: [],
|
||||
useCw: false,
|
||||
cw: null,
|
||||
geo: null,
|
||||
visibility: 'public',
|
||||
visibleUsers: [],
|
||||
localOnly: false,
|
||||
autocomplete: null,
|
||||
draghover: false,
|
||||
quoteId: null,
|
||||
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'),
|
||||
maxNoteTextLength: 1000
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
draftId(): string {
|
||||
return this.renote
|
||||
? `renote:${this.renote.id}`
|
||||
: this.reply
|
||||
? `reply:${this.reply.id}`
|
||||
: 'note';
|
||||
},
|
||||
|
||||
placeholder(): string {
|
||||
const xs = [
|
||||
this.$t('@.note-placeholders.a'),
|
||||
this.$t('@.note-placeholders.b'),
|
||||
this.$t('@.note-placeholders.c'),
|
||||
this.$t('@.note-placeholders.d'),
|
||||
this.$t('@.note-placeholders.e'),
|
||||
this.$t('@.note-placeholders.f')
|
||||
];
|
||||
const x = xs[Math.floor(Math.random() * xs.length)];
|
||||
|
||||
return this.renote
|
||||
? opts.mobile ? this.$t('@.post-form.option-quote-placeholder') : this.$t('@.post-form.quote-placeholder')
|
||||
: this.reply
|
||||
? this.$t('@.post-form.reply-placeholder')
|
||||
: x;
|
||||
},
|
||||
|
||||
submitText(): string {
|
||||
return this.renote
|
||||
? this.$t('@.post-form.renote')
|
||||
: this.reply
|
||||
? this.$t('@.post-form.reply')
|
||||
: this.$t('@.post-form.submit');
|
||||
},
|
||||
|
||||
canPost(): boolean {
|
||||
return !this.posting &&
|
||||
(1 <= this.text.length || 1 <= this.files.length || this.poll || this.renote) &&
|
||||
(length(this.text.trim()) <= this.maxNoteTextLength) &&
|
||||
(!this.poll || this.pollChoices.length >= 2);
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.$root.getMeta().then(meta => {
|
||||
this.maxNoteTextLength = meta.maxNoteTextLength;
|
||||
});
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.initialText) {
|
||||
this.text = this.initialText;
|
||||
}
|
||||
|
||||
if (this.mention) {
|
||||
this.text = this.mention.host ? `@${this.mention.username}@${toASCII(this.mention.host)}` : `@${this.mention.username}`;
|
||||
this.text += ' ';
|
||||
}
|
||||
|
||||
if (this.reply && this.reply.user.host != null) {
|
||||
this.text = `@${this.reply.user.username}@${toASCII(this.reply.user.host)} `;
|
||||
}
|
||||
|
||||
if (this.reply && this.reply.text != null) {
|
||||
const ast = parse(this.reply.text);
|
||||
|
||||
for (const x of extractMentions(ast)) {
|
||||
const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`;
|
||||
|
||||
// 自分は除外
|
||||
if (this.$store.state.i.username == x.username && x.host == null) continue;
|
||||
if (this.$store.state.i.username == x.username && x.host == host) continue;
|
||||
|
||||
// 重複は除外
|
||||
if (this.text.indexOf(`${mention} `) != -1) continue;
|
||||
|
||||
this.text += `${mention} `;
|
||||
}
|
||||
}
|
||||
|
||||
// デフォルト公開範囲
|
||||
this.applyVisibility(this.$store.state.settings.rememberNoteVisibility ? (this.$store.state.device.visibility || this.$store.state.settings.defaultNoteVisibility) : this.$store.state.settings.defaultNoteVisibility);
|
||||
|
||||
// 公開以外へのリプライ時は元の公開範囲を引き継ぐ
|
||||
if (this.reply && ['home', 'followers', 'specified'].includes(this.reply.visibility)) {
|
||||
this.visibility = this.reply.visibility;
|
||||
}
|
||||
|
||||
if (this.reply) {
|
||||
this.$root.api('users/show', { userId: this.reply.userId }).then(user => {
|
||||
this.visibleUsers.push(user);
|
||||
});
|
||||
}
|
||||
|
||||
// keep cw when reply
|
||||
if (this.$store.state.settings.keepCw && this.reply && this.reply.cw) {
|
||||
this.useCw = true;
|
||||
this.cw = this.reply.cw;
|
||||
}
|
||||
|
||||
this.focus();
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.focus();
|
||||
});
|
||||
|
||||
this.$nextTick(() => {
|
||||
// 書きかけの投稿を復元
|
||||
if (!this.instant && !this.mention) {
|
||||
const draft = JSON.parse(localStorage.getItem('drafts') || '{}')[this.draftId];
|
||||
if (draft) {
|
||||
this.text = draft.data.text;
|
||||
this.files = (draft.data.files || []).filter(e => e);
|
||||
if (draft.data.poll) {
|
||||
this.poll = true;
|
||||
this.$nextTick(() => {
|
||||
(this.$refs.poll as any).set(draft.data.poll);
|
||||
});
|
||||
}
|
||||
this.$emit('change-attached-files', this.files);
|
||||
}
|
||||
}
|
||||
|
||||
this.$nextTick(() => this.watch());
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
watch() {
|
||||
this.$watch('text', () => this.saveDraft());
|
||||
this.$watch('poll', () => this.saveDraft());
|
||||
this.$watch('files', () => this.saveDraft());
|
||||
},
|
||||
|
||||
trimmedLength(text: string) {
|
||||
return length(text.trim());
|
||||
},
|
||||
|
||||
addTag(tag: string) {
|
||||
insertTextAtCursor(this.$refs.text, ` #${tag} `);
|
||||
},
|
||||
|
||||
focus() {
|
||||
(this.$refs.text as any).focus();
|
||||
},
|
||||
|
||||
chooseFile() {
|
||||
(this.$refs.file as any).click();
|
||||
},
|
||||
|
||||
chooseFileFromDrive() {
|
||||
this.$chooseDriveFile({
|
||||
multiple: true
|
||||
}).then(files => {
|
||||
for (const x of files) this.attachMedia(x);
|
||||
});
|
||||
},
|
||||
|
||||
attachMedia(driveFile) {
|
||||
this.files.push(driveFile);
|
||||
this.$emit('change-attached-files', this.files);
|
||||
},
|
||||
|
||||
detachMedia(id) {
|
||||
this.files = this.files.filter(x => x.id != id);
|
||||
this.$emit('change-attached-files', this.files);
|
||||
},
|
||||
|
||||
onChangeFile() {
|
||||
for (const x of Array.from((this.$refs.file as any).files)) this.upload(x);
|
||||
},
|
||||
|
||||
upload(file) {
|
||||
(this.$refs.uploader as any).upload(file);
|
||||
},
|
||||
|
||||
onChangeUploadings(uploads) {
|
||||
this.$emit('change-uploadings', uploads);
|
||||
},
|
||||
|
||||
onPollUpdate() {
|
||||
const got = this.$refs.poll.get();
|
||||
this.pollChoices = got.choices;
|
||||
this.pollMultiple = got.multiple;
|
||||
this.pollExpiration = [got.expiration, got.expiresAt || got.expiredAfter];
|
||||
this.saveDraft();
|
||||
},
|
||||
|
||||
setGeo() {
|
||||
if (navigator.geolocation == null) {
|
||||
this.$root.dialog({
|
||||
type: 'warning',
|
||||
text: this.$t('@.post-form.geolocation-alert')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.geolocation.getCurrentPosition(pos => {
|
||||
this.geo = pos.coords;
|
||||
this.$emit('geo-attached', this.geo);
|
||||
}, err => {
|
||||
this.$root.dialog({
|
||||
type: 'error',
|
||||
title: this.$t('@.post-form.error'),
|
||||
text: err.message
|
||||
});
|
||||
}, {
|
||||
enableHighAccuracy: true
|
||||
});
|
||||
},
|
||||
|
||||
removeGeo() {
|
||||
this.geo = null;
|
||||
this.$emit('geo-dettached');
|
||||
},
|
||||
|
||||
setVisibility() {
|
||||
const w = this.$root.new(MkVisibilityChooser, {
|
||||
source: this.$refs.visibilityButton,
|
||||
currentVisibility: this.visibility
|
||||
});
|
||||
w.$once('chosen', v => {
|
||||
this.applyVisibility(v);
|
||||
});
|
||||
},
|
||||
|
||||
applyVisibility(v: string) {
|
||||
const m = v.match(/^local-(.+)/);
|
||||
if (m) {
|
||||
this.localOnly = true;
|
||||
this.visibility = m[1];
|
||||
} else {
|
||||
this.localOnly = false;
|
||||
this.visibility = v;
|
||||
}
|
||||
},
|
||||
|
||||
addVisibleUser() {
|
||||
this.$root.dialog({
|
||||
title: this.$t('@.post-form.enter-username'),
|
||||
user: true
|
||||
}).then(({ canceled, result: user }) => {
|
||||
if (canceled) return;
|
||||
this.visibleUsers.push(user);
|
||||
});
|
||||
},
|
||||
|
||||
removeVisibleUser(user) {
|
||||
this.visibleUsers = erase(user, this.visibleUsers);
|
||||
},
|
||||
|
||||
clear() {
|
||||
this.text = '';
|
||||
this.files = [];
|
||||
this.poll = false;
|
||||
this.$emit('change-attached-files', this.files);
|
||||
},
|
||||
|
||||
onKeydown(e) {
|
||||
if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey) && this.canPost) this.post();
|
||||
},
|
||||
|
||||
async onPaste(e) {
|
||||
for (const item of Array.from(e.clipboardData.items)) {
|
||||
if (item.kind == 'file') {
|
||||
this.upload(item.getAsFile());
|
||||
}
|
||||
}
|
||||
|
||||
const paste = e.clipboardData.getData('text');
|
||||
|
||||
if (paste.startsWith(url + '/notes/')) {
|
||||
e.preventDefault();
|
||||
|
||||
this.$root.dialog({
|
||||
type: 'info',
|
||||
text: this.$t('@.post-form.quote-question'),
|
||||
showCancelButton: true
|
||||
}).then(({ canceled }) => {
|
||||
if (canceled) {
|
||||
insertTextAtCursor(this.$refs.text, paste);
|
||||
return;
|
||||
}
|
||||
|
||||
this.quoteId = paste.substr(url.length).match(/^\/notes\/(.+?)\/?$/)[1];
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onDragover(e) {
|
||||
const isFile = e.dataTransfer.items[0].kind == 'file';
|
||||
const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file';
|
||||
if (isFile || isDriveFile) {
|
||||
e.preventDefault();
|
||||
this.draghover = true;
|
||||
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
||||
}
|
||||
},
|
||||
|
||||
onDragenter(e) {
|
||||
this.draghover = true;
|
||||
},
|
||||
|
||||
onDragleave(e) {
|
||||
this.draghover = false;
|
||||
},
|
||||
|
||||
onDrop(e): void {
|
||||
this.draghover = false;
|
||||
|
||||
// ファイルだったら
|
||||
if (e.dataTransfer.files.length > 0) {
|
||||
e.preventDefault();
|
||||
for (const x of Array.from(e.dataTransfer.files)) this.upload(x);
|
||||
return;
|
||||
}
|
||||
|
||||
//#region ドライブのファイル
|
||||
const driveFile = e.dataTransfer.getData('mk_drive_file');
|
||||
if (driveFile != null && driveFile != '') {
|
||||
const file = JSON.parse(driveFile);
|
||||
this.files.push(file);
|
||||
this.$emit('change-attached-files', this.files);
|
||||
e.preventDefault();
|
||||
}
|
||||
//#endregion
|
||||
},
|
||||
|
||||
async emoji() {
|
||||
const Picker = await import('../../desktop/views/components/emoji-picker-dialog.vue').then(m => m.default);
|
||||
const button = this.$refs.emoji;
|
||||
const rect = button.getBoundingClientRect();
|
||||
const vm = this.$root.new(Picker, {
|
||||
x: button.offsetWidth + rect.left + window.pageXOffset,
|
||||
y: rect.top + window.pageYOffset
|
||||
});
|
||||
vm.$once('chosen', emoji => {
|
||||
insertTextAtCursor(this.$refs.text, emoji);
|
||||
});
|
||||
},
|
||||
|
||||
saveDraft() {
|
||||
if (this.instant) return;
|
||||
|
||||
const data = JSON.parse(localStorage.getItem('drafts') || '{}');
|
||||
|
||||
data[this.draftId] = {
|
||||
updatedAt: new Date(),
|
||||
data: {
|
||||
text: this.text,
|
||||
files: this.files,
|
||||
poll: this.poll && this.$refs.poll ? (this.$refs.poll as any).get() : undefined
|
||||
}
|
||||
};
|
||||
|
||||
localStorage.setItem('drafts', JSON.stringify(data));
|
||||
},
|
||||
|
||||
deleteDraft() {
|
||||
const data = JSON.parse(localStorage.getItem('drafts') || '{}');
|
||||
|
||||
delete data[this.draftId];
|
||||
|
||||
localStorage.setItem('drafts', JSON.stringify(data));
|
||||
},
|
||||
|
||||
kao() {
|
||||
this.text += getFace();
|
||||
},
|
||||
|
||||
post() {
|
||||
this.posting = true;
|
||||
const viaMobile = opts.mobile && !this.$store.state.settings.disableViaMobile;
|
||||
this.$root.api('notes/create', {
|
||||
text: this.text == '' ? undefined : this.text,
|
||||
fileIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
|
||||
replyId: this.reply ? this.reply.id : undefined,
|
||||
renoteId: this.renote ? this.renote.id : this.quoteId ? this.quoteId : undefined,
|
||||
poll: this.poll ? (this.$refs.poll as any).get() : undefined,
|
||||
cw: this.useCw ? this.cw || '' : undefined,
|
||||
visibility: this.visibility,
|
||||
visibleUserIds: this.visibility == 'specified' ? this.visibleUsers.map(u => u.id) : undefined,
|
||||
localOnly: this.localOnly,
|
||||
geo: this.geo ? {
|
||||
coordinates: [this.geo.longitude, this.geo.latitude],
|
||||
altitude: this.geo.altitude,
|
||||
accuracy: this.geo.accuracy,
|
||||
altitudeAccuracy: this.geo.altitudeAccuracy,
|
||||
heading: isNaN(this.geo.heading) ? null : this.geo.heading,
|
||||
speed: this.geo.speed,
|
||||
} : null,
|
||||
viaMobile: viaMobile
|
||||
}).then(data => {
|
||||
this.clear();
|
||||
this.deleteDraft();
|
||||
this.$emit('posted');
|
||||
if (opts.onSuccess) opts.onSuccess(this);
|
||||
}).catch(err => {
|
||||
if (opts.onSuccess) opts.onFailure(this);
|
||||
}).then(() => {
|
||||
this.posting = false;
|
||||
});
|
||||
|
||||
if (this.text && this.text != '') {
|
||||
const hashtags = parse(this.text).filter(x => x.node.type === 'hashtag').map(x => x.node.props.hashtag);
|
||||
const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[];
|
||||
localStorage.setItem('hashtags', JSON.stringify(unique(hashtags.concat(history))));
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
@ -16,7 +16,7 @@
|
||||
</ol>
|
||||
<ol class="emojis" ref="suggests" v-if="emojis.length > 0">
|
||||
<li v-for="emoji in emojis" @click="complete(type, emoji.emoji)" @keydown="onKeydown" tabindex="-1">
|
||||
<span class="emoji" v-if="emoji.isCustomEmoji"><img :src="emoji.url" :alt="emoji.emoji"/></span>
|
||||
<span class="emoji" v-if="emoji.isCustomEmoji"><img :src="$store.state.device.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url" :alt="emoji.emoji"/></span>
|
||||
<span class="emoji" v-else-if="!useOsDefaultEmojis"><img :src="emoji.url" :alt="emoji.emoji"/></span>
|
||||
<span class="emoji" v-else>{{ emoji.emoji }}</span>
|
||||
<span class="name" v-html="emoji.name.replace(q, `<b>${q}</b>`)"></span>
|
||||
@ -31,6 +31,7 @@ import Vue from 'vue';
|
||||
import * as emojilib from 'emojilib';
|
||||
import contains from '../../../common/scripts/contains';
|
||||
import { twemojiBase } from '../../../../../misc/twemoji-base';
|
||||
import { getStaticImageUrl } from '../../../common/scripts/get-static-image-url';
|
||||
|
||||
type EmojiDef = {
|
||||
emoji: string;
|
||||
@ -78,6 +79,7 @@ export default Vue.extend({
|
||||
|
||||
data() {
|
||||
return {
|
||||
getStaticImageUrl,
|
||||
fetching: true,
|
||||
users: [],
|
||||
hashtags: [],
|
||||
|
@ -98,7 +98,7 @@ export default Vue.extend({
|
||||
return {
|
||||
inputValue: this.input && this.input.default ? this.input.default : null,
|
||||
userInputValue: null,
|
||||
selectedValue: null,
|
||||
selectedValue: this.select ? this.select.items ? this.select.items[0].value : this.select.groupedItems[0].items[0].value : null,
|
||||
faTimesCircle, faQuestionCircle
|
||||
};
|
||||
},
|
||||
|
@ -23,11 +23,11 @@
|
||||
</div>
|
||||
|
||||
<div class="board">
|
||||
<div class="labels-x" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
|
||||
<div class="labels-x" v-if="$store.state.settings.gamesReversiShowBoardLabels">
|
||||
<span v-for="i in game.map[0].length">{{ String.fromCharCode(64 + i) }}</span>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="labels-y" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
|
||||
<div class="labels-y" v-if="$store.state.settings.gamesReversiShowBoardLabels">
|
||||
<div v-for="i in game.map.length">{{ i }}</div>
|
||||
</div>
|
||||
<div class="cells" :style="cellsStyle">
|
||||
@ -35,7 +35,7 @@
|
||||
:class="{ empty: stone == null, none: o.map[i] == 'null', isEnded: game.isEnded, myTurn: !game.isEnded && isMyTurn, can: turnUser ? o.canPut(turnUser.id == blackUser.id, i) : null, prev: o.prevPos == i }"
|
||||
@click="set(i)"
|
||||
:title="`${String.fromCharCode(65 + o.transformPosToXy(i)[0])}${o.transformPosToXy(i)[1] + 1}`">
|
||||
<template v-if="$store.state.settings.games.reversi.useAvatarStones">
|
||||
<template v-if="$store.state.settings.gamesReversiUseAvatarStones">
|
||||
<img v-if="stone === true" :src="blackUser.avatarUrl" alt="black">
|
||||
<img v-if="stone === false" :src="whiteUser.avatarUrl" alt="white">
|
||||
</template>
|
||||
@ -45,11 +45,11 @@
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="labels-y" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
|
||||
<div class="labels-y" v-if="this.$store.state.settings.gamesReversiShowBoardLabels">
|
||||
<div v-for="i in game.map.length">{{ i }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="labels-x" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
|
||||
<div class="labels-x" v-if="this.$store.state.settings.gamesReversiShowBoardLabels">
|
||||
<span v-for="i in game.map[0].length">{{ String.fromCharCode(64 + i) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="onchrpzrvnoruiaenfcqvccjfuupzzwv" :class="{ isMobile: $root.isMobile }">
|
||||
<div class="backdrop" ref="backdrop" @click="close"></div>
|
||||
<div class="popover" :class="{ hukidasi }" ref="popover">
|
||||
<div class="popover" :class="{ bubble }" ref="popover">
|
||||
<template v-for="item, i in items">
|
||||
<div v-if="item === null"></div>
|
||||
<button v-if="item" @click="clicked(item.action)" :tabindex="i">
|
||||
@ -28,7 +28,7 @@ export default Vue.extend({
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hukidasi: !this.$root.isMobile
|
||||
bubble: !this.$root.isMobile
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
@ -56,12 +56,12 @@ export default Vue.extend({
|
||||
|
||||
if (left + width - window.pageXOffset > window.innerWidth) {
|
||||
left = window.innerWidth - width + window.pageXOffset;
|
||||
this.hukidasi = false;
|
||||
this.bubble = false;
|
||||
}
|
||||
|
||||
if (top + height - window.pageYOffset > window.innerHeight) {
|
||||
top = window.innerHeight - height + window.pageYOffset;
|
||||
this.hukidasi = false;
|
||||
this.bubble = false;
|
||||
}
|
||||
|
||||
if (top < 0) {
|
||||
@ -150,7 +150,7 @@ export default Vue.extend({
|
||||
|
||||
$balloon-size = 16px
|
||||
|
||||
&.hukidasi
|
||||
&.bubble
|
||||
margin-top $balloon-size
|
||||
transform-origin center -($balloon-size)
|
||||
|
||||
|
@ -300,17 +300,13 @@ export default Vue.extend({
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.mk-messaging-room
|
||||
display flex
|
||||
flex 1
|
||||
flex-direction column
|
||||
height 100%
|
||||
background var(--messagingRoomBg)
|
||||
|
||||
> .body
|
||||
width 100%
|
||||
max-width 600px
|
||||
margin 0 auto
|
||||
flex 1
|
||||
min-height calc(100% - 103px)
|
||||
|
||||
> .init,
|
||||
> .empty
|
||||
|
@ -46,7 +46,7 @@
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<p class="no-history" v-if="!fetching && (messages.length == 0 && groupMessages.length == 0)">{{ $t('no-history') }}</p>
|
||||
<p class="no-history" v-if="!fetching && messages.length == 0">{{ $t('no-history') }}</p>
|
||||
<p class="fetching" v-if="fetching"><fa icon="spinner" pulse fixed-width/>{{ $t('@.loading') }}<mk-ellipsis/></p>
|
||||
<ui-margin>
|
||||
<ui-button @click="startUser()"><fa :icon="faUser"/> {{ $t('start-with-user') }}</ui-button>
|
||||
|
@ -175,7 +175,6 @@ export default Vue.component('misskey-flavored-markdown', {
|
||||
props: {
|
||||
url: token.node.props.url,
|
||||
rel: 'nofollow noopener',
|
||||
target: '_blank'
|
||||
},
|
||||
attrs: {
|
||||
style: 'color:var(--mfmUrl);'
|
||||
|
@ -89,9 +89,7 @@ export default Vue.extend({
|
||||
|
||||
get() {
|
||||
const at = () => {
|
||||
const [date] = moment(this.atDate).toISOString().split('T');
|
||||
const [hour, minute] = this.atTime.split(':');
|
||||
return moment(`${date}T${hour}:${minute}Z`).valueOf();
|
||||
return moment(`${this.atDate} ${this.atTime}`).valueOf();
|
||||
};
|
||||
|
||||
const after = () => {
|
||||
|
@ -16,7 +16,7 @@
|
||||
<button @click="react('pudding')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="10" :title="$t('@.reactions.pudding')" v-particle><mk-reaction-icon reaction="pudding"/></button>
|
||||
</div>
|
||||
<div v-if="enableEmojiReaction" class="text">
|
||||
<input v-model="text" placeholder="または絵文字を入力" @keyup.enter="reactText" @input="tryReactText" v-autocomplete="{ model: 'text' }">
|
||||
<input v-model="text" :placeholder="$t('input-reaction-placeholder')" @keyup.enter="reactText" @input="tryReactText" v-autocomplete="{ model: 'text' }">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -472,13 +472,13 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
games_reversi_showBoardLabels: {
|
||||
get() { return this.$store.state.settings.games.reversi.showBoardLabels; },
|
||||
set(value) { this.$store.dispatch('settings/set', { key: 'games.reversi.showBoardLabels', value }); }
|
||||
get() { return this.$store.state.settings.gamesReversiShowBoardLabels; },
|
||||
set(value) { this.$store.dispatch('settings/set', { key: 'gamesReversiShowBoardLabels', value }); }
|
||||
},
|
||||
|
||||
games_reversi_useAvatarStones: {
|
||||
get() { return this.$store.state.settings.games.reversi.useAvatarStones; },
|
||||
set(value) { this.$store.dispatch('settings/set', { key: 'games.reversi.useAvatarStones', value }); }
|
||||
get() { return this.$store.state.settings.gamesReversiUseAvatarStones; },
|
||||
set(value) { this.$store.dispatch('settings/set', { key: 'gamesReversiUseAvatarStones', value }); }
|
||||
},
|
||||
|
||||
disableAnimatedMfm: {
|
||||
|
@ -43,7 +43,7 @@
|
||||
</i18n>
|
||||
</ui-switch>
|
||||
<div v-if="meta.enableRecaptcha" class="g-recaptcha" :data-sitekey="meta.recaptchaSiteKey" style="margin: 16px 0;"></div>
|
||||
<ui-button type="submit" :disabled="!(meta.ToSUrl ? ToSAgreement : true)">{{ $t('create') }}</ui-button>
|
||||
<ui-button type="submit" :disabled="!(meta.ToSUrl ? ToSAgreement : true) || passwordRetypeState == 'not-match'">{{ $t('create') }}</ui-button>
|
||||
</template>
|
||||
</form>
|
||||
</template>
|
||||
|
@ -210,17 +210,25 @@ export default Vue.extend({
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.prefix) {
|
||||
this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px';
|
||||
if (this.$refs.prefix.offsetWidth) {
|
||||
this.$refs.input.style.paddingLeft = this.$refs.prefix.offsetWidth + 'px';
|
||||
// このコンポーネントが作成された時、非表示状態である場合がある
|
||||
// 非表示状態だと要素の幅などは0になってしまうので、定期的に計算する
|
||||
const clock = setInterval(() => {
|
||||
if (this.$refs.prefix) {
|
||||
this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px';
|
||||
if (this.$refs.prefix.offsetWidth) {
|
||||
this.$refs.input.style.paddingLeft = this.$refs.prefix.offsetWidth + 'px';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.$refs.suffix) {
|
||||
if (this.$refs.suffix.offsetWidth) {
|
||||
this.$refs.input.style.paddingRight = this.$refs.suffix.offsetWidth + 'px';
|
||||
if (this.$refs.suffix) {
|
||||
if (this.$refs.suffix.offsetWidth) {
|
||||
this.$refs.input.style.paddingRight = this.$refs.suffix.offsetWidth + 'px';
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
|
||||
this.$once('hook:beforeDestroy', () => {
|
||||
clearInterval(clock);
|
||||
});
|
||||
});
|
||||
|
||||
this.$on('keydown', (e: KeyboardEvent) => {
|
||||
|
@ -9,7 +9,7 @@
|
||||
</blockquote>
|
||||
</div>
|
||||
<div v-else class="mk-url-preview">
|
||||
<a :class="{ mini: narrow, compact }" :href="url" rel="nofollow noopener" target="_blank" :title="url" v-if="!fetching">
|
||||
<component :is="hasRoute ? 'router-link' : 'a'" :class="{ mini: narrow, compact }" :[attr]="hasRoute ? url.substr(local.length) : url" rel="nofollow noopener" :target="target" :title="url" v-if="!fetching">
|
||||
<div class="thumbnail" v-if="thumbnail" :style="`background-image: url('${thumbnail}')`">
|
||||
<button v-if="!playerEnabled && player.url" @click.prevent="playerEnabled = true" :title="$t('enable-player')"><fa :icon="['far', 'play-circle']"/></button>
|
||||
</div>
|
||||
@ -23,17 +23,18 @@
|
||||
<p :title="sitename">{{ sitename }}</p>
|
||||
</footer>
|
||||
</article>
|
||||
</a>
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../../i18n';
|
||||
import { url as misskeyUrl } from '../../../config';
|
||||
import { url as local } from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('common/views/components/url-preview.vue'),
|
||||
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
@ -60,7 +61,13 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
data() {
|
||||
const isSelf = this.url.startsWith(local);
|
||||
const hasRoute =
|
||||
this.url.substr(local.length).startsWith('/@') ||
|
||||
this.url.substr(local.length).startsWith('/notes/') ||
|
||||
this.url.substr(local.length).startsWith('/pages/');
|
||||
return {
|
||||
local,
|
||||
fetching: true,
|
||||
title: null,
|
||||
description: null,
|
||||
@ -74,7 +81,10 @@ export default Vue.extend({
|
||||
},
|
||||
tweetUrl: null,
|
||||
playerEnabled: false,
|
||||
misskeyUrl,
|
||||
self: isSelf,
|
||||
hasRoute: hasRoute,
|
||||
attr: hasRoute ? 'to' : 'href',
|
||||
target: hasRoute ? null : '_blank'
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -1,29 +1,42 @@
|
||||
<template>
|
||||
<a class="mk-url" :href="url" :rel="rel" :target="target">
|
||||
<span class="schema">{{ schema }}//</span>
|
||||
<span class="hostname">{{ hostname }}</span>
|
||||
<span class="port" v-if="port != ''">:{{ port }}</span>
|
||||
<span class="pathname" v-if="pathname != ''">{{ pathname }}</span>
|
||||
<component :is="hasRoute ? 'router-link' : 'a'" class="mk-url" :[attr]="hasRoute ? url.substr(local.length) : url" :rel="rel" :target="target">
|
||||
<template v-if="!self">
|
||||
<span class="schema">{{ schema }}//</span>
|
||||
<span class="hostname">{{ hostname }}</span>
|
||||
<span class="port" v-if="port != ''">:{{ port }}</span>
|
||||
</template>
|
||||
<span class="pathname" v-if="pathname != ''">{{ self ? pathname.substr(1) : pathname }}</span>
|
||||
<span class="query">{{ query }}</span>
|
||||
<span class="hash">{{ hash }}</span>
|
||||
<fa icon="external-link-square-alt"/>
|
||||
</a>
|
||||
<fa icon="external-link-square-alt" v-if="target === '_blank'"/>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import { toUnicode as decodePunycode } from 'punycode';
|
||||
import { url as local } from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
props: ['url', 'rel', 'target'],
|
||||
props: ['url', 'rel'],
|
||||
data() {
|
||||
const isSelf = this.url.startsWith(local);
|
||||
const hasRoute = isSelf && (
|
||||
this.url.substr(local.length).startsWith('/@') ||
|
||||
this.url.substr(local.length).startsWith('/notes/') ||
|
||||
this.url.substr(local.length).startsWith('/pages/'));
|
||||
return {
|
||||
local,
|
||||
schema: null,
|
||||
hostname: null,
|
||||
port: null,
|
||||
pathname: null,
|
||||
query: null,
|
||||
hash: null
|
||||
hash: null,
|
||||
self: isSelf,
|
||||
hasRoute: hasRoute,
|
||||
attr: hasRoute ? 'to' : 'href',
|
||||
target: hasRoute ? null : '_blank'
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
@ -30,7 +30,7 @@
|
||||
<ui-container>
|
||||
<template #header><fa :icon="['far', 'comment-alt']"/> {{ $t('timeline') }}</template>
|
||||
<div>
|
||||
<x-notes ref="timeline" :pagination="pagination" @inited="() => $emit('loaded')"/>
|
||||
<x-notes ref="timeline" :pagination="pagination" @inited="() => $emit('loaded')" :key="user.id"/>
|
||||
</div>
|
||||
</ui-container>
|
||||
</div>
|
||||
|
@ -22,6 +22,7 @@
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../../i18n';
|
||||
import Progress from '../../scripts/loading';
|
||||
import { faUserClock } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('common/views/pages/follow-requests.vue'),
|
||||
@ -31,6 +32,12 @@ export default Vue.extend({
|
||||
requests: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$emit('init', {
|
||||
title: this.$t('received-follow-requests'),
|
||||
icon: faUserClock
|
||||
});
|
||||
},
|
||||
mounted() {
|
||||
Progress.start();
|
||||
this.$root.api('following/requests/list').then(requests => {
|
||||
|
@ -5,7 +5,7 @@
|
||||
<section style="padding: 0 16px 0 16px;">
|
||||
<ui-input v-model="value.name"><template #prefix><fa :icon="faMagic"/></template><span>{{ $t('blocks._counter.name') }}</span></ui-input>
|
||||
<ui-input v-model="value.text"><span>{{ $t('blocks._counter.text') }}</span></ui-input>
|
||||
<ui-input v-model="value.inc" type="number"><span>{{ $t('blocks._counter.increment') }}</span></ui-input>
|
||||
<ui-input v-model="value.inc" type="number"><span>{{ $t('blocks._counter.inc') }}</span></ui-input>
|
||||
</section>
|
||||
</x-container>
|
||||
</template>
|
@ -19,7 +19,7 @@ import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faImage, faFolderOpen } from '@fortawesome/free-regular-svg-icons';
|
||||
import i18n from '../../../../../i18n';
|
||||
import XContainer from '../page-editor.container.vue';
|
||||
import XFileThumbnail from '../../drive-file-thumbnail.vue';
|
||||
import XFileThumbnail from '../../../components/drive-file-thumbnail.vue';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('pages'),
|
@ -11,7 +11,7 @@
|
||||
</header>
|
||||
|
||||
<section>
|
||||
<a class="view" v-if="pageId" :href="`/@${ author.username }/pages/${ currentName }`" target="_blank"><fa :icon="faExternalLinkSquareAlt"/> {{ $t('view-page') }}</a>
|
||||
<router-link class="view" v-if="pageId" :to="`/@${ author.username }/pages/${ currentName }`"><fa :icon="faExternalLinkSquareAlt"/> {{ $t('view-page') }}</router-link>
|
||||
|
||||
<ui-input v-model="title">
|
||||
<span>{{ $t('title') }}</span>
|
||||
@ -111,20 +111,25 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
props: {
|
||||
page: {
|
||||
type: Object,
|
||||
initPageId: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
initPageName: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
initUser: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
author: this.$store.state.i,
|
||||
readonly: false,
|
||||
page: null,
|
||||
pageId: null,
|
||||
currentName: null,
|
||||
title: '',
|
||||
@ -156,7 +161,7 @@ export default Vue.extend({
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
async created() {
|
||||
this.aiScript = new ASTypeChecker();
|
||||
|
||||
this.$watch('variables', () => {
|
||||
@ -167,6 +172,18 @@ export default Vue.extend({
|
||||
this.aiScript.pageVars = collectPageVars(this.content);
|
||||
}, { deep: true });
|
||||
|
||||
if (this.initPageId) {
|
||||
this.page = await this.$root.api('pages/show', {
|
||||
pageId: this.initPageId,
|
||||
});
|
||||
} else if (this.initPageName && this.initUser) {
|
||||
this.page = await this.$root.api('pages/show', {
|
||||
name: this.initPageName,
|
||||
username: this.initUser,
|
||||
});
|
||||
this.readonly = true;
|
||||
}
|
||||
|
||||
if (this.page) {
|
||||
this.author = this.page.user;
|
||||
this.pageId = this.page.id;
|
@ -1,11 +1,15 @@
|
||||
<template>
|
||||
<div class="">
|
||||
<div class="mrdgzndn">
|
||||
<mfm :text="text" :is-note="false" :i="$store.state.i" :key="text"/>
|
||||
|
||||
<mk-url-preview v-for="url in urls" :url="url" :key="url" class="url"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import { parse } from '../../../../../../mfm/parse';
|
||||
import { unique } from '../../../../../../prelude/array';
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
@ -23,6 +27,20 @@ export default Vue.extend({
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
urls(): string[] {
|
||||
if (this.text) {
|
||||
const ast = parse(this.text);
|
||||
// TODO: 再帰的にURL要素がないか調べる
|
||||
return unique(ast
|
||||
.filter(t => ((t.node.type == 'url' || t.node.type == 'link') && t.node.props.url && !t.node.props.silent))
|
||||
.map(t => t.node.props.url));
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.$watch('script.vars', () => {
|
||||
this.text = this.script.interpolate(this.value.text);
|
||||
@ -32,4 +50,13 @@ export default Vue.extend({
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.mrdgzndn
|
||||
&:not(:first-child)
|
||||
margin-top 0.5em
|
||||
|
||||
&:not(:last-child)
|
||||
margin-bottom 0.5em
|
||||
|
||||
> .url
|
||||
margin 0.5em 0
|
||||
</style>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div v-if="page" class="iroscrza" :class="{ shadow: $store.state.device.useShadow, round: $store.state.device.roundedCorners, center: page.alignCenter }" :style="{ fontFamily: page.font }">
|
||||
<div v-if="page" class="iroscrza" :class="{ shadow: $store.state.device.useShadow, round: $store.state.device.roundedCorners, center: page.alignCenter }" :style="{ fontFamily: page.font }" :key="path">
|
||||
<header>
|
||||
<div class="title">{{ page.title }}</div>
|
||||
</header>
|
||||
@ -25,7 +25,7 @@
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../../../i18n';
|
||||
import { faHeart as faHeartS } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faHeart } from '@fortawesome/free-regular-svg-icons';
|
||||
import { faHeart, faStickyNote } from '@fortawesome/free-regular-svg-icons';
|
||||
import XBlock from './page.block.vue';
|
||||
import { ASEvaluator } from '../../../../../../misc/aiscript/evaluator';
|
||||
import { collectPageVars } from '../../../scripts/collect-page-vars';
|
||||
@ -85,26 +85,46 @@ export default Vue.extend({
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
path(): string {
|
||||
return this.username + '/' + this.pageName;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
path() {
|
||||
this.fetch();
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.$root.api('pages/show', {
|
||||
name: this.pageName,
|
||||
username: this.username,
|
||||
}).then(page => {
|
||||
this.page = page;
|
||||
const pageVars = this.getPageVars();
|
||||
this.script = new Script(new ASEvaluator(this.page.variables, pageVars, {
|
||||
randomSeed: Math.random(),
|
||||
user: page.user,
|
||||
visitor: this.$store.state.i,
|
||||
page: page,
|
||||
url: url
|
||||
}), e => {
|
||||
console.dir(e);
|
||||
});
|
||||
});
|
||||
this.fetch();
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetch() {
|
||||
this.$root.api('pages/show', {
|
||||
name: this.pageName,
|
||||
username: this.username,
|
||||
}).then(page => {
|
||||
this.page = page;
|
||||
this.$emit('init', {
|
||||
title: this.page.title,
|
||||
icon: faStickyNote
|
||||
});
|
||||
const pageVars = this.getPageVars();
|
||||
this.script = new Script(new ASEvaluator(this.page.variables, pageVars, {
|
||||
randomSeed: Math.random(),
|
||||
user: page.user,
|
||||
visitor: this.$store.state.i,
|
||||
page: page,
|
||||
url: url
|
||||
}), e => {
|
||||
console.dir(e);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getPageVars() {
|
||||
return collectPageVars(this.page.content);
|
||||
},
|
||||
@ -148,8 +168,8 @@ export default Vue.extend({
|
||||
> .title
|
||||
z-index 1
|
||||
margin 0
|
||||
padding 32px 64px
|
||||
font-size 24px
|
||||
padding 16px 32px
|
||||
font-size 20px
|
||||
font-weight bold
|
||||
color var(--text)
|
||||
box-shadow 0 var(--lineWidth) rgba(#000, 0.07)
|
||||
@ -158,28 +178,40 @@ export default Vue.extend({
|
||||
padding 16px 32px
|
||||
font-size 20px
|
||||
|
||||
@media (max-width 400px)
|
||||
padding 10px 20px
|
||||
font-size 16px
|
||||
|
||||
> div
|
||||
color var(--text)
|
||||
padding 48px 64px
|
||||
font-size 18px
|
||||
padding 24px 32px
|
||||
font-size 16px
|
||||
|
||||
@media (max-width 600px)
|
||||
padding 24px 32px
|
||||
font-size 16px
|
||||
|
||||
@media (max-width 400px)
|
||||
padding 20px 20px
|
||||
font-size 15px
|
||||
|
||||
> footer
|
||||
color var(--text)
|
||||
padding 0 64px 38px 64px
|
||||
padding 0 32px 28px 32px
|
||||
|
||||
@media (max-width 600px)
|
||||
padding 0 32px 28px 32px
|
||||
|
||||
@media (max-width 400px)
|
||||
padding 0 20px 20px 20px
|
||||
font-size 14px
|
||||
|
||||
> small
|
||||
display block
|
||||
opacity 0.5
|
||||
|
||||
> a
|
||||
font-size 14px
|
||||
font-size 90%
|
||||
|
||||
> a + a
|
||||
margin-left 8px
|
||||
|
@ -7,6 +7,7 @@
|
||||
<ui-margin>
|
||||
<ui-button @click="rename"><fa :icon="faICursor"/> {{ $t('rename') }}</ui-button>
|
||||
<ui-button @click="del"><fa :icon="faTrashAlt"/> {{ $t('delete') }}</ui-button>
|
||||
<ui-button @click="transfer"><fa :icon="faCrown"/> {{ $t('transfer') }}</ui-button>
|
||||
</ui-margin>
|
||||
</section>
|
||||
</ui-container>
|
||||
@ -28,9 +29,10 @@
|
||||
<div>
|
||||
<header>
|
||||
<b><mk-user-name :user="user"/></b>
|
||||
<span class="is-owner" v-if="group.ownerId === user.id">owner</span>
|
||||
<span class="username">@{{ user | acct }}</span>
|
||||
</header>
|
||||
<div>
|
||||
<div v-if="group.ownerId !== user.id">
|
||||
<a @click="remove(user)">{{ $t('remove-user') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
@ -44,7 +46,7 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../../i18n';
|
||||
import { faICursor, faUsers, faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faCrown, faICursor, faUsers, faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faTrashAlt } from '@fortawesome/free-regular-svg-icons';
|
||||
|
||||
export default Vue.extend({
|
||||
@ -60,7 +62,7 @@ export default Vue.extend({
|
||||
return {
|
||||
group: null,
|
||||
users: [],
|
||||
faICursor, faTrashAlt, faUsers, faPlus
|
||||
faCrown, faICursor, faTrashAlt, faUsers, faPlus
|
||||
};
|
||||
},
|
||||
|
||||
@ -78,6 +80,14 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetchGroup() {
|
||||
this.$root.api('users/groups/show', {
|
||||
groupId: this.group.id
|
||||
}).then(group => {
|
||||
this.group = group;
|
||||
})
|
||||
},
|
||||
|
||||
fetchUsers() {
|
||||
this.$root.api('users/show', {
|
||||
userIds: this.group.userIds
|
||||
@ -97,8 +107,15 @@ export default Vue.extend({
|
||||
this.$root.api('users/groups/update', {
|
||||
groupId: this.group.id,
|
||||
name: name
|
||||
}).then(() => {
|
||||
this.fetchGroup();
|
||||
}).catch(e => {
|
||||
this.$root.dialog({
|
||||
type: 'error',
|
||||
text: e
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
del() {
|
||||
@ -130,7 +147,13 @@ export default Vue.extend({
|
||||
groupId: this.group.id,
|
||||
userId: user.id
|
||||
}).then(() => {
|
||||
this.fetchGroup();
|
||||
this.fetchUsers();
|
||||
}).catch(e => {
|
||||
this.$root.dialog({
|
||||
type: 'error',
|
||||
text: e
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
@ -150,6 +173,43 @@ export default Vue.extend({
|
||||
type: 'success',
|
||||
text: t
|
||||
});
|
||||
}).catch(e => {
|
||||
this.$root.dialog({
|
||||
type: 'error',
|
||||
text: e
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
async transfer() {
|
||||
const { result: user } = await this.$root.dialog({
|
||||
user: {
|
||||
local: true
|
||||
}
|
||||
});
|
||||
if (user == null) return;
|
||||
|
||||
this.$root.dialog({
|
||||
type: 'warning',
|
||||
text: this.$t('transfer-are-you-sure').replace('$1', this.group.name).replace('$2', user.username),
|
||||
showCancelButton: true
|
||||
}).then(({ canceled }) => {
|
||||
if (canceled) return;
|
||||
|
||||
this.$root.api('users/groups/transfer', {
|
||||
groupId: this.group.id,
|
||||
userId: user.id
|
||||
}).then(() => {
|
||||
this.$root.dialog({
|
||||
type: 'success',
|
||||
text: this.$t('transferred')
|
||||
});
|
||||
}).catch(e => {
|
||||
this.$root.dialog({
|
||||
type: 'error',
|
||||
text: e
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -179,6 +239,16 @@ export default Vue.extend({
|
||||
> header
|
||||
color var(--text)
|
||||
|
||||
> .is-owner
|
||||
flex-shrink 0
|
||||
align-self center
|
||||
margin-left 8px
|
||||
padding 1px 6px
|
||||
font-size 80%
|
||||
background var(--groupUserListOwnerBg)
|
||||
color var(--groupUserListOwnerFg)
|
||||
border-radius 3px
|
||||
|
||||
> .username
|
||||
margin-left 8px
|
||||
opacity 0.7
|
||||
|
@ -103,6 +103,10 @@ export default Vue.extend({
|
||||
});
|
||||
this.$root.api('i/user-group-invites').then(invites => {
|
||||
this.invites = invites;
|
||||
}).then(() => {
|
||||
this.$root.api('users/groups/joined').then(groups => {
|
||||
this.joinedGroups = groups;
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -3,6 +3,7 @@
|
||||
<p>Maintainer: <b><a :href="'mailto:' + meta.maintainerEmail" target="_blank">{{ meta.maintainerName }}</a></b></p>
|
||||
<p>Machine: {{ meta.machine }}</p>
|
||||
<p>Node: {{ meta.node }}</p>
|
||||
<p>PSQL: {{ meta.psql }}</p>
|
||||
<p>Version: {{ meta.version }} </p>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -146,6 +146,7 @@ init(async (launch, os) => {
|
||||
{ path: '/i/lists/:listId', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/user-list-editor.vue').then(m => m.default), listId: route.params.listId }) },
|
||||
{ path: '/i/groups', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/user-groups.vue').then(m => m.default) }) },
|
||||
{ path: '/i/groups/:groupId', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/user-group-editor.vue').then(m => m.default), groupId: route.params.groupId }) },
|
||||
{ path: '/i/follow-requests', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/follow-requests.vue').then(m => m.default) }) },
|
||||
]}
|
||||
: { path: '/', component: MkHome, children: [
|
||||
{ path: '', name: 'index', component: MkHomeTimeline },
|
||||
@ -167,11 +168,15 @@ init(async (launch, os) => {
|
||||
{ path: '/i/groups', component: () => import('../common/views/pages/user-groups.vue').then(m => m.default) },
|
||||
{ path: '/i/groups/:groupId', props: true, component: () => import('../common/views/pages/user-group-editor.vue').then(m => m.default) },
|
||||
{ path: '/i/follow-requests', component: () => import('../common/views/pages/follow-requests.vue').then(m => m.default) },
|
||||
{ path: '/i/pages/new', component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default) },
|
||||
{ path: '/i/pages/edit/:pageId', component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default), props: route => ({ initPageId: route.params.pageId }) },
|
||||
{ path: '/@:user/pages/:page', component: () => import('../common/views/pages/page/page.vue').then(m => m.default), props: route => ({ pageName: route.params.page, username: route.params.user }) },
|
||||
{ path: '/@:user/pages/:pageName/view-source', component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default), props: route => ({ initUser: route.params.user, initPageName: route.params.pageName }) },
|
||||
]},
|
||||
{ path: '/@:user/pages/:page', props: true, component: () => import('./views/pages/page.vue').then(m => m.default) },
|
||||
{ path: '/@:user/pages/:pageName/view-source', props: true, component: () => import('./views/pages/page-editor.vue').then(m => m.default) },
|
||||
{ path: '/i/pages/new', component: () => import('./views/pages/page-editor.vue').then(m => m.default) },
|
||||
{ path: '/i/pages/edit/:pageId', props: true, component: () => import('./views/pages/page-editor.vue').then(m => m.default) },
|
||||
{ path: '/i/pages/new', component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default) },
|
||||
{ path: '/i/pages/edit/:pageId', component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default), props: route => ({ initPageId: route.params.pageId }) },
|
||||
{ path: '/@:user/pages/:page', component: () => import('../common/views/pages/page/page.vue').then(m => m.default), props: route => ({ pageName: route.params.page, username: route.params.user }) },
|
||||
{ path: '/@:user/pages/:pageName/view-source', component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default), props: route => ({ initUser: route.params.user, initPageName: route.params.pageName }) },
|
||||
{ path: '/i/messaging/group/:group', component: MkMessagingRoom },
|
||||
{ path: '/i/messaging/:user', component: MkMessagingRoom },
|
||||
{ path: '/i/drive', component: MkDrive },
|
||||
|
@ -11,7 +11,7 @@
|
||||
<div class="weekday"
|
||||
v-for="(day, i) in Array(7).fill(0)"
|
||||
:data-today="year == today.getFullYear() && month == today.getMonth() + 1 && today.getDay() == i"
|
||||
:data-is-donichi="i == 0 || i == 6"
|
||||
:data-is-weekend="i == 0 || i == 6"
|
||||
>{{ weekdayText[i] }}</div>
|
||||
</template>
|
||||
<div v-for="n in paddingDays"></div>
|
||||
@ -19,7 +19,7 @@
|
||||
:data-today="isToday(i + 1)"
|
||||
:data-selected="isSelected(i + 1)"
|
||||
:data-is-out-of-range="isOutOfRange(i + 1)"
|
||||
:data-is-donichi="isDonichi(i + 1)"
|
||||
:data-is-weekend="isWeekend(i + 1)"
|
||||
@click="go(i + 1)"
|
||||
:title="isOutOfRange(i + 1) ? null : $t('go')"
|
||||
>
|
||||
@ -96,7 +96,7 @@ export default Vue.extend({
|
||||
(this.start ? test < (this.start as any).getTime() : false);
|
||||
},
|
||||
|
||||
isDonichi(day) {
|
||||
isWeekend(day) {
|
||||
const weekday = (new Date(this.year, this.month - 1, day)).getDay();
|
||||
return weekday == 0 || weekday == 6;
|
||||
},
|
||||
@ -199,14 +199,14 @@ export default Vue.extend({
|
||||
&.weekday
|
||||
color var(--calendarWeek)
|
||||
|
||||
&[data-is-donichi]
|
||||
&[data-is-weekend]
|
||||
color var(--calendarSaturdayOrSunday)
|
||||
|
||||
&[data-today]
|
||||
box-shadow 0 0 0 var(--lineWidth) var(--calendarWeek) inset
|
||||
border-radius 6px
|
||||
|
||||
&[data-is-donichi]
|
||||
&[data-is-weekend]
|
||||
box-shadow 0 0 0 var(--lineWidth) var(--calendarSaturdayOrSunday) inset
|
||||
|
||||
&.day
|
||||
@ -222,7 +222,7 @@ export default Vue.extend({
|
||||
&:active > div
|
||||
background var(--faceClearButtonActive)
|
||||
|
||||
&[data-is-donichi]
|
||||
&[data-is-weekend]
|
||||
color var(--calendarSaturdayOrSunday)
|
||||
|
||||
&[data-is-out-of-range]
|
||||
|
@ -104,18 +104,18 @@
|
||||
<mk-user-name :user="notification.note.user"/>
|
||||
</router-link>
|
||||
</p>
|
||||
<a class="note-preview" :href="notification.note | notePage" :title="getNoteSummary(notification.note)">
|
||||
<router-link class="note-preview" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
|
||||
<mfm :text="getNoteSummary(notification.note)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.emojis"/>
|
||||
</a>
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="notification.type == 'pollVote'">
|
||||
<mk-avatar class="avatar" :user="notification.user"/>
|
||||
<div class="text">
|
||||
<p><fa icon="chart-pie"/><a :href="notification.user | userPage" v-user-preview="notification.user.id">
|
||||
<p><fa icon="chart-pie"/><router-link :to="notification.user | userPage" v-user-preview="notification.user.id">
|
||||
<mk-user-name :user="notification.user"/>
|
||||
</a></p>
|
||||
</router-link></p>
|
||||
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
|
||||
<fa icon="quote-left"/>
|
||||
<mfm :text="getNoteSummary(notification.note)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.emojis"/>
|
||||
|
@ -10,14 +10,15 @@
|
||||
<span v-for="u in visibleUsers">
|
||||
<mk-user-name :user="u"/><a @click="removeVisibleUser(u)">[x]</a>
|
||||
</span>
|
||||
<a @click="addVisibleUser">{{ $t('add-visible-user') }}</a>
|
||||
<a @click="addVisibleUser">{{ $t('@.post-form.add-visible-user') }}</a>
|
||||
</div>
|
||||
<div class="hashtags" v-if="recentHashtags.length > 0 && $store.state.settings.suggestRecentHashtags">
|
||||
<b>{{ $t('recent-tags') }}:</b>
|
||||
<a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)" :title="$t('click-to-tagging')">#{{ tag }}</a>
|
||||
<b>{{ $t('@.post-form.recent-tags') }}:</b>
|
||||
<a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)" :title="$t('@.post-form.click-to-tagging')">#{{ tag }}</a>
|
||||
</div>
|
||||
<div class="local-only" v-if="localOnly == true">{{ $t('local-only-message') }}</div>
|
||||
<input v-show="useCw" ref="cw" v-model="cw" :placeholder="$t('annotations')" v-autocomplete="{ model: 'cw' }">
|
||||
<div class="with-quote" v-if="quoteId">{{ $t('@.post-form.quote-attached') }}</div>
|
||||
<div class="local-only" v-if="localOnly == true">{{ $t('@.post-form.local-only-message') }}</div>
|
||||
<input v-show="useCw" ref="cw" v-model="cw" :placeholder="$t('@.post-form.cw-placeholder')" v-autocomplete="{ model: 'cw' }">
|
||||
<div class="textarea">
|
||||
<textarea :class="{ with: (files.length != 0 || poll) }"
|
||||
ref="text" v-model="text" :disabled="posting"
|
||||
@ -32,13 +33,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<mk-uploader ref="uploader" @uploaded="attachMedia" @change="onChangeUploadings"/>
|
||||
<button class="upload" :title="$t('attach-media-from-local')" @click="chooseFile"><fa icon="upload"/></button>
|
||||
<button class="drive" :title="$t('attach-media-from-drive')" @click="chooseFileFromDrive"><fa icon="cloud"/></button>
|
||||
<button class="kao" :title="$t('insert-a-kao')" @click="kao"><fa :icon="['far', 'smile']"/></button>
|
||||
<button class="poll" :title="$t('create-poll')" @click="poll = !poll"><fa icon="chart-pie"/></button>
|
||||
<button class="cw" :title="$t('hide-contents')" @click="useCw = !useCw"><fa :icon="['far', 'eye-slash']"/></button>
|
||||
<button class="geo" :title="$t('attach-location-information')" @click="geo ? removeGeo() : setGeo()"><fa icon="map-marker-alt"/></button>
|
||||
<button class="visibility" :title="$t('visibility')" @click="setVisibility" ref="visibilityButton">
|
||||
<button class="upload" :title="$t('@.post-form.attach-media-from-local')" @click="chooseFile"><fa icon="upload"/></button>
|
||||
<button class="drive" :title="$t('@.post-form.attach-media-from-drive')" @click="chooseFileFromDrive"><fa icon="cloud"/></button>
|
||||
<button class="kao" :title="$t('@.post-form.insert-a-kao')" @click="kao"><fa :icon="['far', 'smile']"/></button>
|
||||
<button class="poll" :title="$t('@.post-form.create-poll')" @click="poll = !poll"><fa icon="chart-pie"/></button>
|
||||
<button class="cw" :title="$t('@.post-form.hide-contents')" @click="useCw = !useCw"><fa :icon="['far', 'eye-slash']"/></button>
|
||||
<button class="geo" :title="$t('@.post-form.attach-location-information')" @click="geo ? removeGeo() : setGeo()"><fa icon="map-marker-alt"/></button>
|
||||
<button class="visibility" :title="$t('@.post-form.visibility')" @click="setVisibility" ref="visibilityButton">
|
||||
<span v-if="visibility === 'public'"><fa icon="globe"/></span>
|
||||
<span v-if="visibility === 'home'"><fa icon="home"/></span>
|
||||
<span v-if="visibility === 'followers'"><fa icon="unlock"/></span>
|
||||
@ -46,7 +47,7 @@
|
||||
</button>
|
||||
<p class="text-count" :class="{ over: trimmedLength(text) > maxNoteTextLength }">{{ maxNoteTextLength - trimmedLength(text) }}</p>
|
||||
<ui-button primary :wait="posting" class="submit" :disabled="!canPost" @click="post">
|
||||
{{ posting ? $t('posting') : submitText }}<mk-ellipsis v-if="posting"/>
|
||||
{{ posting ? $t('@.post-form.posting') : submitText }}<mk-ellipsis v-if="posting"/>
|
||||
</ui-button>
|
||||
<input ref="file" type="file" multiple="multiple" tabindex="-1" @change="onChangeFile"/>
|
||||
<div class="dropzone" v-if="draghover"></div>
|
||||
@ -56,465 +57,29 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../../i18n';
|
||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||
import getFace from '../../../common/scripts/get-face';
|
||||
import MkVisibilityChooser from '../../../common/views/components/visibility-chooser.vue';
|
||||
import { parse } from '../../../../../mfm/parse';
|
||||
import { host } from '../../../config';
|
||||
import { erase, unique } from '../../../../../prelude/array';
|
||||
import { length } from 'stringz';
|
||||
import { toASCII } from 'punycode';
|
||||
import extractMentions from '../../../../../misc/extract-mentions';
|
||||
import XPostFormAttaches from '../../../common/views/components/post-form-attaches.vue';
|
||||
import form from '../../../common/scripts/post-form';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('desktop/views/components/post-form.vue'),
|
||||
|
||||
components: {
|
||||
MkVisibilityChooser,
|
||||
XPostFormAttaches,
|
||||
XPollEditor: () => import('../../../common/views/components/poll-editor.vue').then(m => m.default)
|
||||
},
|
||||
|
||||
props: {
|
||||
reply: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
renote: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
mention: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
initialText: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
instant: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
posting: false,
|
||||
text: '',
|
||||
files: [],
|
||||
uploadings: [],
|
||||
poll: false,
|
||||
pollChoices: [],
|
||||
pollMultiple: false,
|
||||
pollExpiration: [],
|
||||
useCw: false,
|
||||
cw: null,
|
||||
geo: null,
|
||||
visibility: 'public',
|
||||
visibleUsers: [],
|
||||
localOnly: false,
|
||||
autocomplete: null,
|
||||
draghover: false,
|
||||
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'),
|
||||
maxNoteTextLength: 1000
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
this.$root.getMeta().then(meta => {
|
||||
this.maxNoteTextLength = meta.maxNoteTextLength;
|
||||
});
|
||||
},
|
||||
|
||||
computed: {
|
||||
draftId(): string {
|
||||
return this.renote
|
||||
? `renote:${this.renote.id}`
|
||||
: this.reply
|
||||
? `reply:${this.reply.id}`
|
||||
: 'note';
|
||||
},
|
||||
|
||||
placeholder(): string {
|
||||
const xs = [
|
||||
this.$t('@.note-placeholders.a'),
|
||||
this.$t('@.note-placeholders.b'),
|
||||
this.$t('@.note-placeholders.c'),
|
||||
this.$t('@.note-placeholders.d'),
|
||||
this.$t('@.note-placeholders.e'),
|
||||
this.$t('@.note-placeholders.f')
|
||||
];
|
||||
const x = xs[Math.floor(Math.random() * xs.length)];
|
||||
|
||||
return this.renote
|
||||
? this.$t('quote-placeholder')
|
||||
: this.reply
|
||||
? this.$t('reply-placeholder')
|
||||
: x;
|
||||
},
|
||||
|
||||
submitText(): string {
|
||||
return this.renote
|
||||
? this.$t('renote')
|
||||
: this.reply
|
||||
? this.$t('reply')
|
||||
: this.$t('submit');
|
||||
},
|
||||
|
||||
canPost(): boolean {
|
||||
return !this.posting &&
|
||||
(1 <= this.text.length || 1 <= this.files.length || this.poll || this.renote) &&
|
||||
(length(this.text.trim()) <= this.maxNoteTextLength) &&
|
||||
(!this.poll || this.pollChoices.length >= 2);
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.initialText) {
|
||||
this.text = this.initialText;
|
||||
}
|
||||
|
||||
if (this.mention) {
|
||||
this.text = this.mention.host ? `@${this.mention.username}@${toASCII(this.mention.host)}` : `@${this.mention.username}`;
|
||||
this.text += ' ';
|
||||
}
|
||||
|
||||
if (this.reply && this.reply.user.host != null) {
|
||||
this.text = `@${this.reply.user.username}@${toASCII(this.reply.user.host)} `;
|
||||
}
|
||||
|
||||
if (this.reply && this.reply.text != null) {
|
||||
const ast = parse(this.reply.text);
|
||||
|
||||
for (const x of extractMentions(ast)) {
|
||||
const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`;
|
||||
|
||||
// 自分は除外
|
||||
if (this.$store.state.i.username == x.username && x.host == null) continue;
|
||||
if (this.$store.state.i.username == x.username && x.host == host) continue;
|
||||
|
||||
// 重複は除外
|
||||
if (this.text.indexOf(`${mention} `) != -1) continue;
|
||||
|
||||
this.text += `${mention} `;
|
||||
mixins: [
|
||||
form({
|
||||
onSuccess: self => {
|
||||
self.$notify(self.renote
|
||||
? self.$t('reposted')
|
||||
: self.reply
|
||||
? self.$t('replied')
|
||||
: self.$t('posted'));
|
||||
},
|
||||
onFailure: self => {
|
||||
self.$notify(self.renote
|
||||
? self.$t('renote-failed')
|
||||
: self.reply
|
||||
? self.$t('reply-failed')
|
||||
: self.$t('note-failed'));
|
||||
}
|
||||
}
|
||||
|
||||
// デフォルト公開範囲
|
||||
this.applyVisibility(this.$store.state.settings.rememberNoteVisibility ? (this.$store.state.device.visibility || this.$store.state.settings.defaultNoteVisibility) : this.$store.state.settings.defaultNoteVisibility);
|
||||
|
||||
// 公開以外へのリプライ時は元の公開範囲を引き継ぐ
|
||||
if (this.reply && ['home', 'followers', 'specified'].includes(this.reply.visibility)) {
|
||||
this.visibility = this.reply.visibility;
|
||||
}
|
||||
|
||||
if (this.reply) {
|
||||
this.$root.api('users/show', { userId: this.reply.userId }).then(user => {
|
||||
this.visibleUsers.push(user);
|
||||
});
|
||||
}
|
||||
|
||||
// keep cw when reply
|
||||
if (this.$store.state.settings.keepCw && this.reply && this.reply.cw) {
|
||||
this.useCw = true;
|
||||
this.cw = this.reply.cw;
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
// 書きかけの投稿を復元
|
||||
if (!this.instant && !this.mention) {
|
||||
const draft = JSON.parse(localStorage.getItem('drafts') || '{}')[this.draftId];
|
||||
if (draft) {
|
||||
this.text = draft.data.text;
|
||||
this.files = (draft.data.files || []).filter(e => e);
|
||||
if (draft.data.poll) {
|
||||
this.poll = true;
|
||||
this.$nextTick(() => {
|
||||
(this.$refs.poll as any).set(draft.data.poll);
|
||||
});
|
||||
}
|
||||
this.$emit('change-attached-files', this.files);
|
||||
}
|
||||
}
|
||||
|
||||
this.$nextTick(() => this.watch());
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
trimmedLength(text: string) {
|
||||
return length(text.trim());
|
||||
},
|
||||
|
||||
addTag(tag: string) {
|
||||
insertTextAtCursor(this.$refs.text, ` #${tag} `);
|
||||
},
|
||||
|
||||
watch() {
|
||||
this.$watch('text', () => this.saveDraft());
|
||||
this.$watch('poll', () => this.saveDraft());
|
||||
this.$watch('files', () => this.saveDraft());
|
||||
},
|
||||
|
||||
focus() {
|
||||
(this.$refs.text as any).focus();
|
||||
},
|
||||
|
||||
chooseFile() {
|
||||
(this.$refs.file as any).click();
|
||||
},
|
||||
|
||||
chooseFileFromDrive() {
|
||||
this.$chooseDriveFile({
|
||||
multiple: true
|
||||
}).then(files => {
|
||||
for (const x of files) this.attachMedia(x);
|
||||
});
|
||||
},
|
||||
|
||||
attachMedia(driveFile) {
|
||||
this.files.push(driveFile);
|
||||
this.$emit('change-attached-files', this.files);
|
||||
},
|
||||
|
||||
detachMedia(id) {
|
||||
this.files = this.files.filter(x => x.id != id);
|
||||
this.$emit('change-attached-files', this.files);
|
||||
},
|
||||
|
||||
onChangeFile() {
|
||||
for (const x of Array.from((this.$refs.file as any).files)) this.upload(x);
|
||||
},
|
||||
|
||||
onPollUpdate() {
|
||||
const got = this.$refs.poll.get();
|
||||
this.pollChoices = got.choices;
|
||||
this.pollMultiple = got.multiple;
|
||||
this.pollExpiration = [got.expiration, got.expiresAt || got.expiredAfter];
|
||||
this.saveDraft();
|
||||
},
|
||||
|
||||
upload(file) {
|
||||
(this.$refs.uploader as any).upload(file);
|
||||
},
|
||||
|
||||
onChangeUploadings(uploads) {
|
||||
this.$emit('change-uploadings', uploads);
|
||||
},
|
||||
|
||||
clear() {
|
||||
this.text = '';
|
||||
this.files = [];
|
||||
this.poll = false;
|
||||
this.$emit('change-attached-files', this.files);
|
||||
},
|
||||
|
||||
onKeydown(e) {
|
||||
if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey) && this.canPost) this.post();
|
||||
},
|
||||
|
||||
onPaste(e) {
|
||||
for (const item of Array.from(e.clipboardData.items)) {
|
||||
if (item.kind == 'file') {
|
||||
this.upload(item.getAsFile());
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onDragover(e) {
|
||||
const isFile = e.dataTransfer.items[0].kind == 'file';
|
||||
const isDriveFile = e.dataTransfer.types[0] == 'mk_drive_file';
|
||||
if (isFile || isDriveFile) {
|
||||
e.preventDefault();
|
||||
this.draghover = true;
|
||||
e.dataTransfer.dropEffect = e.dataTransfer.effectAllowed == 'all' ? 'copy' : 'move';
|
||||
}
|
||||
},
|
||||
|
||||
onDragenter(e) {
|
||||
this.draghover = true;
|
||||
},
|
||||
|
||||
onDragleave(e) {
|
||||
this.draghover = false;
|
||||
},
|
||||
|
||||
onDrop(e): void {
|
||||
this.draghover = false;
|
||||
|
||||
// ファイルだったら
|
||||
if (e.dataTransfer.files.length > 0) {
|
||||
e.preventDefault();
|
||||
for (const x of Array.from(e.dataTransfer.files)) this.upload(x);
|
||||
return;
|
||||
}
|
||||
|
||||
//#region ドライブのファイル
|
||||
const driveFile = e.dataTransfer.getData('mk_drive_file');
|
||||
if (driveFile != null && driveFile != '') {
|
||||
const file = JSON.parse(driveFile);
|
||||
this.files.push(file);
|
||||
this.$emit('change-attached-files', this.files);
|
||||
e.preventDefault();
|
||||
}
|
||||
//#endregion
|
||||
},
|
||||
|
||||
setGeo() {
|
||||
if (navigator.geolocation == null) {
|
||||
this.$root.dialog({
|
||||
type: 'warning',
|
||||
text: this.$t('geolocation-alert')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.geolocation.getCurrentPosition(pos => {
|
||||
this.geo = pos.coords;
|
||||
this.$emit('geo-attached', this.geo);
|
||||
}, err => {
|
||||
this.$root.dialog({
|
||||
type: 'error',
|
||||
title: this.$t('error'),
|
||||
text: err.message
|
||||
});
|
||||
}, {
|
||||
enableHighAccuracy: true
|
||||
});
|
||||
},
|
||||
|
||||
removeGeo() {
|
||||
this.geo = null;
|
||||
this.$emit('geo-dettached');
|
||||
},
|
||||
|
||||
setVisibility() {
|
||||
const w = this.$root.new(MkVisibilityChooser, {
|
||||
source: this.$refs.visibilityButton,
|
||||
currentVisibility: this.visibility
|
||||
});
|
||||
w.$once('chosen', v => {
|
||||
this.applyVisibility(v);
|
||||
});
|
||||
},
|
||||
|
||||
applyVisibility(v :string) {
|
||||
const m = v.match(/^local-(.+)/);
|
||||
if (m) {
|
||||
this.localOnly = true;
|
||||
this.visibility = m[1];
|
||||
} else {
|
||||
this.localOnly = false;
|
||||
this.visibility = v;
|
||||
}
|
||||
},
|
||||
|
||||
addVisibleUser() {
|
||||
this.$root.dialog({
|
||||
title: this.$t('enter-username'),
|
||||
user: true
|
||||
}).then(({ canceled, result: user }) => {
|
||||
if (canceled) return;
|
||||
this.visibleUsers.push(user);
|
||||
});
|
||||
},
|
||||
|
||||
removeVisibleUser(user) {
|
||||
this.visibleUsers = erase(user, this.visibleUsers);
|
||||
},
|
||||
|
||||
async emoji() {
|
||||
const Picker = await import('./emoji-picker-dialog.vue').then(m => m.default);
|
||||
const button = this.$refs.emoji;
|
||||
const rect = button.getBoundingClientRect();
|
||||
const vm = this.$root.new(Picker, {
|
||||
x: button.offsetWidth + rect.left + window.pageXOffset,
|
||||
y: rect.top + window.pageYOffset
|
||||
});
|
||||
vm.$once('chosen', emoji => {
|
||||
insertTextAtCursor(this.$refs.text, emoji);
|
||||
});
|
||||
},
|
||||
|
||||
post() {
|
||||
this.posting = true;
|
||||
|
||||
this.$root.api('notes/create', {
|
||||
text: this.text == '' ? undefined : this.text,
|
||||
fileIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
|
||||
replyId: this.reply ? this.reply.id : undefined,
|
||||
renoteId: this.renote ? this.renote.id : undefined,
|
||||
poll: this.poll ? (this.$refs.poll as any).get() : undefined,
|
||||
cw: this.useCw ? this.cw || '' : undefined,
|
||||
visibility: this.visibility,
|
||||
visibleUserIds: this.visibility == 'specified' ? this.visibleUsers.map(u => u.id) : undefined,
|
||||
localOnly: this.localOnly,
|
||||
geo: this.geo ? {
|
||||
coordinates: [this.geo.longitude, this.geo.latitude],
|
||||
altitude: this.geo.altitude,
|
||||
accuracy: this.geo.accuracy,
|
||||
altitudeAccuracy: this.geo.altitudeAccuracy,
|
||||
heading: isNaN(this.geo.heading) ? null : this.geo.heading,
|
||||
speed: this.geo.speed,
|
||||
} : null
|
||||
}).then(data => {
|
||||
this.clear();
|
||||
this.deleteDraft();
|
||||
this.$emit('posted');
|
||||
this.$notify(this.renote
|
||||
? this.$t('reposted')
|
||||
: this.reply
|
||||
? this.$t('replied')
|
||||
: this.$t('posted'));
|
||||
}).catch(err => {
|
||||
this.$notify(this.renote
|
||||
? this.$t('renote-failed')
|
||||
: this.reply
|
||||
? this.$t('reply-failed')
|
||||
: this.$t('note-failed'));
|
||||
}).then(() => {
|
||||
this.posting = false;
|
||||
});
|
||||
|
||||
if (this.text && this.text != '') {
|
||||
const hashtags = parse(this.text).filter(x => x.node.type === 'hashtag').map(x => x.node.props.hashtag);
|
||||
const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[];
|
||||
localStorage.setItem('hashtags', JSON.stringify(unique(hashtags.concat(history))));
|
||||
}
|
||||
},
|
||||
|
||||
saveDraft() {
|
||||
if (this.instant) return;
|
||||
|
||||
const data = JSON.parse(localStorage.getItem('drafts') || '{}');
|
||||
|
||||
data[this.draftId] = {
|
||||
updatedAt: new Date(),
|
||||
data: {
|
||||
text: this.text,
|
||||
files: this.files,
|
||||
poll: this.poll && this.$refs.poll ? (this.$refs.poll as any).get() : undefined
|
||||
}
|
||||
}
|
||||
|
||||
localStorage.setItem('drafts', JSON.stringify(data));
|
||||
},
|
||||
|
||||
deleteDraft() {
|
||||
const data = JSON.parse(localStorage.getItem('drafts') || '{}');
|
||||
|
||||
delete data[this.draftId];
|
||||
|
||||
localStorage.setItem('drafts', JSON.stringify(data));
|
||||
},
|
||||
|
||||
kao() {
|
||||
this.text += getFace();
|
||||
},
|
||||
}
|
||||
}),
|
||||
],
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -17,20 +17,15 @@ import Progress from '../../../common/scripts/loading';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('desktop/views/pages/tag.vue'),
|
||||
data() {
|
||||
return {
|
||||
pagination: {
|
||||
computed: {
|
||||
pagination() {
|
||||
return {
|
||||
endpoint: 'notes/search-by-tag',
|
||||
limit: 20,
|
||||
params: {
|
||||
tag: this.$route.params.tag
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.$refs.timeline.reload();
|
||||
};
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -1,67 +0,0 @@
|
||||
<template>
|
||||
<mk-ui>
|
||||
<main>
|
||||
<x-page-editor v-if="page !== undefined" :page="page" :readonly="readonly"/>
|
||||
</main>
|
||||
</mk-ui>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
XPageEditor: () => import('../../../common/views/components/page-editor/page-editor.vue').then(m => m.default)
|
||||
},
|
||||
|
||||
props: {
|
||||
pageId: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
pageName: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
user: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
page: undefined,
|
||||
readonly: false
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
if (this.pageId) {
|
||||
this.$root.api('pages/show', {
|
||||
pageId: this.pageId,
|
||||
}).then(page => {
|
||||
this.page = page;
|
||||
});
|
||||
} else if (this.pageName && this.user) {
|
||||
this.$root.api('pages/show', {
|
||||
name: this.pageName,
|
||||
username: this.user,
|
||||
}).then(page => {
|
||||
this.readonly = true;
|
||||
this.page = page;
|
||||
});
|
||||
} else {
|
||||
this.page = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
main
|
||||
margin 0 auto
|
||||
padding 16px
|
||||
max-width 900px
|
||||
|
||||
</style>
|
@ -1,36 +0,0 @@
|
||||
<template>
|
||||
<mk-ui>
|
||||
<main>
|
||||
<x-page :page-name="page" :username="user"/>
|
||||
</main>
|
||||
</mk-ui>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
XPage: () => import('../../../common/views/pages/page/page.vue').then(m => m.default)
|
||||
},
|
||||
|
||||
props: {
|
||||
page: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
user: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
main
|
||||
margin 0 auto
|
||||
padding 16px
|
||||
max-width 950px
|
||||
|
||||
</style>
|
@ -13,7 +13,7 @@
|
||||
<div class="body">
|
||||
<div class="main block">
|
||||
<div>
|
||||
<h1 v-if="name != null">{{ name }}</h1>
|
||||
<h1 v-if="name != null && name != ''">{{ name }}</h1>
|
||||
<h1 v-else><img svg-inline src="../../../../assets/title.svg" alt="Misskey"></h1>
|
||||
|
||||
<div class="info">
|
||||
|
@ -282,7 +282,7 @@ export default class MiOS extends EventEmitter {
|
||||
// トークンが再生成されたとき
|
||||
// このままではMisskeyが利用できないので強制的にサインアウトさせる
|
||||
main.on('myTokenRegenerated', () => {
|
||||
alert(locale['common']['my-token-regenerated'])
|
||||
alert(locale['common']['my-token-regenerated']);
|
||||
this.signout();
|
||||
});
|
||||
}
|
||||
|
@ -128,6 +128,7 @@ init((launch, os) => {
|
||||
{ path: '/i/lists/:listId', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/user-list-editor.vue').then(m => m.default), listId: route.params.listId }) },
|
||||
{ path: '/i/groups', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/user-groups.vue').then(m => m.default) }) },
|
||||
{ path: '/i/groups/:groupId', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/user-group-editor.vue').then(m => m.default), groupId: route.params.groupId }) },
|
||||
{ path: '/i/follow-requests', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/follow-requests.vue').then(m => m.default) }) },
|
||||
]}]
|
||||
: [
|
||||
{ path: '/', name: 'index', component: MkIndex },
|
||||
@ -148,8 +149,8 @@ init((launch, os) => {
|
||||
{ path: '/i/drive', name: 'drive', component: MkDrive },
|
||||
{ path: '/i/drive/folder/:folder', component: MkDrive },
|
||||
{ path: '/i/drive/file/:file', component: MkDrive },
|
||||
{ path: '/i/pages/new', component: () => import('./views/pages/page-editor.vue').then(m => m.default) },
|
||||
{ path: '/i/pages/edit/:pageId', props: true, component: () => import('./views/pages/page-editor.vue').then(m => m.default) },
|
||||
{ path: '/i/pages/new', component: UI, props: route => ({ component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default) }) },
|
||||
{ path: '/i/pages/edit/:pageId', component: UI, props: route => ({ component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default), initPageId: route.params.pageId }) },
|
||||
{ path: '/selectdrive', component: MkSelectDrive },
|
||||
{ path: '/search', component: MkSearch },
|
||||
{ path: '/tags/:tag', component: MkTag },
|
||||
@ -162,8 +163,8 @@ init((launch, os) => {
|
||||
{ path: 'following', component: () => import('../common/views/pages/following.vue').then(m => m.default) },
|
||||
{ path: 'followers', component: () => import('../common/views/pages/followers.vue').then(m => m.default) },
|
||||
]},
|
||||
{ path: '/@:user/pages/:page', props: true, component: () => import('./views/pages/page.vue').then(m => m.default) },
|
||||
{ path: '/@:user/pages/:pageName/view-source', props: true, component: () => import('./views/pages/page-editor.vue').then(m => m.default) },
|
||||
{ path: '/@:user/pages/:page', component: UI, props: route => ({ component: () => import('../common/views/pages/page/page.vue').then(m => m.default), pageName: route.params.page, username: route.params.user }) },
|
||||
{ path: '/@:user/pages/:pageName/view-source', component: UI, props: route => ({ component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default), initUser: route.params.user, initPageName: route.params.pageName }) },
|
||||
{ path: '/notes/:note', component: MkNote },
|
||||
{ path: '/authorize-follow', component: MkFollow },
|
||||
{ path: '*', component: MkNotFound }
|
||||
|
@ -5,7 +5,7 @@
|
||||
<div>
|
||||
<header>
|
||||
<mk-reaction-icon :reaction="notification.reaction"/>
|
||||
<router-link :to="notification.user | userPage"><mk-user-name :user="notification.user"/></router-link>
|
||||
<router-link class="name" :to="notification.user | userPage"><mk-user-name :user="notification.user"/></router-link>
|
||||
<mk-time :time="notification.createdAt"/>
|
||||
</header>
|
||||
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
|
||||
@ -21,7 +21,7 @@
|
||||
<div>
|
||||
<header>
|
||||
<fa icon="retweet"/>
|
||||
<router-link :to="notification.user | userPage"><mk-user-name :user="notification.user"/></router-link>
|
||||
<router-link class="name" :to="notification.user | userPage"><mk-user-name :user="notification.user"/></router-link>
|
||||
<mk-time :time="notification.createdAt"/>
|
||||
</header>
|
||||
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note.renote)">
|
||||
@ -37,7 +37,7 @@
|
||||
<div>
|
||||
<header>
|
||||
<fa icon="user-plus"/>
|
||||
<router-link :to="notification.user | userPage"><mk-user-name :user="notification.user"/></router-link>
|
||||
<router-link class="name" :to="notification.user | userPage"><mk-user-name :user="notification.user"/></router-link>
|
||||
<mk-time :time="notification.createdAt"/>
|
||||
</header>
|
||||
</div>
|
||||
@ -48,7 +48,7 @@
|
||||
<div>
|
||||
<header>
|
||||
<fa icon="user-clock"/>
|
||||
<router-link :to="notification.user | userPage"><mk-user-name :user="notification.user"/></router-link>
|
||||
<router-link class="name" :to="notification.user | userPage"><mk-user-name :user="notification.user"/></router-link>
|
||||
<mk-time :time="notification.createdAt"/>
|
||||
</header>
|
||||
</div>
|
||||
@ -59,7 +59,7 @@
|
||||
<div>
|
||||
<header>
|
||||
<fa icon="chart-pie"/>
|
||||
<router-link :to="notification.user | userPage"><mk-user-name :user="notification.user"/></router-link>
|
||||
<router-link class="name" :to="notification.user | userPage"><mk-user-name :user="notification.user"/></router-link>
|
||||
<mk-time :time="notification.createdAt"/>
|
||||
</header>
|
||||
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
|
||||
@ -130,6 +130,12 @@ export default Vue.extend({
|
||||
[data-icon], .mk-reaction-icon
|
||||
margin-right 4px
|
||||
|
||||
> .name
|
||||
text-overflow ellipsis
|
||||
white-space nowrap
|
||||
min-width 0
|
||||
overflow hidden
|
||||
|
||||
> .mk-time
|
||||
margin-left auto
|
||||
color var(--noteHeaderInfo)
|
||||
|
@ -1,6 +1,11 @@
|
||||
<template>
|
||||
<div class="gafaadew">
|
||||
<div class="form">
|
||||
<div class="form"
|
||||
@dragover.stop="onDragover"
|
||||
@dragenter="onDragenter"
|
||||
@dragleave="onDragleave"
|
||||
@drop.stop="onDrop"
|
||||
>
|
||||
<header>
|
||||
<button class="cancel" @click="cancel"><fa icon="times"/></button>
|
||||
<div>
|
||||
@ -17,10 +22,11 @@
|
||||
<mk-user-name :user="u"/>
|
||||
<a @click="removeVisibleUser(u)">[x]</a>
|
||||
</span>
|
||||
<a @click="addVisibleUser">+{{ $t('add-visible-user') }}</a>
|
||||
<a @click="addVisibleUser">+{{ $t('@.post-form.add-visible-user') }}</a>
|
||||
</div>
|
||||
<input v-show="useCw" ref="cw" v-model="cw" :placeholder="$t('annotations')" v-autocomplete="{ model: 'cw' }">
|
||||
<textarea v-model="text" ref="text" :disabled="posting" :placeholder="placeholder" v-autocomplete="{ model: 'text' }"></textarea>
|
||||
<input v-show="useCw" ref="cw" v-model="cw" :placeholder="$t('@.post-form.cw-placeholder')" v-autocomplete="{ model: 'cw' }">
|
||||
<textarea v-model="text" ref="text" :disabled="posting" :placeholder="placeholder" v-autocomplete="{ model: 'text' }" @paste="onPaste"></textarea>
|
||||
<div class="with-quote" v-if="quoteId">{{ $t('@.post-form.quote-attached') }}</div>
|
||||
<x-post-form-attaches class="attaches" :files="files"/>
|
||||
<x-poll-editor v-if="poll" ref="poll" @destroyed="poll = false" @updated="onPollUpdate()"/>
|
||||
<mk-uploader ref="uploader" @uploaded="attachMedia" @change="onChangeUploadings"/>
|
||||
@ -50,337 +56,21 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import i18n from '../../../i18n';
|
||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||
import MkVisibilityChooser from '../../../common/views/components/visibility-chooser.vue';
|
||||
import getFace from '../../../common/scripts/get-face';
|
||||
import { parse } from '../../../../../mfm/parse';
|
||||
import { host } from '../../../config';
|
||||
import { erase, unique } from '../../../../../prelude/array';
|
||||
import { length } from 'stringz';
|
||||
import { toASCII } from 'punycode';
|
||||
import extractMentions from '../../../../../misc/extract-mentions';
|
||||
import form from '../../../common/scripts/post-form';
|
||||
|
||||
export default Vue.extend({
|
||||
i18n: i18n('mobile/views/components/post-form.vue'),
|
||||
components: {
|
||||
XPostFormAttaches: () => import('../../../common/views/components/post-form-attaches.vue').then(m => m.default),
|
||||
XPollEditor: () => import('../../../common/views/components/poll-editor.vue').then(m => m.default)
|
||||
},
|
||||
i18n: i18n(),
|
||||
|
||||
props: {
|
||||
reply: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
renote: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
mention: {
|
||||
type: Object,
|
||||
required: false
|
||||
},
|
||||
initialText: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
instant: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
posting: false,
|
||||
text: '',
|
||||
uploadings: [],
|
||||
files: [],
|
||||
poll: false,
|
||||
pollChoices: [],
|
||||
pollMultiple: false,
|
||||
geo: null,
|
||||
visibility: 'public',
|
||||
visibleUsers: [],
|
||||
localOnly: false,
|
||||
useCw: false,
|
||||
cw: null,
|
||||
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'),
|
||||
maxNoteTextLength: 1000
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
this.$root.getMeta().then(meta => {
|
||||
this.maxNoteTextLength = meta.maxNoteTextLength;
|
||||
});
|
||||
},
|
||||
|
||||
computed: {
|
||||
draftId(): string {
|
||||
return this.renote
|
||||
? `renote:${this.renote.id}`
|
||||
: this.reply
|
||||
? `reply:${this.reply.id}`
|
||||
: 'note';
|
||||
},
|
||||
|
||||
placeholder(): string {
|
||||
const xs = [
|
||||
this.$t('@.note-placeholders.a'),
|
||||
this.$t('@.note-placeholders.b'),
|
||||
this.$t('@.note-placeholders.c'),
|
||||
this.$t('@.note-placeholders.d'),
|
||||
this.$t('@.note-placeholders.e'),
|
||||
this.$t('@.note-placeholders.f')
|
||||
];
|
||||
const x = xs[Math.floor(Math.random() * xs.length)];
|
||||
|
||||
return this.renote
|
||||
? this.$t('quote-placeholder')
|
||||
: this.reply
|
||||
? this.$t('reply-placeholder')
|
||||
: x;
|
||||
},
|
||||
|
||||
submitText(): string {
|
||||
return this.renote
|
||||
? this.$t('renote')
|
||||
: this.reply
|
||||
? this.$t('reply')
|
||||
: this.$t('submit');
|
||||
},
|
||||
|
||||
canPost(): boolean {
|
||||
return !this.posting &&
|
||||
(1 <= this.text.length || 1 <= this.files.length || this.poll || this.renote) &&
|
||||
(this.text.trim().length <= this.maxNoteTextLength) &&
|
||||
(!this.poll || this.pollChoices.length >= 2);
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.initialText) {
|
||||
this.text = this.initialText;
|
||||
}
|
||||
|
||||
if (this.reply && this.reply.user.host != null) {
|
||||
this.text = `@${this.reply.user.username}@${toASCII(this.reply.user.host)} `;
|
||||
}
|
||||
|
||||
if (this.mention) {
|
||||
this.text = this.mention.host ? `@${this.mention.username}@${toASCII(this.mention.host)}` : `@${this.mention.username}`;
|
||||
this.text += ' ';
|
||||
}
|
||||
|
||||
if (this.reply && this.reply.text != null) {
|
||||
const ast = parse(this.reply.text);
|
||||
|
||||
for (const x of extractMentions(ast)) {
|
||||
const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`;
|
||||
|
||||
// 自分は除外
|
||||
if (this.$store.state.i.username == x.username && x.host == null) continue;
|
||||
if (this.$store.state.i.username == x.username && x.host == host) continue;
|
||||
|
||||
// 重複は除外
|
||||
if (this.text.indexOf(`${mention} `) != -1) continue;
|
||||
|
||||
this.text += `${mention} `;
|
||||
}
|
||||
}
|
||||
|
||||
// デフォルト公開範囲
|
||||
this.applyVisibility(this.$store.state.settings.rememberNoteVisibility ? (this.$store.state.device.visibility || this.$store.state.settings.defaultNoteVisibility) : this.$store.state.settings.defaultNoteVisibility);
|
||||
|
||||
// 公開以外へのリプライ時は元の公開範囲を引き継ぐ
|
||||
if (this.reply && ['home', 'followers', 'specified'].includes(this.reply.visibility)) {
|
||||
this.visibility = this.reply.visibility;
|
||||
}
|
||||
|
||||
if (this.reply) {
|
||||
this.$root.api('users/show', { userId: this.reply.userId }).then(user => {
|
||||
this.visibleUsers.push(user);
|
||||
});
|
||||
}
|
||||
|
||||
// keep cw when reply
|
||||
if (this.$store.state.settings.keepCw && this.reply && this.reply.cw) {
|
||||
this.useCw = true;
|
||||
this.cw = this.reply.cw;
|
||||
}
|
||||
|
||||
this.focus();
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.focus();
|
||||
});
|
||||
},
|
||||
mixins: [
|
||||
form({
|
||||
mobile: true
|
||||
}),
|
||||
],
|
||||
|
||||
methods: {
|
||||
trimmedLength(text: string) {
|
||||
return length(text.trim());
|
||||
},
|
||||
|
||||
addTag(tag: string) {
|
||||
insertTextAtCursor(this.$refs.text, ` #${tag} `);
|
||||
},
|
||||
|
||||
focus() {
|
||||
(this.$refs.text as any).focus();
|
||||
},
|
||||
|
||||
addVisibleUser() {
|
||||
this.$root.dialog({
|
||||
title: this.$t('enter-username'),
|
||||
user: true
|
||||
}).then(({ canceled, result: user }) => {
|
||||
if (canceled) return;
|
||||
this.visibleUsers.push(user);
|
||||
});
|
||||
},
|
||||
|
||||
chooseFile() {
|
||||
(this.$refs.file as any).click();
|
||||
},
|
||||
|
||||
chooseFileFromDrive() {
|
||||
this.$chooseDriveFile({
|
||||
multiple: true
|
||||
}).then(files => {
|
||||
for (const x of files) this.attachMedia(x);
|
||||
});
|
||||
},
|
||||
|
||||
attachMedia(driveFile) {
|
||||
this.files.push(driveFile);
|
||||
this.$emit('change-attached-files', this.files);
|
||||
},
|
||||
|
||||
detachMedia(id) {
|
||||
this.files = this.files.filter(x => x.id != id);
|
||||
this.$emit('change-attached-files', this.files);
|
||||
},
|
||||
|
||||
onChangeFile() {
|
||||
for (const x of Array.from((this.$refs.file as any).files)) this.upload(x);
|
||||
},
|
||||
|
||||
onPollUpdate() {
|
||||
const got = this.$refs.poll.get();
|
||||
this.pollChoices = got.choices;
|
||||
this.pollMultiple = got.multiple;
|
||||
},
|
||||
|
||||
upload(file) {
|
||||
(this.$refs.uploader as any).upload(file);
|
||||
},
|
||||
|
||||
onChangeUploadings(uploads) {
|
||||
this.$emit('change-uploadings', uploads);
|
||||
},
|
||||
|
||||
setGeo() {
|
||||
if (navigator.geolocation == null) {
|
||||
this.$root.dialog({
|
||||
type: 'warning',
|
||||
text: this.$t('geolocation-alert')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
navigator.geolocation.getCurrentPosition(pos => {
|
||||
this.geo = pos.coords;
|
||||
}, err => {
|
||||
this.$root.dialog({
|
||||
type: 'error',
|
||||
title: this.$t('error'),
|
||||
text: err.message
|
||||
});
|
||||
}, {
|
||||
enableHighAccuracy: true
|
||||
});
|
||||
},
|
||||
|
||||
removeGeo() {
|
||||
this.geo = null;
|
||||
},
|
||||
|
||||
setVisibility() {
|
||||
const w = this.$root.new(MkVisibilityChooser, {
|
||||
source: this.$refs.visibilityButton,
|
||||
currentVisibility: this.visibility
|
||||
});
|
||||
w.$once('chosen', v => {
|
||||
this.applyVisibility(v);
|
||||
});
|
||||
},
|
||||
|
||||
applyVisibility(v :string) {
|
||||
const m = v.match(/^local-(.+)/);
|
||||
if (m) {
|
||||
this.localOnly = true;
|
||||
this.visibility = m[1];
|
||||
} else {
|
||||
this.localOnly = false;
|
||||
this.visibility = v;
|
||||
}
|
||||
},
|
||||
|
||||
removeVisibleUser(user) {
|
||||
this.visibleUsers = erase(user, this.visibleUsers);
|
||||
},
|
||||
|
||||
clear() {
|
||||
this.text = '';
|
||||
this.files = [];
|
||||
this.poll = false;
|
||||
this.$emit('change-attached-files');
|
||||
},
|
||||
|
||||
post() {
|
||||
this.posting = true;
|
||||
const viaMobile = !this.$store.state.settings.disableViaMobile;
|
||||
this.$root.api('notes/create', {
|
||||
text: this.text == '' ? undefined : this.text,
|
||||
fileIds: this.files.length > 0 ? this.files.map(f => f.id) : undefined,
|
||||
replyId: this.reply ? this.reply.id : undefined,
|
||||
renoteId: this.renote ? this.renote.id : undefined,
|
||||
poll: this.poll ? (this.$refs.poll as any).get() : undefined,
|
||||
cw: this.useCw ? this.cw || '' : undefined,
|
||||
geo: this.geo ? {
|
||||
coordinates: [this.geo.longitude, this.geo.latitude],
|
||||
altitude: this.geo.altitude,
|
||||
accuracy: this.geo.accuracy,
|
||||
altitudeAccuracy: this.geo.altitudeAccuracy,
|
||||
heading: isNaN(this.geo.heading) ? null : this.geo.heading,
|
||||
speed: this.geo.speed,
|
||||
} : null,
|
||||
visibility: this.visibility,
|
||||
visibleUserIds: this.visibility == 'specified' ? this.visibleUsers.map(u => u.id) : undefined,
|
||||
localOnly: this.localOnly,
|
||||
viaMobile: viaMobile
|
||||
}).then(data => {
|
||||
this.$emit('posted');
|
||||
}).catch(err => {
|
||||
this.posting = false;
|
||||
});
|
||||
|
||||
if (this.text && this.text != '') {
|
||||
const hashtags = parse(this.text).filter(x => x.node.type === 'hashtag').map(x => x.node.props.hashtag);
|
||||
const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[];
|
||||
localStorage.setItem('hashtags', JSON.stringify(unique(hashtags.concat(history))));
|
||||
}
|
||||
},
|
||||
|
||||
cancel() {
|
||||
this.$emit('cancel');
|
||||
},
|
||||
|
||||
kao() {
|
||||
this.text += getFace();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -1,67 +0,0 @@
|
||||
<template>
|
||||
<mk-ui>
|
||||
<main>
|
||||
<x-page-editor v-if="page !== undefined" :page="page" :readonly="readonly"/>
|
||||
</main>
|
||||
</mk-ui>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
XPageEditor: () => import('../../../common/views/components/page-editor/page-editor.vue').then(m => m.default)
|
||||
},
|
||||
|
||||
props: {
|
||||
pageId: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
pageName: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
user: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
page: undefined,
|
||||
readonly: false
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
if (this.pageId) {
|
||||
this.$root.api('pages/show', {
|
||||
pageId: this.pageId,
|
||||
}).then(page => {
|
||||
this.page = page;
|
||||
});
|
||||
} else if (this.pageName && this.user) {
|
||||
this.$root.api('pages/show', {
|
||||
name: this.pageName,
|
||||
username: this.user,
|
||||
}).then(page => {
|
||||
this.readonly = true;
|
||||
this.page = page;
|
||||
});
|
||||
} else {
|
||||
this.page = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
main
|
||||
margin 0 auto
|
||||
padding 16px
|
||||
max-width 1000px
|
||||
|
||||
</style>
|
@ -1,39 +0,0 @@
|
||||
<template>
|
||||
<mk-ui>
|
||||
<main>
|
||||
<x-page :page-name="page" :username="user"/>
|
||||
</main>
|
||||
</mk-ui>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
XPage: () => import('../../../common/views/pages/page/page.vue').then(m => m.default)
|
||||
},
|
||||
|
||||
props: {
|
||||
page: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
user: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
main
|
||||
margin 0 auto
|
||||
padding 16px
|
||||
max-width 1000px
|
||||
|
||||
@media (min-width 600px)
|
||||
padding 32px
|
||||
|
||||
</style>
|
@ -31,12 +31,9 @@ const defaultSettings = {
|
||||
wallpaper: null,
|
||||
webSearchEngine: 'https://www.google.com/?#q={{query}}',
|
||||
mutedWords: [],
|
||||
games: {
|
||||
reversi: {
|
||||
showBoardLabels: false,
|
||||
useAvatarStones: true,
|
||||
}
|
||||
}
|
||||
gamesReversiShowBoardLabels: false,
|
||||
gamesReversiUseAvatarStones: true,
|
||||
disableAnimatedMfm: false,
|
||||
};
|
||||
|
||||
const defaultDeviceSettings = {
|
||||
|
@ -235,5 +235,8 @@
|
||||
|
||||
pageBlockBorder: 'rgba(255, 255, 255, 0.1)',
|
||||
pageBlockBorderHover: 'rgba(255, 255, 255, 0.15)',
|
||||
|
||||
groupUserListOwnerFg: '#f15f71',
|
||||
groupUserListOwnerBg: '#5d282e'
|
||||
},
|
||||
}
|
||||
|
@ -235,5 +235,8 @@
|
||||
|
||||
pageBlockBorder: 'rgba(0, 0, 0, 0.1)',
|
||||
pageBlockBorderHover: 'rgba(0, 0, 0, 0.15)',
|
||||
|
||||
groupUserListOwnerFg: '#f15f71',
|
||||
groupUserListOwnerBg: '#ffdfdf'
|
||||
},
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import { URL } from 'url';
|
||||
import * as yaml from 'js-yaml';
|
||||
import { Source, Mixin } from './types';
|
||||
import * as pkg from '../../package.json';
|
||||
|
@ -14,6 +14,8 @@ export type Source = {
|
||||
db: string;
|
||||
user: string;
|
||||
pass: string;
|
||||
disableCache?: boolean;
|
||||
extra?: { [x: string]: string };
|
||||
};
|
||||
redis: {
|
||||
host: string;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as Deque from 'double-ended-queue';
|
||||
import Xev from 'xev';
|
||||
import { deliverQueue, inboxQueue } from '../queue';
|
||||
import { deliverQueue, inboxQueue, dbQueue, objectStorageQueue } from '../queue';
|
||||
|
||||
const ev = new Xev();
|
||||
|
||||
@ -18,6 +18,8 @@ export default function() {
|
||||
|
||||
let activeDeliverJobs = 0;
|
||||
let activeInboxJobs = 0;
|
||||
let activeDbJobs = 0;
|
||||
let activeObjectStorageJobs = 0;
|
||||
|
||||
deliverQueue.on('global:active', () => {
|
||||
activeDeliverJobs++;
|
||||
@ -27,9 +29,19 @@ export default function() {
|
||||
activeInboxJobs++;
|
||||
});
|
||||
|
||||
dbQueue.on('global:active', () => {
|
||||
activeDbJobs++;
|
||||
});
|
||||
|
||||
objectStorageQueue.on('global:active', () => {
|
||||
activeObjectStorageJobs++;
|
||||
});
|
||||
|
||||
async function tick() {
|
||||
const deliverJobCounts = await deliverQueue.getJobCounts();
|
||||
const inboxJobCounts = await inboxQueue.getJobCounts();
|
||||
const dbJobCounts = await dbQueue.getJobCounts();
|
||||
const objectStorageJobCounts = await objectStorageQueue.getJobCounts();
|
||||
|
||||
const stats = {
|
||||
deliver: {
|
||||
@ -43,7 +55,19 @@ export default function() {
|
||||
active: inboxJobCounts.active,
|
||||
waiting: inboxJobCounts.waiting,
|
||||
delayed: inboxJobCounts.delayed
|
||||
}
|
||||
},
|
||||
db: {
|
||||
activeSincePrevTick: activeDbJobs,
|
||||
active: dbJobCounts.active,
|
||||
waiting: dbJobCounts.waiting,
|
||||
delayed: dbJobCounts.delayed
|
||||
},
|
||||
objectStorage: {
|
||||
activeSincePrevTick: activeObjectStorageJobs,
|
||||
active: objectStorageJobCounts.active,
|
||||
waiting: objectStorageJobCounts.waiting,
|
||||
delayed: objectStorageJobCounts.delayed
|
||||
},
|
||||
};
|
||||
|
||||
ev.emit('queueStats', stats);
|
||||
@ -53,6 +77,8 @@ export default function() {
|
||||
|
||||
activeDeliverJobs = 0;
|
||||
activeInboxJobs = 0;
|
||||
activeDbJobs = 0;
|
||||
activeObjectStorageJobs = 0;
|
||||
}
|
||||
|
||||
tick();
|
||||
|
@ -93,8 +93,21 @@ export function initDb(justBorrow = false, sync = false, log = false) {
|
||||
username: config.db.user,
|
||||
password: config.db.pass,
|
||||
database: config.db.db,
|
||||
extra: config.db.extra,
|
||||
synchronize: process.env.NODE_ENV === 'test' || sync,
|
||||
dropSchema: process.env.NODE_ENV === 'test' && !justBorrow,
|
||||
cache: !config.db.disableCache ? {
|
||||
type: 'redis',
|
||||
options: {
|
||||
host: config.redis.host,
|
||||
port: config.redis.port,
|
||||
options:{
|
||||
password: config.redis.pass,
|
||||
prefix: config.redis.prefix,
|
||||
db: config.redis.db || 0
|
||||
}
|
||||
}
|
||||
} : false,
|
||||
logging: log,
|
||||
logger: log ? new MyCustomLogger() : undefined,
|
||||
entities: [
|
||||
|
@ -5,7 +5,7 @@ export default redis.createClient(
|
||||
config.redis.port,
|
||||
config.redis.host,
|
||||
{
|
||||
auth_pass: config.redis.pass,
|
||||
password: config.redis.pass,
|
||||
prefix: config.redis.prefix,
|
||||
db: config.redis.db || 0
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ export default class Reversi {
|
||||
public get winner(): Color | null {
|
||||
return this.isEnded ?
|
||||
this.blackCount == this.whiteCount ? null :
|
||||
this.opts.isLlotheo === this.blackCount > this.whiteCount ? WHITE : BLACK :
|
||||
this.opts.isLlotheo === this.blackCount > this.whiteCount ? WHITE : BLACK :
|
||||
undefined as never;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ console.log('Init database...');
|
||||
|
||||
initDb(false, true, true).then(() => {
|
||||
console.log('Done :)');
|
||||
process.exit(0);
|
||||
}, e => {
|
||||
console.error('Failed to init database');
|
||||
console.error(e);
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { parseFragment, DefaultTreeDocumentFragment } from 'parse5';
|
||||
import { URL } from 'url';
|
||||
import { urlRegex } from './prelude';
|
||||
|
||||
export function fromHtml(html: string): string {
|
||||
|
@ -98,13 +98,13 @@ export const mfmLanguage = P.createLanguage({
|
||||
const text = input.substr(i);
|
||||
const match = text.match(/^(\*|_)([a-zA-Z0-9]+?[\s\S]*?)\1/);
|
||||
if (!match) return P.makeFailure(i, 'not a italic');
|
||||
if (input[i - 1] != null && input[i - 1].match(/[a-z0-9]/i)) return P.makeFailure(i, 'not a italic');
|
||||
if (input[i - 1] != null && input[i - 1] != ' ' && input[i - 1] != '\n') return P.makeFailure(i, 'not a italic');
|
||||
return P.makeSuccess(i + match[0].length, match[2]);
|
||||
});
|
||||
|
||||
return P.alt(xml, underscore).map(x => createTree('italic', r.inline.atLeast(1).tryParse(x), {}));
|
||||
},
|
||||
strike: r => P.regexp(/~~(.+?)~~/, 1).map(x => createTree('strike', r.inline.atLeast(1).tryParse(x), {})),
|
||||
strike: r => P.regexp(/~~([^\n~]+?)~~/, 1).map(x => createTree('strike', r.inline.atLeast(1).tryParse(x), {})),
|
||||
motion: r => {
|
||||
const paren = P.regexp(/\(\(\(([\s\S]+?)\)\)\)/, 1);
|
||||
const xml = P.regexp(/<motion>(.+?)<\/motion>/, 1);
|
||||
@ -164,8 +164,10 @@ export const mfmLanguage = P.createLanguage({
|
||||
} else
|
||||
url = match[0];
|
||||
url = removeOrphanedBrackets(url);
|
||||
if (url.endsWith('.')) url = url.substr(0, url.lastIndexOf('.'));
|
||||
if (url.endsWith(',')) url = url.substr(0, url.lastIndexOf(','));
|
||||
while (url.endsWith('.') || url.endsWith(',')) {
|
||||
if (url.endsWith('.')) url = url.substr(0, url.lastIndexOf('.'));
|
||||
if (url.endsWith(',')) url = url.substr(0, url.lastIndexOf(','));
|
||||
}
|
||||
return P.makeSuccess(i + url.length, url);
|
||||
}).map(x => createLeaf('url', { url: x }));
|
||||
},
|
||||
|
@ -161,7 +161,7 @@ export class ASEvaluator {
|
||||
subtract: (a: number, b: number) => a - b,
|
||||
multiply: (a: number, b: number) => a * b,
|
||||
divide: (a: number, b: number) => a / b,
|
||||
remind: (a: number, b: number) => a % b,
|
||||
mod: (a: number, b: number) => a % b,
|
||||
strLen: (a: string) => a.length,
|
||||
strPick: (a: string, b: number) => a[b - 1],
|
||||
strReplace: (a: string, b: string, c: string) => a.split(b).join(c),
|
||||
|
@ -58,7 +58,7 @@ export const funcDefs: Record<string, { in: any[]; out: any; category: string; i
|
||||
subtract: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faMinus, },
|
||||
multiply: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faTimes, },
|
||||
divide: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
|
||||
remind: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
|
||||
mod: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
|
||||
eq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faEquals, },
|
||||
notEq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faNotEqual, },
|
||||
gt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: faGreaterThan, },
|
||||
|
@ -1,6 +1,5 @@
|
||||
import config from '../config';
|
||||
import { toASCII } from 'punycode';
|
||||
import { URL } from 'url';
|
||||
|
||||
export function getFullApAccount(username: string, host: string | null) {
|
||||
return host ? `${username}@${toPuny(host)}` : `${username}@${toPuny(config.host)}`;
|
||||
|
@ -25,10 +25,8 @@ export async function downloadUrl(url: string, path: string) {
|
||||
rej(error);
|
||||
});
|
||||
|
||||
const requestUrl = new URL(url).pathname.match(/[^\u0021-\u00ff]/) ? encodeURI(url) : url;
|
||||
|
||||
const req = request({
|
||||
url: requestUrl,
|
||||
url: new URL(url).href, // https://github.com/syuilo/misskey/issues/2637
|
||||
proxy: config.proxy,
|
||||
timeout: 10 * 1000,
|
||||
headers: {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user