diff --git a/.config/example.yml b/.config/example.yml index d78a3b678..b2c76e8c4 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -120,9 +120,6 @@ redis: # Proxy remote files (default: false) #proxyRemoteFiles: true -# Sign to ActivityPub GET request (default: false) -#signToActivityPubGet: true - #allowedPrivateNetworks: [ # '127.0.0.1/32' #] diff --git a/.gitignore b/.gitignore index 32d4f96f2..4660c95cf 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ # Intelij-IDEA /.idea +# Sublime Text +/*.sublime-* + # nano .swp # vim diff --git a/.okteto/okteto-pipeline.yml b/.okteto/okteto-pipeline.yml deleted file mode 100644 index e2996fbbc..000000000 --- a/.okteto/okteto-pipeline.yml +++ /dev/null @@ -1,6 +0,0 @@ -build: - misskey: - args: - - NODE_ENV=development -deploy: - - helm upgrade --install misskey chart --set image=${OKTETO_BUILD_MISSKEY_IMAGE} --set url="https://misskey-$(kubectl config view --minify -o jsonpath='{..namespace}').cloud.okteto.net" --set environment=development diff --git a/.woodpecker/build.yml b/.woodpecker/build.yml index a99684cc9..e93473fe8 100644 --- a/.woodpecker/build.yml +++ b/.woodpecker/build.yml @@ -9,7 +9,6 @@ pipeline: install: when: event: - - push - pull_request image: node:18.6.0 commands: @@ -17,7 +16,6 @@ pipeline: build: when: event: - - push - pull_request image: node:18.6.0 commands: diff --git a/.woodpecker/lint-backend.yml b/.woodpecker/lint-backend.yml index c63d944e1..98722a7d4 100644 --- a/.woodpecker/lint-backend.yml +++ b/.woodpecker/lint-backend.yml @@ -9,7 +9,6 @@ pipeline: install: when: event: - - push - pull_request image: node:18.6.0 commands: @@ -17,7 +16,6 @@ pipeline: lint: when: event: - - push - pull_request image: node:18.6.0 commands: diff --git a/.woodpecker/lint-client.yml b/.woodpecker/lint-client.yml index 44958c029..bd4eaadcc 100644 --- a/.woodpecker/lint-client.yml +++ b/.woodpecker/lint-client.yml @@ -9,7 +9,6 @@ pipeline: install: when: event: - - push - pull_request image: node:18.6.0 commands: @@ -17,7 +16,6 @@ pipeline: lint: when: event: - - push - pull_request image: node:18.6.0 commands: diff --git a/.woodpecker/test.yml b/.woodpecker/test.yml index b535aa725..30eb04ee6 100644 --- a/.woodpecker/test.yml +++ b/.woodpecker/test.yml @@ -9,7 +9,6 @@ pipeline: build: when: event: - - push - pull_request image: node:18.6.0 commands: @@ -20,7 +19,6 @@ pipeline: mocha: when: event: - - push - pull_request image: node:18.6.0 commands: @@ -28,7 +26,6 @@ pipeline: e2e: when: event: - - push - pull_request image: cypress/included:10.3.0 commands: diff --git a/CHANGELOG-OLD.md b/CHANGELOG-OLD.md new file mode 100644 index 000000000..5caa96b51 --- /dev/null +++ b/CHANGELOG-OLD.md @@ -0,0 +1,677 @@ + + +## 12.x.x (unreleased) + +### Changes +- ハイライトがみつけるに統合されました +- カスタム絵文字ページはインスタンス情報ページに統合されました +- 連合ページはインスタンス情報ページに統合されました + +### Improvements +- Client: Fix URL-encoded routing +- Server: Allow GET method for some endpoints @syuilo +- Server: Add rate limit to i/notifications @tamaina +- Client: Improve control panel @syuilo +- Client: Show warning in control panel when there is an unresolved abuse report @syuilo +- Client: For notes with specified visibility, show recipients when hovering over visibility symbol. @Johann150 +- Client: Add rss-ticker widget @syuilo +- Client: Removing entries from a clip @futchitwo +- Client: Poll highlights in explore page @syuilo +- Make possible to delete an account by admin @syuilo +- Improve player detection in URL preview @mei23 +- Add Badge Image to Push Notification #8012 @tamaina +- Server: Improve performance +- Server: Supports IPv6 on Redis transport. @mei23 + IPv4/IPv6 is used by default. You can tune this behavior via `redis.family`. + +### Bugfixes +- Server: Fix GenerateVideoThumbnail failed @mei23 +- Server: Ensure temp directory cleanup @Johann150 +- favicons of federated instances not showing @syuilo +- Client: fix switch to receive email notifications @syuilo +- Client: Page freezes when trying to open configuration page of existing webhooks @syuilo + +## 12.111.1 (2022/06/13) + +### Bugfixes +- some fixes of multiple notification read @tamaina +- some GenerateVideoThumbnail failed @Johann150 +- Client: デッキでウィジェットの情報が保存されない問題を修正 @syuilo +- Client: ギャラリーの投稿を開こうとすると編集画面が表示される @futchitwo + +## 12.111.0 (2022/06/11) +### Note +- Node.js 16.15.0 or later is required + +### Improvements +- Supports Unicode Emoji 14.0 @mei23 +- プッシュ通知を複数アカウント対応に #7667 @tamaina +- プッシュ通知にクリックやactionを設定 #7667 @tamaina +- ドライブに画像ファイルをアップロードするときオリジナル画像を破棄してwebpublicのみ保持するオプション @tamaina +- Server: always remove completed tasks of job queue @Johann150 +- Client: アバターの設定で画像をクロップできるように @syuilo +- Client: make emoji stand out more on reaction button @Johann150 +- Client: display URL of QR code for TOTP registration @tamaina +- Client: render quote renote CWs as MFM @pixeldesu +- API: notifications/readは配列でも受け付けるように #7667 @tamaina +- API: ユーザー検索で、クエリがusernameの条件を満たす場合はusernameもLIKE検索するように @tamaina +- MFM: Allow speed changes in all animated MFMs @Johann150 +- The theme color is now better validated. @Johann150 + Your own theme color may be unset if it was in an invalid format. + Admins should check their instance settings if in doubt. +- Perform port diagnosis at startup only when Listen fails @mei23 +- Rate limiting is now also usable for non-authenticated users. @Johann150 @mei23 + Admins should make sure the reverse proxy sets the `X-Forwarded-For` header to the original address. + +### Bugfixes +- Server: keep file order of note attachement @Johann150 +- Server: fix missing foreign key for reports leading to reports page being unusable @Johann150 +- Server: fix internal in-memory caching @Johann150 +- Server: prevent crash when processing certain PNGs @syuilo +- Server: Fix unable to generate video thumbnails @mei23 +- Server: Fix `Cannot find module` issue @mei23 +- Federation: Add rel attribute to host-meta @mei23 +- Federation: add id for activitypub follows @Johann150 +- Federation: use `source` instead of `_misskey_content` @Johann150 +- Federation: ensure resolver does not fetch local resources via HTTP(S) @Johann150 +- Federation: correctly render empty note text @Johann150 +- Federation: Fix quote renotes containing no text being federated correctly @Johann150 +- Federation: remove duplicate br tag/newline @Johann150 +- Federation: add missing authorization checks @Johann150 +- Client: fix profile picture height in mentions @tamaina +- Client: fix abuse reports page to be able to show all reports @Johann150 +- Client: fix settings page @tamaina +- Client: fix profile tabs @futchitwo +- Client: fix popout URL @futchitwo +- Client: correctly handle MiAuth URLs with query string @sn0w +- Client: ノート詳細ページの新しいノートを表示する機能の動作が正しくなるように修正する @xianonn +- MFM: more animated functions support `speed` parameter @futchitwo +- MFM: limit large MFM @Johann150 + +## 12.110.1 (2022/04/23) + +### Bugfixes +- Fix GOP rendering @syuilo +- Improve performance of antenna, clip, and list @xianonn + +## 12.110.0 (2022/04/11) + +### Improvements +- Improve webhook @syuilo +- Client: Show loading icon on splash screen @syuilo + +### Bugfixes +- API: parameter validation of users/show was wrong +- Federation: リモートインスタンスへのダイレクト投稿が届かない問題を修正 @syuilo + +## 12.109.2 (2022/04/03) + +### Bugfixes +- API: admin/update-meta was not working @syuilo +- Client: テーマを切り替えたり読み込んだりするとmeta[name="theme-color"]のcontentがundefinedになる問題を修正 @tamaina + +## 12.109.1 (2022/04/02) + +### Bugfixes +- API: Renoteが行えない問題を修正 + +## 12.109.0 (2022/04/02) + +### Improvements +- Webhooks @syuilo +- Bull Dashboardを組み込み、ジョブキューの確認や操作を行えるように @syuilo + - Bull Dashboardを開くには、最初だけ一旦ログアウトしてから再度管理者権限を持つアカウントでログインする必要があります +- Check that installed Node.js version fulfills version requirement @ThatOneCalculator +- Server: overall performance improvements @syuilo +- Federation: avoid duplicate activity delivery @Johann150 +- Federation: limit federation of reactions on direct notes @Johann150 +- Client: タッチパッド・タッチスクリーンでのデッキの操作性を向上 @tamaina + +### Bugfixes +- email address validation was not working @ybw2016v +- API: fix endpoint endpoint @Johann150 +- API: fix admin/meta endpoint @syuilo +- API: improved validation and documentation for endpoints that accept different variants of input @Johann150 +- API: `notes/create`: The `mediaIds` property is now deprecated. @Johann150 + - Use `fileIds` instead, it has the same behaviour. +- Client: URIエンコーディングが異常でdecodeURIComponentが失敗するとURLが表示できなくなる問題を修正 @tamaina + +## 12.108.1 (2022/03/12) + +### Bugfixes +- リレーが動作しない問題を修正 @xianonn +- ulidを使用していると動作しない問題を修正 @syuilo +- 外部からOGPが正しく取得できない問題を修正 @syuilo +- instance can not get the files from other instance when there are items in allowedPrivateNetworks in .config/default.yml @ybw2016v + +## 12.108.0 (2022/03/09) + +### NOTE +このバージョンからNode v16.14.0以降が必要です + +### Changes +- ノートの最大文字数を設定できる機能が廃止され、デフォルトで一律3000文字になりました @syuilo +- Misskey can no longer terminate HTTPS connections. @Johann150 + - If you did not use a reverse proxy (e.g. nginx) before, you will probably need to adjust + your configuration file and set up a reverse proxy. The `https` configuration key is no + longer recognized! + +### Improvements +- インスタンスデフォルトテーマを設定できるように @syuilo +- ミュートに期限を設定できるように @syuilo +- アンケートが終了したときに通知が作成されるように @syuilo +- プロフィールの追加情報を最大16まで保存できるように @syuilo +- 連合チャートにPub&Subを追加 @syuilo +- 連合チャートにActiveを追加 @syuilo +- デフォルトで10秒以上時間がかかるデータベースへのクエリは中断されるように @syuilo + - 設定ファイルの`db.extra`に`statement_timeout`を設定することでタイムアウト時間を変更できます +- Client: スプラッシュスクリーンにインスタンスのアイコンを表示するように @syuilo + +### Bugfixes +- Client: リアクションピッカーの高さが低くなったまま戻らないことがあるのを修正 @syuilo +- Client: ユーザー名オートコンプリートが正しく動作しない問題を修正 @syuilo +- Client: タッチ操作だとウィジェットの編集がしにくいのを修正 @xianonn +- Client: register_note_view_interruptor()が動かないのを修正 @syuilo +- Client: iPhone X以降(?)でページの内容が全て表示しきれないのを修正 @tamaina +- Client: fix image caption on mobile @nullobsi + +## 12.107.0 (2022/02/12) + +### Improvements +- クライアント: テーマを追加 @syuilo + +### Bugfixes +- API: stats APIで内部エラーが発生する問題を修正 @syuilo +- クライアント: ソフトミュートですべてがマッチしてしまう場合があるのを修正 @tamaina +- クライアント: デバイスのスクリーンのセーフエリアを考慮するように @syuilo +- クライアント: 一部環境でサイドバーの投稿ボタンが表示されない問題を修正 @syuilo + +## 12.106.3 (2022/02/11) + +### Improvements +- クライアント: スマートフォンでの余白を調整 @syuilo + +### Bugfixes +- クライアント: ノートの詳細が表示されない問題を修正 @syuilo + +## 12.106.2 (2022/02/11) + +### Bugfixes +- クライアント: 削除したノートがタイムラインから自動で消えない問題を修正 @syuilo +- クライアント: リアクション数が正しくないことがある問題を修正 @syuilo +- 一部環境でマイグレーションが動作しない問題を修正 @syuilo + +## 12.106.1 (2022/02/11) + +### Bugfixes +- クライアント: ワードミュートが保存できない問題を修正 @syuilo + +## 12.106.0 (2022/02/11) + +### Improvements +- Improve federation chart @syuilo +- クライアント: リアクションピッカーのサイズを設定できるように @syuilo +- クライアント: リアクションピッカーの幅、高さ制限を緩和 @syuilo +- Docker: Update to Node v16.13.2 @mei23 +- Update dependencies + +### Bugfixes +- validate regular expressions in word mutes @Johann150 + +## 12.105.0 (2022/02/09) + +### Improvements +- インスタンスのテーマカラーを設定できるように @syuilo + +### Bugfixes +- 一部環境でマイグレーションが失敗する問題を修正 @syuilo + +## 12.104.0 (2022/02/09) + +### Note +ビルドする前に`npm run clean`を実行してください。 + +このリリースはマイグレーションの規模が大きいため、インスタンスによってはマイグレーションに時間がかかる可能性があります。 +マイグレーションが終わらない場合は、チャートの情報はリセットされてしまいますが`__chart__`で始まるテーブルの**レコード**を全て削除(テーブル自体は消さないでください)してから再度試す方法もあります。 + +### Improvements +- チャートエンジンの強化 @syuilo + - テーブルサイズの削減 + - notes/instance/perUserNotesチャートに添付ファイル付きノートの数を追加 + - activeUsersチャートに新しい項目を追加 + - federationチャートに新しい項目を追加 + - apRequestチャートを追加 + - networkチャート廃止 +- クライアント: 自インスタンス情報ページでチャートを見れるように @syuilo +- クライアント: デバイスの種類を手動指定できるように @syuilo +- クライアント: UIのアイコンを更新 @syuilo +- クライアント: UIのアイコンをセルフホスティングするように @syuilo +- NodeInfo のユーザー数と投稿数の内容を見直す @xianonn + +### Bugfixes +- Client: タイムライン種別を切り替えると「新しいノートがあります」の表示が残留してしまうのを修正 @tamaina +- Client: UIのサイズがおかしくなる問題の修正 @tamaina +- Client: Setting instance information of notes to always show breaks the timeline @Johann150 +- Client: 環境に依っては返信する際のカーソル位置が正しくない問題を修正 @syuilo +- Client: コントロールパネルのユーザー、ファイルにて、インスタンスの表示範囲切り替えが機能しない問題を修正 @syuilo +- Client: アップデートお知らせダイアログが出ないのを修正 @syuilo +- Client: Follows/Followers Visibility changes won't be saved unless clicking on an other checkbox @Johann150 +- API: Fix API cast @mei23 +- add instance favicon where it's missing @solfisher +- チャートの定期resyncが動作していない問題を修正 @syuilo + +## 12.103.1 (2022/02/02) + +### Bugfixes +- クライアント: ツールチップの表示位置が正しくない問題を修正 + +## 12.103.0 (2022/02/02) + +### Improvements +- クライアント: 連合インスタンスページからインスタンス情報再取得を行えるように + +### Bugfixes +- クライアント: 投稿のNSFW画像を表示したあとにリアクションが更新されると画像が非表示になる問題を修正 +- クライアント: 「クリップ」ページが開かない問題を修正 +- クライアント: トレンドウィジェットが動作しないのを修正 +- クライアント: フェデレーションウィジェットが動作しないのを修正 +- クライアント: リアクション設定で絵文字ピッカーが開かないのを修正 +- クライアント: DMページでメンションが含まれる問題を修正 +- クライアント: 投稿フォームのハッシュタグ保持フィールドが動作しない問題を修正 +- クライアント: サイドビューが動かないのを修正 +- クライアント: ensure that specified users does not get duplicates +- Add `img-src` and `media-src` directives to `Content-Security-Policy` for + files and media proxy + +## 12.102.1 (2022/01/27) +### Bugfixes +- チャットが表示できない問題を修正 + +## 12.102.0 (2022/01/27) + +### NOTE +アップデート後、一部カスタム絵文字が表示できなくなる場合があります。その場合、一旦絵文字管理ページから絵文字を一括エクスポートし、再度コントロールパネルから一括インポートすると直ります。 +⚠ 12.102.0以前にエクスポートされたzipとは互換性がありません。アップデートしてからエクスポートを行なってください。 + +### Changes +- Room機能が削除されました + - 後日別リポジトリとして復活予定です +- リバーシ機能が削除されました + - 後日別リポジトリとして復活予定です +- Chat UIが削除されました +- ノートに添付できるファイルの数が16に増えました +- カスタム絵文字にSVGを指定した場合、PNGに変換されて表示されるようになりました + +### Improvements +- カスタム絵文字一括編集機能 +- カスタム絵文字一括インポート +- 投稿フォームで一時的に投稿するアカウントを切り替えられるように +- Unifying Misskey-specific IRIs in JSON-LD `@context` +- クライアントのパフォーマンス向上 +- セキュリティの向上 + +### Bugfixes +- アップロードエラー時の処理を修正 + +## 12.101.1 (2021/12/29) + +### Bugfixes +- SVG絵文字が表示できないのを修正 +- エクスポートした絵文字の拡張子がfalseになることがあるのを修正 + +## 12.101.0 (2021/12/29) + +### Improvements +- クライアント: ノートプレビューの精度を改善 +- クライアント: MFM sparkleエフェクトの改善 +- クライアント: デザインの調整 +- セキュリティの向上 + +### Bugfixes +- クライアント: 一部のコンポーネントが裏に隠れるのを修正 +- fix html blockquote conversion + +## 12.100.2 (2021/12/18) + +### Bugfixes +- クライアント: Deckカラムの増減がページをリロードするまで正しく反映されない問題を修正 +- クライアント: 一部のコンポーネントが裏に隠れるのを修正 +- クライアント: カスタム絵文字一覧ページの負荷が高いのを修正 + +## 12.100.1 (2021/12/17) + +### Bugfixes +- クライアント: デザインの調整 + +## 12.100.0 (2021/12/17) + +### Improvements +- クライアント: モバイルでの各種メニュー、リアクションピッカーの表示を改善 + +### Bugfixes +- クライアント: 一部のコンポーネントが裏に隠れるのを修正 + +## 12.99.3 (2021/12/14) +### Bugfixes +- クライアント: オートコンプリートがダイアログの裏に隠れる問題を修正 + +## 12.99.2 (2021/12/14) + +## 12.99.1 (2021/12/14) + +## 12.99.0 (2021/12/14) + +### Improvements +- Added a user-level instance mute in user settings +- フォローエクスポートでミュートしているユーザーを含めないオプションを追加 +- フォローエクスポートで使われていないアカウントを含めないオプションを追加 +- カスタム絵文字エクスポート機能 +- チャートのパフォーマンスの改善 +- グループから抜けられるように + +### Bugfixes +- クライアント: タッチ機能付きディスプレイを使っていてマウス操作をしている場合に一部機能が動作しない問題を修正 +- クライアント: クリップの設定を編集できない問題を修正 +- クライアント: メニューなどがウィンドウの裏に隠れる問題を修正 + +## 12.98.0 (2021/12/03) + +### Improvements +- API: /antennas/notes API で日付による絞り込みができるように +- クライアント: アンケートに投票する際に確認ダイアログを出すように +- クライアント: Renoteなノート詳細ページから元のノートページに遷移できるように +- クライアント: 画像ポップアップでクリックで閉じられるように +- クライアント: デザインの調整 +- フォロワーを解除できる機能 + +### Bugfixes +- クライアント: LTLやGTLが無効になっている場合でもUI上にタブが表示される問題を修正 +- クライアント: ログインにおいてパスワードが誤っている際のエラーメッセージが正しく表示されない問題を修正 +- クライアント: リアクションツールチップ、Renoteツールチップのユーザーの並び順を修正 +- クライアント: サウンドのマスターボリュームが正しく保存されない問題を修正 +- クライアント: 一部環境において通知が表示されると操作不能になる問題を修正 +- クライアント: モバイルでタップしたときにツールチップが表示される問題を修正 +- クライアント: リモートインスタンスのノートに返信するとき、対象のノートにそのリモートインスタンス内のユーザーへのメンションが含まれていると、返信テキスト内にローカルユーザーへのメンションとして引き継がれてしまう場合がある問題を修正 +- クライアント: 画像ビューワーで全体表示した時に上側の一部しか表示されない画像がある問題を修正 +- API: ユーザーを取得時に条件によっては内部エラーになる問題を修正 + +### Changes +- クライアント: ノートにモデレーターバッジを表示するのを廃止 + +## 12.97.0 (2021/11/19) + +### Improvements +- クライアント: 返信先やRenoteに対しても自動折りたたみされるように +- クライアント: 長いスレッドの表示を改善 +- クライアント: 翻訳にもMFMを適用し、元の文章の改行などを保持するように +- クライアント: アカウント削除に確認ダイアログを出すように + +### Bugfixes +- クライアント: ユーザー検索の「全て」が動作しない問題を修正 +- クライアント: リアクション一覧、Renote一覧ツールチップのスタイルを修正 + +## 12.96.1 (2021/11/13) +### Improvements +- npm scriptの互換性を向上 + +## 12.96.0 (2021/11/13) + +### Improvements +- フォロー/フォロワーを非公開にできるように +- インスタンスプロフィールレンダリング ready +- 通知のリアクションアイコンをホバーで拡大できるように +- RenoteボタンをホバーでRenoteしたユーザー一覧を表示するように +- 返信の際にメンションを含めるように +- 通報があったときに管理者へEメールで通知されるように +- メールアドレスのバリデーションを強化 + +### Bugfixes +- アカウント削除処理があると高負荷になる問題を修正 +- クライアント: 長いメニューが画面からはみ出す問題を修正 +- クライアント: コントロールパネルのジョブキューに個々のジョブが表示されないのを修正 +- クライアント: fix missing i18n string +- fix html conversion issue with code blocks + +### Changes +- ノートにモバイルからの投稿か否かの情報を含めないように + +## 12.95.0 (2021/10/31) + +### Improvements +- スレッドミュート機能 + +### Bugfixes +- リレー向けのActivityが一部実装で除外されてしまうことがあるのを修正 +- 削除したノートやユーザーがリモートから参照されると復活することがあるのを修正 +- クライアント: ページ編集時のドロップダウンメニューなどが動作しない問題を修正 +- クライアント: コントロールパネルのカスタム絵文字タブが切り替わらないように見える問題を修正 +- API: ユーザー情報の hasUnreadChannel が常に false になっている問題を修正 + +## 12.94.1 (2021/10/25) + +### Improvements + +### Bugfixes +- クライアント: ユーザーページのナビゲーションが失敗する問題を修正 + +## 12.94.0 (2021/10/25) + +### Improvements +- クライアント: 画像ビューアを強化 +- クライアント: メンションにユーザーのアバターを表示するように +- クライアント: デザインの調整 +- クライアント: twemojiをセルフホスティングするように + +### Bugfixes +- クライアント: CWで画像が隠されたとき、画像の高さがおかしいことになる問題を修正 + +### NOTE +- このバージョンから、iOS 15未満のサポートがされなくなります。対象のバージョンをお使いの方は、iOSのバージョンアップを行ってください。 + +## 12.93.2 (2021/10/23) + +### Bugfixes +- クライアント: ウィジェットを追加できない問題を修正 + +## 12.93.1 (2021/10/23) + +### Bugfixes +- クライアント: 通知上でローカルのリアクションが表示されないのを修正 + +## 12.93.0 (2021/10/23) + +### Improvements +- クライアント: コントロールパネルのパフォーマンスを改善 +- クライアント: 自分のリアクション一覧を見れるように + - 設定により、リアクション一覧を全員に公開することも可能 +- クライアント: ユーザー検索の精度を強化 +- クライアント: 新しいライトテーマを追加 +- クライアント: 新しいダークテーマを追加 +- API: ユーザーのリアクション一覧を取得する users/reactions を追加 +- API: users/search および users/search-by-username-and-host を強化 +- ミュート及びブロックのインポートを行えるように +- クライアント: /share のクエリでリプライやファイル等の情報を渡せるように +- チャートのsyncを毎日0時に自動で行うように + +### Bugfixes +- クライアント: テーマの管理が行えない問題を修正 +- API: アプリケーション通知が取得できない問題を修正 +- クライアント: リモートノートで意図せずローカルカスタム絵文字が使われてしまうことがあるのを修正 +- ActivityPub: not reacted な Undo.Like がinboxに滞留するのを修正 + +### Changes +- 連合の考慮に問題があることなどが分かったため、モデレーターをブロックできない仕様を廃止しました +- データベースにログを保存しないようになりました + - ログを永続化したい場合はsyslogを利用してください + +## 12.92.0 (2021/10/16) + +### Improvements +- アカウント登録にメールアドレスの設定を必須にするオプション +- クライアント: 全体的なUIのブラッシュアップ +- クライアント: MFM関数構文のサジェストを実装 +- クライアント: ノート本文を投稿フォーム内でプレビューできるように +- クライアント: 未読の通知のみ表示する機能 +- クライアント: 通知ページで通知の種類によるフィルタ +- クライアント: アニメーションを減らす設定の適用範囲を拡充 +- クライアント: 新しいダークテーマを追加 +- クライアント: テーマコンパイラに hue と saturate 関数を追加 +- ActivityPub: HTML -> MFMの変換を強化 +- API: グループから抜ける users/groups/leave エンドポイントを実装 +- API: i/notifications に unreadOnly オプションを追加 +- API: ap系のエンドポイントをログイン必須化+レートリミット追加 +- MFM: Add tag syntaxes of bold and strikethrough + +### Bugfixes +- Fix createDeleteAccountJob +- admin inbox queue does not show individual jobs +- クライアント: ヘッダーのタブが折り返される問題を修正 +- クライアント: ヘッダーにタブが表示されている状態でタイトルをクリックしたときにタブ選択が表示されるのを修正 +- クライアント: ユーザーページのタブが機能していない問題を修正 +- クライアント: ピン留めユーザーの設定項目がない問題を修正 +- クライアント: Deck UIにおいて、重ねたカラムの片方を畳んだ状態で右に出すと表示が壊れる問題を修正 +- API: 管理者およびモデレーターをブロックできてしまう問題を修正 +- MFM: Mentions in the link label are parsed as text +- MFM: Add a property to the URL node indicating whether it was enclosed in <> +- MFM: Disallows < and > in hashtags + +### Changes +- 保守性やユーザビリティの観点から、Misskeyのコマンドラインオプションが削除されました。 + - 必要であれば、代わりに環境変数で設定することができます +- MFM: パフォーマンス、保守性、構文誤認識抑制の観点から、旧関数構文のサポートが削除されました。 + - 旧構文(`[foo bar]`)を使用せず、現行の構文(`$[foo bar]`)を使用してください。 + +## 12.91.0 (2021/09/22) + +### Improvements +- ActivityPub: リモートユーザーのDeleteアクティビティに対応 +- ActivityPub: add resolver check for blocked instance +- ActivityPub: deliverキューのメモリ使用量を削減 +- API: 管理者用アカウント削除APIを実装(/admin/accounts/delete) + - リモートユーザーの削除も可能に +- アカウントが凍結された場合に、凍結された旨を表示してからログアウトするように +- 凍結されたアカウントにログインしようとしたときに、凍結されている旨を表示するように +- リスト、アンテナタイムラインを個別ページとして分割 +- UIの改善 +- MFMにsparklesエフェクトを追加 +- 非ログイン自は更新ダイアログを出さないように +- クライアント起動時、アップデートが利用可能な場合エラー表示およびダイアログ表示しないように + +### Bugfixes +- アカウントデータのエクスポート/インポート処理ができない問題を修正 +- アンテナの既読が付かない問題を修正 +- popupで設定ページを表示すると、アカウントの削除ページにアクセスすることができない問題を修正 +- "問題が発生しました"ウィンドウを開くと☓ボタンがなくて閉じれない問題を修正 + +## 12.90.1 (2021/09/05) + +### Bugfixes +- Dockerfileを修正 +- ノート翻訳時に公開範囲が考慮されていない問題を修正 + +## 12.90.0 (2021/09/04) + +### Improvements +- 藍モード、および藍ウィジェット + - クライアントに藍ちゃんを召喚することができるようになりました。 +- URLからのアップロード, APの添付ファイル, 外部ファイルのプロキシ等では、Privateアドレス等へのリクエストは拒否されるようになりました。 + - developmentで動作している場合は、この制限は適用されません。 + - Proxy使用時には、この制限は適用されません。 + Proxy使用時に同等の制限を行いたい場合は、Proxy側で設定を行う必要があります。 + - `default.yml`にて`allowedPrivateNetworks`にCIDRを追加することにより、宛先ネットワークを指定してこの制限から除外することが出来ます。 +- アップロード, ダウンロード出来るファイルサイズにハードリミットが適用されるようになりました。(約250MB) + - `default.yml`にて`maxFileSize`を変更することにより、制限値を変更することが出来ます。 + +### Bugfixes +- 管理者が最初にサインアップするページでログインされないのを修正 +- CWを維持する設定を復活 +- クライアントの表示を修正 + +## 12.89.2 (2021/08/24) + +### Bugfixes +- カスタムCSSを有効にしているとエラーになる問題を修正 + +## 12.89.1 (2021/08/24) + +### Improvements +- クライアントのデザインの調整 + +### Bugfixes +- 翻訳でDeepLのProアカウントに対応していない問題を修正 +- インスタンス設定でDeepLのAuth Keyが空で表示される問題を修正 +- セキュリティの向上 + +## 12.89.0 (2021/08/21) + +### Improvements +- アカウント削除の安定性を向上 +- 絵文字オートコンプリートの挙動を改修 +- localStorageのaccountsはindexedDBで保持するように +- ActivityPub: ジョブキューの試行タイミングを調整 (#7635) +- API: sw/unregisterを追加 +- ワードミュートのドキュメントを追加 +- クライアントのデザインの調整 +- 依存関係の更新 + +### Bugfixes +- チャンネルを作成しているとアカウントを削除できないのを修正 +- ノートの「削除して編集」をするとアンケートの選択肢が[object Object]になる問題を修正 + +## 12.88.0 (2021/08/17) + +### Features +- ノートの翻訳機能を追加 + - 有効にするには、サーバー管理者がDeepLの無料アカウントを登録し、取得した認証キーを「インスタンス設定 > その他 > DeepL Auth Key」に設定する必要があります。 +- Misskey更新時にダイアログを表示するように +- ジョブキューウィジェットに警報音を鳴らす設定を追加 + +### Improvements +- ブロックの挙動を改修 + - ブロックされたユーザーがブロックしたユーザーに対してアクション出来ないようになりました。詳細はドキュメントをご確認ください。 +- UIデザインの調整 +- データベースのインデックスを最適化 +- Proxy使用時にKeep-Aliveをサポート +- DNSキャッシュでネガティブキャッシュをサポート +- 依存関係の更新 + +### Bugfixes +- タッチ操作でウィンドウを閉じることができない問題を修正 +- Renoteされた時刻が投稿された時刻のように表示される問題を修正 +- コントロールパネルでファイルを削除した際の表示を修正 +- ActivityPub: 長いユーザーの名前や自己紹介の対応 + +## 12.87.0 (2021/08/12) + +### Improvements +- 絵文字オートコンプリートで一文字目は最近使った絵文字をサジェストするように +- 絵文字オートコンプリートのパフォーマンスを改善 +- about-misskeyページにドキュメントへのリンクを追加 +- Docker: Node.jsを16.6.2に +- 依存関係の更新 +- 翻訳の更新 + +### Bugfixes +- Misskey更新時、テーマキャッシュの影響でスタイルがおかしくなる問題を修正 + +## 12.86.0 (2021/08/11) + +### Improvements +- ドキュメントの更新 + - ドキュメントにchangelogを追加 +- ぼかし効果のオプションを追加 +- Vueを3.2.1に更新 +- UIの調整 + +### Bugfixes +- ハッシュタグ入力が空のときに#が付くのを修正 +- フォローリクエストのEメール通知を修正 diff --git a/CHANGELOG.md b/CHANGELOG.md index 65bd56822..3c2a97212 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,680 +1,80 @@ - +## Unreleased +### Added +- Client: Show instance info in ticker +- Client: Readded group pages +- Client: add re-collapsing to quoted notes -## 12.x.x (unreleased) +### Changed +- Client: Use consistent date formatting based on language setting +- Client: Add threshold to reduce occurances of "future" timestamps +- Pages have been considerably simplified, several of the very complex features have been removed. + Pages are now MFM only. + **For admins:** There is a migration in place to convert page contents to text, but not everything can be migrated. + You might want to check if you have any more complex pages on your instance and ask users to migrate them by hand. + Or generally advise all users to simplify their pages to only text. -### Changes -- ハイライトがみつけるに統合されました -- カスタム絵文字ページはインスタンス情報ページに統合されました -- 連合ページはインスタンス情報ページに統合されました +### Removed +- Okteto config and Helm chart +- Client: acrylic styling +- Client: Twitter embeds, the standard URL preview is used instead. +- Promotion entities and endpoints +- Server: The configuration item `signToActivityPubGet` has been removed and will be ignored if set explicitly. + Foundkey will now work as if it was set to `true`. -### Improvements -- Client: Fix URL-encoded routing -- Server: Allow GET method for some endpoints @syuilo -- Server: Add rate limit to i/notifications @tamaina -- Client: Improve control panel @syuilo -- Client: Show warning in control panel when there is an unresolved abuse report @syuilo -- Client: For notes with specified visibility, show recipients when hovering over visibility symbol. @Johann150 -- Client: Add rss-ticker widget @syuilo -- Client: Removing entries from a clip @futchitwo -- Client: Poll highlights in explore page @syuilo -- Make possible to delete an account by admin @syuilo -- Improve player detection in URL preview @mei23 -- Add Badge Image to Push Notification #8012 @tamaina +### Fixed +- Server: Blocking remote accounts + +### Security +- Server: Update `multer` dependency to resolve [CVE-2022-24434](https://nvd.nist.gov/vuln/detail/CVE-2022-24434) + +## 13.0.0-preview1 - 2022-08-05 +### Added +- Server: Replies can now be fetched recursively. + +### Changed +- Server: Replies/quotes cannot have a more open visibility than the parent post +- Server: Allow GET method for some endpoints +- Server: Add rate limit to i/notifications - Server: Improve performance -- Server: Supports IPv6 on Redis transport. @mei23 - IPv4/IPv6 is used by default. You can tune this behavior via `redis.family`. - -### Bugfixes -- Server: Fix GenerateVideoThumbnail failed @mei23 -- Server: Ensure temp directory cleanup @Johann150 -- favicons of federated instances not showing @syuilo -- Client: fix switch to receive email notifications @syuilo -- Client: Page freezes when trying to open configuration page of existing webhooks @syuilo - -## 12.111.1 (2022/06/13) - -### Bugfixes -- some fixes of multiple notification read @tamaina -- some GenerateVideoThumbnail failed @Johann150 -- Client: デッキでウィジェットの情報が保存されない問題を修正 @syuilo -- Client: ギャラリーの投稿を開こうとすると編集画面が表示される @futchitwo - -## 12.111.0 (2022/06/11) -### Note -- Node.js 16.15.0 or later is required - -### Improvements -- Supports Unicode Emoji 14.0 @mei23 -- プッシュ通知を複数アカウント対応に #7667 @tamaina -- プッシュ通知にクリックやactionを設定 #7667 @tamaina -- ドライブに画像ファイルをアップロードするときオリジナル画像を破棄してwebpublicのみ保持するオプション @tamaina -- Server: always remove completed tasks of job queue @Johann150 -- Client: アバターの設定で画像をクロップできるように @syuilo -- Client: make emoji stand out more on reaction button @Johann150 -- Client: display URL of QR code for TOTP registration @tamaina -- Client: render quote renote CWs as MFM @pixeldesu -- API: notifications/readは配列でも受け付けるように #7667 @tamaina -- API: ユーザー検索で、クエリがusernameの条件を満たす場合はusernameもLIKE検索するように @tamaina -- MFM: Allow speed changes in all animated MFMs @Johann150 -- The theme color is now better validated. @Johann150 - Your own theme color may be unset if it was in an invalid format. - Admins should check their instance settings if in doubt. -- Perform port diagnosis at startup only when Listen fails @mei23 -- Rate limiting is now also usable for non-authenticated users. @Johann150 @mei23 - Admins should make sure the reverse proxy sets the `X-Forwarded-For` header to the original address. - -### Bugfixes -- Server: keep file order of note attachement @Johann150 -- Server: fix missing foreign key for reports leading to reports page being unusable @Johann150 -- Server: fix internal in-memory caching @Johann150 -- Server: prevent crash when processing certain PNGs @syuilo -- Server: Fix unable to generate video thumbnails @mei23 -- Server: Fix `Cannot find module` issue @mei23 -- Federation: Add rel attribute to host-meta @mei23 -- Federation: add id for activitypub follows @Johann150 -- Federation: use `source` instead of `_misskey_content` @Johann150 -- Federation: ensure resolver does not fetch local resources via HTTP(S) @Johann150 -- Federation: correctly render empty note text @Johann150 -- Federation: Fix quote renotes containing no text being federated correctly @Johann150 -- Federation: remove duplicate br tag/newline @Johann150 -- Federation: add missing authorization checks @Johann150 -- Client: fix profile picture height in mentions @tamaina -- Client: fix abuse reports page to be able to show all reports @Johann150 -- Client: fix settings page @tamaina -- Client: fix profile tabs @futchitwo -- Client: fix popout URL @futchitwo -- Client: correctly handle MiAuth URLs with query string @sn0w -- Client: ノート詳細ページの新しいノートを表示する機能の動作が正しくなるように修正する @xianonn -- MFM: more animated functions support `speed` parameter @futchitwo -- MFM: limit large MFM @Johann150 - -## 12.110.1 (2022/04/23) - -### Bugfixes -- Fix GOP rendering @syuilo -- Improve performance of antenna, clip, and list @xianonn - -## 12.110.0 (2022/04/11) - -### Improvements -- Improve webhook @syuilo -- Client: Show loading icon on splash screen @syuilo - -### Bugfixes -- API: parameter validation of users/show was wrong -- Federation: リモートインスタンスへのダイレクト投稿が届かない問題を修正 @syuilo - -## 12.109.2 (2022/04/03) - -### Bugfixes -- API: admin/update-meta was not working @syuilo -- Client: テーマを切り替えたり読み込んだりするとmeta[name="theme-color"]のcontentがundefinedになる問題を修正 @tamaina - -## 12.109.1 (2022/04/02) - -### Bugfixes -- API: Renoteが行えない問題を修正 - -## 12.109.0 (2022/04/02) - -### Improvements -- Webhooks @syuilo -- Bull Dashboardを組み込み、ジョブキューの確認や操作を行えるように @syuilo - - Bull Dashboardを開くには、最初だけ一旦ログアウトしてから再度管理者権限を持つアカウントでログインする必要があります -- Check that installed Node.js version fulfills version requirement @ThatOneCalculator -- Server: overall performance improvements @syuilo -- Federation: avoid duplicate activity delivery @Johann150 -- Federation: limit federation of reactions on direct notes @Johann150 -- Client: タッチパッド・タッチスクリーンでのデッキの操作性を向上 @tamaina - -### Bugfixes -- email address validation was not working @ybw2016v -- API: fix endpoint endpoint @Johann150 -- API: fix admin/meta endpoint @syuilo -- API: improved validation and documentation for endpoints that accept different variants of input @Johann150 -- API: `notes/create`: The `mediaIds` property is now deprecated. @Johann150 - - Use `fileIds` instead, it has the same behaviour. -- Client: URIエンコーディングが異常でdecodeURIComponentが失敗するとURLが表示できなくなる問題を修正 @tamaina - -## 12.108.1 (2022/03/12) - -### Bugfixes -- リレーが動作しない問題を修正 @xianonn -- ulidを使用していると動作しない問題を修正 @syuilo -- 外部からOGPが正しく取得できない問題を修正 @syuilo -- instance can not get the files from other instance when there are items in allowedPrivateNetworks in .config/default.yml @ybw2016v - -## 12.108.0 (2022/03/09) - -### NOTE -このバージョンからNode v16.14.0以降が必要です - -### Changes -- ノートの最大文字数を設定できる機能が廃止され、デフォルトで一律3000文字になりました @syuilo -- Misskey can no longer terminate HTTPS connections. @Johann150 - - If you did not use a reverse proxy (e.g. nginx) before, you will probably need to adjust - your configuration file and set up a reverse proxy. The `https` configuration key is no - longer recognized! - -### Improvements -- インスタンスデフォルトテーマを設定できるように @syuilo -- ミュートに期限を設定できるように @syuilo -- アンケートが終了したときに通知が作成されるように @syuilo -- プロフィールの追加情報を最大16まで保存できるように @syuilo -- 連合チャートにPub&Subを追加 @syuilo -- 連合チャートにActiveを追加 @syuilo -- デフォルトで10秒以上時間がかかるデータベースへのクエリは中断されるように @syuilo - - 設定ファイルの`db.extra`に`statement_timeout`を設定することでタイムアウト時間を変更できます -- Client: スプラッシュスクリーンにインスタンスのアイコンを表示するように @syuilo - -### Bugfixes -- Client: リアクションピッカーの高さが低くなったまま戻らないことがあるのを修正 @syuilo -- Client: ユーザー名オートコンプリートが正しく動作しない問題を修正 @syuilo -- Client: タッチ操作だとウィジェットの編集がしにくいのを修正 @xianonn -- Client: register_note_view_interruptor()が動かないのを修正 @syuilo -- Client: iPhone X以降(?)でページの内容が全て表示しきれないのを修正 @tamaina -- Client: fix image caption on mobile @nullobsi - -## 12.107.0 (2022/02/12) - -### Improvements -- クライアント: テーマを追加 @syuilo - -### Bugfixes -- API: stats APIで内部エラーが発生する問題を修正 @syuilo -- クライアント: ソフトミュートですべてがマッチしてしまう場合があるのを修正 @tamaina -- クライアント: デバイスのスクリーンのセーフエリアを考慮するように @syuilo -- クライアント: 一部環境でサイドバーの投稿ボタンが表示されない問題を修正 @syuilo - -## 12.106.3 (2022/02/11) - -### Improvements -- クライアント: スマートフォンでの余白を調整 @syuilo - -### Bugfixes -- クライアント: ノートの詳細が表示されない問題を修正 @syuilo - -## 12.106.2 (2022/02/11) - -### Bugfixes -- クライアント: 削除したノートがタイムラインから自動で消えない問題を修正 @syuilo -- クライアント: リアクション数が正しくないことがある問題を修正 @syuilo -- 一部環境でマイグレーションが動作しない問題を修正 @syuilo - -## 12.106.1 (2022/02/11) - -### Bugfixes -- クライアント: ワードミュートが保存できない問題を修正 @syuilo - -## 12.106.0 (2022/02/11) - -### Improvements -- Improve federation chart @syuilo -- クライアント: リアクションピッカーのサイズを設定できるように @syuilo -- クライアント: リアクションピッカーの幅、高さ制限を緩和 @syuilo -- Docker: Update to Node v16.13.2 @mei23 -- Update dependencies - -### Bugfixes -- validate regular expressions in word mutes @Johann150 - -## 12.105.0 (2022/02/09) - -### Improvements -- インスタンスのテーマカラーを設定できるように @syuilo - -### Bugfixes -- 一部環境でマイグレーションが失敗する問題を修正 @syuilo - -## 12.104.0 (2022/02/09) - -### Note -ビルドする前に`npm run clean`を実行してください。 - -このリリースはマイグレーションの規模が大きいため、インスタンスによってはマイグレーションに時間がかかる可能性があります。 -マイグレーションが終わらない場合は、チャートの情報はリセットされてしまいますが`__chart__`で始まるテーブルの**レコード**を全て削除(テーブル自体は消さないでください)してから再度試す方法もあります。 - -### Improvements -- チャートエンジンの強化 @syuilo - - テーブルサイズの削減 - - notes/instance/perUserNotesチャートに添付ファイル付きノートの数を追加 - - activeUsersチャートに新しい項目を追加 - - federationチャートに新しい項目を追加 - - apRequestチャートを追加 - - networkチャート廃止 -- クライアント: 自インスタンス情報ページでチャートを見れるように @syuilo -- クライアント: デバイスの種類を手動指定できるように @syuilo -- クライアント: UIのアイコンを更新 @syuilo -- クライアント: UIのアイコンをセルフホスティングするように @syuilo -- NodeInfo のユーザー数と投稿数の内容を見直す @xianonn - -### Bugfixes -- Client: タイムライン種別を切り替えると「新しいノートがあります」の表示が残留してしまうのを修正 @tamaina -- Client: UIのサイズがおかしくなる問題の修正 @tamaina -- Client: Setting instance information of notes to always show breaks the timeline @Johann150 -- Client: 環境に依っては返信する際のカーソル位置が正しくない問題を修正 @syuilo -- Client: コントロールパネルのユーザー、ファイルにて、インスタンスの表示範囲切り替えが機能しない問題を修正 @syuilo -- Client: アップデートお知らせダイアログが出ないのを修正 @syuilo -- Client: Follows/Followers Visibility changes won't be saved unless clicking on an other checkbox @Johann150 -- API: Fix API cast @mei23 -- add instance favicon where it's missing @solfisher -- チャートの定期resyncが動作していない問題を修正 @syuilo - -## 12.103.1 (2022/02/02) - -### Bugfixes -- クライアント: ツールチップの表示位置が正しくない問題を修正 - -## 12.103.0 (2022/02/02) - -### Improvements -- クライアント: 連合インスタンスページからインスタンス情報再取得を行えるように - -### Bugfixes -- クライアント: 投稿のNSFW画像を表示したあとにリアクションが更新されると画像が非表示になる問題を修正 -- クライアント: 「クリップ」ページが開かない問題を修正 -- クライアント: トレンドウィジェットが動作しないのを修正 -- クライアント: フェデレーションウィジェットが動作しないのを修正 -- クライアント: リアクション設定で絵文字ピッカーが開かないのを修正 -- クライアント: DMページでメンションが含まれる問題を修正 -- クライアント: 投稿フォームのハッシュタグ保持フィールドが動作しない問題を修正 -- クライアント: サイドビューが動かないのを修正 -- クライアント: ensure that specified users does not get duplicates -- Add `img-src` and `media-src` directives to `Content-Security-Policy` for - files and media proxy - -## 12.102.1 (2022/01/27) -### Bugfixes -- チャットが表示できない問題を修正 - -## 12.102.0 (2022/01/27) - -### NOTE -アップデート後、一部カスタム絵文字が表示できなくなる場合があります。その場合、一旦絵文字管理ページから絵文字を一括エクスポートし、再度コントロールパネルから一括インポートすると直ります。 -⚠ 12.102.0以前にエクスポートされたzipとは互換性がありません。アップデートしてからエクスポートを行なってください。 - -### Changes -- Room機能が削除されました - - 後日別リポジトリとして復活予定です -- リバーシ機能が削除されました - - 後日別リポジトリとして復活予定です -- Chat UIが削除されました -- ノートに添付できるファイルの数が16に増えました -- カスタム絵文字にSVGを指定した場合、PNGに変換されて表示されるようになりました - -### Improvements -- カスタム絵文字一括編集機能 -- カスタム絵文字一括インポート -- 投稿フォームで一時的に投稿するアカウントを切り替えられるように -- Unifying Misskey-specific IRIs in JSON-LD `@context` -- クライアントのパフォーマンス向上 -- セキュリティの向上 - -### Bugfixes -- アップロードエラー時の処理を修正 - -## 12.101.1 (2021/12/29) - -### Bugfixes -- SVG絵文字が表示できないのを修正 -- エクスポートした絵文字の拡張子がfalseになることがあるのを修正 - -## 12.101.0 (2021/12/29) - -### Improvements -- クライアント: ノートプレビューの精度を改善 -- クライアント: MFM sparkleエフェクトの改善 -- クライアント: デザインの調整 -- セキュリティの向上 - -### Bugfixes -- クライアント: 一部のコンポーネントが裏に隠れるのを修正 -- fix html blockquote conversion - -## 12.100.2 (2021/12/18) - -### Bugfixes -- クライアント: Deckカラムの増減がページをリロードするまで正しく反映されない問題を修正 -- クライアント: 一部のコンポーネントが裏に隠れるのを修正 -- クライアント: カスタム絵文字一覧ページの負荷が高いのを修正 - -## 12.100.1 (2021/12/17) - -### Bugfixes -- クライアント: デザインの調整 - -## 12.100.0 (2021/12/17) - -### Improvements -- クライアント: モバイルでの各種メニュー、リアクションピッカーの表示を改善 - -### Bugfixes -- クライアント: 一部のコンポーネントが裏に隠れるのを修正 - -## 12.99.3 (2021/12/14) -### Bugfixes -- クライアント: オートコンプリートがダイアログの裏に隠れる問題を修正 - -## 12.99.2 (2021/12/14) - -## 12.99.1 (2021/12/14) - -## 12.99.0 (2021/12/14) - -### Improvements -- Added a user-level instance mute in user settings -- フォローエクスポートでミュートしているユーザーを含めないオプションを追加 -- フォローエクスポートで使われていないアカウントを含めないオプションを追加 -- カスタム絵文字エクスポート機能 -- チャートのパフォーマンスの改善 -- グループから抜けられるように - -### Bugfixes -- クライアント: タッチ機能付きディスプレイを使っていてマウス操作をしている場合に一部機能が動作しない問題を修正 -- クライアント: クリップの設定を編集できない問題を修正 -- クライアント: メニューなどがウィンドウの裏に隠れる問題を修正 - -## 12.98.0 (2021/12/03) - -### Improvements -- API: /antennas/notes API で日付による絞り込みができるように -- クライアント: アンケートに投票する際に確認ダイアログを出すように -- クライアント: Renoteなノート詳細ページから元のノートページに遷移できるように -- クライアント: 画像ポップアップでクリックで閉じられるように -- クライアント: デザインの調整 -- フォロワーを解除できる機能 - -### Bugfixes -- クライアント: LTLやGTLが無効になっている場合でもUI上にタブが表示される問題を修正 -- クライアント: ログインにおいてパスワードが誤っている際のエラーメッセージが正しく表示されない問題を修正 -- クライアント: リアクションツールチップ、Renoteツールチップのユーザーの並び順を修正 -- クライアント: サウンドのマスターボリュームが正しく保存されない問題を修正 -- クライアント: 一部環境において通知が表示されると操作不能になる問題を修正 -- クライアント: モバイルでタップしたときにツールチップが表示される問題を修正 -- クライアント: リモートインスタンスのノートに返信するとき、対象のノートにそのリモートインスタンス内のユーザーへのメンションが含まれていると、返信テキスト内にローカルユーザーへのメンションとして引き継がれてしまう場合がある問題を修正 -- クライアント: 画像ビューワーで全体表示した時に上側の一部しか表示されない画像がある問題を修正 -- API: ユーザーを取得時に条件によっては内部エラーになる問題を修正 - -### Changes -- クライアント: ノートにモデレーターバッジを表示するのを廃止 - -## 12.97.0 (2021/11/19) - -### Improvements -- クライアント: 返信先やRenoteに対しても自動折りたたみされるように -- クライアント: 長いスレッドの表示を改善 -- クライアント: 翻訳にもMFMを適用し、元の文章の改行などを保持するように -- クライアント: アカウント削除に確認ダイアログを出すように - -### Bugfixes -- クライアント: ユーザー検索の「全て」が動作しない問題を修正 -- クライアント: リアクション一覧、Renote一覧ツールチップのスタイルを修正 - -## 12.96.1 (2021/11/13) -### Improvements -- npm scriptの互換性を向上 - -## 12.96.0 (2021/11/13) - -### Improvements -- フォロー/フォロワーを非公開にできるように -- インスタンスプロフィールレンダリング ready -- 通知のリアクションアイコンをホバーで拡大できるように -- RenoteボタンをホバーでRenoteしたユーザー一覧を表示するように -- 返信の際にメンションを含めるように -- 通報があったときに管理者へEメールで通知されるように -- メールアドレスのバリデーションを強化 - -### Bugfixes -- アカウント削除処理があると高負荷になる問題を修正 -- クライアント: 長いメニューが画面からはみ出す問題を修正 -- クライアント: コントロールパネルのジョブキューに個々のジョブが表示されないのを修正 -- クライアント: fix missing i18n string -- fix html conversion issue with code blocks - -### Changes -- ノートにモバイルからの投稿か否かの情報を含めないように - -## 12.95.0 (2021/10/31) - -### Improvements -- スレッドミュート機能 - -### Bugfixes -- リレー向けのActivityが一部実装で除外されてしまうことがあるのを修正 -- 削除したノートやユーザーがリモートから参照されると復活することがあるのを修正 -- クライアント: ページ編集時のドロップダウンメニューなどが動作しない問題を修正 -- クライアント: コントロールパネルのカスタム絵文字タブが切り替わらないように見える問題を修正 -- API: ユーザー情報の hasUnreadChannel が常に false になっている問題を修正 - -## 12.94.1 (2021/10/25) - -### Improvements - -### Bugfixes -- クライアント: ユーザーページのナビゲーションが失敗する問題を修正 - -## 12.94.0 (2021/10/25) - -### Improvements -- クライアント: 画像ビューアを強化 -- クライアント: メンションにユーザーのアバターを表示するように -- クライアント: デザインの調整 -- クライアント: twemojiをセルフホスティングするように - -### Bugfixes -- クライアント: CWで画像が隠されたとき、画像の高さがおかしいことになる問題を修正 - -### NOTE -- このバージョンから、iOS 15未満のサポートがされなくなります。対象のバージョンをお使いの方は、iOSのバージョンアップを行ってください。 - -## 12.93.2 (2021/10/23) - -### Bugfixes -- クライアント: ウィジェットを追加できない問題を修正 - -## 12.93.1 (2021/10/23) - -### Bugfixes -- クライアント: 通知上でローカルのリアクションが表示されないのを修正 - -## 12.93.0 (2021/10/23) - -### Improvements -- クライアント: コントロールパネルのパフォーマンスを改善 -- クライアント: 自分のリアクション一覧を見れるように - - 設定により、リアクション一覧を全員に公開することも可能 -- クライアント: ユーザー検索の精度を強化 -- クライアント: 新しいライトテーマを追加 -- クライアント: 新しいダークテーマを追加 -- API: ユーザーのリアクション一覧を取得する users/reactions を追加 -- API: users/search および users/search-by-username-and-host を強化 -- ミュート及びブロックのインポートを行えるように -- クライアント: /share のクエリでリプライやファイル等の情報を渡せるように -- チャートのsyncを毎日0時に自動で行うように - -### Bugfixes -- クライアント: テーマの管理が行えない問題を修正 -- API: アプリケーション通知が取得できない問題を修正 -- クライアント: リモートノートで意図せずローカルカスタム絵文字が使われてしまうことがあるのを修正 -- ActivityPub: not reacted な Undo.Like がinboxに滞留するのを修正 - -### Changes -- 連合の考慮に問題があることなどが分かったため、モデレーターをブロックできない仕様を廃止しました -- データベースにログを保存しないようになりました - - ログを永続化したい場合はsyslogを利用してください - -## 12.92.0 (2021/10/16) - -### Improvements -- アカウント登録にメールアドレスの設定を必須にするオプション -- クライアント: 全体的なUIのブラッシュアップ -- クライアント: MFM関数構文のサジェストを実装 -- クライアント: ノート本文を投稿フォーム内でプレビューできるように -- クライアント: 未読の通知のみ表示する機能 -- クライアント: 通知ページで通知の種類によるフィルタ -- クライアント: アニメーションを減らす設定の適用範囲を拡充 -- クライアント: 新しいダークテーマを追加 -- クライアント: テーマコンパイラに hue と saturate 関数を追加 -- ActivityPub: HTML -> MFMの変換を強化 -- API: グループから抜ける users/groups/leave エンドポイントを実装 -- API: i/notifications に unreadOnly オプションを追加 -- API: ap系のエンドポイントをログイン必須化+レートリミット追加 -- MFM: Add tag syntaxes of bold and strikethrough - -### Bugfixes -- Fix createDeleteAccountJob -- admin inbox queue does not show individual jobs -- クライアント: ヘッダーのタブが折り返される問題を修正 -- クライアント: ヘッダーにタブが表示されている状態でタイトルをクリックしたときにタブ選択が表示されるのを修正 -- クライアント: ユーザーページのタブが機能していない問題を修正 -- クライアント: ピン留めユーザーの設定項目がない問題を修正 -- クライアント: Deck UIにおいて、重ねたカラムの片方を畳んだ状態で右に出すと表示が壊れる問題を修正 -- API: 管理者およびモデレーターをブロックできてしまう問題を修正 -- MFM: Mentions in the link label are parsed as text -- MFM: Add a property to the URL node indicating whether it was enclosed in <> -- MFM: Disallows < and > in hashtags - -### Changes -- 保守性やユーザビリティの観点から、Misskeyのコマンドラインオプションが削除されました。 - - 必要であれば、代わりに環境変数で設定することができます -- MFM: パフォーマンス、保守性、構文誤認識抑制の観点から、旧関数構文のサポートが削除されました。 - - 旧構文(`[foo bar]`)を使用せず、現行の構文(`$[foo bar]`)を使用してください。 - -## 12.91.0 (2021/09/22) - -### Improvements -- ActivityPub: リモートユーザーのDeleteアクティビティに対応 -- ActivityPub: add resolver check for blocked instance -- ActivityPub: deliverキューのメモリ使用量を削減 -- API: 管理者用アカウント削除APIを実装(/admin/accounts/delete) - - リモートユーザーの削除も可能に -- アカウントが凍結された場合に、凍結された旨を表示してからログアウトするように -- 凍結されたアカウントにログインしようとしたときに、凍結されている旨を表示するように -- リスト、アンテナタイムラインを個別ページとして分割 -- UIの改善 -- MFMにsparklesエフェクトを追加 -- 非ログイン自は更新ダイアログを出さないように -- クライアント起動時、アップデートが利用可能な場合エラー表示およびダイアログ表示しないように - -### Bugfixes -- アカウントデータのエクスポート/インポート処理ができない問題を修正 -- アンテナの既読が付かない問題を修正 -- popupで設定ページを表示すると、アカウントの削除ページにアクセスすることができない問題を修正 -- "問題が発生しました"ウィンドウを開くと☓ボタンがなくて閉じれない問題を修正 - -## 12.90.1 (2021/09/05) - -### Bugfixes -- Dockerfileを修正 -- ノート翻訳時に公開範囲が考慮されていない問題を修正 - -## 12.90.0 (2021/09/04) - -### Features -- Added a user-level instance mute in user settings - -### Improvements -- 藍モード、および藍ウィジェット - - クライアントに藍ちゃんを召喚することができるようになりました。 -- URLからのアップロード, APの添付ファイル, 外部ファイルのプロキシ等では、Privateアドレス等へのリクエストは拒否されるようになりました。 - - developmentで動作している場合は、この制限は適用されません。 - - Proxy使用時には、この制限は適用されません。 - Proxy使用時に同等の制限を行いたい場合は、Proxy側で設定を行う必要があります。 - - `default.yml`にて`allowedPrivateNetworks`にCIDRを追加することにより、宛先ネットワークを指定してこの制限から除外することが出来ます。 -- アップロード, ダウンロード出来るファイルサイズにハードリミットが適用されるようになりました。(約250MB) - - `default.yml`にて`maxFileSize`を変更することにより、制限値を変更することが出来ます。 - -### Bugfixes -- 管理者が最初にサインアップするページでログインされないのを修正 -- CWを維持する設定を復活 -- クライアントの表示を修正 - -## 12.89.2 (2021/08/24) - -### Bugfixes -- カスタムCSSを有効にしているとエラーになる問題を修正 - -## 12.89.1 (2021/08/24) - -### Improvements -- クライアントのデザインの調整 - -### Bugfixes -- 翻訳でDeepLのProアカウントに対応していない問題を修正 -- インスタンス設定でDeepLのAuth Keyが空で表示される問題を修正 -- セキュリティの向上 - -## 12.89.0 (2021/08/21) - -### Improvements -- アカウント削除の安定性を向上 -- 絵文字オートコンプリートの挙動を改修 -- localStorageのaccountsはindexedDBで保持するように -- ActivityPub: ジョブキューの試行タイミングを調整 (#7635) -- API: sw/unregisterを追加 -- ワードミュートのドキュメントを追加 -- クライアントのデザインの調整 -- 依存関係の更新 - -### Bugfixes -- チャンネルを作成しているとアカウントを削除できないのを修正 -- ノートの「削除して編集」をするとアンケートの選択肢が[object Object]になる問題を修正 - -## 12.88.0 (2021/08/17) - -### Features -- ノートの翻訳機能を追加 - - 有効にするには、サーバー管理者がDeepLの無料アカウントを登録し、取得した認証キーを「インスタンス設定 > その他 > DeepL Auth Key」に設定する必要があります。 -- Misskey更新時にダイアログを表示するように -- ジョブキューウィジェットに警報音を鳴らす設定を追加 - -### Improvements -- ブロックの挙動を改修 - - ブロックされたユーザーがブロックしたユーザーに対してアクション出来ないようになりました。詳細はドキュメントをご確認ください。 -- UIデザインの調整 -- データベースのインデックスを最適化 -- Proxy使用時にKeep-Aliveをサポート -- DNSキャッシュでネガティブキャッシュをサポート -- 依存関係の更新 - -### Bugfixes -- タッチ操作でウィンドウを閉じることができない問題を修正 -- Renoteされた時刻が投稿された時刻のように表示される問題を修正 -- コントロールパネルでファイルを削除した際の表示を修正 -- ActivityPub: 長いユーザーの名前や自己紹介の対応 - -## 12.87.0 (2021/08/12) - -### Improvements -- 絵文字オートコンプリートで一文字目は最近使った絵文字をサジェストするように -- 絵文字オートコンプリートのパフォーマンスを改善 -- about-misskeyページにドキュメントへのリンクを追加 -- Docker: Node.jsを16.6.2に -- 依存関係の更新 -- 翻訳の更新 - -### Bugfixes -- Misskey更新時、テーマキャッシュの影響でスタイルがおかしくなる問題を修正 - -## 12.86.0 (2021/08/11) - -### Improvements -- ドキュメントの更新 - - ドキュメントにchangelogを追加 -- ぼかし効果のオプションを追加 -- Vueを3.2.1に更新 -- UIの調整 - -### Bugfixes -- ハッシュタグ入力が空のときに#が付くのを修正 -- フォローリクエストのEメール通知を修正 +- Server: Supports IPv6 on Redis transport + IPv4/IPv6 is used by default. You can tune this behavior via `redis.family` +- Server: Mutes and blocks now apply recursively to replies and renotes +- Server: Admins can now delete accounts +- Client: Improve control panel +- Client: Show warning in control panel when there is an unresolved abuse report +- Client: For notes with specified visibility, show recipients when hovering over visibility symbol. +- Client: Add rss-ticker widget +- Client: Removing entries from a clip +- Client: Searching in the emoji picker is now case insensitive +- Client: MFM search button changed to a no-op +- Client: Fix URL-encoded routing +- Client: Poll highlights in explore page +- Client: Improve player detection in URL preview +- Client: Add Badge Image to Push Notification +- Client: Custom Emoji pages have been merged into the Instance Info page + +### Removed +- Server: ID generation methods other than `aid` +- Client: Ability to show advertisements + +### Fixed +- Server: Video thumbnails are now generated properly +- Server: Ensure temp directory cleanup +- Client: Favicons of remote instances now show up +- Client: Fix switch to receive email notifications +- Client: Page freezes when trying to open configuration page of existing webhooks +- Client: Fix a bug where new chat messages don't show up +- Client: Fix collapsing long notes +- Client: Add padding to pages + +### Security +- Server: Hide metadata of private notes diff --git a/chart/Chart.yaml b/chart/Chart.yaml deleted file mode 100644 index 8f31cf7fb..000000000 --- a/chart/Chart.yaml +++ /dev/null @@ -1,3 +0,0 @@ -apiVersion: v2 -name: misskey -version: 0.0.0 diff --git a/chart/files/default.yml b/chart/files/default.yml deleted file mode 100644 index a9ef22f42..000000000 --- a/chart/files/default.yml +++ /dev/null @@ -1,165 +0,0 @@ -#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -# Misskey configuration -#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -# ┌─────┐ -#───┘ URL └───────────────────────────────────────────────────── - -# Final accessible URL seen by a user. -# url: https://example.tld/ - -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# URL SETTINGS AFTER THAT! - -# ┌───────────────────────┐ -#───┘ Port and TLS settings └─────────────────────────────────── - -# -# Misskey supports two deployment options for public. -# - -# Option 1: With Reverse Proxy -# -# +----- https://example.tld/ ------------+ -# +------+ |+-------------+ +----------------+| -# | User | ---> || Proxy (443) | ---> | Misskey (3000) || -# +------+ |+-------------+ +----------------+| -# +---------------------------------------+ -# -# You need to setup reverse proxy. (eg. nginx) -# You do not define 'https' section. - -# Option 2: Standalone -# -# +- https://example.tld/ -+ -# +------+ | +---------------+ | -# | User | ---> | | Misskey (443) | | -# +------+ | +---------------+ | -# +------------------------+ -# -# You need to run Misskey as root. -# You need to set Certificate in 'https' section. - -# To use option 1, uncomment below line. -port: 3000 # A port that your Misskey server should listen. - -# To use option 2, uncomment below lines. -#port: 443 - -#https: -# # path for certification -# key: /etc/letsencrypt/live/example.tld/privkey.pem -# cert: /etc/letsencrypt/live/example.tld/fullchain.pem - -# ┌──────────────────────────┐ -#───┘ PostgreSQL configuration └──────────────────────────────── - -db: - host: localhost - port: 5432 - - # Database name - db: misskey - - # Auth - user: example-misskey-user - pass: example-misskey-pass - - # Whether disable Caching queries - #disableCache: true - - # Extra Connection options - #extra: - # ssl: true - -# ┌─────────────────────┐ -#───┘ Redis configuration └───────────────────────────────────── - -redis: - host: localhost - port: 6379 - #pass: example-pass - #prefix: example-prefix - #db: 1 - -# ┌─────────────────────────────┐ -#───┘ Elasticsearch configuration └───────────────────────────── - -#elasticsearch: -# host: localhost -# port: 9200 -# ssl: false -# user: -# pass: - -# ┌───────────────┐ -#───┘ ID generation └─────────────────────────────────────────── - -# You can select the ID generation method. -# You don't usually need to change this setting, but you can -# change it according to your preferences. - -# Available methods: -# aid ... Short, Millisecond accuracy -# meid ... Similar to ObjectID, Millisecond accuracy -# ulid ... Millisecond accuracy -# objectid ... This is left for backward compatibility - -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# ID SETTINGS AFTER THAT! - -id: "aid" -# ┌─────────────────────┐ -#───┘ Other configuration └───────────────────────────────────── - -# Whether disable HSTS -#disableHsts: true - -# Number of worker processes -#clusterLimit: 1 - -# Job concurrency per worker -# deliverJobConcurrency: 128 -# inboxJobConcurrency: 16 - -# Job rate limiter -# deliverJobPerSec: 128 -# inboxJobPerSec: 16 - -# Job attempts -# deliverJobMaxAttempts: 12 -# inboxJobMaxAttempts: 8 - -# IP address family used for outgoing request (ipv4, ipv6 or dual) -#outgoingAddressFamily: ipv4 - -# Syslog option -#syslog: -# host: localhost -# port: 514 - -# Proxy for HTTP/HTTPS -#proxy: http://127.0.0.1:3128 - -#proxyBypassHosts: [ -# 'example.com', -# '192.0.2.8' -#] - -# Proxy for SMTP/SMTPS -#proxySmtp: http://127.0.0.1:3128 # use HTTP/1.1 CONNECT -#proxySmtp: socks4://127.0.0.1:1080 # use SOCKS4 -#proxySmtp: socks5://127.0.0.1:1080 # use SOCKS5 - -# Media Proxy -#mediaProxy: https://example.com/proxy - -# Sign to ActivityPub GET request (default: false) -#signToActivityPubGet: true - -#allowedPrivateNetworks: [ -# '127.0.0.1/32' -#] - -# Upload or download file size limits (bytes) -#maxFileSize: 262144000 diff --git a/chart/templates/ConfigMap.yml b/chart/templates/ConfigMap.yml deleted file mode 100644 index 37c25e086..000000000 --- a/chart/templates/ConfigMap.yml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "misskey.fullname" . }}-configuration -data: - default.yml: |- - {{ .Files.Get "files/default.yml"|nindent 4 }} - url: {{ .Values.url }} diff --git a/chart/templates/Deployment.yml b/chart/templates/Deployment.yml deleted file mode 100644 index d16aece91..000000000 --- a/chart/templates/Deployment.yml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "misskey.fullname" . }} - labels: - {{- include "misskey.labels" . | nindent 4 }} -spec: - selector: - matchLabels: - {{- include "misskey.selectorLabels" . | nindent 6 }} - replicas: 1 - template: - metadata: - labels: - {{- include "misskey.selectorLabels" . | nindent 8 }} - spec: - containers: - - name: misskey - image: {{ .Values.image }} - env: - - name: NODE_ENV - value: {{ .Values.environment }} - volumeMounts: - - name: {{ include "misskey.fullname" . }}-configuration - mountPath: /misskey/.config - readOnly: true - ports: - - containerPort: 3000 - - name: postgres - image: postgres:14-alpine - env: - - name: POSTGRES_USER - value: "example-misskey-user" - - name: POSTGRES_PASSWORD - value: "example-misskey-pass" - - name: POSTGRES_DB - value: "misskey" - ports: - - containerPort: 5432 - - name: redis - image: redis:alpine - ports: - - containerPort: 6379 - volumes: - - name: {{ include "misskey.fullname" . }}-configuration - configMap: - name: {{ include "misskey.fullname" . }}-configuration diff --git a/chart/templates/Service.yml b/chart/templates/Service.yml deleted file mode 100644 index 320958129..000000000 --- a/chart/templates/Service.yml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "misskey.fullname" . }} - annotations: - dev.okteto.com/auto-ingress: "true" -spec: - type: ClusterIP - ports: - - port: 3000 - protocol: TCP - name: http - selector: - {{- include "misskey.selectorLabels" . | nindent 4 }} diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl deleted file mode 100644 index a5a2499f3..000000000 --- a/chart/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "misskey.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "misskey.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "misskey.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "misskey.labels" -}} -helm.sh/chart: {{ include "misskey.chart" . }} -{{ include "misskey.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "misskey.selectorLabels" -}} -app.kubernetes.io/name: {{ include "misskey.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "misskey.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "misskey.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/chart/values.yml b/chart/values.yml deleted file mode 100644 index a7031538a..000000000 --- a/chart/values.yml +++ /dev/null @@ -1,3 +0,0 @@ -url: https://example.tld/ -image: okteto.dev/misskey -environment: production diff --git a/crowdin.yml b/crowdin.yml deleted file mode 100644 index 774ddc7a6..000000000 --- a/crowdin.yml +++ /dev/null @@ -1,4 +0,0 @@ -files: - - source: /locales/ja-JP.yml - translation: /locales/%locale%.yml - update_option: update_as_unapproved diff --git a/docs/DONATORS.md b/docs/DONATORS.md deleted file mode 100644 index 9da5c1a94..000000000 --- a/docs/DONATORS.md +++ /dev/null @@ -1,25 +0,0 @@ -DONATORS -======== -The list of people who have sent donation for Misskey. - -(In random order, honorific titles are omitted.) - -* らふぁ -* 俺様 -* なぎうり -* スルメ https://surume.tk/ -* 藍 -* 音船 https://otofune.me/ -* aqz https://misskey.xyz/aqz -* kotodu "虚無創作中" -* Maya Minatsuki -* Knzk https://knzk.me/@Knzk -* ねじりわさび https://knzk.me/@y -* NCLS https://knzk.me/@imncls] -* こじま @skoji@sandbox.skoji.jp - -:heart: Thanks for donating, guys! - ---- - -If your name is missing, please contact us! diff --git a/docs/INSTALL.md b/docs/INSTALL.md new file mode 100644 index 000000000..37e20a83a --- /dev/null +++ b/docs/INSTALL.md @@ -0,0 +1,204 @@ +# FoundKey Setup and Installation Guide + +This guide will assume that you have administrative rights, either as root or a user with sudo permissions. If you are using a non-root user, prefix the commands with `sudo` except when you are logged into the foundkey user with `su`. + +This guide will also assume you're using Debian or a derivative like Ubuntu. If you are using another OS, you will need to adapt the comamnds and package names to match those that your OS uses. + +## Install dependencies +FoundKey requires the following packages to run: + +### Dependencies :package: +* **[Node.js](https://nodejs.org/en/)** (16.x/18.x) +* **[PostgreSQL](https://www.postgresql.org/)** (12.x minimum; 13.x+ is preferred) +* **[Redis](https://redis.io/)** + +The following are needed to compile native npm modules: +* A C/C++ compiler like **GCC** or **Clang** +* Build tools like **make** +* **[Python](https://python.org/)** (3.x) + +### Optional +* [Yarn](https://yarnpkg.com/) - *If you decide not to install it, use `npx yarn` instead of `yarn`.* +* [FFmpeg](https://www.ffmpeg.org/) + +To install the dependiencies on Debian (or derivatives like Ubuntu) you can use the following commands: +```sh +curl -fsSL https://deb.nodesource.com/setup_16.x | bash - +apt install build-essential python3 nodejs postgresql redis + +# Optional dependencies +apt install ffmpeg +corepack enable # for yarn +``` + +## Create FoundKey user +Create a separate non-root user to run FoundKey: + +```sh +adduser --disabled-password --disabled-login foundkey +``` + +## Install FoundKey +1. Login to the `foundkey` user + + `su - foundkey` + +2. Clone the FoundKey repository + + `git clone --recursive https://akkoma.dev/FoundKeyGang/FoundKey foundkey` + +3. Navigate to the repository + + `cd foundkey` + +4. Install FoundKey's dependencies + + `yarn install` + +## Configure FoundKey +1. Copy `.config/example.yml` to `.config/default.yml`. + + `cp .config/example.yml .config/default.yml` + +2. Edit `default.yml` with a text editor + - Make sure you set the PostgreSQL and Redis settings correctly. + - Use a strong password for the PostgreSQL user and take note of it since it'll be needed later. + +## Build FoundKey + +Build foundkey with the following: + +`NODE_ENV=production yarn build` + +If you're still encountering errors about some modules, use node-gyp: + +1. `npx node-gyp configure` +2. `npx node-gyp build` +3. `NODE_ENV=production yarn build` + +## Setting up the database +Create the appropriate PostgreSQL users with respective passwords, and empty database as named in the configuration file. + +Make sure the database connection also works correctly when run from the user that will later run FoundKey, or it could cause problems later. The encoding of the database should be UTF-8. + +```sh +sudo -u postgres psql +``` + +```sql +create database foundkey with encoding = 'UTF8'; +create user foundkey with encrypted password '{YOUR_PASSWORD}'; +grant all privileges on database foundkey to foundkey; +\q +``` + +Next, initialize the database: + `yarn run init` + +## Running FoundKey +You can either run FoundKey manually or use the system service manager to start FoundKey automatically on startup. + +### Launching manually +Run `NODE_ENV=production npm start` to launch FoundKey manually. To stop the server, use Ctrl-C. + +### Launch with systemd + +Run `systemctl --edit --full --force foundkey.service`, and paste the following: + +```ini +[Unit] +Description=FoundKey daemon + +[Service] +Type=simple +User=foundkey +ExecStart=/usr/bin/npm start +WorkingDirectory=/home/foundkey/foundkey +Environment="NODE_ENV=production" +TimeoutSec=60 +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=foundkey +Restart=always + +[Install] +WantedBy=multi-user.target +``` + +Save the file, then enable and start FoundKey. +```sh +systemctl enable --now foundkey +``` + +You can check if the service is running with `systemctl status foundkey`. + +### Launch with OpenRC + +Copy the following text to `/etc/init.d/foundkey`: + +```sh +#!/sbin/openrc-run + +name=foundkey +description="FoundKey daemon" + +command="/usr/bin/npm" +command_args="start" +command_user="foundkey" + +supervisor="supervise-daemon" +supervise_daemon_args=" -d /home/foundkey/foundkey -e NODE_ENV=\"production\"" + +pidfile="/run/${RC_SVCNAME}.pid" + +depend() { + need net + use logger + + # alternatively, uncomment if using nginx reverse proxy + #use logger nginx +} +``` + +Mark the script as executable and enable the service to start on boot: + +```sh +chmod +x /etc/init.d/foundkey +rc-update add foundkey +``` + +Start the FoundKey service: + +```sh +rc-service foundkey start +``` + +You can check if the service is running with `rc-service foundkey status`. + +### Updating FoundKey +Use git to pull in the latest changes and rerun the build and migration commands: + +```sh +git pull +git submodule update --init +yarn install +NODE_ENV=production yarn build +yarn migrate +``` + +Then restart FoundKey if it's still running. +```sh +# Systemd +systemctl restart foundkey + +# OpenRC +rc-service foundkey restart +``` + +If you encounter any problems with updating, please try the following: +1. `yarn clean` or `yarn cleanall` +2. Retry update (Don't forget `yarn install`) + +---------------------------------------------------------------- + +If you have any questions or troubles, feel free to contact us on IRC: `#foundkey` on `irc.akkoma.dev`, port `6697` with SSL diff --git a/docs/default-reaction.md b/docs/default-reaction.md new file mode 100644 index 000000000..ff2d86f2c --- /dev/null +++ b/docs/default-reaction.md @@ -0,0 +1,2 @@ +# Changing the default Reaction +You can change the default reaction that is used when an ActivityPub "Like" is received from '👍' to '⭐' by changing the boolean value `meta.useStarForReactionFallback` in the databse respectively. \ No newline at end of file diff --git a/docs/emoji.md b/docs/emoji.md new file mode 100644 index 000000000..257cbc39d --- /dev/null +++ b/docs/emoji.md @@ -0,0 +1,111 @@ +# Managing Custom Emoji + +Custom emoji can be managed by administrators or moderators by going to the instance settings and then the custom emoji submenu. +By default you will see a list of the current locally installed emoji. +At the start this list will be empty, but you can add custom emoji in different ways. + +## Copying Emoji from another Instance + +Emoji can be easily copied from another instance. +To do this, switch to the "remote" tab in the custom emoji settings. +You can search emoji by name and/or host they are from. + +When you have found an emoji you want, click it to open a small menu which will allow you to import the emoji. + +Please note that Emoji may be subject to copyright and you are responsible for checking whether you may legally use another emoji. + +## Individual Emoji Import + +If you have an image file that you would like to turn into a custom emoji you can import the image as an emoji. +This works just like attaching files to a note: +You can choose to upload a new file, pick a file from your Misskey drive or upload a file from another URL. + +::: danger +When you import emoji from your drive, the file will remain inside your drive. +Misskey does not make a copy of this file so if you delete it, the emoji will be broken. +::: + +The emoji will be added to the instance and you will then be able to edit or delete it as usual. + +## Bulk Emoji import + +Emojis can be imported in bulk as packed ZIP files with a special format. +This ability can be found in the three dots menu in the top right corner of the custom emoji menu. + +::: warning +Bulk emoji import may overwrite existing emoji or otherwise mess up your instance. +Be sure to only import emoji from trusted sources, ideally only ones you exported yourself. +::: + +### Packed emoji format + +At the top level is a file called `meta.json` which contains information about the emoji contained in the packed file. +A type definition for this file would look like this, where `Meta` is the structure of the whole file. + +```typescript +class Meta { + metaVersion: number; + host: string; + /** + * Date and time representation returned by ECMAScript `Date.prototype.toString`. + */ + exportedAt: string; + emojis: Emoji[]; +} + +class Emoji { + downloaded: boolean; + fileName: string; + emoji: { + id: string; + updatedAt: string; + name: string; + host: null; + category: string; + originalUrl: string; + publicUrl: string; + uri: null; + type: string; + aliases: string[]; + }; +} +``` + +The fields of `Meta` are currently not used or checked when importing emoji, except for the `emojis` field. + +For each `Emoji`: +- `downloaded`: should always be true. If the field is missing or not truthy, the emoji will not be imported. +- `fileName`: name of the image file inside the packed file. +- `emoji`: data associated with the emoji as it was stored in the database. Currently most of these fields are + not even checked for existence. The following are currently used: + - `name`: name of the emoji for the user, e.g. `blobfox` if a user should type in `:blobfox:` to get the emoji. + If a previous emoji with the same name exists, it **will be overwritten**! + - `category`: category of the emoji + - `aliases`: list of strings that should be added as aliases. The admin UI calls these "tags". + +## Editing and Deleting Emoji + +The properties of an emoji can be edited by clicking it in the list of local emoji. +When you click on a custom emoji, a dialog for editing the properties will open. +This dialog will also allow you to delete an emoji. + +::: danger +When you delete a custom emoji, old notes that contain it will still have the text name of the emoji in it. +The emoji will no longer be rendered correctly. +::: + +Note that remote emoji can not be edited or deleted. + +Each emoji can have a name and a category and several tags. +The category is used for structuring the emoji picker. +Meanwhile the tags can be used as alternate names by which the emoji can be found when searching in the emoji picker. + +When you are done editing, save your changes by clicking the check mark in the top right corner of the dialog. + +### Bulk Editing + +Emoji can be edited in bulk by checking the box below the search field. +With this enabled, clicking on an emoji will select it instead of opening the editing dialog. + +The Editing options will be displayed as buttons below the checkbox. +To return to the normal behaviour just uncheck the box again. diff --git a/docs/nginx.md b/docs/nginx.md new file mode 100644 index 000000000..59daa4a1a --- /dev/null +++ b/docs/nginx.md @@ -0,0 +1,86 @@ +# Nginx configuration +1. Create `/etc/nginx/conf.d/misskey.conf` or `/etc/nginx/sites-available/misskey.conf` and copy the following example to the file.\ + (The file name does not have to be "misskey".) +2. Edit as follows: + 1. Replace example.tld with the domain you have prepared.\ + `ssl_certificate` and `ssl_certificate_key` should be the path to the certificate obtained from Let's Encrypt. + 2. If using a CDN such as Cloudflare, remove 4 lines from "If it's behind another reverse proxy or CDN, remove the following." +3. If you create `/etc/nginx/sites-available/misskey.conf`, create symlink as `/etc/nginx/sites-enabled/misskey.conf`.\ + `sudo ln -s /etc/nginx/sites-available/misskey.conf /etc/nginx/sites-enabled/misskey.conf` +4. Run `sudo nginx -t` to verify that the configuration file will be loaded successfully. +5. Run `sudo systemctl restart nginx` to restart nginx. + +# Nginx cofig example + +```nginx +# For WebSocket +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=cache1:16m max_size=1g inactive=720m use_temp_path=off; + +server { + listen 80; + listen [::]:80; + server_name example.tld; + + # For SSL domain validation + root /var/www/html; + location /.well-known/acme-challenge/ { allow all; } + location /.well-known/pki-validation/ { allow all; } + location / { return 301 https://$server_name$request_uri; } +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name example.tld; + + ssl_session_timeout 1d; + ssl_session_cache shared:ssl_session_cache:10m; + ssl_session_tickets off; + + # To use Let's Encrypt certificate + ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem; + + # To use Debian/Ubuntu's self-signed certificate (For testing or before issuing a certificate) + #ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; + #ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; + + # SSL protocol settings + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers off; + ssl_stapling on; + ssl_stapling_verify on; + + # Change to your upload limit + client_max_body_size 80m; + + # Proxy to Node + location / { + proxy_pass http://127.0.0.1:3000; + proxy_set_header Host $host; + proxy_http_version 1.1; + proxy_redirect off; + + # If it's behind another reverse proxy or CDN, remove the following. + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + + # For WebSocket + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + # Cache settings + proxy_cache cache1; + proxy_cache_lock on; + proxy_cache_use_stale updating; + add_header X-Cache $upstream_cache_status; + } +} +``` diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml index 25ae09ac9..6959dcda1 100644 --- a/locales/ar-SA.yml +++ b/locales/ar-SA.yml @@ -254,7 +254,6 @@ remoteUserCaution: "هذه المعلومات قد لا تكون مكتملة ب activity: "النشاط" images: "الصور" birthday: "تاريخ الميلاد" -yearsOld: "{age} سنة" registeredDate: "انضم في" location: "الموقع الجغرافي" theme: "المظهر" @@ -466,8 +465,6 @@ dayOverDayChanges: "يوميا" appearance: "المظهر" clientSettings: "إعدادات العميل" accountSettings: "إعدادات الحساب" -promotion: "ترقية" -promote: "روِّج" numberOfDays: "عدد الأيام" hideThisNote: "إخفاء هذه الملاحظة" showFeaturedNotesInTimeline: "أظهر الملاحظات الشائعة في الخيط الزمني" @@ -532,7 +529,6 @@ poll: "استطلاع رأي" useCw: "إخفاء المحتوى" enablePlayer: "افتح مشغل الفيديو" disablePlayer: "أغلق مشغل الفيديو" -expandTweet: "وسّع التغريدة" themeEditor: "مصمم القوالب" description: "الوصف" describeFile: "أضف تعليقًا توضيحيًا" @@ -1233,7 +1229,6 @@ _pages: liked: "الصفحات المُعجب بها" featured: "الأكثر شعبية" contents: "المحتوى" - variables: "متغيّرات" title: "العنوان" url: "رابط الصفحة" summary: "ملخص الصفحة" @@ -1244,238 +1239,6 @@ _pages: fontSansSerif: "Sans Serif" eyeCatchingImageSet: "عيّن صورة مصغّرة" eyeCatchingImageRemove: "احذف صورة مصغّرة" - chooseBlock: "إضافة كتلة" - selectType: "اختر النوع" - enterVariableName: "أدخل اسم المتغيّر" - variableNameIsAlreadyUsed: "هذا الاسم محجوز" - contentBlocks: "المحتوى" - inputBlocks: "مُدخل" - specialBlocks: "خاص" - blocks: - text: "نص" - textarea: "حقل نصي" - section: "قسم" - image: "الصور" - button: "زرّ" - _if: - variable: "متغيّر" - post: "أنشئ ملاحظة" - _post: - text: "المحتوى" - textInput: "مُدخل نصي" - _textInput: - name: "اسم المتغير" - text: "العنوان" - default: "القيمة الافتراضية" - textareaInput: "مدخل نصي متعدد الأسطر" - _textareaInput: - name: "اسم المتغير" - text: "العنوان" - default: "القيمة الافتراضية" - numberInput: "مُدخل رقمي" - _numberInput: - name: "اسم المتغير" - text: "العنوان" - default: "القيمة الافتراضية" - _canvas: - width: "العُرض" - height: "الإرتفاع" - note: "ملاحظة مضمّنة" - _note: - id: "معرّف الملاحظة" - idDescription: "كبديل يمكنك إدخال رابك الملاحظة هنا" - detailed: "عرض مفصّل" - switch: "بدّل" - _switch: - name: "اسم المتغير" - text: "العنوان" - default: "القيمة الافتراضية" - counter: "العداد" - _counter: - name: "اسم المتغير" - text: "العنوان" - inc: "زِد" - _button: - text: "العنوان" - colored: "ملوّن" - action: "الإجراء عند ضغط الزّر" - _action: - dialog: "أظهر مربع حوار" - _dialog: - content: "المحتوى" - resetRandom: "صفِّر البذرة" - pushEvent: "أرسل حدثًا" - _pushEvent: - event: "اسم الحدث" - message: "إظهار رسالة عند التفعيل" - variable: "أرسل المتغيّر" - no-variable: "لا شيء" - _callAiScript: - functionName: "اسم الدالة" - radioButton: "الخيار " - _radioButton: - name: "اسم المتغير" - title: "العنوان" - values: "قائمة الخيارات (كل خيار في سطر لوحده)" - default: "القيمة الافتراضية" - script: - categories: - logical: "عمليّة منطقيّة" - operation: "حساب" - comparison: "مقارنة" - random: "عشوائي" - value: "القيم" - fn: "دوال" - text: "إجراءات على النصوص" - convert: "تحويل" - list: "القوائم" - blocks: - text: "نص" - textList: "قائمة نصية" - _textList: - info: "اجعل كل مدخل في سطر لوحده" - strLen: "طول النص" - _strLen: - arg1: "نص" - strPick: "استخرج محرفًا" - _strPick: - arg1: "نص" - arg2: "موضع المحرف" - strReplace: "استبدال النّص" - _strReplace: - arg1: "نص" - arg2: "استُبدِل بـ" - arg3: "استُبدِل بـ" - strReverse: "اقلب النص" - _strReverse: - arg1: "نص" - _join: - arg1: "القوائم" - arg2: "فاصل" - add: "إضافة" - _add: - arg1: "أ" - arg2: "ب" - subtract: "اطرح" - _subtract: - arg1: "أ" - arg2: "ب" - multiply: "اضرب" - _multiply: - arg1: "أ" - arg2: "ب" - divide: "اقسم" - _divide: - arg1: "أ" - arg2: "ب" - mod: "الباقي" - _mod: - arg1: "أ" - arg2: "ب" - round: "تقريب عدد عشري" - _round: - arg1: "رقم" - eq: "أ و ب متساويان" - _eq: - arg1: "أ" - arg2: "ب" - notEq: "أ و ب مختلفان" - _notEq: - arg1: "أ" - arg2: "ب" - and: "أ و ب" - _and: - arg1: "أ" - arg2: "ب" - or: "أ أو ب" - _or: - arg1: "أ" - arg2: "ب" - lt: "أ أصغر من ب" - _lt: - arg1: "أ" - arg2: "ب" - gt: "أ أكبر من ب" - _gt: - arg1: "أ" - arg2: "ب" - ltEq: "أ أصغر من أو يساوي ب" - _ltEq: - arg1: "أ" - arg2: "ب" - gtEq: "أ أكبر من أو يساوي ب" - _gtEq: - arg1: "أ" - arg2: "ب" - if: "فرع" - random: "عشوائي" - rannum: "رقم عشوائي" - _rannum: - arg1: "أدنى قيمة" - arg2: "أقصى قيمة" - randomPick: "اختر عشوائيًا من القائمة" - _randomPick: - arg1: "القوائم" - dailyRandom: "عشوائي (يتغير مرة يوميًا لكل مستخدم)" - dailyRannum: "رقم عشوائي (يتغير مرة يوميًا لكل مستخدم)" - _dailyRannum: - arg1: "أدنى قيمة" - arg2: "أقصى قيمة" - dailyRandomPick: "اختيار عشوائي من قائمة (يتغير مرة يوميًا لكل مستخدم)" - _dailyRandomPick: - arg1: "القوائم" - seedRandom: "عشوائي (عبر بذرة)" - _seedRandom: - arg1: "البذرة" - seedRannum: "رقم عشوائي (عبر بذرة)" - _seedRannum: - arg1: "البذرة" - arg2: "أدنى قيمة" - arg3: "أقصى قيمة" - seedRandomPick: "اختيار عشوائي من القائمة (عبر بذرة)" - _seedRandomPick: - arg1: "البذرة" - arg2: "القوائم" - DRPWPM: "اختيار عشوائي من قائمة الاحتمالات (تتغير مرة يوميًا لكل مستخدم)" - _DRPWPM: - arg1: "قائمة نصية" - pick: "اختر من القائمة" - _pick: - arg1: "القوائم" - arg2: "الموضع" - listLen: "طول القائمة" - _listLen: - arg1: "القوائم" - number: "رقم" - stringToNumber: "حوّل نصًا إلى رقم" - _stringToNumber: - arg1: "نص" - numberToString: "حوّل رقمًا إلى نص" - _numberToString: - arg1: "رقم" - _splitStrByLine: - arg1: "نص" - ref: "متغيّر" - aiScriptVar: "متغيّر AiScript" - fn: "دالة" - _fn: - slots: "خانات" - arg1: "المُخرج" - for: "حلقة تكرار" - _for: - arg1: "عدد مرات التكرار" - arg2: "الإجراء" - typeError: "الخانة {slot} تقبل \"{expect}\" لكن القيمة المعطاة هي \"{actual}\"!" - thereIsEmptySlot: "الخانة {slot} فارغة!" - types: - string: "نص" - number: "رقم" - array: "القوائم" - stringArray: "قائمة نصية" - emptySlot: "خانة فارغة" - enviromentVariables: "متغيرات البيئة" - pageVariables: "متغيرات الصفحة" - argVariables: "خانة إدخال" _relayStatus: requesting: "مُعلّق" accepted: "مقبول" diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml index b8b965f1f..3ebd6f431 100644 --- a/locales/bn-BD.yml +++ b/locales/bn-BD.yml @@ -258,7 +258,6 @@ remoteUserCaution: "এই ব্যাবহারকারী রিমোট activity: "কার্যকলাপ" images: "ছবি" birthday: "জন্মদিন" -yearsOld: "{age} বছর" registeredDate: "যোগদানের তারিখ" location: "অবস্থান" theme: "থিম" @@ -473,8 +472,6 @@ dayOverDayChanges: "গতকাল" appearance: "অবয়ব" clientSettings: "ক্লায়েন্ট সেটিংস" accountSettings: "অ্যাকাউন্ট সেটিংস" -promotion: "প্রমোশন" -promote: "প্রচার করুন" numberOfDays: "দিনের সংখ্যা" hideThisNote: "নোটটি লুকান" showFeaturedNotesInTimeline: "টাইমলাইনে সুপারিশকৃত নোটগুলি দেখান" @@ -550,7 +547,6 @@ poll: "জরিপ" useCw: "কন্টেন্ট লুকান" enablePlayer: "ভিডিও প্লেয়ার খুলুন" disablePlayer: "ভিডিও প্লেয়ার বন্ধ করুন" -expandTweet: "টুইট বিস্তারিত করুন" themeEditor: "থিম সম্পাদক" description: "বর্ণনা" describeFile: "ক্যাপশন যোগ করুন" @@ -1325,10 +1321,7 @@ _pages: my: "আমার পৃষ্ঠাগুলি" liked: "পছন্দ করা পৃষ্ঠাগুলি" featured: "জনপ্রিয়" - inspector: "ইনিস্পেক্টর" contents: "বিষয়বস্তু" - content: "পৃষ্ঠার ব্লক" - variables: "চলকগুলি" title: "শিরোনাম" url: "পৃষ্ঠার URL" summary: "পৃষ্ঠার বর্ণনা" @@ -1339,262 +1332,6 @@ _pages: fontSansSerif: "স্যান্স সেরিফ" eyeCatchingImageSet: "থাম্বনেইল সেট করুন" eyeCatchingImageRemove: "থাম্বনেইল সরান" - chooseBlock: "ব্লক যোগ করুন" - selectType: "ধরন নির্বাচন করুন" - enterVariableName: "চলকের নাম লিখুন" - variableNameIsAlreadyUsed: "চলকের নামটি ইতিপূর্বে ব্যাবহৃত হয়েছে" - contentBlocks: "বিষয়বস্তু" - inputBlocks: "ইনপুট" - specialBlocks: "বিশেষ" - blocks: - text: "লেখা" - textarea: "টেক্সট এরিয়া" - section: "বিভাগ" - image: "ছবি" - button: "বাটন" - if: "যদি" - _if: - variable: "চলকগুলি" - post: "নোট লিখুন" - _post: - text: "বিষয়বস্তু" - attachCanvasImage: "ক্যানভাস ছবিসহ পোস্ট করুন" - canvasId: "ক্যানভাস ID" - textInput: "টেক্সট ইনপুট" - _textInput: - name: "চলকের নাম" - text: "শিরোনাম" - default: "ডিফল্ট মান" - textareaInput: "একাধিক লাইনের টেক্সট ইনপুট" - _textareaInput: - name: "চলকের নাম" - text: "শিরোনাম" - default: "ডিফল্ট মান" - numberInput: "সংখ্যা ইনপুট" - _numberInput: - name: "চলকের নাম" - text: "শিরোনাম" - default: "ডিফল্ট মান" - canvas: "ক্যানভাস" - _canvas: - id: "ক্যানভাস ID" - width: "প্রস্থ" - height: "উচ্চতা" - note: "এম্বেড নোট" - _note: - id: "নোট ID" - idDescription: "আপনি এর বদলে নোটের URL পেস্ট করতে পারেন." - detailed: "বিস্তারিত দেখুন" - switch: "সুইচ" - _switch: - name: "চলকের নাম" - text: "শিরোনাম" - default: "ডিফল্ট মান" - counter: "কাউন্টার" - _counter: - name: "চলকের নাম" - text: "শিরোনাম" - inc: "এভাবে মান বাড়ান" - _button: - text: "শিরোনাম" - colored: "রঙ্গিন" - action: "বাটনে ক্লিক করলে যা হবে" - _action: - dialog: "ডায়ালগ দেখান " - _dialog: - content: "বিষয়বস্তু" - resetRandom: "র‍্যানডম সিড রিসেট করুন" - pushEvent: "ইভেন্ট পাঠান" - _pushEvent: - event: "ইভেন্টের নাম" - message: "চালু হলে প্রদর্শনের জন্য বার্তা" - variable: "পাঠানো চলক" - no-variable: "কিছুই না" - callAiScript: "AiScript চালান" - _callAiScript: - functionName: "ফাংশনের নাম" - radioButton: "বহুনির্বাচনী" - _radioButton: - name: "চলকের নাম" - title: "শিরোনাম" - values: "বিকল্পগুলিকে আলাদা লাইনে লিখুন" - default: "ডিফল্ট মান" - script: - categories: - flow: "নিয়ন্ত্রণ" - logical: "লজিক্যাল অপারেশন" - operation: "হিসাব-নিকাশ" - comparison: "তুলনা" - random: "র‍্যান্ডম" - value: "মান" - fn: "ফাংশন" - text: "টেক্সট ম্যানিপুলেশন" - convert: "রুপান্তর" - list: "লিস্ট" - blocks: - text: "লেখা" - multiLineText: "লেখা (একাধিক লাইন)" - textList: "লেখার লিস্ট" - _textList: - info: "প্রতিটি এন্ট্রিকে আলাদা লাইনে লিখুন" - strLen: "লেখার দৈর্ঘ্য" - _strLen: - arg1: "লেখা" - strPick: "অক্ষর বের করে আনুন" - _strPick: - arg1: "লেখা" - arg2: "অক্ষরের অবস্থান" - strReplace: "লেখা প্রতিস্থাপন" - _strReplace: - arg1: "লেখা" - arg2: "যে লেখা প্রতিস্থাপন করা হবে" - arg3: "যা দ্বারা প্রতিস্থাপন করা হবে" - strReverse: "লেখা উল্টান" - _strReverse: - arg1: "লেখা" - join: "লেখা যুক্ত করুন" - _join: - arg1: "লিস্ট" - arg2: "বিভাজক" - add: "যোগ" - _add: - arg1: "A" - arg2: "B" - subtract: "বিয়োগ" - _subtract: - arg1: "A" - arg2: "B" - multiply: "গুন" - _multiply: - arg1: "A" - arg2: "B" - divide: "ভাগ" - _divide: - arg1: "A" - arg2: "B" - mod: "ভাগশেষ" - _mod: - arg1: "A" - arg2: "B" - round: "দশমিক রাউন্ড করুন" - _round: - arg1: "সংখ্যা" - eq: "A ও B সমান" - _eq: - arg1: "A" - arg2: "B" - notEq: "A ও B সমান না" - _notEq: - arg1: "A" - arg2: "B" - and: "A এবং B" - _and: - arg1: "A" - arg2: "B" - or: "A অথবা B" - _or: - arg1: "A" - arg2: "B" - lt: "< A , B হতে কম" - _lt: - arg1: "A" - arg2: "B" - gt: "> A , B হতে বেশী" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A , B হতে কম বা সমান" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A , B হতে বেশী বা সমান" - _gtEq: - arg1: "A" - arg2: "B" - if: "যদি" - _if: - arg1: "যদি" - arg2: "তাহলে" - arg3: "তাছাড়া" - not: "না" - _not: - arg1: "না" - random: "র‍্যান্ডম" - _random: - arg1: "সম্ভাব্যতা" - rannum: "র‍্যানডম সংখ্যা" - _rannum: - arg1: "ন্যূনতম মান" - arg2: "সর্বোচ্চ মান" - randomPick: "তালিকা থেকে দৈবচয়ন করুন" - _randomPick: - arg1: "লিস্ট" - dailyRandom: "র‍্যান্ডম সংখ্যা (প্রতিটি ব্যবহারকারীর জন্য প্রতিদিন পরিবর্তীত হয়)" - _dailyRandom: - arg1: "সম্ভাব্যতা" - dailyRannum: "র‍্যান্ডম সংখ্যা (প্রতিটি ব্যবহারকারীর জন্য প্রতিদিন পরিবর্তীত হয়)" - _dailyRannum: - arg1: "ন্যূনতম মান" - arg2: "সর্বোচ্চ মান" - dailyRandomPick: "তালিকা থেকে এলোমেলোভাবে নির্বাচন করুন (প্রতিটি ব্যবহারকারীর জন্য প্রতিদিন পরিবর্তীত হয়)" - _dailyRandomPick: - arg1: "লিস্ট" - seedRandom: "র‍্যানডম (সীড দ্বারা)" - _seedRandom: - arg1: "সীড" - arg2: "সম্ভাব্যতা" - seedRannum: "র‍্যানডম সংখ্যা (সীড দ্বারা)" - _seedRannum: - arg1: "সীড" - arg2: "ন্যূনতম মান" - arg3: "সর্বোচ্চ মান" - seedRandomPick: "তালিকা থেকে দৈবচয়ন করুন (সীড দ্বারা)" - _seedRandomPick: - arg1: "সীড" - arg2: "লিস্ট" - DRPWPM: "সম্ভাব্যতা সহ একটি তালিকা থেকে এলোমেলোভাবে নির্বাচন করুন (প্রতিটি ব্যবহারকারীর জন্য প্রতিদিন)" - _DRPWPM: - arg1: "লেখার লিস্ট" - pick: "তালিকা থেকে নির্বাচন করুন" - _pick: - arg1: "লিস্ট" - arg2: "অবস্থান" - listLen: "লিস্টের দৈর্ঘ্য পান" - _listLen: - arg1: "লিস্ট" - number: "সংখ্যা" - stringToNumber: "পাঠ্য থেকে সংখ্যা" - _stringToNumber: - arg1: "লেখা" - numberToString: "সংখ্যা থেকে পাঠ্য" - _numberToString: - arg1: "সংখ্যা" - splitStrByLine: "পাঠ্যকে লাইনে বিভক্ত করুন" - _splitStrByLine: - arg1: "লেখা" - ref: "চলক" - aiScriptVar: "AiScript চলক" - fn: "ফাংশন" - _fn: - slots: "স্লটগুলি" - slots-info: "প্রতিটি স্লটকে আলাদা লাইনে লিখুন" - arg1: "আউটপুট" - for: "for-লুপ" - _for: - arg1: "কতবার চলবে" - arg2: "অ্যাকশন" - typeError: "স্লট {slot}, {expect} ধরনের মান গ্রহণ করে, কিন্তু {actual} ধরনের মান দেওয়া হয়েছে!" - thereIsEmptySlot: "স্লট {slot} খালি!" - types: - string: "লেখা" - number: "সংখ্যা" - boolean: "ফ্ল্যাগ" - array: "লিস্ট" - stringArray: "লেখার লিস্ট" - emptySlot: "খালি স্লট" - enviromentVariables: "এনভাইরনমেন্ট ভ্যারিয়েবল" - pageVariables: "পেজের চলক" - argVariables: "ইনপুটের জায়গা" _relayStatus: requesting: "অপেক্ষমান" accepted: "অনুমোদিত" diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 64bc25862..50961ca99 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -147,25 +147,6 @@ _profile: _exportOrImport: followingList: "Seguint" userLists: "Llistes" -_pages: - script: - categories: - list: "Llistes" - blocks: - _join: - arg1: "Llistes" - _randomPick: - arg1: "Llistes" - _dailyRandomPick: - arg1: "Llistes" - _seedRandomPick: - arg2: "Llistes" - _pick: - arg1: "Llistes" - _listLen: - arg1: "Llistes" - types: - array: "Llistes" _notification: youWereFollowed: "t'ha seguit" _types: diff --git a/locales/cs-CZ.yml b/locales/cs-CZ.yml index 2de4b36e2..0f50ef8d3 100644 --- a/locales/cs-CZ.yml +++ b/locales/cs-CZ.yml @@ -241,7 +241,6 @@ remoteUserCaution: "Tyto informace nemusí být aktuální jelikož uživatel je activity: "Aktivita" images: "Obrázky" birthday: "Datum narození" -yearsOld: "{age} let" registeredDate: "Datum registrace" location: "Lokace" theme: "Vzhled" @@ -407,8 +406,6 @@ dayOverDayChanges: "Denně" appearance: "Vzhled" clientSettings: "Nastavení klienta" accountSettings: "Nastavení účtu" -promotion: "Propagace" -promote: "Propagovat" numberOfDays: "Počet dní" deleteAll: "Smazat vše" showFixedPostForm: "Zobrazit formulář pro nové příspěvky nad časovou osou" @@ -513,27 +510,6 @@ _charts: federation: "Federace" _timelines: home: "Domů" -_pages: - blocks: - image: "Obrázky" - script: - categories: - list: "Seznamy" - blocks: - _join: - arg1: "Seznamy" - _randomPick: - arg1: "Seznamy" - _dailyRandomPick: - arg1: "Seznamy" - _seedRandomPick: - arg2: "Seznamy" - _pick: - arg1: "Seznamy" - _listLen: - arg1: "Seznamy" - types: - array: "Seznamy" _notification: youWereFollowed: "Máte nového následovníka" youWereInvitedToGroup: "Pozvat do skupiny" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index 7f96967b6..c3f6c0af5 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -259,7 +259,6 @@ remoteUserCaution: "Diese Informationen sind möglicherweise unvollständig, da activity: "Aktivität" images: "Bilder" birthday: "Geburtstag" -yearsOld: "{age} Jahre alt" registeredDate: "Registrationsdatum" location: "Ort" theme: "Farbschema" @@ -474,8 +473,6 @@ dayOverDayChanges: "Veränderung zu Gestern" appearance: "Aussehen" clientSettings: "Client-Einstellungen" accountSettings: "Benutzerkonto-Einstellungen" -promotion: "Werbung" -promote: "Werbung schalten" numberOfDays: "Anzahl der Tage" hideThisNote: "Diese Notiz verstecken" showFeaturedNotesInTimeline: "Beliebte Notizen in der Chronik anzeigen" @@ -551,7 +548,6 @@ poll: "Umfrage" useCw: "Inhaltswarnung verwenden" enablePlayer: "Video-Player öffnen" disablePlayer: "Video-Player schließen" -expandTweet: "Tweet ausklappen" themeEditor: "Farbschema-Editor" description: "Beschreibung" describeFile: "Beschreibung hinzufügen" @@ -1328,10 +1324,7 @@ _pages: my: "Meine Seiten" liked: "Seiten, die mir gefallen" featured: "Beliebt" - inspector: "Inspektor" contents: "Inhalte" - content: "Seitenblock" - variables: "Variablen" title: "Titel" url: "Seiten-URL" summary: "Zusammenfassung" @@ -1342,262 +1335,6 @@ _pages: fontSansSerif: "Sans Serif" eyeCatchingImageSet: "Vorschaubild festlegen" eyeCatchingImageRemove: "Vorschaubild entfernen" - chooseBlock: "Block hinzufügen" - selectType: "Typ auswählen" - enterVariableName: "Gib einen Variablennamen ein" - variableNameIsAlreadyUsed: "Dieser Name wird bereits von einer anderen Variable verwendet" - contentBlocks: "Inhalt" - inputBlocks: "Eingabe" - specialBlocks: "Spezial" - blocks: - text: "Text" - textarea: "Textfeld" - section: "Abschnitt" - image: "Bild" - button: "Knopf" - if: "Falls" - _if: - variable: "Variable" - post: "Notizfenster" - _post: - text: "Inhalt" - attachCanvasImage: "Leinwandbild anfügen" - canvasId: "Leinwand-ID" - textInput: "Texteingabe" - _textInput: - name: "Variablenname" - text: "Titel" - default: "Standardwert" - textareaInput: "Mehrzeiliges Texteingabefeld" - _textareaInput: - name: "Variablenname" - text: "Titel" - default: "Standardwert" - numberInput: "Zahleneingabe" - _numberInput: - name: "Variablenname" - text: "Titel" - default: "Standardwert" - canvas: "Leinwand" - _canvas: - id: "Leinwand-ID" - width: "Breite" - height: "Höhe" - note: "Eingebettete Notiz" - _note: - id: "Notiz-ID" - idDescription: "Du kannst alternativ auch die Notiz-URL angeben." - detailed: "Detailierte Ansicht" - switch: "Fallunterscheidung" - _switch: - name: "Variablenname" - text: "Titel" - default: "Standardwert" - counter: "Zähler" - _counter: - name: "Variablenname" - text: "Titel" - inc: "Schrittgröße" - _button: - text: "Titel" - colored: "Farbig" - action: "Aktion, die bei Knopfdruck ausgeführt wird" - _action: - dialog: "Dialogfenster anzeigen" - _dialog: - content: "Inhalt" - resetRandom: "Zufallswert zurücksetzen" - pushEvent: "Ein Event senden" - _pushEvent: - event: "Eventname" - message: "Nachricht, die bei Auslösung des Events angezeigt werden soll" - variable: "Variable, die gesendet werden soll" - no-variable: "Keine" - callAiScript: "AiScript ausführen" - _callAiScript: - functionName: "Funktionsname" - radioButton: "Optionsfeld" - _radioButton: - name: "Variablenname" - title: "Titel" - values: "Durch Zeilenümbrüche getrennte Auswahlmöglichkeiten" - default: "Standardwert" - script: - categories: - flow: "Steuerung" - logical: "Logische Operationen" - operation: "Berechnungen" - comparison: "Vergleiche" - random: "Zufällig" - value: "Werte" - fn: "Funktionen" - text: "Textoperationen" - convert: "Konvertierungen" - list: "Listen" - blocks: - text: "Text" - multiLineText: "Text (Mehrzeilig)" - textList: "Textliste" - _textList: - info: "Trenne jeden Eintrag mit einem Zeilenumbruch" - strLen: "Textlänge" - _strLen: - arg1: "Text" - strPick: "Text extrahieren" - _strPick: - arg1: "Text" - arg2: "Textposition" - strReplace: "Textersetzung" - _strReplace: - arg1: "Text" - arg2: "Zu ersetzender Text" - arg3: "Ersetzen mit" - strReverse: "Text umkehren" - _strReverse: - arg1: "Text" - join: "Text zusammenfügen" - _join: - arg1: "Liste" - arg2: "Trennzeichen" - add: "Addieren" - _add: - arg1: "A" - arg2: "B" - subtract: "Subtrahieren" - _subtract: - arg1: "A" - arg2: "B" - multiply: "Multiplizieren" - _multiply: - arg1: "A" - arg2: "B" - divide: "Teilen" - _divide: - arg1: "A" - arg2: "B" - mod: "Rest" - _mod: - arg1: "A" - arg2: "B" - round: "Rundung von Dezimalstellen" - _round: - arg1: "Nummer" - eq: "A und B sind gleich" - _eq: - arg1: "A" - arg2: "B" - notEq: "A und B sind nicht gleich" - _notEq: - arg1: "A" - arg2: "B" - and: "A UND B" - _and: - arg1: "A" - arg2: "B" - or: "A ODER B" - _or: - arg1: "A" - arg2: "B" - lt: "< A ist kleiner als B" - _lt: - arg1: "A" - arg2: "B" - gt: "> A ist größer als B" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A ist kleiner als oder gleich B" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A ist größer als oder gleich B" - _gtEq: - arg1: "A" - arg2: "B" - if: "Kondition" - _if: - arg1: "Falls" - arg2: "Wenn wahr" - arg3: "Sonst" - not: "NICHT" - _not: - arg1: "NICHT" - random: "Zufällig" - _random: - arg1: "Warscheinlichkeit" - rannum: "Zufallsnummer" - _rannum: - arg1: "Minimum" - arg2: "Maximum" - randomPick: "Zufallswahl aus Liste" - _randomPick: - arg1: "Liste" - dailyRandom: "Zufällig (Pro Nutzer jeden Tag verschieden)" - _dailyRandom: - arg1: "Warscheinlichkeit" - dailyRannum: "Zufallsnummer (Pro Nutzer jeden Tag verschieden)" - _dailyRannum: - arg1: "Minimum" - arg2: "Maximum" - dailyRandomPick: "Zufallsauswahl aus einer Liste (Pro Nutzer jeden Tag verschieden)" - _dailyRandomPick: - arg1: "Liste" - seedRandom: "Zufällig (mit Startwert / Seed)" - _seedRandom: - arg1: "Startwert / Seed" - arg2: "Warscheinlichkeit" - seedRannum: "Zufallsnummer (mit Startwert / Seed)" - _seedRannum: - arg1: "Startwert / Seed" - arg2: "Minimum" - arg3: "Maximum" - seedRandomPick: "Zufallsauswahl aus Liste (mit Startwert / Seed)" - _seedRandomPick: - arg1: "Startwert / Seed" - arg2: "Liste" - DRPWPM: "Zufallsauswahl aus gewichteter Liste (Pro Nutzer jeden Tag verschieden)" - _DRPWPM: - arg1: "Textliste" - pick: "Aus einer Liste wählen" - _pick: - arg1: "Liste" - arg2: "Position" - listLen: "Listenlänge abrufen" - _listLen: - arg1: "Liste" - number: "Nummer" - stringToNumber: "Text zu Nummer" - _stringToNumber: - arg1: "Text" - numberToString: "Nummer zu Text" - _numberToString: - arg1: "Nummer" - splitStrByLine: "Text nach Zeilenumbrüchen aufteilen" - _splitStrByLine: - arg1: "Text" - ref: "Variable" - aiScriptVar: "AiScript Variable" - fn: "Funktion" - _fn: - slots: "Slots" - slots-info: "Trenne jeden Slot mit einem Zeilenumbruch" - arg1: "Ausgabe" - for: "for-Schleife" - _for: - arg1: "Anzahl der Schleifendurchläufe" - arg2: "Aktion" - typeError: "Slot {slot} akzeptiert Werte vom Typ „{expect}“, aber es wurde ein „{actual}“ Wert angegeben!" - thereIsEmptySlot: "Slot {slot} ist leer!" - types: - string: "Text" - number: "Nummer" - boolean: "Wahrheitswert" - array: "Liste" - stringArray: "Textliste" - emptySlot: "Leerer Slot" - enviromentVariables: "Umgebungsvariable" - pageVariables: "Seitenelemente" - argVariables: "Eingabeslots" _relayStatus: requesting: "Ausstehend" accepted: "Akzeptiert" diff --git a/locales/en-US.yml b/locales/en-US.yml index 404fbc4e2..61b57ceae 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -259,7 +259,6 @@ remoteUserCaution: "As this user is from a remote instance, the shown informatio activity: "Activity" images: "Images" birthday: "Birthday" -yearsOld: "{age} years old" registeredDate: "Joined on" location: "Location" theme: "Themes" @@ -474,8 +473,6 @@ dayOverDayChanges: "Changes to yesterday" appearance: "Appearance" clientSettings: "Client Settings" accountSettings: "Account Settings" -promotion: "Promoted" -promote: "Promote" numberOfDays: "Number of days" hideThisNote: "Hide this note" showFeaturedNotesInTimeline: "Show featured notes in timelines" @@ -551,7 +548,6 @@ poll: "Poll" useCw: "Hide content" enablePlayer: "Open video player" disablePlayer: "Close video player" -expandTweet: "Expand tweet" themeEditor: "Theme editor" description: "Description" describeFile: "Add caption" @@ -1344,10 +1340,7 @@ _pages: my: "My Pages" liked: "Liked Pages" featured: "Popular" - inspector: "Inspector" contents: "Contents" - content: "Page block" - variables: "Variables" title: "Title" url: "Page URL" summary: "Page summary" @@ -1358,262 +1351,6 @@ _pages: fontSansSerif: "Sans Serif" eyeCatchingImageSet: "Set thumbnail" eyeCatchingImageRemove: "Delete thumbnail" - chooseBlock: "Add a block" - selectType: "Select a type" - enterVariableName: "Enter a variable name" - variableNameIsAlreadyUsed: "This variable name is already in use" - contentBlocks: "Content" - inputBlocks: "Input" - specialBlocks: "Special" - blocks: - text: "Text" - textarea: "Text area" - section: "Section" - image: "Images" - button: "Button" - if: "If" - _if: - variable: "Variable" - post: "Posting form" - _post: - text: "Content" - attachCanvasImage: "Attach canvas image" - canvasId: "Canvas ID" - textInput: "Text input" - _textInput: - name: "Variable name" - text: "Title" - default: "Default value" - textareaInput: "Multiline text input" - _textareaInput: - name: "Variable name" - text: "Title" - default: "Default value" - numberInput: "Numeric input" - _numberInput: - name: "Variable name" - text: "Title" - default: "Default value" - canvas: "Canvas" - _canvas: - id: "Canvas ID" - width: "Width" - height: "Height" - note: "Embedded note" - _note: - id: "Note ID" - idDescription: "You can alternatively paste the note URL here." - detailed: "Detailed view" - switch: "Switch" - _switch: - name: "Variable name" - text: "Title" - default: "Default value" - counter: "Counter" - _counter: - name: "Variable name" - text: "Title" - inc: "Step" - _button: - text: "Title" - colored: "Colored" - action: "Behavior when the button is pressed" - _action: - dialog: "Show a dialog" - _dialog: - content: "Content" - resetRandom: "Reset the random seed" - pushEvent: "Send an event" - _pushEvent: - event: "Event name" - message: "Message to display when activated" - variable: "Variable to send" - no-variable: "None" - callAiScript: "Invoke AiScript" - _callAiScript: - functionName: "Function name" - radioButton: "Choice" - _radioButton: - name: "Variable name" - title: "Title" - values: "List of choices separated by line breaks" - default: "Default value" - script: - categories: - flow: "Flow control" - logical: "Logical operation" - operation: "Computation" - comparison: "Comparison" - random: "Random" - value: "Values" - fn: "Functions" - text: "Text operations" - convert: "Transformations" - list: "Lists" - blocks: - text: "Text" - multiLineText: "Text (multiline)" - textList: "Text list" - _textList: - info: "Separate each entry with a line break" - strLen: "Text length" - _strLen: - arg1: "Text" - strPick: "Extract string" - _strPick: - arg1: "Text" - arg2: "String location" - strReplace: "Replacement string" - _strReplace: - arg1: "Text" - arg2: "Text to be replaced" - arg3: "Replace with" - strReverse: "Flip text" - _strReverse: - arg1: "Text" - join: "Text concatenation" - _join: - arg1: "Lists" - arg2: "Separator" - add: "Add" - _add: - arg1: "A" - arg2: "B" - subtract: "Subtract" - _subtract: - arg1: "A" - arg2: "B" - multiply: "Multiply" - _multiply: - arg1: "A" - arg2: "B" - divide: "Divide" - _divide: - arg1: "A" - arg2: "B" - mod: "Remainder" - _mod: - arg1: "A" - arg2: "B" - round: "Decimal rounding" - _round: - arg1: "Number" - eq: "A and B are equal" - _eq: - arg1: "A" - arg2: "B" - notEq: "A and B are different" - _notEq: - arg1: "A" - arg2: "B" - and: "A AND B" - _and: - arg1: "A" - arg2: "B" - or: "A OR B" - _or: - arg1: "A" - arg2: "B" - lt: "< A is less than B" - _lt: - arg1: "A" - arg2: "B" - gt: "> A is larger than B" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A is less than or equal to B" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A is greater than or equal to B" - _gtEq: - arg1: "A" - arg2: "B" - if: "Branch" - _if: - arg1: "If" - arg2: "Then" - arg3: "Else" - not: "NOT" - _not: - arg1: "NOT" - random: "Random" - _random: - arg1: "Probability" - rannum: "Random number" - _rannum: - arg1: "Minimum value" - arg2: "Maximum value" - randomPick: "Randomly choose from list" - _randomPick: - arg1: "List" - dailyRandom: "Random (Changes once a day for each user)" - _dailyRandom: - arg1: "Probability" - dailyRannum: "Random number (Changes once a day for each user)" - _dailyRannum: - arg1: "Minimum value" - arg2: "Maximum value" - dailyRandomPick: "Randomly choose from a list (Changes once a day for each user)" - _dailyRandomPick: - arg1: "List" - seedRandom: "Random (with seed)" - _seedRandom: - arg1: "Seed" - arg2: "Probability" - seedRannum: "Random number (with seed)" - _seedRannum: - arg1: "Seed" - arg2: "Minimum value" - arg3: "Maximum value" - seedRandomPick: "Randomly choose from list (with seed)" - _seedRandomPick: - arg1: "Seed" - arg2: "List" - DRPWPM: "Randomly choose from weighted list (Changes once a day for each user)" - _DRPWPM: - arg1: "Text list" - pick: "Select from list" - _pick: - arg1: "List" - arg2: "Position" - listLen: "Get length of list" - _listLen: - arg1: "List" - number: "Number" - stringToNumber: "Text to number" - _stringToNumber: - arg1: "Text" - numberToString: "Number to text" - _numberToString: - arg1: "Number" - splitStrByLine: "Split text by line breaks" - _splitStrByLine: - arg1: "Text" - ref: "Variable" - aiScriptVar: "AiScript Variable" - fn: "Function" - _fn: - slots: "Slots" - slots-info: "Separate each slot with a line break" - arg1: "Output" - for: "for-Loop" - _for: - arg1: "Number of times to repeat" - arg2: "Action" - typeError: "Slot {slot} accepts values of type \"{expect}\", but the provided value is of type \"{actual}\"!" - thereIsEmptySlot: "Slot {slot} is empty!" - types: - string: "Text" - number: "Number" - boolean: "Flag" - array: "List" - stringArray: "Text list" - emptySlot: "Empty slot" - enviromentVariables: "Environment variables" - pageVariables: "Page variables" - argVariables: "Input slots" _relayStatus: requesting: "Pending" accepted: "Accepted" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 4f38eda30..16cccdcec 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -258,7 +258,6 @@ remoteUserCaution: "Para el usuario remoto, la información está incompleta" activity: "Actividad" images: "Imágenes" birthday: "Fecha de nacimiento" -yearsOld: "{age} años" registeredDate: "Fecha de registro" location: "Lugar" theme: "Tema" @@ -473,8 +472,6 @@ dayOverDayChanges: "Dif diaria" appearance: "Apariencia" clientSettings: "Configuración del cliente" accountSettings: "Ajustes de cuenta" -promotion: "Promovido" -promote: "Promover" numberOfDays: "Cantidad de dias" hideThisNote: "Ocultar esta nota" showFeaturedNotesInTimeline: "Mostrar notas destacadas en la línea de tiempo" @@ -550,7 +547,6 @@ poll: "Encuesta" useCw: "Esconder contenidos" enablePlayer: "Abrir reproductor" disablePlayer: "Cerrar reproductor" -expandTweet: "Expandir tweet" themeEditor: "Editor de temas" description: "Descripción" describeFile: "Añade una descripción" @@ -1208,10 +1204,7 @@ _pages: unlike: "Quitar me gusta" my: "Mis páginas" liked: "Páginas que me gustan" - inspector: "Inspector" contents: "Contenido" - content: "Bloque de página" - variables: "Variables" title: "Título" url: "URL de la página" summary: "Resumen de la página" @@ -1222,257 +1215,6 @@ _pages: fontSansSerif: "Sans Serif" eyeCatchingImageSet: "Elegir imagen llamativa" eyeCatchingImageRemove: "Borrar imagen llamativa" - chooseBlock: "Agregar bloque" - selectType: "Elegir tipo" - enterVariableName: "Ingrese el nombre de la variable" - variableNameIsAlreadyUsed: "El nombre de la variable ya está en uso" - contentBlocks: "Contenido" - inputBlocks: "Entrada" - specialBlocks: "Especial" - blocks: - text: "Texto" - textarea: "Área de texto" - section: "Sección" - image: "Imagen" - button: "Botón" - if: "si" - _if: - variable: "Variable" - post: "Formulario" - _post: - text: "Contenido" - attachCanvasImage: "Nota con lienzo como imagen" - canvasId: "Lienzo ID" - textInput: "Entrada de texto" - _textInput: - name: "Nombre de variable" - text: "Título" - default: "Valor predeterminado" - textareaInput: "Entrada de texto en múltiples lineas" - _textareaInput: - name: "Nombre de variable" - text: "Título" - default: "Valor predeterminado" - numberInput: "Entrada numérica" - _numberInput: - name: "Nombre de variable" - text: "Título" - default: "Valor predeterminado" - canvas: "Lienzo" - _canvas: - id: "Lienzo ID" - width: "Ancho" - height: "Altura" - switch: "Interruptor" - _switch: - name: "Nombre de variable" - text: "Título" - default: "Valor predeterminado" - counter: "Contador" - _counter: - name: "Nombre de variable" - text: "Título" - inc: "Aumentar cantidad" - _button: - text: "Título" - colored: "Color" - action: "Acción al presionar el botón" - _action: - dialog: "Mostrar cuadro de diálogo" - _dialog: - content: "Contenido" - resetRandom: "Resetear número aleatorio" - pushEvent: "Enviar evento" - _pushEvent: - event: "Nombre del evento" - message: "Mensaje mostrado al apretar" - variable: "Variable a enviar" - no-variable: "Ninguna" - callAiScript: "Invocar AiScript" - _callAiScript: - functionName: "Nombre de la función" - radioButton: "Botón de opción" - _radioButton: - name: "Nombre de variable" - title: "Título" - values: "Opciones separadas por una nueva linea" - default: "Valor predeterminado" - script: - categories: - flow: "Control de flujo" - logical: "Operación lógica" - operation: "Cálculo" - comparison: "Comparar" - random: "Aleatorio" - value: "Valores" - fn: "funciones" - text: "Manejo de texto" - convert: "Conversion" - list: "Listas" - blocks: - text: "Texto" - multiLineText: "Texto (multilinea)" - textList: "Lista de texto" - _textList: - info: "Separe cada texto con una linea nueva" - strLen: "Largo del texto" - _strLen: - arg1: "Texto" - strPick: "Extraer caracteres" - _strPick: - arg1: "Texto" - arg2: "Posición del caracter" - strReplace: "Sustituir texto" - _strReplace: - arg1: "Texto" - arg2: "Texto a reemplazar" - arg3: "Texto reemplazado" - strReverse: "Invertir texto" - _strReverse: - arg1: "Texto" - join: "Concatenar texto" - _join: - arg1: "Listas" - arg2: "Separador" - add: "Suma" - _add: - arg1: "A" - arg2: "B" - subtract: "Resta" - _subtract: - arg1: "A" - arg2: "B" - multiply: "Multiplicación" - _multiply: - arg1: "A" - arg2: "B" - divide: "División" - _divide: - arg1: "A" - arg2: "B" - mod: "Resto" - _mod: - arg1: "A" - arg2: "B" - round: "Redondear decimales" - _round: - arg1: "Número" - eq: "A y B son iguales" - _eq: - arg1: "A" - arg2: "B" - notEq: "A y B son distintos" - _notEq: - arg1: "A" - arg2: "B" - and: "A y B" - _and: - arg1: "A" - arg2: "B" - or: "A o B" - _or: - arg1: "A" - arg2: "B" - lt: "< A es menor que B" - _lt: - arg1: "A" - arg2: "B" - gt: "> A es mayor que B" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A es menor o igual que B" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A es mayor o igual que B" - _gtEq: - arg1: "A" - arg2: "B" - if: "Si" - _if: - arg1: "si" - arg2: "Entonces" - arg3: "Si no" - not: "Negación" - _not: - arg1: "Negación" - random: "Aleatorio" - _random: - arg1: "probabilidad" - rannum: "Número aleatorio" - _rannum: - arg1: "Mínimo" - arg2: "Máximo" - randomPick: "Elegir aleatoriamente de la lista" - _randomPick: - arg1: "Listas" - dailyRandom: "Aleatorio (Diariamente para cada usuario)" - _dailyRandom: - arg1: "probabilidad" - dailyRannum: "Número aleatorio (Diariamente para cada usuario)" - _dailyRannum: - arg1: "Mínimo" - arg2: "Máximo" - dailyRandomPick: "Elegir aleatoriamente de la lista (Diariamente para cada usuario)" - _dailyRandomPick: - arg1: "Listas" - seedRandom: "Aleatorio (semilla)" - _seedRandom: - arg1: "Semilla" - arg2: "probabilidad" - seedRannum: "Número aleatorio (semilla)" - _seedRannum: - arg1: "Semilla" - arg2: "Mínimo" - arg3: "Máximo" - seedRandomPick: "Elegir aleatoriamente de la lista (semilla)" - _seedRandomPick: - arg1: "Semilla" - arg2: "Listas" - DRPWPM: "Elegir aleatoriamente de la lista ponderada (Diariamente para cada usuario)" - _DRPWPM: - arg1: "Lista de texto" - pick: "Elegir de la lista" - _pick: - arg1: "Listas" - arg2: "Posición" - listLen: "Obtener largo de la lista" - _listLen: - arg1: "Listas" - number: "Número" - stringToNumber: "De texto a número" - _stringToNumber: - arg1: "Texto" - numberToString: "De número a texto" - _numberToString: - arg1: "Número" - splitStrByLine: "Separar texto en lineas" - _splitStrByLine: - arg1: "Texto" - ref: "Variables" - aiScriptVar: "Variable de AiScript" - fn: "funciones" - _fn: - slots: "Slots" - slots-info: "Separe cada uno de los slots con una linea nueva" - arg1: "Salida" - for: "Repetir" - _for: - arg1: "Cantidad de repeticiones" - arg2: "Acción" - typeError: "El slot {slot} acepta el tipo {expect} pero fue ingresado el tipo {actual}" - thereIsEmptySlot: "El slot {slot} está vacío" - types: - string: "Texto" - number: "Número" - boolean: "Booleano" - array: "Listas" - stringArray: "Lista de texto" - emptySlot: "Slot vacío" - enviromentVariables: "Variables de entorno" - pageVariables: "Items de la página" - argVariables: "Slot de entrada" _relayStatus: requesting: "Pendiente" accepted: "Aceptar" diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index b1bcebd5a..188963ae8 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -256,7 +256,6 @@ remoteUserCaution: "Les informations de ce compte risqueraient d’être incompl activity: "Activité" images: "Images" birthday: "Date de naissance" -yearsOld: "{age} ans" registeredDate: "Inscrit le" location: "Localisation" theme: "Thème" @@ -470,8 +469,6 @@ dayOverDayChanges: "Journalier" appearance: "Apparence" clientSettings: "Paramètres du client" accountSettings: "Paramètres du compte" -promotion: "Promu" -promote: "Promouvoir" numberOfDays: "Nombre de jours" hideThisNote: "Masquer cette note" showFeaturedNotesInTimeline: "Afficher les notes des Tendances dans le fil d'actualité" @@ -547,7 +544,6 @@ poll: "Sondage" useCw: "Masquer le contenu" enablePlayer: "Ouvrir dans le lecteur vidéo" disablePlayer: "Fermer le lecteur vidéo" -expandTweet: "Étendre le tweet" themeEditor: "Éditeur de thèmes" description: "Description" describeFile: "Ajouter une description d'image" @@ -1311,10 +1307,7 @@ _pages: my: "Mes pages" liked: "Pages favorites" featured: "Populaire" - inspector: "Inspecteur" contents: "Contenu" - content: "Bloc de page" - variables: "Variables" title: "Titre" url: "URL de la page" summary: "Résumé de page" @@ -1325,262 +1318,6 @@ _pages: fontSansSerif: "Sans Serif" eyeCatchingImageSet: "Définir une image attractive" eyeCatchingImageRemove: "Supprimer l'image attractive" - chooseBlock: "Ajouter un bloc" - selectType: "Choisir un type" - enterVariableName: "Veuillez entrer un nom pour votre variable" - variableNameIsAlreadyUsed: "Ce nom de variable est déjà utilisé" - contentBlocks: "Contenu" - inputBlocks: "Blocs d'entrée" - specialBlocks: "Spécial" - blocks: - text: "Texte" - textarea: "Zone de texte" - section: "Section" - image: "Images" - button: "Bouton" - if: "Si" - _if: - variable: "Variables" - post: "Formulaire de publication" - _post: - text: "Contenu" - attachCanvasImage: "Publier avec Toile comme image" - canvasId: "Toile ID" - textInput: "Entrée textuelle" - _textInput: - name: "Nom de la variable" - text: "Titre" - default: "Valeur par défaut" - textareaInput: "Entrée textuelle multi-ligne" - _textareaInput: - name: "Nom de la variable" - text: "Titre" - default: "Valeur par défaut" - numberInput: "Entrée numérique" - _numberInput: - name: "Nom de la variable" - text: "Titre" - default: "Valeur par défaut" - canvas: "Toile" - _canvas: - id: "Toile ID" - width: "Largeur" - height: "Hauteur" - note: "Note intégrée" - _note: - id: "Identifiant de la note" - idDescription: "Pour configurer la note, vous pouvez aussi coller ici l'URL correspondante." - detailed: "Afficher les détails" - switch: "Interrupteur" - _switch: - name: "Nom de la variable" - text: "Titre" - default: "Valeur par défaut" - counter: "Compteur" - _counter: - name: "Nom de la variable" - text: "Titre" - inc: "Augmenter de" - _button: - text: "Titre" - colored: "Coloré" - action: "Opération à effectuer lorsque le bouton est pressé" - _action: - dialog: "Afficher une fenêtre de dialogue" - _dialog: - content: "Contenu" - resetRandom: "Réinitialiser un nombre aléatoire" - pushEvent: "Envoyer un évènement" - _pushEvent: - event: "Nom de l’évènement" - message: "Message à afficher lorsqu’il est activé" - variable: "Variable à envoyer" - no-variable: "Rien" - callAiScript: "Appeler AiScript" - _callAiScript: - functionName: "Nom de la fonction" - radioButton: "Choix" - _radioButton: - name: "Nom de la variable" - title: "Titre" - values: "Liste des choix (un par ligne)" - default: "Valeur par défaut" - script: - categories: - flow: "Contrôle" - logical: "Opération logique" - operation: "Calculer" - comparison: "Comparer" - random: "Aléatoire" - value: "Valeur" - fn: "Fonction" - text: "Manipulation de texte" - convert: "Convertir" - list: "Listes" - blocks: - text: "Texte" - multiLineText: "Texte (multi-ligne)" - textList: "Liste de texte" - _textList: - info: "Veuillez séparer chaque entrée avec un saut de ligne" - strLen: "Longueur du texte" - _strLen: - arg1: "Texte" - strPick: "Extraire un caractère" - _strPick: - arg1: "Texte" - arg2: "Position du joueur" - strReplace: "Remplacement de texte" - _strReplace: - arg1: "Texte" - arg2: "Avant le remplacement" - arg3: "Après le remplacement" - strReverse: "Inverser le texte" - _strReverse: - arg1: "Texte" - join: "Concaténer du texte" - _join: - arg1: "Listes" - arg2: "Séparateur" - add: "Ajouter" - _add: - arg1: "A" - arg2: "B" - subtract: "Soustraire" - _subtract: - arg1: "A" - arg2: "B" - multiply: "Multiplier par" - _multiply: - arg1: "A" - arg2: "B" - divide: "Diviser par" - _divide: - arg1: "A" - arg2: "B" - mod: "Reste" - _mod: - arg1: "A" - arg2: "B" - round: "Arrondir les décimales" - _round: - arg1: "Numérique" - eq: "A et B sont égaux" - _eq: - arg1: "A" - arg2: "B" - notEq: "A et B sont différents" - _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 inférieur à B" - _lt: - arg1: "A" - arg2: "B" - gt: "A est supérieur à B" - _gt: - arg1: "A" - arg2: "B" - ltEq: "A est inférieur ou égal à B" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: "A est supérieur ou égal à B" - _gtEq: - arg1: "A" - arg2: "B" - if: "Branche" - _if: - arg1: "Si" - arg2: "Si" - arg3: "Sinon" - not: "Nier" - _not: - arg1: "Nier" - random: "Aléatoire" - _random: - arg1: "Probabilité" - rannum: "Nombre aléatoire" - _rannum: - arg1: "Minimum" - arg2: "Maximum" - randomPick: "Sélectionner au hasard dans la liste" - _randomPick: - arg1: "Listes" - dailyRandom: "Aléatoire (Quotidien pour chaque utilisateur)" - _dailyRandom: - arg1: "Probabilité" - dailyRannum: "Numéros aléatoires (Quotidien pour chaque utilisateur)" - _dailyRannum: - arg1: "Minimum" - arg2: "Maximum" - dailyRandomPick: "Sélectionné au hasard dans la liste (Quotidien pour chaque utilisateur)" - _dailyRandomPick: - arg1: "Listes" - seedRandom: "Aléatoire (graine)" - _seedRandom: - arg1: "Graine" - arg2: "Probabilité" - seedRannum: "Nombre aléatoire (Graine)" - _seedRannum: - arg1: "Graine" - arg2: "Minimum" - arg3: "Maximum" - seedRandomPick: "Sélectionné au hasard dans la liste (graine)" - _seedRandomPick: - arg1: "Graine" - arg2: "Listes" - DRPWPM: "Sélectionné au hasard dans une liste de probabilités (Quotidien pour chaque utilisateur)" - _DRPWPM: - arg1: "Liste de texte" - pick: "Sélectionner dans la liste" - _pick: - arg1: "Listes" - arg2: "Position" - listLen: "Longueur de la liste" - _listLen: - arg1: "Listes" - number: "Numérique" - stringToNumber: "Convertir du texte en numérique" - _stringToNumber: - arg1: "Texte" - numberToString: "Convertir du numérique en texte" - _numberToString: - arg1: "Numérique" - splitStrByLine: "Séparer le texte par des sauts de lignes" - _splitStrByLine: - arg1: "Texte" - ref: "Variables" - aiScriptVar: "Variable d'AiScript" - fn: "Fonction" - _fn: - slots: "Slots" - slots-info: "Veuillez insérer un seul slot par ligne" - arg1: "Sortie" - for: "Répéter" - _for: - arg1: "Compter" - arg2: "Action" - typeError: "Le slot {slot} accepte \"{expect}\" mais a \"{actual}\" !" - 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" - argVariables: "Entrée slot" _relayStatus: requesting: "En attente" accepted: "Accepté" diff --git a/locales/id-ID.yml b/locales/id-ID.yml index e51715aec..d1e16f3ee 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -258,7 +258,6 @@ remoteUserCaution: "Informasi ini mungkin tidak mutakhir, karena pengguna ini be activity: "Aktivitas" images: "Gambar" birthday: "Tanggal lahir" -yearsOld: "{age} tahun" registeredDate: "Bergabung pada" location: "Lokasi" theme: "Tema" @@ -473,8 +472,6 @@ dayOverDayChanges: "Harian" appearance: "Tampilan" clientSettings: "Pengaturan Klien" accountSettings: "Pengaturan Akun" -promotion: "Promosi" -promote: "Promosikan" numberOfDays: "Jumlah hari" hideThisNote: "Sembunyikan catatan ini" showFeaturedNotesInTimeline: "Tampilkan catatan yang diunggulkan di linimasa" @@ -550,7 +547,6 @@ poll: "Angket" useCw: "Sembunyikan konten" enablePlayer: "Buka pemutar video" disablePlayer: "Tutup pemutar video" -expandTweet: "Perluas utas" themeEditor: "Penyunting tema" description: "Deskripsi" describeFile: "Tambahkan keterangan" @@ -1327,10 +1323,7 @@ _pages: my: "Halaman saya" liked: "Halaman yang disukai" featured: "Populer" - inspector: "Inspektor" contents: "Konten" - content: "Blokir Halaman" - variables: "Variabel" title: "Judul" url: "URL Halaman" summary: "Ringkasan Halaman" @@ -1341,262 +1334,6 @@ _pages: fontSansSerif: "Sans-serif" eyeCatchingImageSet: "Setel gambar yang menarik" eyeCatchingImageRemove: "Hapus gambar yang menarik" - chooseBlock: "Tambahkan blokir" - selectType: "Pilih jenis" - enterVariableName: "Mohon masukkan nama untuk variabel kamu" - variableNameIsAlreadyUsed: "Nama ini sudah digunakan oleh variabel lain" - contentBlocks: "Konten" - inputBlocks: "Masukan" - specialBlocks: "Khusus" - blocks: - text: "Teks" - textarea: "Area teks" - section: "Bagian" - image: "Gambar" - button: "Tombol" - if: "Jika" - _if: - variable: "Variabel" - post: "Buat catatan" - _post: - text: "Isi" - attachCanvasImage: "Posting dengan kanvas sebagai gambar" - canvasId: "ID Kanvas" - textInput: "Masukan teks" - _textInput: - name: "Nama variabel" - text: "Judul" - default: "Nilai bawaan" - textareaInput: "Masukan teks multibaris" - _textareaInput: - name: "Nama variabel" - text: "Judul" - default: "Nilai bawaan" - numberInput: "Masukan angka" - _numberInput: - name: "Nama variabel" - text: "Judul" - default: "Nilai bawaan" - canvas: "Kanvas" - _canvas: - id: "ID Kanvas" - width: "Lebar" - height: "Tinggi" - note: "Catatan yang ditanam" - _note: - id: "ID Catatan" - idDescription: "Kamu dapat menyetel ini dengan menempelkan tautan URL Catatan." - detailed: "Tampilan rincian" - switch: "Beralih" - _switch: - name: "Nama variabel" - text: "Judul" - default: "Nilai bawaan" - counter: "Penghitung" - _counter: - name: "Nama variabel" - text: "Judul" - inc: "Meningkat dengan" - _button: - text: "Judul" - colored: "Diwarnai" - action: "Operasi akan dimulai ketika tombol ditekan" - _action: - dialog: "Tampilkan dialog" - _dialog: - content: "Isi" - resetRandom: "Atur ulang benih acak" - pushEvent: "Kirim event" - _pushEvent: - event: "Nama event" - message: "Pesan yang tampil ketika diaktifkan" - variable: "Variable untuk kirim" - no-variable: "Tidak ada" - callAiScript: "Panggil AiScript" - _callAiScript: - functionName: "Nama fungsi" - radioButton: "Pilihan" - _radioButton: - name: "Nama variabel" - title: "Judul" - values: "Daftar pilihan (dipisahkan dengan garis baru)" - default: "Nilai bawaan" - script: - categories: - flow: "Arus kendali" - logical: "Operasi logis" - operation: "Menghitung" - comparison: "Membandingkan" - random: "Acak" - value: "Nilai" - fn: "Fungsi" - text: "Operasi teks" - convert: "Mengubah" - list: "Daftar" - blocks: - text: "Teks" - multiLineText: "Teks (multibaris)" - textList: "Daftar teks" - _textList: - info: "Pisahkan setiap entri dengan baris baru" - strLen: "Panjang teks" - _strLen: - arg1: "Teks" - strPick: "Ekstrak karakter" - _strPick: - arg1: "Teks" - arg2: "Lokasi karakter" - strReplace: "Penggantian teks" - _strReplace: - arg1: "Teks" - arg2: "Teks yang akan diganti" - arg3: "Diganti dengan" - strReverse: "Balikkan teks" - _strReverse: - arg1: "Teks" - join: "Rangkaian teks" - _join: - arg1: "Daftar" - arg2: "Pemisah" - add: "Tambah" - _add: - arg1: "A" - arg2: "B" - subtract: "Kurangi" - _subtract: - arg1: "A" - arg2: "B" - multiply: "Kali" - _multiply: - arg1: "A" - arg2: "B" - divide: "Bagi" - _divide: - arg1: "A" - arg2: "B" - mod: "Sisa" - _mod: - arg1: "A" - arg2: "B" - round: "Bulat desimal" - _round: - arg1: "Angka" - eq: "A dan B adalah sama" - _eq: - arg1: "A" - arg2: "B" - notEq: "A dan B adalah berbeda" - _notEq: - arg1: "A" - arg2: "B" - and: "A DAN B" - _and: - arg1: "A" - arg2: "B" - or: "A ATAU B" - _or: - arg1: "A" - arg2: "B" - lt: "< A ikurang dari B" - _lt: - arg1: "A" - arg2: "B" - gt: "> A lebih dari B" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A kurang dari sama dengan B" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A lebih dari sama dengan B" - _gtEq: - arg1: "A" - arg2: "B" - if: "Cabang" - _if: - arg1: "Jika" - arg2: "Jika benar" - arg3: "Jika salah" - not: "BUKAN" - _not: - arg1: "NOT" - random: "Acak" - _random: - arg1: "Probabilitas" - rannum: "Angka acak" - _rannum: - arg1: "Nilai minimum" - arg2: "Nilai maksimum" - randomPick: "Pilih secara acak dari daftar" - _randomPick: - arg1: "Daftar" - dailyRandom: "Acak (bertahan sehari)" - _dailyRandom: - arg1: "Probabilitas" - dailyRannum: "Angka acak (bertahan sehari)" - _dailyRannum: - arg1: "Nilai minimum" - arg2: "Nilai maksimum" - dailyRandomPick: "Pilih secara acak dari daftar (bertahan sehari)" - _dailyRandomPick: - arg1: "Daftar" - seedRandom: "Acak (dengan seed)" - _seedRandom: - arg1: "Seed" - arg2: "Probabilitas" - seedRannum: "Angka acak (dengan seed)" - _seedRannum: - arg1: "Seed" - arg2: "Nilai minimum" - arg3: "Nilai maksimum" - seedRandomPick: "Pilih secara acak dari daftar (dengan seed)" - _seedRandomPick: - arg1: "Seed" - arg2: "Daftar" - DRPWPM: "Pilih secara acak dari daftar berbobot (bertahan sehari)" - _DRPWPM: - arg1: "Daftar teks" - pick: "Pilih dari daftar" - _pick: - arg1: "Daftar" - arg2: "Posisi" - listLen: "Dapatkan panjangnya dari daftar" - _listLen: - arg1: "Daftar" - number: "Angka" - stringToNumber: "Teks ke angka" - _stringToNumber: - arg1: "Teks" - numberToString: "Angka ke teks" - _numberToString: - arg1: "Angka" - splitStrByLine: "Pisahkan teks dengan baris baru" - _splitStrByLine: - arg1: "Teks" - ref: "Variabel" - aiScriptVar: "Variabel AiScript" - fn: "Fungsi" - _fn: - slots: "Slot" - slots-info: "Pisahkan setiap slot dengan baris baru" - arg1: "Keluaran" - for: "Ulangi" - _for: - arg1: "Jumlah angka untuk diulangi" - arg2: "Aksi" - typeError: "Slot {slot} menerima tipe \"{expect}\", sayangnya nilai yang disediakan adalah \"{actual}\"!" - thereIsEmptySlot: "Slot {slot} kosong!" - types: - string: "Teks" - number: "Angka" - boolean: "Markah" - array: "Daftar" - stringArray: "Daftar teks" - emptySlot: "Slot kosong" - enviromentVariables: "Variabel Lingkungan" - pageVariables: "Elemen halaman" - argVariables: "Masukan slot" _relayStatus: requesting: "Menunggu" accepted: "Disetujui" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 91c3a9c46..e9dd2679b 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -254,7 +254,6 @@ remoteUserCaution: "Può darsi che le informazioni siano incomplete perché ques activity: "Attività" images: "Immagini" birthday: "Compleanno" -yearsOld: "{age}Anni" registeredDate: "Iscrizione a.." location: "Posizione" theme: "Tema" @@ -469,8 +468,6 @@ dayOverDayChanges: "Giornaliero" appearance: "Aspetto" clientSettings: "Impostazioni client" accountSettings: "Impostazioni account" -promotion: "Promossa" -promote: "Pubblicizza" numberOfDays: "Numero di giorni" hideThisNote: "Nasconda la nota" showFeaturedNotesInTimeline: "Mostrare le note di tendenza nella tua timeline" @@ -546,7 +543,6 @@ poll: "Sondaggio" useCw: "Nascondere media" enablePlayer: "Apri in lettore video" disablePlayer: "Chiudi lettore video" -expandTweet: "Espandi tweet" themeEditor: "Editor di temi" description: "Descrizione" describeFile: "Aggiungi una descrizione d'immagine" @@ -1227,8 +1223,6 @@ _pages: liked: "Pagine che mi piacciono" featured: "Popolari" contents: "Contenuto" - content: "Blocco di pagina" - variables: "Variabili" title: "Titolo" url: "URL della pagina" summary: "Riassunto di pagina" @@ -1238,172 +1232,6 @@ _pages: fontSansSerif: "Sans serif" eyeCatchingImageSet: "Imposta un'immagine attrattiva" eyeCatchingImageRemove: "Elimina l'immagine attrattiva" - chooseBlock: "Aggiungi blocco" - selectType: "Seleziona tipo" - enterVariableName: "Digita un nome di variabile" - variableNameIsAlreadyUsed: "Esiste già una variabile con lo stesso nome" - contentBlocks: "Contenuto" - inputBlocks: "Blocchi di input" - specialBlocks: "Speciale" - blocks: - text: "Testo" - textarea: "Area di testo" - section: "Sezione" - image: "Immagini" - button: "Pulsante" - if: "Se" - _if: - variable: "Variabili" - post: "Finestra di pubblicazione" - _post: - text: "Contenuto" - textInput: "Immissione testo" - _textInput: - name: "Nome della variabile" - text: "Titolo" - default: "Valore predefinito" - textareaInput: "Immissione testo a più righe" - _textareaInput: - name: "Nome della variabile" - text: "Titolo" - default: "Valore predefinito" - numberInput: "Immissione numerica" - _numberInput: - name: "Nome della variabile" - text: "Titolo" - default: "Valore predefinito" - _canvas: - width: "Larghezza" - height: "Altezza" - note: "Nota integrata" - _note: - id: "ID nota" - idDescription: "Qui puoi anche incollare l'URL della nota che vuoi impostare." - detailed: "Visualizzazione dettagliata" - switch: "Interruttore" - _switch: - name: "Nome della variabile" - text: "Titolo" - default: "Valore predefinito" - counter: "Contatore" - _counter: - name: "Nome della variabile" - text: "Titolo" - inc: "Valore da aggiungere" - _button: - text: "Titolo" - colored: "Colorato" - action: "Operazione da eseguire quando viene premuto il pulsante" - _action: - dialog: "Visualizzare una finestra di dialogo" - _dialog: - content: "Contenuto" - resetRandom: "Ripristinare un numero aleatorio" - pushEvent: "Inviare evento" - _pushEvent: - event: "Nome evento" - message: "Messaggio da visualizzare quando abilitato" - variable: "Variabile da inviare" - no-variable: "Nessun contenuto" - callAiScript: "Chiamare AiScript" - _callAiScript: - functionName: "Nome della funzione" - radioButton: "Opzioni" - _radioButton: - name: "Nome della variabile" - title: "Titolo" - default: "Valore predefinito" - script: - categories: - comparison: "Metodo comparativo" - random: "Aleatorietà" - value: "Valore" - fn: "Funzione" - list: "Liste" - blocks: - text: "Testo" - multiLineText: "Testo (a più righe)" - textList: "Lista di testo" - _strLen: - arg1: "Testo" - _strPick: - arg1: "Testo" - _strReplace: - arg1: "Testo" - _strReverse: - arg1: "Testo" - _join: - arg1: "Liste" - _add: - arg1: "A" - arg2: "B" - _subtract: - arg1: "A" - arg2: "B" - _multiply: - arg1: "A" - arg2: "B" - _divide: - arg1: "A" - arg2: "B" - _mod: - arg1: "A" - arg2: "B" - _eq: - arg1: "A" - arg2: "B" - notEq: "A e B sono differenti" - _notEq: - arg1: "A" - arg2: "B" - and: "A e B" - _and: - arg1: "A" - arg2: "B" - or: "A o B" - _or: - arg1: "A" - arg2: "B" - _lt: - arg1: "A" - arg2: "B" - _gt: - arg1: "A" - arg2: "B" - _ltEq: - arg1: "A" - arg2: "B" - _gtEq: - arg1: "A" - arg2: "B" - _if: - arg1: "Se" - arg2: "Se" - random: "Aleatorietà" - _randomPick: - arg1: "Liste" - _dailyRandomPick: - arg1: "Liste" - _seedRandom: - arg2: "Probabilità" - _seedRandomPick: - arg2: "Liste" - _DRPWPM: - arg1: "Lista di testo" - _pick: - arg1: "Liste" - _listLen: - arg1: "Liste" - _stringToNumber: - arg1: "Testo" - _splitStrByLine: - arg1: "Testo" - ref: "Variabili" - fn: "Funzione" - types: - string: "Testo" - array: "Liste" - stringArray: "Lista di testo" _relayStatus: requesting: "In attesa di approvazione" accepted: "Approvato" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 401f9ed35..031f3d044 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -259,7 +259,6 @@ remoteUserCaution: "リモートユーザーのため、情報が不完全です activity: "アクティビティ" images: "画像" birthday: "誕生日" -yearsOld: "{age}歳" registeredDate: "登録日" location: "場所" theme: "テーマ" @@ -474,8 +473,6 @@ dayOverDayChanges: "前日比" appearance: "アピアランス" clientSettings: "クライアント設定" accountSettings: "アカウント設定" -promotion: "プロモーション" -promote: "プロモート" numberOfDays: "日数" hideThisNote: "このノートを非表示" showFeaturedNotesInTimeline: "タイムラインにおすすめのノートを表示する" @@ -551,7 +548,6 @@ poll: "アンケート" useCw: "内容を隠す" enablePlayer: "プレイヤーを開く" disablePlayer: "プレイヤーを閉じる" -expandTweet: "ツイートを展開する" themeEditor: "テーマエディター" description: "説明" describeFile: "キャプションを付ける" @@ -1384,10 +1380,7 @@ _pages: my: "自分のページ" liked: "いいねしたページ" featured: "人気" - inspector: "インスペクター" contents: "コンテンツ" - content: "ページブロック" - variables: "変数" title: "タイトル" url: "ページURL" summary: "ページの要約" @@ -1398,274 +1391,6 @@ _pages: fontSansSerif: "サンセリフ" eyeCatchingImageSet: "アイキャッチ画像を設定" eyeCatchingImageRemove: "アイキャッチ画像を削除" - chooseBlock: "ブロックを追加" - selectType: "種類を選択" - enterVariableName: "変数名を決めてください" - variableNameIsAlreadyUsed: "その変数名は既に使われています" - contentBlocks: "コンテンツ" - inputBlocks: "入力" - specialBlocks: "特殊" - blocks: - text: "テキスト" - textarea: "テキストエリア" - section: "セクション" - image: "画像" - button: "ボタン" - - if: "もし" - _if: - variable: "変数" - - post: "投稿フォーム" - _post: - text: "内容" - attachCanvasImage: "キャンバスの画像を添付する" - canvasId: "キャンバスID" - - textInput: "テキスト入力" - _textInput: - name: "変数名" - text: "タイトル" - default: "デフォルト値" - - textareaInput: "複数行テキスト入力" - _textareaInput: - name: "変数名" - text: "タイトル" - default: "デフォルト値" - - numberInput: "数値入力" - _numberInput: - name: "変数名" - text: "タイトル" - default: "デフォルト値" - - canvas: "キャンバス" - _canvas: - id: "キャンバスID" - width: "幅" - height: "高さ" - - note: "ノート埋め込み" - _note: - id: "ノートID" - idDescription: "ノートURLをペーストして設定することもできます。" - detailed: "詳細な表示" - - switch: "スイッチ" - _switch: - name: "変数名" - text: "タイトル" - default: "デフォルト値" - - counter: "カウンター" - _counter: - name: "変数名" - text: "タイトル" - inc: "増加値" - - _button: - text: "タイトル" - colored: "色付き" - action: "ボタンを押したときの動作" - _action: - dialog: "ダイアログを表示する" - _dialog: - content: "内容" - resetRandom: "乱数をリセット" - pushEvent: "イベントを送信させる" - _pushEvent: - event: "イベント名" - message: "押したときに表示するメッセージ" - variable: "送信する変数" - no-variable: "なし" - callAiScript: "AiScript呼び出し" - _callAiScript: - functionName: "関数名" - - radioButton: "選択肢" - _radioButton: - name: "変数名" - title: "タイトル" - values: "改行で区切った選択肢" - default: "デフォルト値" - - script: - categories: - flow: "制御" - logical: "論理演算" - operation: "計算" - comparison: "比較" - random: "ランダム" - value: "値" - fn: "関数" - text: "テキスト操作" - convert: "変換" - list: "リスト" - blocks: - text: "テキスト" - multiLineText: "テキスト(複数行)" - textList: "テキストのリスト" - _textList: - info: "ひとつひとつを改行で区切ってください" - strLen: "テキストの長さ" - _strLen: - arg1: "テキスト" - strPick: "文字取り出し" - _strPick: - arg1: "テキスト" - arg2: "文字の位置" - strReplace: "テキスト置き換え" - _strReplace: - arg1: "テキスト" - arg2: "置き換え前" - arg3: "置き換え後" - strReverse: "テキストを反転" - _strReverse: - arg1: "テキスト" - join: "テキストを連結" - _join: - arg1: "リスト" - arg2: "区切り" - add: "足す" - _add: - arg1: "A" - arg2: "B" - subtract: "引く" - _subtract: - arg1: "A" - arg2: "B" - multiply: "掛ける" - _multiply: - arg1: "A" - arg2: "B" - divide: "割る" - _divide: - arg1: "A" - arg2: "B" - mod: "割った余り" - _mod: - arg1: "A" - arg2: "B" - round: "小数を丸める" - _round: - arg1: "数値" - eq: "AとBが同じ" - _eq: - arg1: "A" - arg2: "B" - notEq: "AとBが異なる" - _notEq: - arg1: "A" - arg2: "B" - and: "AかつB" - _and: - arg1: "A" - arg2: "B" - or: "AまたはB" - _or: - arg1: "A" - arg2: "B" - lt: "< AがBより小さい" - _lt: - arg1: "A" - arg2: "B" - gt: "> AがBより大きい" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= AがBと同じか小さい" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= AがBと同じか大きい" - _gtEq: - arg1: "A" - arg2: "B" - if: "分岐" - _if: - arg1: "もし" - arg2: "なら" - arg3: "そうでなければ" - not: "否定" - _not: - arg1: "否定" - random: "ランダム" - _random: - arg1: "確率" - rannum: "乱数" - _rannum: - arg1: "最小" - arg2: "最大" - randomPick: "リストからランダムに選択" - _randomPick: - arg1: "リスト" - dailyRandom: "ランダム (ユーザーごとに日替わり)" - _dailyRandom: - arg1: "確率" - dailyRannum: "乱数 (ユーザーごとに日替わり)" - _dailyRannum: - arg1: "最小" - arg2: "最大" - dailyRandomPick: "リストからランダムに選択 (ユーザーごとに日替わり)" - _dailyRandomPick: - arg1: "リスト" - seedRandom: "ランダム (シード)" - _seedRandom: - arg1: "シード" - arg2: "確率" - seedRannum: "乱数 (シード)" - _seedRannum: - arg1: "シード" - arg2: "最小" - arg3: "最大" - seedRandomPick: "リストからランダムに選択 (シード)" - _seedRandomPick: - arg1: "シード" - arg2: "リスト" - DRPWPM: "確率付きリストからランダムに選択 (ユーザーごとに日替わり)" - _DRPWPM: - arg1: "テキストのリスト" - pick: "リストから選択" - _pick: - arg1: "リスト" - arg2: "位置" - listLen: "リストの長さを取得" - _listLen: - arg1: "リスト" - number: "数値" - stringToNumber: "テキストを数値に" - _stringToNumber: - arg1: "テキスト" - numberToString: "数値をテキストに" - _numberToString: - arg1: "数値" - splitStrByLine: "テキストを行で分割" - _splitStrByLine: - arg1: "テキスト" - ref: "変数" - aiScriptVar: "AiScript変数" - fn: "関数" - _fn: - slots: "スロット" - slots-info: "スロットひとつひとつを改行で区切ってください" - arg1: "出力" - for: "繰り返し" - _for: - arg1: "回数" - arg2: "処理" - typeError: "スロット{slot}は\"{expect}\"を受け付けますが、\"{actual}\"が入れられています!" - thereIsEmptySlot: "スロット{slot}が空です!" - types: - string: "テキスト" - number: "数値" - boolean: "フラグ" - array: "リスト" - stringArray: "テキストのリスト" - emptySlot: "空のスロット" - enviromentVariables: "環境変数" - pageVariables: "ページ要素" - argVariables: "入力スロット" _relayStatus: requesting: "承認待ち" diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index d5ea43d4e..acb4d07b5 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -258,7 +258,6 @@ remoteUserCaution: "リモートユーザーやから、足りひん情報ある activity: "アクティビティ" images: "画像" birthday: "生まれた日" -yearsOld: "{age}歳" registeredDate: "始めた日" location: "場所" theme: "テーマ" @@ -463,8 +462,6 @@ dayOverDayChanges: "前日比" appearance: "見た目" clientSettings: "クライアントの設定" accountSettings: "アカウントの設定" -promotion: "宣伝" -promote: "宣伝" numberOfDays: "日数" hideThisNote: "このノートは表示せんでいい" showFeaturedNotesInTimeline: "タイムラインにおすすめのノートを表示してや" @@ -525,7 +522,6 @@ addedRelays: "追加済みのリレー" poll: "アンケート" enablePlayer: "プレイヤーを開く" disablePlayer: "プレイヤーを閉じる" -expandTweet: "ツイートを展開する" themeEditor: "テーマエディター" description: "説明" author: "作者" @@ -936,252 +932,6 @@ _pages: fontSansSerif: "サンセリフ" eyeCatchingImageSet: "アイキャッチ画像を設定" eyeCatchingImageRemove: "アイキャッチ画像を削除" - chooseBlock: "ブロックを追加" - selectType: "種類を選択" - contentBlocks: "コンテンツ" - inputBlocks: "入力" - specialBlocks: "特殊" - blocks: - text: "テキスト" - textarea: "テキストエリア" - section: "セクション" - image: "画像" - button: "ボタン" - if: "もし" - _if: - variable: "変数" - post: "投稿フォーム" - _post: - text: "内容" - canvasId: "キャンバスID" - textInput: "テキスト入力" - _textInput: - name: "変数名" - text: "タイトル" - default: "デフォルト値" - textareaInput: "複数行テキスト入力" - _textareaInput: - name: "変数名" - text: "タイトル" - default: "デフォルト値" - numberInput: "数値入力" - _numberInput: - name: "変数名" - text: "タイトル" - default: "デフォルト値" - canvas: "キャンバス" - _canvas: - id: "キャンバスID" - width: "幅" - height: "高さ" - note: "ノート埋め込み" - _note: - id: "ノートID" - detailed: "詳細な表示" - switch: "スイッチ" - _switch: - name: "変数名" - text: "タイトル" - default: "デフォルト値" - counter: "カウンター" - _counter: - name: "変数名" - text: "タイトル" - inc: "増加値" - _button: - text: "タイトル" - colored: "色付き" - action: "ボタンを押したときの動作" - _action: - dialog: "ダイアログを表示する" - _dialog: - content: "内容" - resetRandom: "乱数をリセット" - pushEvent: "イベントを送信させる" - _pushEvent: - event: "イベント名" - no-variable: "なし" - callAiScript: "AiScript呼び出し" - _callAiScript: - functionName: "関数名" - radioButton: "選択肢" - _radioButton: - name: "変数名" - title: "タイトル" - values: "改行で区切った選択肢" - default: "デフォルト値" - script: - categories: - flow: "制御" - logical: "論理演算" - operation: "計算" - comparison: "比較" - random: "ランダム" - value: "値" - fn: "関数" - text: "関数" - convert: "変換" - list: "リスト" - blocks: - text: "テキスト" - multiLineText: "テキスト(複数行)" - textList: "テキストのリスト" - strLen: "テキストの長さ" - _strLen: - arg1: "テキスト" - strPick: "文字取り出し" - _strPick: - arg1: "テキスト" - arg2: "文字の位置" - strReplace: "テキスト置き換え" - _strReplace: - arg1: "テキスト" - arg2: "置き換え前" - arg3: "置き換え後" - strReverse: "テキストを反転" - _strReverse: - arg1: "テキスト" - join: "テキストを連結" - _join: - arg1: "リスト" - arg2: "区切り" - add: "足す" - _add: - arg1: "A" - arg2: "B" - subtract: "引く" - _subtract: - arg1: "A" - arg2: "A" - multiply: "掛ける" - _multiply: - arg1: "A" - arg2: "B" - divide: "割る" - _divide: - arg1: "A" - arg2: "B" - mod: "割った余り" - _mod: - arg1: "A" - arg2: "B" - round: "小数を丸める" - _round: - arg1: "数値" - eq: "AとBが同じ" - _eq: - arg1: "A" - arg2: "B" - notEq: "AとBが異なる" - _notEq: - arg1: "A" - arg2: "B" - and: "AかつB" - _and: - arg1: "A" - arg2: "B" - or: "AまたはB" - _or: - arg1: "A" - arg2: "B" - lt: "< AがBより小さい" - _lt: - arg1: "A" - arg2: "B" - gt: "> AがBより大きい" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= AがBと同じか小さい" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= AがBと同じか大きい" - _gtEq: - arg1: "A" - arg2: "B" - if: "分岐" - _if: - arg1: "もし" - arg2: "なら" - arg3: "そうでなければ" - not: "否定" - _not: - arg1: "否定" - random: "ランダム" - _random: - arg1: "確率" - rannum: "乱数" - _rannum: - arg1: "最小" - arg2: "最大" - randomPick: "リストからランダムに選ぶ" - _randomPick: - arg1: "リスト" - dailyRandom: "ランダム (ユーザーごとに日替わり)" - _dailyRandom: - arg1: "確率" - dailyRannum: "乱数 (ユーザーごとに日替わり)" - _dailyRannum: - arg1: "最小" - arg2: "最大" - dailyRandomPick: "リストからランダムに選ぶ (ユーザーごとに日替わり)" - _dailyRandomPick: - arg1: "リスト" - seedRandom: "ランダム (シード)" - _seedRandom: - arg1: "シード" - arg2: "確率" - seedRannum: "乱数 (シード)" - _seedRannum: - arg1: "シード" - arg2: "最小" - arg3: "最大" - seedRandomPick: "リストからランダムに選択 (シード)" - _seedRandomPick: - arg1: "シード" - arg2: "リスト" - DRPWPM: "確率付きリストからランダムに選ぶ (ユーザーごとに日替わり)" - _DRPWPM: - arg1: "テキストのリスト" - pick: "リストから選ぶ" - _pick: - arg1: "リスト" - arg2: "位置" - listLen: "リストの長さを取得" - _listLen: - arg1: "リスト" - number: "数値" - stringToNumber: "テキストを数値に" - _stringToNumber: - arg1: "テキスト" - numberToString: "数値をテキストに" - _numberToString: - arg1: "数値" - splitStrByLine: "テキストを行で分割" - _splitStrByLine: - arg1: "テキスト" - ref: "変数" - aiScriptVar: "AiScript変数" - fn: "関数" - _fn: - slots: "スロット" - arg1: "出力" - for: "繰り返し" - _for: - arg1: "回数" - arg2: "処理" - thereIsEmptySlot: "スロット{slot}が空っぽやで!" - types: - string: "テキスト" - number: "数値" - boolean: "フラグ" - array: "リスト" - stringArray: "テキストのリスト" - emptySlot: "空のスロット" - enviromentVariables: "環境変数" - pageVariables: "ページ要素" - argVariables: "入力スロット" _notification: fileUploaded: "ファイルが無事アップロードされたで。" youGotMention: "{name}からのメンション" diff --git a/locales/kab-KAB.yml b/locales/kab-KAB.yml index a794d9ca5..e29544f3f 100644 --- a/locales/kab-KAB.yml +++ b/locales/kab-KAB.yml @@ -88,28 +88,6 @@ _pages: fontSerif: "Serif" fontSansSerif: "Sans Serif" eyeCatchingImageRemove: "Kkes tugna i d-ijebden" - selectType: "Fren anaw" - contentBlocks: "Agbur" - inputBlocks: "Anekcum" - specialBlocks: "Uzzig" - script: - categories: - list: "Tibdarin" - blocks: - _join: - arg1: "Tibdarin" - _randomPick: - arg1: "Tibdarin" - _dailyRandomPick: - arg1: "Tibdarin" - _seedRandomPick: - arg2: "Tibdarin" - _pick: - arg1: "Tibdarin" - _listLen: - arg1: "Tibdarin" - types: - array: "Tibdarin" _notification: youWereFollowed: "Yeṭṭafaṛ-ik·em-id" _types: diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index d240c4e73..06d0c35b6 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -258,7 +258,6 @@ remoteUserCaution: "리모트 유저이기 때문에, 정보가 정확하지 않 activity: "활동" images: "이미지" birthday: "생일" -yearsOld: "{age}세" registeredDate: "등록일" location: "장소" theme: "테마" @@ -473,8 +472,6 @@ dayOverDayChanges: "어제보다" appearance: "모양" clientSettings: "클라이언트 설정" accountSettings: "계정 설정" -promotion: "프로모션" -promote: "프로모션하기" numberOfDays: "며칠동안" hideThisNote: "이 노트를 숨기기" showFeaturedNotesInTimeline: "타임라인에 추천 노트를 표시" @@ -550,7 +547,6 @@ poll: "투표" useCw: "내용 숨기기" enablePlayer: "플레이어 열기" disablePlayer: "플레이어 닫기" -expandTweet: "트윗 확장하기" themeEditor: "테마 에디터" description: "설명" describeFile: "캡션 추가" @@ -1327,10 +1323,7 @@ _pages: my: "내 페이지" liked: "좋아요한 페이지" featured: "인기" - inspector: "인스펙터" contents: "콘텐츠" - content: "페이지 블록" - variables: "변수" title: "제목" url: "페이지 URL" summary: "페이지 요약" @@ -1341,262 +1334,6 @@ _pages: fontSansSerif: "고딕체" eyeCatchingImageSet: "아이캐치 이미지를 설정" eyeCatchingImageRemove: "아이캐치 이미지를 삭제" - chooseBlock: "블록 추가" - selectType: "종류 선택" - enterVariableName: "변수명을 지정해주세요" - variableNameIsAlreadyUsed: "해당 변수명은 이미 사용중입니다" - contentBlocks: "콘텐츠" - inputBlocks: "입력" - specialBlocks: "특수" - blocks: - text: "텍스트" - textarea: "텍스트 영역" - section: "섹션" - image: "이미지" - button: "버튼" - if: "조건문" - _if: - variable: "변수" - post: "글 입력란" - _post: - text: "내용" - attachCanvasImage: "캔버스의 이미지와 함께 게시하기" - canvasId: "캔버스 ID" - textInput: "텍스트 입력" - _textInput: - name: "변수명" - text: "제목" - default: "기본값" - textareaInput: "여러 줄 텍스트 입력" - _textareaInput: - name: "변수명" - text: "제목" - default: "기본값" - numberInput: "수치 입력" - _numberInput: - name: "변수명" - text: "제목" - default: "기본값" - canvas: "캔버스" - _canvas: - id: "캔버스 ID" - width: "폭" - height: "높이" - note: "노트필기" - _note: - id: "노트 ID" - idDescription: "노트 URL을 붙여넣어 설정할 수도 있습니다." - detailed: "세부 정보 보기" - switch: "스위치" - _switch: - name: "변수명" - text: "제목" - default: "기본값" - counter: "카운터" - _counter: - name: "변수명" - text: "제목" - inc: "증가치" - _button: - text: "제목" - colored: "색 입히기" - action: "버튼을 눌렀을 때의 동작" - _action: - dialog: "대화상자를 표시" - _dialog: - content: "내용" - resetRandom: "난수를 초기화" - pushEvent: "이벤트 보내기" - _pushEvent: - event: "이벤트 이름" - message: "눌렀을 때 표시할 페이지" - variable: "보낼 변수" - no-variable: "없음" - callAiScript: "AiScript 호출" - _callAiScript: - functionName: "함수명" - radioButton: "선택지" - _radioButton: - name: "변수명" - title: "제목" - values: "줄바꿈으로 구분된 선택지" - default: "기본값" - script: - categories: - flow: "흐름 제어" - logical: "논리 연산" - operation: "계산" - comparison: "비교" - random: "랜덤" - value: "값" - fn: "함수" - text: "텍스트 조작" - convert: "변환" - list: "리스트" - blocks: - text: "텍스트" - multiLineText: "텍스트 (여러 줄)" - textList: "텍스트 목록" - _textList: - info: "각각을 줄바꿈으로 구분해주세요" - strLen: "텍스트의 길이" - _strLen: - arg1: "텍스트" - strPick: "문자 추출" - _strPick: - arg1: "텍스트" - arg2: "문자 위치" - strReplace: "텍스트 대체" - _strReplace: - arg1: "텍스트" - arg2: "대체될 텍스트" - arg3: "대체할 텍스트" - strReverse: "텍스트 뒤집기" - _strReverse: - arg1: "텍스트" - join: "텍스트 합치기" - _join: - arg1: "리스트" - arg2: "구분자" - add: "더하기" - _add: - arg1: "A" - arg2: "B" - subtract: "빼기" - _subtract: - arg1: "A" - arg2: "B" - multiply: "곱하기" - _multiply: - arg1: "A" - arg2: "B" - divide: "나누기" - _divide: - arg1: "A" - arg2: "B" - mod: "나눈 나머지" - _mod: - arg1: "A" - arg2: "B" - round: "소수점을 반올림" - _round: - arg1: "수치" - eq: "A와 B가 동일" - _eq: - arg1: "A" - arg2: "B" - notEq: "A와 B가 다름" - _notEq: - arg1: "A" - arg2: "B" - and: "A와 B가 둘 다 참" - _and: - arg1: "A" - arg2: "B" - or: "A, B중 하나 이상이 참" - _or: - arg1: "A" - arg2: "B" - lt: "< A가 B보다 작음" - _lt: - arg1: "A" - arg2: "B" - gt: "> A가 B보다 큼" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A가 B보다 작거나 같음" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A가 B보다 크거나 같음" - _gtEq: - arg1: "A" - arg2: "B" - if: "분기" - _if: - arg1: "조건문" - arg2: "참일 경우" - arg3: "거짓일 경우" - not: "부정" - _not: - arg1: "부정" - random: "랜덤" - _random: - arg1: "확률" - rannum: "난수" - _rannum: - arg1: "최솟값" - arg2: "최댓값" - randomPick: "목록에서 임의로 선택" - _randomPick: - arg1: "리스트" - dailyRandom: "랜덤 (하루동안 결과 유지)" - _dailyRandom: - arg1: "확률" - dailyRannum: "난수 (하루동안 결과 유지)" - _dailyRannum: - arg1: "최솟값" - arg2: "최댓값" - dailyRandomPick: "목록에서 임의로 선택 (하루동안 결과 유지)" - _dailyRandomPick: - arg1: "리스트" - seedRandom: "무작위 (시드)" - _seedRandom: - arg1: "시드" - arg2: "확률" - seedRannum: "난수 (시드)" - _seedRannum: - arg1: "시드" - arg2: "최솟값" - arg3: "최댓값" - seedRandomPick: "목록에서 무작위로 선택 (시드)" - _seedRandomPick: - arg1: "시드" - arg2: "리스트" - DRPWPM: "확률형 목록에서 임의로 선택 (하루동안 결과 유지)" - _DRPWPM: - arg1: "텍스트 목록" - pick: "목록에서 선택" - _pick: - arg1: "리스트" - arg2: "위치" - listLen: "리스트의 길이 가져오기" - _listLen: - arg1: "리스트" - number: "수치" - stringToNumber: "텍스트를 수치로" - _stringToNumber: - arg1: "텍스트" - numberToString: "수치를 텍스트로" - _numberToString: - arg1: "수치" - splitStrByLine: "텍스트를 행 단위로 분할" - _splitStrByLine: - arg1: "텍스트" - ref: "변수" - aiScriptVar: "AiScript 변수" - fn: "함수" - _fn: - slots: "슬롯" - slots-info: "각 슬롯을 줄바꿈으로 구분하여 주세요" - arg1: "출력" - for: "반복" - _for: - arg1: "횟수" - arg2: "처리" - typeError: "슬롯 {slot}은 \"{expect}\"를 사용할 수 있지만 \"{actual}이 들어있습니다!" - thereIsEmptySlot: "슬롯 {slot}이(가) 비었습니다!" - types: - string: "텍스트" - number: "수치" - boolean: "플래그" - array: "리스트" - stringArray: "텍스트 목록" - emptySlot: "빈 슬롯" - enviromentVariables: "환경 변수" - pageVariables: "페이지 요소" - argVariables: "입력 슬롯" _relayStatus: requesting: "대기 중" accepted: "승인됨" diff --git a/locales/nl-NL.yml b/locales/nl-NL.yml index e708e0c94..1174d1a6f 100644 --- a/locales/nl-NL.yml +++ b/locales/nl-NL.yml @@ -244,7 +244,6 @@ remoteUserCaution: "Aangezien deze gebruiker van een externe server afkomstig is activity: "Activiteit" images: "Afbeeldingen" birthday: "Geboortedatum" -yearsOld: "{age} jaar" registeredDate: "Inschrijvingsdatum" location: "Locatie" theme: "Thema's" @@ -344,27 +343,6 @@ _charts: federation: "Federatie" _timelines: home: "Startpagina" -_pages: - blocks: - image: "Afbeeldingen" - script: - categories: - list: "Lijsten" - blocks: - _join: - arg1: "Lijsten" - _randomPick: - arg1: "Lijsten" - _dailyRandomPick: - arg1: "Lijsten" - _seedRandomPick: - arg2: "Lijsten" - _pick: - arg1: "Lijsten" - _listLen: - arg1: "Lijsten" - types: - array: "Lijsten" _notification: youWereFollowed: "volgde jou" _types: diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index 84b2b0f4d..e4765fead 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -253,7 +253,6 @@ remoteUserCaution: "Te informacje mogą nie być aktualne, ponieważ użytkownik activity: "Aktywność" images: "Zdjęcia" birthday: "Data urodzenia" -yearsOld: "{age} lat" registeredDate: "Zarejestrowano" location: "Lokalizacja" theme: "Motywy" @@ -466,8 +465,6 @@ dayOverDayChanges: "Codziennie" appearance: "Wygląd" clientSettings: "Ustawienia klienta" accountSettings: "Ustawienia konta" -promotion: "Promowane" -promote: "Promuj" numberOfDays: "Liczba dni" hideThisNote: "Ukryj ten wpis" showFeaturedNotesInTimeline: "Pokazuj wyróżnione wpisy w osi czasu" @@ -537,7 +534,6 @@ poll: "Ankieta" useCw: "Ukryj zawartość" enablePlayer: "Otwórz odtwarzacz wideo" disablePlayer: "Zamknij odtwarzacz wideo" -expandTweet: "Rozwiń tweet" themeEditor: "Edytor motywu" description: "Opis" describeFile: "dodaj podpis" @@ -1117,10 +1113,7 @@ _pages: my: "Moje strony" liked: "Polubione strony" featured: "Wyróżnione" - inspector: "Inspektor" contents: "Zawartość" - content: "Blokada strony" - variables: "Zmienne" title: "Tytuł" url: "URL strony" summary: "Podsumowanie strony" @@ -1131,243 +1124,6 @@ _pages: fontSansSerif: "Bezszeryfowa" eyeCatchingImageSet: "Ustaw przyciągające wzrok zdjęcie" eyeCatchingImageRemove: "Usuń przyciągające wzrok zdjęcie" - chooseBlock: "Dodaj blok" - selectType: "Wybierz typ" - enterVariableName: "Wprowadź nazwę dla swojej zmiennej" - variableNameIsAlreadyUsed: "Ta nazwa jest już używana przez inną zmienną" - contentBlocks: "Zawartość" - inputBlocks: "Wejście" - specialBlocks: "Specjalne" - blocks: - text: "Tekst" - textarea: "Pole tekstowe" - section: "Sekcja" - image: "Zdjęcia" - button: "Przycisk" - if: "Jeżeli" - _if: - variable: "Zmienna" - post: "Utwórz wpis" - _post: - text: "Treść" - textInput: "Pole tekstowe" - _textInput: - name: "Nazwa zmiennej" - text: "Tytuł" - default: "Domyślna wartość" - textareaInput: "Pole tekstowe na wiele wierszy" - _textareaInput: - name: "Nazwa zmiennej" - text: "Tytuł" - default: "Domyślna wartość" - numberInput: "Pole na liczbę" - _numberInput: - name: "Nazwa zmiennej" - text: "Tytuł" - default: "Domyślna wartość" - _canvas: - width: "Szerokość" - height: "Wysokość" - note: "Osadzony wpis" - _note: - id: "ID wpisu" - idDescription: "Możesz też wkleić adres URL wpisu, aby go ustawić." - detailed: "Szczegółowy widok" - switch: "Przełącznik" - _switch: - name: "Nazwa zmiennej" - text: "Tytuł" - default: "Domyślna wartość" - counter: "Licznik" - _counter: - name: "Nazwa zmiennej" - text: "Tytuł" - inc: "Zwiększ o" - _button: - text: "Tytuł" - colored: "Kolorowe" - action: "Działanie wykonywane przy naciśnięciu przycisku" - _action: - dialog: "Pokazuj okno dialogowe" - _dialog: - content: "Treść" - resetRandom: "Resetuj losowe ziarno" - pushEvent: "Wyślij zdarzenie" - _pushEvent: - event: "Nazwa zdarzenia" - message: "Wiadomość do wyświetlenia po aktywowaniu" - variable: "Zmienna do wysłania" - no-variable: "Brak" - callAiScript: "Wywołaj AiScript" - _callAiScript: - functionName: "Nazwa funkcji" - radioButton: "Wybór" - _radioButton: - name: "Nazwa zmiennej" - title: "Tytuł" - values: "Lista wyborów (oddzielonych znakiem nowego wiersza)" - default: "Domyślna wartość" - script: - categories: - flow: "Kontrola przepływu" - logical: "Operacje logiczne" - operation: "Obliczanie" - comparison: "Porównanie" - random: "Losowe" - value: "Wartość" - fn: "Funkcje" - text: "Działania na tekście" - convert: "Transformacja" - list: "Listy" - blocks: - text: "Tekst" - multiLineText: "Tekst (w wielu wierszach)" - _textList: - info: "Oddziel każdy wpis znakiem nowego wiersza" - strLen: "Długość tekstu" - _strLen: - arg1: "Tekst" - _strPick: - arg1: "Tekst" - arg2: "Położenie znaku" - strReplace: "Zamiana tekstu" - _strReplace: - arg1: "Tekst" - arg2: "Tekst do zamiany" - arg3: "Zamieniono z" - _strReverse: - arg1: "Tekst" - _join: - arg1: "Listy" - arg2: "Odstęp" - add: "Dodaj" - _add: - arg1: "A" - arg2: "B" - subtract: "Odejmij" - _subtract: - arg1: "A" - arg2: "B" - multiply: "Pomnóż" - _multiply: - arg1: "A" - arg2: "B" - divide: "Podziel" - _divide: - arg1: "A" - arg2: "B" - mod: "Reszta" - _mod: - arg1: "A" - arg2: "B" - _round: - arg1: "Liczba" - eq: "A i B są sobie równe" - _eq: - arg1: "A" - arg2: "B" - notEq: "A i B różnią się" - _notEq: - arg1: "A" - arg2: "B" - and: "A I B" - _and: - arg1: "A" - arg2: "B" - or: "A LUB B" - _or: - arg1: "A" - arg2: "B" - lt: "< A jest mniejsze niż B" - _lt: - arg1: "A" - arg2: "B" - gt: "> A jest większe od B" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A jest mniejsze lub równe B" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A jest większe lub równe B" - _gtEq: - arg1: "A" - arg2: "B" - if: "Warunek" - _if: - arg1: "Jeżeli" - arg2: "Jeżeli prawda" - not: "NIE" - _not: - arg1: "NIE" - random: "Losowe" - _random: - arg1: "Prawdopodobieństwo" - rannum: "Losowa liczba" - _rannum: - arg1: "Minimalna wartość" - arg2: "Maksymalna wartość" - randomPick: "Wybierz losowo z listy" - _randomPick: - arg1: "Listy" - dailyRandom: "Losowo (zostaje na dzień)" - _dailyRandom: - arg1: "Prawdopodobieństwo" - dailyRannum: "Losowa liczba (zostaje na dzień)" - _dailyRannum: - arg1: "Minimalna wartość" - arg2: "Maksymalna wartość" - dailyRandomPick: "Wybierz losowo z listy (zostaje na dzień)" - _dailyRandomPick: - arg1: "Listy" - seedRandom: "Losowo (z ziarnem)" - _seedRandom: - arg1: "Ziarno" - arg2: "Prawdopodobieństwo" - seedRannum: "Losowa liczba (z ziarnem)" - _seedRannum: - arg1: "Ziarno" - arg2: "Minimalna wartość" - arg3: "Maksymalna wartość" - seedRandomPick: "Wybierz losowo z listy (z ziarnem)" - _seedRandomPick: - arg1: "Ziarno" - arg2: "Listy" - DRPWPM: "Wybierz losowo z ważonej listy (zostaje na dzień)" - pick: "Wybierz z listy" - _pick: - arg1: "Listy" - arg2: "Położenie" - listLen: "Uzyskaj długość listy" - _listLen: - arg1: "Listy" - number: "Liczba" - stringToNumber: "Tekst na liczbę" - _stringToNumber: - arg1: "Tekst" - numberToString: "Liczba na tekst" - _numberToString: - arg1: "Liczba" - splitStrByLine: "Rozdziel tekst znakami nowej linii" - _splitStrByLine: - arg1: "Tekst" - ref: "Zmienne" - aiScriptVar: "Zmienna AiScript" - fn: "Funkcje" - _fn: - arg1: "Wyjście" - for: "Powtórzenie" - _for: - arg1: "Liczba powtórzeń" - arg2: "Działanie" - types: - string: "Tekst" - number: "Liczba" - boolean: "Flaguj" - array: "Listy" - enviromentVariables: "Zmienna środowiskowa" - pageVariables: "Element strony" _relayStatus: requesting: "Oczekujące" accepted: "Zaakceptowano" diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml index e771b99c1..7efdcfb0f 100644 --- a/locales/pt-PT.yml +++ b/locales/pt-PT.yml @@ -190,173 +190,6 @@ _exportOrImport: muteList: "Silenciar" blockingList: "Bloquear" userLists: "Listas" -_pages: - blocks: - _button: - _action: - _pushEvent: - event: "Nome do evento" - message: "Mostrar mensagem quando ativado" - variable: "Variável a mandar" - no-variable: "Nenhum" - callAiScript: "Invocar AiScript" - _callAiScript: - functionName: "Nome da função" - radioButton: "Escolha" - _radioButton: - values: "Lista de escolhas separadas por quebras de texto" - script: - categories: - logical: "Operação lógica" - operation: "Cálculos" - comparison: "Comparação" - list: "Listas" - blocks: - _strReplace: - arg2: "Texto que irá ser substituído" - arg3: "Substituir com" - strReverse: "Virar texto" - join: "Sequência de texto" - _join: - arg1: "Listas" - arg2: "Separador" - add: "Somar" - _add: - arg1: "A" - arg2: "B" - subtract: "Subtrair" - _subtract: - arg1: "A" - arg2: "B" - multiply: "Multiplicar" - _multiply: - arg1: "A" - arg2: "B" - divide: "Dividir" - _divide: - arg1: "A" - arg2: "B" - mod: "O resto de" - _mod: - arg1: "A" - arg2: "B" - round: "Arredondar decimal" - _round: - arg1: "Numérico" - eq: "A e B são iguais" - _eq: - arg1: "A" - arg2: "B" - notEq: "A e B são diferentes" - _notEq: - arg1: "A" - arg2: "B" - and: "A e B" - _and: - arg1: "A" - arg2: "B" - or: "A OU B" - _or: - arg1: "A" - arg2: "B" - lt: "< A é menor do que B" - _lt: - arg1: "A" - arg2: "B" - gt: "> A é maior do que B" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A é maior ou igual a B" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A é maior ou igual a B" - _gtEq: - arg1: "A" - arg2: "B" - if: "Galho" - _if: - arg1: "Se" - arg2: "Então" - arg3: "Se não" - not: "NÃO" - _not: - arg1: "NÃO" - random: "Aleatório" - _random: - arg1: "Probabilidade" - rannum: "Numeral aleatório" - _rannum: - arg1: "Valor mínimo" - arg2: "Valor máximo" - randomPick: "Escolher aleatoriamente de uma lista" - _randomPick: - arg1: "Listas" - dailyRandom: "Aleatório (Muda uma vez por dia para cada usuário)" - _dailyRandom: - arg1: "Probabilidade" - dailyRannum: "Numeral aleatório (Muda uma vez por dia para cada usuário)" - _dailyRannum: - arg1: "Valor mínimo" - arg2: "Valor máximo" - dailyRandomPick: "Escolher aleatoriamente de uma lista (Muda uma vez por dia para cada usuário)" - _dailyRandomPick: - arg1: "Listas" - seedRandom: "Aleatório (com semente)" - _seedRandom: - arg1: "Semente" - arg2: "Probabilidade" - seedRannum: "Número aleatório (com semente)" - _seedRannum: - arg1: "Semente" - arg2: "Valor mínimo" - arg3: "Valor máximo" - seedRandomPick: "Escolher aleatoriamente de uma lista (com uma semente)" - _seedRandomPick: - arg1: "Semente" - arg2: "Listas" - DRPWPM: "Escolher aleatoriamente de uma lista ponderada (Muda uma vez por dia para cada usuário)" - _DRPWPM: - arg1: "Lista de texto" - pick: "Escolhe a partir da lista" - _pick: - arg1: "Listas" - arg2: "Posição" - listLen: "Pegar comprimento da lista" - _listLen: - arg1: "Listas" - number: "Numérico" - stringToNumber: "Texto para numérico" - _stringToNumber: - arg1: "Texto" - numberToString: "Numérico para texto" - _numberToString: - arg1: "Numérico" - splitStrByLine: "Dividir texto por quebras" - _splitStrByLine: - arg1: "Texto" - ref: "Variável" - aiScriptVar: "Variável AiScript" - fn: "Função" - _fn: - slots: "Espaços" - slots-info: "Separar cada espaço com uma quebra de texto" - arg1: "Resultado" - for: "Repetição 'for'" - _for: - arg1: "Número de repetições" - arg2: "Ação" - typeError: "Espaço {slot} aceita valores de tipo \"{expect}\", mas o valor dado é do tipo \"{actual}\"!" - thereIsEmptySlot: "O espaço {slot} está vazio!" - types: - string: "Texto" - number: "Numérico" - array: "Listas" - stringArray: "Lista de texto" - emptySlot: "Espaço vazio" - enviromentVariables: "Variáveis de ambiente" - pageVariables: "Variáveis de página" _relayStatus: requesting: "Pendente" accepted: "Aprovado" diff --git a/locales/ro-RO.yml b/locales/ro-RO.yml index dc757192d..351229452 100644 --- a/locales/ro-RO.yml +++ b/locales/ro-RO.yml @@ -258,7 +258,6 @@ remoteUserCaution: "Deoarece acest utilizator este dintr-o instanță externă, activity: "Activitate" images: "Imagini" birthday: "Zi de naștere" -yearsOld: "{age} ani" registeredDate: "Data înregistrării" location: "Locație" theme: "Teme" @@ -473,8 +472,6 @@ dayOverDayChanges: "Schimbări până ieri" appearance: "Aspect" clientSettings: "Setări client" accountSettings: "Setări cont" -promotion: "Promovat" -promote: "Promovează" numberOfDays: "Numărul zilelor" hideThisNote: "Ascunde această notă" showFeaturedNotesInTimeline: "Arată notele recomandate în cronologii" @@ -550,7 +547,6 @@ poll: "Sondaj" useCw: "Ascunde conținutul" enablePlayer: "Deschide player-ul video" disablePlayer: "Închide player-ul video" -expandTweet: "Expandează tweet" themeEditor: "Editor de teme" description: "Descriere" describeFile: "Adaugă titrări" @@ -684,27 +680,6 @@ _charts: federation: "Federație" _timelines: home: "Acasă" -_pages: - blocks: - image: "Imagini" - script: - categories: - list: "Liste" - blocks: - _join: - arg1: "Liste" - _randomPick: - arg1: "Liste" - _dailyRandomPick: - arg1: "Liste" - _seedRandomPick: - arg2: "Liste" - _pick: - arg1: "Liste" - _listLen: - arg1: "Liste" - types: - array: "Liste" _notification: youWereFollowed: "te-a urmărit" youWereInvitedToGroup: "Ai fost invitat într-un grup" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index dcf152b25..ffc7cca2a 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -258,7 +258,6 @@ remoteUserCaution: "Это пользователь с другого сайта activity: "Активность" images: "Изображения" birthday: "День рождения" -yearsOld: "Возраст: {age}" registeredDate: "Дата регистрации" location: "Местоположение" theme: "Тема" @@ -473,8 +472,6 @@ dayOverDayChanges: "За день" appearance: "Внешний вид" clientSettings: "Настройки клиента" accountSettings: "Настройки учетной записи" -promotion: "Продвинуто" -promote: "Продвинуть" numberOfDays: "Количество дней" hideThisNote: "Спрятать эту запись" showFeaturedNotesInTimeline: "Показывать в ленте заметки из «Горячего»" @@ -550,7 +547,6 @@ poll: "Опрос" useCw: "Скрывать содержимое под предупреждением" enablePlayer: "Включить проигрыватель" disablePlayer: "Выключить проигрыватель" -expandTweet: "Развернуть твит" themeEditor: "Редактор темы оформления" description: "Описание" describeFile: "Добавить подпись" @@ -1310,10 +1306,7 @@ _pages: my: "Свои страницы" liked: "Понравившиеся страницы" featured: "Популярные" - inspector: "Инспектор" contents: "Содержимое" - content: "Содержимое" - variables: "Переменные" title: "Заголовок" url: "Адрес страницы" summary: "Краткое содержание" @@ -1324,262 +1317,6 @@ _pages: fontSansSerif: "Гротеск (без засечек)" eyeCatchingImageSet: "Добавить картинку для привлечения внимания" eyeCatchingImageRemove: "Убрать картинку для привлечения внимания" - chooseBlock: "Добавить блок" - selectType: "Выберите вид" - enterVariableName: "Ведите имя переменной" - variableNameIsAlreadyUsed: "Это имя уже есть у другой переменной" - contentBlocks: "Содержательные" - inputBlocks: "Для ввода" - specialBlocks: "Особые" - blocks: - text: "Текст" - textarea: "Текст в рамке" - section: "Раздел" - image: "Изображения" - button: "Кнопка" - if: "Условный" - _if: - variable: "Переменная" - post: "Создание заметки" - _post: - text: "Текст" - attachCanvasImage: "Прикрепить изображение с холста" - canvasId: "Метка холста" - textInput: "Поле ввода текста" - _textInput: - name: "Имя переменной" - text: "Подпись" - default: "Исходное содержимое" - textareaInput: "Многострочное поле ввода текста" - _textareaInput: - name: "Имя переменной" - text: "Подпись" - default: "Исходное содержимое" - numberInput: "Поле для ввода числа" - _numberInput: - name: "Имя переменной" - text: "Подпись" - default: "Исходное значение" - canvas: "Холст" - _canvas: - id: "Метка холста" - width: "Ширина" - height: "Высота" - note: "Встроенная заметка" - _note: - id: "Идентификатор заметки" - idDescription: "Можно также вставить ссылку на заметку." - detailed: "Подробный вид" - switch: "Выключатель" - _switch: - name: "Имя переменной" - text: "Подпись" - default: "Исходное содержимое" - counter: "Кнопка со счётчиком" - _counter: - name: "Имя переменной" - text: "Надпись" - inc: "Увеличивать на" - _button: - text: "Надпись" - colored: "Выделена цветом" - action: "Действие по нажатию" - _action: - dialog: "Показать всплывающий текст" - _dialog: - content: "Всплывающий текст" - resetRandom: "Сброс генератора случайности" - pushEvent: "Вызвать событие" - _pushEvent: - event: "Имя события" - message: "Сообщение при нажатии" - variable: "Передать переменную с событием" - no-variable: "нет" - callAiScript: "Вызвать AiScript" - _callAiScript: - functionName: "Имя функции" - radioButton: "Кнопка-переключатель" - _radioButton: - name: "Имя переменной" - title: "Заголовок" - values: "Значения" - default: "Исходное значение" - script: - categories: - flow: "Управление исполнением" - logical: "Логические" - operation: "Арифметические" - comparison: "Сравнение" - random: "Случайные" - value: "Значения" - fn: "Функции" - text: "Текстовые" - convert: "Преобразование" - list: "Список" - blocks: - text: "Строка текста" - multiLineText: "Многострочный текст" - textList: "Список строк текста" - _textList: - info: "Пишите каждый пункт с новой строки" - strLen: "Длина текста" - _strLen: - arg1: "Текст" - strPick: "Взять знак из текста" - _strPick: - arg1: "Текст" - arg2: "Позиция знака" - strReplace: "Замена текста" - _strReplace: - arg1: "Текст, в котором заменять" - arg2: "Заменяемый текст" - arg3: "Менять на" - strReverse: "В обратном порядке" - _strReverse: - arg1: "Текст" - join: "Объединение" - _join: - arg1: "Списки" - arg2: "Разделитель" - add: "Добавить" - _add: - arg1: "A" - arg2: "B" - subtract: "Вычитание" - _subtract: - arg1: "A" - arg2: "B" - multiply: "Умножение" - _multiply: - arg1: "A" - arg2: "B" - divide: "Деление" - _divide: - arg1: "A" - arg2: "B" - mod: "Остаток от деления" - _mod: - arg1: "A" - arg2: "B" - round: "Округление до целого" - _round: - arg1: "Число" - eq: "A равно B" - _eq: - arg1: "А" - arg2: "B" - notEq: "A не равно B" - _notEq: - arg1: "A" - arg2: "B" - and: "A и B" - _and: - arg1: "A" - arg2: "B" - or: "A или B" - _or: - arg1: "A" - arg2: "B" - lt: "A < B (меньше)" - _lt: - arg1: "A" - arg2: "B" - gt: "A > B (больше)" - _gt: - arg1: "A" - arg2: "B" - ltEq: "A ⩽ B (меньше или равно)" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: "A ⩾ B (больше или равно)" - _gtEq: - arg1: "A" - arg2: "B" - if: "Условный" - _if: - arg1: "Условие" - arg2: "Если правда" - arg3: "Если ложь" - not: "Отрицание" - _not: - arg1: "Условие" - random: "Случайность" - _random: - arg1: "Вероятность" - rannum: "Случайное число" - _rannum: - arg1: "Минимум" - arg2: "Максимум" - randomPick: "Случайный выбор из списка" - _randomPick: - arg1: "Списки" - dailyRandom: "Случайность (на день для пользователя)" - _dailyRandom: - arg1: "Вероятность" - dailyRannum: "Случайное число (на день для пользователя)" - _dailyRannum: - arg1: "Минимум" - arg2: "Максимум" - dailyRandomPick: "Случайный выбор из списка (на день для пользователя)" - _dailyRandomPick: - arg1: "Списки" - seedRandom: "Псевдослучайность (заданная зерном)" - _seedRandom: - arg1: "Зерно" - arg2: "Вероятность" - seedRannum: "Псевдослучайное число (заданное зерном)" - _seedRannum: - arg1: "Зерно" - arg2: "Минимум" - arg3: "Максимум" - seedRandomPick: "Псевдослучайный выбор из списка (заданный зерном)" - _seedRandomPick: - arg1: "Зерно" - arg2: "Списки" - DRPWPM: "Случайный выбор из взвешенного списка (на день для пользователя)" - _DRPWPM: - arg1: "Список строк текста" - pick: "Выбор из списка" - _pick: - arg1: "Списки" - arg2: "Индекс" - listLen: "Количество элементов в списке" - _listLen: - arg1: "Списки" - number: "Число" - stringToNumber: "Число из текста" - _stringToNumber: - arg1: "Текст" - numberToString: "Число в текст" - _numberToString: - arg1: "Число" - splitStrByLine: "Разделение текста на строки" - _splitStrByLine: - arg1: "Текст" - ref: "Переменная" - aiScriptVar: "Переменная AiScript" - fn: "Свои функции" - _fn: - slots: "Аргументы" - slots-info: "Напишите имя каждого аргумента с новой строки" - arg1: "Формула" - for: "Цикл" - _for: - arg1: "Количество повторений" - arg2: "Действие" - typeError: "Аргумент {slot} должен быть иметь тип «{expect}», а передали «{actual}»!" - thereIsEmptySlot: "Аргумент {slot} не заполнен!" - types: - string: "Текст" - number: "Число" - boolean: "Логический" - array: "Списки" - stringArray: "Список строк текста" - emptySlot: "Пустой аргумент" - enviromentVariables: "Переменная окружения" - pageVariables: "Элемент страницы" - argVariables: "Аргументы" _relayStatus: requesting: "В ожидании одобрения" accepted: "Одобрено." diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml index 16af4d026..49f494019 100644 --- a/locales/sk-SK.yml +++ b/locales/sk-SK.yml @@ -258,7 +258,6 @@ remoteUserCaution: "Tieto informácie nemusia byť aktuálne, keďže používat activity: "Aktivita" images: "Obrázky" birthday: "Dátum narodenia" -yearsOld: "{age} rokov" registeredDate: "Dátum registrácie" location: "Lokalita" theme: "Téma" @@ -473,8 +472,6 @@ dayOverDayChanges: "Medzidenné zmeny" appearance: "Vzhľad" clientSettings: "Nastavenia klienta" accountSettings: "Nastavenia účtu" -promotion: "Propagácia" -promote: "Propagovať" numberOfDays: "Počet dní" hideThisNote: "Skryť túto poznámku" showFeaturedNotesInTimeline: "Zobraziť významné poznámky v časovej osi" @@ -550,7 +547,6 @@ poll: "Hlasovanie" useCw: "Skryť obsah" enablePlayer: "Otvoriť video prehrávač" disablePlayer: "Zavrieť video prehrávač" -expandTweet: "Rozšíriť tweet" themeEditor: "Editor tém" description: "Popis" describeFile: "Pridať nadpis" @@ -1324,10 +1320,7 @@ _pages: my: "Moje stránky" liked: "Obľúbené stránky" featured: "Význačné" - inspector: "Inšpektor" contents: "Obsah" - content: "Blok stránky" - variables: "Premenné" title: "Nadpis" url: "URL stránky" summary: "Zhrnutie stránky" @@ -1338,262 +1331,6 @@ _pages: fontSansSerif: "Bezpätkové" eyeCatchingImageSet: "Nastaviť miniatúru" eyeCatchingImageRemove: "Odstrániť miniatúru" - chooseBlock: "Pridať blok" - selectType: "Vyberte typ" - enterVariableName: "Zadajte meno premennej" - variableNameIsAlreadyUsed: "Meno premennej s už používa" - contentBlocks: "Obsah" - inputBlocks: "Vstup" - specialBlocks: "Špeciálne" - blocks: - text: "Text" - textarea: "Textové pole" - section: "Sekcia" - image: "Obrázky" - button: "Tlačidlo" - if: "Ak" - _if: - variable: "Premenné" - post: "Napísať poznámku" - _post: - text: "Obsah" - attachCanvasImage: "Príspevok s obrázkom na plátne" - canvasId: "ID plátna" - textInput: "Textový vstup" - _textInput: - name: "Meno premennej" - text: "Nadpis" - default: "Predvolená hodnota" - textareaInput: "Viacriadkový textový vstup" - _textareaInput: - name: "Meno premennej" - text: "Nadpis" - default: "Predvolená hodnota" - numberInput: "Číselný vstup" - _numberInput: - name: "Meno premennej" - text: "Nadpis" - default: "Predvolená hodnota" - canvas: "Plátno" - _canvas: - id: "ID plátna" - width: "Šírka" - height: "Výška" - note: "Vložená poznámka" - _note: - id: "ID poznámky" - idDescription: "Alebo môžete vložiť URL poznámky sem" - detailed: "Podrobný pohľad" - switch: "Prepnúť" - _switch: - name: "Meno premennej" - text: "Nadpis" - default: "Predvolená hodnota" - counter: "Počítadlo" - _counter: - name: "Meno premennej" - text: "Nadpis" - inc: "Pripočítať" - _button: - text: "Nadpis" - colored: "Farebné" - action: "Operácia po stlačení tlačidla" - _action: - dialog: "Zobraziť dialóg" - _dialog: - content: "Obsah" - resetRandom: "Resetovať zdroj náhodnosti" - pushEvent: "Poslať udalosť" - _pushEvent: - event: "Názov udalosti" - message: "Zobrazená správa po aktivácii" - variable: "Odoslaná premenná" - no-variable: "Žiadne" - callAiScript: "Spustiť AiScript" - _callAiScript: - functionName: "Názov funkcie" - radioButton: "Možnosť" - _radioButton: - name: "Meno premennej" - title: "Nadpis" - values: "Zoznam možností oddelené novými riadkami" - default: "Predvolená hodnota" - script: - categories: - flow: "Riadenie behu" - logical: "Logická operácia" - operation: "Výpočet" - comparison: "Porovnanie" - random: "Náhodné" - value: "Hodnoty" - fn: "Funkcie" - text: "Textové operácie" - convert: "Transformácie" - list: "Zoznamy" - blocks: - text: "Text" - multiLineText: "Text (viacriadkový)" - textList: "Zoznam textov" - _textList: - info: "Oddeľte každú položku novým riadkom" - strLen: "Dĺžka textu" - _strLen: - arg1: "Text" - strPick: "Vybrať znak" - _strPick: - arg1: "Text" - arg2: "Pozícia znaku" - strReplace: "Náhradný text" - _strReplace: - arg1: "Text" - arg2: "Nahradený text" - arg3: "Nahradiť s" - strReverse: "Otočiť text" - _strReverse: - arg1: "Text" - join: "Spojiť texty" - _join: - arg1: "Zoznamy" - arg2: "Oddeľovač" - add: "Pridať" - _add: - arg1: "A" - arg2: "B" - subtract: "Odčítať" - _subtract: - arg1: "A" - arg2: "B" - multiply: "Násobiť" - _multiply: - arg1: "A" - arg2: "B" - divide: "Deliť" - _divide: - arg1: "A" - arg2: "B" - mod: "Zvyšok po delení" - _mod: - arg1: "A" - arg2: "B" - round: "Zaokrúhliť" - _round: - arg1: "Číslo" - eq: "A a B sa rovnajú" - _eq: - arg1: "A" - arg2: "B" - notEq: "A a B sa nerovnajú" - _notEq: - arg1: "A" - arg2: "B" - and: "A a zároveň B" - _and: - arg1: "A" - arg2: "B" - or: "A alebo B" - _or: - arg1: "A" - arg2: "B" - lt: "< A je menšie ako B" - _lt: - arg1: "A" - arg2: "B" - gt: "> A je väčšie ako B" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A je menšie alebo rovné B" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A je väčšie alebo rovné B" - _gtEq: - arg1: "A" - arg2: "B" - if: "Vetva" - _if: - arg1: "Ak" - arg2: "Potom" - arg3: "Inak" - not: "Opak" - _not: - arg1: "Opak" - random: "Náhodné" - _random: - arg1: "Pravdepodobnosť" - rannum: "Náhodné číslo" - _rannum: - arg1: "Minimálna hodnota" - arg2: "Maximálna hodnota" - randomPick: "Náhodný výber zo zoznamu" - _randomPick: - arg1: "Zoznam" - dailyRandom: "Náhodne (zmení sa raz denne pre každého používateľa)" - _dailyRandom: - arg1: "Pravdepodobnosť" - dailyRannum: "Náhodné číslo (Mení sa denne pre každého používateľa)" - _dailyRannum: - arg1: "Minimálna hodnota" - arg2: "Maximálna hodnota" - dailyRandomPick: "Náhodný výber zo zoznamu (Mení sa denne pre každého používateľa)" - _dailyRandomPick: - arg1: "Zoznam" - seedRandom: "Náhodne (so seedom)" - _seedRandom: - arg1: "Seed" - arg2: "Pravdepodobnosť" - seedRannum: "Náhodné číslo (so seedom)" - _seedRannum: - arg1: "Seed" - arg2: "Minimálna hodnota" - arg3: "Maximálna hodnota" - seedRandomPick: "Náhodný výber zo zoznamu (so seedom)" - _seedRandomPick: - arg1: "Seed" - arg2: "Zoznam" - DRPWPM: "Náhodný výber z váženého zoznamu (Mení sa denne pre každého používateľa)" - _DRPWPM: - arg1: "Zoznam textov" - pick: "Vybrať zo zoznamu" - _pick: - arg1: "Zoznam" - arg2: "Pozícia" - listLen: "Získať dĺžku zoznamu" - _listLen: - arg1: "Zoznam" - number: "Číslo" - stringToNumber: "Text na číslo" - _stringToNumber: - arg1: "Text" - numberToString: "Číslo na text" - _numberToString: - arg1: "Číslo" - splitStrByLine: "Rozdelí text po riadkoch" - _splitStrByLine: - arg1: "Text" - ref: "Premenné" - aiScriptVar: "AiScript premenná" - fn: "Funkcie" - _fn: - slots: "Sloty" - slots-info: "Oddeľte každý slot novým riadkom" - arg1: "Výstup" - for: "For cyklus" - _for: - arg1: "Počet opakovaní" - arg2: "Akcia" - typeError: "Slot {slot} akceptuje hodnoty typu \"{expect}\", ale dodaná hodnota je typu \"{actual}\"!" - thereIsEmptySlot: "Slot {slot} je prázdny!" - types: - string: "Text" - number: "Číslo" - boolean: "Boolean" - array: "Zoznamy" - stringArray: "Zoznam textov" - emptySlot: "Prázdny slot" - enviromentVariables: "Premenné prostredia" - pageVariables: "Premenné stránky" - argVariables: "Vstupné sloty" _relayStatus: requesting: "Čaká sa" accepted: "Akceptované" diff --git a/locales/sv-SE.yml b/locales/sv-SE.yml index c1d254efd..18a5babb5 100644 --- a/locales/sv-SE.yml +++ b/locales/sv-SE.yml @@ -280,25 +280,6 @@ _exportOrImport: userLists: "Listor" _charts: federation: "Federation" -_pages: - script: - categories: - list: "Listor" - blocks: - _join: - arg1: "Listor" - _randomPick: - arg1: "Listor" - _dailyRandomPick: - arg1: "Listor" - _seedRandomPick: - arg2: "Listor" - _pick: - arg1: "Listor" - _listLen: - arg1: "Listor" - types: - array: "Listor" _notification: youWereFollowed: "följde dig" _types: diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index 7ca44999c..f918bd984 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -258,7 +258,6 @@ remoteUserCaution: "Інформація може бути неповною, о activity: "Активність" images: "Зображення" birthday: "День народження" -yearsOld: "{age} років" registeredDate: "Приєднався(лась)" location: "Локація" theme: "Тема" @@ -473,8 +472,6 @@ dayOverDayChanges: "Доба" appearance: "Вигляд" clientSettings: "Налаштування клієнта" accountSettings: "Налаштування акаунта" -promotion: "Виділене" -promote: "Виділити" numberOfDays: "Кількість днів" hideThisNote: "Сховати цю нотатку" showFeaturedNotesInTimeline: "Показувати популярні нотатки у стрічці" @@ -550,7 +547,6 @@ poll: "Опитування" useCw: "Приховати вміст" enablePlayer: "Відкрити відеоплеєр" disablePlayer: "Закрити відеоплеєр" -expandTweet: "Розгорнути твіт" themeEditor: "Редактор тем" description: "Опис" describeFile: "Додати підпис" @@ -1128,10 +1124,7 @@ _pages: my: "Мої сторінки" liked: "Вподобані сторінки" featured: "Популярні" - inspector: "Інспектор" contents: "Вміст" - content: "Блок сторінки" - variables: "Змінні" title: "Заголовок" url: "URL сторінки" summary: "Короткий зміст" @@ -1142,261 +1135,6 @@ _pages: fontSansSerif: "Sans serif" eyeCatchingImageSet: "Встановити привабливе зображення" eyeCatchingImageRemove: "Видалити привабливе зображення" - chooseBlock: "Додати блок" - selectType: "Виберіть тип" - enterVariableName: "Введіть назву для змінної" - variableNameIsAlreadyUsed: "Ця назва вже використовується іншою змінною" - contentBlocks: "Контент" - inputBlocks: "Ввід" - specialBlocks: "Особливе" - blocks: - text: "Текст" - textarea: "Текстова область" - section: "Розділ" - image: "Зображення" - button: "Кнопка" - if: "Якщо" - _if: - variable: "Змінні" - post: "Створення нотатки" - _post: - text: "Вміст" - canvasId: "Ідентифікатор полотна" - textInput: "Введення тексту" - _textInput: - name: "Ім'я змінної" - text: "Назва" - default: "Значення за замовчуванням" - textareaInput: "Багаторядкове введення тексту" - _textareaInput: - name: "Ім'я змінної" - text: "Назва" - default: "Значення за замовчуванням" - numberInput: "Числове введення" - _numberInput: - name: "Ім'я змінної" - text: "Назва" - default: "Значення за замовчуванням" - canvas: "Полотно" - _canvas: - id: "Ідентифікатор полотна" - width: "Ширина" - height: "Висота" - note: "Вбудована нотатка" - _note: - id: "Ідентифікатор нотатки" - idDescription: "Також можна вказати посилання на нотатку" - detailed: "Детальний вигляд" - switch: "Перемикач" - _switch: - name: "Ім'я змінної" - text: "Назва" - default: "Значення за замовчуванням" - counter: "Лічильник" - _counter: - name: "Ім'я змінної" - text: "Назва" - inc: "Збільшити на" - _button: - text: "Напис" - colored: "Кольоровий" - action: "Дія кнопки" - _action: - dialog: "Показати повідомлення" - _dialog: - content: "Вміст" - resetRandom: "Скидання генератора випадковості" - pushEvent: "Надіслати подію" - _pushEvent: - event: "Назві події" - message: "Повідомлення для відображення при активації" - variable: "Змінна для надсилання" - no-variable: "Відсутньо" - callAiScript: "Виклик AiScript" - _callAiScript: - functionName: "Ім'я функції" - radioButton: "Вибір" - _radioButton: - name: "Ім'я змінної" - title: "Напис" - values: "Варіанти, розділені розривами рядків" - default: "Значення за замовчуванням" - script: - categories: - flow: "Керування потоком" - logical: "Логічні операції" - operation: "Обчислення" - comparison: "Порівняння" - random: "Випадковість" - value: "Значення" - fn: "Функції" - text: "Дії з текстом" - convert: "Перетворення" - list: "Списки" - blocks: - text: "Текст" - multiLineText: "Текст (багаторядковий)" - textList: "Текстовий список" - _textList: - info: "Використовувати новий рядок як роздільник для вводу" - strLen: "Довжина тексту" - _strLen: - arg1: "Текст" - strPick: "Вибрати символ" - _strPick: - arg1: "Текст" - arg2: "Розташування символу" - strReplace: "Заміна тексту" - _strReplace: - arg1: "Текст" - arg2: "Текст, який потрібно замінити" - arg3: "Заміняти на" - strReverse: "Перевернути текст" - _strReverse: - arg1: "Текст" - join: "Конкатенація тексту" - _join: - arg1: "Списки" - arg2: "Розділювач" - add: "Додати" - _add: - arg1: "A" - arg2: "B" - subtract: "Відняти" - _subtract: - arg1: "A" - arg2: "B" - multiply: "Помножити" - _multiply: - arg1: "A" - arg2: "B" - divide: "Поділити" - _divide: - arg1: "A" - arg2: "B" - mod: "Остача" - _mod: - arg1: "A" - arg2: "B" - round: "Десяткове округлення" - _round: - arg1: "Число" - eq: "A дорівнює B" - _eq: - arg1: "A" - arg2: "B" - notEq: "A не дорівнює B" - _notEq: - arg1: "A" - arg2: "B" - and: "А І Б" - _and: - arg1: "A" - arg2: "B" - or: "A АБО B" - _or: - arg1: "A" - arg2: "B" - lt: "< A менше, ніж B" - _lt: - arg1: "A" - arg2: "B" - gt: "> A більше, ніж B" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A менше або дорівнює B" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A більше або дорівнює B" - _gtEq: - arg1: "A" - arg2: "B" - if: "Умова" - _if: - arg1: "Якщо" - arg2: "Якщо так" - arg3: "Якщо ні" - not: "НЕ" - _not: - arg1: "НЕ" - random: "Випадково" - _random: - arg1: "Імовірність" - rannum: "Випадкове число" - _rannum: - arg1: "Мінімальне значення" - arg2: "Максимальне значення" - randomPick: "Випадковий вибір зі списку" - _randomPick: - arg1: "Списки" - dailyRandom: "Випадково (триває добу)" - _dailyRandom: - arg1: "Імовірність" - dailyRannum: "Випадкове число (триває добу)" - _dailyRannum: - arg1: "Мінімальне значення" - arg2: "Максимальне значення" - dailyRandomPick: "Випадково вибрати зі списку (триває добу)" - _dailyRandomPick: - arg1: "Списки" - seedRandom: "Випадковість (з насінням)" - _seedRandom: - arg1: "Насіння" - arg2: "Імовірність" - seedRannum: "Випадкове число (з насінням)" - _seedRannum: - arg1: "Насіння" - arg2: "Мінімальне значення" - arg3: "Максимальне значення" - seedRandomPick: "Випадково вибрати зі списку (з насінням)" - _seedRandomPick: - arg1: "Насіння" - arg2: "Списки" - DRPWPM: "Випадково вибрати зі зваженого списку (триває добу)" - _DRPWPM: - arg1: "Текстовий список" - pick: "Вибір зі списку" - _pick: - arg1: "Списки" - arg2: "Позиція" - listLen: "Отримати довжину списку" - _listLen: - arg1: "Списки" - number: "Число" - stringToNumber: "Текст на число" - _stringToNumber: - arg1: "Текст" - numberToString: "Число на текст" - _numberToString: - arg1: "Число" - splitStrByLine: "Розбиття тексту на рядки" - _splitStrByLine: - arg1: "Текст" - ref: "Змінні" - aiScriptVar: "Змінна AiScript" - fn: "Функції" - _fn: - slots: "Паз" - slots-info: "Використовувати нову лінію як роздільник пазів" - arg1: "Вивід" - for: "Повторення" - _for: - arg1: "Кількість повторень" - arg2: "Дія" - typeError: "Паз {slot} приймає \"{expect}\" тип, але надана змінна має тип \"{actual}\"!" - thereIsEmptySlot: "Паз {slot} пустий!" - types: - string: "Текст" - number: "Число" - boolean: "Прапорець" - array: "Списки" - stringArray: "Текстовий список" - emptySlot: "Пустий паз" - enviromentVariables: "Змінні середовища" - pageVariables: "Елемент сторінки" - argVariables: "Стрічка вводу" _relayStatus: requesting: "Очікує затвердження" accepted: "Затверджено" diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml index fe7709d88..af716775b 100644 --- a/locales/vi-VN.yml +++ b/locales/vi-VN.yml @@ -258,7 +258,6 @@ remoteUserCaution: "Vì người dùng này ở máy chủ khác, thông tin hi activity: "Hoạt động" images: "Hình ảnh" birthday: "Sinh nhật" -yearsOld: "{age} tuổi" registeredDate: "Tham gia" location: "Đến từ" theme: "Chủ đề" @@ -473,8 +472,6 @@ dayOverDayChanges: "Thay đổi hôm qua" appearance: "Giao diện" clientSettings: "Cài đặt Client" accountSettings: "Cài đặt tài khoản" -promotion: "Quảng cáo" -promote: "Quảng cáo" numberOfDays: "Số ngày" hideThisNote: "Ẩn tút này" showFeaturedNotesInTimeline: "Hiện tút nổi bật trong bảng tin" @@ -550,7 +547,6 @@ poll: "Bình chọn" useCw: "Ẩn nội dung" enablePlayer: "Mở trình phát video" disablePlayer: "Đóng trình phát video" -expandTweet: "Mở rộng tweet" themeEditor: "Công cụ thiết kế theme" description: "Mô tả" describeFile: "Thêm mô tả" @@ -1325,10 +1321,7 @@ _pages: my: "Trang của tôi" liked: "Trang đã thích" featured: "Nổi tiếng" - inspector: "Thanh tra" contents: "Nội dung" - content: "Chặn Trang" - variables: "Biến thể" title: "Tựa đề" url: "URL Trang" summary: "Mô tả Trang" @@ -1339,262 +1332,6 @@ _pages: fontSansSerif: "Sans Serif" eyeCatchingImageSet: "Đặt ảnh thu nhỏ" eyeCatchingImageRemove: "Xóa ảnh thu nhỏ" - chooseBlock: "Thêm khối" - selectType: "Chọn kiểu" - enterVariableName: "Nhập tên một biến thể" - variableNameIsAlreadyUsed: "Tên biến thể này đã được sử dụng" - contentBlocks: "Nội dung" - inputBlocks: "Nhập" - specialBlocks: "Đặc biệt" - blocks: - text: "Văn bản" - textarea: "Khu vực văn bản" - section: "Mục " - image: "Hình ảnh" - button: "Nút" - if: "Nếu" - _if: - variable: "Biến thể" - post: "Mẫu đăng" - _post: - text: "Nội dung" - attachCanvasImage: "Đính kèm hình canva" - canvasId: "ID Canva" - textInput: "Văn bản đầu vào" - _textInput: - name: "Tên biến thể" - text: "Tựa đề" - default: "Giá trị mặc định" - textareaInput: "Văn bản nhiều dòng đầu vào" - _textareaInput: - name: "Tên biến thể" - text: "Tựa đề" - default: "Giá trị mặc định" - numberInput: "Đầu vào số" - _numberInput: - name: "Tên biến thể" - text: "Tựa đề" - default: "Giá trị mặc định" - canvas: "Canva" - _canvas: - id: "ID Canva" - width: "Chiều rộng" - height: "Chiều cao" - note: "Tút đã nhúng" - _note: - id: "ID tút" - idDescription: "Ngoài ra, bạn có thể dán URL tút vào đây." - detailed: "Xem chi tiết" - switch: "Chuyển đổi" - _switch: - name: "Tên biến thể" - text: "Tựa đề" - default: "Giá trị mặc định" - counter: "Bộ đếm" - _counter: - name: "Tên biến thể" - text: "Tựa đề" - inc: "Bước" - _button: - text: "Tựa đề" - colored: "Với màu" - action: "Thao tác khi nhấn nút" - _action: - dialog: "Hiện hộp thoại" - _dialog: - content: "Nội dung" - resetRandom: "Đặt lại seed ngẫu nhiên" - pushEvent: "Gửi một sự kiện" - _pushEvent: - event: "Tên sự kiện" - message: "Tin nhắn hiển thị khi kích hoạt" - variable: "Biển thể để gửi" - no-variable: "Không" - callAiScript: "Gọi AiScript" - _callAiScript: - functionName: "Tên tính năng" - radioButton: "Lựa chọn" - _radioButton: - name: "Tên biến thể" - title: "Tựa đề" - values: "Phân tách các mục bằng cách xuống dòng" - default: "Giá trị mặc định" - script: - categories: - flow: "Điều khiển" - logical: "Hoạt động logic" - operation: "Tính toán" - comparison: "So sánh" - random: "Ngẫu nhiên" - value: "Giá trị" - fn: "Tính năng" - text: "Tác vụ văn bản" - convert: "Chuyển đổi" - list: "Danh sách" - blocks: - text: "Văn bản" - multiLineText: "Văn bản (nhiều dòng)" - textList: "Văn bản liệt kê" - _textList: - info: "Phân tách mục bằng cách xuống dòng" - strLen: "Độ dài văn bản" - _strLen: - arg1: "Văn bản" - strPick: "Trích xuất chuỗi" - _strPick: - arg1: "Văn bản" - arg2: "Vị trí chuỗi" - strReplace: "Thay thế chuỗi" - _strReplace: - arg1: "Nội dung" - arg2: "Văn bản thay thế" - arg3: "Thay thế bằng" - strReverse: "Lật văn bản" - _strReverse: - arg1: "Văn bản" - join: "Nối văn bản" - _join: - arg1: "Danh sách" - arg2: "Phân cách" - add: "Cộng" - _add: - arg1: "A" - arg2: "B" - subtract: "Trừ" - _subtract: - arg1: "A" - arg2: "B" - multiply: "Nhân" - _multiply: - arg1: "A" - arg2: "B" - divide: "Chia" - _divide: - arg1: "A" - arg2: "B" - mod: "Phần còn lại" - _mod: - arg1: "A" - arg2: "B" - round: "Làm tròn thập phân" - _round: - arg1: "Số" - eq: "A và B bằng nhau" - _eq: - arg1: "A" - arg2: "B" - notEq: "A và B khác nhau" - _notEq: - arg1: "A" - arg2: "B" - and: "A VÀ B" - _and: - arg1: "A" - arg2: "B" - or: "A HOẶC B" - _or: - arg1: "A" - arg2: "B" - lt: "< A nhỏ hơn B" - _lt: - arg1: "A" - arg2: "B" - gt: "> A lớn hơn B" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A nhỏ hơn hoặc bằng B" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A lớn hơn hoặc bằng B" - _gtEq: - arg1: "A" - arg2: "B" - if: "Nhánh" - _if: - arg1: "Nếu" - arg2: "Sau đó" - arg3: "Khác" - not: "KHÔNG" - _not: - arg1: "KHÔNG" - random: "Ngẫu nhiên" - _random: - arg1: "Xác suất" - rannum: "Số ngẫu nhiên" - _rannum: - arg1: "Giá trị tối thiểu" - arg2: "Giá trị tối đa" - randomPick: "Chọn ngẫu nhiên từ danh sách" - _randomPick: - arg1: "Danh sách" - dailyRandom: "Ngẫu nhiên (Đổi mỗi người một lần mỗi ngày)" - _dailyRandom: - arg1: "Xác suất" - dailyRannum: "Số ngẫu nhiên (Đổi mỗi người một lần mỗi ngày)" - _dailyRannum: - arg1: "Giá trị tối thiểu" - arg2: "Giá trị tối đa" - dailyRandomPick: "Chọn ngẫu nhiên từ một danh sách (Đổi mỗi người một lần mỗi ngày)" - _dailyRandomPick: - arg1: "Danh sách" - seedRandom: "Ngẫu nhiên (với seed)" - _seedRandom: - arg1: "Seed" - arg2: "Xác suất" - seedRannum: "Số ngẫu nhiên (với seed)" - _seedRannum: - arg1: "Seed" - arg2: "Giá trị tối thiểu" - arg3: "Giá trị tối đa" - seedRandomPick: "Chọn ngẫu nhiên từ danh sách (với seed)" - _seedRandomPick: - arg1: "Seed" - arg2: "Danh sách" - DRPWPM: "Chọn ngẫu nhiên từ danh sách nặng (Đổi mỗi người một lần mỗi ngày)" - _DRPWPM: - arg1: "Văn bản liệt kê" - pick: "Chọn từ danh sách" - _pick: - arg1: "Danh sách" - arg2: "Vị trí" - listLen: "Lấy độ dài danh sách" - _listLen: - arg1: "Danh sách" - number: "Số" - stringToNumber: "Chữ thành số" - _stringToNumber: - arg1: "Văn bản" - numberToString: "Số thành chữ" - _numberToString: - arg1: "Số" - splitStrByLine: "Phân cách văn bản bằng cách xuống dòng" - _splitStrByLine: - arg1: "Văn bản" - ref: "Biến thể" - aiScriptVar: "Biển thể AiScript" - fn: "Tính năng" - _fn: - slots: "Chỗ" - slots-info: "Phân cách chỗ bằng cách xuống dòng" - arg1: "Đầu ra" - for: "để-Lặp lại" - _for: - arg1: "Số lần lặp lại" - arg2: "Hành động" - typeError: "Chỗ {slot} chấp nhận các giá trị thuộc loại \"{expect}\", nhưng giá trị được cung cấp thuộc loại \"{actual}\"!" - thereIsEmptySlot: "Chỗ {slot} đang trống!" - types: - string: "Văn bản" - number: "Số" - boolean: "Cờ" - array: "Danh sách" - stringArray: "Văn bản liệt kê" - emptySlot: "Chỗ trống" - enviromentVariables: "Biến môi trường" - pageVariables: "Biến trang" - argVariables: "Đầu vào chỗ" _relayStatus: requesting: "Đang chờ" accepted: "Đã duyệt" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 1719af0f6..b9b9b7475 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -258,7 +258,6 @@ remoteUserCaution: "由于此用户来自其它实例,显示的信息可能不 activity: "活动" images: "图片" birthday: "生日" -yearsOld: "{age}岁" registeredDate: "注册于" location: "位置" theme: "主题" @@ -473,8 +472,6 @@ dayOverDayChanges: "与前一日相比" appearance: "外观" clientSettings: "客户端设置" accountSettings: "账户设置" -promotion: "推广" -promote: "推广" numberOfDays: "天数" hideThisNote: "隐藏这条帖子" showFeaturedNotesInTimeline: "在时间线上显示热门推荐" @@ -550,7 +547,6 @@ poll: "调查问卷" useCw: "隐藏内容" enablePlayer: "打开播放器" disablePlayer: "关闭播放器" -expandTweet: "展开帖子" themeEditor: "主题编辑器" description: "描述" describeFile: "添加标题" @@ -1324,10 +1320,7 @@ _pages: my: "我的页面" liked: "喜欢的页面" featured: "热门" - inspector: "检查器" contents: "内容" - content: "页面内容" - variables: "变量" title: "标题" url: "页面URL" summary: "页面摘要" @@ -1338,262 +1331,6 @@ _pages: fontSansSerif: "无衬线字体" eyeCatchingImageSet: "设置封面图片" eyeCatchingImageRemove: "删除封面图片" - chooseBlock: "添加块" - selectType: "选择类型" - enterVariableName: "请输入变量名" - variableNameIsAlreadyUsed: "变量名已使用" - contentBlocks: "内容" - inputBlocks: "输入" - specialBlocks: "特殊" - blocks: - text: "文本" - textarea: "文本区域" - section: "章节" - image: "图片" - button: "按钮" - if: "如果" - _if: - variable: "变量" - post: "投稿窗口" - _post: - text: "内容" - attachCanvasImage: "附加画布图像" - canvasId: "画布ID" - textInput: "文本输入" - _textInput: - name: "变量名" - text: "标题" - default: "默认值" - textareaInput: "多行文本输入" - _textareaInput: - name: "变量名" - text: "标题" - default: "默认值" - numberInput: "输入数值" - _numberInput: - name: "变量名" - text: "标题" - default: "默认值" - canvas: "画布" - _canvas: - id: "画布ID" - width: "宽度" - height: "高度" - note: "嵌入的帖子" - _note: - id: "帖子ID" - idDescription: "您也可以通过粘贴帖子的URL来进行设置。" - detailed: "显示详细信息" - switch: "开关" - _switch: - name: "变量名" - text: "标题" - default: "默认值" - counter: "计数器" - _counter: - name: "变量名" - text: "标题" - inc: "增加值" - _button: - text: "标题" - colored: "彩色" - action: "按下按钮时的行为" - _action: - dialog: "显示对话框" - _dialog: - content: "内容" - resetRandom: "重置随机值" - pushEvent: "发送事件" - _pushEvent: - event: "事件名称" - message: "按下时显示的消息" - variable: "发送的变量" - no-variable: "空" - callAiScript: "调用AiScript" - _callAiScript: - functionName: "函数名" - radioButton: "选择项" - _radioButton: - name: "变量名" - title: "标题" - values: "使用换行区分的选择项" - default: "默认值" - script: - categories: - flow: "控制" - logical: "逻辑运算" - operation: "计算" - comparison: "比较" - random: "随机" - value: "值" - fn: "函数" - text: "文本操作" - convert: "转换" - list: "列表" - blocks: - text: "文本" - multiLineText: "文本 (多行)" - textList: "文本列表" - _textList: - info: "请使用换行符分隔每行" - strLen: "文本长度" - _strLen: - arg1: "文本" - strPick: "提取字符" - _strPick: - arg1: "文本" - arg2: "字符位置" - strReplace: "替换文本" - _strReplace: - arg1: "文本" - arg2: "替换之前" - arg3: "替换之后" - strReverse: "文本反向" - _strReverse: - arg1: "文本" - join: "合并文本" - _join: - arg1: "列表" - arg2: "分隔符" - add: "加" - _add: - arg1: "A" - arg2: "B" - subtract: "减" - _subtract: - arg1: "A" - arg2: "B" - multiply: "乘" - _multiply: - arg1: "A" - arg2: "B" - divide: "除" - _divide: - arg1: "A" - arg2: "B" - mod: "取模(MOD)" - _mod: - arg1: "A" - arg2: "B" - round: "四舍五入" - _round: - arg1: "数值" - eq: "A和B相等" - _eq: - arg1: "A" - arg2: "B" - notEq: "A和B不等" - _notEq: - arg1: "A" - arg2: "B" - and: "A和B" - _and: - arg1: "A" - arg2: "B" - or: "A或B" - _or: - arg1: "A" - arg2: "B" - lt: "< A小于B" - _lt: - arg1: "A" - arg2: "B" - gt: "> A大于B" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A小于等于B" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A大于等于B" - _gtEq: - arg1: "A" - arg2: "B" - if: "分支" - _if: - arg1: "如果" - arg2: "如果" - arg3: "否则" - not: "否" - _not: - arg1: "否" - random: "随机" - _random: - arg1: "概率" - rannum: "随机数" - _rannum: - arg1: "最小值" - arg2: "最大值" - randomPick: "从列表中随机选择" - _randomPick: - arg1: "列表" - dailyRandom: "随机(每个用户每日)" - _dailyRandom: - arg1: "概率" - dailyRannum: "随机数(每个用户每日)" - _dailyRannum: - arg1: "最小值" - arg2: "最大值" - dailyRandomPick: "从列表中随机选择(每个用户每日)" - _dailyRandomPick: - arg1: "列表" - seedRandom: "随机 (种子)" - _seedRandom: - arg1: "种子" - arg2: "概率" - seedRannum: "随机数(种子)" - _seedRannum: - arg1: "种子" - arg2: "最小值" - arg3: "最大值" - seedRandomPick: "从列表中随机选择 (种子)" - _seedRandomPick: - arg1: "种子" - arg2: "列表" - DRPWPM: "从概率列表中随机选择(每用户每天)" - _DRPWPM: - arg1: "文本列表" - pick: "从列表中选择" - _pick: - arg1: "列表" - arg2: "位置" - listLen: "获取列表长度" - _listLen: - arg1: "列表" - number: "数值" - stringToNumber: "文本到数字" - _stringToNumber: - arg1: "文本" - numberToString: "数字到文本" - _numberToString: - arg1: "数值" - splitStrByLine: "将文本按行拆分" - _splitStrByLine: - arg1: "文本" - ref: "变量" - aiScriptVar: "AiScript变量" - fn: "函数" - _fn: - slots: "槽函数" - slots-info: "请使用换行符分隔每个槽函数" - arg1: "输出" - for: "重复" - _for: - arg1: "次数" - arg2: "处理" - typeError: "槽函数{slot}需要传入“{expect}”,但是实际传入为“{actual}”!" - thereIsEmptySlot: "槽函数{slot}为空!" - types: - string: "文字" - number: "数值" - boolean: "Flag" - array: "列表" - stringArray: "文本列表" - emptySlot: "空白槽函数" - enviromentVariables: "环境变量" - pageVariables: "页面元素" - argVariables: "输入变量" _relayStatus: requesting: "待批准" accepted: "已批准" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 354ae8ea7..556990842 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -258,7 +258,6 @@ remoteUserCaution: "由於該使用者來自遠端實例,因此資訊可能非 activity: "動態" images: "圖片" birthday: "生日" -yearsOld: "{age}歲" registeredDate: "註冊日期" location: "位置" theme: "外觀主題" @@ -473,8 +472,6 @@ dayOverDayChanges: "與前一日相比" appearance: "外觀" clientSettings: "用戶端設定" accountSettings: "帳戶設定" -promotion: "推廣" -promote: "推廣" numberOfDays: "有效天數" hideThisNote: "隱藏此貼文" showFeaturedNotesInTimeline: "在時間軸上顯示熱門推薦" @@ -550,7 +547,6 @@ poll: "投票" useCw: "隱藏內容" enablePlayer: "打開播放器" disablePlayer: "關閉播放器" -expandTweet: "展開推文" themeEditor: "主題編輯器" description: "描述" describeFile: "添加標題 " @@ -1324,10 +1320,7 @@ _pages: my: "我的頁面" liked: "已喜歡的頁面" featured: "人氣" - inspector: "面板檢查" contents: "內容" - content: "頁面方塊" - variables: "變數" title: "標題" url: "頁面網址" summary: "頁面摘要" @@ -1338,262 +1331,6 @@ _pages: fontSansSerif: "無襯線體" eyeCatchingImageSet: "設定封面影像" eyeCatchingImageRemove: "刪除封面影像" - chooseBlock: "新增方塊" - selectType: "選擇類型" - enterVariableName: "請輸入變數名稱" - variableNameIsAlreadyUsed: "變數名稱已被佔用" - contentBlocks: "內容" - inputBlocks: "輸入" - specialBlocks: "特殊" - blocks: - text: "字串" - textarea: "字串區域" - section: "區段" - image: "圖片" - button: "按鈕" - if: "如果" - _if: - variable: "變數" - post: "發佈窗口" - _post: - text: "内容" - attachCanvasImage: "附加相簿圖像 " - canvasId: "畫布ID" - textInput: "插入字串" - _textInput: - name: "變數名稱" - text: "標題" - default: "預設值" - textareaInput: "多行文字输入" - _textareaInput: - name: "變數名稱" - text: "標題" - default: "預設值" - numberInput: "輸入數值" - _numberInput: - name: "變數名稱" - text: "標題" - default: "預設值" - canvas: "畫布" - _canvas: - id: "畫布ID" - width: "寬度" - height: "高度" - note: "嵌式貼文" - _note: - id: "貼文ID" - idDescription: "您也可以粘貼筆記 URL 並進行設置。 " - detailed: "顯示詳細內容" - switch: "開關" - _switch: - name: "變數名稱" - text: "標題" - default: "預設值" - counter: "計數器" - _counter: - name: "變數名稱" - text: "標題" - inc: "増加値" - _button: - text: "標題" - colored: "彩色" - action: "按下按鈕後發生的行為" - _action: - dialog: "顯示對話框 " - _dialog: - content: "内容" - resetRandom: "重設亂數" - pushEvent: "發送事件" - _pushEvent: - event: "事件名稱" - message: "按下時顯示的消息 " - variable: "要發送的變數" - no-variable: "沒有" - callAiScript: "調用AiScript" - _callAiScript: - functionName: "函數名稱" - radioButton: "選項" - _radioButton: - name: "變數名稱" - title: "標題" - values: "由換行符分隔的選項" - default: "預設值" - script: - categories: - flow: "控制" - logical: "邏輯運算" - operation: "計算" - comparison: "對比" - random: "隨機" - value: "數值 " - fn: "函数" - text: "文本操作" - convert: "轉換" - list: "清單" - blocks: - text: "字串" - multiLineText: "字串(多行)" - textList: "字串串列" - _textList: - info: "請分開每個換行符 " - strLen: "字串長度" - _strLen: - arg1: "字串" - strPick: "提取字元" - _strPick: - arg1: "字串" - arg2: "字元位置" - strReplace: "替換字串" - _strReplace: - arg1: "字串" - arg2: "替換前" - arg3: "替換後" - strReverse: "倒轉字串" - _strReverse: - arg1: "字串" - join: "合併字串" - _join: - arg1: "清單" - arg2: "分隔字元" - add: "加" - _add: - arg1: "A" - arg2: "B" - subtract: "减去" - _subtract: - arg1: "A" - arg2: "B" - multiply: "乘" - _multiply: - arg1: "A" - arg2: "B" - divide: "除" - _divide: - arg1: "A" - arg2: "B" - mod: "餘數" - _mod: - arg1: "A" - arg2: "B" - round: "四舍五入" - _round: - arg1: "數值" - eq: "A和B相等" - _eq: - arg1: "A" - arg2: "B" - notEq: "A和B不等" - _notEq: - arg1: "A" - arg2: "B" - and: "A和B" - _and: - arg1: "A" - arg2: "B" - or: "A或B" - _or: - arg1: "A" - arg2: "B" - lt: "< A小於B" - _lt: - arg1: "A" - arg2: "B" - gt: "> A大於B" - _gt: - arg1: "A" - arg2: "B" - ltEq: "<= A小於或等於B" - _ltEq: - arg1: "A" - arg2: "B" - gtEq: ">= A大於或等於B" - _gtEq: - arg1: "A" - arg2: "B" - if: "分支" - _if: - arg1: "如果" - arg2: "如果" - arg3: "除此以外 " - not: "否" - _not: - arg1: "否" - random: "隨機" - _random: - arg1: "機率" - rannum: "亂數" - _rannum: - arg1: "下限" - arg2: "上限" - randomPick: "從列表中隨機選擇 " - _randomPick: - arg1: "清單" - dailyRandom: "隨機(使用者每日變化 )" - _dailyRandom: - arg1: "機率" - dailyRannum: "亂數(使用者每日變化)" - _dailyRannum: - arg1: "下限" - arg2: "上限" - dailyRandomPick: "從列表中隨機選擇(使用者每日變化 ) " - _dailyRandomPick: - arg1: "清單" - seedRandom: "隨機抽選種子碼" - _seedRandom: - arg1: "種子" - arg2: "機率" - seedRannum: "亂數 (種子)" - _seedRannum: - arg1: "種子" - arg2: "最小值" - arg3: "最大值" - seedRandomPick: "從列表中隨機選擇 (種子)" - _seedRandomPick: - arg1: "種子" - arg2: "清單" - DRPWPM: "从機率列表中隨機選擇(每個用户每天)" - _DRPWPM: - arg1: "字串串列" - pick: "從清單中選取" - _pick: - arg1: "清單" - arg2: "位置" - listLen: "取得清單長度" - _listLen: - arg1: "清單" - number: "數值" - stringToNumber: "將字串轉換至數値" - _stringToNumber: - arg1: "字串" - numberToString: "將數値轉換至字串" - _numberToString: - arg1: "數值" - splitStrByLine: "於換行時分割字串" - _splitStrByLine: - arg1: "字串" - ref: "變數" - aiScriptVar: "AiScript的變數" - fn: "函数" - _fn: - slots: "欄位" - slots-info: "用換行符分隔每個欄位" - arg1: "輸出" - for: "重複 " - _for: - arg1: "重複次數" - arg2: "處理" - typeError: "槽參數{slot}需要傳入“{expect}”,但是實際傳入為“{actual}”!" - thereIsEmptySlot: "參數{slot}是空的!" - types: - string: "字串" - number: "数值" - boolean: "標記" - array: "清單" - stringArray: "字串列表" - emptySlot: "空欄位" - enviromentVariables: "環境變數" - pageVariables: "頁面元素" - argVariables: "輸入欄位" _relayStatus: requesting: "等待核准" accepted: "已通過核准" diff --git a/package.json b/package.json index ffec400f9..444b3c0d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "foundkey", - "version": "12.111.1-test.1", + "version": "13.0.0-preview.1", "repository": { "type": "git", "url": "https://akkoma.dev/FoundKeyGang/FoundKey.git" diff --git a/packages/backend/migration/1659335999000-pages-to-plaintext.js b/packages/backend/migration/1659335999000-pages-to-plaintext.js new file mode 100644 index 000000000..2f0a2f194 --- /dev/null +++ b/packages/backend/migration/1659335999000-pages-to-plaintext.js @@ -0,0 +1,82 @@ +export class pagesToPlaintext1659335999000 { + name = 'pagesToPlaintext1659335999000' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "page" ADD "text" text`); + + async function noteUrl(noteId) { + const note = await queryRunner.query(`SELECT "uri", "userHost" FROM "note" WHERE "id" = $1`, [noteId]); + if (note.uri) return note.uri; + // don't really have access to the configuration here so just guess + else return `https://${note.userHost}/notes/${noteId}`; + } + + async function fileUrl(fileId) { + const file = await queryRunner.query(`SELECT "url" from "drive_file" WHERE "id" = $1`, [fileId]); + return file.url; + } + + async function convertBlock(block) { + switch (block.type) { + case 'note': + if (block.note) return await noteUrl(block.note); + else break; + case 'section': + return (await Promise.all(block.children.map(convertBlock))).join('\n'); + case 'text': + return block.text; + case 'textarea': + return '```\n' + block.text + '```'; + case 'image': + if (block.fileId) return '![image](' + await fileUrl(block.fileId) + ')'; + else break; + case 'if': // no idea how to convert these + case 'post': // new note form, why? + case 'canvas': // there is some aiscript api for these but dont think anyone ever used it + // interactive elements can also not be converted + case 'button': + case 'numberInput': + case 'textInput': + case 'switch': + case 'radioButton': + case 'counter': + break; + } + + return `(There was a/an ${block.type} here in a previous version but it is no longer supported.)`; + } + + await queryRunner.query(`SELECT id, "content" FROM "page"`) + .then(pages => Promise.all(pages.map(page => { + return Promise.all(page.content.map(convertBlock)) + .then(texts => { + queryRunner.query(`UPDATE "page" SET "text" = $1 WHERE "id" = $2`, [texts.join('\n'), page.id]); + }); + }))); + + await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "content"`); + await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "variables"`); + await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "script"`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "page" ADD "content" jsonb default '[]'::jsonb`); + await queryRunner.query(`ALTER TABLE "page" ADD "variables" jsonb default '[]'::jsonb`); + await queryRunner.query(`ALTER TABLE "page" ADD "script" character varying(16384) default ''`); + + // The conversion from the previous page content to text is lossy, + // so we can just convert it back to a big text block. + await queryRunner.query(`SELECT "id", "text" FROM "page"`) + .then(pages => Promise.all(pages.map(page => { + const content = [{ + // just a random UUID to keep the data structure + id: '0730b23f-ab5b-4d56-8bd1-f4ead3f72af7', + type: 'text', + text: page.text, + }]; + return queryRunner.query(`UPDATE "page" SET "content" = $1 WHERE "id" = $2`, [JSON.stringify(content), page.id]); + }))); + + await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "text"`); + } +} diff --git a/packages/backend/migration/1660251834642-remove-promo-entities.js b/packages/backend/migration/1660251834642-remove-promo-entities.js new file mode 100644 index 000000000..5dd735aec --- /dev/null +++ b/packages/backend/migration/1660251834642-remove-promo-entities.js @@ -0,0 +1,25 @@ +export class removePromoEntities1660251834642 { + name = 'removePromoEntities1660251834642'; + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "promo_read" DROP CONSTRAINT "FK_a46a1a603ecee695d7db26da5f4"`, undefined); + await queryRunner.query(`ALTER TABLE "promo_read" DROP CONSTRAINT "FK_9657d55550c3d37bfafaf7d4b05"`, undefined); + await queryRunner.query(`ALTER TABLE "promo_note" DROP CONSTRAINT "FK_e263909ca4fe5d57f8d4230dd5c"`, undefined); + await queryRunner.query(`DROP INDEX "IDX_2882b8a1a07c7d281a98b6db16"`, undefined); + await queryRunner.query(`DROP INDEX "IDX_9657d55550c3d37bfafaf7d4b0"`, undefined); + await queryRunner.query(`DROP TABLE "promo_read"`, undefined); + await queryRunner.query(`DROP INDEX "IDX_83f0862e9bae44af52ced7099e"`, undefined); + await queryRunner.query(`DROP TABLE "promo_note"`, undefined); + } + + async down(queryRunner) { + await queryRunner.query(`CREATE TABLE "promo_note" ("noteId" character varying(32) NOT NULL, "expiresAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, CONSTRAINT "REL_e263909ca4fe5d57f8d4230dd5" UNIQUE ("noteId"), CONSTRAINT "PK_e263909ca4fe5d57f8d4230dd5c" PRIMARY KEY ("noteId"))`, undefined); + await queryRunner.query(`CREATE INDEX "IDX_83f0862e9bae44af52ced7099e" ON "promo_note" ("userId") `, undefined); + await queryRunner.query(`CREATE TABLE "promo_read" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, CONSTRAINT "PK_61917c1541002422b703318b7c9" PRIMARY KEY ("id"))`, undefined); + await queryRunner.query(`CREATE INDEX "IDX_9657d55550c3d37bfafaf7d4b0" ON "promo_read" ("userId") `, undefined); + await queryRunner.query(`CREATE UNIQUE INDEX "IDX_2882b8a1a07c7d281a98b6db16" ON "promo_read" ("userId", "noteId") `, undefined); + await queryRunner.query(`ALTER TABLE "promo_note" ADD CONSTRAINT "FK_e263909ca4fe5d57f8d4230dd5c" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, undefined); + await queryRunner.query(`ALTER TABLE "promo_read" ADD CONSTRAINT "FK_9657d55550c3d37bfafaf7d4b05" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, undefined); + await queryRunner.query(`ALTER TABLE "promo_read" ADD CONSTRAINT "FK_a46a1a603ecee695d7db26da5f4" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, undefined); + } +} diff --git a/packages/backend/package.json b/packages/backend/package.json index 09fb52b3d..db30548af 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -69,7 +69,7 @@ "mime-types": "2.1.35", "misskey-js": "0.0.14", "mocha": "10.0.0", - "multer": "1.4.4", + "multer": "1.4.5-lts.1", "nested-property": "4.0.0", "node-fetch": "3.2.6", "nodemailer": "6.7.6", diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index 78510c837..2f182e1ae 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -63,8 +63,6 @@ export type Source = { mediaProxy?: string; proxyRemoteFiles?: boolean; - - signToActivityPubGet?: boolean; }; /** diff --git a/packages/backend/src/db/postgre.ts b/packages/backend/src/db/postgre.ts index d36032dad..363671268 100644 --- a/packages/backend/src/db/postgre.ts +++ b/packages/backend/src/db/postgre.ts @@ -57,8 +57,6 @@ import { Clip } from '@/models/entities/clip.js'; import { ClipNote } from '@/models/entities/clip-note.js'; import { Antenna } from '@/models/entities/antenna.js'; import { AntennaNote } from '@/models/entities/antenna-note.js'; -import { PromoNote } from '@/models/entities/promo-note.js'; -import { PromoRead } from '@/models/entities/promo-read.js'; import { Relay } from '@/models/entities/relay.js'; import { MutedNote } from '@/models/entities/muted-note.js'; import { Channel } from '@/models/entities/channel.js'; @@ -159,8 +157,6 @@ export const entities = [ ClipNote, Antenna, AntennaNote, - PromoNote, - PromoRead, Relay, MutedNote, Channel, diff --git a/packages/backend/src/mfm/from-html.ts b/packages/backend/src/mfm/from-html.ts index 7751bac56..9921c4088 100644 --- a/packages/backend/src/mfm/from-html.ts +++ b/packages/backend/src/mfm/from-html.ts @@ -8,10 +8,10 @@ const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/; const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/; export function fromHtml(html: string, hashtagNames?: string[]): string { - // some AP servers like Pixelfed use br tags as well as newlines - html = html.replace(/\r?\n/gi, '\n'); - - const dom = parse5.parseFragment(html); + const dom = parse5.parseFragment( + // some AP servers like Pixelfed use br tags as well as newlines + html.replace(/\r?\n/gi, '\n'), + ); let text = ''; diff --git a/packages/backend/src/mfm/to-html.ts b/packages/backend/src/mfm/to-html.ts index 581cfabf1..dd3992bfd 100644 --- a/packages/backend/src/mfm/to-html.ts +++ b/packages/backend/src/mfm/to-html.ts @@ -106,13 +106,18 @@ export function toHtml(nodes: mfm.MfmNode[] | null, mentionedRemoteUsers: IMenti }, mention(node) { + // Mastodon microformat: span.h-card > a.u-url.mention const a = doc.createElement('a'); const { username, host, acct } = node.props; const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username === username && remoteUser.host === host); - a.href = remoteUserInfo ? (remoteUserInfo.url ? remoteUserInfo.url : remoteUserInfo.uri) : `${config.url}/${acct}`; + a.href = remoteUserInfo?.url ?? remoteUserInfo?.uri ?? `${config.url}/${acct}`; a.className = 'u-url mention'; a.textContent = acct; - return a; + + const card = doc.createElement('span'); + card.className = 'h-card'; + card.appendChild(a); + return card; }, quote(node) { diff --git a/packages/backend/src/misc/acct.ts b/packages/backend/src/misc/acct.ts index c32cee86c..60160cc4f 100644 --- a/packages/backend/src/misc/acct.ts +++ b/packages/backend/src/misc/acct.ts @@ -4,8 +4,11 @@ export type Acct = { }; export function parse(acct: string): Acct { - if (acct.startsWith('@')) acct = acct.substr(1); - const split = acct.split('@', 2); + const split = acct.split('@'); + if (split[0].length === 0) { + // there was an initial at + split.shift(); + } return { username: split[0], host: split[1] || null }; } diff --git a/packages/backend/src/misc/app-lock.ts b/packages/backend/src/misc/app-lock.ts index 295c3728e..dedbd6dbf 100644 --- a/packages/backend/src/misc/app-lock.ts +++ b/packages/backend/src/misc/app-lock.ts @@ -9,8 +9,8 @@ const retryDelay = 100; const lock: (key: string, timeout?: number) => Promise<() => void> = redisClient - ? promisify(redisLock(redisClient, retryDelay)) - : async () => () => { }; + ? promisify(redisLock(redisClient, retryDelay)) + : async () => () => { }; /** * Get AP Object lock diff --git a/packages/backend/src/misc/captcha.ts b/packages/backend/src/misc/captcha.ts index 4238116fe..1431a4d80 100644 --- a/packages/backend/src/misc/captcha.ts +++ b/packages/backend/src/misc/captcha.ts @@ -9,7 +9,7 @@ export async function verifyRecaptcha(secret: string, response: string) { }); if (result.success !== true) { - const errorCodes = result['error-codes'] ? result['error-codes']?.join(', ') : ''; + const errorCodes = result['error-codes'] ? result['error-codes'].join(', ') : ''; throw new Error(`recaptcha-failed: ${errorCodes}`); } } @@ -20,7 +20,7 @@ export async function verifyHcaptcha(secret: string, response: string) { }); if (result.success !== true) { - const errorCodes = result['error-codes'] ? result['error-codes']?.join(', ') : ''; + const errorCodes = result['error-codes'] ? result['error-codes'].join(', ') : ''; throw new Error(`hcaptcha-failed: ${errorCodes}`); } } diff --git a/packages/backend/src/misc/check-hit-antenna.ts b/packages/backend/src/misc/check-hit-antenna.ts index 6f39aff75..aa9247b41 100644 --- a/packages/backend/src/misc/check-hit-antenna.ts +++ b/packages/backend/src/misc/check-hit-antenna.ts @@ -65,7 +65,7 @@ export async function checkHitAntenna(antenna: Antenna, note: (Note | Packed<'No and.every(keyword => antenna.caseSensitive ? note.text!.includes(keyword) - : note.text!.toLowerCase().includes(keyword.toLowerCase()) + : note.text!.toLowerCase().includes(keyword.toLowerCase()), )); if (!matched) return false; @@ -83,7 +83,7 @@ export async function checkHitAntenna(antenna: Antenna, note: (Note | Packed<'No and.every(keyword => antenna.caseSensitive ? note.text!.includes(keyword) - : note.text!.toLowerCase().includes(keyword.toLowerCase()) + : note.text!.toLowerCase().includes(keyword.toLowerCase()), )); if (matched) return false; diff --git a/packages/backend/src/misc/convert-host.ts b/packages/backend/src/misc/convert-host.ts index ac572b22c..aa771af14 100644 --- a/packages/backend/src/misc/convert-host.ts +++ b/packages/backend/src/misc/convert-host.ts @@ -1,12 +1,12 @@ -import { URL } from 'node:url'; import { toASCII } from 'punycode'; +import { URL } from 'node:url'; import config from '@/config/index.js'; -export function getFullApAccount(username: string, host: string | null) { +export function getFullApAccount(username: string, host: string | null): string { return host ? `${username}@${toPuny(host)}` : `${username}@${toPuny(config.host)}`; } -export function isSelfHost(host: string) { +export function isSelfHost(host: string | null): boolean { if (host == null) return true; return toPuny(config.host) === toPuny(host); } diff --git a/packages/backend/src/misc/create-temp.ts b/packages/backend/src/misc/create-temp.ts index fa88769de..429977669 100644 --- a/packages/backend/src/misc/create-temp.ts +++ b/packages/backend/src/misc/create-temp.ts @@ -18,7 +18,7 @@ export function createTempDir(): Promise<[string, () => void]> { (e, path, cleanup) => { if (e) return rej(e); res([path, cleanup]); - } + }, ); }); } diff --git a/packages/backend/src/misc/gen-id.ts b/packages/backend/src/misc/gen-id.ts index 3caa81906..641182c14 100644 --- a/packages/backend/src/misc/gen-id.ts +++ b/packages/backend/src/misc/gen-id.ts @@ -7,10 +7,8 @@ import * as crypto from 'node:crypto'; const TIME2000 = 946684800000; let counter = crypto.randomBytes(2).readUInt16LE(0); -export function genId(date?: Date): string { - if (!date || (date > new Date())) date = new Date(); - - let t = date.getTime(); +export function genId(date?: Date = new Date()): string { + let t = Math.min(date, new Date()); t -= TIME2000; if (t < 0) t = 0; if (isNaN(t)) throw new Error('Failed to create AID: Invalid Date'); diff --git a/packages/backend/src/misc/is-instance-muted.ts b/packages/backend/src/misc/is-instance-muted.ts index a74ba524e..d744ba656 100644 --- a/packages/backend/src/misc/is-instance-muted.ts +++ b/packages/backend/src/misc/is-instance-muted.ts @@ -1,15 +1,15 @@ import { Packed } from './schema.js'; export function isInstanceMuted(note: Packed<'Note'>, mutedInstances: Set): boolean { - if (mutedInstances.has(note?.user?.host ?? '')) return true; - if (mutedInstances.has(note?.reply?.user?.host ?? '')) return true; - if (mutedInstances.has(note?.renote?.user?.host ?? '')) return true; + if (mutedInstances.has(note.user.host ?? '')) return true; + if (mutedInstances.has(note.reply?.user.host ?? '')) return true; + if (mutedInstances.has(note.renote?.user.host ?? '')) return true; return false; } export function isUserFromMutedInstance(notif: Packed<'Notification'>, mutedInstances: Set): boolean { - if (mutedInstances.has(notif?.user?.host ?? '')) return true; + if (mutedInstances.has(notif.user?.host ?? '')) return true; return false; } diff --git a/packages/backend/src/misc/is-user-related.ts b/packages/backend/src/misc/is-user-related.ts index dc7bfbf0a..79eedf914 100644 --- a/packages/backend/src/misc/is-user-related.ts +++ b/packages/backend/src/misc/is-user-related.ts @@ -1,7 +1,7 @@ export function isUserRelated(note: any, ids: Set): boolean { if (ids.has(note.userId)) return true; // note author is muted if (note.mentions && note.mentions.some((user: string) => ids.has(user))) return true; // any of mentioned users are muted - if (note.reply && isUserRelated(note.reply, ids)) return true; // also check reply target + if (note.reply && isUserRelated(note.reply, ids)) return true; // also check reply target if (note.renote && isUserRelated(note.renote, ids)) return true; // also check renote target return false; } diff --git a/packages/backend/src/misc/nyaize.ts b/packages/backend/src/misc/nyaize.ts index 500d1db2c..b6b9a9b76 100644 --- a/packages/backend/src/misc/nyaize.ts +++ b/packages/backend/src/misc/nyaize.ts @@ -8,7 +8,7 @@ export function nyaize(text: string): string { .replace(/(?<=every)one/gi, x => x === 'ONE' ? 'NYAN' : 'nyan') // ko-KR .replace(/[나-낳]/g, match => String.fromCharCode( - match.charCodeAt(0)! + '냐'.charCodeAt(0) - '나'.charCodeAt(0) + match.charCodeAt(0)! + '냐'.charCodeAt(0) - '나'.charCodeAt(0), )) .replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, '다냥') .replace(/(야(?=\?))|(야$)|(야(?= ))/gm, '냥'); diff --git a/packages/backend/src/misc/reaction-lib.ts b/packages/backend/src/misc/reaction-lib.ts index 5f70be1fd..949ca696a 100644 --- a/packages/backend/src/misc/reaction-lib.ts +++ b/packages/backend/src/misc/reaction-lib.ts @@ -54,10 +54,10 @@ export function convertLegacyReactions(reactions: Record) { return _reactions2; } -export async function toDbReaction(reaction?: string | null, reacterHost?: string | null): Promise { +export async function toDbReaction(reaction?: string | null, idnReacterHost?: string | null): Promise { if (reaction == null) return await getFallbackReaction(); - reacterHost = toPunyNullable(reacterHost); + const reacterHost = toPunyNullable(idnReacterHost); // 文字列タイプのリアクションを絵文字に変換 if (Object.keys(legacies).includes(reaction)) return legacies[reaction]; @@ -124,8 +124,8 @@ export function decodeReaction(str: string): DecodedReaction { }; } -export function convertLegacyReaction(reaction: string): string { - reaction = decodeReaction(reaction).reaction; +export function convertLegacyReaction(_reaction: string): string { + const reaction = decodeReaction(_reaction).reaction; if (Object.keys(legacies).includes(reaction)) return legacies[reaction]; return reaction; } diff --git a/packages/backend/src/models/entities/abuse-user-report.ts b/packages/backend/src/models/entities/abuse-user-report.ts index 305c465f0..9e5c4f793 100644 --- a/packages/backend/src/models/entities/abuse-user-report.ts +++ b/packages/backend/src/models/entities/abuse-user-report.ts @@ -52,7 +52,7 @@ export class AbuseUserReport { public resolved: boolean; @Column('boolean', { - default: false + default: false, }) public forwarded: boolean; diff --git a/packages/backend/src/models/entities/page.ts b/packages/backend/src/models/entities/page.ts index 5b0ac90b2..67da0c13a 100644 --- a/packages/backend/src/models/entities/page.ts +++ b/packages/backend/src/models/entities/page.ts @@ -75,21 +75,10 @@ export class Page { @JoinColumn() public eyeCatchingImage: DriveFile | null; - @Column('jsonb', { - default: [], - }) - public content: Record[]; - - @Column('jsonb', { - default: [], - }) - public variables: Record[]; - - @Column('varchar', { - length: 16384, + @Column('text', { default: '', }) - public script: string; + public text: string; /** * public ... 公開 diff --git a/packages/backend/src/models/entities/promo-note.ts b/packages/backend/src/models/entities/promo-note.ts deleted file mode 100644 index 13b0b9742..000000000 --- a/packages/backend/src/models/entities/promo-note.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { PrimaryColumn, Entity, Index, JoinColumn, Column, OneToOne } from 'typeorm'; -import { id } from '../id.js'; -import { Note } from './note.js'; -import { User } from './user.js'; - -@Entity() -export class PromoNote { - @PrimaryColumn(id()) - public noteId: Note['id']; - - @OneToOne(type => Note, { - onDelete: 'CASCADE', - }) - @JoinColumn() - public note: Note | null; - - @Column('timestamp with time zone') - public expiresAt: Date; - - //#region Denormalized fields - @Index() - @Column({ - ...id(), - comment: '[Denormalized]', - }) - public userId: User['id']; - //#endregion -} diff --git a/packages/backend/src/models/entities/promo-read.ts b/packages/backend/src/models/entities/promo-read.ts deleted file mode 100644 index ca5d08054..000000000 --- a/packages/backend/src/models/entities/promo-read.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { id } from '../id.js'; -import { Note } from './note.js'; -import { User } from './user.js'; - -@Entity() -@Index(['userId', 'noteId'], { unique: true }) -export class PromoRead { - @PrimaryColumn(id()) - public id: string; - - @Column('timestamp with time zone', { - comment: 'The created date of the PromoRead.', - }) - public createdAt: Date; - - @Index() - @Column(id()) - public userId: User['id']; - - @ManyToOne(type => User, { - onDelete: 'CASCADE', - }) - @JoinColumn() - public user: User | null; - - @Column(id()) - public noteId: Note['id']; - - @ManyToOne(type => Note, { - onDelete: 'CASCADE', - }) - @JoinColumn() - public note: Note | null; -} diff --git a/packages/backend/src/models/index.ts b/packages/backend/src/models/index.ts index 1005f8c70..dce7af4d9 100644 --- a/packages/backend/src/models/index.ts +++ b/packages/backend/src/models/index.ts @@ -1,4 +1,3 @@ -import { } from 'typeorm'; import { db } from '@/db/postgre.js'; import { Announcement } from './entities/announcement.js'; @@ -50,8 +49,6 @@ import { ClipRepository } from './repositories/clip.js'; import { ClipNote } from './entities/clip-note.js'; import { AntennaRepository } from './repositories/antenna.js'; import { AntennaNote } from './entities/antenna-note.js'; -import { PromoNote } from './entities/promo-note.js'; -import { PromoRead } from './entities/promo-read.js'; import { EmojiRepository } from './repositories/emoji.js'; import { RelayRepository } from './repositories/relay.js'; import { ChannelRepository } from './repositories/channel.js'; @@ -116,8 +113,6 @@ export const Clips = (ClipRepository); export const ClipNotes = db.getRepository(ClipNote); export const Antennas = (AntennaRepository); export const AntennaNotes = db.getRepository(AntennaNote); -export const PromoNotes = db.getRepository(PromoNote); -export const PromoReads = db.getRepository(PromoRead); export const Relays = (RelayRepository); export const MutedNotes = db.getRepository(MutedNote); export const Channels = (ChannelRepository); diff --git a/packages/backend/src/models/repositories/app.ts b/packages/backend/src/models/repositories/app.ts index 9f30442a1..182347e74 100644 --- a/packages/backend/src/models/repositories/app.ts +++ b/packages/backend/src/models/repositories/app.ts @@ -12,7 +12,7 @@ export const AppRepository = db.getRepository(App).extend({ detail?: boolean, includeSecret?: boolean, includeProfileImageIds?: boolean - } + }, ): Promise> { const opts = Object.assign({ detail: false, diff --git a/packages/backend/src/models/repositories/auth-session.ts b/packages/backend/src/models/repositories/auth-session.ts index 55ce446fb..59aec7d9e 100644 --- a/packages/backend/src/models/repositories/auth-session.ts +++ b/packages/backend/src/models/repositories/auth-session.ts @@ -7,7 +7,7 @@ import { Apps } from '../index.js'; export const AuthSessionRepository = db.getRepository(AuthSession).extend({ async pack( src: AuthSession['id'] | AuthSession, - me?: { id: User['id'] } | null | undefined + me?: { id: User['id'] } | null | undefined, ) { const session = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); diff --git a/packages/backend/src/models/repositories/blocking.ts b/packages/backend/src/models/repositories/blocking.ts index 1c0b4c9ff..637e04bdb 100644 --- a/packages/backend/src/models/repositories/blocking.ts +++ b/packages/backend/src/models/repositories/blocking.ts @@ -8,7 +8,7 @@ import { Users } from '../index.js'; export const BlockingRepository = db.getRepository(Blocking).extend({ async pack( src: Blocking['id'] | Blocking, - me?: { id: User['id'] } | null | undefined + me?: { id: User['id'] } | null | undefined, ): Promise> { const blocking = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); @@ -24,7 +24,7 @@ export const BlockingRepository = db.getRepository(Blocking).extend({ packMany( blockings: any[], - me: { id: User['id'] } + me: { id: User['id'] }, ) { return Promise.all(blockings.map(x => this.pack(x, me))); }, diff --git a/packages/backend/src/models/repositories/drive-folder.ts b/packages/backend/src/models/repositories/drive-folder.ts index 598b909b4..bb744a4b7 100644 --- a/packages/backend/src/models/repositories/drive-folder.ts +++ b/packages/backend/src/models/repositories/drive-folder.ts @@ -9,7 +9,7 @@ export const DriveFolderRepository = db.getRepository(DriveFolder).extend({ src: DriveFolder['id'] | DriveFolder, options?: { detail: boolean - } + }, ): Promise> { const opts = Object.assign({ detail: false, diff --git a/packages/backend/src/models/repositories/follow-request.ts b/packages/backend/src/models/repositories/follow-request.ts index 2bded951b..dc81c35ed 100644 --- a/packages/backend/src/models/repositories/follow-request.ts +++ b/packages/backend/src/models/repositories/follow-request.ts @@ -6,7 +6,7 @@ import { Users } from '../index.js'; export const FollowRequestRepository = db.getRepository(FollowRequest).extend({ async pack( src: FollowRequest['id'] | FollowRequest, - me?: { id: User['id'] } | null | undefined + me?: { id: User['id'] } | null | undefined, ) { const request = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); diff --git a/packages/backend/src/models/repositories/following.ts b/packages/backend/src/models/repositories/following.ts index d70b89819..5d4c57af1 100644 --- a/packages/backend/src/models/repositories/following.ts +++ b/packages/backend/src/models/repositories/following.ts @@ -52,12 +52,10 @@ export const FollowingRepository = db.getRepository(Following).extend({ opts?: { populateFollowee?: boolean; populateFollower?: boolean; - } + } = {}, ): Promise> { const following = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); - if (opts == null) opts = {}; - return await awaitAll({ id: following.id, createdAt: following.createdAt.toISOString(), @@ -78,7 +76,7 @@ export const FollowingRepository = db.getRepository(Following).extend({ opts?: { populateFollowee?: boolean; populateFollower?: boolean; - } + }, ) { return Promise.all(followings.map(x => this.pack(x, me, opts))); }, diff --git a/packages/backend/src/models/repositories/gallery-like.ts b/packages/backend/src/models/repositories/gallery-like.ts index 08ca4962b..33f5b3ebb 100644 --- a/packages/backend/src/models/repositories/gallery-like.ts +++ b/packages/backend/src/models/repositories/gallery-like.ts @@ -5,7 +5,7 @@ import { GalleryPosts } from '../index.js'; export const GalleryLikeRepository = db.getRepository(GalleryLike).extend({ async pack( src: GalleryLike['id'] | GalleryLike, - me?: any + me?: any, ) { const like = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); @@ -17,7 +17,7 @@ export const GalleryLikeRepository = db.getRepository(GalleryLike).extend({ packMany( likes: any[], - me: any + me: any, ) { return Promise.all(likes.map(x => this.pack(x, me))); }, diff --git a/packages/backend/src/models/repositories/messaging-message.ts b/packages/backend/src/models/repositories/messaging-message.ts index b3a7ea465..8c63bd819 100644 --- a/packages/backend/src/models/repositories/messaging-message.ts +++ b/packages/backend/src/models/repositories/messaging-message.ts @@ -11,7 +11,7 @@ export const MessagingMessageRepository = db.getRepository(MessagingMessage).ext options?: { populateRecipient?: boolean, populateGroup?: boolean, - } + }, ): Promise> { const opts = options || { populateRecipient: true, diff --git a/packages/backend/src/models/repositories/muting.ts b/packages/backend/src/models/repositories/muting.ts index c34e908cf..02ee075d8 100644 --- a/packages/backend/src/models/repositories/muting.ts +++ b/packages/backend/src/models/repositories/muting.ts @@ -8,7 +8,7 @@ import { Users } from '../index.js'; export const MutingRepository = db.getRepository(Muting).extend({ async pack( src: Muting['id'] | Muting, - me?: { id: User['id'] } | null | undefined + me?: { id: User['id'] } | null | undefined, ): Promise> { const muting = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); @@ -25,7 +25,7 @@ export const MutingRepository = db.getRepository(Muting).extend({ packMany( mutings: any[], - me: { id: User['id'] } + me: { id: User['id'] }, ) { return Promise.all(mutings.map(x => this.pack(x, me))); }, diff --git a/packages/backend/src/models/repositories/note-favorite.ts b/packages/backend/src/models/repositories/note-favorite.ts index 8d09d6bfb..47d549455 100644 --- a/packages/backend/src/models/repositories/note-favorite.ts +++ b/packages/backend/src/models/repositories/note-favorite.ts @@ -6,7 +6,7 @@ import { Notes } from '../index.js'; export const NoteFavoriteRepository = db.getRepository(NoteFavorite).extend({ async pack( src: NoteFavorite['id'] | NoteFavorite, - me?: { id: User['id'] } | null | undefined + me?: { id: User['id'] } | null | undefined, ) { const favorite = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); @@ -21,7 +21,7 @@ export const NoteFavoriteRepository = db.getRepository(NoteFavorite).extend({ packMany( favorites: any[], - me: { id: User['id'] } + me: { id: User['id'] }, ) { return Promise.allSettled(favorites.map(x => this.pack(x, me))) .then(promises => promises.flatMap(result => result.status === 'fulfilled' ? [result.value] : [])); diff --git a/packages/backend/src/models/repositories/note-reaction.ts b/packages/backend/src/models/repositories/note-reaction.ts index b76ec0401..77981d59d 100644 --- a/packages/backend/src/models/repositories/note-reaction.ts +++ b/packages/backend/src/models/repositories/note-reaction.ts @@ -42,5 +42,5 @@ export const NoteReactionRepository = db.getRepository(NoteReaction).extend({ // filter out rejected promises, only keep fulfilled values return reactions.flatMap(result => result.status === 'fulfilled' ? [result.value] : []); - } + }, }); diff --git a/packages/backend/src/models/repositories/note.ts b/packages/backend/src/models/repositories/note.ts index 38080c205..6e5da24fd 100644 --- a/packages/backend/src/models/repositories/note.ts +++ b/packages/backend/src/models/repositories/note.ts @@ -137,7 +137,7 @@ export const NoteRepository = db.getRepository(Note).extend({ _hint_?: { myReactions: Map; }; - } + }, ): Promise> { const opts = Object.assign({ detail: true, @@ -163,7 +163,7 @@ export const NoteRepository = db.getRepository(Note).extend({ : await Channels.findOneBy({ id: note.channelId }) : null; - const reactionEmojiNames = Object.keys(note.reactions).filter(x => x?.startsWith(':')).map(x => decodeReaction(x).reaction).map(x => x.replace(/:/g, '')); + const reactionEmojiNames = Object.keys(note.reactions).filter(x => x.startsWith(':')).map(x => decodeReaction(x).reaction).map(x => x.replace(/:/g, '')); const packed: Packed<'Note'> = await awaitAll({ id: note.id, @@ -233,7 +233,7 @@ export const NoteRepository = db.getRepository(Note).extend({ me?: { id: User['id'] } | null | undefined, options?: { detail?: boolean; - } + }, ) { if (notes.length === 0) return []; diff --git a/packages/backend/src/models/repositories/notification.ts b/packages/backend/src/models/repositories/notification.ts index 169743ce7..df783351e 100644 --- a/packages/backend/src/models/repositories/notification.ts +++ b/packages/backend/src/models/repositories/notification.ts @@ -16,7 +16,7 @@ export const NotificationRepository = db.getRepository(Notification).extend({ _hintForEachNotes_?: { myReactions: Map; }; - } + }, ): Promise> { const notification = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); const token = notification.appAccessTokenId ? await AccessTokens.findOneByOrFail({ id: notification.appAccessTokenId }) : null; @@ -85,7 +85,7 @@ export const NotificationRepository = db.getRepository(Notification).extend({ async packMany( notifications: Notification[], - meId: User['id'] + meId: User['id'], ) { if (notifications.length === 0) return []; diff --git a/packages/backend/src/models/repositories/page-like.ts b/packages/backend/src/models/repositories/page-like.ts index f4bcbc564..e5d01a05a 100644 --- a/packages/backend/src/models/repositories/page-like.ts +++ b/packages/backend/src/models/repositories/page-like.ts @@ -6,7 +6,7 @@ import { Pages } from '../index.js'; export const PageLikeRepository = db.getRepository(PageLike).extend({ async pack( src: PageLike['id'] | PageLike, - me?: { id: User['id'] } | null | undefined + me?: { id: User['id'] } | null | undefined, ) { const like = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); @@ -18,7 +18,7 @@ export const PageLikeRepository = db.getRepository(PageLike).extend({ packMany( likes: any[], - me: { id: User['id'] } + me: { id: User['id'] }, ) { return Promise.all(likes.map(x => this.pack(x, me))); }, diff --git a/packages/backend/src/models/repositories/page.ts b/packages/backend/src/models/repositories/page.ts index 092b26b39..53d70b70d 100644 --- a/packages/backend/src/models/repositories/page.ts +++ b/packages/backend/src/models/repositories/page.ts @@ -2,7 +2,6 @@ import { db } from '@/db/postgre.js'; import { Page } from '@/models/entities/page.js'; import { Packed } from '@/misc/schema.js'; import { awaitAll } from '@/prelude/await-all.js'; -import { DriveFile } from '@/models/entities/drive-file.js'; import { User } from '@/models/entities/user.js'; import { Users, DriveFiles, PageLikes } from '../index.js'; @@ -14,66 +13,21 @@ export const PageRepository = db.getRepository(Page).extend({ const meId = me ? me.id : null; const page = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src }); - const attachedFiles: Promise[] = []; - const collectFile = (xs: any[]) => { - for (const x of xs) { - if (x.type === 'image') { - attachedFiles.push(DriveFiles.findOneBy({ - id: x.fileId, - userId: page.userId, - })); - } - if (x.children) { - collectFile(x.children); - } - } - }; - collectFile(page.content); - - // 後方互換性のため - let migrated = false; - const migrate = (xs: any[]) => { - for (const x of xs) { - if (x.type === 'input') { - if (x.inputType === 'text') { - x.type = 'textInput'; - } - if (x.inputType === 'number') { - x.type = 'numberInput'; - if (x.default) x.default = parseInt(x.default, 10); - } - migrated = true; - } - if (x.children) { - migrate(x.children); - } - } - }; - migrate(page.content); - if (migrated) { - this.update(page.id, { - content: page.content, - }); - } - return await awaitAll({ id: page.id, createdAt: page.createdAt.toISOString(), updatedAt: page.updatedAt.toISOString(), userId: page.userId, user: Users.pack(page.user || page.userId, me), // { detail: true } すると無限ループするので注意 - content: page.content, - variables: page.variables, + text: page.text, title: page.title, name: page.name, summary: page.summary, hideTitleWhenPinned: page.hideTitleWhenPinned, alignCenter: page.alignCenter, font: page.font, - script: page.script, eyeCatchingImageId: page.eyeCatchingImageId, eyeCatchingImage: page.eyeCatchingImageId ? await DriveFiles.pack(page.eyeCatchingImageId) : null, - attachedFiles: DriveFiles.packMany((await Promise.all(attachedFiles)).filter((x): x is DriveFile => x != null)), likedCount: page.likedCount, isLiked: meId ? await PageLikes.findOneBy({ pageId: page.id, userId: meId }).then(x => x != null) : undefined, }); diff --git a/packages/backend/src/models/schema/page.ts b/packages/backend/src/models/schema/page.ts index 55ba3ce7f..658361bf5 100644 --- a/packages/backend/src/models/schema/page.ts +++ b/packages/backend/src/models/schema/page.ts @@ -29,12 +29,8 @@ export const packedPageSchema = { type: 'string', optional: false, nullable: true, }, - content: { - type: 'array', - optional: false, nullable: false, - }, - variables: { - type: 'array', + text: { + type: 'string', optional: false, nullable: false, }, userId: { diff --git a/packages/backend/src/models/schema/user.ts b/packages/backend/src/models/schema/user.ts index 253681695..f2cb995a8 100644 --- a/packages/backend/src/models/schema/user.ts +++ b/packages/backend/src/models/schema/user.ts @@ -161,19 +161,19 @@ export const packedUserDetailedNotMeOnlySchema = { type: 'array', nullable: false, optional: false, items: { - type: 'object', - nullable: false, optional: false, - properties: { - name: { - type: 'string', - nullable: false, optional: false, - }, - value: { - type: 'string', - nullable: false, optional: false, - }, + type: 'object', + nullable: false, optional: false, + properties: { + name: { + type: 'string', + nullable: false, optional: false, }, - maxLength: 4, + value: { + type: 'string', + nullable: false, optional: false, + }, + }, + maxLength: 4, }, }, followersCount: { diff --git a/packages/backend/src/prelude/await-all.ts b/packages/backend/src/prelude/await-all.ts index b955c3a5d..fd9832d6f 100644 --- a/packages/backend/src/prelude/await-all.ts +++ b/packages/backend/src/prelude/await-all.ts @@ -10,7 +10,7 @@ export async function awaitAll(obj: Promiseable): Promise { const resolvedValues = await Promise.all(values.map(value => (!value || !value.constructor || value.constructor.name !== 'Object') ? value - : awaitAll(value) + : awaitAll(value), )); for (let i = 0; i < keys.length; i++) { diff --git a/packages/backend/src/prelude/time.ts b/packages/backend/src/prelude/time.ts index 0da1f7913..06a06debd 100644 --- a/packages/backend/src/prelude/time.ts +++ b/packages/backend/src/prelude/time.ts @@ -6,12 +6,12 @@ const dateTimeIntervals = { export function dateUTC(time: number[]): Date { const d = time.length === 2 ? Date.UTC(time[0], time[1]) - : time.length === 3 ? Date.UTC(time[0], time[1], time[2]) - : time.length === 4 ? Date.UTC(time[0], time[1], time[2], time[3]) - : time.length === 5 ? Date.UTC(time[0], time[1], time[2], time[3], time[4]) - : time.length === 6 ? Date.UTC(time[0], time[1], time[2], time[3], time[4], time[5]) - : time.length === 7 ? Date.UTC(time[0], time[1], time[2], time[3], time[4], time[5], time[6]) - : null; + : time.length === 3 ? Date.UTC(time[0], time[1], time[2]) + : time.length === 4 ? Date.UTC(time[0], time[1], time[2], time[3]) + : time.length === 5 ? Date.UTC(time[0], time[1], time[2], time[3], time[4]) + : time.length === 6 ? Date.UTC(time[0], time[1], time[2], time[3], time[4], time[5]) + : time.length === 7 ? Date.UTC(time[0], time[1], time[2], time[3], time[4], time[5], time[6]) + : null; if (!d) throw new Error('wrong number of arguments'); diff --git a/packages/backend/src/queue/index.ts b/packages/backend/src/queue/index.ts index dc8c7abd3..1603865b9 100644 --- a/packages/backend/src/queue/index.ts +++ b/packages/backend/src/queue/index.ts @@ -21,9 +21,9 @@ import { ThinUser } from './types.js'; function renderError(e: Error): any { return { - stack: e?.stack, - message: e?.message, - name: e?.name, + stack: e.stack, + message: e.message, + name: e.name, }; } diff --git a/packages/backend/src/queue/processors/db/export-custom-emojis.ts b/packages/backend/src/queue/processors/db/export-custom-emojis.ts index 39c5141da..e2bb0c6f1 100644 --- a/packages/backend/src/queue/processors/db/export-custom-emojis.ts +++ b/packages/backend/src/queue/processors/db/export-custom-emojis.ts @@ -8,7 +8,6 @@ import config from '@/config/index.js'; import { createTemp, createTempDir } from '@/misc/create-temp.js'; import { downloadUrl } from '@/misc/download-url.js'; import { Users, Emojis } from '@/models/index.js'; -import { } from '@/queue/types.js'; import { addFile } from '@/services/drive/add-file.js'; import { queueLogger } from '../../logger.js'; diff --git a/packages/backend/src/remote/activitypub/audience.ts b/packages/backend/src/remote/activitypub/audience.ts index 92a028824..0e2111f0c 100644 --- a/packages/backend/src/remote/activitypub/audience.ts +++ b/packages/backend/src/remote/activitypub/audience.ts @@ -21,7 +21,7 @@ export async function parseAudience(actor: CacheableRemoteUser, to?: ApObject, c const limit = promiseLimit(2); const mentionedUsers = (await Promise.all( - others.map(id => limit(() => resolvePerson(id, resolver).catch(() => null))) + others.map(id => limit(() => resolvePerson(id, resolver).catch(() => null))), )).filter((x): x is CacheableUser => x != null); if (toGroups.public.length > 0) { diff --git a/packages/backend/src/remote/activitypub/models/image.ts b/packages/backend/src/remote/activitypub/models/image.ts index 40da9ac27..bb7ba96df 100644 --- a/packages/backend/src/remote/activitypub/models/image.ts +++ b/packages/backend/src/remote/activitypub/models/image.ts @@ -35,7 +35,7 @@ export async function createImage(actor: CacheableRemoteUser, value: any): Promi uri: image.url, sensitive: image.sensitive, isLink: !instance.cacheRemoteFiles, - comment: truncate(image.name, DB_MAX_IMAGE_COMMENT_LENGTH) + comment: truncate(image.name, DB_MAX_IMAGE_COMMENT_LENGTH), }); if (file.isLink) { diff --git a/packages/backend/src/remote/activitypub/models/note.ts b/packages/backend/src/remote/activitypub/models/note.ts index c532f81ae..fc915b2a3 100644 --- a/packages/backend/src/remote/activitypub/models/note.ts +++ b/packages/backend/src/remote/activitypub/models/note.ts @@ -65,9 +65,7 @@ export async function fetchNote(object: string | IObject): Promise /** * Noteを作成します。 */ -export async function createNote(value: string | IObject, resolver?: Resolver, silent = false): Promise { - if (resolver == null) resolver = new Resolver(); - +export async function createNote(value: string | IObject, resolver?: Resolver = new Resolver(), silent = false): Promise { const object: any = await resolver.resolve(value); const entryUri = getApId(value); @@ -198,7 +196,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s // テキストのパース let text: string | null = null; - if (note.source?.mediaType === 'text/x.misskeymarkdown' && typeof note.source?.content === 'string') { + if (note.source?.mediaType === 'text/x.misskeymarkdown' && typeof note.source.content === 'string') { text = note.source.content; } else if (typeof note._misskey_content !== 'undefined') { text = note._misskey_content; @@ -302,8 +300,8 @@ export async function resolveNote(value: string | IObject, resolver?: Resolver): } } -export async function extractEmojis(tags: IObject | IObject[], host: string): Promise { - host = toPuny(host); +export async function extractEmojis(tags: IObject | IObject[], idnHost: string): Promise { + const host = toPuny(idnHost); if (!tags) return []; diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts index 2bd1334c1..5db7fdfa2 100644 --- a/packages/backend/src/remote/activitypub/models/person.ts +++ b/packages/backend/src/remote/activitypub/models/person.ts @@ -134,15 +134,13 @@ export async function fetchPerson(uri: string, resolver?: Resolver): Promise { +export async function createPerson(uri: string, resolver?: Resolver = new Resolver()): Promise { if (typeof uri !== 'string') throw new Error('uri is not string'); if (uri.startsWith(config.url)) { throw new StatusError('cannot resolve local user', 400, 'cannot resolve local user'); } - if (resolver == null) resolver = new Resolver(); - const object = await resolver.resolve(uri) as any; const person = validateActor(object, uri); @@ -283,7 +281,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise { +export async function updatePerson(uri: string, resolver?: Resolver = new Resolver(), hint?: IObject): Promise { if (typeof uri !== 'string') throw new Error('uri is not string'); // URIがこのサーバーを指しているならスキップ @@ -299,8 +297,6 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint } //#endregion - if (resolver == null) resolver = new Resolver(); - const object = hint || await resolver.resolve(uri); const person = validateActor(object, uri); @@ -405,8 +401,7 @@ export async function resolvePerson(uri: string, resolver?: Resolver): Promise { if (typeof name !== 'string') { - name = 'unknown#0000'; + return { id, username: 'unknown', discriminator: '0000' }; + } else { + const [username, discriminator] = name.split('#'); + return { id, username, discriminator }; } - const [username, discriminator] = name.split('#'); - return { id, username, discriminator }; }; function addService(target: { [x: string]: any }, source: IApPropertyValue) { diff --git a/packages/backend/src/remote/activitypub/models/question.ts b/packages/backend/src/remote/activitypub/models/question.ts index 43393737c..0ea14c3a0 100644 --- a/packages/backend/src/remote/activitypub/models/question.ts +++ b/packages/backend/src/remote/activitypub/models/question.ts @@ -5,9 +5,7 @@ import Resolver from '../resolver.js'; import { IObject, IQuestion, isQuestion } from '../type.js'; import { apLogger } from '../logger.js'; -export async function extractPollFromQuestion(source: string | IObject, resolver?: Resolver): Promise { - if (resolver == null) resolver = new Resolver(); - +export async function extractPollFromQuestion(source: string | IObject, resolver?: Resolver = new Resolver()): Promise { const question = await resolver.resolve(source); if (!isQuestion(question)) { diff --git a/packages/backend/src/remote/activitypub/renderer/block.ts b/packages/backend/src/remote/activitypub/renderer/block.ts index 13815fb76..802d7280b 100644 --- a/packages/backend/src/remote/activitypub/renderer/block.ts +++ b/packages/backend/src/remote/activitypub/renderer/block.ts @@ -7,7 +7,7 @@ import { Blocking } from '@/models/entities/blocking.js'; * @param block The block to be rendered. The blockee relation must be loaded. */ export function renderBlock(block: Blocking) { - if (block.blockee?.url == null) { + if (block.blockee?.uri == null) { throw new Error('renderBlock: missing blockee uri'); } diff --git a/packages/backend/src/remote/activitypub/renderer/index.ts b/packages/backend/src/remote/activitypub/renderer/index.ts index d082d2a97..bf31c2227 100644 --- a/packages/backend/src/remote/activitypub/renderer/index.ts +++ b/packages/backend/src/remote/activitypub/renderer/index.ts @@ -53,7 +53,5 @@ export const attachLdSignature = async (activity: any, user: { id: User['id']; h const ldSignature = new LdSignature(); ldSignature.debug = false; - activity = await ldSignature.signRsaSignature2017(activity, keypair.privateKey, `${config.url}/users/${user.id}#main-key`); - - return activity; + return await ldSignature.signRsaSignature2017(activity, keypair.privateKey, `${config.url}/users/${user.id}#main-key`); }; diff --git a/packages/backend/src/remote/activitypub/renderer/person.ts b/packages/backend/src/remote/activitypub/renderer/person.ts index d9c009bcf..213741143 100644 --- a/packages/backend/src/remote/activitypub/renderer/person.ts +++ b/packages/backend/src/remote/activitypub/renderer/person.ts @@ -77,11 +77,11 @@ export async function renderPerson(user: ILocalUser) { attachment: attachment.length ? attachment : undefined, } as any; - if (profile?.birthday) { + if (profile.birthday) { person['vcard:bday'] = profile.birthday; } - if (profile?.location) { + if (profile.location) { person['vcard:Address'] = profile.location; } diff --git a/packages/backend/src/remote/activitypub/resolver.ts b/packages/backend/src/remote/activitypub/resolver.ts index 0fdc19547..3cea4c44e 100644 --- a/packages/backend/src/remote/activitypub/resolver.ts +++ b/packages/backend/src/remote/activitypub/resolver.ts @@ -72,13 +72,11 @@ export default class Resolver { throw new Error('Instance is blocked'); } - if (config.signToActivityPubGet && !this.user) { + if (!this.user) { this.user = await getInstanceActor(); } - const object = (this.user - ? await signedGet(value, this.user) - : await getJson(value, 'application/activity+json, application/ld+json')) as IObject; + const object = await signedGet(value, this.user); if (object == null || ( Array.isArray(object['@context']) ? @@ -123,7 +121,7 @@ export default class Resolver { if (parsed.rest == null || !/^\w+$/.test(parsed.rest)) throw new Error('resolveLocal: invalid follow URI'); return Promise.all( - [parsed.id, parsed.rest].map(id => Users.findOneByOrFail({ id })) + [parsed.id, parsed.rest].map(id => Users.findOneByOrFail({ id })), ) .then(([follower, followee]) => renderActivity(renderFollow(follower, followee, url))); default: diff --git a/packages/backend/src/remote/resolve-user.ts b/packages/backend/src/remote/resolve-user.ts index 6a8d4bee0..0d79c5d10 100644 --- a/packages/backend/src/remote/resolve-user.ts +++ b/packages/backend/src/remote/resolve-user.ts @@ -2,7 +2,7 @@ import { URL } from 'node:url'; import chalk from 'chalk'; import { IsNull } from 'typeorm'; import config from '@/config/index.js'; -import { toPuny } from '@/misc/convert-host.js'; +import { isSelfHost, toPuny } from '@/misc/convert-host.js'; import { User, IRemoteUser } from '@/models/entities/user.js'; import { Users } from '@/models/index.js'; import webFinger from './webfinger.js'; @@ -11,10 +11,10 @@ import { remoteLogger } from './logger.js'; const logger = remoteLogger.createSubLogger('resolve-user'); -export async function resolveUser(username: string, host: string | null): Promise { +export async function resolveUser(username: string, idnHost: string | null): Promise { const usernameLower = username.toLowerCase(); - if (host == null) { + if (idnHost == null) { logger.info(`return local user: ${usernameLower}`); return await Users.findOneBy({ usernameLower, host: IsNull() }).then(u => { if (u == null) { @@ -25,9 +25,7 @@ export async function resolveUser(username: string, host: string | null): Promis }); } - host = toPuny(host); - - if (config.host === host) { + if (isSelfHost(idnHost)) { logger.info(`return local user: ${usernameLower}`); return await Users.findOneBy({ usernameLower, host: IsNull() }).then(u => { if (u == null) { @@ -38,6 +36,8 @@ export async function resolveUser(username: string, host: string | null): Promis }); } + // `idnHost` can not be null here because that would have branched off with `isSelfHost`. + const host = toPuny(idnHost!); const user = await Users.findOneBy({ usernameLower, host }) as IRemoteUser | null; const acctLower = `${usernameLower}@${host}`; diff --git a/packages/backend/src/server/api/common/inject-promo.ts b/packages/backend/src/server/api/common/inject-promo.ts deleted file mode 100644 index b0da8118b..000000000 --- a/packages/backend/src/server/api/common/inject-promo.ts +++ /dev/null @@ -1,34 +0,0 @@ -import rndstr from 'rndstr'; -import { Note } from '@/models/entities/note.js'; -import { User } from '@/models/entities/user.js'; -import { PromoReads, PromoNotes, Notes, Users } from '@/models/index.js'; - -export async function injectPromo(timeline: Note[], user?: User | null) { - if (timeline.length < 5) return; - - // TODO: readやexpireフィルタはクエリ側でやる - - const reads = user ? await PromoReads.findBy({ - userId: user.id, - }) : []; - - let promos = await PromoNotes.find(); - - promos = promos.filter(n => n.expiresAt.getTime() > Date.now()); - promos = promos.filter(n => !reads.map(r => r.noteId).includes(n.noteId)); - - if (promos.length === 0) return; - - // Pick random promo - const promo = promos[Math.floor(Math.random() * promos.length)]; - - const note = await Notes.findOneByOrFail({ id: promo.noteId }); - - // Join - note.user = await Users.findOneByOrFail({ id: note.userId }); - - (note as any)._prId_ = rndstr('a-z0-9', 8); - - // Inject promo - timeline.splice(3, 0, note); -} diff --git a/packages/backend/src/server/api/common/read-messaging-message.ts b/packages/backend/src/server/api/common/read-messaging-message.ts index 4f660a4e2..e8e16f319 100644 --- a/packages/backend/src/server/api/common/read-messaging-message.ts +++ b/packages/backend/src/server/api/common/read-messaging-message.ts @@ -18,7 +18,7 @@ import orderedCollection from '@/remote/activitypub/renderer/ordered-collection. export async function readUserMessagingMessage( userId: User['id'], otherpartyId: User['id'], - messageIds: MessagingMessage['id'][] + messageIds: MessagingMessage['id'][], ) { if (messageIds.length === 0) return; @@ -58,7 +58,7 @@ export async function readUserMessagingMessage( recipientId: userId, isRead: false, }, - take: 1 + take: 1, }); if (!count) { @@ -73,7 +73,7 @@ export async function readUserMessagingMessage( export async function readGroupMessagingMessage( userId: User['id'], groupId: UserGroup['id'], - messageIds: MessagingMessage['id'][] + messageIds: MessagingMessage['id'][], ) { if (messageIds.length === 0) return; @@ -135,8 +135,9 @@ export async function readGroupMessagingMessage( } export async function deliverReadActivity(user: { id: User['id']; host: null; }, recipient: IRemoteUser, messages: MessagingMessage | MessagingMessage[]) { - messages = toArray(messages).filter(x => x.uri); - const contents = messages.map(x => renderReadActivity(user, x)); + const contents = toArray(messages) + .filter(x => x.uri) + .map(x => renderReadActivity(user, x)); if (contents.length > 1) { const collection = orderedCollection(null, contents.length, undefined, undefined, contents); diff --git a/packages/backend/src/server/api/common/read-notification.ts b/packages/backend/src/server/api/common/read-notification.ts index 041610d62..4a1837139 100644 --- a/packages/backend/src/server/api/common/read-notification.ts +++ b/packages/backend/src/server/api/common/read-notification.ts @@ -7,7 +7,7 @@ import { Notifications, Users } from '@/models/index.js'; export async function readNotification( userId: User['id'], - notificationIds: Notification['id'][] + notificationIds: Notification['id'][], ) { if (notificationIds.length === 0) return; @@ -27,7 +27,7 @@ export async function readNotification( export async function readNotificationByQuery( userId: User['id'], - query: Record + query: Record, ) { const notificationIds = await Notifications.findBy({ ...query, diff --git a/packages/backend/src/server/api/common/signup.ts b/packages/backend/src/server/api/common/signup.ts index 7178a7420..f246a454e 100644 --- a/packages/backend/src/server/api/common/signup.ts +++ b/packages/backend/src/server/api/common/signup.ts @@ -64,7 +64,7 @@ export async function signup(opts: { passphrase: undefined, }, } as any, (err, publicKey, privateKey) => - err ? rej(err) : res([publicKey, privateKey]) + err ? rej(err) : res([publicKey, privateKey]), )); let account!: User; diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 372fd503f..5a70d1a4f 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -33,7 +33,6 @@ import * as ep___admin_getTableStats from './endpoints/admin/get-table-stats.js' import * as ep___admin_invite from './endpoints/admin/invite.js'; import * as ep___admin_moderators_add from './endpoints/admin/moderators/add.js'; import * as ep___admin_moderators_remove from './endpoints/admin/moderators/remove.js'; -import * as ep___admin_promo_create from './endpoints/admin/promo/create.js'; import * as ep___admin_queue_clear from './endpoints/admin/queue/clear.js'; import * as ep___admin_queue_deliverDelayed from './endpoints/admin/queue/deliver-delayed.js'; import * as ep___admin_queue_inboxDelayed from './endpoints/admin/queue/inbox-delayed.js'; @@ -261,7 +260,6 @@ import * as ep___pages_unlike from './endpoints/pages/unlike.js'; import * as ep___pages_update from './endpoints/pages/update.js'; import * as ep___ping from './endpoints/ping.js'; import * as ep___pinnedUsers from './endpoints/pinned-users.js'; -import * as ep___promo_read from './endpoints/promo/read.js'; import * as ep___requestResetPassword from './endpoints/request-reset-password.js'; import * as ep___resetDb from './endpoints/reset-db.js'; import * as ep___resetPassword from './endpoints/reset-password.js'; @@ -342,7 +340,6 @@ const eps = [ ['admin/invite', ep___admin_invite], ['admin/moderators/add', ep___admin_moderators_add], ['admin/moderators/remove', ep___admin_moderators_remove], - ['admin/promo/create', ep___admin_promo_create], ['admin/queue/clear', ep___admin_queue_clear], ['admin/queue/deliver-delayed', ep___admin_queue_deliverDelayed], ['admin/queue/inbox-delayed', ep___admin_queue_inboxDelayed], @@ -570,7 +567,6 @@ const eps = [ ['pages/update', ep___pages_update], ['ping', ep___ping], ['pinned-users', ep___pinnedUsers], - ['promo/read', ep___promo_read], ['request-reset-password', ep___requestResetPassword], ['reset-db', ep___resetDb], ['reset-password', ep___resetPassword], diff --git a/packages/backend/src/server/api/endpoints/admin/get-table-stats.ts b/packages/backend/src/server/api/endpoints/admin/get-table-stats.ts index aca2540fd..8a0e1350a 100644 --- a/packages/backend/src/server/api/endpoints/admin/get-table-stats.ts +++ b/packages/backend/src/server/api/endpoints/admin/get-table-stats.ts @@ -28,7 +28,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async () => { const sizes = await - db.query(` + db.query(` SELECT relname AS "table", reltuples as "count", pg_total_relation_size(C.oid) AS "size" FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) WHERE nspname NOT IN ('pg_catalog', 'information_schema') diff --git a/packages/backend/src/server/api/endpoints/admin/promo/create.ts b/packages/backend/src/server/api/endpoints/admin/promo/create.ts deleted file mode 100644 index 006c85fa9..000000000 --- a/packages/backend/src/server/api/endpoints/admin/promo/create.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { PromoNotes } from '@/models/index.js'; -import define from '../../../define.js'; -import { ApiError } from '../../../error.js'; -import { getNote } from '../../../common/getters.js'; - -export const meta = { - tags: ['admin'], - - requireCredential: true, - requireModerator: true, - - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'ee449fbe-af2a-453b-9cae-cf2fe7c895fc', - }, - - alreadyPromoted: { - message: 'The note has already promoted.', - code: 'ALREADY_PROMOTED', - id: 'ae427aa2-7a41-484f-a18c-2c1104051604', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - noteId: { type: 'string', format: 'misskey:id' }, - expiresAt: { type: 'integer' }, - }, - required: ['noteId', 'expiresAt'], -} as const; - -// eslint-disable-next-line import/no-default-export -export default define(meta, paramDef, async (ps, user) => { - const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); - throw err; - }); - - const exist = await PromoNotes.findOneBy({ noteId: note.id }); - - if (exist != null) { - throw new ApiError(meta.errors.alreadyPromoted); - } - - await PromoNotes.insert({ - noteId: note.id, - expiresAt: new Date(ps.expiresAt), - userId: note.userId, - }); -}); diff --git a/packages/backend/src/server/api/endpoints/admin/show-user.ts b/packages/backend/src/server/api/endpoints/admin/show-user.ts index 78033aed5..bc9c193f8 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-user.ts @@ -25,7 +25,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { const [user, profile] = await Promise.all([ Users.findOneBy({ id: ps.userId }), - UserProfiles.findOneBy({ userId: ps.userId }) + UserProfiles.findOneBy({ userId: ps.userId }), ]); if (user == null || profile == null) { diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts index a46d6759a..f86b6c7d8 100644 --- a/packages/backend/src/server/api/endpoints/antennas/notes.ts +++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts @@ -58,7 +58,7 @@ export default define(meta, paramDef, async (ps, user) => { } const query = makePaginationQuery(Notes.createQueryBuilder('note'), - ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) + ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) .innerJoin(AntennaNotes.metadata.targetName, 'antennaNote', 'antennaNote.noteId = note.id') .innerJoinAndSelect('note.user', 'user') .leftJoinAndSelect('user.avatar', 'avatar') diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index 7c585c530..cbebf0044 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -47,8 +47,8 @@ export const meta = { type: 'object', optional: false, nullable: false, ref: 'UserDetailedNotMe', - } - } + }, + }, }, { type: 'object', @@ -62,9 +62,9 @@ export const meta = { type: 'object', optional: false, nullable: false, ref: 'Note', - } - } - } + }, + }, + }, ], }, } as const; diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts index 17c64bce3..6757dba1f 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts @@ -47,7 +47,7 @@ export default define(meta, paramDef, async (ps, user) => { DriveFiles.findOneBy({ id: fileId, userId: user.id, - }) + }), ))).filter((file): file is DriveFile => file != null); if (files.length === 0) { diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts index 48a51fc0d..94be32b02 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts @@ -46,7 +46,7 @@ export default define(meta, paramDef, async (ps, user) => { DriveFiles.findOneBy({ id: fileId, userId: user.id, - }) + }), ))).filter((file): file is DriveFile => file != null); if (files.length === 0) { diff --git a/packages/backend/src/server/api/endpoints/hashtags/trend.ts b/packages/backend/src/server/api/endpoints/hashtags/trend.ts index 069f1bc64..aee186401 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/trend.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/trend.ts @@ -127,7 +127,7 @@ export default define(meta, paramDef, async () => { .andWhere('note.createdAt > :gt', { gt: new Date(now.getTime() - (interval * (i + 1))) }) .cache(60000) // 1 min .getRawOne() - .then(x => parseInt(x.count, 10)) + .then(x => parseInt(x.count, 10)), ))); } @@ -140,7 +140,7 @@ export default define(meta, paramDef, async () => { .andWhere('note.createdAt > :gt', { gt: new Date(now.getTime() - rangeA) }) .cache(60000 * 60) // 60 min .getRawOne() - .then(x => parseInt(x.count, 10)) + .then(x => parseInt(x.count, 10)), )); const stats = hots.map((tag, i) => ({ diff --git a/packages/backend/src/server/api/endpoints/i/gallery/likes.ts b/packages/backend/src/server/api/endpoints/i/gallery/likes.ts index 563af4091..f5ceddd43 100644 --- a/packages/backend/src/server/api/endpoints/i/gallery/likes.ts +++ b/packages/backend/src/server/api/endpoints/i/gallery/likes.ts @@ -27,7 +27,7 @@ export const meta = { ref: 'GalleryPost', }, }, - } + }, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/i/page-likes.ts b/packages/backend/src/server/api/endpoints/i/page-likes.ts index 159b9c25b..987387237 100644 --- a/packages/backend/src/server/api/endpoints/i/page-likes.ts +++ b/packages/backend/src/server/api/endpoints/i/page-likes.ts @@ -26,7 +26,7 @@ export const meta = { ref: 'Page', }, }, - } + }, }, } as const; diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 36581c08f..fd2437b3a 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -57,7 +57,7 @@ export const meta = { message: 'Invalid Regular Expression.', code: 'INVALID_REGEXP', id: '0d786918-10df-41cd-8f33-8dec7d9a89a5', - } + }, }, res: { @@ -77,7 +77,8 @@ export const paramDef = { lang: { type: 'string', enum: [null, ...Object.keys(langmap)], nullable: true }, avatarId: { type: 'string', format: 'misskey:id', nullable: true }, bannerId: { type: 'string', format: 'misskey:id', nullable: true }, - fields: { type: 'array', + fields: { + type: 'array', minItems: 0, maxItems: 16, items: { diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 2b6de3756..0d11c5a92 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -1,4 +1,4 @@ -import { IsNull, MoreThan } from 'typeorm'; +import { IsNull } from 'typeorm'; import config from '@/config/index.js'; import { fetchMeta } from '@/misc/fetch-meta.js'; import { Emojis, Users } from '@/models/index.js'; diff --git a/packages/backend/src/server/api/endpoints/notes/children.ts b/packages/backend/src/server/api/endpoints/notes/children.ts index 7357a8212..afd7f41cf 100644 --- a/packages/backend/src/server/api/endpoints/notes/children.ts +++ b/packages/backend/src/server/api/endpoints/notes/children.ts @@ -1,4 +1,3 @@ -import { Brackets } from 'typeorm'; import { Notes } from '@/models/index.js'; import define from '../../define.js'; import { makePaginationQuery } from '../../common/make-pagination-query.js'; diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts index 2257cd736..8eafe556c 100644 --- a/packages/backend/src/server/api/endpoints/pages/create.ts +++ b/packages/backend/src/server/api/endpoints/pages/create.ts @@ -43,19 +43,13 @@ export const paramDef = { title: { type: 'string' }, name: { type: 'string', minLength: 1 }, summary: { type: 'string', nullable: true }, - content: { type: 'array', items: { - type: 'object', additionalProperties: true, - } }, - variables: { type: 'array', items: { - type: 'object', additionalProperties: true, - } }, - script: { type: 'string' }, + text: { type: 'string', minLength: 1 }, eyeCatchingImageId: { type: 'string', format: 'misskey:id', nullable: true }, font: { type: 'string', enum: ['serif', 'sans-serif'], default: 'sans-serif' }, alignCenter: { type: 'boolean', default: false }, hideTitleWhenPinned: { type: 'boolean', default: false }, }, - required: ['title', 'name', 'content', 'variables', 'script'], + required: ['title', 'name', 'text'], } as const; // eslint-disable-next-line import/no-default-export @@ -88,9 +82,7 @@ export default define(meta, paramDef, async (ps, user) => { title: ps.title, name: ps.name, summary: ps.summary, - content: ps.content, - variables: ps.variables, - script: ps.script, + text: ps.text, eyeCatchingImageId: eyeCatchingImage ? eyeCatchingImage.id : null, userId: user.id, visibility: 'public', diff --git a/packages/backend/src/server/api/endpoints/pages/update.ts b/packages/backend/src/server/api/endpoints/pages/update.ts index 9fa6a7fc5..319af3b88 100644 --- a/packages/backend/src/server/api/endpoints/pages/update.ts +++ b/packages/backend/src/server/api/endpoints/pages/update.ts @@ -49,19 +49,13 @@ export const paramDef = { title: { type: 'string' }, name: { type: 'string', minLength: 1 }, summary: { type: 'string', nullable: true }, - content: { type: 'array', items: { - type: 'object', additionalProperties: true, - } }, - variables: { type: 'array', items: { - type: 'object', additionalProperties: true, - } }, - script: { type: 'string' }, + text: { type: 'string', minLength: 1 }, eyeCatchingImageId: { type: 'string', format: 'misskey:id', nullable: true }, font: { type: 'string', enum: ['serif', 'sans-serif'] }, alignCenter: { type: 'boolean' }, hideTitleWhenPinned: { type: 'boolean' }, }, - required: ['pageId', 'title', 'name', 'content', 'variables', 'script'], + required: ['pageId', 'title', 'name', 'text'], } as const; // eslint-disable-next-line import/no-default-export @@ -101,9 +95,7 @@ export default define(meta, paramDef, async (ps, user) => { title: ps.title, name: ps.name === undefined ? page.name : ps.name, summary: ps.name === undefined ? page.summary : ps.summary, - content: ps.content, - variables: ps.variables, - script: ps.script, + text: ps.text, alignCenter: ps.alignCenter === undefined ? page.alignCenter : ps.alignCenter, hideTitleWhenPinned: ps.hideTitleWhenPinned === undefined ? page.hideTitleWhenPinned : ps.hideTitleWhenPinned, font: ps.font === undefined ? page.font : ps.font, diff --git a/packages/backend/src/server/api/endpoints/promo/read.ts b/packages/backend/src/server/api/endpoints/promo/read.ts deleted file mode 100644 index 7c37fcbf7..000000000 --- a/packages/backend/src/server/api/endpoints/promo/read.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { PromoReads } from '@/models/index.js'; -import { genId } from '@/misc/gen-id.js'; -import define from '../../define.js'; -import { ApiError } from '../../error.js'; -import { getNote } from '../../common/getters.js'; - -export const meta = { - tags: ['notes'], - - requireCredential: true, - - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'd785b897-fcd3-4fe9-8fc3-b85c26e6c932', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - noteId: { type: 'string', format: 'misskey:id' }, - }, - required: ['noteId'], -} as const; - -// eslint-disable-next-line import/no-default-export -export default define(meta, paramDef, async (ps, user) => { - const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); - throw err; - }); - - const exist = await PromoReads.findOneBy({ - noteId: note.id, - userId: user.id, - }); - - if (exist != null) { - return; - } - - await PromoReads.insert({ - id: genId(), - createdAt: new Date(), - noteId: note.id, - userId: user.id, - }); -}); diff --git a/packages/backend/src/server/api/endpoints/stats.ts b/packages/backend/src/server/api/endpoints/stats.ts index c32e5f45e..2d263cae8 100644 --- a/packages/backend/src/server/api/endpoints/stats.ts +++ b/packages/backend/src/server/api/endpoints/stats.ts @@ -1,6 +1,5 @@ import { IsNull } from 'typeorm'; import { Instances, NoteReactions, Notes, Users } from '@/models/index.js'; -import { } from '@/services/chart/index.js'; import define from '../define.js'; export const meta = { diff --git a/packages/backend/src/server/api/error.ts b/packages/backend/src/server/api/error.ts index 3f0861fdb..448c7a0c8 100644 --- a/packages/backend/src/server/api/error.ts +++ b/packages/backend/src/server/api/error.ts @@ -8,21 +8,22 @@ export class ApiError extends Error { public httpStatusCode?: number; public info?: any; - constructor(e?: E | null | undefined, info?: any | null | undefined) { - if (e == null) e = { + constructor( + e?: E | null | undefined = { message: 'Internal error occurred. Please contact us if the error persists.', code: 'INTERNAL_ERROR', id: '5d37dbcb-891e-41ca-a3d6-e690c97775ac', kind: 'server', httpStatusCode: 500, - }; - + }, + info?: any | null | undefined, + ) { super(e.message); this.message = e.message; this.code = e.code; this.id = e.id; - this.kind = e.kind || 'client'; - this.httpStatusCode = e.httpStatusCode; + this.kind = e.kind ?? 'client'; + this.httpStatusCode = e.httpStatusCode ?? 500; this.info = info; } } diff --git a/packages/backend/src/server/api/openapi/gen-spec.ts b/packages/backend/src/server/api/openapi/gen-spec.ts index e3cbf2d47..e929d643e 100644 --- a/packages/backend/src/server/api/openapi/gen-spec.ts +++ b/packages/backend/src/server/api/openapi/gen-spec.ts @@ -37,7 +37,7 @@ export function genOpenapiSpec() { Bearer: { type: 'http', scheme: 'bearer', - } + }, }, }, }; diff --git a/packages/backend/src/server/api/openapi/schemas.ts b/packages/backend/src/server/api/openapi/schemas.ts index 14bef9cab..4a0844b42 100644 --- a/packages/backend/src/server/api/openapi/schemas.ts +++ b/packages/backend/src/server/api/openapi/schemas.ts @@ -55,6 +55,6 @@ export const schemas = { }, ...Object.fromEntries( - Object.entries(refs).map(([key, schema]) => [key, convertSchemaToOpenApiSchema(schema)]) + Object.entries(refs).map(([key, schema]) => [key, convertSchemaToOpenApiSchema(schema)]), ), }; diff --git a/packages/backend/src/server/api/private/signin.ts b/packages/backend/src/server/api/private/signin.ts index 4544a75d3..667d721ad 100644 --- a/packages/backend/src/server/api/private/signin.ts +++ b/packages/backend/src/server/api/private/signin.ts @@ -172,7 +172,7 @@ export default async (ctx: Koa.Context) => { body.credentialId .replace(/-/g, '+') .replace(/_/g, '/'), - 'base64' + 'base64', ).toString('hex'), }); diff --git a/packages/backend/src/server/api/streaming.ts b/packages/backend/src/server/api/streaming.ts index 7cf365faf..dff353c2e 100644 --- a/packages/backend/src/server/api/streaming.ts +++ b/packages/backend/src/server/api/streaming.ts @@ -1,6 +1,6 @@ -import * as http from 'node:http'; import { EventEmitter } from 'events'; import { ParsedUrlQuery } from 'querystring'; +import * as http from 'node:http'; import * as websocket from 'websocket'; import { subscriber as redisClient } from '@/db/redis.js'; @@ -8,13 +8,13 @@ import { Users } from '@/models/index.js'; import MainStreamConnection from './stream/index.js'; import authenticate from './authenticate.js'; -export const initializeStreamingServer = (server: http.Server) => { +export const initializeStreamingServer = (server: http.Server): void => { // Init websocket server const ws = new websocket.server({ httpServer: server, }); - ws.on('request', async (request) => { + ws.on('request', async (request): Promise => { const q = request.resourceURL.query as ParsedUrlQuery; const [user, app] = await authenticate(request.httpRequest.headers.authorization, q.i) diff --git a/packages/backend/src/server/nodeinfo.ts b/packages/backend/src/server/nodeinfo.ts index a4a388ed6..0a67e872d 100644 --- a/packages/backend/src/server/nodeinfo.ts +++ b/packages/backend/src/server/nodeinfo.ts @@ -13,7 +13,7 @@ const nodeinfo2_0path = '/nodeinfo/2.0'; export const links = [{ rel: 'http://nodeinfo.diaspora.software/ns/schema/2.1', - href: config.url + nodeinfo2_1path + href: config.url + nodeinfo2_1path, }, { rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0', href: config.url + nodeinfo2_0path, diff --git a/packages/backend/src/server/web/manifest.ts b/packages/backend/src/server/web/manifest.ts index ee568b807..5b10145d4 100644 --- a/packages/backend/src/server/web/manifest.ts +++ b/packages/backend/src/server/web/manifest.ts @@ -2,7 +2,7 @@ import Koa from 'koa'; import { fetchMeta } from '@/misc/fetch-meta.js'; import manifest from './manifest.json' assert { type: 'json' }; -export const manifestHandler = async (ctx: Koa.Context) => { +export const manifestHandler = async (ctx: Koa.Context): Promise => { // TODO //const res = structuredClone(manifest); const res = JSON.parse(JSON.stringify(manifest)); diff --git a/packages/backend/src/server/web/url-preview.ts b/packages/backend/src/server/web/url-preview.ts index 10ec4874b..b28e813c6 100644 --- a/packages/backend/src/server/web/url-preview.ts +++ b/packages/backend/src/server/web/url-preview.ts @@ -8,7 +8,7 @@ import { getJson } from '@/misc/fetch.js'; const logger = new Logger('url-preview'); -export const urlPreviewHandler = async (ctx: Koa.Context) => { +export const urlPreviewHandler = async (ctx: Koa.Context): Promise => { const url = ctx.query.url; if (typeof url !== 'string') { ctx.status = 400; diff --git a/packages/backend/src/server/well-known.ts b/packages/backend/src/server/well-known.ts index 91131560e..f4db66354 100644 --- a/packages/backend/src/server/well-known.ts +++ b/packages/backend/src/server/well-known.ts @@ -13,11 +13,11 @@ const router = new Router(); const XRD = (...x: { element: string, value?: string, attributes?: Record }[]) => `${x.map(({ element, value, attributes }) => - `<${ - Object.entries(typeof attributes === 'object' && attributes || {}).reduce((a, [k, v]) => `${a} ${k}="${escapeAttribute(v)}"`, element) - }${ - typeof value === 'string' ? `>${escapeValue(value)}`).reduce((a, c) => a + c, '')}`; + `<${ + Object.entries(typeof attributes === 'object' && attributes || {}).reduce((a, [k, v]) => `${a} ${k}="${escapeAttribute(v)}"`, element) + }${ + typeof value === 'string' ? `>${escapeValue(value)}`).reduce((a, c) => a + c, '')}`; const allPath = '/.well-known/(.*)'; const webFingerPath = '/.well-known/webfinger'; diff --git a/packages/backend/src/services/create-notification.ts b/packages/backend/src/services/create-notification.ts index ece868a1c..6b04bb946 100644 --- a/packages/backend/src/services/create-notification.ts +++ b/packages/backend/src/services/create-notification.ts @@ -9,7 +9,7 @@ import { sendEmailNotification } from './send-email-notification.js'; export async function createNotification( notifieeId: User['id'], type: Notification['type'], - data: Partial + data: Partial, ) { if (data.notifierId && (notifieeId === data.notifierId)) { return null; diff --git a/packages/backend/src/services/create-system-user.ts b/packages/backend/src/services/create-system-user.ts index 8d74c90f2..4f3a3bc01 100644 --- a/packages/backend/src/services/create-system-user.ts +++ b/packages/backend/src/services/create-system-user.ts @@ -10,7 +10,7 @@ import { UsedUsername } from '@/models/entities/used-username.js'; import { db } from '@/db/postgre.js'; import generateNativeUserToken from '../server/api/common/generate-native-user-token.js'; -export async function createSystemUser(username: string) { +export async function createSystemUser(username: string): Promise { const password = uuid(); // Generate hash of password diff --git a/packages/backend/src/services/delete-account.ts b/packages/backend/src/services/delete-account.ts index 0fdceb671..c1ab9e2be 100644 --- a/packages/backend/src/services/delete-account.ts +++ b/packages/backend/src/services/delete-account.ts @@ -8,7 +8,7 @@ export async function deleteAccount(user: { host: string | null; }): Promise { // 物理削除する前にDelete activityを送信する - await doPostSuspend(user).catch(e => {}); + await doPostSuspend(user).catch(() => {}); createDeleteAccountJob(user, { soft: false, diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts index f7b784188..45d53492d 100644 --- a/packages/backend/src/services/drive/add-file.ts +++ b/packages/backend/src/services/drive/add-file.ts @@ -256,9 +256,12 @@ export async function generateAlts(path: string, type: string, generateWeb: bool /** * Upload to ObjectStorage */ -async function upload(key: string, stream: fs.ReadStream | Buffer, type: string, filename?: string) { - if (type === 'image/apng') type = 'image/png'; - if (!FILE_TYPE_BROWSERSAFE.includes(type)) type = 'application/octet-stream'; +async function upload(key: string, stream: fs.ReadStream | Buffer, _type: string, filename?: string) { + const type = (_type === 'image/apng') + ? 'image/png' + : (FILE_TYPE_BROWSERSAFE.includes(_type)) + ? _type + : 'application/octet-stream'; const meta = await fetchMeta(); @@ -276,7 +279,7 @@ async function upload(key: string, stream: fs.ReadStream | Buffer, type: string, const s3 = getS3(meta); const upload = s3.upload(params, { - partSize: s3.endpoint?.hostname === 'storage.googleapis.com' ? 500 * 1024 * 1024 : 8 * 1024 * 1024, + partSize: s3.endpoint.hostname === 'storage.googleapis.com' ? 500 * 1024 * 1024 : 8 * 1024 * 1024, }); const result = await upload.promise(); @@ -342,7 +345,7 @@ export async function addFile({ isLink = false, url = null, uri = null, - sensitive = null + sensitive = null, }: AddFileArgs): Promise { const info = await getFileInfo(path); logger.info(`${JSON.stringify(info)}`); @@ -428,10 +431,9 @@ export async function addFile({ file.blurhash = info.blurhash || null; file.isLink = isLink; file.isSensitive = user - ? Users.isLocalUser(user) && profile!.alwaysMarkNsfw ? true : - (sensitive !== null && sensitive !== undefined) - ? sensitive - : false + ? Users.isLocalUser(user) && profile!.alwaysMarkNsfw + ? true + : sensitive ?? false : false; if (url !== null) { diff --git a/packages/backend/src/services/drive/image-processor.ts b/packages/backend/src/services/drive/image-processor.ts index 2c564ea59..9b3c95af9 100644 --- a/packages/backend/src/services/drive/image-processor.ts +++ b/packages/backend/src/services/drive/image-processor.ts @@ -38,11 +38,11 @@ export async function convertSharpToJpeg(sharp: sharp.Sharp, width: number, heig * Convert to WebP * with resize, remove metadata, resolve orientation, stop animation */ -export async function convertToWebp(path: string, width: number, height: number, quality: number = 85): Promise { +export async function convertToWebp(path: string, width: number, height: number, quality = 85): Promise { return convertSharpToWebp(await sharp(path), width, height, quality); } -export async function convertSharpToWebp(sharp: sharp.Sharp, width: number, height: number, quality: number = 85): Promise { +export async function convertSharpToWebp(sharp: sharp.Sharp, width: number, height: number, quality = 85): Promise { const data = await sharp .resize(width, height, { fit: 'inside', diff --git a/packages/backend/src/services/drive/upload-from-url.ts b/packages/backend/src/services/drive/upload-from-url.ts index 67056cf84..65a062faf 100644 --- a/packages/backend/src/services/drive/upload-from-url.ts +++ b/packages/backend/src/services/drive/upload-from-url.ts @@ -36,12 +36,6 @@ export async function uploadFromUrl({ name = null; } - // If the comment is same as the name, skip comment - // (image.name is passed in when receiving attachment) - if (comment !== null && name === comment) { - comment = null; - } - // Create temp file const [path, cleanup] = await createTemp(); @@ -49,7 +43,20 @@ export async function uploadFromUrl({ // write content at URL to temp file await downloadUrl(url, path); - const driveFile = await addFile({ user, path, name, comment, folderId, force, isLink, url, uri, sensitive }); + const driveFile = await addFile({ + user, + path, + name, + // If the comment is same as the name, skip comment + // (image.name is passed in when receiving attachment) + comment: name === comment ? null : comment, + folderId, + force, + isLink, + url, + uri, + sensitive, + }); logger.succ(`Got: ${driveFile.id}`); return driveFile!; } catch (e) { diff --git a/packages/backend/src/services/fetch-instance-metadata.ts b/packages/backend/src/services/fetch-instance-metadata.ts index d318ed74c..f18310fd2 100644 --- a/packages/backend/src/services/fetch-instance-metadata.ts +++ b/packages/backend/src/services/fetch-instance-metadata.ts @@ -235,7 +235,7 @@ async function getSiteName(info: NodeInfo | null, doc: DOMWindow['document'] | n } if (manifest) { - return manifest?.name || manifest?.short_name; + return manifest.name || manifest.short_name; } return null; @@ -261,7 +261,7 @@ async function getDescription(info: NodeInfo | null, doc: DOMWindow['document'] } if (manifest) { - return manifest?.name || manifest?.short_name; + return manifest.name || manifest.short_name; } return null; diff --git a/packages/backend/src/services/logger.ts b/packages/backend/src/services/logger.ts index a2bc940d8..3b165f2f6 100644 --- a/packages/backend/src/services/logger.ts +++ b/packages/backend/src/services/logger.ts @@ -47,10 +47,9 @@ export default class Logger { return logger; } - private log(level: Level, message: string, data?: Record | null, important = false, subDomains: Domain[] = [], store = true): void { + private log(level: Level, message: string, data?: Record | null, important = false, subDomains: Domain[] = [], _store = true): void { if (envOption.quiet) return; - if (!this.store) store = false; - if (level === 'debug') store = false; + const store = _store && this.store && (level !== 'debug'); if (this.parentLogger) { this.parentLogger.log(level, message, data, important, [this.domain].concat(subDomains), store); @@ -95,9 +94,8 @@ export default class Logger { } } - public error(x: string | Error, data?: Record | null, important = false): void { // 実行を継続できない状況で使う + public error(x: string | Error, data?: Record = {}, important = false): void { // 実行を継続できない状況で使う if (x instanceof Error) { - data = data || {}; data.e = x; this.log('error', x.toString(), data, important); } else if (typeof x === 'object') { diff --git a/packages/backend/src/services/messages/create.ts b/packages/backend/src/services/messages/create.ts index 4c76bee5e..b5892a891 100644 --- a/packages/backend/src/services/messages/create.ts +++ b/packages/backend/src/services/messages/create.ts @@ -92,7 +92,7 @@ export async function createMessage(user: { id: User['id']; host: User['host']; text: message.text, userId: message.userId, visibility: 'specified', - mentions: [ recipientUser ].map(u => u.id), + mentions: [ recipientUser.id ], mentionedRemoteUsers: JSON.stringify([ recipientUser ].map(u => ({ uri: u.uri, username: u.username, diff --git a/packages/backend/src/services/messages/delete.ts b/packages/backend/src/services/messages/delete.ts index 1e7ce1981..25f49ae50 100644 --- a/packages/backend/src/services/messages/delete.ts +++ b/packages/backend/src/services/messages/delete.ts @@ -7,12 +7,12 @@ import renderDelete from '@/remote/activitypub/renderer/delete.js'; import renderTombstone from '@/remote/activitypub/renderer/tombstone.js'; import { deliver } from '@/queue/index.js'; -export async function deleteMessage(message: MessagingMessage) { +export async function deleteMessage(message: MessagingMessage): Promise { await MessagingMessages.delete(message.id); - postDeleteMessage(message); + await postDeleteMessage(message); } -async function postDeleteMessage(message: MessagingMessage) { +async function postDeleteMessage(message: MessagingMessage): Promise { if (message.recipientId) { const user = await Users.findOneByOrFail({ id: message.userId }); const recipient = await Users.findOneByOrFail({ id: message.recipientId }); diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 4312deb30..84bfa89eb 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -679,12 +679,12 @@ async function extractMentionedUsers(user: { host: User['host']; }, tokens: mfm. const mentions = extractMentions(tokens); let mentionedUsers = (await Promise.all(mentions.map(m => - resolveUser(m.username, m.host || user.host).catch(() => null) + resolveUser(m.username, m.host || user.host).catch(() => null), ))).filter(x => x != null) as User[]; // Drop duplicate users mentionedUsers = mentionedUsers.filter((u, i, self) => - i === self.findIndex(u2 => u.id === u2.id) + i === self.findIndex(u2 => u.id === u2.id), ); return mentionedUsers; diff --git a/packages/backend/src/services/note/delete.ts b/packages/backend/src/services/note/delete.ts index 620a05e1a..fc156b584 100644 --- a/packages/backend/src/services/note/delete.ts +++ b/packages/backend/src/services/note/delete.ts @@ -21,7 +21,7 @@ import { deliverToRelays } from '../relay.js'; * @param user 投稿者 * @param note 投稿 */ -export default async function(user: { id: User['id']; uri: User['uri']; host: User['host']; }, note: Note, quiet = false) { +export default async function(user: { id: User['id']; uri: User['uri']; host: User['host']; }, note: Note, quiet = false): Promise { const deletedAt = new Date(); // この投稿を除く指定したユーザーによる指定したノートのリノートが存在しないとき @@ -83,7 +83,7 @@ export default async function(user: { id: User['id']; uri: User['uri']; host: Us }); } -async function findCascadingNotes(note: Note) { +async function findCascadingNotes(note: Note): Promise { const cascadingNotes: Note[] = []; const recursive = async (noteId: string) => { @@ -105,7 +105,7 @@ async function findCascadingNotes(note: Note) { return cascadingNotes.filter(note => note.userHost === null); // filter out non-local users } -async function getMentionedRemoteUsers(note: Note) { +async function getMentionedRemoteUsers(note: Note): Promise { const where = [] as any[]; // mention / reply / dm diff --git a/packages/backend/src/services/note/polls/update.ts b/packages/backend/src/services/note/polls/update.ts index 68cbb9835..a0ce5f92f 100644 --- a/packages/backend/src/services/note/polls/update.ts +++ b/packages/backend/src/services/note/polls/update.ts @@ -6,7 +6,7 @@ import { Note } from '@/models/entities/note.js'; import { deliverToFollowers } from '@/remote/activitypub/deliver-manager.js'; import { deliverToRelays } from '../../relay.js'; -export async function deliverQuestionUpdate(noteId: Note['id']) { +export async function deliverQuestionUpdate(noteId: Note['id']): Promise { const note = await Notes.findOneBy({ id: noteId }); if (note == null) throw new Error('note not found'); diff --git a/packages/backend/src/services/note/reaction/create.ts b/packages/backend/src/services/note/reaction/create.ts index 1647ca4bc..0fa84d346 100644 --- a/packages/backend/src/services/note/reaction/create.ts +++ b/packages/backend/src/services/note/reaction/create.ts @@ -33,14 +33,14 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note, } // TODO: cache - reaction = await toDbReaction(reaction, user.host); + const dbReaction = await toDbReaction(reaction, user.host); const record: NoteReaction = { id: genId(), createdAt: new Date(), noteId: note.id, userId: user.id, - reaction, + reaction: dbReaction, }; // Create reaction @@ -53,7 +53,7 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note, userId: user.id, }); - if (exists.reaction !== reaction) { + if (exists.reaction !== dbReaction) { // 別のリアクションがすでにされていたら置き換える await deleteReaction(user, note); await NoteReactions.insert(record); @@ -67,7 +67,7 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note, } // Increment reactions count - const sql = `jsonb_set("reactions", '{${reaction}}', (COALESCE("reactions"->>'${reaction}', '0')::int + 1)::text::jsonb)`; + const sql = `jsonb_set("reactions", '{${dbReaction}}', (COALESCE("reactions"->>'${dbReaction}', '0')::int + 1)::text::jsonb)`; await Notes.createQueryBuilder().update() .set({ reactions: () => sql, @@ -79,7 +79,7 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note, perUserReactionsChart.update(user, note); // カスタム絵文字リアクションだったら絵文字情報も送る - const decodedReaction = decodeReaction(reaction); + const decodedReaction = decodeReaction(dbReaction); const emoji = await Emojis.findOne({ where: { @@ -103,7 +103,7 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note, createNotification(note.userId, 'reaction', { notifierId: user.id, noteId: note.id, - reaction, + reaction: dbReaction, }); } @@ -116,7 +116,7 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note, createNotification(watcher.userId, 'reaction', { notifierId: user.id, noteId: note.id, - reaction, + reaction: dbReaction, }); } }); diff --git a/packages/backend/src/services/note/read.ts b/packages/backend/src/services/note/read.ts index 15bf8d3de..0b678893c 100644 --- a/packages/backend/src/services/note/read.ts +++ b/packages/backend/src/services/note/read.ts @@ -18,7 +18,7 @@ export default async function( info?: { following: Set; followingChannels: Set; - } + }, ) { const following = info?.following ? info.following : new Set((await Followings.find({ where: { diff --git a/packages/backend/src/services/note/unread.ts b/packages/backend/src/services/note/unread.ts index d10b37a43..829a024ee 100644 --- a/packages/backend/src/services/note/unread.ts +++ b/packages/backend/src/services/note/unread.ts @@ -8,7 +8,7 @@ export async function insertNoteUnread(userId: User['id'], note: Note, params: { // NOTE: isSpecifiedがtrueならisMentionedは必ずfalse isSpecified: boolean; isMentioned: boolean; -}) { +}): Promise { //#region ミュートしているなら無視 // TODO: 現在の仕様ではChannelにミュートは適用されないのでよしなにケアする const mute = await Mutings.findBy({ diff --git a/packages/backend/src/services/push-notification.ts b/packages/backend/src/services/push-notification.ts index a763f5399..56a8c83bf 100644 --- a/packages/backend/src/services/push-notification.ts +++ b/packages/backend/src/services/push-notification.ts @@ -29,7 +29,7 @@ function truncateNotification(notification: Packed<'Notification'>): any { reply: undefined, renote: undefined, user: undefined as any, // 通知を受け取ったユーザーである場合が多いのでこれも捨てる - } + }, }; } diff --git a/packages/backend/src/services/register-or-fetch-instance-doc.ts b/packages/backend/src/services/register-or-fetch-instance-doc.ts index df7d125d0..75fea50f2 100644 --- a/packages/backend/src/services/register-or-fetch-instance-doc.ts +++ b/packages/backend/src/services/register-or-fetch-instance-doc.ts @@ -6,8 +6,8 @@ import { Cache } from '@/misc/cache.js'; const cache = new Cache(1000 * 60 * 60); -export async function registerOrFetchInstanceDoc(host: string): Promise { - host = toPuny(host); +export async function registerOrFetchInstanceDoc(idnHost: string): Promise { + const host = toPuny(idnHost); const cached = cache.get(host); if (cached) return cached; diff --git a/packages/backend/src/services/send-email.ts b/packages/backend/src/services/send-email.ts index 08bc12a30..b4dd0d828 100644 --- a/packages/backend/src/services/send-email.ts +++ b/packages/backend/src/services/send-email.ts @@ -5,7 +5,7 @@ import Logger from './logger.js'; export const logger = new Logger('email'); -export async function sendEmail(to: string, subject: string, html: string, text: string) { +export async function sendEmail(to: string, subject: string, html: string, text: string): Promise { const meta = await fetchMeta(true); const iconUrl = `${config.url}/static-assets/mi-white.png`; diff --git a/packages/backend/src/services/suspend-user.ts b/packages/backend/src/services/suspend-user.ts index df8d034ff..b891a6a1c 100644 --- a/packages/backend/src/services/suspend-user.ts +++ b/packages/backend/src/services/suspend-user.ts @@ -7,7 +7,7 @@ import { User } from '@/models/entities/user.js'; import { Users, Followings } from '@/models/index.js'; import { publishInternalEvent } from '@/services/stream.js'; -export async function doPostSuspend(user: { id: User['id']; host: User['host'] }) { +export async function doPostSuspend(user: { id: User['id']; host: User['host'] }): Promise { publishInternalEvent('userChangeSuspendedState', { id: user.id, isSuspended: true }); if (Users.isLocalUser(user)) { diff --git a/packages/backend/src/services/update-hashtag.ts b/packages/backend/src/services/update-hashtag.ts index 07468db0f..9f549c3f4 100644 --- a/packages/backend/src/services/update-hashtag.ts +++ b/packages/backend/src/services/update-hashtag.ts @@ -5,13 +5,13 @@ import { genId } from '@/misc/gen-id.js'; import { Hashtag } from '@/models/entities/hashtag.js'; import { normalizeForSearch } from '@/misc/normalize-for-search.js'; -export async function updateHashtags(user: { id: User['id']; host: User['host']; }, tags: string[]) { +export async function updateHashtags(user: { id: User['id']; host: User['host']; }, tags: string[]): Promise { for (const tag of tags) { await updateHashtag(user, tag); } } -export async function updateUsertags(user: User, tags: string[]) { +export async function updateUsertags(user: User, tags: string[]): Promise { for (const tag of tags) { await updateHashtag(user, tag, true, true); } @@ -21,8 +21,8 @@ export async function updateUsertags(user: User, tags: string[]) { } } -export async function updateHashtag(user: { id: User['id']; host: User['host']; }, tag: string, isUserAttached = false, inc = true) { - tag = normalizeForSearch(tag); +export async function updateHashtag(user: { id: User['id']; host: User['host']; }, _tag: string, isUserAttached = false, inc = true): Promise { + const tag = normalizeForSearch(_tag); const index = await Hashtags.findOneBy({ name: tag }); diff --git a/packages/backend/src/services/user-list/push.ts b/packages/backend/src/services/user-list/push.ts index d073afcd3..527aa7bf5 100644 --- a/packages/backend/src/services/user-list/push.ts +++ b/packages/backend/src/services/user-list/push.ts @@ -7,7 +7,7 @@ import { genId } from '@/misc/gen-id.js'; import { fetchProxyAccount } from '@/misc/fetch-proxy-account.js'; import createFollowing from '../following/create.js'; -export async function pushUserToUserList(target: User, list: UserList) { +export async function pushUserToUserList(target: User, list: UserList): Promise { await UserListJoinings.insert({ id: genId(), createdAt: new Date(), diff --git a/packages/backend/src/services/validate-email-for-account.ts b/packages/backend/src/services/validate-email-for-account.ts index 132168fb3..3f863fb71 100644 --- a/packages/backend/src/services/validate-email-for-account.ts +++ b/packages/backend/src/services/validate-email-for-account.ts @@ -24,11 +24,11 @@ export async function validateEmailForAccount(emailAddress: string): Promise<{ return { available, reason: available ? null : - exist !== 0 ? 'used' : - validated.reason === 'regex' ? 'format' : - validated.reason === 'disposable' ? 'disposable' : - validated.reason === 'mx' ? 'mx' : - validated.reason === 'smtp' ? 'smtp' : - null, + exist !== 0 ? 'used' : + validated.reason === 'regex' ? 'format' : + validated.reason === 'disposable' ? 'disposable' : + validated.reason === 'mx' ? 'mx' : + validated.reason === 'smtp' ? 'smtp' : + null, }; } diff --git a/packages/backend/yarn.lock b/packages/backend/yarn.lock index c01c9b87f..160319759 100644 --- a/packages/backend/yarn.lock +++ b/packages/backend/yarn.lock @@ -1486,13 +1486,12 @@ bull@4.8.4: semver "^7.3.2" uuid "^8.3.0" -busboy@^0.2.11: - version "0.2.14" - resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453" - integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM= +busboy@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== dependencies: - dicer "0.2.5" - readable-stream "1.1.x" + streamsearch "^1.1.0" bytes@3.1.0, bytes@^3.1.0: version "3.1.0" @@ -2237,14 +2236,6 @@ detect-libc@^2.0.0: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.0.tgz#c528bc09bc6d1aa30149228240917c225448f204" integrity sha512-S55LzUl8HUav8l9E2PBTlC5PAJrHK7tkM+XXFGD+fbsbkTzhCpG6K05LxJcUOEWzMa4v6ptcMZ9s3fOdJDu0Zw== -dicer@0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f" - integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8= - dependencies: - readable-stream "1.1.x" - streamsearch "0.1.2" - diff@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" @@ -3552,7 +3543,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3861,11 +3852,6 @@ is-whitespace@^0.3.0: resolved "https://registry.yarnpkg.com/is-whitespace/-/is-whitespace-0.3.0.tgz#1639ecb1be036aec69a54cbb401cfbed7114ab7f" integrity sha1-Fjnssb4DauxppUy7QBz77XEUq38= -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -4765,17 +4751,16 @@ msgpackr@^1.5.2: optionalDependencies: msgpackr-extract "^1.0.14" -multer@1.4.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.4.tgz#e2bc6cac0df57a8832b858d7418ccaa8ebaf7d8c" - integrity sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw== +multer@1.4.5-lts.1: + version "1.4.5-lts.1" + resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.5-lts.1.tgz#803e24ad1984f58edffbc79f56e305aec5cfd1ac" + integrity sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ== dependencies: append-field "^1.0.0" - busboy "^0.2.11" + busboy "^1.0.0" concat-stream "^1.5.2" mkdirp "^0.5.4" object-assign "^4.1.1" - on-finished "^2.3.0" type-is "^1.6.4" xtend "^4.0.0" @@ -5771,16 +5756,6 @@ re2@1.17.7: nan "^2.16.0" node-gyp "^9.0.0" -readable-stream@1.1.x: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -6303,10 +6278,10 @@ stream-parser@~0.3.1: dependencies: debug "2" -streamsearch@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" - integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== strict-event-emitter-types@2.0.0: version "2.0.0" @@ -6371,11 +6346,6 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" diff --git a/packages/client/src/components/MkNoteSub.vue b/packages/client/src/components/MkNoteSub.vue index aac3f233b..c8f8e3090 100644 --- a/packages/client/src/components/MkNoteSub.vue +++ b/packages/client/src/components/MkNoteSub.vue @@ -27,22 +27,21 @@ diff --git a/packages/client/src/components/captcha.vue b/packages/client/src/components/captcha.vue index 736073491..ac68899fb 100644 --- a/packages/client/src/components/captcha.vue +++ b/packages/client/src/components/captcha.vue @@ -82,7 +82,7 @@ function requestRender() { captcha.value.render(captchaEl.value, { sitekey: props.sitekey, theme: defaultStore.state.darkMode ? 'dark' : 'light', - callback: callback, + callback, 'expired-callback': callback, 'error-callback': callback, }); diff --git a/packages/client/src/components/channel-follow-button.vue b/packages/client/src/components/channel-follow-button.vue index dff02beec..1d7f16393 100644 --- a/packages/client/src/components/channel-follow-button.vue +++ b/packages/client/src/components/channel-follow-button.vue @@ -1,5 +1,6 @@