Compare commits

..

40 Commits

Author SHA1 Message Date
syuilo
96c7c85ad0 Merge pull request #13045 from misskey-dev/develop
* perf(drop-and-fusion): remove root Transition component for improve performance

* refactor(drop-and-fusion): some refactors

* clean up

* enhance(drop-and-fusion): some tweaks

* Feat(frontend): リアクション・ノート内絵文字・/about#emojisで絵文字詳細が見られるように (#12984)

* リアクション・ノート内絵文字・/about#emojisで絵文字詳細が見られるように

* update CHANGELOG.md

* fix locale & type errors

* fix locale etc

* fix

* fix type

* lint fixes

* lint fixes(2)

* tweak

* fix(backend): 虚無ノートを投稿できる問題の修正と `api.json` の OpenAPI Specification 3.1.0 への対応 (#12969)

* fix(backend): `text: null`だけのノートは投稿できないように

* add test

* Update CHANGELOG.md

* chore: bump OpenAPI Specification from 3.0.0 to 3.1.0

* chore: テストがすでにコメントで記述されていたのでそっちを使うことにする

* fix test

* fix(backend): prohibit posting whitespace-only notes

* Update CHANGELOG.md

* fix(backend): `renoteId`または`fileIds`(`mediaIds`)または`poll`が`null`でない場合に、`text  が空白文字のみで構成されたリクエストになることを許可して、結果は`text: null`を返すように

* test(backend): 引用renoteで空白文字のみで構成されたtextにするとレスポンスが`text: null`になることをチェックするテストを追加

* fix(frontend): `text`が`null`であって`renoteId`と`replyId`が`null`でないようなノートは引用リノートとして表示するように

* fix(misskey-js): OpenAPI 3.1に対応

* fix(misskey-js): 型生成をOpenAPI Specification 3.1.0に対応

* fix(ci): `validate-api.json`をOpenAPI Specification 3.1.0に対応

* fix(ci): スキーマ書き換えの際のミスを修正

* Revert "fix(frontend): `text`が`null`であって`renoteId`と`replyId`が`null`でないようなノートは引用リノートとして表示するように"

This reverts commit a9ca55343d.

* fix(misskey-js): `build-misskey-js-with-types`時は`api.json`のGETをスキップするように

* Revert "fix(misskey-js): `build-misskey-js-with-types`時は`api.json`のGETをスキップするように"

This reverts commit 865458989f.

* fix(misskey-js): `openapi-parser`で`validate`のかわりに`parse`を用いるように

* Update CHANGELOG.md

* fix type

* enhance(drop-and-fusion): refactor and new mode(wip)

* feat: 枠線をつけるMFMを追加 (#12981)

* Update MkMisskeyFlavoredMarkdown.ts

* Update const.ts

* Update MkMisskeyFlavoredMarkdown.ts

* Update MkMisskeyFlavoredMarkdown.ts

* Update CHANGELOG.md

* feat(CI): CHANGELOG.mdの追記個所をチェックするCIを追加 (#12963)

* feat(CI): CHANGELOG.mdの追記個所をチェックするCIを追加

* fix

* remove strategy

* fix

* fix

* enhance(drop-and-fusion): sweets mode

* 完成 (#12980)

* enhance(frontend): Playの説明欄にMFMを使えるように (#12899)

* (enhance) Playの説明欄にMFMを使えるように

* Update Changelog

* use class for mfm component

* Update packages/frontend/src/pages/flash/flash-edit.vue

Co-authored-by: 1Step621 <86859447+1STEP621@users.noreply.github.com>

* Update flash.vue

* Update CHANGELOG.md

---------

Co-authored-by: 1Step621 <86859447+1STEP621@users.noreply.github.com>

* fix: isPrivateIpで検証時にipバージョンが一致するかを確認するように (#12988)

* fix: isPrivateIpで検証時にipバージョンが一致するかを確認するように

* Update CHANGELOG.md

* Update CHANGELOG.md

* enhance(frontend) 日本語の拡張絵文字辞書を追加 (#12855)

* Create ja-JP.json

* Update general.vue

* Update ja-JP.json

* Update ja-JP.json

* Update ja-JP.json

* fix

* fix design

* (Add) ひらがな [wip]

* fix lint

* Apply suggestions from code review

Co-authored-by: 1Step621 <86859447+1STEP621@users.noreply.github.com>

* (add) ja-JP_hira

Co-authored-by: 1Step621 <86859447+1STEP621@users.noreply.github.com>

* (enhance) 言語名をちゃんと表示するように

---------

Co-authored-by: 1Step621 <86859447+1STEP621@users.noreply.github.com>

* refactor: noteテーブルのインデックス整理と配列カラムへのクエリでインデックスを使うように (#12993)

* Optimize note model index

* enhance(backend): ANY()をやめる (MisskeyIO#239)

* add small e2e test drive endpoint

---------

Co-authored-by: まっちゃとーにゅ <17376330+u1-liquid@users.noreply.github.com>

* enhance(frontend): dedicated games page

* enhance: 動画・音声周りのUIと動作改良 (#12925)

* wip

* (fix) `/files` をバイトレンジリクエストに対応させる

* video

* audio

* fix

* fix

* spdx

* fix (rangeRequest)

* fix

* Update CHANGELOG.md

* (add) ボリュームを保存できるように

* (fix) ミュート復帰時に音量が固定される

* named export

* tweak design

* Add sensitive class for audio component

* Refactor seekbar styles

* Refactor hms

* Revert "(add) ボリュームを保存できるように"

This reverts commit 6271f9493b.

* Revert "(fix) ミュート復帰時に音量が固定される"

This reverts commit a65002b56e.

* revert revert changes

---------

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

* (style) sticky系フッターのデザイン調整 (#13005)

* enhance(frontend): ページ遷移時にPlayerを閉じるように (#13013)

* なんかできた

* update changelog.md

* onDeactivatedを使うように

* Enhance(frontend): MkCustomEmojiDetailedDialogを調整 (#13015)

* MkEmojiDetailedDialogを調整

* 絵文字ライセンスでMFMを使えるように

* <a> -> <MkLink>

* 入力ボックスでmfmのオートコンプリートを効かせる

* enhance(frontend): チャンネルノートの場合はその前後を見れるように (#13019)

* チャンネルノートの場合はその前後を見れるように

* Update Changelog

* $[border ...]にクリッピング機能を追加 (#13002)

* Update MkMisskeyFlavoredMarkdown.ts

* Update MkMisskeyFlavoredMarkdown.ts

* Update CHANGELOG.md

* Set clipping as default

* Fix: properly handle cc followers (#13009)

* Fix: properly handle cc followers

Fix #13001

* Update CHANGELOG.md

* Fix syntax error

* enhance(drop-and-fusion): ゲームバランスの調整など

* MkCodeにコピーボタンを追加 (#12999)

* Update MkCode.vue

* Update MkCode.vue

* Update MkCode.vue

* Update MkCode.vue

* Update MkCode.vue

* Update MkCode.vue

* Update MkCode.vue

* Update MkCode.vue

* Update MkCode.vue

* Update MkCode.vue

* Update MkCode.vue

* Update MkCode.vue

* Update MkCode.vue

* Update CHANGELOG.md

---------

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

* chore(drop-and-fusion): bump version

* refactor: MkCodeをブロックとインラインで別コンポーネント化する (#13026)

* Create MkCodeInline.vue

* Update MkCode.vue

* Update MkMisskeyFlavoredMarkdown.ts

* Update flash.vue

* Update MkCodeInline.vue

* fix(frontend/MediaVideo): 再生シークバーの当たり判定を調整 (#13027)

* fix(frontend/MediaVideo): 再生シークバーの当たり判定を調整

* fix

* feat(frontend): 横スワイプでタブを切り替える機能 (#13011)

* (add) 横スワイプでタブを切り替える機能

* Change Changelog

* y方向の移動が一定量を超えたらスワイプを中断するように

* Update swipe distance thresholds

* Remove console.log

* adjust threshold

* rename, use v-model

* fix

* Update MkHorizontalSwipe.vue

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

* use css module

---------

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

* refactor: fully typed locales (#13033)

* refactor: fully typed locales

* refactor: hide parameterized locale strings from type data in ts access

* refactor: missing assertions

* docs: annotation

* refactor: style

* fix(frontend/HorizontalSwipe): ページの要素がはみ出る問題を修正 (#13036)

* 「外部サイトからインストール」のパスを /install-extensions に変更 (#12991)

* /install-extensionsに変更

* CHANGELOG.mdに追記

* 旧パスも利用できるように

* fix: Some fixes for #12850 (#12862)

- refinement the error message when trueMail validation fails
- the settings of trueMail are not displayed after saving
- changing how `Active Email Validation` is saved

* Enhance(frontend): MFMの属性にオートコンプリートが利用できるように (#12803)

* MFMのパラメータでオートコンプリートできるように

* tweak conditions & refactor

* ファイル末尾の改行忘れ

* remove console.log & refactor

* 型付けに敗北

* fix

* update CHANGELOG.md

* tweak conditions

* CHANGELOGの様式ミス

* CHANGELOGを書く場所を間違えていたので修正

* move changelog

* move changelog

* typeof MFM_TAGS[number]

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

* $[border.noclip ]対応

* Update const.ts

---------

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

* feat: reversi

Resolve #12962

* refactor: deprecate i18n.t (#13039)

* refactor: deprecate i18n.t

* revert: deprecate i18n.t

This reverts commit 7dbf873a2f.

* chore: reimpl

* refactor: extract bubble-game engine as independent package

* lint fix

* lint fixes

* tweak reversi map

* fix lint

* fix(dev): fix workspace settings

* fix(dev): fix pnpm dev

* enhance(reversi): tweak reversi

* refactor: migrate to ESM

* fix api-extractor

* add missing ext

* enhance(reversi): tweak reversi

* 🎨

* Fix(frontend): 日本語のUnicode絵文字追加辞書をインストールすると絵文字ピッカーでUnicode絵文字を検索できなくなるのを修正 (#13046)

* 絵文字辞書のサロゲートペアを修正

* update CHANGELOG.md

* Revert "update CHANGELOG.md"

This reverts commit 7c24fa611a.

* enhance(reversi): tweak reversi

Resolve #13048

* Update Dockerfile

* enhance(reversi): tweak reversi

* enhance(frontend): ノート作成画面の添付メニューから直接ファイルを消せるように (#12858)

* (enhance) 添付画面から直接ファイルを消せるように

* Update Changelog

---------

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

* enhance(reversi): tweak reversi

* enhance(sw): オフライン表示のデザインを改善 (#13052)

* enhance(sw): オフライン表示のデザインを改善

* Update Changelog

* fix

* fix

* fix

* 言語が取得できなかった場合のフォールバックを追加

* (change) translation key

* enhance(reversi): tweak reversi

* enhance(reversi): tweak reversi

* fix(frontend): MkHorizontalSwipeでメニューを閉じるのに2回クリックが必要になる問題を修正

#13055

* return a `Vary: Accept` header for all dual-format endpoints #365 (#13044)

`/users/:user`, `/@:user`, `/notes/:note` return different responses
depending on the request's `Accept:` header. If we don't consistently
return a `Vary: Accept` header, browsers and caching proxies will get
confused, and return AP representations when HTML was requested, or
vice versa.

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

* enhance(frontend): タイムラインフィルターの設定を保持+センシティブなノートを隠せるように (#12848)

* (enhance) タイムラインフィルターの状態を記憶するように

* fix

* (enhance) センシティブな投稿をミュート形式で表示する(TLのみ)

* fix

* Update Changelog

* Fix changelog

* Lintエラーを潰す

* Update locales/ja-JP.yml

* hideSensitive -> withSensitive

* Update CHANGELOG.md

* Update ja-JP.yml

---------

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

* Enhance(frontend): 絵文字編集ダイアログをウィンドウにする (#13047)

* 絵文字編集ダイアログをウィンドウにする

* update CHANGELOG.md

* update deps

* New Crowdin updates (#12845)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Lao)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Lao)

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

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

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

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

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

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

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

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Lao)

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

* New translations ja-jp.yml (Romanian)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Arabic)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Dutch)

* New translations ja-jp.yml (Polish)

* New translations ja-jp.yml (Portuguese)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Slovak)

* New translations ja-jp.yml (Swedish)

* New translations ja-jp.yml (Ukrainian)

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

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Bengali)

* New translations ja-jp.yml (Uzbek)

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

* New translations ja-jp.yml (Korean (Gyeongsang))

* New translations ja-jp.yml (Catalan)

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Arabic)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Greek)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Polish)

* New translations ja-jp.yml (Portuguese)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Slovak)

* New translations ja-jp.yml (Ukrainian)

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

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Bengali)

* New translations ja-jp.yml (Uzbek)

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

* New translations ja-jp.yml (Korean (Gyeongsang))

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

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

* New translations ja-jp.yml (Italian)

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

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

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

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

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

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

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

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Spanish)

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

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Arabic)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Portuguese)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Slovak)

* New translations ja-jp.yml (Ukrainian)

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

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Indonesian)

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

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (German)

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

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

* New translations ja-jp.yml (Thai)

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

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

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

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (Romanian)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Arabic)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Greek)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Polish)

* New translations ja-jp.yml (Portuguese)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Slovak)

* New translations ja-jp.yml (Ukrainian)

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

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Bengali)

* New translations ja-jp.yml (Uzbek)

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

* New translations ja-jp.yml (Korean (Gyeongsang))

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

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

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Korean)

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

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Indonesian)

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

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

* chore(deps-dev): bump vite in /scripts/changelog-checker (#13040)

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.0.11 to 5.0.12.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.0.12/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.0.12/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* enhance(frontend): 季節に応じた画面の演出を南半球に対応させる (#12838)

* (enhance) 季節に応じた画面の演出を南半球に対応させる

* Update Changelog

* (add) 半球の簡易自動判定

---------

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

* enhance(frontend): リファクタリングなど

* perf(reversi): improve performance of reversi backend

* 2024.2.0-beta.1

* fix(frontend/pizzax): デフォルト値が適用できないことがあるのを修正 (#13057)

* fix(frontend/pizzax): デフォルト値が適用できないことがあるのを修正

* fix

* いらんプロパティをけす

* refactor(reversi): refactoring of reversi backend

* New Crowdin updates (#13056)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Lao)

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

* New translations ja-jp.yml (Romanian)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Arabic)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (Danish)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Greek)

* New translations ja-jp.yml (Hungarian)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Dutch)

* New translations ja-jp.yml (Norwegian)

* New translations ja-jp.yml (Polish)

* New translations ja-jp.yml (Portuguese)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Slovak)

* New translations ja-jp.yml (Swedish)

* New translations ja-jp.yml (Turkish)

* New translations ja-jp.yml (Ukrainian)

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

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Bengali)

* New translations ja-jp.yml (Croatian)

* New translations ja-jp.yml (Uyghur)

* New translations ja-jp.yml (Lojban)

* New translations ja-jp.yml (Sinhala)

* New translations ja-jp.yml (Uzbek)

* New translations ja-jp.yml (Kannada)

* New translations ja-jp.yml (Haitian Creole)

* New translations ja-jp.yml (Kabyle)

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

* New translations ja-jp.yml (Korean (Gyeongsang))

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

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

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

* 2024.2.0-beta.2

* enhance(reversi): some tweaks

* perf(reversi): improve performance of reversi backend

* fix lint

* enhance(reversi): render ogp

* fix lint

* fix: 2024-01-22 10:50時点のdevelopにてCIがコケている (#13060)

* fix: バブルゲームのビルド失敗修正

* fix: api.jsonの定義誤りを修正

* fix: lint.yml(typecheck)

* fix: fix eslint error

* fix: frontend vitest version

* fix: frontend vitest version

* fix:

* fix: cypress

* fix: misskey-js test

* fix: misskey-js tsd(tsdはpakcage.jsonのexportsをサポートしない?)

* fix: conflict

* fix: 間違えて上書きしたところを修正

* fix: 再

* fix: api.json

* fix: api.json

* fix: タイムアウト延長

* Update packages/misskey-js/jest.config.cjs

Co-authored-by: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Co-authored-by: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>

* 🎨

* fix lint

* 2024.2.0-beta.3

* chore: publish misskey-js automatically (#13014)

* chore: publish @misskey-dev/misskey-js

* remove @misskey-dev/

* ??

* correct version

* version

* fix of #13014 (misskey-js publish)

* 修正できたかも (#13066)

* perf: (productionの)dependenciesから@typesを削除、reversi/bubble-gameをesbuildにする (#13067)

* perf: (productionの)dependenciesから@typesを削除、reversi/bubble-gameをesbuildにする

* fix

* fix

* fix(build): スクリプトの名前の変更漏れ (#13068)

* fix(build): スクリプトの名前の変更漏れ

* 漏れの漏れ

* 🎨

* enhance(reversi): improve desync handling

* New Crowdin updates (#13061)

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

* New translations ja-jp.yml (Korean)

* 2024.2.0-beta.4

* fix(frontend/HorizontalSwipe): スワイプ・UIアニメーションが無効の際はトランジションを行わないように (#13076)

* fix(frontend/HorizontalSwipe): アニメーションを減らすが考慮されるように

* fix

* fix

* revert unused change

* fix

* 🎨

* enhance(reversi): 準備中の自分の対局も一覧に表示するように

* enhance(reversi): more robust matching process

* fix of 65557d5f27

* enhance(reversi): 開始時に対局をシェアできるように

* enhance(reversi): improve stability

* New translations ja-jp.yml (Japanese, Kansai) (#13074)

* enhance(reversi): improve game setting flow

* enhance(reversi): tweak MATCHING_TIMEOUT_MS

* perf(reversi): set expire matchSpecific and matchAny

* fix(reversi): wait redis operation to improve stability

* 2024.2.0-beta.5

* fix(frontend/pizzax): オブジェクトにnullがある場合に正しくマージされないのを修正 (#13073)

* fix(frontend/pizzax): オブジェクトにnullがある場合に正しくマージされない

* fix types

* マージを内製

* fix(frontend/reversi): fix game preview

* enhance(reversi): improve matching system

* New translations ja-jp.yml (Japanese, Kansai) (#13077)

* 2024.2.0-beta.6

* enhance(reversi): 変則なしマッチングを可能に

* fix(reversi/backend): refactor and fixes

* Create deploy-test-environment.yml (#13079)

* test

* Revert "Create deploy-test-environment.yml (#13079)"

This reverts commit 4de14fb5cf.

* New Crowdin updates (#13080)

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

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

* 2024.2.0-beta.7

* New Crowdin updates (#13082)

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

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

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (German)

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

* fix(dev): pnpm devで依存関係更新が一部反映されない (#13091)

* fix misskey-js version

* refactor(frontend/MediaPlayer): cssの重複を削除 (#13094)

* Update MkMediaAudio.vue

* Update MkMediaVideo.vue

* enhance(frontend): リモートのユーザーはメニューから直接リモートで表示できるように (#13087)

* enhance(frontend): リモートのユーザーはメニューから直接リモートで表示できるように

* change changelog

* Apply suggestions from code review

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

---------

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

* fix(backend): Fix typos in job configurations (#13086)

* Fix typos

* Update CHANGELOG

* Update CHANGELOG.md

* feat(frontend/nirax): リダイレクトを設定できるように (#13030)

* feat(frontend/nirax): リダイレクトを設定できるように

* revert demonstrative changes

* fix

* revert unrelated changes

* リダイレクトの際にパスが変わらない問題を修正

* リダイレクトが必要なrouteを設定

* fix lint

* router向けe2eテストの追加

* fix

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Co-authored-by: samunohito <46447427+samunohito@users.noreply.github.com>

* fix(i18n): ストック情報とフロー情報の文言をわかりやすく変更 (#13085)

* fix(i18n): ストック情報とフロー情報をわかりやすく書き直す

* Update ja-JP.yml

* Update ja-JP.yml

* test(frontend): load default config to start vite (#12867)

Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com>

* iOSで大きな画像を変換してアップロードできない問題を修正 (#13109)

Fix https://github.com/misskey-dev/misskey/issues/12026

* refactor: frontendのcomponentsの型エラーを改善 (#12926)

* add: safeFloatParserを追加

* fix: 欠けていた型を追加

* refactor: pageBlockTypesをjson-schemaに移植

* refactor: components/global内の型エラーが出ている箇所を修正

* lint: fix null check style

* refactor: fix type error

* refactor: fix some type errors

* fix: 翻訳が抜けていた箇所を修正

* refactor: getJsonSchemaで正しいスキーマが返されるように修正

* fix: MkChartの型エラーとbytesオプションが機能していない問題を修正

* fix(misskey-js): `drive`->`folderUpdated`のpayloadの型が間違っていたのを修正

* refactor: fix some type errors

* change: Captcha読み込み中の文言をLoadingに変更

* refactor(backend/misskey-js): MainEventの型を改善

* refactor: chartjs-plugin-gradientが二重でpluginに登録されていたのを修正

* update: misskey-js.api.md

* refactor: fix some type errors

* fix: backendのtypecheckが落ちていたのを修正

* update: misskey-js.api.md

* add: json-schemaのnoteにpollの型定義を追加

* refactor: noteのjson-schemaの型を改善

* refactor: MkPoll

* refactor: fix some type errors

* change: UserLiteにisLockedを持たせるように

* fix: notificationスキーマにroleが含まれていないのを修正

* Revert "change: UserLiteにisLockedを持たせるように"

This reverts commit 1bb0c8e7a9.

* fix: フォロー通知から鍵垢へのフォローを行うと処理中のまま止まってしまう問題を修正

* refactor: noteスキーマのvisibilityにenumを追加

* change: deepCloneのCloneableTypeにundefinedを追加

* refactor: fix some type errors

* refactor: `allowEmpty: false`を使用していた箇所を`minLength: 1`に置き換え

* enhance: API 'retension' のresponseの型を追加

* fix: Chart関連のtooltipが正しい位置に表示されない問題を修正

* refactor: fix some type errors

* fix: 型情報が不足していたのを修正

* enhance: announcementスキーマにenumを追加

* enhance: ロールポリシーの型定義をRoleServiceからjson-schemaに移植

* refactor: policiesを`ref: RolePolicies`に統一

* fix: API `meta` のレスポンスの型にpoliciesが含まれていないのを修正

* refactor: fix some type errors

* fix: backendのlintが落ちているのを修正

* fix: MkFoldableSectionの開閉時のanimationが適用されていない問題を修正

* fix: backendのtypecheckが落ちているのを修正

* update: run build-misskey-js-with-types

* fix: MkDialogのmount時に文字数制限の判定が行われない問題を修正

* update: CHANGELOG.md

* refactor: MkUserSelectDialogの型を改善

* fix: deepCloneでundefinedはcloneしないように (#9207)

* change: frontendのcloneをbackend側にも反映

* update: CHANGELOG.md

* fix: RoleServiceからPackを通して型RolePoliciesに依存させないように

* Update packages/frontend/src/scripts/get-note-summary.ts

* revert RoleService.ts changes

* change:  optional chaining -> non-null assertion

* remove: unused import

* fix: propsで渡されたuserがUserLiteの場合に意図しない動作になってしまうのを修正

* change: fix null check style

* refactor: fix type error

* change: fix null check style

* Update packages/frontend/src/components/MkDrive.vue

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

* refactor: css moduleでglobalを使わないように

* refactor: roleのiconUrlは必ず存在するものとして扱うように

* enhance: MenuButtonのactiveにcomputedを受け付けられるように

* Update packages/frontend/src/components/MkNotePreview.vue

* Update MkWindow.vue

* refactor: notification.noteは必ず存在するものとして扱うように

* Update packages/frontend/src/components/MkNotification.vue

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

* fix: MkSignupDialogでdoneのemit時にresを含んでいなかったのを修正

* Update packages/frontend/src/scripts/clone.ts

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

* refactor: 不要な返り値の型を削除

* refactor: 不要なnullチェックを削除

* update: misskey-js-autogen

* update: clone.ts

* refactor

* Update MkNotification.vue

* Update MkNotification.vue

* ✌️

* Update MkNotification.vue

* Update MkNotification.vue

* Update MkNotification.vue

* Update MkNotifications.vue

* Update MkUserSetupDialog.Profile.vue

* Update MkUserCardMini.vue

* ✌️

* Update MkMenu.vue

---------

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

* fix/refactor(reversi): 既存のバグを修正・型定義を強化 (#13105)

* 既存のバグを修正

* fix types

* fix misskey-js autogen

* Update index.d.ts

---------

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

* update deps

* 2024.2.0-beta.8

* Revert "Revert "Create deploy-test-environment.yml (#13079)""

This reverts commit 4553d6426b.

* refactor(frontend): global/router -> router

* refactor(backend): User関連のスキーマ/型の指定を強くする (#12808)

* refactor(backend): User関連のスキーマ/型の指定を強くする

* refactor(backend): `pack()`の引数にスキーマを指定するように

* chore: fix ci

* fix: 変更漏れ

* fix ci

---------

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

* fix(frontend): styleの指定方法を変更 (#13120)

* fix(ci): `misskey-js` のバージョンチェックをトリガーする条件の修正 (#13116)

* fix(misskey-js): バージョンチェックのトリガー条件を修正

* chore(misskey-js): 2024.2.0-beta.8

* Fix(frontend): リバーシで自分自信を招待できるのを修正 & os.selectUser()のincludeSelfが機能していないのを修正 (#13117)

* リバーシで自分自信を招待できるのを修正 & os.selectUser()のincludeSelfが機能していないのを修正

* lint fix

* enhance(frontend): 🌸

* chore(deps): bump codecov/codecov-action from 3 to 4 (#13125)

Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: Hide reactions of all remote users / feat: moderators can see reactions of all users (#13128)

* fix: Hide reactions of all remote users
https://github.com/misskey-dev/misskey/issues/12964

* feat: Moderators can see reactions of all users
https://github.com/misskey-dev/misskey/issues/13127

* modify CHANGELOG.md

* fix iAmModerator

* chore(deps): bump peter-evans/slash-command-dispatch from 3 to 4 (#13124)

Bumps [peter-evans/slash-command-dispatch](https://github.com/peter-evans/slash-command-dispatch) from 3 to 4.
- [Release notes](https://github.com/peter-evans/slash-command-dispatch/releases)
- [Commits](https://github.com/peter-evans/slash-command-dispatch/compare/v3...v4)

---
updated-dependencies:
- dependency-name: peter-evans/slash-command-dispatch
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* 「見たことのあるリノートを省略して表示」が効いていない問題を修正  (#13133)

* fix: 「見たことのあるリノートを省略して表示」が効いていない問題を修正
fix #13131

* add a comment

* fix(backend): "誰でも新規登録できるようにする"の初期値をOFFにする (#13130)

* fix(backend): "誰でも新規登録できるようにする"の初期値をOFFにする

* fix CHANGELOG.md

* fix

* Update deploy-test-environment.yml (#13136)

* fix: api-docが開けない問題を修正 (#13132)

* refactor: 自己参照を使用している箇所に`selfRef`を持たせるように

* feat: スキーマ生成時に自己参照を含むかどうかを指定できるように

* fix: api.jsonにselfRefが含まれているのを修正

* refactor: 他の箇所と同様にselfRefの除去を行うように

* remove: 不要なimportを削除

* refactor(frontend): `os.popup()`の`props`の型チェックを有効化 (#13140)

* refactor(frontend): `os.popup()`の`props`の型チェックを有効化

* refactor: `ComponentProps`に書き換え

* refacor: `import type`

* enhance(frontend): shiki v1に移行 (#13138)

* enhance(frontend): shiki v1に移行

* optimize chunks, エラーを握りつぶす

* wasmを分離

* バンドルサイズの警告の最小値を650kBに引き上げ

* optimize

* fix(frontend): アバターデコレーションのアニメーションが止まらない (#13139)

* fix(frontend): アバターデコレーションのアニメーションが止まらない

* Update Changelog

* i -> index

* key

* revert lint fixes

* fix(frontend): selectUserのパラメータを調整 (#13142)

* fix(frontend): selectUserのパラメータを調整

* ついでに軽微なスタイルの修正

* fix(frontend): チャートのlegendがクリックに反応しない問題を修正

これにより発生 https://github.com/misskey-dev/misskey/pull/12926

* New Crowdin updates (#13090)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Korean (Gyeongsang))

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

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (French)

* 2024.2.0-beta.9

* fix(backend): メール配信機能が無効ならばメールを送ることのないように (#13152)

Do not send email if email delivery is disabled

* ignore `instance.actor` when checking if there are local users (#13146)

* ignore `instance.actor` when checking if there are local users

We've seen this happen a few times:

* there was some AP software at $some_domain
* it gets replaced by Misskey
* before the first user can be created, an AP activity comes in
* Misskey resolves the activity
* to do this, it creates the `instance.actor` to sign its request
* now there *is* a local user, so the `meta` endpoint returns
  `requireSetup:false`
* the admin is very confused

This commit factors out the check, and doesn't count the
`instance.actor` as a real user.

* autogen bits

* keep cached avatar&banner when refresh fails to get new values (#13145)

* keep cached avatar&banner when refresh fails to get new values

when the remote explicitly tells us a user image is gone, we remove
our cached value, but if we fail to get the image, we keep whatever
value we already have

this should minimise the problem of avatars randomly disappearing

* autogen bits

* pnpm run build-misskey-js-with-types

---------

Co-authored-by: tamaina <tamaina@hotmail.co.jp>

* update patrons

* New Crowdin updates (#13156)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Korean (Gyeongsang))

* New translations ja-jp.yml (Korean (Gyeongsang))

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* Fix(frontend): クロップ後の解像度が異様に低くなる問題の修正&クロップに失敗する問題&コメントにnullという文字列が入る問題の修正 (#13162)

* Fix(frontend): Fix resolution of cropped image (misskey-dev#11489)

* CHANGELOG

* Fix(frontend): クロップの際、folderIdがnullだと文字列のnullが送られ検索できない問題

* Fix: キャプションが存在しないときにクロップすると'null'がキャプションに入ってしまう問題 (misskey-dev#11813)

* Update CHANGELOG

* refactor(frontend): `os.popup()`の`events`の型チェックを有効化 (#13165)

* 2024.2.0-beta.10

* enhance(frontend): シンタックスハイライトにテーマを適用できるように (#13175)

* enhance(frontend): シンタックスハイライトにテーマを適用できるように

* Update Changelog

* こっちも

* テーマの値がディープマージされるように

* 常にテーマ設定に準じるように

* テーマ更新時に新しいshikiテーマを読み込むように

* enhance(frontend): KeepAliveのページキャッシュを削除できるように (#13180)

* enhance(frontend): 内部のページキャッシュを削除できるように

* Update Changelog

* Enhance(frontend): フロント側でもリアクション権限のチェックをするように (#13134)

* フロント側でもリアクション権限のチェックをするように

* update CHANGELOG.md

* lint fixes

* remove unrelated diffs

* deny -> reject
denyは「(信用しないことを理由に)拒否する」という意味らしい

* allow -> accept

* EmojiSimpleにlocalOnlyを含めるように

* リアクション権限のない絵文字は打てないように(ダイアログを出すのではなく)

* regenerate type definitions

* lint fix

* remove unused locales

* remove unnecessary async

* fix(frontend): エラー画像URLを設定した後解除すると,デフォルトの画像が表示されない問題の修正 (#13172)

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>

* enhance(frontend): リモートへの引用リノートと同一のリンクにはリンクプレビューを表示しないように (#13178)

* enhance(frontend): リモートへの引用リノートと同一のリンクにはリンクプレビューを表示しないように

* Update Changelog

---------

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

* AP Key の JSON-LD 表現を修正 (#13170)

* CHANGELOGを修正 (#13181)

* chore(frontend): reword possible typo (#13182)

* fix(bubble-game): 共有用画像のコメントにnullが入る問題を修正 (#13183)

* fix(misskey-js): 自動生成物の冒頭からバージョンと日付を削除 (#13185)

* Enhance: 連合向けのノート配信を軽量化 (#13192)

* AP HTML表現をシンプルに

* a

* CHANGELOG

* リンク

* Fix(frontend): MkCodeEditorで行がずれていくのを修正 (#13188)

* MkCodeEditorで行がずれていくのを修正

* update CHANGELOG.md

* 正しい 2024.2.0-beta.10 改版手順? (#13173)

* 正しい 2024.2.0-beta.10 改版手順?

* run build-misskey-js-with-types

* enhance(frontend/HorizontalSwipe): 操作性の改善 (#13038)

* Update swipe thresholds and touch-action

* スワイプ中にPullToRefreshが反応しないように

* 横スワイプに関与する可能性のある要素がある場合はスワイプを発火しないように

* update threshold

* isSwipingを外部化

* rename

---------

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

* typo

* Fix: Summaly proxy利用時にプレイヤーが動作しないことがあるのを修正 (#13196)

* Fix: Summaly proxy利用時にプレイヤーが動作しないことがあるのを修正

* CHANGELOG

* test(frontend): migrate MSW in Storybook to v2 (#13195)

* fix(frontend) misskey-js type (#13202)

* refactor(backend): exist -> exists (#13203)

* refactor(backend): exist -> exists

* fix

* fix(frontend): aiscriptのコードブロックでのハイライト指定を修正 (#13208)

* chore: use vite@5.1.0 / pnpm@8.15.1

* fix: 特定文字列を含むノートを投稿できないようにする管理画面用設定項目を追加 (#13210)

* fix: 特定文字列を含むノートを投稿できないようにする管理画面用設定項目を追加

* Serviceでチェックするように変更

* perf(frontend): splash screenのdomが消えない場合があるのを修正

https://github.com/misskey-dev/misskey/issues/10805

* chore(deps): bump pnpm/action-setup from 2 to 3 (#13215)

Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 2 to 3.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v2...v3)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* New Crowdin updates (#13179)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Korean)

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

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Russian)

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

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (Catalan)

* update deps

* 2024.2.0-beta.11

* fix misskey-js version

* dev: Update misskey-tga deploy-test-environment.yml (#13221)

* fix: misskey-jsの型定義生成時にバックエンドの依存パッケージもビルドするように (#13249)

* fix(frontend): vue v3.4.16でタイムラインが正常に表示できない問題を修正

* type

* fix: misskey-jsの型定義生成時にバックエンドの依存パッケージもビルドするように

* Revert "type"

This reverts commit bac0951bd1.

* Revert "fix(frontend): vue v3.4.16でタイムラインが正常に表示できない問題を修正"

This reverts commit 92b2165828.

* Update about-misskey.vue

* New Crowdin updates (#13216)

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Italian)

* feat: provide tarball (#13260)

* feat: provide tarball

* build: pack on build-assets

* chore: use ignore-walk

* chore: debug

* build: dependencies

* New translations ja-jp.yml (Spanish) (#13261)

* update SPDX-FileCopyrightText

* refactor(msjs): avoid any (part 1) (#13247)

* refactor(msjs): avoid any

* run api extractor

---------

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <daisho7308+f@gmail.com>

* ci(test-frontend): Cypressのテストの失敗時、永遠に止まらない問題を回避 (MisskeyIO#434) (#13274)

失敗しないようタイムアウトの延長・15分で止まるように

* chore: 以前の開発環境(backendにアクセスする方式)を立ち上げられるように (#13220)

* chore: 以前の開発環境(backendにアクセスする方式)を立ち上げられるように

* Update scripts/dev.mjs

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>

---------

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>

* fix: downgrade vue to 3.4.15

* enhance: 禁止ワードはリモートノートも対象に (#13280)

Resolve #13279

* Update CHANGELOG.md (#13282)

#13281 に対応していることを強調

* perf: omit search for immutable static requests (#13265)

* perf: omit search for immutable static requests

* perf: also applies to /files

* fix: exclude /proxy

* /files/:key/*を301 redirectに

---------

Co-authored-by: tamaina <tamaina@hotmail.co.jp>

* Revert "update SPDX-FileCopyrightText"

This reverts commit 9b5aeb76d8.

* (re)  update SPDX-FileCopyrightText
Fix  #13290

* fix(frontend): エラーページのトラブルシューティングがリンク切れしている問題 (#176) (#13288)

* fix: TypeAssertionExpression breaks Storybook builds

* build: upgrade Storybook to 8 beta (#13297)

* chore: upgrade Storybook to 8

* ci: restore Storybook workflow

* build: createRequire

* ci: TurboSnap life extension

* dev: Update misskey-tga (#13223)

* Update deploy-test-environment.yml

* Update .github/workflows/deploy-test-environment.yml

Co-authored-by: anatawa12 <anatawa12@icloud.com>

* Update deploy-test-environment.yml

* Update deploy-test-environment.yml

---------

Co-authored-by: anatawa12 <anatawa12@icloud.com>

* fix(ci): publish docker image fails (#13325)

* fix(ci): publish docker image fails

* fix: `docker.yml`

* refactor: remove inaccurate name

* fix: match version

* feat(backend): likeOnlyなどでハートにフォールバックする際異体字セレクタがない方に揃える (#13299)

* feat(backend): likeOnlyなどでハートにフォールバックする際異体字セレクタがない方に揃える

close #13298

* Update ReactionService.ts

* chore(backend): prefer single quote for string literal

* fix(backend): add missing schemas and fix incorrect schemas (#13295)

* fix(backend): add missing schemas and fix incorrect schemas

* fix: ci

* fix: ci (本命)

* fix: run `pnpm build-misskey-js-with-types`

* fix: typos

* fix: role-condition-formula-value contains `id`

* fix: incorrect schema

* リモートユーザーが復活してもキャッシュにより該当ユーザーのActivityが受け入れられないのを修正 Fix #13273 (#13275)

* リモートユーザーが復活してもキャッシュにより該当ユーザーのActivityが受け入れられないのを修正 Fix #13273

* CHAGELOG

* Use Redis event

---------

Co-authored-by: tamaina <tamaina@hotmail.co.jp>

* refactor(backend): misc/cacheをシンプルな実装に戻した

* fix

* fix type

* Update CHANGELOG.md

* New Crowdin updates (#13267)

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

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (Thai)

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

* fix(frontend): vue v3.4.16以降でタイムラインが正常に表示できない問題を修正 (#13248)

* fix(frontend): vue v3.4.16でタイムラインが正常に表示できない問題を修正

* type

* Revert "fix: downgrade vue to 3.4.15"

This reverts commit e12369ac13.

* Update pnpm-lock.yaml

---------

Co-authored-by: tamaina <tamaina@hotmail.co.jp>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>

* 2024.2.0-beta.12

* fix(ci): publish docker image fails (3) (#13327)

* fix(ci): publish docker image fails (3)

* fix: set `tags`

* fix(frontend/pageMetadata): ページタイトルが更新されない問題 (#13289)

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>

* chore(deps): bump actions/github-script from 6.4.0 to 7.0.1 (#13311)

Bumps [actions/github-script](https://github.com/actions/github-script) from 6.4.0 to 7.0.1.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v6.4.0...v7.0.1)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump pnpm/action-setup from 2 to 3 (#13310)

Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 2 to 3.
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](https://github.com/pnpm/action-setup/compare/v2.0.0...v3)

---
updated-dependencies:
- dependency-name: pnpm/action-setup
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump actions/checkout from 3.6.0 to 4.1.1 (#13309)

Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3.6.0...v4.1.1)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump actions/upload-artifact from 3 to 4 (#13308)

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump actions/setup-node from 3.8.1 to 4.0.2 (#13307)

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3.8.1 to 4.0.2.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3.8.1...v4.0.2)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build: docker buildのpnpm i実行時にNODE_ENV=productionが指定されるようにする (#13329)

* fix of  #13330 (#13330)

* build: docker buildのpnpm i実行時にNODE_ENV=productionが指定されるようにする

* build: 消す行間違ってたのを修正

* fix(dev): devコマンドの実装を修正 (#13336)

* fix misskey-js version

* refactor(backend): remove/replace deprecated type deps (#13252)

* Update CHANGELOG.md

* 2024.2.0-beta.13

* Merge pull request from GHSA-qqrm-9grj-6v32

* maybe ok

* fix

* test wip

* ✌️

* fix

* if (res.ok)

* validateContentTypeSetAsJsonLD

* 条件を考慮し直す

* その他の+json接尾辞が付いているメディアタイプも受け容れる

* https://github.com/misskey-dev/misskey-ghsa-qqrm-9grj-6v32/pull/1#discussion_r1490999009

* add `; profile="https://www.w3.org/ns/activitystreams"`

* application/ld+json;

* feat: add link to local note in initial comment of abuse note (#13347)

* feat: add link to local note in initial comment of abuse note

* docs(changelog): ノートの通報時にリモートのノートであっても自インスタンスにおけるノートのリンクを含むように

* feat: license violation protection (#13285)

* spec(frontend): aboutページにリポジトリ・フィードバックのURLを表示させる

Cherry-picked from MisskeyIO#441
Cherry-picked from MisskeyIO#438

* feat: license violation protection

* build: fix typo

* build: fix typo

* fix: farewell to the static type land

* fix: key typo

* fix: import typo

* fix: properly interpret `prominently`

* docs: add disclaimer

* docs: update CHANGELOG

* chore: add gap

---------

Co-authored-by: まっちゃとーにゅ <17376330+u1-liquid@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: 1Step621 <86859447+1STEP621@users.noreply.github.com>
Co-authored-by: zyoshoka <107108195+zyoshoka@users.noreply.github.com>
Co-authored-by: FineArchs <133759614+FineArchs@users.noreply.github.com>
Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com>
Co-authored-by: ikasoba <57828948+ikasoba@users.noreply.github.com>
Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Co-authored-by: GrapeApple0 <84321396+GrapeApple0@users.noreply.github.com>
Co-authored-by: YS <47836716+yszkst@users.noreply.github.com>
Co-authored-by: まっちゃとーにゅ <17376330+u1-liquid@users.noreply.github.com>
Co-authored-by: a <a@trwnh.com>
Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
Co-authored-by: Korange <hi@korange.work>
Co-authored-by: AsukaMari <2037177696@qq.com>
Co-authored-by: dakkar <dakkar@thenautilus.net>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>
Co-authored-by: tamaina <tamaina@hotmail.co.jp>
Co-authored-by: Srgr0 <66754887+Srgr0@users.noreply.github.com>
Co-authored-by: woxtu <woxtup@gmail.com>
Co-authored-by: Kagami Sascha Rosylight <saschanaz@outlook.com>
Co-authored-by: yukineko <27853966+hideki0403@users.noreply.github.com>
Co-authored-by: atsuchan <83960488+atsu1125@users.noreply.github.com>
Co-authored-by: taichan <40626578+tai-cha@users.noreply.github.com>
Co-authored-by: Soli <personal@str08.net>
Co-authored-by: MeiMei <30769358+mei23@users.noreply.github.com>
Co-authored-by: Kisaragi <48310258+KisaragiEffective@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <daisho7308+f@gmail.com>
Co-authored-by: taiy <53635909+taiyme@users.noreply.github.com>
Co-authored-by: anatawa12 <anatawa12@icloud.com>
2024-02-17 15:05:47 +09:00
syuilo
339acd2644 Merge pull request #12828 from misskey-dev/develop
Release: 2023.12.2
2023-12-28 08:31:51 +09:00
syuilo
53898c5006 Merge pull request #12771 from misskey-dev/develop
Release: 2023.12.1
2023-12-27 21:28:38 +09:00
syuilo
0b5228f3cd Merge pull request #12564 from misskey-dev/develop
Release: 2023.12.0
2023-12-23 20:00:20 +09:00
syuilo
9784d10c62 Merge pull request #12330 from misskey-dev/develop
Release: 2023.11.1
2023-11-17 18:32:42 +09:00
syuilo
0c2dd33593 Merge pull request #12177 from misskey-dev/develop
Release: 2023.11.0
2023-11-05 18:18:35 +09:00
syuilo
3043b5256d Merge pull request #12060 from misskey-dev/develop
Release: 2023.10.2
2023-10-21 14:18:53 +09:00
syuilo
7e7138c0eb Merge pull request #12011 from misskey-dev/develop
Release: 2023.10.1
2023-10-12 09:21:04 +09:00
syuilo
f964ef163b Merge pull request #11963 from misskey-dev/develop
Release: 2023.10.0
2023-10-10 20:40:13 +09:00
syuilo
0e6cd577cc Merge pull request #11926 from misskey-dev/develop
* fix(backend): Redisに古いMisskeyバージョンのキャッシュが残っている場合の問題を修正

* Update CHANGELOG.md

* enhance(front)end: improve moderation log

* enhance: ノートの翻訳機能の利用可否をロールで設定可能に

Resolve #11923

* 2023.9.3

* 後方互換性の強化

* Update CHANGELOG.md

* fix test

* [ci skip] New Crowdin updates (#11922)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Korean)

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

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Thai)

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

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

* feat: AiScriptでホストのアドレスを参照できる定数 (#11924)

* add HOST_URL

* Update CHANGELOG.md

* tweak

---------

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

---------

Co-authored-by: FineArchs <133759614+FineArchs@users.noreply.github.com>
2023-09-30 09:40:00 +09:00
syuilo
7adc8fcaf5 Merge pull request #11920 from misskey-dev/develop
Release: 2023.9.2
2023-09-29 18:11:30 +09:00
syuilo
e57b536767 Merge pull request #11898 from misskey-dev/develop
2023.9.1
2023-09-25 17:12:28 +09:00
syuilo
f32915b515 Merge pull request #11874 from misskey-dev/develop
Release: 2023.9.0
2023-09-24 18:21:31 +09:00
syuilo
a8d45d4b0d Merge pull request #11384 from misskey-dev/develop
Release: 13.14.2
2023-07-27 13:00:14 +09:00
syuilo
4e24aff408 Merge pull request #11338 from misskey-dev/develop
Release: 13.14.1
2023-07-21 20:40:03 +09:00
syuilo
e64a81aa1d Merge pull request #11301 from misskey-dev/develop
Release: 13.14.0
2023-07-21 20:36:07 +09:00
syuilo
7093662ce5 Merge pull request #10990 from misskey-dev/develop
Release: 13.13.2
2023-06-13 16:46:01 +09:00
syuilo
32c741154d Merge pull request #10961 from misskey-dev/develop
Release: 13.13.1
2023-06-06 11:34:36 +09:00
syuilo
407a965c1d Merge pull request #10932 from misskey-dev/develop
Release: 13.13.0
2023-06-05 19:47:08 +09:00
syuilo
de6348e8a0 Merge pull request #10833 from misskey-dev/develop
* refactor(frontend): use css modules

* feat: 投稿したコンテンツのAIによる学習を軽減するオプションを追加

Resolve #10819

* enhance(backend): publicReactionsをデフォルトtrueに

* 念のためnoimageaiもつける

* add X-Robots-Tag: noai

* Update ja-JP.yml

* fix(frontend): ブラーエフェクトを有効にしている状態で高負荷になる問題を修正

* enhance(backend): graceful shutdown for job queue and refactor

* fix(backend): テスト時は一部のサービスを停止

* fix test

* New Crowdin updates (#10815)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Korean)

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

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

* refactor

* bump

* refactor(frontend): use css module

* refactor(frontend): use css module

* delete unused component

* センシティブワードを正規表現、CWにも適用するように (#10688)

* cwにセンシティブが効いてない

* CWが無いときにTextを見るように

* 比較演算子間違えた

* とりあえずチェック

* 正規表現対応

* /test/giにも対応

* matchでしなくてもいいのでは感

* レビュー修正

* Update packages/backend/src/core/NoteCreateService.ts

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

* Update packages/backend/src/core/NoteCreateService.ts

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

* 修正

* wipかも

* wordsでスペース区切りのものできたかも

* なんか動いたかも

* test作成

* 文言の修正

* 修正

* note参照

---------

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

* Update CHANGELOG.md

* New Crowdin updates (#10823)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* ci: fix typo

* fix(frontend): より明確な説明にしたのとtypo修正

* fix typo

* fix(frontend): カラーバーがリプライには表示されないのを修正

* fix(frontend): チャンネル内の検索ボックスが挙動不審な問題を修正

Fix #10793

* enhance(backend): ノートのハッシュタグもMeilisearchに突っ込むように

今後ハッシュタグ検索とか実装するときのため

* feat(frontend): ユーザー指定ノート検索

* fix(frontend): fix retention chart rendering

* Update about-misskey.vue

* meta: Remove @rinsuki from reviewer-lottery (#10830)

* New Crowdin updates (#10824)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

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

* New translations ja-JP.yml (English)

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

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

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

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

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

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

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (Russian)

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

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Thai)

* enhance(frontend): アカウント初期設定ウィザードにプライバシー設定を追加

* Update CHANGELOG.md

* fix(backend): ひとつのMeilisearchサーバーを複数のMisskeyサーバーで使えない問題を修正

* fix MkUserSetupDialog.Privacy.vue

* ci: skip non-Japanese locale on TurboSnap

* ci: notify on changes for push events

* ci: fix missing branch

* Update basic.cy.js

* [ci skip] New Crowdin updates (#10834)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (German)

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

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

* New translations ja-JP.yml (Arabic)

* 🎨

* 🎨

* enhance(frontend): add retention line chart

* update deps

* refactor

* fix(frontend): Pageにおいて画像ブロックに画像を設定できない問題を修正

Fix #10837

---------

Co-authored-by: nenohi <kimutipartylove@gmail.com>
Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
Co-authored-by: rinsuki <428rinsuki+git@gmail.com>
2023-05-12 12:41:53 +09:00
syuilo
9ad57324db Merge pull request #10814 from misskey-dev/develop
Release: 13.12.1
2023-05-09 15:38:17 +09:00
syuilo
94690c835e Merge pull request #10774 from misskey-dev/develop
Release: 13.12.0
2023-05-09 09:17:34 +09:00
syuilo
c5d2dba28d Merge pull request #10608 from misskey-dev/develop
Release: 13.11.3
2023-04-13 12:18:07 +09:00
syuilo
272e0c874f Merge pull request #10606 from misskey-dev/EbiseLutica-patch-1
Update CHANGELOG.md
2023-04-13 08:35:14 +09:00
Ebise Lutica
d429f810a9 Update CHANGELOG.md 2023-04-13 00:31:22 +09:00
syuilo
75b28d6782 Merge pull request #10578 from misskey-dev/develop
Release: 13.11.2
2023-04-11 15:51:07 +09:00
syuilo
8b1362ab03 Merge pull request #10543 from misskey-dev/develop
Release: 13.11.1
2023-04-09 10:29:36 +09:00
syuilo
a096f621cf Merge pull request #10506 from misskey-dev/develop
13.11.0
2023-04-08 21:27:21 +09:00
syuilo
f54a9542bb Merge pull request #10402 from misskey-dev/develop
Release: 13.10.3
2023-03-25 08:36:41 +09:00
syuilo
a52bbc7c8d Merge pull request #10388 from misskey-dev/develop
Release: 13.10.2
2023-03-22 18:47:10 +09:00
syuilo
59768bdf3f Merge pull request #10383 from misskey-dev/develop
Release: 13.10.1
2023-03-22 16:30:36 +09:00
syuilo
1e67e9c661 Merge pull request #10342 from misskey-dev/develop
Release: 13.10.0
2023-03-22 09:55:38 +09:00
syuilo
ae517a99a7 Merge pull request #10218 from misskey-dev/develop
Release: 13.9.2
2023-03-06 11:54:12 +09:00
syuilo
b23a9b1a88 Merge pull request #10181 from misskey-dev/develop
Release: 13.9.1
2023-03-03 20:56:50 +09:00
syuilo
5bd68aa3e0 Merge pull request #10177 from misskey-dev/develop
Release: 13.9.0
2023-03-03 15:35:40 +09:00
syuilo
647ce174b3 Merge pull request #10112 from misskey-dev/develop
Release: 13.8.1
2023-02-26 20:57:13 +09:00
syuilo
02c8fd9de5 Merge pull request #10108 from misskey-dev/develop
* Add dialog to remove follower (#9718)

* update PULL_REQUEST_TEMPLATE

* 起動時にRedisの疎通確認を行う (#9832)

* 起動時にRedisの疎通確認を行う

* check:connectをstart内に移動

---------

Co-authored-by: tamaina <tamaina@hotmail.co.jp>

* Pass `--detectOpenHandles` to Jest (#9895)

Co-authored-by: tamaina <tamaina@hotmail.co.jp>

* enhance(client): MkUrlPreviewの閉じるボタンを見やすく (#9913)

Co-authored-by: tamaina <tamaina@hotmail.co.jp>

* test(backend): restore ap-request tests (#9997)

Co-authored-by: tamaina <tamaina@hotmail.co.jp>

* fix/refaftor(client): MkTime.vueの変更 (#10061)

* fix(client): MkTime.timeにstringでもDateでない値が入った場合、?を表示

* fix(client): MkTimeを改良

* numberを許容

* falsyな値もとる

* 不明

* ありません

* fix

* fix(server): notes/createで、fileIdsと見つかったファイルの数が異なる場合はエラーにする (#9911)

* fix(server): notes/createで、fileIdsと見つかったファイルの数が異なる場合はエラーにする

* NO_SUCH_FILE

* Update codecov.yml

* Update apple-touch-icon.png

* デプロイされているプレビュー環境がない場合はプレビュー環境を削除しないようにする (#10062)

* デプロイされているプレビュー環境がない場合はDestroy preview environmentを実行しないようにする

* CIがない場合の処理追加

* enhance(client): improve clip menu ux

* 未知のユーザーが deleteActor されたら処理をスキップする (#10067)

* fix(client): Android ChromeでPWAとしてインストールできない問題を修正 (#10069)

* fix(client): Android ChromeでPWAとしてインストールできない問題を修正

* 順番関係ある?

* Windows環境でswcを使うと正常にビルドができない問題の修正 (#10074)

* Update @swc/core to v1.3.36

* Update CHANGELOG.md

* Update CHANGELOG.md

* バックグラウンドで一定時間経過したらページネーションのアイテム更新をしない (#10053)

* 🎨

* feat: 2つの検索画面の統合 (#9949) (#10038)

* feat: 検索画面の UI を統一

* fix: エラーの修正

* add: changelog

---------

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

* enhance(client): ノートメニューからユーザーメニューを開けるように

Resolve #10019

* enhance(client): renoteした際の表示を改善

Resolve #10078

* Update CHANGELOG.md

* enhance(client): tweak contextmenu position calculation

* 🎨

* 🎨

* feat: in-channel featured note

Resolve #9938

* refactor(frontend): fix eslint error (#10084)

* Simplify search.vue (remove dead code) (#10088)

* Simplify search.vue

This is already handled by the code above it, no need to handle it twice

* Remove unused imports

* Update about-misskey.vue

* test(server): add validation test of api:notes/create (#10090)

* fix(server): notes/createのバリデーションが効いていない
Fix #10079

Co-Authored-By: mei23 <m@m544.net>

* anyOf内にバリデーションを書いても最初の一つしかチェックされない

* ✌️

* wip

* wip

* ✌️

* RequiredProp

* Revert "RequiredProp"

This reverts commit 7469390011.

* add api:notes/create

* fix lint

* text

* ✌️

* improve readability

---------

Co-authored-by: mei23 <m@m544.net>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>

* New Crowdin updates (#10059)

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

* New translations ja-JP.yml (Romanian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Slovak)

* New translations ja-JP.yml (Ukrainian)

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

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

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Vietnamese)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Bengali)

* New translations ja-JP.yml (Thai)

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

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

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

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Ukrainian)

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

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (Ukrainian)

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

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

* New translations ja-JP.yml (Thai)

* New translations ja-JP.yml (Thai)

* New translations ja-JP.yml (Thai)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Spanish)

* enhance(client): improve user menu ux

* enhance(client): photoswipe 表示時に戻る操作をしても前の画面に戻らないように (#10098)

* enhance(client): photoswipe 表示時に戻る操作をしても前の画面に戻らないように

* add: changelog

---------

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

* enhance(client): メニューの「もっと」からインスタンス情報を見れるように

* [Fix] fixed an typo in error message (#10102)

* Update codecov.yml

* Update CHANGELOG.md

* fix(server): エラーのスタックトレースは返さないように

Fix #10064

* [chore]Editorconfig: ymlに加えてyamlファイルに対しても同じ規約を適用する (#10081)

* Added yaml file in addition to yml file, in editorconfig

* Applied editorconfig for pnpm-workspace.yaml

---------

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

* update deps

* ホームタイムラインの読み込みでクエリタイムアウトになるのを修正する (#10106)

* refactor

* New translations ja-JP.yml (French) (#10103)

* Update CHANGELOG.md

* 13.8.0

---------

Co-authored-by: atsuchan <83960488+atsu1125@users.noreply.github.com>
Co-authored-by: Masaya Suzuki <15100604+massongit@users.noreply.github.com>
Co-authored-by: tamaina <tamaina@hotmail.co.jp>
Co-authored-by: Kagami Sascha Rosylight <saschanaz@outlook.com>
Co-authored-by: taiy <53635909+taiyme@users.noreply.github.com>
Co-authored-by: xianon <xianon@hotmail.co.jp>
Co-authored-by: kabo2468 <28654659+kabo2468@users.noreply.github.com>
Co-authored-by: YS <47836716+yszkst@users.noreply.github.com>
Co-authored-by: Khsmty <me@khsmty.com>
Co-authored-by: Soni L <EnderMoneyMod@gmail.com>
Co-authored-by: mei23 <m@m544.net>
Co-authored-by: daima3629 <52790780+daima3629@users.noreply.github.com>
Co-authored-by: Windymelt <1113940+windymelt@users.noreply.github.com>
2023-02-26 20:21:54 +09:00
syuilo
1ba49b614d Merge pull request #10058 from misskey-dev/develop
Release: 13.7.5
2023-02-24 13:06:55 +09:00
tamaina
40de14415c Release: 13.7.4
Merge pull request #10050 from misskey-dev/develop
2023-02-23 23:11:25 +09:00
tamaina
7c9330a02f Release: 13.7.3
Merge pull request #10048 from misskey-dev/develop
2023-02-23 22:15:56 +09:00
473 changed files with 18698 additions and 28974 deletions

View File

@@ -38,7 +38,7 @@
# Option 3: If neither of the above applies to you. # Option 3: If neither of the above applies to you.
# (In this case, the source code should be published # (In this case, the source code should be published
# on the Misskey interface. IT IS NOT ENOUGH TO # on the Misskey interface. IT IS NOT ENOUGH TO
# DISCLOSE THE SOURCE CODE WHEN A USER REQUESTS IT BY # DISCLOSE THE SOURCE CODE WEHN A USER REQUESTS IT BY
# E-MAIL OR OTHER MEANS. If you are not satisfied # E-MAIL OR OTHER MEANS. If you are not satisfied
# with this, it is recommended that you read the # with this, it is recommended that you read the
# license again carefully. Anyway, enabling this # license again carefully. Anyway, enabling this

View File

@@ -8,7 +8,7 @@
"version": "8.9.2" "version": "8.9.2"
}, },
"ghcr.io/devcontainers/features/node:1": { "ghcr.io/devcontainers/features/node:1": {
"version": "20.12.2" "version": "20.10.0"
} }
}, },
"forwardPorts": [3000], "forwardPorts": [3000],
@@ -19,6 +19,7 @@
"editorconfig.editorconfig", "editorconfig.editorconfig",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"Vue.volar", "Vue.volar",
"Vue.vscode-typescript-vue-plugin",
"Orta.vscode-jest", "Orta.vscode-jest",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"mrmlnc.vscode-json5" "mrmlnc.vscode-json5"

View File

@@ -5,28 +5,29 @@ on:
branches: branches:
- master - master
- develop - develop
- improve-misskey-js-autogen-check
paths: paths:
- packages/backend/** - packages/backend/**
jobs: jobs:
# pull_request_target safety: permissions: read-all, and there are no secrets used in this job check-misskey-js-autogen:
generate-misskey-js:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read pull-requests: write
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
env:
api_json_name: "api-head.json"
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v4.1.1 uses: actions/checkout@v4.1.1
with: with:
submodules: true submodules: true
ref: refs/pull/${{ github.event.pull_request.number }}/merge ref: ${{ github.event.pull_request.head.sha }}
- name: setup pnpm - name: setup pnpm
uses: pnpm/action-setup@v3 uses: pnpm/action-setup@v3
with: with:
version: 9 version: 8
- name: setup node - name: setup node
id: setup-node id: setup-node
@@ -38,81 +39,79 @@ jobs:
- name: install dependencies - name: install dependencies
run: pnpm i --frozen-lockfile run: pnpm i --frozen-lockfile
# generate api.json - name: wait get-api-diff
- name: Copy Config uses: lewagon/wait-on-check-action@v1.3.3
run: cp .config/example.yml .config/default.yml with:
- name: Build ref: ${{ github.event.pull_request.head.sha }}
run: pnpm build check-regexp: get-from-misskey .+
- name: Generate API JSON repo-token: ${{ secrets.GITHUB_TOKEN }}
run: pnpm --filter backend generate-api-json wait-interval: 30
# build misskey js - name: Download artifact
- name: Build misskey-js uses: actions/github-script@v7.0.1
with:
script: |
const fs = require('fs');
const workflows = await github.rest.actions.listWorkflowRunsForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
head_sha: `${{ github.event.pull_request.head.sha }}`
}).then(x => x.data.workflow_runs);
console.log(workflows.map(x => ({name: x.name, title: x.display_title})));
const run_id = workflows.find(x => x.name.includes("Get api.json from Misskey")).id;
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: run_id,
});
let matchArtifacts = allArtifacts.data.artifacts.filter((artifact) => {
return artifact.name.startsWith("api-artifact-") || artifact.name == "api-artifact"
});
await Promise.all(matchArtifacts.map(async (artifact) => {
let download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: artifact.id,
archive_format: 'zip',
});
await fs.promises.writeFile(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data));
}));
- name: unzip artifacts
run: |- run: |-
cp packages/backend/built/api.json packages/misskey-js/generator/api.json find . -mindepth 1 -maxdepth 1 -type f -name '*.zip' -exec unzip {} -d . ';'
pnpm run --filter misskey-js-type-generator generate ls -la
# packages/misskey-js/generator/built/autogen - name: get head checksum
- name: Upload Generated run: |-
uses: actions/upload-artifact@v4 checksum=$(realpath head_checksum)
with:
name: generated-misskey-js
path: packages/misskey-js/generator/built/autogen
# pull_request_target safety: permissions: read-all, and there are no secrets used in this job cd packages/misskey-js/src
get-actual-misskey-js: find autogen -type f -exec sh -c 'echo $(sed -E "s/^\s+\*\s+generatedAt:.+$//" {} | sha256sum | cut -d" " -f 1) {}' \; > $checksum
runs-on: ubuntu-latest cd ../../..
permissions:
contents: read
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
steps:
- name: checkout
uses: actions/checkout@v4.1.1
with:
submodules: true
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- name: Upload From Merged - name: build autogen
uses: actions/upload-artifact@v4 run: |-
with: checksum=$(realpath ${api_json_name}_checksum)
name: actual-misskey-js mv $api_json_name packages/misskey-js/generator/api.json
path: packages/misskey-js/src/autogen
# pull_request_target safety: nothing is cloned from repository cd packages/misskey-js/generator
comment-misskey-js-autogen: pnpm run generate
runs-on: ubuntu-latest cd built
needs: [generate-misskey-js, get-actual-misskey-js] find autogen -type f -exec sh -c 'echo $(sed -E "s/^\s+\*\s+generatedAt:.+$//" {} | sha256sum | cut -d" " -f 1) {}' \; > $checksum
permissions: cd ../../../..
pull-requests: write
steps:
- name: download generated-misskey-js
uses: actions/download-artifact@v4
with:
name: generated-misskey-js
path: misskey-js-generated
- name: download actual-misskey-js - name: check update for type definitions
uses: actions/download-artifact@v4 run: diff head_checksum ${api_json_name}_checksum
with:
name: actual-misskey-js
path: misskey-js-actual
- name: check misskey-js changes
id: check-changes
run: |
diff -r -u --label=generated --label=on-tree ./misskey-js-generated ./misskey-js-actual > misskey-js.diff || true
if [ -s misskey-js.diff ]; then
echo "changes=true" >> $GITHUB_OUTPUT
else
echo "changes=false" >> $GITHUB_OUTPUT
fi
- name: Print full diff
run: cat ./misskey-js.diff
- name: send message - name: send message
if: steps.check-changes.outputs.changes == 'true' if: failure()
uses: thollander/actions-comment-pull-request@v2 uses: thollander/actions-comment-pull-request@v2
with: with:
comment_tag: check-misskey-js-autogen comment_tag: check-misskey-js-autogen
@@ -126,7 +125,7 @@ jobs:
``` ```
- name: send message - name: send message
if: steps.check-changes.outputs.changes == 'false' if: success()
uses: thollander/actions-comment-pull-request@v2 uses: thollander/actions-comment-pull-request@v2
with: with:
comment_tag: check-misskey-js-autogen comment_tag: check-misskey-js-autogen

View File

@@ -1,75 +0,0 @@
name: Check SPDX-License-Identifier
on:
push:
branches:
- master
- develop
pull_request:
jobs:
check-spdx-license-id:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4.1.1
- name: Check
run: |
counter=0
search() {
local directory="$1"
find "$directory" -type f \
'(' \
-name "*.cjs" -and -not -name '*.config.cjs' -o \
-name "*.html" -o \
-name "*.js" -and -not -name '*.config.js' -o \
-name "*.mjs" -and -not -name '*.config.mjs' -o \
-name "*.scss" -o \
-name "*.ts" -and -not -name '*.config.ts' -o \
-name "*.vue" \
')' -and \
-not -name '*eslint*'
}
check() {
local file="$1"
if ! (
grep -q "SPDX-FileCopyrightText: syuilo and misskey-project" "$file" ||
grep -q "SPDX-License-Identifier: AGPL-3.0-only" "$file"
); then
echo "Missing: $file"
((counter++))
fi
}
directories=(
"cypress/e2e"
"packages/backend/migration"
"packages/backend/src"
"packages/backend/test"
"packages/frontend/.storybook"
"packages/frontend/@types"
"packages/frontend/lib"
"packages/frontend/public"
"packages/frontend/src"
"packages/frontend/test"
"packages/misskey-bubble-game/src"
"packages/misskey-reversi/src"
"packages/sw/src"
"scripts"
)
for directory in "${directories[@]}"; do
for file in $(search $directory); do
check "$file"
done
done
if [ $counter -gt 0 ]; then
echo "SPDX-License-Identifier is missing in $counter files."
exit 1
else
echo "SPDX-License-Identifier is certainly described in all target files!"
exit 0
fi

View File

@@ -50,9 +50,12 @@ jobs:
- name: Get PR ref - name: Get PR ref
id: get-ref id: get-ref
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
PR_REF="refs/pull/${{ github.event.issue.number }}/head" PR_NUMBER=$(jq --raw-output .issue.number $GITHUB_EVENT_PATH)
echo "pr-ref=$PR_REF" >> $GITHUB_OUTPUT PR_REF=$(gh pr view $PR_NUMBER --json headRefName -q '.headRefName')
echo "pr-ref=$PR_REF" > $GITHUB_OUTPUT
- name: Extract wait time - name: Extract wait time
id: get-wait-time id: get-wait-time

View File

@@ -18,7 +18,7 @@ jobs:
strategy: strategy:
matrix: matrix:
node-version: [20.12.2] node-version: [20.10.0]
api-json-name: [api-base.json, api-head.json] api-json-name: [api-base.json, api-head.json]
include: include:
- api-json-name: api-base.json - api-json-name: api-base.json
@@ -34,7 +34,7 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v3 uses: pnpm/action-setup@v3
with: with:
version: 9 version: 8
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.2 uses: actions/setup-node@v4.0.2

View File

@@ -29,7 +29,7 @@ jobs:
submodules: true submodules: true
- uses: pnpm/action-setup@v3 - uses: pnpm/action-setup@v3
with: with:
version: 9 version: 8
run_install: false run_install: false
- uses: actions/setup-node@v4.0.2 - uses: actions/setup-node@v4.0.2
with: with:
@@ -56,7 +56,7 @@ jobs:
submodules: true submodules: true
- uses: pnpm/action-setup@v3 - uses: pnpm/action-setup@v3
with: with:
version: 9 version: 7
run_install: false run_install: false
- uses: actions/setup-node@v4.0.2 - uses: actions/setup-node@v4.0.2
with: with:
@@ -82,7 +82,7 @@ jobs:
submodules: true submodules: true
- uses: pnpm/action-setup@v3 - uses: pnpm/action-setup@v3
with: with:
version: 9 version: 7
run_install: false run_install: false
- uses: actions/setup-node@v4.0.2 - uses: actions/setup-node@v4.0.2
with: with:
@@ -92,6 +92,6 @@ jobs:
- run: pnpm i --frozen-lockfile - run: pnpm i --frozen-lockfile
- run: pnpm --filter misskey-js run build - run: pnpm --filter misskey-js run build
if: ${{ matrix.workspace == 'backend' }} if: ${{ matrix.workspace == 'backend' }}
- run: pnpm --filter misskey-reversi run build - run: pnpm --filter misskey-reversi run build:tsc
if: ${{ matrix.workspace == 'backend' }} if: ${{ matrix.workspace == 'backend' }}
- run: pnpm --filter ${{ matrix.workspace }} run typecheck - run: pnpm --filter ${{ matrix.workspace }} run typecheck

View File

@@ -17,7 +17,7 @@ jobs:
strategy: strategy:
matrix: matrix:
node-version: [20.12.2] node-version: [20.10.0]
steps: steps:
- uses: actions/checkout@v4.1.1 - uses: actions/checkout@v4.1.1
@@ -26,7 +26,7 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v3 uses: pnpm/action-setup@v3
with: with:
version: 9 version: 8
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.2 uses: actions/setup-node@v4.0.2

View File

@@ -1,40 +0,0 @@
name: "Release Manager: sync changelog with PR"
on:
push:
branches:
- release/**
paths:
- 'CHANGELOG.md'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
contents: write
issues: write
pull-requests: write
jobs:
edit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# headがrelease/かつopenのPRを1つ取得
- name: Get PR
run: |
echo "pr_number=$(gh pr list --limit 1 --head "${{ github.ref_name }}" --json number --jq '.[] | .number')" >> $GITHUB_OUTPUT
id: get_pr
- name: Get target version
uses: misskey-dev/release-manager-actions/.github/actions/get-target-version@v1
id: v
# CHANGELOG.mdの内容を取得
- name: Get changelog
uses: misskey-dev/release-manager-actions/.github/actions/get-changelog@v1
with:
version: ${{ steps.v.outputs.target_version }}
id: changelog
# PRのnotesを更新
- name: Update PR
run: |
gh pr edit ${{ steps.get_pr.outputs.pr_number }} --body "${{ steps.changelog.outputs.changelog }}"

View File

@@ -1,122 +0,0 @@
name: "Release Manager [Dispatch]"
on:
workflow_dispatch:
inputs:
## Specify the type of the next release.
#version_increment_type:
# type: choice
# description: 'VERSION INCREMENT TYPE'
# default: 'patch'
# required: false
# options:
# - 'major'
# - 'minor'
# - 'patch'
merge:
type: boolean
description: 'MERGE RELEASE BRANCH TO MAIN'
default: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
contents: write
issues: write
pull-requests: write
jobs:
get-pr:
runs-on: ubuntu-latest
outputs:
pr_number: ${{ steps.get_pr.outputs.pr_number }}
steps:
- uses: actions/checkout@v4
# headがrelease/かつopenのPRを1つ取得
- name: Get PRs
run: |
echo "pr_number=$(gh pr list --limit 1 --search "head:release/ is:open" --json number --jq '.[] | .number')" >> $GITHUB_OUTPUT
id: get_pr
merge:
uses: misskey-dev/release-manager-actions/.github/workflows/merge.yml@v1
needs: get-pr
if: ${{ needs.get-pr.outputs.pr_number != '' && inputs.merge == true }}
with:
pr_number: ${{ needs.get-pr.outputs.pr_number }}
package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }}
# Text to prepend to the changelog
# The first line must be `## Unreleased`
changes_template: |
## Unreleased
### General
-
### Client
-
### Server
-
use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
secrets:
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
RULESET_EDIT_APP_ID: ${{ secrets.RULESET_EDIT_APP_ID }}
RULESET_EDIT_APP_PRIVATE_KEY: ${{ secrets.RULESET_EDIT_APP_PRIVATE_KEY }}
create-prerelease:
uses: misskey-dev/release-manager-actions/.github/workflows/create-prerelease.yml@v1
needs: get-pr
if: ${{ needs.get-pr.outputs.pr_number != '' && inputs.merge != true }}
with:
pr_number: ${{ needs.get-pr.outputs.pr_number }}
package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }}
use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
secrets:
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
create-target:
uses: misskey-dev/release-manager-actions/.github/workflows/create-target.yml@v1
needs: get-pr
if: ${{ needs.get-pr.outputs.pr_number == '' }}
with:
# The script for version increment.
# process.env.CURRENT_VERSION: The current version.
#
# Misskey calender versioning (yyyy.MM.patch) example
version_increment_script: |
const now = new Date();
const year = now.toLocaleDateString('en-US', { year: 'numeric', timeZone: 'Asia/Tokyo' });
const month = now.toLocaleDateString('en-US', { month: 'numeric', timeZone: 'Asia/Tokyo' });
const [major, minor, _patch] = process.env.CURRENT_VERSION.split('.');
const patch = Number(_patch.split('-')[0]);
if (Number.isNaN(patch)) {
console.error('Invalid patch version', year, month, process.env.CURRENT_VERSION, major, minor, _patch);
throw new Error('Invalid patch version');
}
if (year !== major || month !== minor) {
return `${year}.${month}.0`;
} else {
return `${major}.${minor}.${patch + 1}`;
}
##Semver example
#version_increment_script: |
# const [major, minor, patch] = process.env.CURRENT_VERSION.split('.');
# if ("${{ inputs.version_increment_type }}" === "major") {
# return `${Number(major) + 1}.0.0`;
# } else if ("${{ inputs.version_increment_type }}" === "minor") {
# return `${major}.${Number(minor) + 1}.0`;
# } else {
# return `${major}.${minor}.${Number(patch) + 1}`;
# }
package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }}
use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
secrets:
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
RULESET_EDIT_APP_ID: ${{ secrets.RULESET_EDIT_APP_ID }}
RULESET_EDIT_APP_PRIVATE_KEY: ${{ secrets.RULESET_EDIT_APP_PRIVATE_KEY }}

View File

@@ -1,38 +0,0 @@
name: "Release Manager: release RC when ready for review"
on:
pull_request:
types: [ready_for_review]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
contents: write
issues: write
pull-requests: write
jobs:
check:
runs-on: ubuntu-latest
outputs:
ref: ${{ steps.get_pr.outputs.ref }}
steps:
- uses: actions/checkout@v4
# PR情報を取得
- name: Get PR
run: |
pr_json=$(gh pr view ${{ github.event.pull_request.number }} --json isDraft,headRefName)
echo "ref=$(echo $pr_json | jq -r '.headRefName')" >> $GITHUB_OUTPUT
id: get_pr
release:
uses: misskey-dev/release-manager-actions/.github/workflows/create-prerelease.yml@v1
needs: check
if: startsWith(needs.check.outputs.ref, 'release/')
with:
pr_number: ${{ github.event.pull_request.number }}
package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }}
use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
secrets:
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}

View File

@@ -36,7 +36,7 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v3 uses: pnpm/action-setup@v3
with: with:
version: 9 version: 8
run_install: false run_install: false
- name: Use Node.js 20.x - name: Use Node.js 20.x
uses: actions/setup-node@v4.0.2 uses: actions/setup-node@v4.0.2
@@ -87,13 +87,12 @@ jobs:
if [ "$CHROMATIC_PARAMETER" = " --skip" ]; then if [ "$CHROMATIC_PARAMETER" = " --skip" ]; then
echo "skip=true" >> $GITHUB_OUTPUT echo "skip=true" >> $GITHUB_OUTPUT
fi fi
BRANCH="${{ github.event.pull_request.head.user.login }}:$HEAD_REF" BRANCH="${{ github.event.pull_request.head.user.login }}:${{ github.event.pull_request.head.ref }}"
if [ "$BRANCH" = "misskey-dev:$HEAD_REF" ]; then if [ "$BRANCH" = "misskey-dev:${{ github.event.pull_request.head.ref }}" ]; then
BRANCH="$HEAD_REF" BRANCH="${{ github.event.pull_request.head.ref }}"
fi fi
pnpm --filter frontend chromatic --exit-once-uploaded -d storybook-static --branch-name $BRANCH $(echo "$CHROMATIC_PARAMETER") pnpm --filter frontend chromatic --exit-once-uploaded -d storybook-static --branch-name $BRANCH $(echo "$CHROMATIC_PARAMETER")
env: env:
HEAD_REF: ${{ github.event.pull_request.head.ref }}
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
- name: Notify that Chromatic detects changes - name: Notify that Chromatic detects changes
uses: actions/github-script@v7.0.1 uses: actions/github-script@v7.0.1

View File

@@ -21,7 +21,7 @@ jobs:
strategy: strategy:
matrix: matrix:
node-version: [20.12.2] node-version: [20.10.0]
services: services:
postgres: postgres:
@@ -43,10 +43,8 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v3 uses: pnpm/action-setup@v3
with: with:
version: 9 version: 8
run_install: false run_install: false
- name: Install FFmpeg
uses: FedericoCarboni/setup-ffmpeg@v3
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.2 uses: actions/setup-node@v4.0.2
with: with:
@@ -73,7 +71,7 @@ jobs:
strategy: strategy:
matrix: matrix:
node-version: [20.12.2] node-version: [20.10.0]
services: services:
postgres: postgres:
@@ -95,7 +93,7 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v3 uses: pnpm/action-setup@v3
with: with:
version: 9 version: 8
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.2 uses: actions/setup-node@v4.0.2

View File

@@ -26,7 +26,7 @@ jobs:
strategy: strategy:
matrix: matrix:
node-version: [20.12.2] node-version: [20.10.0]
steps: steps:
- uses: actions/checkout@v4.1.1 - uses: actions/checkout@v4.1.1
@@ -35,7 +35,7 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v3 uses: pnpm/action-setup@v3
with: with:
version: 9 version: 8
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.2 uses: actions/setup-node@v4.0.2
@@ -64,7 +64,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
node-version: [20.12.2] node-version: [20.10.0]
browser: [chrome] browser: [chrome]
services: services:
@@ -93,7 +93,7 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v3 uses: pnpm/action-setup@v3
with: with:
version: 9 version: 7
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.2 uses: actions/setup-node@v4.0.2

View File

@@ -20,7 +20,7 @@ jobs:
strategy: strategy:
matrix: matrix:
node-version: [20.12.2] node-version: [20.10.0]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/ # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps: steps:

View File

@@ -16,7 +16,7 @@ jobs:
strategy: strategy:
matrix: matrix:
node-version: [20.12.2] node-version: [20.10.0]
steps: steps:
- uses: actions/checkout@v4.1.1 - uses: actions/checkout@v4.1.1
@@ -25,7 +25,7 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v3 uses: pnpm/action-setup@v3
with: with:
version: 9 version: 8
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.2 uses: actions/setup-node@v4.0.2

View File

@@ -17,7 +17,7 @@ jobs:
strategy: strategy:
matrix: matrix:
node-version: [20.12.2] node-version: [20.10.0]
steps: steps:
- uses: actions/checkout@v4.1.1 - uses: actions/checkout@v4.1.1
@@ -26,7 +26,7 @@ jobs:
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v3 uses: pnpm/action-setup@v3
with: with:
version: 9 version: 8
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.2 uses: actions/setup-node@v4.0.2

View File

@@ -1 +1 @@
20.12.2 20.10.0

View File

@@ -3,7 +3,9 @@
"editorconfig.editorconfig", "editorconfig.editorconfig",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"Vue.volar", "Vue.volar",
"Vue.vscode-typescript-vue-plugin",
"Orta.vscode-jest", "Orta.vscode-jest",
"dbaeumer.vscode-eslint",
"mrmlnc.vscode-json5" "mrmlnc.vscode-json5"
] ]
} }

View File

@@ -7,7 +7,7 @@
"*.test.ts": "typescript" "*.test.ts": "typescript"
}, },
"jest.jestCommandLine": "pnpm run jest", "jest.jestCommandLine": "pnpm run jest",
"jest.runMode": "on-demand", "jest.autoRun": "off",
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll": "explicit" "source.fixAll": "explicit"
}, },

View File

@@ -1,137 +1,16 @@
## 2024.5.0 <!--
## 202x.x.x (unreleased)
### Note
- コントロールパネル内にあるサマリープロキシの設定個所がセキュリティから全般へ変更となります。
- 悪意のある第三者がリモートユーザーになりすましたアクティビティを受け取れてしまう問題を修正しました。詳しくは[GitHub security advisory](https://github.com/misskey-dev/misskey/security/advisories/GHSA-2vxv-pv3m-3wvj)をご覧ください。
### General
- Enhance: URLプレビューの有効化・無効化を設定できるように #13569
- Enhance: アンテナでBotによるートを除外できるように
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/545)
- Enhance: クリップのノート数を表示するように
- Enhance: コンディショナルロールの条件として以下を新たに追加 (#13667)
- 猫ユーザーか
- botユーザーか
- サスペンド済みユーザーか
- 鍵アカウントユーザーか
- 「アカウントを見つけやすくする」が有効なユーザーか
- Fix: Play作成時に設定した公開範囲が機能していない問題を修正
- Fix: 正規化されていない状態のhashtagが連合されてきたhtmlに含まれているとhashtagが正しくhashtagに復元されない問題を修正
### Client
- Feat: アップロードするファイルの名前をランダム文字列にできるように
- Enhance: 自分のノートの添付ファイルから直接ファイルの詳細ページに飛べるように
- Enhance: 広告がMisskeyと同一ドメインの場合はRouterで遷移するように
- Enhance: リアクション・いいねの総数を表示するように
- Enhance: リアクション受け入れが「いいねのみ」の場合はリアクション絵文字一覧を表示しないように
- Enhance: 設定>プラグインのページからプラグインの簡易的なログやエラーを見られるように
- 実装の都合により、プラグインは1つエラーを起こした時に即時停止するようになりました
- Enhance: ページのデザインを変更
- Enhance: 2要素認証ワンタイムパスワードの入力欄を改善
- Enhance: 「今日誕生日のフォロー中ユーザー」ウィジェットを手動でリロードできるように
- Enhance: 映像・音声の再生にブラウザのネイティブプレイヤーを使用できるように
- Enhance: 映像・音声の再生メニューに「再生速度」「ループ再生」「ピクチャインピクチャ」を追加
- Enhance: 映像・音声の再生にキーボードショートカットが使えるように
- Enhance: ノートについているリアクションの「もっと!」から、リアクションの一覧を表示できるように
- Enhance: リプライにて引用がある場合テキストが空でもノートできるように
- 引用したいートのURLをコピーしリプライ投稿画面にペーストして添付することで達成できます
- Enhance: フォローするかどうかの確認ダイアログを出せるように
- Enhance: Playを手動でリロードできるように
- Enhance: 通報のコメント内のリンクをクリックした際、ウィンドウで開くように
- Enhance: `Ui:C:postForm` および `Ui:C:postFormButton``localOnly``visibility` を設定できるように
- Enhance: AiScriptを0.18.0にバージョンアップ
- Fix: 一部のページ内リンクが正しく動作しない問題を修正
- Fix: 周年の実績が閏年を考慮しない問題を修正
- Fix: ローカルURLのプレビューポップアップが左上に表示される
- Fix: WebGL2をサポートしないブラウザで「季節に応じた画面の演出」が有効になっているとき、Misskeyが起動できなくなる問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/459)
- Fix: ページタイトルでローカルユーザーとリモートユーザーの区別がつかない問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/528)
- Fix: コードブロックのシンタックスハイライトで使用される定義ファイルをCDNから取得するように #13177
- CDNから取得せずMisskey本体にバンドルする場合は`pacakges/frontend/vite.config.ts`を修正してください。
- Fix: タイムゾーンによっては、「今日誕生日のフォロー中ユーザー」ウィジェットが正しく動作しない問題を修正
- Fix: CWのみの引用リートが詳細ページで純粋なリートとして誤って扱われてしまう問題を修正
- Fix: ート詳細ページにおいてCW付き引用リートのCWボタンのラベルに「引用」が含まれていない問題を修正
- Fix: ダイアログの入力で字数制限に違反していてもEnterキーが押せてしまう問題を修正
- Fix: ダイレクト投稿の宛先が保存されない問題を修正
- Fix: Playのページを離れたときに、Playが正常に初期化されない問題を修正
- Fix: ページのOGP URLが間違っているのを修正
- Fix: リバーシの対局を正しく共有できないことがある問題を修正
- Fix: 通知をグループ化している際に、人数が正常に表示されないことがある問題を修正
- Fix: 連合なしの状態の読み書きができない問題を修正
### Server
- Enhance: エンドポイント`antennas/update`の必須項目を`antennaId`のみに
- Enhance: misskey-dev/summaly@5.1.0の取り込み(プレビュー生成処理の効率化)
- Enhance: ドライブのファイルがNSFWかどうか個別に連合されるように (#13756)
- 可能な場合、ノートの添付ファイルのセンシティブ判定がファイル単位になります
- Fix: リモートから配送されたアクティビティにJSON-LD compactionをかける
- Fix: フォローリクエストを作成する際に既存のものは削除するように
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/440)
- Fix: エンドポイント`notes/translate`のエラーを改善
- Fix: CleanRemoteFilesProcessorService report progress from 100% (#13632)
- Fix: 一部の音声ファイルが映像ファイルとして扱われる問題を修正
- Fix: リプライのみの引用リートと、CWのみの引用リートが純粋なリートとして誤って扱われてしまう問題を修正
- Fix: 登録にメール認証が必須になっている場合、登録されているメールアドレスを削除できないように
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/606)
- Fix: Add Cache-Control to Bull Board
- Fix: nginx経由で/files/にRangeリクエストされた場合に正しく応答できないのを修正
- Fix: 一部のタイムラインのストリーミングでインスタンスミュートが効かない問題を修正
- Fix: グローバルタイムラインで返信が表示されないことがある問題を修正
- Fix: リノートをミュートしたユーザの投稿のリノートがミュートされる問題を修正
- Fix: AP Link等は添付ファイル扱いしないようになど (#13754)
## 2024.3.1
### General ### General
- -
### Client ### Client
- Fix: 絵文字関係の不具合を修正 (#13485) -
- 履歴に残っている or ピン留めされた絵文字がコントロールパネルより削除されていた際にリアクションデッキが表示できなくなる
- Unicode絵文字が履歴に残っている or ピン留めされているとリアクションデッキが表示できなくなる
- Fix: カスタム絵文字の画像読み込みに失敗した際はテキストではなくダミー画像を表示 #13487
### Server ### Server
- -
## 2024.3.0 -->
### General
- Enhance: 投稿者のロールに応じて、一つのノートに含むことのできるメンションとダイレクト投稿の宛先の人数に上限を設定できるように
* デフォルトのメンション上限は20アカウントに設定されます。管理者はベースロールの設定で変更可能です。
* 連合の問い合わせに応答しないサーバーのリモートユーザーへのメンションは、上限の人数に含めない実装になっています。
- Enhance: 通知がミュート、凍結を考慮するようになりました
- Enhance: サーバーごとにモデレーションノートを残せるように
- Enhance: コンディショナルロールの条件に「マニュアルロールへのアサイン」を追加
- Enhance: 通知の受信設定に「フォロー中またはフォロワー」を追加
- Enhance: 通知の履歴をリセットできるように
- Fix: ダイレクトなノートに対してはダイレクトでしか返信できないように
### Client
- Enhance: ノート作成画面のファイル添付メニューの区切り線の位置を調整
- Fix: syuilo/misskeyの時代からあるインスタンスが改変されたバージョンであると誤認識される問題
- Fix: MFMのオートコンプリートが出るべき状況で出ないことがある問題を修正
- Fix: チャートのラベルが消えている問題を修正
- Fix: 画面表示後最初の音声再生が爆音になることがある問題を修正
- Fix: 設定のバックアップ作成時に名前を入力しなかった場合、ローカライゼーションがおかしくなる問題を修正
- Fix: ページ`/admin/emojis`の絵文字編集ダイアログで「リアクションとして使えるロール」を追加する際に何も選択せずOKを押下すると画面が固まる問題を修正
- Fix: 絵文字サジェストの順位で、絵文字自体の名前が同じものよりもタグで一致しているものが優先されてしまう問題を修正
- Fix: ユーザの情報のポップアップが消えなくなることがある問題を修正
### Server
- Enhance: エンドポイント`flash/update``flashId`以外のパラメータは必須ではなくなりました
- Fix: nodeinfoにenableMcaptchaとenableTurnstileが無いのを修正
- Fix: 破損した通知をクライアントに送信しないように
* 通知欄が無限にリロードされる問題が改善する可能性があります
- Fix: 禁止キーワードを含むートがDelayed Queueに追加されて再処理される問題を修正
- Fix: 自分がフォローしていないアカウントのフォロワー限定ノートが閲覧できることがある問題を修正
- Fix: タイムラインのオプションで「リノートを表示」を無効にしている際、投票のみの引用リノートが流れてこない問題を修正
- Fix: エンドポイント`admin/emoji/update`の各種修正
- 必須パラメータを`id`または`name`のいずれかのみに
- `id`の代わりに`name`で絵文字を指定可能に(`id``name`両指定時は従来通り`name`を変更する挙動)
- `category`および`licence`が指定なしの時勝手にnullに上書きされる挙動を修正
- Fix: 通知の受信設定で「相互フォロー」が正しく動作しない問題を修正
## 2024.2.0 ## 2024.2.0

View File

@@ -316,98 +316,6 @@ export const handlers = [
Don't forget to re-run the `.storybook/generate.js` script after adding, editing, or removing the above files. Don't forget to re-run the `.storybook/generate.js` script after adding, editing, or removing the above files.
## Nest
### Nest Service Circular dependency / Nestでサービスの循環参照でエラーが起きた場合
#### forwardRef
まずは簡単に`forwardRef`を試してみる
```typescript
export class FooService {
constructor(
@Inject(forwardRef(() => BarService))
private barService: BarService
) {
}
}
```
#### OnModuleInit
できなければ`OnModuleInit`を使う
```typescript
import { Injectable, OnModuleInit } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import { BarService } from '@/core/BarService';
@Injectable()
export class FooService implements OnModuleInit {
private barService: BarService // constructorから移動してくる
constructor(
private moduleRef: ModuleRef,
) {
}
async onModuleInit() {
this.barService = this.moduleRef.get(BarService.name);
}
public async niceMethod() {
return await this.barService.incredibleMethod({ hoge: 'fuga' });
}
}
```
##### Service Unit Test
テストで`onModuleInit`を呼び出す必要がある
```typescript
// import ...
describe('test', () => {
let app: TestingModule;
let fooService: FooService; // for test case
let barService: BarService; // for test case
beforeEach(async () => {
app = await Test.createTestingModule({
imports: ...,
providers: [
FooService,
{ // mockする (mockは必須ではないかもしれない)
provide: BarService,
useFactory: () => ({
incredibleMethod: jest.fn(),
}),
},
{ // Provideにする
provide: BarService.name,
useExisting: BarService,
},
],
})
.useMocker(...
.compile();
fooService = app.get<FooService>(FooService);
barService = app.get<BarService>(BarService) as jest.Mocked<BarService>;
// onModuleInitを実行する
await fooService.onModuleInit();
});
test('nice', () => {
await fooService.niceMethod();
expect(barService.incredibleMethod).toHaveBeenCalled();
expect(barService.incredibleMethod.mock.lastCall![0])
.toEqual({ hoge: 'fuga' });
});
})
```
## Notes ## Notes
### Misskeyのドメイン固有の概念は`Mi`をprefixする ### Misskeyのドメイン固有の概念は`Mi`をprefixする

View File

@@ -1,6 +1,6 @@
# syntax = docker/dockerfile:1.4 # syntax = docker/dockerfile:1.4
ARG NODE_VERSION=20.12.2-bullseye ARG NODE_VERSION=20.10.0-bullseye
# build assets & compile TypeScript # build assets & compile TypeScript

View File

@@ -1,11 +1,9 @@
<div align="center"> <div align="center">
<a href="https://misskey-hub.net"> <a href="https://misskey-hub.net">
<img src="./assets/title_float.svg" alt="Misskey logo" style="border-radius:50%" width="300"/> <img src="./assets/title_float.svg" alt="Misskey logo" style="border-radius:50%" width="400"/>
</a> </a>
**🌎 **Misskey** is an open source, federated social media platform that's free forever! 🚀** **🌎 **[Misskey](https://misskey-hub.net/)** is an open source, decentralized social media platform that's free forever! 🚀**
[Learn more](https://misskey-hub.net/)
--- ---
@@ -24,6 +22,41 @@
<a href="https://www.patreon.com/syuilo"> <a href="https://www.patreon.com/syuilo">
<img src="https://custom-icon-badges.herokuapp.com/badge/become_a-patron-F96854?logoColor=F96854&style=for-the-badge&logo=patreon&labelColor=363B40" alt="become a patron"/></a> <img src="https://custom-icon-badges.herokuapp.com/badge/become_a-patron-F96854?logoColor=F96854&style=for-the-badge&logo=patreon&labelColor=363B40" alt="become a patron"/></a>
---
[![codecov](https://codecov.io/gh/misskey-dev/misskey/branch/develop/graph/badge.svg?token=R6IQZ3QJOL)](https://codecov.io/gh/misskey-dev/misskey)
</div>
<div>
<a href="https://xn--931a.moe/"><img src="https://github.com/misskey-dev/misskey/blob/develop/assets/ai.png?raw=true" align="right" height="320px"/></a>
## ✨ Features
- **ActivityPub support**\
Not on Misskey? No problem! Not only can Misskey instances talk to each other, but you can make friends with people on other networks like Mastodon and Pixelfed!
- **Reactions**\
You can add emoji reactions to any post! No longer are you bound by a like button, show everyone exactly how you feel with the tap of a button.
- **Drive**\
With Misskey's built in drive, you get cloud storage right in your social media, where you can upload any files, make folders, and find media from posts you've made!
- **Rich Web UI**\
Misskey has a rich and easy to use Web UI!
It is highly customizable, from changing the layout and adding widgets to making custom themes.
Furthermore, plugins can be created using AiScript, an original programming language.
- And much more...
</div>
<div style="clear: both;"></div>
## Documentation
Misskey Documentation can be found at [Misskey Hub](https://misskey-hub.net/docs/), some of the links and graphics above also lead to specific portions of it.
## Sponsors
<div align="center">
<a class="rss3" title="RSS3" href="https://rss3.io/" target="_blank"><img src="https://rss3.mypinata.cloud/ipfs/QmUG6H3Z7D5P511shn7sB4CPmpjH5uZWu4m5mWX7U3Gqbu" alt="RSS3" height="60"></a>
</div> </div>
## Thanks ## Thanks

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
describe('Before setup instance', () => { describe('Before setup instance', () => {
beforeEach(() => { beforeEach(() => {
cy.resetState(); cy.resetState();

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
describe('Router transition', () => { describe('Router transition', () => {
describe('Redirect', () => { describe('Redirect', () => {
// サーバの初期化。ルートのテストに関しては各describeごとに1度だけ実行で十分だと思う使いまわした方が早い // サーバの初期化。ルートのテストに関しては各describeごとに1度だけ実行で十分だと思う使いまわした方が早い

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
/* flaky /* flaky
describe('After user signed in', () => { describe('After user signed in', () => {
beforeEach(() => { beforeEach(() => {

View File

@@ -30,13 +30,9 @@ Cypress.Commands.add('visitHome', () => {
}) })
Cypress.Commands.add('resetState', () => { Cypress.Commands.add('resetState', () => {
// iframe.contentWindow.indexedDB.deleteDatabase() がchromeのバグで使用できないため、indexedDBを無効化している。 cy.window(win => {
// see https://github.com/misskey-dev/misskey/issues/13605#issuecomment-2053652123
/*
cy.window().then(win => {
win.indexedDB.deleteDatabase('keyval-store'); win.indexedDB.deleteDatabase('keyval-store');
}); });
*/
cy.request('POST', '/api/reset-db', {}).as('reset'); cy.request('POST', '/api/reset-db', {}).as('reset');
cy.get('@reset').its('status').should('equal', 204); cy.get('@reset').its('status').should('equal', 204);
cy.reload(true); cy.reload(true);

View File

@@ -1,19 +0,0 @@
declare global {
namespace Cypress {
interface Chainable {
login(username: string, password: string): Chainable<void>;
registerUser(
username: string,
password: string,
isAdmin?: boolean
): Chainable<void>;
resetState(): Chainable<void>;
visitHome(): Chainable<void>;
}
}
}
export {}

View File

@@ -1,8 +0,0 @@
{
"compilerOptions": {
"lib": ["dom", "es5"],
"target": "es5",
"types": ["cypress", "node"]
},
"include": ["./**/*.ts"]
}

View File

@@ -1014,7 +1014,6 @@ renotes: "أعد النشر"
sourceCode: "الشفرة المصدرية" sourceCode: "الشفرة المصدرية"
flip: "اقلب" flip: "اقلب"
lastNDays: "آخر {n} أيام" lastNDays: "آخر {n} أيام"
surrender: "ألغِ"
_initialAccountSetting: _initialAccountSetting:
accountCreated: "نجح إنشاء حسابك!" accountCreated: "نجح إنشاء حسابك!"
letsStartAccountSetup: "إذا كنت جديدًا لنعدّ حسابك الشخصي." letsStartAccountSetup: "إذا كنت جديدًا لنعدّ حسابك الشخصي."

View File

@@ -1210,7 +1210,6 @@ hemisphere: "Geolocalització"
withSensitive: "Incloure notes amb fitxers sensibles" withSensitive: "Incloure notes amb fitxers sensibles"
userSaysSomethingSensitive: "La publicació de {name} conte material sensible" userSaysSomethingSensitive: "La publicació de {name} conte material sensible"
enableHorizontalSwipe: "Lliscar per canviar de pestanya" enableHorizontalSwipe: "Lliscar per canviar de pestanya"
surrender: "Cancel·lar "
_bubbleGame: _bubbleGame:
howToPlay: "Com es juga" howToPlay: "Com es juga"
_howToPlay: _howToPlay:

View File

@@ -1098,7 +1098,6 @@ renotes: "Přeposlat"
sourceCode: "Zdrojový kód" sourceCode: "Zdrojový kód"
flip: "Otočit" flip: "Otočit"
lastNDays: "Posledních {n} dnů" lastNDays: "Posledních {n} dnů"
surrender: "Zrušit"
_initialAccountSetting: _initialAccountSetting:
accountCreated: "Váš účet byl úspěšně vytvořen!" accountCreated: "Váš účet byl úspěšně vytvořen!"
letsStartAccountSetup: "Pro začátek si nastavte svůj profil." letsStartAccountSetup: "Pro začátek si nastavte svůj profil."

View File

@@ -1184,7 +1184,6 @@ decorate: "Dekorieren"
addMfmFunction: "MFM hinzufügen" addMfmFunction: "MFM hinzufügen"
sfx: "Soundeffekte" sfx: "Soundeffekte"
lastNDays: "Letzten {n} Tage" lastNDays: "Letzten {n} Tage"
surrender: "Abbrechen"
_announcement: _announcement:
forExistingUsers: "Nur für existierende Nutzer" forExistingUsers: "Nur für existierende Nutzer"
forExistingUsersDescription: "Ist diese Option aktiviert, wird diese Ankündigung nur Nutzern angezeigt, die zum Zeitpunkt der Ankündigung bereits registriert sind. Ist sie deaktiviert, wird sie auch Nutzern, die sich nach dessen Veröffentlichung registrieren, angezeigt." forExistingUsersDescription: "Ist diese Option aktiviert, wird diese Ankündigung nur Nutzern angezeigt, die zum Zeitpunkt der Ankündigung bereits registriert sind. Ist sie deaktiviert, wird sie auch Nutzern, die sich nach dessen Veröffentlichung registrieren, angezeigt."

View File

@@ -991,7 +991,6 @@ neverShow: "Don't show again"
remindMeLater: "Maybe later" remindMeLater: "Maybe later"
didYouLikeMisskey: "Have you taken a liking to Misskey?" didYouLikeMisskey: "Have you taken a liking to Misskey?"
pleaseDonate: "{host} uses the free software, Misskey. We would highly appreciate your donations so development of Misskey can continue!" pleaseDonate: "{host} uses the free software, Misskey. We would highly appreciate your donations so development of Misskey can continue!"
correspondingSourceIsAvailable: "The corresponding source code is available at {anchor}"
roles: "Roles" roles: "Roles"
role: "Role" role: "Role"
noRole: "Role not found" noRole: "Role not found"
@@ -1042,8 +1041,6 @@ resetPasswordConfirm: "Really reset your password?"
sensitiveWords: "Sensitive words" sensitiveWords: "Sensitive words"
sensitiveWordsDescription: "The visibility of all notes containing any of the configured words will be set to \"Home\" automatically. You can list multiple by separating them via line breaks." sensitiveWordsDescription: "The visibility of all notes containing any of the configured words will be set to \"Home\" automatically. You can list multiple by separating them via line breaks."
sensitiveWordsDescription2: "Using spaces will create AND expressions and surrounding keywords with slashes will turn them into a regular expression." sensitiveWordsDescription2: "Using spaces will create AND expressions and surrounding keywords with slashes will turn them into a regular expression."
prohibitedWords: "Prohibited words"
prohibitedWordsDescription: "Enables an error when attempting to post a note containing the set word(s). Multiple words can be set, separated by a new line."
prohibitedWordsDescription2: "Using spaces will create AND expressions and surrounding keywords with slashes will turn them into a regular expression." prohibitedWordsDescription2: "Using spaces will create AND expressions and surrounding keywords with slashes will turn them into a regular expression."
hiddenTags: "Hidden hashtags" hiddenTags: "Hidden hashtags"
hiddenTagsDescription: "Select tags which will not shown on trend list.\nMultiple tags could be registered by lines." hiddenTagsDescription: "Select tags which will not shown on trend list.\nMultiple tags could be registered by lines."
@@ -1160,7 +1157,6 @@ showRenotes: "Show renotes"
edited: "Edited" edited: "Edited"
notificationRecieveConfig: "Notification Settings" notificationRecieveConfig: "Notification Settings"
mutualFollow: "Mutual follow" mutualFollow: "Mutual follow"
followingOrFollower: "Following or follower"
fileAttachedOnly: "Only notes with files" fileAttachedOnly: "Only notes with files"
showRepliesToOthersInTimeline: "Show replies to others in timeline" showRepliesToOthersInTimeline: "Show replies to others in timeline"
hideRepliesToOthersInTimeline: "Hide replies to others from timeline" hideRepliesToOthersInTimeline: "Hide replies to others from timeline"
@@ -1170,12 +1166,6 @@ confirmShowRepliesAll: "This operation is irreversible. Would you really like to
confirmHideRepliesAll: "This operation is irreversible. Would you really like to hide replies to others from everyone you follow in your timeline?" confirmHideRepliesAll: "This operation is irreversible. Would you really like to hide replies to others from everyone you follow in your timeline?"
externalServices: "External Services" externalServices: "External Services"
sourceCode: "Source code" sourceCode: "Source code"
sourceCodeIsNotYetProvided: "Source code is not yet available. Contact the administrator to fix this problem."
repositoryUrl: "Repository URL"
repositoryUrlDescription: "If you are using Misskey as is (without any changes to the source code), enter https://github.com/misskey-dev/misskey"
repositoryUrlOrTarballRequired: "If you have not published a repository, you must provide a tarball instead. See .config/example.yml for more information."
feedback: "Feedback"
feedbackUrl: "Feedback URL"
impressum: "Impressum" impressum: "Impressum"
impressumUrl: "Impressum URL" impressumUrl: "Impressum URL"
impressumDescription: "In some countries, like germany, the inclusion of operator contact information (an Impressum) is legally required for commercial websites." impressumDescription: "In some countries, like germany, the inclusion of operator contact information (an Impressum) is legally required for commercial websites."
@@ -1211,8 +1201,6 @@ soundWillBePlayed: "Sound will be played"
showReplay: "View Replay" showReplay: "View Replay"
replay: "Replay" replay: "Replay"
replaying: "Showing replay" replaying: "Showing replay"
endReplay: "Exit Replay"
copyReplayData: "Copy replay data"
ranking: "Ranking" ranking: "Ranking"
lastNDays: "Last {n} days" lastNDays: "Last {n} days"
backToTitle: "Go back to title" backToTitle: "Go back to title"
@@ -1220,20 +1208,8 @@ hemisphere: "Where are you located"
withSensitive: "Include notes with sensitive files" withSensitive: "Include notes with sensitive files"
userSaysSomethingSensitive: "Post by {name} contains sensitive content" userSaysSomethingSensitive: "Post by {name} contains sensitive content"
enableHorizontalSwipe: "Swipe to switch tabs" enableHorizontalSwipe: "Swipe to switch tabs"
loading: "Loading"
surrender: "Cancel"
gameRetry: "Retry"
_bubbleGame: _bubbleGame:
howToPlay: "How to play" howToPlay: "How to play"
hold: "Hold"
_score:
score: "Score"
scoreYen: "Amount of money earned"
highScore: "High score"
maxChain: "Maximum number of chains"
yen: "{yen} Yen"
estimatedQty: "{qty} Pieces"
scoreSweets: "{onigiriQtyWithUnit} Onigiri"
_howToPlay: _howToPlay:
section1: "Adjust the position and drop the object into the box." section1: "Adjust the position and drop the object into the box."
section2: "When two objects of the same type touch each other, they will change into a different object and you score points." section2: "When two objects of the same type touch each other, they will change into a different object and you score points."
@@ -1655,7 +1631,6 @@ _role:
gtlAvailable: "Can view the global timeline" gtlAvailable: "Can view the global timeline"
ltlAvailable: "Can view the local timeline" ltlAvailable: "Can view the local timeline"
canPublicNote: "Can send public notes" canPublicNote: "Can send public notes"
mentionMax: "Maximum number of mentions in a note"
canInvite: "Can create instance invite codes" canInvite: "Can create instance invite codes"
inviteLimit: "Invite limit" inviteLimit: "Invite limit"
inviteLimitCycle: "Invite limit cooldown" inviteLimitCycle: "Invite limit cooldown"
@@ -1679,7 +1654,6 @@ _role:
canUseTranslator: "Translator usage" canUseTranslator: "Translator usage"
avatarDecorationLimit: "Maximum number of avatar decorations that can be applied" avatarDecorationLimit: "Maximum number of avatar decorations that can be applied"
_condition: _condition:
roleAssignedTo: "Assigned to manual roles"
isLocal: "Local user" isLocal: "Local user"
isRemote: "Remote user" isRemote: "Remote user"
createdLessThan: "Less than X has passed since account creation" createdLessThan: "Less than X has passed since account creation"
@@ -1780,8 +1754,6 @@ _aboutMisskey:
contributors: "Main contributors" contributors: "Main contributors"
allContributors: "All contributors" allContributors: "All contributors"
source: "Source code" source: "Source code"
original: "Original"
thisIsModifiedVersion: "{name} uses a modified version of the original Misskey."
translation: "Translate Misskey" translation: "Translate Misskey"
donate: "Donate to Misskey" donate: "Donate to Misskey"
morePatrons: "We also appreciate the support of many other helpers not listed here. Thank you! 🥰" morePatrons: "We also appreciate the support of many other helpers not listed here. Thank you! 🥰"
@@ -2300,7 +2272,6 @@ _notification:
reactedBySomeUsers: "{n} users reacted" reactedBySomeUsers: "{n} users reacted"
renotedBySomeUsers: "Renote from {n} users" renotedBySomeUsers: "Renote from {n} users"
followedBySomeUsers: "Followed by {n} users" followedBySomeUsers: "Followed by {n} users"
flushNotification: "Clear notifications"
_types: _types:
all: "All" all: "All"
note: "New notes" note: "New notes"
@@ -2398,7 +2369,6 @@ _moderationLogTypes:
resetPassword: "Password reset" resetPassword: "Password reset"
suspendRemoteInstance: "Remote instance suspended" suspendRemoteInstance: "Remote instance suspended"
unsuspendRemoteInstance: "Remote instance unsuspended" unsuspendRemoteInstance: "Remote instance unsuspended"
updateRemoteInstanceNote: "Moderation note updated for remote instance."
markSensitiveDriveFile: "File marked as sensitive" markSensitiveDriveFile: "File marked as sensitive"
unmarkSensitiveDriveFile: "File unmarked as sensitive" unmarkSensitiveDriveFile: "File unmarked as sensitive"
resolveAbuseReport: "Report resolved" resolveAbuseReport: "Report resolved"
@@ -2519,8 +2489,6 @@ _reversi:
opponentHasSettingsChanged: "The opponent has changed their settings." opponentHasSettingsChanged: "The opponent has changed their settings."
allowIrregularRules: "Irregular rules (completely free)" allowIrregularRules: "Irregular rules (completely free)"
disallowIrregularRules: "No irregular rules" disallowIrregularRules: "No irregular rules"
showBoardLabels: "Display row and column numbering on the board"
useAvatarAsStone: "Turn stones into user avatars"
_offlineScreen: _offlineScreen:
title: "Offline - cannot connect to the server" title: "Offline - cannot connect to the server"
header: "Unable to connect to the server" header: "Unable to connect to the server"

View File

@@ -1209,7 +1209,6 @@ hemisphere: "Región"
withSensitive: "Mostrar notas que contengan material sensible" withSensitive: "Mostrar notas que contengan material sensible"
userSaysSomethingSensitive: "La publicación de {name} contiene material sensible" userSaysSomethingSensitive: "La publicación de {name} contiene material sensible"
enableHorizontalSwipe: "Deslice para cambiar de pestaña" enableHorizontalSwipe: "Deslice para cambiar de pestaña"
surrender: "detener"
_bubbleGame: _bubbleGame:
howToPlay: "Cómo jugar" howToPlay: "Cómo jugar"
_howToPlay: _howToPlay:

View File

@@ -380,11 +380,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Activer hCaptcha" enableHcaptcha: "Activer hCaptcha"
hcaptchaSiteKey: "Clé du site" hcaptchaSiteKey: "Clé du site"
hcaptchaSecretKey: "Clé secrète" hcaptchaSecretKey: "Clé secrète"
mcaptcha: "mCaptcha"
enableMcaptcha: "Activer mCaptcha"
mcaptchaSiteKey: "Clé du site" mcaptchaSiteKey: "Clé du site"
mcaptchaSecretKey: "Clé secrète" mcaptchaSecretKey: "Clé secrète"
mcaptchaInstanceUrl: "URL de l'instance de mCaptcha"
recaptcha: "reCAPTCHA" recaptcha: "reCAPTCHA"
enableRecaptcha: "Activer reCAPTCHA" enableRecaptcha: "Activer reCAPTCHA"
recaptchaSiteKey: "Clé du site" recaptchaSiteKey: "Clé du site"
@@ -526,7 +523,7 @@ hideThisNote: "Masquer cette note"
showFeaturedNotesInTimeline: "Afficher les notes des Tendances dans le fil d'actualité" showFeaturedNotesInTimeline: "Afficher les notes des Tendances dans le fil d'actualité"
objectStorage: "Stockage d'objets" objectStorage: "Stockage d'objets"
useObjectStorage: "Utiliser le stockage d'objets" useObjectStorage: "Utiliser le stockage d'objets"
objectStorageBaseUrl: "URL de base" objectStorageBaseUrl: "Base URL"
objectStorageBaseUrlDesc: "Préfixe dURL utilisé pour construire lURL vers le référencement dobjet (média). Spécifiez son URL si vous utilisez un CDN ou un proxy, sinon spécifiez ladresse accessible au public selon le guide de service que vous allez utiliser. P.ex. 'https://<bucket>.s3.amazonaws.com' pour AWS S3 et 'https://storage.googleapis.com/<bucket>' pour GCS." objectStorageBaseUrlDesc: "Préfixe dURL utilisé pour construire lURL vers le référencement dobjet (média). Spécifiez son URL si vous utilisez un CDN ou un proxy, sinon spécifiez ladresse accessible au public selon le guide de service que vous allez utiliser. P.ex. 'https://<bucket>.s3.amazonaws.com' pour AWS S3 et 'https://storage.googleapis.com/<bucket>' pour GCS."
objectStorageBucket: "Bucket" objectStorageBucket: "Bucket"
objectStorageBucketDesc: "Veuillez spécifier le nom du compartiment utilisé sur le service configuré." objectStorageBucketDesc: "Veuillez spécifier le nom du compartiment utilisé sur le service configuré."
@@ -631,7 +628,6 @@ medium: "Moyen"
small: "Petit" small: "Petit"
generateAccessToken: "Générer un jeton d'accès" generateAccessToken: "Générer un jeton d'accès"
permission: "Autorisations " permission: "Autorisations "
adminPermission: "Droits de l'administrateur"
enableAll: "Tout activer" enableAll: "Tout activer"
disableAll: "Tout désactiver" disableAll: "Tout désactiver"
tokenRequested: "Autoriser l'accès au compte" tokenRequested: "Autoriser l'accès au compte"
@@ -1035,18 +1031,12 @@ nonSensitiveOnlyForLocalLikeOnlyForRemote: "Non sensibles seulement (mentions j'
rolesAssignedToMe: "Rôles attribués à moi" rolesAssignedToMe: "Rôles attribués à moi"
resetPasswordConfirm: "Souhaitez-vous réinitialiser votre mot de passe ?" resetPasswordConfirm: "Souhaitez-vous réinitialiser votre mot de passe ?"
sensitiveWords: "Mots sensibles" sensitiveWords: "Mots sensibles"
sensitiveWordsDescription2: "Séparer par une espace pour créer une expression AND ; entourer de barres obliques pour créer une expression régulière."
prohibitedWords: "Mots interdits"
prohibitedWordsDescription2: "Séparer par une espace pour créer une expression AND ; entourer de barres obliques pour créer une expression régulière."
hiddenTags: "Hashtags cachés" hiddenTags: "Hashtags cachés"
hiddenTagsDescription: "Les hashtags définis ne s'afficheront pas dans les tendances. Vous pouvez définir plusieurs hashtags en faisant un saut de ligne." hiddenTagsDescription: "Les hashtags définis ne s'afficheront pas dans les tendances. Vous pouvez définir plusieurs hashtags en faisant un saut de ligne."
notesSearchNotAvailable: "La recherche de notes n'est pas disponible." notesSearchNotAvailable: "La recherche de notes n'est pas disponible."
license: "Licence" license: "Licence"
unfavoriteConfirm: "Vraiment supprimer des favoris ?"
myClips: "Mes clips" myClips: "Mes clips"
drivecleaner: "Nettoyeur du Disque" drivecleaner: "Nettoyeur du Disque"
retryAllQueuesNow: "Réessayer tous les fils d'attente immédiatement"
retryAllQueuesConfirmTitle: "Vraiment réessayer ?"
retryAllQueuesConfirmText: "Cela peut augmenter temporairement la charge du serveur." retryAllQueuesConfirmText: "Cela peut augmenter temporairement la charge du serveur."
enableChartsForRemoteUser: "Générer les graphiques pour les utilisateurs distants" enableChartsForRemoteUser: "Générer les graphiques pour les utilisateurs distants"
enableChartsForFederatedInstances: "Générer les graphiques pour les instances distantes" enableChartsForFederatedInstances: "Générer les graphiques pour les instances distantes"
@@ -1056,8 +1046,6 @@ limitWidthOfReaction: "Limiter la largeur maximale des réactions et les affiche
noteIdOrUrl: "Identifiant de la note ou URL" noteIdOrUrl: "Identifiant de la note ou URL"
video: "Vidéo" video: "Vidéo"
videos: "Vidéos" videos: "Vidéos"
audio: "Audio"
audioFiles: "Fichiers audio"
dataSaver: "Économiseur de données" dataSaver: "Économiseur de données"
accountMigration: "Migration de compte" accountMigration: "Migration de compte"
accountMoved: "Cet·te utilisateur·rice a migré son compte vers :" accountMoved: "Cet·te utilisateur·rice a migré son compte vers :"
@@ -1096,10 +1084,7 @@ specifyUser: "Spécifier l'utilisateur·rice"
failedToPreviewUrl: "Aperçu d'URL échoué" failedToPreviewUrl: "Aperçu d'URL échoué"
update: "Mettre à jour" update: "Mettre à jour"
rolesThatCanBeUsedThisEmojiAsReaction: "Rôles qui peuvent utiliser cet émoji comme réaction" rolesThatCanBeUsedThisEmojiAsReaction: "Rôles qui peuvent utiliser cet émoji comme réaction"
rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "Si aucun rôle n'est spécifié, tout le monde peut utiliser cet émoji comme réaction."
rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "Il faut un rôle public."
cancelReactionConfirm: "Supprimez la réaction ?" cancelReactionConfirm: "Supprimez la réaction ?"
changeReactionConfirm: "Changer la réaction ?"
later: "Plus tard" later: "Plus tard"
goToMisskey: "Retour vers Misskey" goToMisskey: "Retour vers Misskey"
additionalEmojiDictionary: "Dictionnaires d'émojis additionnels" additionalEmojiDictionary: "Dictionnaires d'émojis additionnels"
@@ -1125,13 +1110,11 @@ used: "Utilisé"
expired: "Expiré" expired: "Expiré"
doYouAgree: "Êtes-vous daccord ?" doYouAgree: "Êtes-vous daccord ?"
beSureToReadThisAsItIsImportant: "Assurez-vous de le lire; c'est important." beSureToReadThisAsItIsImportant: "Assurez-vous de le lire; c'est important."
iHaveReadXCarefullyAndAgree: "J'ai lu le contenu de « {x} » et donne mon accord."
dialog: "Dialogue" dialog: "Dialogue"
icon: "Avatar" icon: "Avatar"
forYou: "Pour vous" forYou: "Pour vous"
currentAnnouncements: "Annonces actuelles" currentAnnouncements: "Annonces actuelles"
pastAnnouncements: "Annonces passées" pastAnnouncements: "Annonces passées"
youHaveUnreadAnnouncements: "Il y a des annonces non lues."
replies: "Réponses" replies: "Réponses"
renotes: "Renotes" renotes: "Renotes"
loadReplies: "Inclure les réponses" loadReplies: "Inclure les réponses"
@@ -1146,7 +1129,6 @@ showRenotes: "Afficher les renotes"
edited: "Modifié" edited: "Modifié"
notificationRecieveConfig: "Paramètres des notifications" notificationRecieveConfig: "Paramètres des notifications"
mutualFollow: "Abonnement mutuel" mutualFollow: "Abonnement mutuel"
fileAttachedOnly: "Avec fichiers joints seulement"
showRepliesToOthersInTimeline: "Afficher les réponses aux autres dans le fil" showRepliesToOthersInTimeline: "Afficher les réponses aux autres dans le fil"
hideRepliesToOthersInTimeline: "Masquer les réponses aux autres dans le fil" hideRepliesToOthersInTimeline: "Masquer les réponses aux autres dans le fil"
showRepliesToOthersInTimelineAll: "Afficher les réponses de toutes les personnes que vous suivez dans le fil" showRepliesToOthersInTimelineAll: "Afficher les réponses de toutes les personnes que vous suivez dans le fil"
@@ -1155,11 +1137,6 @@ confirmShowRepliesAll: "Cette opération est irréversible. Voulez-vous vraiment
confirmHideRepliesAll: "Cette opération est irréversible. Voulez-vous vraiment masquer les réponses de toutes les personnes que vous suivez dans le fil ?" confirmHideRepliesAll: "Cette opération est irréversible. Voulez-vous vraiment masquer les réponses de toutes les personnes que vous suivez dans le fil ?"
externalServices: "Services externes" externalServices: "Services externes"
sourceCode: "Code source" sourceCode: "Code source"
sourceCodeIsNotYetProvided: "Le code source n'est pas encore disponible. Veuillez signaler ce problème aux administrateurs."
repositoryUrl: "URL du dépôt"
repositoryUrlDescription: "Entrez l'URL du dépôt où se trouve le code source ici. Si vous utilisez Misskey tel quel (sans changer le code source), entrez https://github.com/misskey-dev/misskey"
feedback: "Commentaires"
feedbackUrl: "URL pour les commentaires"
impressum: "Impressum" impressum: "Impressum"
impressumUrl: "URL de l'impressum" impressumUrl: "URL de l'impressum"
impressumDescription: "Dans certains pays comme l'Allemagne, il est obligatoire d'afficher les informations sur l'opérateur d'un site (un impressum)." impressumDescription: "Dans certains pays comme l'Allemagne, il est obligatoire d'afficher les informations sur l'opérateur d'un site (un impressum)."
@@ -1187,32 +1164,7 @@ remainingN: "Restants : {n}"
overwriteContentConfirm: "Voulez-vous remplacer le contenu actuel ?" overwriteContentConfirm: "Voulez-vous remplacer le contenu actuel ?"
seasonalScreenEffect: "Effet d'écran saisonnier" seasonalScreenEffect: "Effet d'écran saisonnier"
decorate: "Décorer" decorate: "Décorer"
addMfmFunction: "Insérer MFM"
enableQuickAddMfmFunction: "Afficher le sélecteur de MFM avancé"
bubbleGame: "Jeu de bulles"
sfx: "Effets sonores"
soundWillBePlayed: "Le son sera joué"
showReplay: "Voir le replay"
replay: "Rediffusion"
replaying: "En cours de rediffusion"
endReplay: "Arrêter la rediffusion"
copyReplayData: "Copier les données de la rediffusion"
ranking: "Classement"
lastNDays: "Derniers {n} jours" lastNDays: "Derniers {n} jours"
backToTitle: "Retourner au titre"
hemisphere: "Votre région"
enableHorizontalSwipe: "Glisser pour changer d'onglet"
loading: "Chargement en cours"
surrender: "Annuler"
gameRetry: "Réessayer"
_bubbleGame:
howToPlay: "Comment jouer"
hold: "Réserver"
_score:
score: "Score"
scoreYen: "Montant gagné"
highScore: "Meilleur score"
yen: "{yen} yens"
_announcement: _announcement:
forExistingUsers: "Pour les utilisateurs existants seulement" forExistingUsers: "Pour les utilisateurs existants seulement"
readConfirmTitle: "Marquer comme lu ?" readConfirmTitle: "Marquer comme lu ?"
@@ -1350,13 +1302,10 @@ _achievements:
title: "Régulier III" title: "Régulier III"
description: "Se connecter pour un total de 400 jours" description: "Se connecter pour un total de 400 jours"
_login500: _login500:
title: "Expert I"
description: "Se connecter pour un total de 500 jours" description: "Se connecter pour un total de 500 jours"
_login600: _login600:
title: "Expert II"
description: "Se connecter pour un total de 600 jours" description: "Se connecter pour un total de 600 jours"
_login700: _login700:
title: "Expert III"
description: "Se connecter pour un total de 700 jours" description: "Se connecter pour un total de 700 jours"
_login800: _login800:
description: "Se connecter pour un total de 800 jours" description: "Se connecter pour un total de 800 jours"
@@ -1451,12 +1400,9 @@ _role:
description: "Description du rôle" description: "Description du rôle"
permission: "Rôle et autorisations" permission: "Rôle et autorisations"
assignTarget: "Attribuer" assignTarget: "Attribuer"
manual: "Manuel"
manualRoles: "Rôles manuels" manualRoles: "Rôles manuels"
conditional: "Conditionnel"
conditionalRoles: "Rôles conditionnels" conditionalRoles: "Rôles conditionnels"
condition: "Condition" condition: "Condition"
isConditionalRole: "Ceci est un rôle conditionnel."
isPublic: "Rôle public" isPublic: "Rôle public"
options: "Options" options: "Options"
policies: "Stratégies" policies: "Stratégies"

View File

@@ -1209,7 +1209,6 @@ hemisphere: "Letak kamu tinggal"
withSensitive: "Lampirkan catatan dengan berkas sensitif" withSensitive: "Lampirkan catatan dengan berkas sensitif"
userSaysSomethingSensitive: "Postingan oleh {name} mengandung konten sensitif" userSaysSomethingSensitive: "Postingan oleh {name} mengandung konten sensitif"
enableHorizontalSwipe: "Geser untuk mengganti tab" enableHorizontalSwipe: "Geser untuk mengganti tab"
surrender: "Batalkan"
_bubbleGame: _bubbleGame:
howToPlay: "Cara bermain" howToPlay: "Cara bermain"
_howToPlay: _howToPlay:

250
locales/index.d.ts vendored
View File

@@ -1616,10 +1616,6 @@ export interface Locale extends ILocale {
* 除外キーワード * 除外キーワード
*/ */
"antennaExcludeKeywords": string; "antennaExcludeKeywords": string;
/**
* Botアカウントを除外
*/
"antennaExcludeBots": string;
/** /**
* スペースで区切るとAND指定になり、改行で区切るとOR指定になります * スペースで区切るとAND指定になり、改行で区切るとOR指定になります
*/ */
@@ -1996,10 +1992,6 @@ export interface Locale extends ILocale {
* ノートのアクションをホバー時のみ表示する * ノートのアクションをホバー時のみ表示する
*/ */
"showNoteActionsOnlyHover": string; "showNoteActionsOnlyHover": string;
/**
* ノートのリアクション数を表示する
*/
"showReactionsCount": string;
/** /**
* 履歴はありません * 履歴はありません
*/ */
@@ -4664,10 +4656,6 @@ export interface Locale extends ILocale {
* 相互フォロー * 相互フォロー
*/ */
"mutualFollow": string; "mutualFollow": string;
/**
* フォロー中またはフォロワー
*/
"followingOrFollower": string;
/** /**
* ファイル付きのみ * ファイル付きのみ
*/ */
@@ -4868,14 +4856,6 @@ export interface Locale extends ILocale {
* リプレイ中 * リプレイ中
*/ */
"replaying": string; "replaying": string;
/**
* リプレイを終了
*/
"endReplay": string;
/**
* リプレイデータをコピー
*/
"copyReplayData": string;
/** /**
* ランキング * ランキング
*/ */
@@ -4904,97 +4884,11 @@ export interface Locale extends ILocale {
* スワイプしてタブを切り替える * スワイプしてタブを切り替える
*/ */
"enableHorizontalSwipe": string; "enableHorizontalSwipe": string;
/**
* 読み込み中
*/
"loading": string;
/**
* やめる
*/
"surrender": string;
/**
* リトライ
*/
"gameRetry": string;
/**
* 使用しない場合は空欄にしてください
*/
"notUsePleaseLeaveBlank": string;
/**
* ワンタイムパスワードを使う
*/
"useTotp": string;
/**
* バックアップコードを使う
*/
"useBackupCode": string;
/**
* アプリを起動
*/
"launchApp": string;
/**
* 動画・音声の再生にブラウザのUIを使用する
*/
"useNativeUIForVideoAudioPlayer": string;
/**
* オリジナルのファイル名を保持
*/
"keepOriginalFilename": string;
/**
* この設定をオフにすると、アップロード時にファイル名が自動でランダム文字列に置き換えられます。
*/
"keepOriginalFilenameDescription": string;
/**
* 説明文はありません
*/
"noDescription": string;
/**
* フォローの際常に確認する
*/
"alwaysConfirmFollow": string;
/**
* お問い合わせ
*/
"inquiry": string;
"_bubbleGame": { "_bubbleGame": {
/** /**
* 遊び方 * 遊び方
*/ */
"howToPlay": string; "howToPlay": string;
/**
* ホールド
*/
"hold": string;
"_score": {
/**
* スコア
*/
"score": string;
/**
* 稼いだ金額
*/
"scoreYen": string;
/**
* ハイスコア
*/
"highScore": string;
/**
* 最大チェーン数
*/
"maxChain": string;
/**
* {yen}円
*/
"yen": ParameterizedString<"yen">;
/**
* {qty}個分
*/
"estimatedQty": ParameterizedString<"qty">;
/**
* おにぎり {onigiriQtyWithUnit}
*/
"scoreSweets": ParameterizedString<"onigiriQtyWithUnit">;
};
"_howToPlay": { "_howToPlay": {
/** /**
* 位置を調整してハコにモノを落とします。 * 位置を調整してハコにモノを落とします。
@@ -6490,10 +6384,6 @@ export interface Locale extends ILocale {
* パブリック投稿の許可 * パブリック投稿の許可
*/ */
"canPublicNote": string; "canPublicNote": string;
/**
* ノート内の最大メンション数
*/
"mentionMax": string;
/** /**
* サーバー招待コードの発行 * サーバー招待コードの発行
*/ */
@@ -6584,10 +6474,6 @@ export interface Locale extends ILocale {
"avatarDecorationLimit": string; "avatarDecorationLimit": string;
}; };
"_condition": { "_condition": {
/**
* マニュアルロールにアサイン済み
*/
"roleAssignedTo": string;
/** /**
* ローカルユーザー * ローカルユーザー
*/ */
@@ -6596,26 +6482,6 @@ export interface Locale extends ILocale {
* リモートユーザー * リモートユーザー
*/ */
"isRemote": string; "isRemote": string;
/**
* 猫ユーザー
*/
"isCat": string;
/**
* botユーザー
*/
"isBot": string;
/**
* サスペンド済みユーザー
*/
"isSuspended": string;
/**
* 鍵アカウントユーザー
*/
"isLocked": string;
/**
* 「アカウントを見つけやすくする」が有効なユーザー
*/
"isExplorable": string;
/** /**
* アカウント作成から~以内 * アカウント作成から~以内
*/ */
@@ -6869,10 +6735,6 @@ export interface Locale extends ILocale {
* ソースを表示 * ソースを表示
*/ */
"viewSource": string; "viewSource": string;
/**
* ログを表示
*/
"viewLog": string;
}; };
"_preferencesBackups": { "_preferencesBackups": {
/** /**
@@ -7590,9 +7452,13 @@ export interface Locale extends ILocale {
*/ */
"step1": ParameterizedString<"a" | "b">; "step1": ParameterizedString<"a" | "b">;
/** /**
* 次に、表示されているQRコードをアプリでスキャンするか、ボタンをクリックして端末上でアプリを開きます。 * 次に、表示されているQRコードをアプリでスキャンます。
*/ */
"step2": string; "step2": string;
/**
* QRコードをクリックすると、お使いの端末にインストールされている認証アプリやキーリングに登録できます。
*/
"step2Click": string;
/** /**
* デスクトップアプリを使用する場合は次のURIを入力します * デスクトップアプリを使用する場合は次のURIを入力します
*/ */
@@ -7685,10 +7551,6 @@ export interface Locale extends ILocale {
* バックアップコードが全て使用されました。認証アプリを利用できない場合、これ以上アカウントにアクセスできなくなります。認証アプリを再登録してください。 * バックアップコードが全て使用されました。認証アプリを利用できない場合、これ以上アカウントにアクセスできなくなります。認証アプリを再登録してください。
*/ */
"backupCodesExhaustedWarning": string; "backupCodesExhaustedWarning": string;
/**
* 詳細なガイドはこちら
*/
"moreDetailedGuideHere": string;
}; };
"_permissions": { "_permissions": {
/** /**
@@ -8699,10 +8561,6 @@ export interface Locale extends ILocale {
* 説明 * 説明
*/ */
"summary": string; "summary": string;
/**
* 非公開に設定するとプロフィールに表示されなくなりますが、URLを知っている人は引き続きアクセスできます。
*/
"visibilityDescription": string;
}; };
"_pages": { "_pages": {
/** /**
@@ -8874,14 +8732,6 @@ export interface Locale extends ILocale {
* ボタン * ボタン
*/ */
"button": string; "button": string;
/**
* 動的ブロック
*/
"dynamic": string;
/**
* このブロックは廃止されています。今後は{play}を利用してください。
*/
"dynamicDescription": ParameterizedString<"play">;
/** /**
* ノート埋め込み * ノート埋め込み
*/ */
@@ -8993,10 +8843,6 @@ export interface Locale extends ILocale {
* {n}人がリアクションしました * {n}人がリアクションしました
*/ */
"reactedBySomeUsers": ParameterizedString<"n">; "reactedBySomeUsers": ParameterizedString<"n">;
/**
* {n}人がいいねしました
*/
"likedBySomeUsers": ParameterizedString<"n">;
/** /**
* {n}人がリノートしました * {n}人がリノートしました
*/ */
@@ -9005,10 +8851,6 @@ export interface Locale extends ILocale {
* {n}人にフォローされました * {n}人にフォローされました
*/ */
"followedBySomeUsers": ParameterizedString<"n">; "followedBySomeUsers": ParameterizedString<"n">;
/**
* 通知の履歴をリセットする
*/
"flushNotification": string;
"_types": { "_types": {
/** /**
* すべて * すべて
@@ -9330,7 +9172,7 @@ export interface Locale extends ILocale {
*/ */
"updateServerSettings": string; "updateServerSettings": string;
/** /**
* ユーザーのモデレーションノート更新 * モデレーションノート更新
*/ */
"updateUserNote": string; "updateUserNote": string;
/** /**
@@ -9377,10 +9219,6 @@ export interface Locale extends ILocale {
* リモートサーバーを再開 * リモートサーバーを再開
*/ */
"unsuspendRemoteInstance": string; "unsuspendRemoteInstance": string;
/**
* リモートサーバーのモデレーションノート更新
*/
"updateRemoteInstanceNote": string;
/** /**
* ファイルをセンシティブ付与 * ファイルをセンシティブ付与
*/ */
@@ -9817,14 +9655,6 @@ export interface Locale extends ILocale {
* 変則なし * 変則なし
*/ */
"disallowIrregularRules": string; "disallowIrregularRules": string;
/**
* 盤面に行・列番号を表示
*/
"showBoardLabels": string;
/**
* 石をアイコンにする
*/
"useAvatarAsStone": string;
}; };
"_offlineScreen": { "_offlineScreen": {
/** /**
@@ -9836,74 +9666,6 @@ export interface Locale extends ILocale {
*/ */
"header": string; "header": string;
}; };
"_urlPreviewSetting": {
/**
* URLプレビューの設定
*/
"title": string;
/**
* URLプレビューを有効にする
*/
"enable": string;
/**
* プレビュー取得時のタイムアウト(ms)
*/
"timeout": string;
/**
* プレビュー取得の所要時間がこの値を超えた場合、プレビューは生成されません。
*/
"timeoutDescription": string;
/**
* Content-Lengthの最大値(byte)
*/
"maximumContentLength": string;
/**
* Content-Lengthがこの値を超えた場合、プレビューは生成されません。
*/
"maximumContentLengthDescription": string;
/**
* Content-Lengthが取得できた場合のみプレビューを生成
*/
"requireContentLength": string;
/**
* 相手サーバがContent-Lengthを返さない場合、プレビューは生成されません。
*/
"requireContentLengthDescription": string;
/**
* User-Agent
*/
"userAgent": string;
/**
* プレビュー取得時に使用されるUser-Agentを設定します。空欄の場合、デフォルトのUser-Agentが使用されます。
*/
"userAgentDescription": string;
/**
* プレビューを生成するプロキシのエンドポイント
*/
"summaryProxy": string;
/**
* Misskey本体ではなく、サマリープロキシを使用してプレビューを生成します。
*/
"summaryProxyDescription": string;
/**
* プロキシには下記パラメータがクエリ文字列として連携されます。プロキシ側がこれらをサポートしない場合、設定値は無視されます。
*/
"summaryProxyDescription2": string;
};
"_mediaControls": {
/**
* ピクチャインピクチャ
*/
"pip": string;
/**
* 再生速度
*/
"playbackRate": string;
/**
* ループ再生
*/
"loop": string;
};
} }
declare const locales: { declare const locales: {
[lang: string]: Locale; [lang: string]: Locale;

View File

@@ -991,7 +991,6 @@ neverShow: "Non mostrare più"
remindMeLater: "Rimanda" remindMeLater: "Rimanda"
didYouLikeMisskey: "Ti piace Misskey?" didYouLikeMisskey: "Ti piace Misskey?"
pleaseDonate: "Misskey è il software libero utilizzato su {host}. Offrendo una donazione è più facile continuare a svilupparlo!" pleaseDonate: "Misskey è il software libero utilizzato su {host}. Offrendo una donazione è più facile continuare a svilupparlo!"
correspondingSourceIsAvailable: ""
roles: "Ruoli" roles: "Ruoli"
role: "Ruolo" role: "Ruolo"
noRole: "Ruolo non trovato" noRole: "Ruolo non trovato"
@@ -1169,12 +1168,6 @@ confirmShowRepliesAll: "Questa è una attività irreversibile. Vuoi davvero incl
confirmHideRepliesAll: "Questa è una attività irreversibile. Vuoi davvero escludere tutte le risposte dei following in TL?" confirmHideRepliesAll: "Questa è una attività irreversibile. Vuoi davvero escludere tutte le risposte dei following in TL?"
externalServices: "Servizi esterni" externalServices: "Servizi esterni"
sourceCode: "Codice sorgente" sourceCode: "Codice sorgente"
sourceCodeIsNotYetProvided: ""
repositoryUrl: "URL della repository"
repositoryUrlDescription: "Se esiste un repository il cui il codice sorgente è disponibile pubblicamente, inserisci il suo URL. Se stai utilizzando Misskey così com'è (senza alcuna modifica al codice sorgente), inserisci https://github.com/misskey-dev/misskey."
repositoryUrlOrTarballRequired: "Se non disponi di un repository pubblico, dovrai fornire un file tarball (tar). Vedere .config/example.yml per i dettagli."
feedback: "Feedback"
feedbackUrl: "URL di feedback"
impressum: "Dichiarazione di proprietà" impressum: "Dichiarazione di proprietà"
impressumUrl: "URL della dichiarazione di proprietà" impressumUrl: "URL della dichiarazione di proprietà"
impressumDescription: "La dichiarazione di proprietà, è obbligatoria in alcuni paesi come la Germania (Impressum)." impressumDescription: "La dichiarazione di proprietà, è obbligatoria in alcuni paesi come la Germania (Impressum)."
@@ -1206,7 +1199,7 @@ addMfmFunction: "Aggiungi decorazioni"
enableQuickAddMfmFunction: "Attiva il selettore di funzioni MFM" enableQuickAddMfmFunction: "Attiva il selettore di funzioni MFM"
bubbleGame: "Bubble Game" bubbleGame: "Bubble Game"
sfx: "Effetti sonori" sfx: "Effetti sonori"
soundWillBePlayed: "Con musica ed effetti sonori" soundWillBePlayed: "Verrà riprodotto il suono"
showReplay: "Vedi i replay" showReplay: "Vedi i replay"
replay: "Replay" replay: "Replay"
replaying: "Replay in corso" replaying: "Replay in corso"
@@ -1217,13 +1210,12 @@ hemisphere: "Geolocalizzazione"
withSensitive: "Mostra le Note con allegati espliciti" withSensitive: "Mostra le Note con allegati espliciti"
userSaysSomethingSensitive: "Note da {name} con allegati espliciti" userSaysSomethingSensitive: "Note da {name} con allegati espliciti"
enableHorizontalSwipe: "Trascina per invertire i tab" enableHorizontalSwipe: "Trascina per invertire i tab"
surrender: "Annulla"
_bubbleGame: _bubbleGame:
howToPlay: "Come giocare" howToPlay: "Come giocare"
_howToPlay: _howToPlay:
section1: "Scegli la posizione e rilascia l'oggetto nel contenitore." section1: "Regola la posizione e rilascia l'oggetto nella casella."
section2: "Se due oggetti dello stesso tipo si toccano, si trasformano in un oggetto diverso, aumentando il punteggio." section2: "Ottieni un punteggio, quando due oggetti dello stesso tipo si toccano e si trasformano in un oggetto diverso."
section3: "Se gli oggetti escono dal limite superiore del contenitore, il gioco finisce. Cerca di ottenere un punteggio elevato fondendo gli oggetti, evitando che escano dal contenitore!" section3: "Se gli oggetti traboccano dalla scatola, il gioco finisce. Cerca di ottenere un punteggio elevato fondendo gli oggetti, evitando che escano dalla scatola!"
_announcement: _announcement:
forExistingUsers: "Solo ai profili attuali" forExistingUsers: "Solo ai profili attuali"
forExistingUsersDescription: "L'annuncio sarà visibile solo ai profili esistenti in questo momento. Se disabilitato, sarà visibile anche ai profili che verranno creati dopo la pubblicazione di questo annuncio." forExistingUsersDescription: "L'annuncio sarà visibile solo ai profili esistenti in questo momento. Se disabilitato, sarà visibile anche ai profili che verranno creati dopo la pubblicazione di questo annuncio."
@@ -1764,8 +1756,6 @@ _aboutMisskey:
contributors: "Principali sostenitori" contributors: "Principali sostenitori"
allContributors: "Tutti i sostenitori" allContributors: "Tutti i sostenitori"
source: "Codice sorgente" source: "Codice sorgente"
original: "Originale"
thisIsModifiedVersion: "{name} sta usando una versione modificata diversa da Misskey originale."
translation: "Tradurre Misskey" translation: "Tradurre Misskey"
donate: "Sostieni Misskey" donate: "Sostieni Misskey"
morePatrons: "Apprezziamo sinceramente il supporto di tante altre persone. Grazie mille! 🥰" morePatrons: "Apprezziamo sinceramente il supporto di tante altre persone. Grazie mille! 🥰"

View File

@@ -400,7 +400,6 @@ name: "名前"
antennaSource: "受信ソース" antennaSource: "受信ソース"
antennaKeywords: "受信キーワード" antennaKeywords: "受信キーワード"
antennaExcludeKeywords: "除外キーワード" antennaExcludeKeywords: "除外キーワード"
antennaExcludeBots: "Botアカウントを除外"
antennaKeywordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります" antennaKeywordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります"
notifyAntenna: "新しいノートを通知する" notifyAntenna: "新しいノートを通知する"
withFileAntenna: "ファイルが添付されたノートのみ" withFileAntenna: "ファイルが添付されたノートのみ"
@@ -495,7 +494,6 @@ emojiStyle: "絵文字のスタイル"
native: "ネイティブ" native: "ネイティブ"
disableDrawer: "メニューをドロワーで表示しない" disableDrawer: "メニューをドロワーで表示しない"
showNoteActionsOnlyHover: "ノートのアクションをホバー時のみ表示する" showNoteActionsOnlyHover: "ノートのアクションをホバー時のみ表示する"
showReactionsCount: "ノートのリアクション数を表示する"
noHistory: "履歴はありません" noHistory: "履歴はありません"
signinHistory: "ログイン履歴" signinHistory: "ログイン履歴"
enableAdvancedMfm: "高度なMFMを有効にする" enableAdvancedMfm: "高度なMFMを有効にする"
@@ -1162,7 +1160,6 @@ showRenotes: "リノートを表示"
edited: "編集済み" edited: "編集済み"
notificationRecieveConfig: "通知の受信設定" notificationRecieveConfig: "通知の受信設定"
mutualFollow: "相互フォロー" mutualFollow: "相互フォロー"
followingOrFollower: "フォロー中またはフォロワー"
fileAttachedOnly: "ファイル付きのみ" fileAttachedOnly: "ファイル付きのみ"
showRepliesToOthersInTimeline: "TLに他の人への返信を含める" showRepliesToOthersInTimeline: "TLに他の人への返信を含める"
hideRepliesToOthersInTimeline: "TLに他の人への返信を含めない" hideRepliesToOthersInTimeline: "TLに他の人への返信を含めない"
@@ -1213,8 +1210,6 @@ soundWillBePlayed: "サウンドが再生されます"
showReplay: "リプレイを見る" showReplay: "リプレイを見る"
replay: "リプレイ" replay: "リプレイ"
replaying: "リプレイ中" replaying: "リプレイ中"
endReplay: "リプレイを終了"
copyReplayData: "リプレイデータをコピー"
ranking: "ランキング" ranking: "ランキング"
lastNDays: "直近{n}日" lastNDays: "直近{n}日"
backToTitle: "タイトルへ" backToTitle: "タイトルへ"
@@ -1222,31 +1217,9 @@ hemisphere: "お住まいの地域"
withSensitive: "センシティブなファイルを含むノートを表示" withSensitive: "センシティブなファイルを含むノートを表示"
userSaysSomethingSensitive: "{name}のセンシティブなファイルを含む投稿" userSaysSomethingSensitive: "{name}のセンシティブなファイルを含む投稿"
enableHorizontalSwipe: "スワイプしてタブを切り替える" enableHorizontalSwipe: "スワイプしてタブを切り替える"
loading: "読み込み中"
surrender: "やめる"
gameRetry: "リトライ"
notUsePleaseLeaveBlank: "使用しない場合は空欄にしてください"
useTotp: "ワンタイムパスワードを使う"
useBackupCode: "バックアップコードを使う"
launchApp: "アプリを起動"
useNativeUIForVideoAudioPlayer: "動画・音声の再生にブラウザのUIを使用する"
keepOriginalFilename: "オリジナルのファイル名を保持"
keepOriginalFilenameDescription: "この設定をオフにすると、アップロード時にファイル名が自動でランダム文字列に置き換えられます。"
noDescription: "説明文はありません"
alwaysConfirmFollow: "フォローの際常に確認する"
inquiry: "お問い合わせ"
_bubbleGame: _bubbleGame:
howToPlay: "遊び方" howToPlay: "遊び方"
hold: "ホールド"
_score:
score: "スコア"
scoreYen: "稼いだ金額"
highScore: "ハイスコア"
maxChain: "最大チェーン数"
yen: "{yen}円"
estimatedQty: "{qty}個分"
scoreSweets: "おにぎり {onigiriQtyWithUnit}"
_howToPlay: _howToPlay:
section1: "位置を調整してハコにモノを落とします。" section1: "位置を調整してハコにモノを落とします。"
section2: "同じ種類のモノがくっつくと別のモノに変化して、スコアが得られます。" section2: "同じ種類のモノがくっつくと別のモノに変化して、スコアが得られます。"
@@ -1677,7 +1650,6 @@ _role:
gtlAvailable: "グローバルタイムラインの閲覧" gtlAvailable: "グローバルタイムラインの閲覧"
ltlAvailable: "ローカルタイムラインの閲覧" ltlAvailable: "ローカルタイムラインの閲覧"
canPublicNote: "パブリック投稿の許可" canPublicNote: "パブリック投稿の許可"
mentionMax: "ノート内の最大メンション数"
canInvite: "サーバー招待コードの発行" canInvite: "サーバー招待コードの発行"
inviteLimit: "招待コードの作成可能数" inviteLimit: "招待コードの作成可能数"
inviteLimitCycle: "招待コードの発行間隔" inviteLimitCycle: "招待コードの発行間隔"
@@ -1701,14 +1673,8 @@ _role:
canUseTranslator: "翻訳機能の利用" canUseTranslator: "翻訳機能の利用"
avatarDecorationLimit: "アイコンデコレーションの最大取付個数" avatarDecorationLimit: "アイコンデコレーションの最大取付個数"
_condition: _condition:
roleAssignedTo: "マニュアルロールにアサイン済み"
isLocal: "ローカルユーザー" isLocal: "ローカルユーザー"
isRemote: "リモートユーザー" isRemote: "リモートユーザー"
isCat: "猫ユーザー"
isBot: "botユーザー"
isSuspended: "サスペンド済みユーザー"
isLocked: "鍵アカウントユーザー"
isExplorable: "「アカウントを見つけやすくする」が有効なユーザー"
createdLessThan: "アカウント作成から~以内" createdLessThan: "アカウント作成から~以内"
createdMoreThan: "アカウント作成から~経過" createdMoreThan: "アカウント作成から~経過"
followersLessThanOrEq: "フォロワー数が~以下" followersLessThanOrEq: "フォロワー数が~以下"
@@ -1788,7 +1754,6 @@ _plugin:
installWarn: "信頼できないプラグインはインストールしないでください。" installWarn: "信頼できないプラグインはインストールしないでください。"
manage: "プラグインの管理" manage: "プラグインの管理"
viewSource: "ソースを表示" viewSource: "ソースを表示"
viewLog: "ログを表示"
_preferencesBackups: _preferencesBackups:
list: "作成したバックアップ" list: "作成したバックアップ"
@@ -1995,7 +1960,8 @@ _2fa:
alreadyRegistered: "既に設定は完了しています。" alreadyRegistered: "既に設定は完了しています。"
registerTOTP: "認証アプリの設定を開始" registerTOTP: "認証アプリの設定を開始"
step1: "まず、{a}や{b}などの認証アプリをお使いのデバイスにインストールします。" step1: "まず、{a}や{b}などの認証アプリをお使いのデバイスにインストールします。"
step2: "次に、表示されているQRコードをアプリでスキャンするか、ボタンをクリックして端末上でアプリを開きます。" step2: "次に、表示されているQRコードをアプリでスキャンます。"
step2Click: "QRコードをクリックすると、お使いの端末にインストールされている認証アプリやキーリングに登録できます。"
step2Uri: "デスクトップアプリを使用する場合は次のURIを入力します" step2Uri: "デスクトップアプリを使用する場合は次のURIを入力します"
step3Title: "確認コードを入力" step3Title: "確認コードを入力"
step3: "アプリに表示されている確認コード(トークン)を入力します。" step3: "アプリに表示されている確認コード(トークン)を入力します。"
@@ -2019,7 +1985,6 @@ _2fa:
backupCodesDescription: "認証アプリが使用できなくなった場合、以下のバックアップコードを使ってアカウントにアクセスできます。これらのコードは必ず安全な場所に保管してください。各コードは一回だけ使用できます。" backupCodesDescription: "認証アプリが使用できなくなった場合、以下のバックアップコードを使ってアカウントにアクセスできます。これらのコードは必ず安全な場所に保管してください。各コードは一回だけ使用できます。"
backupCodeUsedWarning: "バックアップコードが使用されました。認証アプリが使えなくなっている場合、なるべく早く認証アプリを再設定してください。" backupCodeUsedWarning: "バックアップコードが使用されました。認証アプリが使えなくなっている場合、なるべく早く認証アプリを再設定してください。"
backupCodesExhaustedWarning: "バックアップコードが全て使用されました。認証アプリを利用できない場合、これ以上アカウントにアクセスできなくなります。認証アプリを再登録してください。" backupCodesExhaustedWarning: "バックアップコードが全て使用されました。認証アプリを利用できない場合、これ以上アカウントにアクセスできなくなります。認証アプリを再登録してください。"
moreDetailedGuideHere: "詳細なガイドはこちら"
_permissions: _permissions:
"read:account": "アカウントの情報を見る" "read:account": "アカウントの情報を見る"
@@ -2296,7 +2261,6 @@ _play:
title: "タイトル" title: "タイトル"
script: "スクリプト" script: "スクリプト"
summary: "説明" summary: "説明"
visibilityDescription: "非公開に設定するとプロフィールに表示されなくなりますが、URLを知っている人は引き続きアクセスできます。"
_pages: _pages:
newPage: "ページの作成" newPage: "ページの作成"
@@ -2342,8 +2306,6 @@ _pages:
section: "セクション" section: "セクション"
image: "画像" image: "画像"
button: "ボタン" button: "ボタン"
dynamic: "動的ブロック"
dynamicDescription: "このブロックは廃止されています。今後は{play}を利用してください。"
note: "ノート埋め込み" note: "ノート埋め込み"
_note: _note:
@@ -2376,10 +2338,8 @@ _notification:
sendTestNotification: "テスト通知を送信する" sendTestNotification: "テスト通知を送信する"
notificationWillBeDisplayedLikeThis: "通知はこのように表示されます" notificationWillBeDisplayedLikeThis: "通知はこのように表示されます"
reactedBySomeUsers: "{n}人がリアクションしました" reactedBySomeUsers: "{n}人がリアクションしました"
likedBySomeUsers: "{n}人がいいねしました"
renotedBySomeUsers: "{n}人がリノートしました" renotedBySomeUsers: "{n}人がリノートしました"
followedBySomeUsers: "{n}人にフォローされました" followedBySomeUsers: "{n}人にフォローされました"
flushNotification: "通知の履歴をリセットする"
_types: _types:
all: "すべて" all: "すべて"
@@ -2474,7 +2434,7 @@ _moderationLogTypes:
updateCustomEmoji: "カスタム絵文字更新" updateCustomEmoji: "カスタム絵文字更新"
deleteCustomEmoji: "カスタム絵文字削除" deleteCustomEmoji: "カスタム絵文字削除"
updateServerSettings: "サーバー設定更新" updateServerSettings: "サーバー設定更新"
updateUserNote: "ユーザーのモデレーションノート更新" updateUserNote: "モデレーションノート更新"
deleteDriveFile: "ファイルを削除" deleteDriveFile: "ファイルを削除"
deleteNote: "ノートを削除" deleteNote: "ノートを削除"
createGlobalAnnouncement: "全体のお知らせを作成" createGlobalAnnouncement: "全体のお知らせを作成"
@@ -2486,7 +2446,6 @@ _moderationLogTypes:
resetPassword: "パスワードをリセット" resetPassword: "パスワードをリセット"
suspendRemoteInstance: "リモートサーバーを停止" suspendRemoteInstance: "リモートサーバーを停止"
unsuspendRemoteInstance: "リモートサーバーを再開" unsuspendRemoteInstance: "リモートサーバーを再開"
updateRemoteInstanceNote: "リモートサーバーのモデレーションノート更新"
markSensitiveDriveFile: "ファイルをセンシティブ付与" markSensitiveDriveFile: "ファイルをセンシティブ付与"
unmarkSensitiveDriveFile: "ファイルをセンシティブ解除" unmarkSensitiveDriveFile: "ファイルをセンシティブ解除"
resolveAbuseReport: "通報を解決" resolveAbuseReport: "通報を解決"
@@ -2612,29 +2571,8 @@ _reversi:
opponentHasSettingsChanged: "相手が設定を変更しました" opponentHasSettingsChanged: "相手が設定を変更しました"
allowIrregularRules: "変則許可 (完全フリー)" allowIrregularRules: "変則許可 (完全フリー)"
disallowIrregularRules: "変則なし" disallowIrregularRules: "変則なし"
showBoardLabels: "盤面に行・列番号を表示"
useAvatarAsStone: "石をアイコンにする"
_offlineScreen: _offlineScreen:
title: "オフライン - サーバーに接続できません" title: "オフライン - サーバーに接続できません"
header: "サーバーに接続できません" header: "サーバーに接続できません"
_urlPreviewSetting:
title: "URLプレビューの設定"
enable: "URLプレビューを有効にする"
timeout: "プレビュー取得時のタイムアウト(ms)"
timeoutDescription: "プレビュー取得の所要時間がこの値を超えた場合、プレビューは生成されません。"
maximumContentLength: "Content-Lengthの最大値(byte)"
maximumContentLengthDescription: "Content-Lengthがこの値を超えた場合、プレビューは生成されません。"
requireContentLength: "Content-Lengthが取得できた場合のみプレビューを生成"
requireContentLengthDescription: "相手サーバがContent-Lengthを返さない場合、プレビューは生成されません。"
userAgent: "User-Agent"
userAgentDescription: "プレビュー取得時に使用されるUser-Agentを設定します。空欄の場合、デフォルトのUser-Agentが使用されます。"
summaryProxy: "プレビューを生成するプロキシのエンドポイント"
summaryProxyDescription: "Misskey本体ではなく、サマリープロキシを使用してプレビューを生成します。"
summaryProxyDescription2: "プロキシには下記パラメータがクエリ文字列として連携されます。プロキシ側がこれらをサポートしない場合、設定値は無視されます。"
_mediaControls:
pip: "ピクチャインピクチャ"
playbackRate: "再生速度"
loop: "ループ再生"

View File

@@ -991,7 +991,6 @@ neverShow: "今後表示しない"
remindMeLater: "また後で" remindMeLater: "また後で"
didYouLikeMisskey: "Misskey気に入ってくれた" didYouLikeMisskey: "Misskey気に入ってくれた"
pleaseDonate: "Misskeyは{host}が使うとる無料のソフトウェアやで。これからも開発を続けれるように、寄付したってな~。" pleaseDonate: "Misskeyは{host}が使うとる無料のソフトウェアやで。これからも開発を続けれるように、寄付したってな~。"
correspondingSourceIsAvailable: "{anchor}"
roles: "ロール" roles: "ロール"
role: "ロール" role: "ロール"
noRole: "ロールはありまへん" noRole: "ロールはありまへん"
@@ -1209,7 +1208,6 @@ hemisphere: "住んでる地域"
withSensitive: "センシティブなファイルを含むノートを表示" withSensitive: "センシティブなファイルを含むノートを表示"
userSaysSomethingSensitive: "{name}のセンシティブなファイルを含む投稿" userSaysSomethingSensitive: "{name}のセンシティブなファイルを含む投稿"
enableHorizontalSwipe: "スワイプしてタブを切り替える" enableHorizontalSwipe: "スワイプしてタブを切り替える"
surrender: "やめとく"
_bubbleGame: _bubbleGame:
howToPlay: "遊び方" howToPlay: "遊び方"
_howToPlay: _howToPlay:

View File

@@ -640,7 +640,6 @@ icon: "아바타"
replies: "답하기" replies: "답하기"
renotes: "리노트" renotes: "리노트"
attach: "옇기" attach: "옇기"
surrender: "아이예"
_initialAccountSetting: _initialAccountSetting:
startTutorial: "길라잡이 하기" startTutorial: "길라잡이 하기"
_initialTutorial: _initialTutorial:

View File

@@ -991,7 +991,6 @@ neverShow: "다시 보지 않기"
remindMeLater: "나중에 알림" remindMeLater: "나중에 알림"
didYouLikeMisskey: "Misskey가 마음에 드시나요?" didYouLikeMisskey: "Misskey가 마음에 드시나요?"
pleaseDonate: "Misskey는 {host} 서버의 무료 소프트웨어입니다. 앞으로도 개발을 이어 나가려면 후원이 절실히 필요합니다!" pleaseDonate: "Misskey는 {host} 서버의 무료 소프트웨어입니다. 앞으로도 개발을 이어 나가려면 후원이 절실히 필요합니다!"
correspondingSourceIsAvailable: "소스 코드는 {anchor}에서 받아보실 수 있습니다."
roles: "역할" roles: "역할"
role: "역할" role: "역할"
noRole: "역할이 없습니다" noRole: "역할이 없습니다"
@@ -1169,12 +1168,6 @@ confirmShowRepliesAll: "이 조작은 되돌릴 수 없습니다. 정말로 타
confirmHideRepliesAll: "이 조작은 되돌릴 수 없습니다. 정말로 타임라인에 현재 팔로우 중인 사람 전원의 답글이 나오지 않게 하시겠습니까?" confirmHideRepliesAll: "이 조작은 되돌릴 수 없습니다. 정말로 타임라인에 현재 팔로우 중인 사람 전원의 답글이 나오지 않게 하시겠습니까?"
externalServices: "외부 서비스" externalServices: "외부 서비스"
sourceCode: "소스 코드" sourceCode: "소스 코드"
sourceCodeIsNotYetProvided: "소스 코드를 아직 제공하지 않습니다. 이 문제를 해결하려면 관리자에게 문의해 주세요."
repositoryUrl: "저장소 URL"
repositoryUrlDescription: "소스 코드를 공개한 저장소가 있는 경우, 그 URL을 적습니다. Misskey를 원본 그대로 (소스 코드를 어떤 식으로도 변경하지 않고) 쓰고 있는 경우 https://github.com/misskey-dev/misskey 라고 적습니다."
repositoryUrlOrTarballRequired: "저장소를 공개하지 않은 경우 대신 tarball을 제공할 필요가 있습니다. 세부사항은 .config/example.yml을 참조해 주세요."
feedback: "피드백"
feedbackUrl: "피드백 URL"
impressum: "운영자 정보" impressum: "운영자 정보"
impressumUrl: "운영자 정보 URL" impressumUrl: "운영자 정보 URL"
impressumDescription: "독일 등의 일부 나라와 지역에서는 꼭 표시해야 합니다(Impressum)." impressumDescription: "독일 등의 일부 나라와 지역에서는 꼭 표시해야 합니다(Impressum)."
@@ -1217,7 +1210,6 @@ hemisphere: "거주 지역"
withSensitive: "민감한 파일이 포함된 노트 보기" withSensitive: "민감한 파일이 포함된 노트 보기"
userSaysSomethingSensitive: "{name}의 민감한 파일이 포함된 게시물" userSaysSomethingSensitive: "{name}의 민감한 파일이 포함된 게시물"
enableHorizontalSwipe: "스와이프하여 탭 전환" enableHorizontalSwipe: "스와이프하여 탭 전환"
surrender: "그만두기"
_bubbleGame: _bubbleGame:
howToPlay: "설명" howToPlay: "설명"
_howToPlay: _howToPlay:
@@ -1764,8 +1756,6 @@ _aboutMisskey:
contributors: "주요 기여자" contributors: "주요 기여자"
allContributors: "모든 기여자" allContributors: "모든 기여자"
source: "소스 코드" source: "소스 코드"
original: "원본"
thisIsModifiedVersion: "{name}에서는 원본 미스키를 수정한 버전을 사용하고 있습니다."
translation: "Misskey를 번역하기" translation: "Misskey를 번역하기"
donate: "Misskey에 기부하기" donate: "Misskey에 기부하기"
morePatrons: "이 외에도 다른 많은 분들이 도움을 주시고 계십니다. 감사합니다🥰" morePatrons: "이 외에도 다른 많은 분들이 도움을 주시고 계십니다. 감사합니다🥰"
@@ -2381,7 +2371,6 @@ _moderationLogTypes:
resetPassword: "비밀번호 재설정" resetPassword: "비밀번호 재설정"
suspendRemoteInstance: "리모트 서버를 정지" suspendRemoteInstance: "리모트 서버를 정지"
unsuspendRemoteInstance: "리모트 서버의 정지를 해제" unsuspendRemoteInstance: "리모트 서버의 정지를 해제"
updateRemoteInstanceNote: "리모트 서버의 조정 기록 갱신"
markSensitiveDriveFile: "파일에 열람주의를 설정" markSensitiveDriveFile: "파일에 열람주의를 설정"
unmarkSensitiveDriveFile: "파일에 열람주의를 해제" unmarkSensitiveDriveFile: "파일에 열람주의를 해제"
resolveAbuseReport: "신고 처리" resolveAbuseReport: "신고 처리"

View File

@@ -463,7 +463,6 @@ options: "Alternativ"
icon: "Avatar" icon: "Avatar"
replies: "Svar" replies: "Svar"
renotes: "Renote" renotes: "Renote"
surrender: "Avbryt"
_initialAccountSetting: _initialAccountSetting:
theseSettingsCanEditLater: "Du kan endre disse innstillingene senere." theseSettingsCanEditLater: "Du kan endre disse innstillingene senere."
_achievements: _achievements:

View File

@@ -1011,7 +1011,6 @@ renotes: "Repostar"
keepScreenOn: "Manter a tela do dispositivo sempre ligada" keepScreenOn: "Manter a tela do dispositivo sempre ligada"
flip: "Inversão" flip: "Inversão"
lastNDays: "Últimos {n} dias" lastNDays: "Últimos {n} dias"
surrender: "Cancelar"
_initialAccountSetting: _initialAccountSetting:
followUsers: "Siga usuários que lhe interessam para criar a sua linha do tempo." followUsers: "Siga usuários que lhe interessam para criar a sua linha do tempo."
_serverSettings: _serverSettings:

View File

@@ -1085,7 +1085,6 @@ loadReplies: "Показать ответы"
sourceCode: "Исходный код" sourceCode: "Исходный код"
flip: "Переворот" flip: "Переворот"
lastNDays: "Последние {n} сут" lastNDays: "Последние {n} сут"
surrender: "Этот пост не может быть отменен."
_initialAccountSetting: _initialAccountSetting:
accountCreated: "Аккаунт успешно создан!" accountCreated: "Аккаунт успешно создан!"
letsStartAccountSetup: "Давайте настроим вашу учётную запись." letsStartAccountSetup: "Давайте настроим вашу учётную запись."

View File

@@ -8,12 +8,12 @@ search: "ค้นหา"
notifications: "การเเจ้งเตือน" notifications: "การเเจ้งเตือน"
username: "ชื่อผู้ใช้" username: "ชื่อผู้ใช้"
password: "รหัสผ่าน" password: "รหัสผ่าน"
forgotPassword: "ลืมรหัสผ่าน" forgotPassword: "ลืมรหัสผ่านใช่ไหม"
fetchingAsApObject: "กำลังดึงข้อมูลจากสหพันธ์..." fetchingAsApObject: "กำลังดึงข้อมูลจากสหพันธ์..."
ok: "ตกลง" ok: "ตกลง"
gotIt: "เข้าใจแล้ว !" gotIt: "เข้าใจแล้ว !"
cancel: "ยกเลิก" cancel: "ยกเลิก"
noThankYou: "ไม่เอาดีกว่า" noThankYou: "ไม่เป็นไร"
enterUsername: "กรอกชื่อผู้ใช้" enterUsername: "กรอกชื่อผู้ใช้"
renotedBy: "รีโน้ตโดย {user}" renotedBy: "รีโน้ตโดย {user}"
noNotes: "ไม่มีโน้ต" noNotes: "ไม่มีโน้ต"
@@ -31,16 +31,16 @@ login: "เข้าสู่ระบบ"
loggingIn: "กำลังเข้าสู่ระบบ" loggingIn: "กำลังเข้าสู่ระบบ"
logout: "ออกจากระบบ" logout: "ออกจากระบบ"
signup: "สร้างบัญชีผู้ใช้" signup: "สร้างบัญชีผู้ใช้"
uploading: "กำลังอัโหลด" uploading: "กำลังอัโหลด..."
save: "บันทึก" save: "บันทึก"
users: "ผู้ใช้งาน" users: "ผู้ใช้งาน"
addUser: "เพิ่มผู้ใช้" addUser: "เพิ่มผู้ใช้"
favorite: "รายการโปรด" favorite: "รายการโปรด"
favorites: "รายการโปรด" favorites: "รายการโปรด"
unfavorite: "ลบออกจากรายการโปรด" unfavorite: "ลบออกจากรายการโปรด"
favorited: "เพิ่มลงรายการโปรดแล้ว" favorited: "เพิ่มแล้วในรายการโปรด"
alreadyFavorited: "เพิ่มลงรายการโปรดอยู่แล้ว" alreadyFavorited: "เพิ่มในรายการโปรดอยู่แล้ว"
cantFavorite: "ไม่สามารถเพิ่มลงรายการโปรดได้" cantFavorite: "ไม่สามารถเพิ่มในรายการโปรดได้"
pin: "ปักหมุด" pin: "ปักหมุด"
unpin: "เลิกปักหมุด" unpin: "เลิกปักหมุด"
copyContent: "คัดลอกเนื้อหา" copyContent: "คัดลอกเนื้อหา"
@@ -65,18 +65,18 @@ loadMore: "แสดงเพิ่มเติม"
showMore: "แสดงเพิ่มเติม" showMore: "แสดงเพิ่มเติม"
showLess: "ปิด" showLess: "ปิด"
youGotNewFollower: "ได้ติดตามคุณ" youGotNewFollower: "ได้ติดตามคุณ"
receiveFollowRequest: "มีคำขอติดตามส่งมาหา" receiveFollowRequest: "คำขอผู้ติดตามที่ได้รับ"
followRequestAccepted: "การติดตามได้รับการอนุมัติแล้ว" followRequestAccepted: "อนุมัติการติดตามแล้ว"
mention: "กล่าวถึง" mention: "กล่าวถึง"
mentions: "พูดถึง" mentions: "พูดถึง"
directNotes: "โพสต์แบบไดเร็กต์" directNotes: "ไดเร็คโน้ต"
importAndExport: "นำเข้า / ส่งออก" importAndExport: "นำเข้า / ส่งออก"
import: "นำเข้า" import: "นำเข้า"
export: "ส่งออก" export: "ส่งออก"
files: "ไฟล์" files: "ไฟล์"
download: "ดาวน์โหลด" download: "ดาวน์โหลด"
driveFileDeleteConfirm: "ต้องการลบไฟล์ “{name}” ใช่ไหม? โน้ตที่แนบมากับไฟล์นี้ก็จะถูกลบไปด้วย" driveFileDeleteConfirm: "ต้องการลบไฟล์ “{name}” ใช่หรือไม่? โน้ตที่แนบมากับไฟล์นี้ก็จะถูกลบไปด้วย"
unfollowConfirm: "ต้องการเลิกติดตาม {name} ใช่ไหม?" unfollowConfirm: "ต้องการเลิกติดตาม {name}?"
exportRequested: "คุณได้ร้องขอการส่งออก อาจใช้เวลาสักครู่ และจะถูกเพิ่มในไดรฟ์ของคุณเมื่อเสร็จสิ้นแล้ว" exportRequested: "คุณได้ร้องขอการส่งออก อาจใช้เวลาสักครู่ และจะถูกเพิ่มในไดรฟ์ของคุณเมื่อเสร็จสิ้นแล้ว"
importRequested: "คุณได้ร้องขอการนำเข้า การดำเนินการนี้อาจใช้เวลาสักครู่" importRequested: "คุณได้ร้องขอการนำเข้า การดำเนินการนี้อาจใช้เวลาสักครู่"
lists: "รายชื่อ" lists: "รายชื่อ"
@@ -128,9 +128,9 @@ emojiPickerDisplay: "แสดงตัวจิ้มเอโมจิ"
overwriteFromPinnedEmojisForReaction: "เขียนทับการตั้งค่ารีแอคชั่น" overwriteFromPinnedEmojisForReaction: "เขียนทับการตั้งค่ารีแอคชั่น"
overwriteFromPinnedEmojis: "เขียนทับการตั้งค่าทั่วไป" overwriteFromPinnedEmojis: "เขียนทับการตั้งค่าทั่วไป"
reactionSettingDescription2: "ลากเพื่อจัดลำดับใหม่ คลิกที่เอโมจินั้นเพื่อลบ กด “+” เพื่อเพิ่ม" reactionSettingDescription2: "ลากเพื่อจัดลำดับใหม่ คลิกที่เอโมจินั้นเพื่อลบ กด “+” เพื่อเพิ่ม"
rememberNoteVisibility: "จำการตั้งค่าการมองเห็นโน้ต" rememberNoteVisibility: "จดจำการตั้งค่าการมองเห็นตัวโน้ต"
attachCancel: "ยกเลิกแนบไฟล์" attachCancel: "ลบไฟล์ออกที่แนบมา"
deleteFile: "ลบไฟล์ออก" deleteFile: "ลบไฟล์ออกแล้ว"
markAsSensitive: "ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน" markAsSensitive: "ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน"
unmarkAsSensitive: "ยกเลิกทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน" unmarkAsSensitive: "ยกเลิกทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน"
enterFileName: "พิมพ์ชื่อไฟล์" enterFileName: "พิมพ์ชื่อไฟล์"
@@ -138,14 +138,14 @@ mute: "ปิดเสียง"
unmute: "ยกเลิกการปิดเสียง" unmute: "ยกเลิกการปิดเสียง"
renoteMute: "ปิดเสียงรีโน้ต" renoteMute: "ปิดเสียงรีโน้ต"
renoteUnmute: "เปิดเสียง รีโน้ต" renoteUnmute: "เปิดเสียง รีโน้ต"
block: "บล็อ" block: "บล็อ"
unblock: "เลิกบล็อก" unblock: "เลิกปิดกั้น"
suspend: "ระงับ" suspend: "ถูกระงับ"
unsuspend: "เลิกระงับ" unsuspend: "ยกเลิกระงับ"
blockConfirm: "ต้องการบล็อกบัญชีนี้ใช่ไหม?" blockConfirm: "ต้องการบล็อกบัญชีนี้?"
unblockConfirm: "ต้องการเลิกบล็อบัญชีนี้ใช่ไหม?" unblockConfirm: "ต้องการปลดบล็อบัญชีนี้?"
suspendConfirm: "ต้องการระงับบัญชีนี้ใช่ไหม?" suspendConfirm: "ต้องการระงับบัญชีนี้?"
unsuspendConfirm: "ต้องการยกเลิกการระงับบัญชีนี้ใช่ไหม?" unsuspendConfirm: "ต้องการยกเลิกการระงับบัญชีนี้?"
selectList: "เลือกรายชื่อ" selectList: "เลือกรายชื่อ"
editList: "แก้ไขรายชื่อ" editList: "แก้ไขรายชื่อ"
selectChannel: "เลือกช่อง" selectChannel: "เลือกช่อง"
@@ -162,13 +162,13 @@ emojiUrl: "URL ของเอโมจิ"
addEmoji: "แทรกเอโมจิ" addEmoji: "แทรกเอโมจิ"
settingGuide: "การตั้งค่าที่แนะนำ" settingGuide: "การตั้งค่าที่แนะนำ"
cacheRemoteFiles: "แคชไฟล์ระยะไกล" cacheRemoteFiles: "แคชไฟล์ระยะไกล"
cacheRemoteFilesDescription: "หากเปิดใช้งาน ไฟล์ระยะไกลจะถูกแคชไว้ ทำให้แสดงภาพเร็วขึ้น แต่ก็ใช้พื้นที่เก็บข้อมูลของเซิร์ฟเวอร์มากขึ้นเช่นกัน สำหรับขีดจำกัดที่ผู้ใช้ระยะไกลถูกแคชไว้จะขึ้นอยู่กับความจุไดรฟ์ตามบทบาทของเขา เมื่อเกินแล้วไฟล์เก่าจะถูกลบออกและเก็บเป็นลิงก์แทน หากปิดใช้งาน ไฟล์ระยะไกลจะถูกเก็บเป็นลิงก์ตั้งแต่ต้น เราแนะนำให้ตั้งค่า proxyRemoteFiles ใน default.yml เป็น true เพื่อสร้างธัมบ์เนลและปกป้องความเป็นส่วนตัวของผู้ใช้" cacheRemoteFilesDescription: "เมื่อปิดใช้งานการตั้งค่านี้ ไฟล์ระยะไกลนั้นจะถูกโหลดโดยตรงจากอินสแตนซ์ระยะไกล แต่กรณีการปิดใช้งานนี้จะช่วยลดปริมาณการใช้พื้นที่จัดเก็บข้อมูล แต่เพิ่มปริมาณการใช้งาน เพราะเนื่องจากจะไม่มีการสร้างภาพขนาดย่อ"
youCanCleanRemoteFilesCache: "คุณสามารถล้างแคชได้โดยคลิกที่ปุ่ม 🗑️ ในมุมมองการจัดการไฟล์" youCanCleanRemoteFilesCache: "คุณสามารถล้างแคชได้โดยคลิกที่ปุ่ม 🗑️ ในมุมมองการจัดการไฟล์"
cacheRemoteSensitiveFiles: "แคชไฟล์ระยะไกลที่มีเนื้อหาละเอียดอ่อน" cacheRemoteSensitiveFiles: "แคชไฟล์ระยะไกลที่มีเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน"
cacheRemoteSensitiveFilesDescription: "เมื่อปิดการใช้งานการตั้งค่านี้ ไฟล์ระยะไกลที่มีเครื่องหมายว่ามีเนื้อหาละเอียดอ่อนนั้นจะถูกโหลดโดยตรงจากอินสแตนซ์ระยะไกลโดยที่ไม่มีการแคช" cacheRemoteSensitiveFilesDescription: "เมื่อปิดการใช้งานการตั้งค่านี้ ไฟล์ระยะไกลที่มีเครื่องหมายว่ามีเนื้อหาละเอียดอ่อนนั้นจะถูกโหลดโดยตรงจากอินสแตนซ์ระยะไกลโดยที่ไม่มีการแคช"
flagAsBot: "ทำเครื่องหมายบอกว่าบัญชีนี้เป็นบอ" flagAsBot: "ทำเครื่องหมายบอกว่าบัญชีนี้เป็นบอ"
flagAsBotDescription: "การเปิดใช้งานตัวเลือกนี้หากบัญชีนี้ถูกควบคุมโดยนักเขียนโปรแกรม หรือ ถ้าหากเปิดใช้งาน มันจะทำหน้าที่เป็นแฟล็กสำหรับนักพัฒนารายอื่นๆ และเพื่อป้องกันการโต้ตอบแบบไม่มีที่สิ้นสุดกับบอทตัวอื่นๆ และยังสามารถปรับเปลี่ยนระบบภายในของ Misskey เพื่อปฏิบัติต่อบัญชีนี้เป็นบอท" flagAsBotDescription: "การเปิดใช้งานตัวเลือกนี้หากบัญชีนี้ถูกควบคุมโดยนักเขียนโปรแกรม หรือ ถ้าหากเปิดใช้งาน มันจะทำหน้าที่เป็นแฟล็กสำหรับนักพัฒนารายอื่นๆ และเพื่อป้องกันการโต้ตอบแบบไม่มีที่สิ้นสุดกับบอทตัวอื่นๆ และยังสามารถปรับเปลี่ยนระบบภายในของ Misskey เพื่อปฏิบัติต่อบัญชีนี้เป็นบอท"
flagAsCat: "เมี้ยววววววววววววววว!!!!!!!!!!!" flagAsCat: "เมี้ยววววววว!!!!!!!!!!! (ทำเครื่องหมายว่าบัญชีนี้เป็นแมว)"
flagAsCatDescription: "เหมียวเหมียวเมี้ยว??" flagAsCatDescription: "เหมียวเหมียวเมี้ยว??"
flagShowTimelineReplies: "แสดงตอบกลับ ในไทม์ไลน์" flagShowTimelineReplies: "แสดงตอบกลับ ในไทม์ไลน์"
flagShowTimelineRepliesDescription: "แสดงการตอบกลับของผู้ใช้งานไปยังโน้ตของผู้ใช้งานรายอื่นๆในไทม์ไลน์หากได้เปิดเอาไว้" flagShowTimelineRepliesDescription: "แสดงการตอบกลับของผู้ใช้งานไปยังโน้ตของผู้ใช้งานรายอื่นๆในไทม์ไลน์หากได้เปิดเอาไว้"
@@ -180,7 +180,7 @@ showOnRemote: "ดูบนอินสแตนซ์ระยะไกล"
general: "ทั่วไป" general: "ทั่วไป"
wallpaper: "ภาพพื้นหลัง" wallpaper: "ภาพพื้นหลัง"
setWallpaper: "ตั้งค่าภาพพื้นหลัง" setWallpaper: "ตั้งค่าภาพพื้นหลัง"
removeWallpaper: "นำภาพพื้นหลังออก" removeWallpaper: "นำภาพพื้นหลังออก"
searchWith: "ค้นหา: {q}" searchWith: "ค้นหา: {q}"
youHaveNoLists: "คุณไม่มีรายชื่อใดๆ " youHaveNoLists: "คุณไม่มีรายชื่อใดๆ "
followConfirm: "ต้องการติดตาม {name} ใช่ไหม?" followConfirm: "ต้องการติดตาม {name} ใช่ไหม?"
@@ -189,11 +189,11 @@ proxyAccountDescription: "บัญชีพร็อกซี่ คือ บ
host: "โฮสต์" host: "โฮสต์"
selectUser: "เลือกผู้ใช้งาน" selectUser: "เลือกผู้ใช้งาน"
recipient: "ผู้รับ" recipient: "ผู้รับ"
annotation: "หมายเหตุประกอบ" annotation: "ความคิดเห็น"
federation: "สหพันธ์" federation: "สหพันธ์"
instances: "อินสแตนซ์" instances: "อินสแตนซ์"
registeredAt: "วันที่ลงทะเบียน" registeredAt: "จดทะเบียนที่"
latestRequestReceivedAt: "คำขอล่าสุดที่ได้รับ" latestRequestReceivedAt: "ได้รับคำขอล่าสุดไปแล้ว"
latestStatus: "สถานะล่าสุด" latestStatus: "สถานะล่าสุด"
storageUsage: "พื้นที่จัดเก็บข้อมูลที่ใช้ไป" storageUsage: "พื้นที่จัดเก็บข้อมูลที่ใช้ไป"
charts: "โดดเด่น" charts: "โดดเด่น"
@@ -215,10 +215,10 @@ disk: "ดิสก์"
instanceInfo: "ข้อมูลอินสแตนซ์" instanceInfo: "ข้อมูลอินสแตนซ์"
statistics: "สถิติการใช้งาน" statistics: "สถิติการใช้งาน"
clearQueue: "ล้างคิว" clearQueue: "ล้างคิว"
clearQueueConfirmTitle: "ต้องการล้างคิวใช่ไหม?" clearQueueConfirmTitle: "คุณแน่ใจแล้วหรอว่าต้องการที่จะล้างคิว?"
clearQueueConfirmText: "โพสต์ที่ยังค้างในคิวจะไม่ถูกจัดส่งอีกต่อไป โดยปกติแล้วการดำเนินการนี้ไม่จำเป็น" clearQueueConfirmText: "โพสต์ที่ยังค้างในคิวจะไม่ถูกจัดส่งอีกต่อไป โดยปกติแล้วการดำเนินการนี้ไม่จำเป็น"
clearCachedFiles: "ล้างแคช" clearCachedFiles: "ล้างแคช"
clearCachedFilesConfirm: "ต้องการลบไฟล์ระยะไกลที่แคชไว้ทั้งหมดใช่ไหม?" clearCachedFilesConfirm: "ต้องการลบไฟล์ระยะไกลที่แคชไว้ทั้งหมด?"
blockedInstances: "อินสแตนซ์ที่ถูกบล็อก" blockedInstances: "อินสแตนซ์ที่ถูกบล็อก"
blockedInstancesDescription: "ระบุชื่อโฮสต์ของอินสแตนซ์ที่คุณต้องการบล็อก อินสแตนซ์ที่อยู่ในรายการนั้นจะไม่สามารถพูดคุยกับอินสแตนซ์นี้ได้อีกต่อไป" blockedInstancesDescription: "ระบุชื่อโฮสต์ของอินสแตนซ์ที่คุณต้องการบล็อก อินสแตนซ์ที่อยู่ในรายการนั้นจะไม่สามารถพูดคุยกับอินสแตนซ์นี้ได้อีกต่อไป"
silencedInstances: "ปิดปากอินสแตนซ์นี้แล้ว" silencedInstances: "ปิดปากอินสแตนซ์นี้แล้ว"
@@ -228,7 +228,7 @@ mutedUsers: "ผู้ใช้ที่ถูกปิดเสียง"
blockedUsers: "ผู้ใช้ที่ถูกบล็อก" blockedUsers: "ผู้ใช้ที่ถูกบล็อก"
noUsers: "ไม่พบผู้ใช้งาน" noUsers: "ไม่พบผู้ใช้งาน"
editProfile: "แก้ไขโปรไฟล์" editProfile: "แก้ไขโปรไฟล์"
noteDeleteConfirm: "ต้องการลบโน้ตนี้ใช่ไหม?" noteDeleteConfirm: "ต้องการลบโน้ตนี้?"
pinLimitExceeded: "คุณไม่สามารถปักหมุดโน้ตเพิ่มเติมใดๆได้อีก" pinLimitExceeded: "คุณไม่สามารถปักหมุดโน้ตเพิ่มเติมใดๆได้อีก"
intro: "การติดตั้ง Misskey เสร็จสิ้นแล้วนะ! โปรดสร้างผู้ใช้งานที่เป็นผู้ดูแลระบบ" intro: "การติดตั้ง Misskey เสร็จสิ้นแล้วนะ! โปรดสร้างผู้ใช้งานที่เป็นผู้ดูแลระบบ"
done: "เสร็จสิ้น" done: "เสร็จสิ้น"
@@ -237,7 +237,7 @@ preview: "แสดงตัวอย่าง"
default: "ค่าเริ่มต้น" default: "ค่าเริ่มต้น"
defaultValueIs: "ค่าเริ่มต้น: {value}" defaultValueIs: "ค่าเริ่มต้น: {value}"
noCustomEmojis: "ไม่มีเอโมจิ" noCustomEmojis: "ไม่มีเอโมจิ"
noJobs: "ไม่มีงาน" noJobs: "ไม่มีชิ้นงาน"
federating: "สหพันธ์" federating: "สหพันธ์"
blocked: "ถูกบล็อก" blocked: "ถูกบล็อก"
suspended: "ถูกระงับ" suspended: "ถูกระงับ"
@@ -261,11 +261,11 @@ usernameOrUserId: "ชื่อผู้ใช้หรือรหัสผู
noSuchUser: "ไม่พบผู้ใช้" noSuchUser: "ไม่พบผู้ใช้"
lookup: "การค้นหา" lookup: "การค้นหา"
announcements: "ประกาศ" announcements: "ประกาศ"
imageUrl: "URL รูปภาพ" imageUrl: "url รูปภาพ"
remove: "ลบ" remove: "ลบ"
removed: "ถูกลบไปแล้ว" removed: "ถูกลบไปแล้ว"
removeAreYouSure: "ต้องการลบ “{x}” ใช่ไหม?" removeAreYouSure: "ต้องการที่จะลบ “{x}” ออก?"
deleteAreYouSure: "ต้องการลบ {x}” ใช่ไหม?" deleteAreYouSure: "ต้องการลบ {x} หรือไม่คะ?"
resetAreYouSure: "รีเซ็ตเลยไหม?" resetAreYouSure: "รีเซ็ตเลยไหม?"
areYouSure: "แน่ใจแล้วใช่ไหมคะ?" areYouSure: "แน่ใจแล้วใช่ไหมคะ?"
saved: "บันทึกแล้ว" saved: "บันทึกแล้ว"
@@ -275,7 +275,7 @@ keepOriginalUploading: "เก็บภาพต้นฉบับ"
keepOriginalUploadingDescription: "เก็บภาพต้นฉบับไว้เมื่ออัปโหลดภาพ หากปิด รูปภาพสำหรับการเผยแพร่ทางเว็บจะถูกสร้างขึ้นในเบราว์เซอร์เมื่อทำการอัปโหลด" keepOriginalUploadingDescription: "เก็บภาพต้นฉบับไว้เมื่ออัปโหลดภาพ หากปิด รูปภาพสำหรับการเผยแพร่ทางเว็บจะถูกสร้างขึ้นในเบราว์เซอร์เมื่อทำการอัปโหลด"
fromDrive: "จากไดรฟ์" fromDrive: "จากไดรฟ์"
fromUrl: "จาก URL" fromUrl: "จาก URL"
uploadFromUrl: "อัโหลดจาก URL" uploadFromUrl: "อัโหลดจาก URL"
uploadFromUrlDescription: "URL ของไฟล์ที่คุณต้องการอัปโหลด" uploadFromUrlDescription: "URL ของไฟล์ที่คุณต้องการอัปโหลด"
uploadFromUrlRequested: "ร้องขอการอัปโหลดแล้ว" uploadFromUrlRequested: "ร้องขอการอัปโหลดแล้ว"
uploadFromUrlMayTakeTime: "การอัปโหลดอาจใช้เวลาสักครู่จึงจะเสร็จสมบูรณ์" uploadFromUrlMayTakeTime: "การอัปโหลดอาจใช้เวลาสักครู่จึงจะเสร็จสมบูรณ์"
@@ -289,7 +289,7 @@ agree: "ยอมรับ"
agreeBelow: "ฉันยอมรับถึงด้านล่าง" agreeBelow: "ฉันยอมรับถึงด้านล่าง"
basicNotesBeforeCreateAccount: "หมายเหตุสำคัญ" basicNotesBeforeCreateAccount: "หมายเหตุสำคัญ"
termsOfService: "เงื่อนไขการให้บริการ" termsOfService: "เงื่อนไขการให้บริการ"
start: "เริ่ม" start: "เริ่มต้น​ใช้งาน​"
home: "หน้าแรก" home: "หน้าแรก"
remoteUserCaution: "ข้อมูลอาจไม่สมบูรณ์เนื่องจากผู้ใช้รายนี้มาจากอินสแตนซ์ระยะไกล" remoteUserCaution: "ข้อมูลอาจไม่สมบูรณ์เนื่องจากผู้ใช้รายนี้มาจากอินสแตนซ์ระยะไกล"
activity: "กิจกรรม" activity: "กิจกรรม"
@@ -333,11 +333,11 @@ rename: "เปลี่ยนชื่อ"
avatar: "ไอคอน" avatar: "ไอคอน"
banner: "แบนเนอร์" banner: "แบนเนอร์"
displayOfSensitiveMedia: "แสดงสื่อที่มีเนื้อหาละเอียดอ่อน" displayOfSensitiveMedia: "แสดงสื่อที่มีเนื้อหาละเอียดอ่อน"
whenServerDisconnected: "เมื่อสูญเสียการเชื่อมต่อกับเซิร์ฟเวอร์" whenServerDisconnected: "สูญเสียการเชื่อมต่อกับเซิร์ฟเวอร์"
disconnectedFromServer: "การเชื่อมต่อเซิร์ฟเวอร์ถูกตัด" disconnectedFromServer: "ถูกตัดการเชื่อมต่อออกจากเซิร์ฟเวอร์"
reload: "รีโหลด" reload: "รีโหลด"
doNothing: "เมิน" doNothing: "เมิน"
reloadConfirm: "รีโหลดเลยไหม?" reloadConfirm: "นายต้องการรีเฟรชไทม์ไลน์หรือป่าว?"
watch: "ดู" watch: "ดู"
unwatch: "หยุดดู" unwatch: "หยุดดู"
accept: "ยอมรับ" accept: "ยอมรับ"
@@ -347,7 +347,7 @@ instanceName: "ชื่ออินสแตนซ์"
instanceDescription: "คำอธิบายอินสแตนซ์" instanceDescription: "คำอธิบายอินสแตนซ์"
maintainerName: "ผู้ดูแล" maintainerName: "ผู้ดูแล"
maintainerEmail: "อีเมลผู้ดูแลระบบ" maintainerEmail: "อีเมลผู้ดูแลระบบ"
tosUrl: "URL เงื่อนไขการให้บริการ" tosUrl: "เงื่อนไขการให้บริการ URL"
thisYear: "ปีนี้" thisYear: "ปีนี้"
thisMonth: "เดือนนี้" thisMonth: "เดือนนี้"
today: "วันนี้" today: "วันนี้"
@@ -370,7 +370,7 @@ inMb: "เป็นเมกะไบต์"
bannerUrl: "URL รูปภาพแบนเนอร์" bannerUrl: "URL รูปภาพแบนเนอร์"
backgroundImageUrl: "URL ภาพพื้นหลัง" backgroundImageUrl: "URL ภาพพื้นหลัง"
basicInfo: "ข้อมูลเบื้องต้น" basicInfo: "ข้อมูลเบื้องต้น"
pinnedUsers: "ผู้ใช้ที่ถูกปักหมุด" pinnedUsers: "ผู้ใช้งานที่ได้รับการปักหมุด"
pinnedUsersDescription: "ป้อนชื่อผู้ใช้ที่คุณต้องการปักหมุดในหน้า “ค้นพบ” ฯลฯ คั่นด้วยการขึ้นบรรทัดใหม่" pinnedUsersDescription: "ป้อนชื่อผู้ใช้ที่คุณต้องการปักหมุดในหน้า “ค้นพบ” ฯลฯ คั่นด้วยการขึ้นบรรทัดใหม่"
pinnedPages: "หน้าเพจที่ปักหมุด" pinnedPages: "หน้าเพจที่ปักหมุด"
pinnedPagesDescription: "ป้อนเส้นทางของหน้าเพจที่คุณต้องการปักหมุดไว้ที่หน้าแรกของอินสแตนซ์นี้ คั่นด้วยขึ้นบรรทัดใหม่" pinnedPagesDescription: "ป้อนเส้นทางของหน้าเพจที่คุณต้องการปักหมุดไว้ที่หน้าแรกของอินสแตนซ์นี้ คั่นด้วยขึ้นบรรทัดใหม่"
@@ -409,16 +409,16 @@ caseSensitive: "อักษรพิมพ์ใหญ่-พิมพ์เล
withReplies: "รวมตอบกลับ" withReplies: "รวมตอบกลับ"
connectedTo: "บัญชีดังต่อไปนี้มีการเชื่อมต่อกัน" connectedTo: "บัญชีดังต่อไปนี้มีการเชื่อมต่อกัน"
notesAndReplies: "โพสต์และการตอบกลับ" notesAndReplies: "โพสต์และการตอบกลับ"
withFiles: "มไฟล์" withFiles: "รวบรวมไฟล์"
silence: "ถูกปิดปาก" silence: "ถูกปิดปาก"
silenceConfirm: "ต้องการปิดปากผู้ใช้รายนี้ใช่ไหม?" silenceConfirm: "ต้องการที่จะ ปิดปาก ผู้ใช้รายนี้?"
unsilence: "ยกเลิกการปิดปาก" unsilence: "ยกเลิกการปิดปาก"
unsilenceConfirm: "ต้องการเลิกปิดปากผู้ใช้รายนี้ใช่ไหม?" unsilenceConfirm: "ต้องการยกเลิกปิดปากผู้ใช้รายนี้?"
popularUsers: "ผู้ใช้ที่เป็นที่นิยม" popularUsers: "ผู้ใช้ที่เป็นที่นิยม"
recentlyUpdatedUsers: "ผู้ใช้ที่เพิ่งใช้งานล่าสุด" recentlyUpdatedUsers: "ผู้ใช้ที่เพิ่งใช้งานล่าสุด"
recentlyRegisteredUsers: "ผู้ใช้ที่เข้าร่วมใหม่" recentlyRegisteredUsers: "ผู้ใช้ที่เข้าร่วมใหม่"
recentlyDiscoveredUsers: "ผู้ใช้ที่เพิ่งค้นพบใหม่" recentlyDiscoveredUsers: "ผู้ใช้ที่เพิ่งค้นพบใหม่"
exploreUsersCount: "มีผู้ใช้ {count} ราย" exploreUsersCount: "มีผู้ใช้ {จำนวน} ราย"
exploreFediverse: "สำรวจสหพันธ์" exploreFediverse: "สำรวจสหพันธ์"
popularTags: "แท็กยอดนิยม" popularTags: "แท็กยอดนิยม"
userList: "ลิสต์" userList: "ลิสต์"
@@ -435,7 +435,7 @@ moderation: "การกลั่นกรอง"
moderationNote: "โน้ตการกลั่นกรอง" moderationNote: "โน้ตการกลั่นกรอง"
addModerationNote: "เพิ่มโน้ตการกลั่นกรอง" addModerationNote: "เพิ่มโน้ตการกลั่นกรอง"
moderationLogs: "ปูมการแก้ไข" moderationLogs: "ปูมการแก้ไข"
nUsersMentioned: "กล่าวถึงโดยผู้ใช้ {n} ราย" nUsersMentioned: "กล่าวถึงโดยผู้ใช้ {n} รายนี้"
securityKeyAndPasskey: "ความปลอดภัยและรหัสผ่าน" securityKeyAndPasskey: "ความปลอดภัยและรหัสผ่าน"
securityKey: "กุญแจความปลอดภัย" securityKey: "กุญแจความปลอดภัย"
lastUsed: "ใช้ล่าสุด" lastUsed: "ใช้ล่าสุด"
@@ -449,7 +449,7 @@ reduceUiAnimation: "ลดภาพเคลื่อนไหว UI"
share: "แบ่งปัน" share: "แบ่งปัน"
notFound: "ไม่พบหน้าที่ต้องการ" notFound: "ไม่พบหน้าที่ต้องการ"
notFoundDescription: "ไม่พบหน้าตาม URL ที่ระบุ" notFoundDescription: "ไม่พบหน้าตาม URL ที่ระบุ"
uploadFolder: "โฟลเดอร์เริ่มต้นสำหรับอัโหลด" uploadFolder: "โฟลเดอร์เริ่มต้นสำหรับอัโหลด"
markAsReadAllNotifications: "ทำเครื่องหมายการแจ้งเตือนทั้งหมดว่าอ่านแล้ว" markAsReadAllNotifications: "ทำเครื่องหมายการแจ้งเตือนทั้งหมดว่าอ่านแล้ว"
markAsReadAllUnreadNotes: "ทำเครื่องหมายโน้ตทั้งหมดว่าอ่านแล้ว" markAsReadAllUnreadNotes: "ทำเครื่องหมายโน้ตทั้งหมดว่าอ่านแล้ว"
markAsReadAllTalkMessages: "ทำเครื่องหมายข้อความทั้งหมดว่าอ่านแล้ว" markAsReadAllTalkMessages: "ทำเครื่องหมายข้อความทั้งหมดว่าอ่านแล้ว"
@@ -464,7 +464,7 @@ text: "ข้อความ"
enable: "เปิดใช้งาน" enable: "เปิดใช้งาน"
next: "ถัด​ไป" next: "ถัด​ไป"
retype: "พิมพ์รหัสอีกครั้ง" retype: "พิมพ์รหัสอีกครั้ง"
noteOf: "โน้ตของ {user}" noteOf: "โน้ต โดย {user}"
quoteAttached: "อ้างอิง" quoteAttached: "อ้างอิง"
quoteQuestion: "ต้องการที่จะแนบมันเพื่ออ้างอิงใช่ไหม?" quoteQuestion: "ต้องการที่จะแนบมันเพื่ออ้างอิงใช่ไหม?"
noMessagesYet: "ยังไม่มีข้อความ" noMessagesYet: "ยังไม่มีข้อความ"
@@ -472,7 +472,7 @@ newMessageExists: "คุณมีข้อความใหม่"
onlyOneFileCanBeAttached: "สามารถแนบไฟล์ได้เพียงไฟล์เดียวต่อ 1 ข้อความ" onlyOneFileCanBeAttached: "สามารถแนบไฟล์ได้เพียงไฟล์เดียวต่อ 1 ข้อความ"
signinRequired: "กรุณาลงทะเบียนหรือลงชื่อเข้าใช้ก่อนดำเนินการต่อ" signinRequired: "กรุณาลงทะเบียนหรือลงชื่อเข้าใช้ก่อนดำเนินการต่อ"
invitations: "คำเชิญ" invitations: "คำเชิญ"
invitationCode: "รหัสเชิญ" invitationCode: "รหัสคำเชิญ"
checking: "Checking" checking: "Checking"
available: "พร้อมใช้งาน" available: "พร้อมใช้งาน"
unavailable: "ไม่พร้อมใช้" unavailable: "ไม่พร้อมใช้"
@@ -557,7 +557,7 @@ popout: "ป๊อปเอาต์"
volume: "ระดับเสียง" volume: "ระดับเสียง"
masterVolume: "ระดับเสียงหลัก" masterVolume: "ระดับเสียงหลัก"
notUseSound: "ไม่ใช้เสียง" notUseSound: "ไม่ใช้เสียง"
useSoundOnlyWhenActive: "มีเสียงออกเฉพาะตอนกำลังใช้ Misskey อยู่เท่านั้น" useSoundOnlyWhenActive: "มีเสียงออกเฉพาะเมื่อ Misskey ทำงานอยู่"
details: "รายละเอียด" details: "รายละเอียด"
chooseEmoji: "เลือกเอโมจิ" chooseEmoji: "เลือกเอโมจิ"
unableToProcess: "ไม่สามารถดำเนินการให้เสร็จสิ้นได้" unableToProcess: "ไม่สามารถดำเนินการให้เสร็จสิ้นได้"
@@ -570,8 +570,8 @@ installedDate: "วันที่ติดตั้ง"
lastUsedDate: "ใช้งานครั้งล่าสุด" lastUsedDate: "ใช้งานครั้งล่าสุด"
state: "สถานะ" state: "สถานะ"
sort: "เรียงลำดับ" sort: "เรียงลำดับ"
ascendingOrder: "เรียงลำดับขึ้น" ascendingOrder: "เรียงจากน้อยไปมาก"
descendingOrder: "เรียงลำดับลง" descendingOrder: "เรียงจากมากไปน้อย"
scratchpad: "Scratchpad" scratchpad: "Scratchpad"
scratchpadDescription: "Scratchpad เป็นการจัดเตรียมสภาพแวดล้อมสำหรับการทดลอง AiScript แต่คุณสามารถเขียน ดำเนินการ และตรวจสอบผลลัพธ์ของการโต้ตอบกับ Misskey มันได้ด้วยนะ" scratchpadDescription: "Scratchpad เป็นการจัดเตรียมสภาพแวดล้อมสำหรับการทดลอง AiScript แต่คุณสามารถเขียน ดำเนินการ และตรวจสอบผลลัพธ์ของการโต้ตอบกับ Misskey มันได้ด้วยนะ"
output: "เอาท์พุต" output: "เอาท์พุต"
@@ -579,15 +579,15 @@ script: "สคริปต์"
disablePagesScript: "ปิดการใช้งาน AiScript บนเพจ" disablePagesScript: "ปิดการใช้งาน AiScript บนเพจ"
updateRemoteUser: "อัปเดตข้อมูลผู้ใช้งานระยะไกล" updateRemoteUser: "อัปเดตข้อมูลผู้ใช้งานระยะไกล"
unsetUserAvatar: "เลิกตั้งอวตาร" unsetUserAvatar: "เลิกตั้งอวตาร"
unsetUserAvatarConfirm: "ต้องการเลิกตั้งอวตารใข่ไหม?" unsetUserAvatarConfirm: "ต้องการเลิกตั้งอวตาร?"
unsetUserBanner: "เลิกตั้งแบนเนอร์" unsetUserBanner: "เลิกตั้งแบนเนอร์"
unsetUserBannerConfirm: "ต้องการเลิกตั้งแบนเนอร์?" unsetUserBannerConfirm: "ต้องการเลิกตั้งแบนเนอร์?"
deleteAllFiles: "ลบไฟล์ทั้งหมด" deleteAllFiles: "ลบไฟล์ทั้งหมด"
deleteAllFilesConfirm: "ต้องการลบไฟล์ทั้งหมดใช่ไหม?" deleteAllFilesConfirm: "ต้องการลบไฟล์ทั้งหมดหรือไม่?"
removeAllFollowing: "เลิกติดตามผู้ใช้ที่ติดตามทั้งหมด" removeAllFollowing: "เลิกติดตามผู้ใช้ที่ติดตามทั้งหมด"
removeAllFollowingDescription: "เลิกติดตามทั้งหมดจาก {host} โปรดเรียกใช้สิ่งนี้เมื่ออินสแตนซ์ดังกล่าวได้สูญหายตายจากไปแล้ว" removeAllFollowingDescription: "เลิกติดตามทั้งหมดจาก {host} โปรดเรียกใช้สิ่งนี้เมื่ออินสแตนซ์ดังกล่าวได้สูญหายตายจากไปแล้ว"
userSuspended: "ผู้ใช้รายนี้ถูกระงับการใช้งาน" userSuspended: "ผู้ใช้รายนี้ถูกระงับการใช้งาน"
userSilenced: "ผู้ใช้รายนี้ถูกปิดปากอยู่" userSilenced: "ผู้ใช้รายนี้กำลังถูกปิดกั้น"
yourAccountSuspendedTitle: "บัญชีนี้นั้นถูกระงับ" yourAccountSuspendedTitle: "บัญชีนี้นั้นถูกระงับ"
yourAccountSuspendedDescription: "บัญชีนี้ถูกระงับ เนื่องจากละเมิดข้อกำหนดในการให้บริการของเซิร์ฟเวอร์หรืออาจจะละเมิดหลักเกณฑ์ชุมชน หรือ อาจจะโดนร้องเรียนเรื่องการละเมิดลิขสิทธิ์และอื่นๆอย่างต่อเนื่องซ้ำๆ หากคุณคิดว่าไม่ได้ทำผิดจริงๆหรือตัดสินผิดพลาด ได้โปรดกรุณาติดต่อผู้ดูแลระบบหากคุณต้องการทราบเหตุผลโดยละเอียดเพิ่มเติม และขอความกรุณาอย่าสร้างบัญชีใหม่" yourAccountSuspendedDescription: "บัญชีนี้ถูกระงับ เนื่องจากละเมิดข้อกำหนดในการให้บริการของเซิร์ฟเวอร์หรืออาจจะละเมิดหลักเกณฑ์ชุมชน หรือ อาจจะโดนร้องเรียนเรื่องการละเมิดลิขสิทธิ์และอื่นๆอย่างต่อเนื่องซ้ำๆ หากคุณคิดว่าไม่ได้ทำผิดจริงๆหรือตัดสินผิดพลาด ได้โปรดกรุณาติดต่อผู้ดูแลระบบหากคุณต้องการทราบเหตุผลโดยละเอียดเพิ่มเติม และขอความกรุณาอย่าสร้างบัญชีใหม่"
tokenRevoked: "โทเค็นไม่ถูกต้อง" tokenRevoked: "โทเค็นไม่ถูกต้อง"
@@ -600,7 +600,7 @@ addItem: "เพิ่มรายการ"
rearrange: "จัดใหม่" rearrange: "จัดใหม่"
relays: "รีเลย์" relays: "รีเลย์"
addRelay: "เพิ่มรีเลย์" addRelay: "เพิ่มรีเลย์"
inboxUrl: "URL ของอินบ็อกซ์" inboxUrl: "อินบ็อกซ์ URL"
addedRelays: "เพิ่มรีเลย์แล้ว" addedRelays: "เพิ่มรีเลย์แล้ว"
serviceworkerInfo: "ต้องเปิดใช้งานสำหรับการแจ้งเตือนแบบพุช" serviceworkerInfo: "ต้องเปิดใช้งานสำหรับการแจ้งเตือนแบบพุช"
deletedNote: "โน้ตที่ถูกลบ" deletedNote: "โน้ตที่ถูกลบ"
@@ -617,7 +617,7 @@ description: "รายละเอียด"
describeFile: "เพิ่มแคปชั่น" describeFile: "เพิ่มแคปชั่น"
enterFileDescription: "ใส่แคปชั่น" enterFileDescription: "ใส่แคปชั่น"
author: "ผู้เขียน" author: "ผู้เขียน"
leaveConfirm: "มีการเปลี่ยนแปลงที่ยังไม่ได้บันทึก ต้องการละทิ้งมันใช่ไหม?" leaveConfirm: "คุณมีการเปลี่ยนแปลงที่ไม่ได้บันทึกนะ นายต้องการทิ้งการเปลี่ยนแปลงเหล่านั้นหรอ?"
manage: "การจัดการ" manage: "การจัดการ"
plugins: "ปลั๊กอิน" plugins: "ปลั๊กอิน"
preferencesBackups: "ตั้งค่าการสำรองข้อมูล" preferencesBackups: "ตั้งค่าการสำรองข้อมูล"
@@ -664,7 +664,7 @@ display: "แสดงผล"
copy: "คัดลอก" copy: "คัดลอก"
metrics: "เมตริก" metrics: "เมตริก"
overview: "ภาพรวม" overview: "ภาพรวม"
logs: "ปูม" logs: "บันทึกข้อมูลระบบ"
delayed: "ดีเลย์" delayed: "ดีเลย์"
database: "ฐานข้อมูล" database: "ฐานข้อมูล"
channel: "ช่อง" channel: "ช่อง"
@@ -672,26 +672,26 @@ create: "สร้าง"
notificationSetting: "ตั้งค่าการแจ้งเตือน" notificationSetting: "ตั้งค่าการแจ้งเตือน"
notificationSettingDesc: "เลือกประเภทการแจ้งเตือนที่ต้องการจะแสดง" notificationSettingDesc: "เลือกประเภทการแจ้งเตือนที่ต้องการจะแสดง"
useGlobalSetting: "ใช้การตั้งค่าส่วนกลาง" useGlobalSetting: "ใช้การตั้งค่าส่วนกลาง"
useGlobalSettingDesc: "เมื่อเปิดใช้งาน ใช้การตั้งค่าการแจ้งเตือนจากบัญชีคุณ เมื่อปิดใช้งาน สามารถตั้งค่าได้อย่างอิสระ" useGlobalSettingDesc: "หากเปิดไว้ ระบบจะใช้การตั้งค่าการแจ้งเตือนของบัญชีของคุณ หากปิดอยู่ สามารถทำการกำหนดค่าแต่ละรายการได้นะ"
other: "อื่น ๆ" other: "อื่น ๆ"
regenerateLoginToken: "สร้างโทเค็นการเข้าสู่ระบบอีกครั้ง" regenerateLoginToken: "สร้างโทเค็นการเข้าสู่ระบบอีกครั้ง"
regenerateLoginTokenDescription: "สร้างโทเค็นใหม่ที่ใช้ภายในระหว่างการเข้าสู่ระบบ โดยตามหลักปกติแล้วการดำเนินการนี้ไม่จำเป็น หากสร้างใหม่ อุปกรณ์ทั้งหมดจะถูกออกจากระบบนะ" regenerateLoginTokenDescription: "สร้างโทเค็นใหม่ที่ใช้ภายในระหว่างการเข้าสู่ระบบ โดยตามหลักปกติแล้วการดำเนินการนี้ไม่จำเป็น หากสร้างใหม่ อุปกรณ์ทั้งหมดจะถูกออกจากระบบนะ"
theKeywordWhenSearchingForCustomEmoji: "คีย์เวิร์ดสำหรับใช้ค้นหาอโมจิที่กำหนดเอง" theKeywordWhenSearchingForCustomEmoji: "คีย์เวิร์ดสำหรับใช้ค้นหาอโมจิที่กำหนดเอง"
setMultipleBySeparatingWithSpace: "คั่นหลายรายการด้วยช่องว่าง" setMultipleBySeparatingWithSpace: "คั่นหลายรายการด้วยช่องว่าง"
fileIdOrUrl: "ID ของไฟล์ หรือ URL" fileIdOrUrl: "ไฟล์ ID หรือ URL"
behavior: "พฤติกรรม" behavior: "พฤติกรรม"
sample: "ตัวอย่าง" sample: "ตัวอย่าง"
abuseReports: "รายงาน" abuseReports: "รายงาน"
reportAbuse: "รายงาน" reportAbuse: "รายงาน"
reportAbuseRenote: "รายงานรีโน้ต" reportAbuseRenote: "รายงานรีโน้ต"
reportAbuseOf: "รายงาน {name}" reportAbuseOf: "รายงาน {ชื่อ}"
fillAbuseReportDescription: "กรุณากรอกรายละเอียดเกี่ยวกับรายงานนี้ หากเป็นเรื่องเกี่ยวกับโน้ตโดยเฉพาะ ได้โปรดระบุ URL" fillAbuseReportDescription: "กรุณากรอกรายละเอียดเกี่ยวกับรายงานนี้ หากเป็นเรื่องเกี่ยวกับโน้ตโดยเฉพาะ ได้โปรดระบุ URL"
abuseReported: "เราได้ส่งรายงานของคุณไปแล้ว ขอบคุณมากๆนะ" abuseReported: "เราได้ส่งรายงานของคุณไปแล้ว ขอบคุณมากๆนะ"
reporter: "ผู้รายงาน" reporter: "นักข่าว"
reporteeOrigin: "รายงานต้นทาง" reporteeOrigin: "รายงานต้นทาง"
reporterOrigin: "แหล่งผู้รายงาน" reporterOrigin: "นักข่าวต้นทาง"
forwardReport: "ส่งต่อรายงานไปยังอินสแตนซ์ระยะไกล" forwardReport: "ส่งต่อรายงานไปยังอินสแตนซ์ระยะไกล"
forwardReportIsAnonymous: "ข้อมูลของคุณจะไม่ปรากฏบนอินสแตนซ์ระยะไกลและปรากฏเป็นบัญชีระบบที่ไม่ระบุชื่อ" forwardReportIsAnonymous: "แทนที่จะเป็นบัญชีของคุณ บัญชีระบบที่ไม่ระบุตัวตนจะแสดงเป็นนักข่าวที่อินสแตนซ์ระยะไกล"
send: "ส่ง" send: "ส่ง"
abuseMarkAsResolved: "ทำเครื่องหมายรายงานว่าแก้ไขแล้ว" abuseMarkAsResolved: "ทำเครื่องหมายรายงานว่าแก้ไขแล้ว"
openInNewTab: "เปิดในแท็บใหม่" openInNewTab: "เปิดในแท็บใหม่"
@@ -699,7 +699,7 @@ openInSideView: "เปิดในมุมมองด้านข้าง"
defaultNavigationBehaviour: "พฤติกรรมการนำทางที่เป็นค่าเริ่มต้น" defaultNavigationBehaviour: "พฤติกรรมการนำทางที่เป็นค่าเริ่มต้น"
editTheseSettingsMayBreakAccount: "การแก้ไขการตั้งค่าเหล่านี้อาจทำให้บัญชีของคุณเสียหายนะ" editTheseSettingsMayBreakAccount: "การแก้ไขการตั้งค่าเหล่านี้อาจทำให้บัญชีของคุณเสียหายนะ"
instanceTicker: "ข้อมูลอินสแตนซ์ของโน้ต" instanceTicker: "ข้อมูลอินสแตนซ์ของโน้ต"
waitingFor: "กำลังรอ {x}" waitingFor: "กำลังรอคอย {x}"
random: "สุ่มค่า" random: "สุ่มค่า"
system: "ระบบ" system: "ระบบ"
switchUi: "สลับ UI" switchUi: "สลับ UI"
@@ -709,7 +709,7 @@ createNew: "สร้างใหม่"
optional: "ไม่บังคับ" optional: "ไม่บังคับ"
createNewClip: "สร้างคลิปใหม่" createNewClip: "สร้างคลิปใหม่"
unclip: "ลบคลิป" unclip: "ลบคลิป"
confirmToUnclipAlreadyClippedNote: "โน้ตนี้เป็นส่วนหนึ่งของคลิป {name}” อยู่แล้ว ต้องการนำมันออกจากคลิปใช่ไหม?" confirmToUnclipAlreadyClippedNote: "โน้ตนี้เป็นส่วนหนึ่งของคลิป \"{name}\" แล้ว คุณต้องการลบออกจากคลิปนี้แทนอย่างงั้นหรอ?"
public: "สาธารณะ" public: "สาธารณะ"
private: "ส่วนตัว" private: "ส่วนตัว"
i18nInfo: "Misskey กำลังได้รับการแปลเป็นภาษาต่างๆ โดยอาสาสมัคร คุณสามารถช่วยเหลือได้ที่ {link}" i18nInfo: "Misskey กำลังได้รับการแปลเป็นภาษาต่างๆ โดยอาสาสมัคร คุณสามารถช่วยเหลือได้ที่ {link}"
@@ -732,7 +732,7 @@ driveFilesCount: "จำนวนไฟล์ไดรฟ์"
driveUsage: "การใช้พื้นที่ไดรฟ์" driveUsage: "การใช้พื้นที่ไดรฟ์"
noCrawle: "ปฏิเสธการจัดทำดัชนีของโปรแกรมรวบรวมข้อมูล" noCrawle: "ปฏิเสธการจัดทำดัชนีของโปรแกรมรวบรวมข้อมูล"
noCrawleDescription: "ขอให้เครื่องมือค้นหาไม่จัดทำดัชนีหน้าโปรไฟล์ โน้ต หน้าเพจ ฯลฯ" noCrawleDescription: "ขอให้เครื่องมือค้นหาไม่จัดทำดัชนีหน้าโปรไฟล์ โน้ต หน้าเพจ ฯลฯ"
lockedAccountInfo: "แม้ว่าการอนุมัติการติดตามถูกเปิดใช้งานอยู่ทุกคนก็ยังคงสามารถเห็นโน้ตของคุณได้ เว้นแต่ว่าคุณจะเปลี่ยนการเปิดเผยโน้ตของคุณเป็น “เฉพาะผู้ติดตาม" lockedAccountInfo: "เว้นแต่ว่าคุณจะต้องตั้งค่าการเปิดเผยโน้ตเป็น \"ผู้ติดตามเท่านั้น\" โน้ตย่อของคุณจะปรากฏแก่ทุกคน ถึงแม้ว่าคุณจะเป็นกำหนดให้ผู้ติดตามต้องได้รับการอนุมัติด้วยตนเองก็ตาม"
alwaysMarkSensitive: "ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อนเป็นค่าเริ่มต้น" alwaysMarkSensitive: "ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อนเป็นค่าเริ่มต้น"
loadRawImages: "โหลดภาพต้นฉบับแทนการแสดงภาพขนาดย่อ" loadRawImages: "โหลดภาพต้นฉบับแทนการแสดงภาพขนาดย่อ"
disableShowingAnimatedImages: "ไม่ต้องเล่นภาพเคลื่อนไหว" disableShowingAnimatedImages: "ไม่ต้องเล่นภาพเคลื่อนไหว"
@@ -768,29 +768,29 @@ nNotes: "{n} โน้ต"
sendErrorReports: "ส่งรายงานว่าข้อผิดพลาด" sendErrorReports: "ส่งรายงานว่าข้อผิดพลาด"
sendErrorReportsDescription: "เมื่อเปิดใช้งาน ข้อมูลข้อผิดพลาดโดยรายละเอียดนั้นจะถูกแชร์ให้กับ Misskey เมื่อเกิดปัญหา ซึ่งช่วยปรับปรุงคุณภาพของ Misskey\nซึ่งจะรวมถึงข้อมูล เช่น เวอร์ชั่นของระบบปฏิบัติการ เบราว์เซอร์ที่คุณใช้ กิจกรรมของคุณใน Misskey เป็นต้น" sendErrorReportsDescription: "เมื่อเปิดใช้งาน ข้อมูลข้อผิดพลาดโดยรายละเอียดนั้นจะถูกแชร์ให้กับ Misskey เมื่อเกิดปัญหา ซึ่งช่วยปรับปรุงคุณภาพของ Misskey\nซึ่งจะรวมถึงข้อมูล เช่น เวอร์ชั่นของระบบปฏิบัติการ เบราว์เซอร์ที่คุณใช้ กิจกรรมของคุณใน Misskey เป็นต้น"
myTheme: "ธีมของฉัน" myTheme: "ธีมของฉัน"
backgroundColor: "สีพื้นหลัง" backgroundColor: "ภาพพื้นหลัง"
accentColor: "สีหลัก" accentColor: "รูปแบบสี"
textColor: "สีข้อความ" textColor: "สีข้อความ"
saveAs: "บันทึกเป็น..." saveAs: "บันทึกเป็น..."
advanced: "ขั้นสูง" advanced: "ขั้นสูง"
advancedSettings: "การตั้งค่าขั้นสูง" advancedSettings: "การตั้งค่าขั้นสูง"
value: "ค่า" value: "ค่า"
createdAt: "สร้างเมื่อ" createdAt: "สร้างเมื่อ"
updatedAt: "อัเดล่าสุด" updatedAt: "อัเดล่าสุด"
saveConfirm: "บันทึกเปลี่ยนแปลงมั้ย?" saveConfirm: "บันทึกเปลี่ยนแปลงมั้ย?"
deleteConfirm: "ลบจริงๆเหรอ?" deleteConfirm: "ลบจริงๆเหรอ?"
invalidValue: "ค่านี้ไม่ถูกต้อง" invalidValue: "ค่านี้ไม่ถูกต้อง"
registry: "ทะเบียน" registry: "ทะเบียน"
closeAccount: "ปิด บัญชี" closeAccount: "ปิด บัญชี"
currentVersion: "เวอร์ชั่นปัจจุบัน" currentVersion: "เวอร์ชั่นปัจจุบัน"
latestVersion: "เวอร์ชั่นล่าสุด" latestVersion: "รุ่นปัจจุบัน"
youAreRunningUpToDateClient: "คุณกำลังใช้ไคลเอ็นต์เวอร์ชันใหม่ล่าสุดนะ" youAreRunningUpToDateClient: "คุณกำลังใช้ไคลเอ็นต์เวอร์ชันใหม่ล่าสุดนะ"
newVersionOfClientAvailable: "มีไคลเอ็นต์เวอร์ชันใหม่กว่าของคุณพร้อมใช้งานนะ" newVersionOfClientAvailable: "มีไคลเอ็นต์เวอร์ชันใหม่กว่าของคุณพร้อมใช้งานนะ"
usageAmount: "การใช้งาน" usageAmount: "การใช้งาน"
capacity: "ความจุ" capacity: "ความจุ"
inUse: "ใช้แล้ว" inUse: "ใช้แล้ว"
editCode: "แก้ไขโค้ด" editCode: "แก้ไขโค้ด"
apply: "นำไปใช้" apply: "ตกลง"
receiveAnnouncementFromInstance: "รับการแจ้งเตือนจากอินสแตนซ์นี้" receiveAnnouncementFromInstance: "รับการแจ้งเตือนจากอินสแตนซ์นี้"
emailNotification: "การแจ้งเตือนทางอีเมล" emailNotification: "การแจ้งเตือนทางอีเมล"
publish: "เผยแพร่" publish: "เผยแพร่"
@@ -802,7 +802,7 @@ showingPastTimeline: "กำลังแสดงผลไทม์ไลน์
clear: "ล้าง" clear: "ล้าง"
markAllAsRead: "ทำเครื่องหมายทั้งหมดว่าอ่านแล้ว" markAllAsRead: "ทำเครื่องหมายทั้งหมดว่าอ่านแล้ว"
goBack: "ย้อนกลับ" goBack: "ย้อนกลับ"
unlikeConfirm: "ต้องการเลิกถูกใจใช่ไหม?" unlikeConfirm: "เลิกถูกใจจริงๆ หรือ?"
fullView: "มุมมองแบบเต็ม" fullView: "มุมมองแบบเต็ม"
quitFullView: "ออกจากมุมมองแบบเต็ม" quitFullView: "ออกจากมุมมองแบบเต็ม"
addDescription: "เพิ่มคำอธิบาย" addDescription: "เพิ่มคำอธิบาย"
@@ -813,12 +813,12 @@ userInfo: "ข้อมูลผู้ใช้"
unknown: "ไม่ทราบสถานะ" unknown: "ไม่ทราบสถานะ"
onlineStatus: "สถานะออนไลน์" onlineStatus: "สถานะออนไลน์"
hideOnlineStatus: "ซ่อนสถานะออนไลน์" hideOnlineStatus: "ซ่อนสถานะออนไลน์"
hideOnlineStatusDescription: "การซ่อนสถานะออนไลน์อาจทำให้ฟังก์ชันบางอย่าง เช่น การค้นหา สะดวกน้อยลง" hideOnlineStatusDescription: "การซ่อนสถานะออนไลน์ของคุณช่วยลดความสะดวกของคุณสมบัติบางอย่าง เช่น การค้นหา อ่ะนะ"
online: "ออนไลน์" online: "ออนไลน์"
active: "ใช้งานอยู่" active: "ใช้งานอยู่"
offline: "ออฟไลน์" offline: "ออฟไลน์"
notRecommended: "ไม่แนะนำ" notRecommended: "ไม่แนะนำ"
botProtection: "การป้องกัน Bot" botProtection: "การป้องกัน Bot (or AI)"
instanceBlocking: "อินสแตนซ์ที่ถูกบล็อก" instanceBlocking: "อินสแตนซ์ที่ถูกบล็อก"
selectAccount: "เลือกบัญชี" selectAccount: "เลือกบัญชี"
switchAccount: "สลับบัญชีผู้ใช้" switchAccount: "สลับบัญชีผู้ใช้"
@@ -880,7 +880,7 @@ itsOff: "ปิดใช้งาน"
on: "เปิด" on: "เปิด"
off: "ปิด" off: "ปิด"
emailRequiredForSignup: "จำเป็นต้องการใช้ที่อยู่อีเมลสำหรับการสมัคร" emailRequiredForSignup: "จำเป็นต้องการใช้ที่อยู่อีเมลสำหรับการสมัคร"
unread: "ยังไม่ได้อ่าน" unread: "ไม่ได้อ่าน"
filter: "กรอง" filter: "กรอง"
controlPanel: "แผงควบคุม" controlPanel: "แผงควบคุม"
manageAccounts: "จัดการบัญชี" manageAccounts: "จัดการบัญชี"
@@ -888,13 +888,13 @@ makeReactionsPublic: "ตั้งค่าประวัติการรี
makeReactionsPublicDescription: "การทำเช่นนี้จะทำให้รายการรีแอคชั่นของคุณที่ผ่านมาทั้งหมดปรากฏต่อสาธารณะ" makeReactionsPublicDescription: "การทำเช่นนี้จะทำให้รายการรีแอคชั่นของคุณที่ผ่านมาทั้งหมดปรากฏต่อสาธารณะ"
classic: "คลาสสิค" classic: "คลาสสิค"
muteThread: "ปิดเสียงเธรด" muteThread: "ปิดเสียงเธรด"
unmuteThread: "เลิกปิดเสียงเธรด" unmuteThread: "เปิดเสียงเธรด"
followingVisibility: "การมองเห็นที่เรากำลังติดตาม" followingVisibility: "การมองเห็นที่เรากำลังติดตาม"
followersVisibility: "การมองเห็นผู้ที่กำลังติดตามเรา" followersVisibility: "การมองเห็นผู้ที่กำลังติดตามเรา"
continueThread: "ดูความต่อเนื่องเธรด" continueThread: "ดูความต่อเนื่องเธรด"
deleteAccountConfirm: "การดำเนินการนี้จะลบบัญชีของคุณอย่างถาวรเลยนะ แน่ใจหรอดำเนินการ?" deleteAccountConfirm: "การดำเนินการนี้จะลบบัญชีของคุณอย่างถาวรเลยนะ แน่ใจหรอดำเนินการ?"
incorrectPassword: "รหัสผ่านไม่ถูกต้อง" incorrectPassword: "รหัสผ่านไม่ถูกต้อง"
voteConfirm: "ต้องการโหวต “{choice}” ใช่ไหม?" voteConfirm: "ยืนยันการโหวต “{choice}” ไหม?"
hide: "ซ่อน" hide: "ซ่อน"
useDrawerReactionPickerForMobile: "แสดง ตัวจิ้มรีแอคชั่น เป็นแบบลิ้นชัก เมื่อใช้บนมือถือ" useDrawerReactionPickerForMobile: "แสดง ตัวจิ้มรีแอคชั่น เป็นแบบลิ้นชัก เมื่อใช้บนมือถือ"
welcomeBackWithName: "ยินดีต้อนรับการกลับมานะคะ, คุณ{name}" welcomeBackWithName: "ยินดีต้อนรับการกลับมานะคะ, คุณ{name}"
@@ -941,13 +941,13 @@ deleteAccount: "ลบบัญชี"
document: "เอกสาร" document: "เอกสาร"
numberOfPageCache: "จำนวนหน้าเพจที่แคช" numberOfPageCache: "จำนวนหน้าเพจที่แคช"
numberOfPageCacheDescription: "การเพิ่มจำนวนนี้จะช่วยเพิ่มความสะดวกให้กับผู้ใช้งาน แต่จะทำให้เซิร์ฟเวอร์โหลดมากขึ้นและต้องใช้หน่วยความจำมากขึ้นอีกด้วย" numberOfPageCacheDescription: "การเพิ่มจำนวนนี้จะช่วยเพิ่มความสะดวกให้กับผู้ใช้งาน แต่จะทำให้เซิร์ฟเวอร์โหลดมากขึ้นและต้องใช้หน่วยความจำมากขึ้นอีกด้วย"
logoutConfirm: "ต้องการออกจากระบบใช่ไหม?" logoutConfirm: "ต้องการออกจากระบบ?"
lastActiveDate: "ใช้งานล่าสุดเมื่อ" lastActiveDate: "ใช้งานล่าสุดที่"
statusbar: "แถบสถานะ" statusbar: "แถบสถานะ"
pleaseSelect: "ตัวเลือก" pleaseSelect: "ตัวเลือก"
reverse: "พลิก" reverse: "ย้อนกลับ"
colored: "สี" colored: "สี"
refreshInterval: "ความถี่ในการอัเดต" refreshInterval: "รอบการอัเดต"
label: "ป้ายชื่อ" label: "ป้ายชื่อ"
type: "รูปแบบ" type: "รูปแบบ"
speed: "ความเร็ว" speed: "ความเร็ว"
@@ -974,8 +974,8 @@ unsubscribePushNotification: "ปิดการแจ้งเตือนแ
pushNotificationAlreadySubscribed: "การแจ้งเตือนแบบพุชได้เปิดใช้งานแล้ว" pushNotificationAlreadySubscribed: "การแจ้งเตือนแบบพุชได้เปิดใช้งานแล้ว"
pushNotificationNotSupported: "เบราว์เซอร์หรืออินสแตนซ์ของคุณนั้นไม่รองรับการแจ้งเตือนแบบพุช" pushNotificationNotSupported: "เบราว์เซอร์หรืออินสแตนซ์ของคุณนั้นไม่รองรับการแจ้งเตือนแบบพุช"
sendPushNotificationReadMessage: "ลบการแจ้งเตือนแบบพุชเมื่ออ่านการแจ้งเตือนหรือข้อความที่เกี่ยวข้องแล้ว" sendPushNotificationReadMessage: "ลบการแจ้งเตือนแบบพุชเมื่ออ่านการแจ้งเตือนหรือข้อความที่เกี่ยวข้องแล้ว"
sendPushNotificationReadMessageCaption: "อาจทำให้อุปกรณ์ของคุณใช้พลังงานมากขึ้น" sendPushNotificationReadMessageCaption: "การแจ้งเตือนที่มีข้อความ \"{emptyPushNotificationMessage}\" จะแสดงขึ้นมาในช่วงระยะเวลาสั้นๆ การดำเนินการนี้อาจทำให้เพิ่มการใช้งานแบตเตอรี่ของอุปกรณ์ถ้าหากมีนะ"
windowMaximize: "ขยายใหญ่สุด" windowMaximize: "ขยายใหญ่สุดแล้ว"
windowMinimize: "ย่อเล็กที่สุด" windowMinimize: "ย่อเล็กที่สุด"
windowRestore: "เลิกทำ" windowRestore: "เลิกทำ"
caption: "คำอธิบาย" caption: "คำอธิบาย"
@@ -991,7 +991,6 @@ neverShow: "ไม่ต้องแสดงข้อความนี้อ
remindMeLater: "ไว้ครั้งหน้าแล้วกัน" remindMeLater: "ไว้ครั้งหน้าแล้วกัน"
didYouLikeMisskey: "คุณชอบ Misskey ไหม?" didYouLikeMisskey: "คุณชอบ Misskey ไหม?"
pleaseDonate: "Misskey เป็นซอฟต์แวร์ฟรีที่ใช้งานโดย {host} เราขอขอบคุณการสนับสนุนของคุณอย่างสูงเพื่อให้การพัฒนา Misskey สามารถดำเนินต่อไปได้!" pleaseDonate: "Misskey เป็นซอฟต์แวร์ฟรีที่ใช้งานโดย {host} เราขอขอบคุณการสนับสนุนของคุณอย่างสูงเพื่อให้การพัฒนา Misskey สามารถดำเนินต่อไปได้!"
correspondingSourceIsAvailable: "ซอร์สโค้ดที่เกี่ยวข้องมีอยู่ที่ {anchor}"
roles: "บทบาท" roles: "บทบาท"
role: "บทบาท" role: "บทบาท"
noRole: "ไม่พบบทบาท" noRole: "ไม่พบบทบาท"
@@ -1060,7 +1059,7 @@ enableChartsForFederatedInstances: "สร้างแผนภูมิข้
showClipButtonInNoteFooter: "เพิ่ม “คลิป” ไปยังเมนูสั่งการของโน้ต" showClipButtonInNoteFooter: "เพิ่ม “คลิป” ไปยังเมนูสั่งการของโน้ต"
reactionsDisplaySize: "ขนาดของรีแอคชั่น" reactionsDisplaySize: "ขนาดของรีแอคชั่น"
limitWidthOfReaction: "จำกัดความกว้างสูงสุดของรีแอคชั่นและแสดงให้เล็กลง" limitWidthOfReaction: "จำกัดความกว้างสูงสุดของรีแอคชั่นและแสดงให้เล็กลง"
noteIdOrUrl: "ID ของโน้ต หรือ URL" noteIdOrUrl: "โน้ต ID หรือ URL"
video: "วีดีโอ" video: "วีดีโอ"
videos: "วีดีโอ" videos: "วีดีโอ"
audio: "เสียง" audio: "เสียง"
@@ -1082,7 +1081,7 @@ leftBottom: "ล่างซ้าย"
rightBottom: "ล่างขวา" rightBottom: "ล่างขวา"
stackAxis: "ทิศทางการซ้อน" stackAxis: "ทิศทางการซ้อน"
vertical: "แนวตั้ง" vertical: "แนวตั้ง"
horizontal: "แนวนอน" horizontal: "ด้านข้าง"
position: "ตำแหน่ง" position: "ตำแหน่ง"
serverRules: "กฎของเซิร์ฟเวอร์" serverRules: "กฎของเซิร์ฟเวอร์"
pleaseConfirmBelowBeforeSignup: "โปรดยืนยันที่ด้านล่างก่อนสมัครใช้งาน" pleaseConfirmBelowBeforeSignup: "โปรดยืนยันที่ด้านล่างก่อนสมัครใช้งาน"
@@ -1098,17 +1097,17 @@ thisChannelArchived: "ช่องนี้ถูกเก็บถาวรแ
displayOfNote: "การแสดงโน้ต" displayOfNote: "การแสดงโน้ต"
initialAccountSetting: "ตั้งค่าโปรไฟล์" initialAccountSetting: "ตั้งค่าโปรไฟล์"
youFollowing: "ติดตามแล้ว" youFollowing: "ติดตามแล้ว"
preventAiLearning: "ปฏิเสธการเรียนรู้ด้วย generative AI" preventAiLearning: "ปฏิเสธการใช้งาน ในการเรียนรู้ของเครื่อง (Generative AI)"
preventAiLearningDescription: "ส่งคำร้องขอไม่ให้ใช้ ข้อความในโน้ตที่โพสต์, หรือเนื้อหารูปภาพ ฯลฯ ในการเรียนรู้ของเครื่อง(machine learning) / Predictive AI / Generative AI โดยการเพิ่มแฟล็ก “noai” ลง HTML-Response ให้กับเนื้อหาที่เกี่ยวข้อง แต่ทั้งนี้ ไม่ได้ป้องกัน AI จากการเรียนรู้ได้อย่างสมบูรณ์ เนื่องจากมี AI บางตัวเท่านั้นที่จะเคารพคำขอดังกล่าว" preventAiLearningDescription: "การส่งคำร้องขอโปรแกรมรวบรวมข้อมูลไม่ให้ใช้ข้อความที่โพสต์หรือรูปภาพ ฯลฯ ในชุดข้อมูลแมชชีนเลิร์นนิง (Predictive / Generative AI) สิ่งนี้นั้นทำได้โดยการเพิ่มแฟล็กการตอบสนอง \"noai\" HTML ให้กับเนื้อหาที่เกี่ยวข้อง แต่อย่างไรก็ตามแล้ว การป้องกันโดยสมบูรณ์นั้นไม่สามารถทำได้ผ่านแฟล็กนี้เนื่องจากอาจจะทำให้ถูกเพิกเฉยได้"
options: "ตัวเลือกบทบาท" options: "ตัวเลือกบทบาท"
specifyUser: "ผู้ใช้เฉพาะ" specifyUser: "ผู้ใช้เฉพาะ"
failedToPreviewUrl: "ไม่สามารถดูตัวอย่างได้" failedToPreviewUrl: "ไม่สามารถดูตัวอย่างได้"
update: "อัปเดต" update: "อัปเดต"
rolesThatCanBeUsedThisEmojiAsReaction: "บทบาทที่สามารถใช้เอโมจินี้เป็นรีแอคชั่นได้" rolesThatCanBeUsedThisEmojiAsReaction: "บทบาทที่สามารถใช้เอโมจินี้เป็นรีแอคชั่นได้"
rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "ถ้าหากไม่ได้ระบุบทบาท ใคร ๆ ก็สามารถใช้เอโมจินี้เพื่อรีแอคชั่นได้" rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "ถ้าหากไม่ได้ระบุบทบาท ทุกคนนั้นก็สามารถใช้เอโมจินี้เพื่อรีแอคชั่นได้นะ"
rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "บทบาทเหล่านี้ต้องเป็นสาธารณะ" rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "บทบาทเหล่านี้ต้องเป็นสาธารณะ"
cancelReactionConfirm: "ต้องการลบรีแอคชั่นใช่ไหม?" cancelReactionConfirm: "ต้องการลบรีแอคชั่นของคุณจริงๆหรอ?"
changeReactionConfirm: "ต้องการเปลี่ยนรีแอคชั่นใช่ไหม?" changeReactionConfirm: "ต้องการเปลี่ยนรีแอคชั่นของคุณจริงๆหรอ?"
later: "ไว้ทีหลัง" later: "ไว้ทีหลัง"
goToMisskey: "ถึง Misskey" goToMisskey: "ถึง Misskey"
additionalEmojiDictionary: "พจนานุกรมเอโมจิเพิ่มเติม" additionalEmojiDictionary: "พจนานุกรมเอโมจิเพิ่มเติม"
@@ -1117,20 +1116,20 @@ branding: "แบรนดิ้ง"
enableServerMachineStats: "เผยแพร่สถานะฮาร์ดแวร์ของเซิร์ฟเวอร์" enableServerMachineStats: "เผยแพร่สถานะฮาร์ดแวร์ของเซิร์ฟเวอร์"
enableIdenticonGeneration: "เปิดใช้งานผู้ใช้สร้างตัวระบุ" enableIdenticonGeneration: "เปิดใช้งานผู้ใช้สร้างตัวระบุ"
turnOffToImprovePerformance: "การปิดส่วนนี้สามารถเพิ่มประสิทธิภาพได้" turnOffToImprovePerformance: "การปิดส่วนนี้สามารถเพิ่มประสิทธิภาพได้"
createInviteCode: "สร้างรหัสเชิญ" createInviteCode: "สร้างคำเชิญ"
createWithOptions: "สร้างด้วยตัวเลือก" createWithOptions: "สร้างด้วยตัวเลือก"
createCount: "จำนวนรหัสเชิญ" createCount: "จำนวนการเชิญ"
inviteCodeCreated: "สร้างรหัสเชิญแล้ว" inviteCodeCreated: "สร้างคำเชิญแล้ว"
inviteLimitExceeded: "จำนวนรหัสเชิญที่สามารถสร้างได้ถึงขีดจำกัดแล้ว" inviteLimitExceeded: "คุณสร้างคำเชิญเกินถึงขีดจำกัดแล้วนะ"
createLimitRemaining: "รหัสเชิญที่สามารถสร้างได้: เหลืออยู่ {limit} รหัส" createLimitRemaining: "ขีดจำกัดการเชิญ: {limit} ที่เหลืออยู่"
inviteLimitResetCycle: "สามารถสร้างรหัสเชิญได้อีกสูงสุด {limit} รหัส ภายใน {time}" inviteLimitResetCycle: "ขีดจำกัดนี้จะถูกรีเซ็ตเป็น {limit} ที่ {time}."
expirationDate: "วันที่หมดอายุ" expirationDate: "วันที่หมดอายุ"
noExpirationDate: "ไม่มีหมดอายุ" noExpirationDate: "ไม่มีหมดอายุ"
inviteCodeUsedAt: "วันเวลาที่ใช้รหัสเชิญ" inviteCodeUsedAt: "รหัสคำเชิญใช้แล้วที่"
registeredUserUsingInviteCode: "ผู้ใช้ที่ใช้รหัสเชิญ" registeredUserUsingInviteCode: "ใช้คำเชิญแล้วโดย"
waitingForMailAuth: "กำลังรอการยืนยันอีเมล" waitingForMailAuth: "กำลังรอการยืนยันอีเมล"
inviteCodeCreator: "ผู้ใช้ที่สร้างรหัสเชิญ" inviteCodeCreator: "สร้างการเชิญแล้วโดย"
usedAt: "วันเวลาที่ถูกใช้" usedAt: "ใช้แล้วที่"
unused: "ยังไม่ได้ใช้" unused: "ยังไม่ได้ใช้"
used: "ถูกใช้แล้ว" used: "ถูกใช้แล้ว"
expired: "หมดอายุแล้ว" expired: "หมดอายุแล้ว"
@@ -1149,7 +1148,7 @@ renotes: "รีโน้ต"
loadReplies: "แสดงการตอบกลับ" loadReplies: "แสดงการตอบกลับ"
loadConversation: "แสดงบทสนทนา" loadConversation: "แสดงบทสนทนา"
pinnedList: "รายชื่อที่ปักหมุดไว้" pinnedList: "รายชื่อที่ปักหมุดไว้"
keepScreenOn: "เปิดหน้าจออุปกรณ์ค้างไว้" keepScreenOn: "เปิดหน้าจอไว้"
verifiedLink: "ความเป็นเจ้าของลิงก์ได้รับการยืนยันแล้ว" verifiedLink: "ความเป็นเจ้าของลิงก์ได้รับการยืนยันแล้ว"
notifyNotes: "แจ้งเตือนเกี่ยวกับโพสต์ใหม่" notifyNotes: "แจ้งเตือนเกี่ยวกับโพสต์ใหม่"
unnotifyNotes: "หยุดการแจ้งเตือนเกี่ยวกับโน้ตใหม่" unnotifyNotes: "หยุดการแจ้งเตือนเกี่ยวกับโน้ตใหม่"
@@ -1160,7 +1159,6 @@ showRenotes: "แสดงรีโน้ต"
edited: "แก้ไขแล้ว" edited: "แก้ไขแล้ว"
notificationRecieveConfig: "การตั้งค่าการแจ้งเตือน" notificationRecieveConfig: "การตั้งค่าการแจ้งเตือน"
mutualFollow: "ติดตามซึ่งกันและกัน" mutualFollow: "ติดตามซึ่งกันและกัน"
followingOrFollower: "กำลังติดตามหรือผู้ติดตาม"
fileAttachedOnly: "เฉพาะโน้ตที่มีไฟล์เท่านั้น" fileAttachedOnly: "เฉพาะโน้ตที่มีไฟล์เท่านั้น"
showRepliesToOthersInTimeline: "แสดงการตอบกลับผู้อื่นลงในไทม์ไลน์" showRepliesToOthersInTimeline: "แสดงการตอบกลับผู้อื่นลงในไทม์ไลน์"
hideRepliesToOthersInTimeline: "ไม่แสดงการตอบกลับผู้อื่นลงในไทม์ไลน์" hideRepliesToOthersInTimeline: "ไม่แสดงการตอบกลับผู้อื่นลงในไทม์ไลน์"
@@ -1170,12 +1168,6 @@ confirmShowRepliesAll: "การดำเนินการนี้ไม่
confirmHideRepliesAll: "การดำเนินการนี้ไม่สามารถย้อนกลับได้ คุณต้องการซ่อนการตอบกลับผู้อื่นจากผู้ใช้ทุกคนที่คุณติดตามอยู่ในไทม์ไลน์ของคุณหรือไม่?" confirmHideRepliesAll: "การดำเนินการนี้ไม่สามารถย้อนกลับได้ คุณต้องการซ่อนการตอบกลับผู้อื่นจากผู้ใช้ทุกคนที่คุณติดตามอยู่ในไทม์ไลน์ของคุณหรือไม่?"
externalServices: "บริการภายนอก" externalServices: "บริการภายนอก"
sourceCode: "ซอร์สโค้ด" sourceCode: "ซอร์สโค้ด"
sourceCodeIsNotYetProvided: "ซอร์สโค้ดยังไม่พร้อมใช้งาน โปรดติดต่อผู้ดูแลระบบของคุณเพื่อแก้ไขปัญหานี้"
repositoryUrl: "URL ของ repository"
repositoryUrlDescription: "หากมีที่เก็บซอร์สโค้ดที่เปิดเผยต่อสาธารณะ ให้ป้อน URL ที่เก็บซอร์สโค้ดนั้น แต่หากคุณใช้ Misskey ตามต้นฉบับ (ไม่มีการเปลี่ยนแปลงซอร์สโค้ด) ให้ป้อน https://github.com/misskey-dev/misskey"
repositoryUrlOrTarballRequired: "หากคุณไม่มี repository สาธารณะ คุณจะต้องจัดเตรียม tarball แทน ดู .config/example.yml สำหรับรายละเอียด"
feedback: "ฟีดแบ็ก"
feedbackUrl: "URLของฟีดแบ็ก"
impressum: "อิมเพรสชั่น" impressum: "อิมเพรสชั่น"
impressumUrl: "URL อิมเพรสชั่น" impressumUrl: "URL อิมเพรสชั่น"
impressumDescription: "การติดป้ายกำกับ (Impressum) มีผลบังคับใช้ในบางประเทศและภูมิภาค เช่น ประเทศเยอรมนี" impressumDescription: "การติดป้ายกำกับ (Impressum) มีผลบังคับใช้ในบางประเทศและภูมิภาค เช่น ประเทศเยอรมนี"
@@ -1187,7 +1179,7 @@ attach: "แนบ"
detach: "นำออก" detach: "นำออก"
detachAll: "เอาออกทั้งหมด" detachAll: "เอาออกทั้งหมด"
angle: "แองเกิล" angle: "แองเกิล"
flip: "พลิก" flip: "ย้อนกลับ"
showAvatarDecorations: "แสดงตกแต่งอวตาร" showAvatarDecorations: "แสดงตกแต่งอวตาร"
releaseToRefresh: "ปล่อยเพื่อรีเฟรช" releaseToRefresh: "ปล่อยเพื่อรีเฟรช"
refreshing: "กำลังรีเฟรช..." refreshing: "กำลังรีเฟรช..."
@@ -1211,29 +1203,15 @@ soundWillBePlayed: "จะมีการเล่นเอฟเฟกต์เ
showReplay: "ดูรีเพลย์" showReplay: "ดูรีเพลย์"
replay: "รีเพลย์" replay: "รีเพลย์"
replaying: "กำลังรีเพลย์" replaying: "กำลังรีเพลย์"
endReplay: "ออกจากรีเพลย์"
copyReplayData: "คัดลอกข้อมูลรีเพลย์"
ranking: "อันดับ" ranking: "อันดับ"
lastNDays: "ล่าสุด {n} วันที่แล้ว" lastNDays: "ล่าสุด {n} วันที่แล้ว"
backToTitle: "กลับไปหน้าไตเติ้ล" backToTitle: "กลับไปหน้าไตเติ้ล"
hemisphere: "พื้นที่ที่อาศัยอยู่" hemisphere: "พื้นที่ที่อาศัยอยู่"
withSensitive: "แสดงโน้ตที่มีไฟล์เนื้อหาละเอียดอ่อน" withSensitive: "แสดงโน้ตที่มีไฟล์ที่ระบุว่ามีเนื้อหาละเอียดอ่อน"
userSaysSomethingSensitive: "โพสต์ที่มีไฟล์เนื้อหาละเอียดอ่อนของ {name}" userSaysSomethingSensitive: "โพสต์ที่มีไฟล์เนื้อหาละเอียดอ่อนของ {name}"
enableHorizontalSwipe: "ปัดเพื่อสลับแท็บ" enableHorizontalSwipe: "ปัดเพื่อสลับแท็บ"
loading: "กำลังโหลด"
surrender: "ยอมแพ้"
gameRetry: "เริ่มเกมใหม่"
_bubbleGame: _bubbleGame:
howToPlay: "วิธีเล่น" howToPlay: "วิธีเล่น"
hold: "หยุดชั่วคราว"
_score:
score: "คะแนน"
scoreYen: "จำนวนเงินที่ได้รับ"
highScore: "คะแนนสูงสุด"
maxChain: "จำนวน chain สูงสุด"
yen: "{yen} เยน"
estimatedQty: "{qty} อัน"
scoreSweets: "โอนิงิริ {onigiriQtyWithUnit}"
_howToPlay: _howToPlay:
section1: "ขยับตำแหน่งและวางวัตถุลงในกล่อง" section1: "ขยับตำแหน่งและวางวัตถุลงในกล่อง"
section2: "เมื่อวัตถุประเภทเดียวกันมารวมกัน พวกมันจะกลายเป็นวัตถุใหม่และคุณจะได้รับคะแนน" section2: "เมื่อวัตถุประเภทเดียวกันมารวมกัน พวกมันจะกลายเป็นวัตถุใหม่และคุณจะได้รับคะแนน"
@@ -1241,16 +1219,16 @@ _bubbleGame:
_announcement: _announcement:
forExistingUsers: "ผู้ใช้งานที่มีอยู่เท่านั้น" forExistingUsers: "ผู้ใช้งานที่มีอยู่เท่านั้น"
forExistingUsersDescription: "การประกาศนี้จะแสดงต่อผู้ใช้ที่มีอยู่ ณ จุดที่เผยแพร่นั้นๆถ้าหากเปิดใช้งาน ถ้าหากปิดใช้งานผู้ที่กำลังสมัครใหม่หลังจากโพสต์แล้วนั้นก็จะเห็นเช่นกัน" forExistingUsersDescription: "การประกาศนี้จะแสดงต่อผู้ใช้ที่มีอยู่ ณ จุดที่เผยแพร่นั้นๆถ้าหากเปิดใช้งาน ถ้าหากปิดใช้งานผู้ที่กำลังสมัครใหม่หลังจากโพสต์แล้วนั้นก็จะเห็นเช่นกัน"
needConfirmationToRead: "จำเป็นต้องยืนยันว่าอ่านแล้ว" needConfirmationToRead: "จำเป็นต้องยืนยันเพื่อทำเครื่องหมายบอกว่าอ่านแล้ว"
needConfirmationToReadDescription: "กล่องโต้ตอบการยืนยันจะปรากฏขึ้นเมื่อจะทำเครื่องหมายว่าอ่านแล้ว นอกจากนี้ยังทำให้ประกาศนี้ยังไม่ถูกอ่านเมื่อใช้ฟังก์ชั่นทำเครื่องหมายทั้งหมดว่าอ่านแล้ว" needConfirmationToReadDescription: "ข้อความแจ้งแยก ถ้าหากต้องการเพื่อยืนยันว่ากำลังทำเครื่องหมายประกาศนี้ว่าอ่านแล้วจะแสดงขึ้นถ้าหากเปิดใช้งาน การประกาศนั้นจะไม่รวมอยู่ในฟังก์ชั่นว่า \"ทำเครื่องหมายทั้งหมดว่าอ่านแล้ว\""
end: "เก็บประกาศ" end: "เก็บประกาศ"
tooManyActiveAnnouncementDescription: "การมีประกาศที่ใช้งานมากเกินไปนั้นอาจจะทำให้ประสบการณ์ของผู้ใช้งานนั้นดูแย่ลง โปรดกรุณาพิจารณาการเก็บประกาศที่ล้าสมัยด้วยนะค่ะ" tooManyActiveAnnouncementDescription: "การมีประกาศที่ใช้งานมากเกินไปนั้นอาจจะทำให้ประสบการณ์ของผู้ใช้งานนั้นดูแย่ลง โปรดกรุณาพิจารณาการเก็บประกาศที่ล้าสมัยด้วยนะค่ะ"
readConfirmTitle: "ทำเครื่องหมายว่าอ่านแล้วเลยไหม?" readConfirmTitle: "ทำเครื่องหมายบอกว่าอ่านแล้วเลยมั้ย?"
readConfirmText: "จะทำเครื่องหมายใส่ “{title}ว่าอ่านแล้ว" readConfirmText: "การดำเนินการนี้จะทำเครื่องหมายเนื้อหาของ \"{title}\" บอกว่าอ่านแล้วนะ"
shouldNotBeUsedToPresentPermanentInfo: "เราขอแนะนำให้ใช้ประกาศเพื่อโพสต์ข้อมูลแบบ flow มากกว่าข้อมูลแบบ stock เนื่องจากมีแนวโน้มที่จะส่งผลเสียต่อ UX โดยเฉพาะสำหรับผู้ใช้ใหม่" shouldNotBeUsedToPresentPermanentInfo: "เราขอแนะนำให้ใช้ประกาศเพื่อโพสต์ข้อมูลแบบ flow มากกว่าข้อมูลแบบ stock เนื่องจากมีแนวโน้มที่จะส่งผลเสียต่อ UX โดยเฉพาะสำหรับผู้ใช้ใหม่"
dialogAnnouncementUxWarn: "เราขอแนะนำให้ใช้ด้วยความระมัดระวัง เนื่องจากการแจ้งเตือนแบบกล่องโต้ตอบตั้งแต่ 2 รายการขึ้นไปพร้อมกันอาจส่งผลเสียต่อ UX ได้อย่างมาก" dialogAnnouncementUxWarn: "เราขอแนะนำให้ใช้ด้วยความระมัดระวัง เนื่องจากการแจ้งเตือนแบบกล่องโต้ตอบตั้งแต่ 2 รายการขึ้นไปพร้อมกันอาจส่งผลเสียต่อ UX ได้อย่างมาก"
silence: "ไม่มีการแจ้งเตือน" silence: "ไม่มีการแจ้งเตือน"
silenceDescription: "หากเปิดใช้งาน จะไม่มีการแจ้งเตือนประกาศนี้ และผู้ใช้จะไม่จำเป็นต้องทำเครื่องหมายว่าอ่านแล้ว" silenceDescription: "หากเปิดใช้งาน จะไม่ได้แจ้งเตือนประกาศนี้ และผู้ใช้จะไม่จำเป็นต้องอ่าน"
_initialAccountSetting: _initialAccountSetting:
accountCreated: "คุณได้สร้างบัญชีของคุณสำเร็จเรียบร้อยแล้ว!" accountCreated: "คุณได้สร้างบัญชีของคุณสำเร็จเรียบร้อยแล้ว!"
letsStartAccountSetup: "สำหรับผู้เริ่มต้นมาตั้งค่าโปรไฟล์ของคุณกันเถอะ" letsStartAccountSetup: "สำหรับผู้เริ่มต้นมาตั้งค่าโปรไฟล์ของคุณกันเถอะ"
@@ -1337,7 +1315,7 @@ _timelineDescription:
_serverRules: _serverRules:
description: "ชุดของกฎที่จะแสดงก่อนการลงทะเบียนเราขอแนะนำให้ตั้งค่าสรุปข้อกำหนดในการให้บริการ" description: "ชุดของกฎที่จะแสดงก่อนการลงทะเบียนเราขอแนะนำให้ตั้งค่าสรุปข้อกำหนดในการให้บริการ"
_serverSettings: _serverSettings:
iconUrl: "URL ไอคอน" iconUrl: "ไอคอน URL"
appIconDescription: "ระบุไอคอนที่จะใช้เมื่อ {host} แสดงเป็นแอป" appIconDescription: "ระบุไอคอนที่จะใช้เมื่อ {host} แสดงเป็นแอป"
appIconUsageExample: "E.g. เป็น PWA หรือเมื่อแสดงผลเป็นบุ๊กมาร์กหน้าจอหลักบนโทรศัพท์" appIconUsageExample: "E.g. เป็น PWA หรือเมื่อแสดงผลเป็นบุ๊กมาร์กหน้าจอหลักบนโทรศัพท์"
appIconStyleRecommendation: "เนื่องจากไอคอนอาจถูกครอบตัดเป็นสี่เหลี่ยมจัตุรัสหรือวงกลม จึงแนะนำให้ใช้ไอคอนที่มีขอบสีรอบๆ เนื้อหา" appIconStyleRecommendation: "เนื่องจากไอคอนอาจถูกครอบตัดเป็นสี่เหลี่ยมจัตุรัสหรือวงกลม จึงแนะนำให้ใช้ไอคอนที่มีขอบสีรอบๆ เนื้อหา"
@@ -1625,7 +1603,7 @@ _role:
assignTarget: "มอบหมาย" assignTarget: "มอบหมาย"
descriptionOfAssignTarget: "แบบ<b>ปรับเอง</b> เพิ่มถอนบทบาทนี้แก่ผู้ใช้ด้วยตัวเอง\nแบบ<b>มีเงื่อนไข</b> เพิ่มถอนบทบาทนี้แก่ผู้ใช้โดยอัตโนมัติหากเข้าเงื่อนไขใดต่อไปนี้" descriptionOfAssignTarget: "แบบ<b>ปรับเอง</b> เพิ่มถอนบทบาทนี้แก่ผู้ใช้ด้วยตัวเอง\nแบบ<b>มีเงื่อนไข</b> เพิ่มถอนบทบาทนี้แก่ผู้ใช้โดยอัตโนมัติหากเข้าเงื่อนไขใดต่อไปนี้"
manual: "ปรับเอง" manual: "ปรับเอง"
manualRoles: "บทบาทแบบทำมือ" manualRoles: "บทบาทแบบทำเอง"
conditional: "มีเงื่อนไข" conditional: "มีเงื่อนไข"
conditionalRoles: "บทบาทแบบมีเงื่อนไข" conditionalRoles: "บทบาทแบบมีเงื่อนไข"
condition: "เงื่อนไข" condition: "เงื่อนไข"
@@ -1637,13 +1615,13 @@ _role:
baseRole: "เทมเพลตบทบาท" baseRole: "เทมเพลตบทบาท"
useBaseValue: "ใช้ตามเทมเพลตบทบาท" useBaseValue: "ใช้ตามเทมเพลตบทบาท"
chooseRoleToAssign: "เลือกบทบาทที่ต้องการกำหนด" chooseRoleToAssign: "เลือกบทบาทที่ต้องการกำหนด"
iconUrl: "URL ไอคอน" iconUrl: "ไอคอน URL"
asBadge: "แสดงเป็นตรา" asBadge: "แสดงเป็นตรา"
descriptionOfAsBadge: "เมื่อเปิดใช้งาน ไอคอนบทบาทจะปรากฏถัดจากชื่อผู้ใช้" descriptionOfAsBadge: "เมื่อเปิดใช้งาน ไอคอนบทบาทจะปรากฏถัดจากชื่อผู้ใช้"
isExplorable: "ค้นหาผู้ใช้ได้ง่ายขึ้นโดยดูจากบทบาท" isExplorable: "ค้นหาผู้ใช้ได้ง่ายขึ้นโดยดูจากบทบาท"
descriptionOfIsExplorable: "เมื่อเปิดใช้งาน ไทมไลน์บทบาทนี้และสมาชิกที่มีบทบาทนี้จะเปิดเผยเป็นสาธารณะ" descriptionOfIsExplorable: "เมื่อเปิดใช้งาน ไทมไลน์บทบาทนี้และสมาชิกที่มีบทบาทนี้จะเปิดเผยเป็นสาธารณะ"
displayOrder: "ลำดับการแสดงผล" displayOrder: "ตำแหน่ง"
descriptionOfDisplayOrder: "เลขที่สูงกว่าจะแสดงบน UI ก่อน" descriptionOfDisplayOrder: "ยิ่งตัวเลขสูง ตำแหน่ง UI ก็ยิ่งสูงขึ้นนะ"
canEditMembersByModerator: "อนุญาตให้ผู้ควบคุมแก้ไขสมาชิก" canEditMembersByModerator: "อนุญาตให้ผู้ควบคุมแก้ไขสมาชิก"
descriptionOfCanEditMembersByModerator: "เมื่อเปิดใช้ นอกเหนือจากผู้ควบคุมและผู้ดูแลระบบแล้ว จะสามารถเพิ่มถอนบทบาทนี้แก่ผู้ใช้ได้ แต่เมื่อปิดใช้ จะมีเฉพาะผู้ดูแลระบบเท่านั้นที่จะสามารถดำเนินการได้" descriptionOfCanEditMembersByModerator: "เมื่อเปิดใช้ นอกเหนือจากผู้ควบคุมและผู้ดูแลระบบแล้ว จะสามารถเพิ่มถอนบทบาทนี้แก่ผู้ใช้ได้ แต่เมื่อปิดใช้ จะมีเฉพาะผู้ดูแลระบบเท่านั้นที่จะสามารถดำเนินการได้"
priority: "ลำดับความสำคัญ" priority: "ลำดับความสำคัญ"
@@ -1655,7 +1633,6 @@ _role:
gtlAvailable: "การดูไทม์ไลน์ทั่วโลก" gtlAvailable: "การดูไทม์ไลน์ทั่วโลก"
ltlAvailable: "การดูไทม์ไลน์ในท้องถิ่น" ltlAvailable: "การดูไทม์ไลน์ในท้องถิ่น"
canPublicNote: "สามารถโพสต์แบบสาธารณะ" canPublicNote: "สามารถโพสต์แบบสาธารณะ"
mentionMax: "จำนวนการกล่าวถึงสูงสุดต่อโน้ต"
canInvite: "สร้างรหัสเชิญอินสแตนซ์" canInvite: "สร้างรหัสเชิญอินสแตนซ์"
inviteLimit: "จำกัดการเชิญ" inviteLimit: "จำกัดการเชิญ"
inviteLimitCycle: "คูลดาวน์ในการเชิญ" inviteLimitCycle: "คูลดาวน์ในการเชิญ"
@@ -1679,7 +1656,6 @@ _role:
canUseTranslator: "การใช้งานแปล" canUseTranslator: "การใช้งานแปล"
avatarDecorationLimit: "จำนวนการตกแต่งไอคอนสูงสุดที่สามารถติดตั้งได้" avatarDecorationLimit: "จำนวนการตกแต่งไอคอนสูงสุดที่สามารถติดตั้งได้"
_condition: _condition:
roleAssignedTo: "มอบหมายให้มีบทบาทแบบทำมือ"
isLocal: "ผู้ใช้ในพื้นที่" isLocal: "ผู้ใช้ในพื้นที่"
isRemote: "ผู้ใช้ระยะไกล" isRemote: "ผู้ใช้ระยะไกล"
createdLessThan: "สร้างน้อยกว่า" createdLessThan: "สร้างน้อยกว่า"
@@ -1709,13 +1685,13 @@ _emailUnavailable:
smtp: "เซิร์ฟเวอร์อีเมลนี้ไม่มีการตอบสนอง" smtp: "เซิร์ฟเวอร์อีเมลนี้ไม่มีการตอบสนอง"
banned: "คุณไม่สามารถลงทะเบียนด้วยที่อยู่อีเมลนี้ได้" banned: "คุณไม่สามารถลงทะเบียนด้วยที่อยู่อีเมลนี้ได้"
_ffVisibility: _ffVisibility:
public: "สาธารณะ" public: "เผยแพร่"
followers: "ปรากฏให้แก่ผู้ติดตามเท่านั้น" followers: "ปรากฏให้แก่ผู้ติดตามเท่านั้น"
private: "ส่วนตัว" private: "ส่วนตัว"
_signup: _signup:
almostThere: "เกือบจะเสร็จแล้ว" almostThere: "เกือบจะเสร็จแล้ว"
emailAddressInfo: "กรุณากรอกที่อยู่อีเมลที่คุณใช้ ที่อยู่อีเมลของคุณจะไม่ถูกเผยแพร่สู่สาธารณชน" emailAddressInfo: "กรุณากรอกที่อยู่อีเมลที่คุณใช้ ที่อยู่อีเมลของคุณจะไม่ถูกเผยแพร่สู่สาธารณชน"
emailSent: "อีเมลยืนยันได้ถูกส่งไปยังที่อยู่อีเมลที่คุณป้อน ({email}) แล้ว กรุณาติดตามลิงก์ในอีเมลเพื่อสร้างบัญชีให้เสร็จสมบูรณ์ ลิงก์ที่ให้ไว้จะหมดอายุใน 30 นาที" emailSent: "เราได้ส่งอีเมลยืนยันไปยังที่อยู่อีเมลของคุณแล้วนะ ({email}) โปรดคลิกลิงก์ที่รวมไว้เพื่อสร้างบัญชีให้เสร็จสิ้น"
_accountDelete: _accountDelete:
accountDelete: "ลบบัญชีผู้ใช้" accountDelete: "ลบบัญชีผู้ใช้"
mayTakeTime: "เนื่องจากการลบบัญชีนี้จะเป็นกระบวนการที่ต้องใช้ทรัพยากรมาก จึงอาจจะต้องใช้เวลาสักครู่ถึงจะเสร็จสมบูรณ์ ทั้งนี้ขึ้นอยู่กับจำนวนเนื้อหาที่คุณสร้างและจำนวนไฟล์ที่คุณอัปโหลดนะ" mayTakeTime: "เนื่องจากการลบบัญชีนี้จะเป็นกระบวนการที่ต้องใช้ทรัพยากรมาก จึงอาจจะต้องใช้เวลาสักครู่ถึงจะเสร็จสมบูรณ์ ทั้งนี้ขึ้นอยู่กับจำนวนเนื้อหาที่คุณสร้างและจำนวนไฟล์ที่คุณอัปโหลดนะ"
@@ -1753,7 +1729,7 @@ _plugin:
viewSource: "ดูต้นฉบับ" viewSource: "ดูต้นฉบับ"
_preferencesBackups: _preferencesBackups:
list: "สร้างการสำรองข้อมูล" list: "สร้างการสำรองข้อมูล"
saveNew: "บันทึกข้อมูลสำรองใหม่" saveNew: "บันทึกใหม่"
loadFile: "โหลดจากไฟล์" loadFile: "โหลดจากไฟล์"
apply: "นำไปใช้กับอุปกรณ์นี้" apply: "นำไปใช้กับอุปกรณ์นี้"
save: "บันทึก" save: "บันทึก"
@@ -1763,8 +1739,8 @@ _preferencesBackups:
applyConfirm: "คุณต้องการใช้ข้อมูลสำรอง \"{name}\" กับอุปกรณ์นี้อย่างงั้นจริงหรอ การตั้งค่าที่มีอยู่ของอุปกรณ์นี้จะถูกเขียนทับนะ" applyConfirm: "คุณต้องการใช้ข้อมูลสำรอง \"{name}\" กับอุปกรณ์นี้อย่างงั้นจริงหรอ การตั้งค่าที่มีอยู่ของอุปกรณ์นี้จะถูกเขียนทับนะ"
saveConfirm: "บันทึกข้อมูลสำรองเป็น {name} มั้ย?" saveConfirm: "บันทึกข้อมูลสำรองเป็น {name} มั้ย?"
deleteConfirm: "ลบข้อมูลสำรอง {name} มั้ย?" deleteConfirm: "ลบข้อมูลสำรอง {name} มั้ย?"
renameConfirm: "ต้องการเปลี่ยนชื่อข้อมูลสำรองจาก {old} เป็น {new}” ใช่ไหม?" renameConfirm: "เปลี่ยนชื่อข้อมูลสำรองนี้จาก \"{old}\" เป็น \"{new}\" หรือไม่?"
noBackups: "ไม่มีข้อมูลสำรอง สามารถบันทึกการตั้งค่าไคลเอนต์ปัจจุบันไปยังเซิร์ฟเวอร์ด้วย “บันทึกข้อมูลสำรองใหม่”" noBackups: "ไม่มีข้อมูลสำรองนะ คุณสามารถสำรองข้อมูลการตั้งค่าไคลเอนต์ของคุณบนเซิร์ฟเวอร์นี้โดยใช้ \"สร้างการสำรองข้อมูลใหม่\"ได้นะ"
createdAt: "สร้างเมื่อ: {date} {time}" createdAt: "สร้างเมื่อ: {date} {time}"
updatedAt: "อัปเดตเมื่อ: {date} {time}" updatedAt: "อัปเดตเมื่อ: {date} {time}"
cannotLoad: "การโหลดล้มเหลว" cannotLoad: "การโหลดล้มเหลว"
@@ -1780,16 +1756,14 @@ _aboutMisskey:
contributors: "ผู้สนับสนุนหลัก" contributors: "ผู้สนับสนุนหลัก"
allContributors: "ผู้มีส่วนร่วมทั้งหมด" allContributors: "ผู้มีส่วนร่วมทั้งหมด"
source: "ซอร์สโค้ด" source: "ซอร์สโค้ด"
original: "ต้นฉบับ"
thisIsModifiedVersion: "{name} ใช้ Misskey เวอร์ชันดัดแปลง"
translation: "แปลภาษา Misskey" translation: "แปลภาษา Misskey"
donate: "บริจาคให้กับ Misskey" donate: "บริจาคให้กับ Misskey"
morePatrons: "และอีกหลายท่านที่ไม่ได้เอ่ยนาม ขอบคุณที่ร่วมช่วยเหลือตลอดมานะคะ 🥰" morePatrons: " ขอบคุณทุกท่านที่ร่วมกันช่วยเหลือตลอดมานะคะ 🥰"
patrons: "ผู้อุปถัมภ์" patrons: "สมาชิกพันธมิตร"
projectMembers: "สมาชิกในโครงการ" projectMembers: "สมาชิกในโครงการ"
_displayOfSensitiveMedia: _displayOfSensitiveMedia:
respect: "ซ่อนสื่อที่มีเนื้อหาละเอียดอ่อน" respect: "ซ่อนสื่อที่ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน"
ignore: "แสดงสื่อที่มีเนื้อหาละเอียดอ่อน" ignore: "แสดงสื่อที่ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน"
force: "ซ่อนสื่อทั้งหมด" force: "ซ่อนสื่อทั้งหมด"
_instanceTicker: _instanceTicker:
none: "ไม่ต้องแสดง" none: "ไม่ต้องแสดง"
@@ -1857,8 +1831,8 @@ _theme:
importInfo: "ถ้าหากต้องการป้อนโค้ดที่นี่ คุณยังสามารถนำเข้าไปยังโปรแกรมแก้ไขธีมได้" importInfo: "ถ้าหากต้องการป้อนโค้ดที่นี่ คุณยังสามารถนำเข้าไปยังโปรแกรมแก้ไขธีมได้"
deleteConstantConfirm: "คุณต้องการลบค่าคงที่ {const} หรือป่าว?" deleteConstantConfirm: "คุณต้องการลบค่าคงที่ {const} หรือป่าว?"
keys: keys:
accent: "สีหลัก" accent: "เน้น"
bg: "พื้นหลัง" bg: "ภาพพื้นหลัง"
fg: "ข้อความ" fg: "ข้อความ"
focus: "โฟกัส" focus: "โฟกัส"
indicator: "ตัวบ่งชี้" indicator: "ตัวบ่งชี้"
@@ -1894,11 +1868,11 @@ _theme:
wallpaperOverlay: "วอลล์เปเปอร์ซ้อนทับ" wallpaperOverlay: "วอลล์เปเปอร์ซ้อนทับ"
badge: "ตรา" badge: "ตรา"
messageBg: "พื้นหลังแชท" messageBg: "พื้นหลังแชท"
accentDarken: "สีหลัก (มืด)" accentDarken: "เน้น (มืด)"
accentLighten: "สีหลัก (สว่าง)" accentLighten: "เน้น (สว่าง)"
fgHighlighted: "ข้อความที่ไฮไลต์" fgHighlighted: "ข้อความที่ไฮไลต์"
_sfx: _sfx:
note: "โน้ต" note: "หมายเหตุ"
noteMy: "โน้ตของตัวเอง" noteMy: "โน้ตของตัวเอง"
notification: "การเเจ้งเตือน" notification: "การเเจ้งเตือน"
antenna: "เสาอากาศ" antenna: "เสาอากาศ"
@@ -1985,7 +1959,7 @@ _permissions:
"read:reactions": "ดูรีแอคชั่นของคุณ" "read:reactions": "ดูรีแอคชั่นของคุณ"
"write:reactions": "แก้ไขรีแอคชั่นของคุณ" "write:reactions": "แก้ไขรีแอคชั่นของคุณ"
"write:votes": "โหวตบนสำรวจความคิดเห็น" "write:votes": "โหวตบนสำรวจความคิดเห็น"
"read:pages": "ดหน้าเพจ" "read:pages": "ดหน้าเพจ"
"write:pages": "แก้ไขหรือลบเพจของคุณ" "write:pages": "แก้ไขหรือลบเพจของคุณ"
"read:page-likes": "ดูรายการเพจที่ถูกใจไว้" "read:page-likes": "ดูรายการเพจที่ถูกใจไว้"
"write:page-likes": "แก้ไขรายการเพจที่ถูกใจ" "write:page-likes": "แก้ไขรายการเพจที่ถูกใจ"
@@ -1997,8 +1971,8 @@ _permissions:
"write:gallery": "แก้ไขแกลเลอรี่ของคุณ" "write:gallery": "แก้ไขแกลเลอรี่ของคุณ"
"read:gallery-likes": "ดูรายการโพสต์แกลเลอรีที่ถูกใจไว้" "read:gallery-likes": "ดูรายการโพสต์แกลเลอรีที่ถูกใจไว้"
"write:gallery-likes": "แก้ไขรายการโพสต์แกลเลอรีที่ถูกใจไว้" "write:gallery-likes": "แก้ไขรายการโพสต์แกลเลอรีที่ถูกใจไว้"
"read:flash": "ดู Play" "read:flash": "วิว เพลย์"
"write:flash": "แก้ไข Play" "write:flash": "แก้ไขเพลย์"
"read:flash-likes": "ดูรายการ play ที่ถูกใจไว้" "read:flash-likes": "ดูรายการ play ที่ถูกใจไว้"
"write:flash-likes": "แก้ไขรายการ play ที่ถูกใจไว้" "write:flash-likes": "แก้ไขรายการ play ที่ถูกใจไว้"
"read:admin:abuse-user-reports": "ดูรายงานจากผู้ใช้" "read:admin:abuse-user-reports": "ดูรายงานจากผู้ใช้"
@@ -2025,8 +1999,8 @@ _permissions:
"read:admin:roles": "ดูบทบาท" "read:admin:roles": "ดูบทบาท"
"write:admin:relays": "จัดการรีเลย์" "write:admin:relays": "จัดการรีเลย์"
"read:admin:relays": "ดูรีเลย์" "read:admin:relays": "ดูรีเลย์"
"write:admin:invite-codes": "จัดการรหัสเชิญ" "write:admin:invite-codes": "จัดการคำเชิญ"
"read:admin:invite-codes": "ดูรหัสเชิญ" "read:admin:invite-codes": "ดูรหัสคำเชิญ"
"write:admin:announcements": "จัดการประกาศ" "write:admin:announcements": "จัดการประกาศ"
"read:admin:announcements": "ดูประกาศ" "read:admin:announcements": "ดูประกาศ"
"write:admin:avatar-decorations": "จัดการการตกแต่งอวตาร" "write:admin:avatar-decorations": "จัดการการตกแต่งอวตาร"
@@ -2044,7 +2018,7 @@ _permissions:
"read:admin:stream": "ใช้ Websocket API สำหรับผู้ดูแลระบบ" "read:admin:stream": "ใช้ Websocket API สำหรับผู้ดูแลระบบ"
"write:admin:ad": "จัดการโฆษณา" "write:admin:ad": "จัดการโฆษณา"
"read:admin:ad": "ดูโฆษณา" "read:admin:ad": "ดูโฆษณา"
"write:invite-codes": "สร้างรหัสเชิญ" "write:invite-codes": "สร้างรหัสคำเชิญ"
"read:invite-codes": "รับรหัสเชิญ" "read:invite-codes": "รับรหัสเชิญ"
"write:clip-favorite": "ควบคุมการถูกใจของคลิป" "write:clip-favorite": "ควบคุมการถูกใจของคลิป"
"read:clip-favorite": "ดูการถูกใจของคลิป" "read:clip-favorite": "ดูการถูกใจของคลิป"
@@ -2097,8 +2071,8 @@ _widgets:
onlineUsers: "ผู้ใช้ที่ออนไลน์" onlineUsers: "ผู้ใช้ที่ออนไลน์"
jobQueue: "คิวงาน" jobQueue: "คิวงาน"
serverMetric: "ตัวชี้วัดเซิร์ฟเวอร์" serverMetric: "ตัวชี้วัดเซิร์ฟเวอร์"
aiscript: " คอนโซล AiScript" aiscript: "AiScript คอนโซล"
aiscriptApp: "แอป AiScript" aiscriptApp: "AiScript แอพ"
aichan: "ไอ" aichan: "ไอ"
userList: "รายชื่อผู้ใช้" userList: "รายชื่อผู้ใช้"
_userList: _userList:
@@ -2112,15 +2086,15 @@ _cw:
files: "{count} ไฟล์" files: "{count} ไฟล์"
_poll: _poll:
noOnlyOneChoice: "จำเป็นต้องมีอย่างน้อยสองตัวเลือก" noOnlyOneChoice: "จำเป็นต้องมีอย่างน้อยสองตัวเลือก"
choiceN: "ตัวเลือกที่ {n}" choiceN: "ตัวเลือก {n}"
noMore: "เพิ่มตัวเลือกอีกไม่ได้แล้ว" noMore: "คุณไม่สามารถเพิ่มตัวเลือกอื่นได้"
canMultipleVote: "สามารถตอบได้หลายคำตอบ" canMultipleVote: "สามารถตอบได้หลายคำตอบ"
expiration: "สิ้นสุดโพล" expiration: "สิ้นสุดการสำรวจความคิดเห็น"
infinite: "ไม่กำหนดระยะเวลา" infinite: "ไม่ต้องเลย"
at: "ระบุวันเวลา" at: "จบที่..."
after: "ระบุระยะเวลา" after: "สิ้นสุดหลัง..."
deadlineDate: "วันสิ้นสุด" deadlineDate: "วันสิ้นสุด"
deadlineTime: "เวลา" deadlineTime: "ชั่วโมง"
duration: "ระยะเวลา" duration: "ระยะเวลา"
votesCount: "{n} คะแนนเสียง" votesCount: "{n} คะแนนเสียง"
totalVotes: "{n} คะแนนเสียงทั้งหมด" totalVotes: "{n} คะแนนเสียงทั้งหมด"
@@ -2128,17 +2102,17 @@ _poll:
showResult: "ดูผลลัพธ์" showResult: "ดูผลลัพธ์"
voted: "โหวตแล้ว" voted: "โหวตแล้ว"
closed: "สิ้นสุดแล้ว" closed: "สิ้นสุดแล้ว"
remainingDays: "เหลืออีก {d} วัน {h} ชั่วโมง" remainingDays: "จะเสร็จสิ้นในอีก {d} วัน {h} ชั่วโมง"
remainingHours: "เหลืออีก {h} ชั่วโมง {m} นาที" remainingHours: "{h} ชั่วโมง(s) {m} นาที(s) ที่เหลืออยู่"
remainingMinutes: "เหลืออีก {m} นาที {s} วินาที" remainingMinutes: "{m} นาที(s) {s} วินาที(s) ที่เหลืออยู่"
remainingSeconds: "เหลืออีก {s} วินาที" remainingSeconds: "{s} นาที(s) ที่เหลืออยู่"
_visibility: _visibility:
public: "สาธารณะ" public: "สาธารณะ"
publicDescription: "โน้ตของคุณจะปรากฏแก่ผู้ใช้ทุกคน" publicDescription: "โน้ตของคุณจะปรากฏแก่ผู้ใช้ทุกคน"
home: "หน้าแรก" home: "หน้าแรก"
homeDescription: "โพสลงไทม์ไลน์ที่บ้านเท่านั้น" homeDescription: "โพสลงไทม์ไลน์ที่บ้านเท่านั้น"
followers: "ผู้ติดตาม" followers: "ผู้ติดตาม"
followersDescription: "เฉพาะผู้ติดตามเท่านั้นที่มองเห็นได้" followersDescription: "ทำให้ผู้ติดตามนั้นมองเห็นแค่คุณเท่านั้น"
specified: "ไดเร็ค" specified: "ไดเร็ค"
specifiedDescription: "ทำให้มองเห็นได้เฉพาะผู้ใช้ที่ระบุเท่านั้น" specifiedDescription: "ทำให้มองเห็นได้เฉพาะผู้ใช้ที่ระบุเท่านั้น"
disableFederation: "ไม่มีสหพันธ์" disableFederation: "ไม่มีสหพันธ์"
@@ -2148,11 +2122,11 @@ _postForm:
quotePlaceholder: "อ้างโน้ตนี้..." quotePlaceholder: "อ้างโน้ตนี้..."
channelPlaceholder: "โพสต์ลงช่อง..." channelPlaceholder: "โพสต์ลงช่อง..."
_placeholders: _placeholders:
a: "ตอนนี้เป็นยังไงบ้าง?" a: "คุณเป็นอะไรไปหรอ?"
b: "มีอะไรเกิดขึ้นหรือเปล่า?" b: "เกิดอะไรขึ้นรอบตัวคุณ?"
c: "กำลังคิดอะไรอยู่?" c: "คุณกำลังคิดอะไรอยู่?"
d: "ต้องการจะพูดอะไรไหม?" d: "คุณต้องการจะพูดอะไร?"
e: "มาเขียนกันเถอะ" e: "เริ่มเขียน..."
f: "กำลังรอให้คุณเขียน..." f: "กำลังรอให้คุณเขียน..."
_profile: _profile:
name: "ชื่อ" name: "ชื่อ"
@@ -2166,11 +2140,11 @@ _profile:
metadataContent: "เนื้อหา" metadataContent: "เนื้อหา"
changeAvatar: "เปลี่ยนอวาตาร์" changeAvatar: "เปลี่ยนอวาตาร์"
changeBanner: "เปลี่ยนแบนเนอร์" changeBanner: "เปลี่ยนแบนเนอร์"
verifiedLinkDescription: "หากป้อน URL ที่มีลิงก์ไปยังโปรไฟล์ของคุณ ไอคอนการยืนยันความเป็นเจ้าของจะแสดงถัดจากฟิลด์นั้น ๆ" verifiedLinkDescription: "โดยการป้อน URL ที่มีลิงก์ไปยังโปรไฟล์ของคุณตรงนี้ ส่วนไอคอนการยืนยันความเป็นเจ้าของนั้นก็สามารถแสดงถัดจากฟิลด์ได้นะ"
avatarDecorationMax: "คุณสามารถเพิ่มการตกแต่งได้สูงสุด {max}" avatarDecorationMax: "คุณสามารถเพิ่มการตกแต่งได้สูงสุด {max}"
_exportOrImport: _exportOrImport:
allNotes: "โน้ตทั้งหมด" allNotes: "โน้ตทั้งหมด"
favoritedNotes: "โน้ตที่ถูกใจไว้" favoritedNotes: "บันทึกที่ชื่นชอบ"
clips: "คลิป" clips: "คลิป"
followingList: "กำลังติดตาม" followingList: "กำลังติดตาม"
muteList: "ปิดเสียง" muteList: "ปิดเสียง"
@@ -2253,7 +2227,7 @@ _pages:
summary: "สรุปเพจ" summary: "สรุปเพจ"
alignCenter: "เซ็นเตอร์" alignCenter: "เซ็นเตอร์"
hideTitleWhenPinned: "ซ่อนชื่อหน้าเพจเมื่อปักหมุดไว้ที่โปรไฟล์" hideTitleWhenPinned: "ซ่อนชื่อหน้าเพจเมื่อปักหมุดไว้ที่โปรไฟล์"
font: "แบบอักษร" font: "ตัวอักษร"
fontSerif: "Serif" fontSerif: "Serif"
fontSansSerif: "Sans Serif" fontSansSerif: "Sans Serif"
eyeCatchingImageSet: "ตั้งค่าภาพขนาดย่อ" eyeCatchingImageSet: "ตั้งค่าภาพขนาดย่อ"
@@ -2279,28 +2253,27 @@ _relayStatus:
accepted: "ได้รับการอนุมัติ" accepted: "ได้รับการอนุมัติ"
rejected: "ถูกปฏิเสธ" rejected: "ถูกปฏิเสธ"
_notification: _notification:
fileUploaded: "ไฟล์ถูกอัโหลดแล้ว" fileUploaded: "ไฟล์ถูกอัโหลดแล้วน่ะ"
youGotMention: "{name} กล่าวถึงคุณ" youGotMention: "{name} กล่าวถึงคุณ"
youGotReply: "{name} ตอบกลับถึงคุณ" youGotReply: "{name} ตอบกลับถึงคุณ"
youGotQuote: "{name} อ้างอิงคุณ" youGotQuote: "{name} อ้างถึงคุณ"
youRenoted: "รีโน้ตจาก {name}" youRenoted: "รีโน้ตจาก {name}"
youWereFollowed: "ได้ติดตามคุณ" youWereFollowed: "ได้ติดตามคุณ"
youReceivedFollowRequest: "ได้รับคำขอติดตาม" youReceivedFollowRequest: "คุณมีคำขอติดตามใหม่น่ะ"
yourFollowRequestAccepted: "คำขอติดตามได้รับการอนุมัติแล้ว" yourFollowRequestAccepted: "คำขอติดตามของคุณได้รับการยอมรับแล้วน่ะ"
pollEnded: "ผลโพลออกมาแล้ว" pollEnded: "โพลสำรวจความคิดเห็นผลลัพธ์มีพร้อมใช้งาน"
newNote: "โพสต์ใหม่" newNote: "โพสต์ใหม่"
unreadAntennaNote: "เสาอากาศ {name}" unreadAntennaNote: "เสาอากาศ {name}"
roleAssigned: "ได้รับบทบาท" roleAssigned: "ได้รับบทบาท"
emptyPushNotificationMessage: "อัปเดตการแจ้งเตือนแบบพุชแล้ว" emptyPushNotificationMessage: "การแจ้งเตือนแบบพุชได้รับการอัพเดทแล้ว"
achievementEarned: "รับความสำเร็จ" achievementEarned: "รับความสำเร็จ"
testNotification: "ทดสอบการแจ้งเตือน" testNotification: "ทดสอบการแจ้งเตือน"
checkNotificationBehavior: "กดเพื่อดูลักษณะการแจ้งเตือน" checkNotificationBehavior: "กดเพื่อดูลักษณะการแจ้งเตือน"
sendTestNotification: "ส่งทดสอบการแจ้งเตือน" sendTestNotification: "ส่งทดสอบการแจ้งเตือน"
notificationWillBeDisplayedLikeThis: "การแจ้งเตือนมีลักษณะแบบนี้" notificationWillBeDisplayedLikeThis: "การแจ้งเตือนมีลักษณะแบบนี้"
reactedBySomeUsers: "ถูกรีแอคชั่นโดยผู้ใช้ {n} ราย" reactedBySomeUsers: "ถูกรีแอคชั่นโดยผู้ใช้ {n} ราย"
renotedBySomeUsers: "รีโน้ตจากผู้ใช้ {n} ราย" renotedBySomeUsers: "Renote จากผู้ใช้จำนวน {n} ราย"
followedBySomeUsers: "มีผู้ติดตาม {n} ราย" followedBySomeUsers: "มีผู้ติดตาม {n} ราย"
flushNotification: "ล้างประวัติการแจ้งเตือน"
_types: _types:
all: "ทั้งหมด" all: "ทั้งหมด"
note: "โน้ตใหม่" note: "โน้ตใหม่"
@@ -2310,9 +2283,9 @@ _notification:
renote: "รีโน้ต" renote: "รีโน้ต"
quote: "อ้างคำพูด" quote: "อ้างคำพูด"
reaction: "รีแอคชั่น" reaction: "รีแอคชั่น"
pollEnded: "โพลสิ้นสุดแล้ว" pollEnded: "โพลนี้สิ้นสุดลงแล้ว"
receiveFollowRequest: "ได้รับคำร้องขอติดตาม" receiveFollowRequest: "ได้รับคำขอติดตาม\n"
followRequestAccepted: "อนุมัติให้ติดตามแล้ว" followRequestAccepted: "ยอมรับคำขอติดตาม"
roleAssigned: "ให้บทบาท" roleAssigned: "ให้บทบาท"
achievementEarned: "ปลดล็อกความสำเร็จแล้ว" achievementEarned: "ปลดล็อกความสำเร็จแล้ว"
app: "การแจ้งเตือนจากแอปที่มีลิงก์" app: "การแจ้งเตือนจากแอปที่มีลิงก์"
@@ -2349,7 +2322,7 @@ _deck:
list: "รายการ" list: "รายการ"
channel: "ช่อง" channel: "ช่อง"
mentions: "พูดถึง" mentions: "พูดถึง"
direct: "ไดเร็กต์" direct: "ไดเร็"
roleTimeline: "บทบาทไทม์ไลน์" roleTimeline: "บทบาทไทม์ไลน์"
_dialog: _dialog:
charactersExceeded: "คุณกำลังมีตัวอักขระเกินขีดจำกัดสูงสุดแล้วนะ! ปัจจุบันอยู่ที่ {current} จาก {max}" charactersExceeded: "คุณกำลังมีตัวอักขระเกินขีดจำกัดสูงสุดแล้วนะ! ปัจจุบันอยู่ที่ {current} จาก {max}"
@@ -2380,8 +2353,8 @@ _moderationLogTypes:
updateRole: "อัปเดตบทบาทแล้ว" updateRole: "อัปเดตบทบาทแล้ว"
assignRole: "ได้รับมอบหมายบทบาท" assignRole: "ได้รับมอบหมายบทบาท"
unassignRole: "ถอดออกจากบทบาทแล้ว" unassignRole: "ถอดออกจากบทบาทแล้ว"
suspend: "ระงับ" suspend: "ถูกระงับ"
unsuspend: "เลิกระงับ" unsuspend: "เลิกถูกระงับ"
addCustomEmoji: "เพิ่มเอโมจิที่กำหนดเองแล้ว" addCustomEmoji: "เพิ่มเอโมจิที่กำหนดเองแล้ว"
updateCustomEmoji: "อัปเดตเอโมจิที่กำหนดเองแล้ว" updateCustomEmoji: "อัปเดตเอโมจิที่กำหนดเองแล้ว"
deleteCustomEmoji: "ลบเอโมจิที่กำหนดเองออกแล้ว" deleteCustomEmoji: "ลบเอโมจิที่กำหนดเองออกแล้ว"
@@ -2396,13 +2369,12 @@ _moderationLogTypes:
deleteGlobalAnnouncement: "ลบประกาศทั่วโลกออกแล้ว" deleteGlobalAnnouncement: "ลบประกาศทั่วโลกออกแล้ว"
deleteUserAnnouncement: "ลบประกาศผู้ใช้ออกแล้ว" deleteUserAnnouncement: "ลบประกาศผู้ใช้ออกแล้ว"
resetPassword: "รีเซ็ตรหัสผ่าน" resetPassword: "รีเซ็ตรหัสผ่าน"
suspendRemoteInstance: "ระงับอินสแตนซ์ระยะไกล" suspendRemoteInstance: "อินสแตนซ์ระยะไกลถูกระงับ"
unsuspendRemoteInstance: "เลิกระงับอินสแตนซ์ระยะไกล" unsuspendRemoteInstance: "อินสแตนซ์ระยะไกลเลิกการระงับ"
updateRemoteInstanceNote: "อัปเดตโน้ตการกลั่นกรองของอินสแตนซ์ระยะไกลแล้ว"
markSensitiveDriveFile: "ทำเครื่องหมายไฟล์ว่ามีเนื้อหาละเอียดอ่อน" markSensitiveDriveFile: "ทำเครื่องหมายไฟล์ว่ามีเนื้อหาละเอียดอ่อน"
unmarkSensitiveDriveFile: "ยกเลิกทำเครื่องหมายไฟล์ว่ามีเนื้อหาละเอียดอ่อน" unmarkSensitiveDriveFile: "ยกเลิกทำเครื่องหมายไฟล์ว่ามีเนื้อหาละเอียดอ่อน"
resolveAbuseReport: "รายงานได้รับการแก้ไขแล้ว" resolveAbuseReport: "รายงานได้รับการแก้ไขแล้ว"
createInvitation: "สร้างรหัสเชิญ" createInvitation: "สร้างคำเชิญ"
createAd: "สร้างโฆษณาแล้ว" createAd: "สร้างโฆษณาแล้ว"
deleteAd: "ลบโฆษณาออกแล้ว" deleteAd: "ลบโฆษณาออกแล้ว"
updateAd: "อัปเดตโฆษณาแล้ว" updateAd: "อัปเดตโฆษณาแล้ว"
@@ -2519,8 +2491,6 @@ _reversi:
opponentHasSettingsChanged: "อีกฝ่ายเปลี่ยนการตั้งค่า" opponentHasSettingsChanged: "อีกฝ่ายเปลี่ยนการตั้งค่า"
allowIrregularRules: "อนุญาตกฎที่ไม่ปรกติ (โหมดฟรีทุกอย่าง)" allowIrregularRules: "อนุญาตกฎที่ไม่ปรกติ (โหมดฟรีทุกอย่าง)"
disallowIrregularRules: "ไม่อนุญาตกฎที่ไม่ปรกติ" disallowIrregularRules: "ไม่อนุญาตกฎที่ไม่ปรกติ"
showBoardLabels: "แสดงหมายเลขแถว/คอลัมน์บนกระดาน"
useAvatarAsStone: "ใช้รูปอวตารเป็นหมาก"
_offlineScreen: _offlineScreen:
title: "ออฟไลน์ - ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ได้" title: "ออฟไลน์ - ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ได้"
header: "ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ได้" header: "ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ได้"

View File

@@ -1048,7 +1048,6 @@ verifiedLink: "Chúng tôi đã xác nhận bạn là chủ sở hữu của đ
sourceCode: "Mã nguồn" sourceCode: "Mã nguồn"
flip: "Lật" flip: "Lật"
lastNDays: "{n} ngày trước" lastNDays: "{n} ngày trước"
surrender: "Từ chối"
_announcement: _announcement:
forExistingUsers: "Chỉ những người dùng đã tồn tại" forExistingUsers: "Chỉ những người dùng đã tồn tại"
forExistingUsersDescription: "Nếu được bật, thông báo này sẽ chỉ hiển thị với những người dùng đã tồn tại vào lúc thông báo được tạo. Nếu tắt đi, những tài khoản mới đăng ký sau khi thông báo được đăng lên cũng sẽ thấy nó." forExistingUsersDescription: "Nếu được bật, thông báo này sẽ chỉ hiển thị với những người dùng đã tồn tại vào lúc thông báo được tạo. Nếu tắt đi, những tài khoản mới đăng ký sau khi thông báo được đăng lên cũng sẽ thấy nó."

View File

@@ -336,7 +336,7 @@ displayOfSensitiveMedia: "显示敏感媒体"
whenServerDisconnected: "与服务器连接中断时" whenServerDisconnected: "与服务器连接中断时"
disconnectedFromServer: "已和服务器断开连接" disconnectedFromServer: "已和服务器断开连接"
reload: "重新加载" reload: "重新加载"
doNothing: "关闭" doNothing: "关闭弹窗"
reloadConfirm: "确定要重新加载吗?" reloadConfirm: "确定要重新加载吗?"
watch: "关注" watch: "关注"
unwatch: "取消关注" unwatch: "取消关注"
@@ -991,7 +991,6 @@ neverShow: "不再显示"
remindMeLater: "稍后提醒我" remindMeLater: "稍后提醒我"
didYouLikeMisskey: "您喜欢 Misskey 吗?" didYouLikeMisskey: "您喜欢 Misskey 吗?"
pleaseDonate: "Misskey 是 {host} 所使用的免费软件。为了今后也能够维持 Misskey 的开发,请在有余力的情况下进行捐助!" pleaseDonate: "Misskey 是 {host} 所使用的免费软件。为了今后也能够维持 Misskey 的开发,请在有余力的情况下进行捐助!"
correspondingSourceIsAvailable: "对应的源代码可在{anchor}找到"
roles: "角色" roles: "角色"
role: "角色" role: "角色"
noRole: "角色不存在" noRole: "角色不存在"
@@ -1043,7 +1042,6 @@ sensitiveWords: "敏感词"
sensitiveWordsDescription: "将包含设置词的帖子的可见范围设置为首页。可以通过用换行符分隔来设置多个。" sensitiveWordsDescription: "将包含设置词的帖子的可见范围设置为首页。可以通过用换行符分隔来设置多个。"
sensitiveWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。" sensitiveWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。"
prohibitedWords: "禁用词" prohibitedWords: "禁用词"
prohibitedWordsDescription: "发布包含设定词汇的帖子时将出错。可用换行设定多个关键字"
prohibitedWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。" prohibitedWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。"
hiddenTags: "隐藏标签" hiddenTags: "隐藏标签"
hiddenTagsDescription: "设定的标签将不会在时间线上显示。可使用换行来设置多个标签。" hiddenTagsDescription: "设定的标签将不会在时间线上显示。可使用换行来设置多个标签。"
@@ -1117,7 +1115,7 @@ branding: "品牌"
enableServerMachineStats: "公开服务器硬件统计信息" enableServerMachineStats: "公开服务器硬件统计信息"
enableIdenticonGeneration: "启用生成用户 Identicon" enableIdenticonGeneration: "启用生成用户 Identicon"
turnOffToImprovePerformance: "关闭该选项可以提高性能。" turnOffToImprovePerformance: "关闭该选项可以提高性能。"
createInviteCode: "生成邀请码" createInviteCode: "发行邀请码"
createWithOptions: "使用选项来创建" createWithOptions: "使用选项来创建"
createCount: "发行数" createCount: "发行数"
inviteCodeCreated: "已创建邀请码" inviteCodeCreated: "已创建邀请码"
@@ -1129,7 +1127,7 @@ noExpirationDate: "不设置有效日期"
inviteCodeUsedAt: "邀请码被使用的日期和时间" inviteCodeUsedAt: "邀请码被使用的日期和时间"
registeredUserUsingInviteCode: "使用了邀请码的用户" registeredUserUsingInviteCode: "使用了邀请码的用户"
waitingForMailAuth: "等待验证电子邮件" waitingForMailAuth: "等待验证电子邮件"
inviteCodeCreator: "生成邀请码的用户" inviteCodeCreator: "发行邀请码的用户"
usedAt: "使用时间" usedAt: "使用时间"
unused: "未使用" unused: "未使用"
used: "已使用" used: "已使用"
@@ -1160,7 +1158,6 @@ showRenotes: "显示转帖"
edited: "已编辑" edited: "已编辑"
notificationRecieveConfig: "通知接收设置" notificationRecieveConfig: "通知接收设置"
mutualFollow: "互相关注" mutualFollow: "互相关注"
followingOrFollower: "关注中或关注者"
fileAttachedOnly: "仅限媒体" fileAttachedOnly: "仅限媒体"
showRepliesToOthersInTimeline: "在时间线中包含给别人的回复" showRepliesToOthersInTimeline: "在时间线中包含给别人的回复"
hideRepliesToOthersInTimeline: "在时间线中隐藏给别人的回复" hideRepliesToOthersInTimeline: "在时间线中隐藏给别人的回复"
@@ -1170,12 +1167,6 @@ confirmShowRepliesAll: "此操作不可撤销。确认要在时间线中包含
confirmHideRepliesAll: "此操作不可撤销。确认要在时间线中隐藏现在关注的所有人的回复吗?" confirmHideRepliesAll: "此操作不可撤销。确认要在时间线中隐藏现在关注的所有人的回复吗?"
externalServices: "外部服务" externalServices: "外部服务"
sourceCode: "源代码" sourceCode: "源代码"
sourceCodeIsNotYetProvided: "还未提供源代码。要解决此问题请联系管理员。"
repositoryUrl: "仓库地址"
repositoryUrlDescription: "若源代码所在的仓库是公开的,请填入对应的 URL。若是按原样使用 Misskey并未追加或者修改代码的情况请填入 https://github.com/misskey-dev/misskey。"
repositoryUrlOrTarballRequired: "若仓库并未公开,则需要提供 tarball 作为替代。详情请看 .config/example.yml。"
feedback: "反馈"
feedbackUrl: "反馈地址"
impressum: "运营商信息" impressum: "运营商信息"
impressumUrl: "运营商信息地址" impressumUrl: "运营商信息地址"
impressumDescription: "德国等国家和地区有义务展示此类信息Impressum。" impressumDescription: "德国等国家和地区有义务展示此类信息Impressum。"
@@ -1205,14 +1196,11 @@ seasonalScreenEffect: "应景的画面效果"
decorate: "装饰" decorate: "装饰"
addMfmFunction: "添加装饰" addMfmFunction: "添加装饰"
enableQuickAddMfmFunction: "显示高级 MFM 选择器" enableQuickAddMfmFunction: "显示高级 MFM 选择器"
bubbleGame: "泡泡游戏"
sfx: "音效" sfx: "音效"
soundWillBePlayed: "声音将会播放" soundWillBePlayed: "声音将会播放"
showReplay: "观看回放" showReplay: "查看重播"
replay: "重播" replay: "重播"
replaying: "重播中" replaying: "重播中"
endReplay: "结束回放"
copyReplayData: "复制回放数据"
ranking: "排行榜" ranking: "排行榜"
lastNDays: "最近 {n} 天" lastNDays: "最近 {n} 天"
backToTitle: "返回标题" backToTitle: "返回标题"
@@ -1220,19 +1208,8 @@ hemisphere: "居住地区"
withSensitive: "显示包含敏感媒体的帖子" withSensitive: "显示包含敏感媒体的帖子"
userSaysSomethingSensitive: "含 {name} 敏感文件的帖子" userSaysSomethingSensitive: "含 {name} 敏感文件的帖子"
enableHorizontalSwipe: "滑动切换标签页" enableHorizontalSwipe: "滑动切换标签页"
loading: "读取中"
surrender: "取消"
gameRetry: "重试"
_bubbleGame: _bubbleGame:
howToPlay: "游戏说明" howToPlay: "游戏说明"
hold: "抓住"
_score:
score: "得分"
scoreYen: "赚到的钱"
highScore: "最高分"
maxChain: "最高连击数"
yen: "{yen} 日元"
estimatedQty: "约 {qty} 个"
_howToPlay: _howToPlay:
section1: "对准位置将Emoji投入盒子。" section1: "对准位置将Emoji投入盒子。"
section2: "相同的Emoji相互接触合成后会得到新的Emoji以此获得分数。" section2: "相同的Emoji相互接触合成后会得到新的Emoji以此获得分数。"
@@ -1321,8 +1298,8 @@ _initialTutorial:
description: "对于服务器方针所要求要求的,又或者不适合直接展示的附件,请添加「敏感」标记。\n" description: "对于服务器方针所要求要求的,又或者不适合直接展示的附件,请添加「敏感」标记。\n"
tryThisFile: "试试看,将附加到此窗口的图像标注为敏感!" tryThisFile: "试试看,将附加到此窗口的图像标注为敏感!"
_exampleNote: _exampleNote:
note: "拆纳豆包装时出错了…" note: "不该打开纳豆的盖子的……"
method: "要标注附件为敏感内容,请单击该文件以打开菜单,然后单击“标记为敏感内容”。" method: "要标注附件为敏感内容,请单击该文件以打开菜单,然后单击“设置为敏感”。"
sensitiveSucceeded: "附加文件时,请遵循服务器的条款来设置正确敏感设定。\n" sensitiveSucceeded: "附加文件时,请遵循服务器的条款来设置正确敏感设定。\n"
doItToContinue: "将图像标记为敏感后才能够继续" doItToContinue: "将图像标记为敏感后才能够继续"
_done: _done:
@@ -1653,9 +1630,8 @@ _role:
gtlAvailable: "查看全局时间线" gtlAvailable: "查看全局时间线"
ltlAvailable: "查看本地时间线" ltlAvailable: "查看本地时间线"
canPublicNote: "允许公开发帖" canPublicNote: "允许公开发帖"
mentionMax: "帖子内最多提及数"
canInvite: "发放服务器邀请码" canInvite: "发放服务器邀请码"
inviteLimit: "可生成邀请码的数量" inviteLimit: "可发行邀请码的数量"
inviteLimitCycle: "邀请码的发行间隔" inviteLimitCycle: "邀请码的发行间隔"
inviteExpirationTime: "邀请码的有效日期" inviteExpirationTime: "邀请码的有效日期"
canManageCustomEmojis: "管理自定义表情符号" canManageCustomEmojis: "管理自定义表情符号"
@@ -1677,7 +1653,6 @@ _role:
canUseTranslator: "使用翻译功能" canUseTranslator: "使用翻译功能"
avatarDecorationLimit: "可添加头像挂件的最大个数" avatarDecorationLimit: "可添加头像挂件的最大个数"
_condition: _condition:
roleAssignedTo: "已分配给手动角色"
isLocal: "是本地用户" isLocal: "是本地用户"
isRemote: "是远程用户" isRemote: "是远程用户"
createdLessThan: "账户创建时间少于" createdLessThan: "账户创建时间少于"
@@ -1778,8 +1753,6 @@ _aboutMisskey:
contributors: "主要贡献者" contributors: "主要贡献者"
allContributors: "全体贡献者" allContributors: "全体贡献者"
source: "源代码" source: "源代码"
original: "原版"
thisIsModifiedVersion: "{name}正在使用修改后的 Misskey。"
translation: "翻译 Misskey" translation: "翻译 Misskey"
donate: "赞助 Misskey" donate: "赞助 Misskey"
morePatrons: "还有很多其它的人也在支持我们,非常感谢🥰" morePatrons: "还有很多其它的人也在支持我们,非常感谢🥰"
@@ -2042,7 +2015,7 @@ _permissions:
"read:admin:stream": "使用管理员用的 Websocket API" "read:admin:stream": "使用管理员用的 Websocket API"
"write:admin:ad": "编辑广告" "write:admin:ad": "编辑广告"
"read:admin:ad": "查看广告" "read:admin:ad": "查看广告"
"write:invite-codes": "生成邀请码" "write:invite-codes": "发行邀请码"
"read:invite-codes": "获取已发行的邀请码" "read:invite-codes": "获取已发行的邀请码"
"write:clip-favorite": "编辑便签的点赞" "write:clip-favorite": "编辑便签的点赞"
"read:clip-favorite": "查看便签的点赞" "read:clip-favorite": "查看便签的点赞"
@@ -2298,7 +2271,6 @@ _notification:
reactedBySomeUsers: "{n} 人回应了" reactedBySomeUsers: "{n} 人回应了"
renotedBySomeUsers: "{n} 人转发了" renotedBySomeUsers: "{n} 人转发了"
followedBySomeUsers: "被 {n} 人关注" followedBySomeUsers: "被 {n} 人关注"
flushNotification: "重置通知历史"
_types: _types:
all: "全部" all: "全部"
note: "用户的新帖子" note: "用户的新帖子"
@@ -2396,11 +2368,10 @@ _moderationLogTypes:
resetPassword: "重置密码" resetPassword: "重置密码"
suspendRemoteInstance: "停止远程服务器" suspendRemoteInstance: "停止远程服务器"
unsuspendRemoteInstance: "恢复远程服务器" unsuspendRemoteInstance: "恢复远程服务器"
updateRemoteInstanceNote: "更新远程服务器的管理笔记"
markSensitiveDriveFile: "标记网盘文件为敏感媒体" markSensitiveDriveFile: "标记网盘文件为敏感媒体"
unmarkSensitiveDriveFile: "取消标记网盘文件为敏感媒体" unmarkSensitiveDriveFile: "取消标记网盘文件为敏感媒体"
resolveAbuseReport: "处理举报" resolveAbuseReport: "处理举报"
createInvitation: "生成邀请码" createInvitation: "发行邀请码"
createAd: "创建了广告" createAd: "创建了广告"
deleteAd: "删除了广告" deleteAd: "删除了广告"
updateAd: "更新了广告" updateAd: "更新了广告"
@@ -2491,8 +2462,6 @@ _reversi:
myTurn: "你的回合" myTurn: "你的回合"
turnOf: "{name}的回合" turnOf: "{name}的回合"
pastTurnOf: "{name}的回合" pastTurnOf: "{name}的回合"
surrender: "认输"
surrendered: "已认输"
timeout: "超时" timeout: "超时"
drawn: "平局" drawn: "平局"
won: "{name}获胜" won: "{name}获胜"
@@ -2514,8 +2483,6 @@ _reversi:
opponentHasSettingsChanged: "对手更改了设定" opponentHasSettingsChanged: "对手更改了设定"
allowIrregularRules: "允许非常规规则(完全自由)" allowIrregularRules: "允许非常规规则(完全自由)"
disallowIrregularRules: "禁止非常规规则" disallowIrregularRules: "禁止非常规规则"
showBoardLabels: "显示行号和列号"
useAvatarAsStone: "用头像作为棋子"
_offlineScreen: _offlineScreen:
title: "离线——无法连接到服务器" title: "离线——无法连接到服务器"
header: "无法连接到服务器" header: "无法连接到服务器"

View File

@@ -991,7 +991,6 @@ neverShow: "不再顯示"
remindMeLater: "以後再說" remindMeLater: "以後再說"
didYouLikeMisskey: "您喜歡 Misskey 嗎?" didYouLikeMisskey: "您喜歡 Misskey 嗎?"
pleaseDonate: "Misskey 是由 {host} 使用的免費軟體。請贊助我們,讓開發得以持續!" pleaseDonate: "Misskey 是由 {host} 使用的免費軟體。請贊助我們,讓開發得以持續!"
correspondingSourceIsAvailable: "對應的原始碼可以在 {anchor} 處找到。"
roles: "角色" roles: "角色"
role: "角色" role: "角色"
noRole: "沒有角色" noRole: "沒有角色"
@@ -1160,7 +1159,6 @@ showRenotes: "顯示其他人的轉發貼文"
edited: "已編輯" edited: "已編輯"
notificationRecieveConfig: "接受通知的設定" notificationRecieveConfig: "接受通知的設定"
mutualFollow: "互相追隨" mutualFollow: "互相追隨"
followingOrFollower: "追隨中或追隨者"
fileAttachedOnly: "顯示包含附件的貼文" fileAttachedOnly: "顯示包含附件的貼文"
showRepliesToOthersInTimeline: "顯示給其他人的回覆" showRepliesToOthersInTimeline: "顯示給其他人的回覆"
hideRepliesToOthersInTimeline: "在時間軸上隱藏給其他人的回覆" hideRepliesToOthersInTimeline: "在時間軸上隱藏給其他人的回覆"
@@ -1170,12 +1168,6 @@ confirmShowRepliesAll: "進行此操作後無法復原。您真的希望時間
confirmHideRepliesAll: "進行此操作後無法復原。您真的希望時間軸「不包含」您目前追隨的所有人的回覆嗎?" confirmHideRepliesAll: "進行此操作後無法復原。您真的希望時間軸「不包含」您目前追隨的所有人的回覆嗎?"
externalServices: "外部服務" externalServices: "外部服務"
sourceCode: "原始碼" sourceCode: "原始碼"
sourceCodeIsNotYetProvided: "尚未提供原始碼,請洽詢管理員解決這個問題。"
repositoryUrl: "儲存庫 URL"
repositoryUrlDescription: "如果存在可公開取得原始碼的儲存庫,請輸入其 URL。 如果您按原樣使用 Misskey不對原始碼進行任何更改請輸入 https://github.com/misskey-dev/misskey。"
repositoryUrlOrTarballRequired: "如果儲存庫不是公開的,則必須提供 tarball。 詳細資訊請參閱 .config/example.yml。"
feedback: "意見回饋"
feedbackUrl: "意見回饋 URL"
impressum: "營運者資訊" impressum: "營運者資訊"
impressumUrl: "營運者資訊網址" impressumUrl: "營運者資訊網址"
impressumDescription: "在德國與部份地區必須要明確顯示營運者資訊。" impressumDescription: "在德國與部份地區必須要明確顯示營運者資訊。"
@@ -1211,8 +1203,6 @@ soundWillBePlayed: "將播放音效"
showReplay: "觀看重播" showReplay: "觀看重播"
replay: "重播" replay: "重播"
replaying: "重播中" replaying: "重播中"
endReplay: "退出重播"
copyReplayData: "複製重播資料"
ranking: "排行榜" ranking: "排行榜"
lastNDays: "過去 {n} 天" lastNDays: "過去 {n} 天"
backToTitle: "回到遊戲標題頁" backToTitle: "回到遊戲標題頁"
@@ -1220,20 +1210,8 @@ hemisphere: "您居住的地區"
withSensitive: "顯示包含敏感檔案的貼文" withSensitive: "顯示包含敏感檔案的貼文"
userSaysSomethingSensitive: "包含 {name} 敏感檔案的貼文" userSaysSomethingSensitive: "包含 {name} 敏感檔案的貼文"
enableHorizontalSwipe: "滑動切換時間軸" enableHorizontalSwipe: "滑動切換時間軸"
loading: "載入中"
surrender: "退出"
gameRetry: "再試一次"
_bubbleGame: _bubbleGame:
howToPlay: "玩法說明" howToPlay: "玩法說明"
hold: "保留"
_score:
score: "分數"
scoreYen: "賺取的金額"
highScore: "最高分"
maxChain: "最大結合數"
yen: "{yen} 日圓"
estimatedQty: "{qty}個"
scoreSweets: "飯糰 {onigiriQtyWithUnit}"
_howToPlay: _howToPlay:
section1: "調整位置並將物體放入盒子中。" section1: "調整位置並將物體放入盒子中。"
section2: "當相同類型的物體黏在一起時,它們會變成不同的物體,您就會得到分數。" section2: "當相同類型的物體黏在一起時,它們會變成不同的物體,您就會得到分數。"
@@ -1655,7 +1633,6 @@ _role:
gtlAvailable: "瀏覽全域時間軸" gtlAvailable: "瀏覽全域時間軸"
ltlAvailable: "瀏覽本地時間軸" ltlAvailable: "瀏覽本地時間軸"
canPublicNote: "允許公開貼文" canPublicNote: "允許公開貼文"
mentionMax: "貼文內的最大提及數"
canInvite: "發行伺服器邀請碼" canInvite: "發行伺服器邀請碼"
inviteLimit: "可建立邀請碼的數量" inviteLimit: "可建立邀請碼的數量"
inviteLimitCycle: "邀請碼的發放間隔" inviteLimitCycle: "邀請碼的發放間隔"
@@ -1679,7 +1656,6 @@ _role:
canUseTranslator: "使用翻譯功能" canUseTranslator: "使用翻譯功能"
avatarDecorationLimit: "頭像裝飾的最大設置量" avatarDecorationLimit: "頭像裝飾的最大設置量"
_condition: _condition:
roleAssignedTo: "手動指派角色完成"
isLocal: "本地使用者" isLocal: "本地使用者"
isRemote: "遠端使用者" isRemote: "遠端使用者"
createdLessThan: "帳戶加入時間不超過" createdLessThan: "帳戶加入時間不超過"
@@ -1780,8 +1756,6 @@ _aboutMisskey:
contributors: "主要貢獻者" contributors: "主要貢獻者"
allContributors: "全體貢獻人員" allContributors: "全體貢獻人員"
source: "原始碼" source: "原始碼"
original: "原始"
thisIsModifiedVersion: "{name} 使用原始 Misskey 的修改版本。"
translation: "翻譯 Misskey" translation: "翻譯 Misskey"
donate: "贊助 Misskey" donate: "贊助 Misskey"
morePatrons: "還有許許多多幫助我們的其他人,非常感謝你們。 🥰" morePatrons: "還有許許多多幫助我們的其他人,非常感謝你們。 🥰"
@@ -2300,7 +2274,6 @@ _notification:
reactedBySomeUsers: "{n}人做出了反應" reactedBySomeUsers: "{n}人做出了反應"
renotedBySomeUsers: "{n}人做了轉發" renotedBySomeUsers: "{n}人做了轉發"
followedBySomeUsers: "被{n}人追隨了" followedBySomeUsers: "被{n}人追隨了"
flushNotification: "重置通知歷史紀錄"
_types: _types:
all: "全部 " all: "全部 "
note: "使用者的最新貼文" note: "使用者的最新貼文"
@@ -2386,7 +2359,7 @@ _moderationLogTypes:
updateCustomEmoji: "更新自訂表情符號" updateCustomEmoji: "更新自訂表情符號"
deleteCustomEmoji: "刪除自訂表情符號" deleteCustomEmoji: "刪除自訂表情符號"
updateServerSettings: "更新伺服器設定" updateServerSettings: "更新伺服器設定"
updateUserNote: "更新了使用者的管理筆記" updateUserNote: "更新管理筆記"
deleteDriveFile: "刪除檔案" deleteDriveFile: "刪除檔案"
deleteNote: "刪除貼文" deleteNote: "刪除貼文"
createGlobalAnnouncement: "建立全網通知" createGlobalAnnouncement: "建立全網通知"
@@ -2398,7 +2371,6 @@ _moderationLogTypes:
resetPassword: "重設密碼" resetPassword: "重設密碼"
suspendRemoteInstance: "封鎖遠端伺服器" suspendRemoteInstance: "封鎖遠端伺服器"
unsuspendRemoteInstance: "解除封鎖遠端伺服器" unsuspendRemoteInstance: "解除封鎖遠端伺服器"
updateRemoteInstanceNote: "更新了遠端伺服器的管理筆記"
markSensitiveDriveFile: "標記為敏感檔案" markSensitiveDriveFile: "標記為敏感檔案"
unmarkSensitiveDriveFile: "撤銷標記為敏感檔案" unmarkSensitiveDriveFile: "撤銷標記為敏感檔案"
resolveAbuseReport: "解決檢舉" resolveAbuseReport: "解決檢舉"
@@ -2519,8 +2491,6 @@ _reversi:
opponentHasSettingsChanged: "對手更改了設定" opponentHasSettingsChanged: "對手更改了設定"
allowIrregularRules: "允許異常規則(完全自由)" allowIrregularRules: "允許異常規則(完全自由)"
disallowIrregularRules: "不允許異常規則" disallowIrregularRules: "不允許異常規則"
showBoardLabels: "在棋盤上顯示行、列號"
useAvatarAsStone: "用大頭貼當作棋子"
_offlineScreen: _offlineScreen:
title: "離線-無法連接伺服器" title: "離線-無法連接伺服器"
header: "無法連接伺服器" header: "無法連接伺服器"

View File

@@ -1,12 +1,12 @@
{ {
"name": "misskey", "name": "misskey",
"version": "2024.5.0-beta.1", "version": "2024.2.0",
"codename": "nasubi", "codename": "nasubi",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/misskey-dev/misskey.git" "url": "https://github.com/misskey-dev/misskey.git"
}, },
"packageManager": "pnpm@9.0.6", "packageManager": "pnpm@8.15.1",
"workspaces": [ "workspaces": [
"packages/frontend", "packages/frontend",
"packages/backend", "packages/backend",
@@ -48,25 +48,22 @@
"lodash": "4.17.21" "lodash": "4.17.21"
}, },
"dependencies": { "dependencies": {
"cssnano": "6.1.2", "cssnano": "6.0.3",
"execa": "8.0.1", "execa": "8.0.1",
"fast-glob": "3.3.2", "fast-glob": "3.3.2",
"ignore-walk": "6.0.4", "ignore-walk": "6.0.4",
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
"postcss": "8.4.38", "postcss": "8.4.33",
"tar": "6.2.1", "tar": "6.2.0",
"terser": "5.30.3", "terser": "5.27.0",
"typescript": "5.4.5", "typescript": "5.3.3"
"esbuild": "0.20.2",
"glob": "10.3.12"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "20.12.7", "@typescript-eslint/eslint-plugin": "6.18.1",
"@typescript-eslint/eslint-plugin": "7.7.1", "@typescript-eslint/parser": "6.18.1",
"@typescript-eslint/parser": "7.7.1",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"cypress": "13.7.3", "cypress": "13.6.3",
"eslint": "8.57.0", "eslint": "8.56.0",
"ncp": "2.0.0", "ncp": "2.0.0",
"start-server-and-test": "2.0.3" "start-server-and-test": "2.0.3"
}, },

View File

@@ -19,6 +19,5 @@
}, },
"target": "es2022" "target": "es2022"
}, },
"minify": false, "minify": false
"sourceMaps": "inline"
} }

View File

@@ -19,6 +19,6 @@
</head> </head>
<body> <body>
<redoc spec-url="/api.json" expand-responses="200" expand-single-schema-field="true"></redoc> <redoc spec-url="/api.json" expand-responses="200" expand-single-schema-field="true"></redoc>
<script src="https://cdn.redoc.ly/redoc/v2.1.3/bundles/redoc.standalone.js" integrity="sha256-u4DgqzYXoArvNF/Ymw3puKexfOC6lYfw0sfmeliBJ1I=" crossorigin="anonymous"></script> <script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script>
</body> </body>
</html> </html>

View File

@@ -4,7 +4,7 @@
*/ */
import Redis from 'ioredis'; import Redis from 'ioredis';
import { loadConfig } from '../built/config.js'; import { loadConfig } from './built/config.js';
const config = loadConfig(); const config = loadConfig();
const redis = new Redis(config.redis); const redis = new Redis(config.redis);

View File

@@ -0,0 +1,8 @@
import { loadConfig } from './built/config.js'
import { genOpenapiSpec } from './built/server/api/openapi/gen-spec.js'
import { writeFileSync } from "node:fs";
const config = loadConfig();
const spec = genOpenapiSpec(config, true);
writeFileSync('./built/api.json', JSON.stringify(spec), 'utf-8');

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class UserBlacklistAnntena1689325027964 { export class UserBlacklistAnntena1689325027964 {
name = 'UserBlacklistAnntena1689325027964' name = 'UserBlacklistAnntena1689325027964'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class FixRenoteMuting1690417561185 { export class FixRenoteMuting1690417561185 {
name = 'FixRenoteMuting1690417561185' name = 'FixRenoteMuting1690417561185'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class ChangeCacheRemoteFilesDefault1690417561186 { export class ChangeCacheRemoteFilesDefault1690417561186 {
name = 'ChangeCacheRemoteFilesDefault1690417561186' name = 'ChangeCacheRemoteFilesDefault1690417561186'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class Fix1690417561187 { export class Fix1690417561187 {
name = 'Fix1690417561187' name = 'Fix1690417561187'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class User2faBackupCodes1690569881926 { export class User2faBackupCodes1690569881926 {
name = 'User2faBackupCodes1690569881926' name = 'User2faBackupCodes1690569881926'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class RefineAnnouncement1691649257651 { export class RefineAnnouncement1691649257651 {
name = 'RefineAnnouncement1691649257651' name = 'RefineAnnouncement1691649257651'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class RefineAnnouncement21691657412740 { export class RefineAnnouncement21691657412740 {
name = 'RefineAnnouncement21691657412740' name = 'RefineAnnouncement21691657412740'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class VerifiedLinks1695260774117 { export class VerifiedLinks1695260774117 {
name = 'VerifiedLinks1695260774117' name = 'VerifiedLinks1695260774117'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class FollowingNotify1695288787870 { export class FollowingNotify1695288787870 {
name = 'FollowingNotify1695288787870' name = 'FollowingNotify1695288787870'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class ShortName1695440131671 { export class ShortName1695440131671 {
name = 'ShortName1695440131671' name = 'ShortName1695440131671'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class MutingNotificationTypes1695605508898 { export class MutingNotificationTypes1695605508898 {
name = 'MutingNotificationTypes1695605508898' name = 'MutingNotificationTypes1695605508898'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class NoteUpdatedAt1695901659683 { export class NoteUpdatedAt1695901659683 {
name = 'NoteUpdatedAt1695901659683' name = 'NoteUpdatedAt1695901659683'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class UserListMembership1696323464251 { export class UserListMembership1696323464251 {
name = 'UserListMembership1696323464251' name = 'UserListMembership1696323464251'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class Hibernation1696331570827 { export class Hibernation1696331570827 {
name = 'Hibernation1696331570827' name = 'Hibernation1696331570827'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class Clean1696332072038 { export class Clean1696332072038 {
name = 'Clean1696332072038' name = 'Clean1696332072038'

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class HardMute1700383825690 { export class HardMute1700383825690 {
name = 'HardMute1700383825690' name = 'HardMute1700383825690'

View File

@@ -1,16 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class RepositoryUrlFromSyuiloToMisskeyDev1708266695091 {
name = 'RepositoryUrlFromSyuiloToMisskeyDev1708266695091'
async up(queryRunner) {
await queryRunner.query(`UPDATE "meta" SET "repositoryUrl" = 'https://github.com/misskey-dev/misskey' WHERE "repositoryUrl" = 'https://github.com/syuilo/misskey'`);
}
async down(queryRunner) {
// no valid down migration
}
}

View File

@@ -1,16 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class PerInstanceModNote1708399372194 {
name = 'PerInstanceModNote1708399372194'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "instance" ADD "moderationNote" character varying(16384) NOT NULL DEFAULT ''`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "moderationNote"`);
}
}

View File

@@ -1,42 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class UrlPreviewMeta1710512074000 {
name = 'UrlPreviewMeta1710512074000'
async up(queryRunner) {
await queryRunner.query(`
alter table meta
rename column "summalyProxy" to "urlPreviewSummaryProxyUrl";
alter table meta
add "urlPreviewEnabled" boolean default true not null;
alter table meta
add "urlPreviewTimeout" integer default 10000 not null;
alter table meta
add "urlPreviewMaximumContentLength" bigint default 10485760 not null;
alter table meta
add "urlPreviewRequireContentLength" boolean default false not null;
alter table meta
add "urlPreviewUserAgent" varchar(1024) default null;
`);
}
async down(queryRunner) {
await queryRunner.query(`
alter table meta
rename column "urlPreviewSummaryProxyUrl" to "summalyProxy";
alter table meta
drop column "urlPreviewEnabled";
alter table meta
drop column "urlPreviewTimeout";
alter table meta
drop column "urlPreviewMaximumContentLength";
alter table meta
drop column "urlPreviewRequireContentLength";
alter table meta
drop column "urlPreviewUserAgent";
`);
}
}

View File

@@ -1,16 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class AntennaExcludeBots1710919614510 {
name = 'AntennaExcludeBots1710919614510'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "antenna" ADD "excludeBots" boolean NOT NULL DEFAULT false`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "excludeBots"`);
}
}

View File

@@ -11,15 +11,15 @@
"start:test": "cross-env NODE_ENV=test node ./built/boot/entry.js", "start:test": "cross-env NODE_ENV=test node ./built/boot/entry.js",
"migrate": "pnpm typeorm migration:run -d ormconfig.js", "migrate": "pnpm typeorm migration:run -d ormconfig.js",
"revert": "pnpm typeorm migration:revert -d ormconfig.js", "revert": "pnpm typeorm migration:revert -d ormconfig.js",
"check:connect": "node ./scripts/check_connect.js", "check:connect": "node ./check_connect.js",
"build": "swc src -d built -D --strip-leading-paths", "build": "swc src -d built -D",
"build:test": "swc test-server -d built-test -D --config-file test-server/.swcrc --strip-leading-paths", "build:test": "swc test-server -d built-test -D --config-file test-server/.swcrc",
"watch:swc": "swc src -d built -D -w --strip-leading-paths", "watch:swc": "swc src -d built -D -w",
"build:tsc": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json", "build:tsc": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
"watch": "node ./scripts/watch.mjs", "watch": "node watch.mjs",
"restart": "pnpm build && pnpm start", "restart": "pnpm build && pnpm start",
"dev": "node ./scripts/dev.mjs", "dev": "nodemon -w src -e ts,js,mjs,cjs,json --exec \"cross-env NODE_ENV=development pnpm run restart\"",
"typecheck": "tsc --noEmit && tsc -p test --noEmit", "typecheck": "tsc --noEmit",
"eslint": "eslint --quiet \"src/**/*.ts\"", "eslint": "eslint --quiet \"src/**/*.ts\"",
"lint": "pnpm typecheck && pnpm eslint", "lint": "pnpm typecheck && pnpm eslint",
"jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --config jest.config.unit.cjs", "jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --config jest.config.unit.cjs",
@@ -31,7 +31,7 @@
"test:e2e": "pnpm build && pnpm build:test && pnpm jest:e2e", "test:e2e": "pnpm build && pnpm build:test && pnpm jest:e2e",
"test-and-coverage": "pnpm jest-and-coverage", "test-and-coverage": "pnpm jest-and-coverage",
"test-and-coverage:e2e": "pnpm build && pnpm build:test && pnpm jest-and-coverage:e2e", "test-and-coverage:e2e": "pnpm build && pnpm build:test && pnpm jest-and-coverage:e2e",
"generate-api-json": "pnpm build && node ./scripts/generate_api_json.js" "generate-api-json": "pnpm build && node ./generate_api_json.js"
}, },
"optionalDependencies": { "optionalDependencies": {
"@swc/core-android-arm64": "1.3.11", "@swc/core-android-arm64": "1.3.11",
@@ -67,39 +67,38 @@
"dependencies": { "dependencies": {
"@aws-sdk/client-s3": "3.412.0", "@aws-sdk/client-s3": "3.412.0",
"@aws-sdk/lib-storage": "3.412.0", "@aws-sdk/lib-storage": "3.412.0",
"@bull-board/api": "5.17.0", "@bull-board/api": "5.14.0",
"@bull-board/fastify": "5.17.0", "@bull-board/fastify": "5.14.0",
"@bull-board/ui": "5.17.0", "@bull-board/ui": "5.14.0",
"@discordapp/twemoji": "15.0.3", "@discordapp/twemoji": "15.0.2",
"@fastify/accepts": "4.3.0", "@fastify/accepts": "4.3.0",
"@fastify/cookie": "9.3.1", "@fastify/cookie": "9.3.1",
"@fastify/cors": "9.0.1", "@fastify/cors": "8.5.0",
"@fastify/express": "3.0.0", "@fastify/express": "2.3.0",
"@fastify/http-proxy": "9.5.0", "@fastify/http-proxy": "9.3.0",
"@fastify/multipart": "8.2.0", "@fastify/multipart": "8.1.0",
"@fastify/static": "7.0.3", "@fastify/static": "6.12.0",
"@fastify/view": "9.1.0", "@fastify/view": "8.2.0",
"@misskey-dev/sharp-read-bmp": "1.2.0", "@misskey-dev/sharp-read-bmp": "^1.1.1",
"@misskey-dev/summaly": "5.1.0", "@misskey-dev/summaly": "^5.0.3",
"@napi-rs/canvas": "^0.1.52", "@nestjs/common": "10.2.10",
"@nestjs/common": "10.3.8", "@nestjs/core": "10.2.10",
"@nestjs/core": "10.3.8", "@nestjs/testing": "10.2.10",
"@nestjs/testing": "10.3.8",
"@peertube/http-signature": "1.7.0", "@peertube/http-signature": "1.7.0",
"@simplewebauthn/server": "10.0.0", "@simplewebauthn/server": "9.0.2",
"@sinonjs/fake-timers": "11.2.2", "@sinonjs/fake-timers": "11.2.2",
"@smithy/node-http-handler": "2.5.0", "@smithy/node-http-handler": "2.1.10",
"@swc/cli": "0.3.12", "@swc/cli": "0.1.63",
"@swc/core": "1.4.17", "@swc/core": "1.3.107",
"@twemoji/parser": "15.1.1", "@twemoji/parser": "15.0.0",
"accepts": "1.3.8", "accepts": "1.3.8",
"ajv": "8.13.0", "ajv": "8.12.0",
"archiver": "7.0.1", "archiver": "6.0.1",
"async-mutex": "0.5.0", "async-mutex": "0.4.1",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"blurhash": "2.0.5", "blurhash": "2.0.5",
"body-parser": "1.20.2", "body-parser": "1.20.2",
"bullmq": "5.7.8", "bullmq": "5.1.9",
"cacheable-lookup": "7.0.0", "cacheable-lookup": "7.0.0",
"cbor": "9.0.2", "cbor": "9.0.2",
"chalk": "5.3.0", "chalk": "5.3.0",
@@ -110,84 +109,84 @@
"content-disposition": "0.5.4", "content-disposition": "0.5.4",
"date-fns": "2.30.0", "date-fns": "2.30.0",
"deep-email-validator": "0.1.21", "deep-email-validator": "0.1.21",
"fastify": "4.26.2", "fastify": "4.25.2",
"fastify-raw-body": "4.3.0", "fastify-raw-body": "4.3.0",
"feed": "4.2.2", "feed": "4.2.2",
"file-type": "19.0.0", "file-type": "19.0.0",
"fluent-ffmpeg": "2.1.2", "fluent-ffmpeg": "2.1.2",
"form-data": "4.0.0", "form-data": "4.0.0",
"got": "14.2.1", "got": "14.1.0",
"happy-dom": "14.7.1", "happy-dom": "10.0.3",
"hpagent": "1.2.0", "hpagent": "1.2.0",
"htmlescape": "1.1.1", "http-link-header": "1.1.1",
"http-link-header": "1.1.3", "ioredis": "5.3.2",
"ioredis": "5.4.1",
"ip-cidr": "3.1.0", "ip-cidr": "3.1.0",
"ipaddr.js": "2.2.0", "ipaddr.js": "2.1.0",
"is-svg": "5.0.0", "is-svg": "5.0.0",
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
"jsdom": "24.0.0", "jsdom": "23.2.0",
"json5": "2.2.3", "json5": "2.2.3",
"jsonld": "8.3.2", "jsonld": "8.3.2",
"jsrsasign": "11.1.0", "jsrsasign": "11.0.0",
"meilisearch": "0.38.0", "meilisearch": "0.37.0",
"mfm-js": "0.24.0", "mfm-js": "0.24.0",
"microformats-parser": "2.0.2", "microformats-parser": "2.0.2",
"mime-types": "2.1.35", "mime-types": "2.1.35",
"misskey-js": "workspace:*", "misskey-js": "workspace:*",
"misskey-reversi": "workspace:*", "misskey-reversi": "workspace:*",
"ms": "3.0.0-canary.1", "ms": "3.0.0-canary.1",
"nanoid": "5.0.7", "nanoid": "5.0.4",
"nested-property": "4.0.0", "nested-property": "4.0.0",
"node-fetch": "3.3.2", "node-fetch": "3.3.2",
"nodemailer": "6.9.13", "nodemailer": "6.9.8",
"nsfwjs": "2.4.2", "nsfwjs": "2.4.2",
"oauth": "0.10.0", "oauth": "0.10.0",
"oauth2orize": "1.12.0", "oauth2orize": "1.12.0",
"oauth2orize-pkce": "0.1.2", "oauth2orize-pkce": "0.1.2",
"os-utils": "0.0.14", "os-utils": "0.0.14",
"otpauth": "9.2.3", "otpauth": "9.2.2",
"parse5": "7.1.2", "parse5": "7.1.2",
"pg": "8.11.5", "pg": "8.11.3",
"pkce-challenge": "4.1.0", "pkce-challenge": "4.1.0",
"probe-image-size": "7.2.3", "probe-image-size": "7.2.3",
"promise-limit": "2.7.0", "promise-limit": "2.7.0",
"pug": "3.0.2", "pug": "3.0.2",
"punycode": "2.3.1", "punycode": "2.3.1",
"pureimage": "0.3.17",
"qrcode": "1.5.3", "qrcode": "1.5.3",
"random-seed": "0.3.0", "random-seed": "0.3.0",
"ratelimiter": "3.4.1", "ratelimiter": "3.4.1",
"re2": "1.20.10", "re2": "1.20.9",
"redis-lock": "0.1.4", "redis-lock": "0.1.4",
"reflect-metadata": "0.2.2", "reflect-metadata": "0.1.14",
"rename": "1.0.4", "rename": "1.0.4",
"rss-parser": "3.13.0", "rss-parser": "3.13.0",
"rxjs": "7.8.1", "rxjs": "7.8.1",
"sanitize-html": "2.13.0", "sanitize-html": "2.11.0",
"secure-json-parse": "2.7.0", "secure-json-parse": "2.7.0",
"sharp": "0.33.3", "sharp": "0.32.6",
"slacc": "0.0.10", "slacc": "0.0.10",
"strict-event-emitter-types": "2.0.0", "strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0", "stringz": "2.1.0",
"systeminformation": "5.22.7", "systeminformation": "5.21.24",
"tinycolor2": "1.6.0", "tinycolor2": "1.6.0",
"tmp": "0.2.3", "tmp": "0.2.1",
"tsc-alias": "1.8.8", "tsc-alias": "1.8.8",
"tsconfig-paths": "4.2.0", "tsconfig-paths": "4.2.0",
"typeorm": "0.3.20", "typeorm": "0.3.20",
"typescript": "5.4.5", "typescript": "5.3.3",
"ulid": "2.3.0", "ulid": "2.3.0",
"vary": "1.1.2", "vary": "1.1.2",
"web-push": "3.6.7", "web-push": "3.6.7",
"ws": "8.17.0", "ws": "8.16.0",
"xev": "3.0.2" "xev": "3.0.2"
}, },
"devDependencies": { "devDependencies": {
"@jest/globals": "29.7.0", "@jest/globals": "29.7.0",
"@misskey-dev/eslint-plugin": "1.0.0", "@misskey-dev/eslint-plugin": "1.0.0",
"@nestjs/platform-express": "10.3.8", "@nestjs/platform-express": "10.3.1",
"@simplewebauthn/types": "10.0.0", "@simplewebauthn/types": "9.0.1",
"@swc/jest": "0.2.36", "@swc/jest": "0.2.31",
"@types/accepts": "1.3.7", "@types/accepts": "1.3.7",
"@types/archiver": "6.0.2", "@types/archiver": "6.0.2",
"@types/bcryptjs": "2.4.6", "@types/bcryptjs": "2.4.6",
@@ -195,30 +194,29 @@
"@types/color-convert": "2.0.3", "@types/color-convert": "2.0.3",
"@types/content-disposition": "0.5.8", "@types/content-disposition": "0.5.8",
"@types/fluent-ffmpeg": "2.1.24", "@types/fluent-ffmpeg": "2.1.24",
"@types/htmlescape": "^1.1.3",
"@types/http-link-header": "1.0.5", "@types/http-link-header": "1.0.5",
"@types/jest": "29.5.12", "@types/jest": "29.5.11",
"@types/js-yaml": "4.0.9", "@types/js-yaml": "4.0.9",
"@types/jsdom": "21.1.6", "@types/jsdom": "21.1.6",
"@types/jsonld": "1.5.13", "@types/jsonld": "1.5.13",
"@types/jsrsasign": "10.5.14", "@types/jsrsasign": "10.5.12",
"@types/mime-types": "2.1.4", "@types/mime-types": "2.1.4",
"@types/ms": "0.7.34", "@types/ms": "0.7.34",
"@types/node": "20.12.7", "@types/node": "20.11.17",
"@types/node-fetch": "3.0.3", "@types/node-fetch": "3.0.3",
"@types/nodemailer": "6.4.15", "@types/nodemailer": "6.4.14",
"@types/oauth": "0.9.4", "@types/oauth": "0.9.4",
"@types/oauth2orize": "1.11.5", "@types/oauth2orize": "1.11.3",
"@types/oauth2orize-pkce": "0.1.2", "@types/oauth2orize-pkce": "0.1.2",
"@types/pg": "8.11.5", "@types/pg": "8.11.0",
"@types/pug": "2.0.10", "@types/pug": "2.0.10",
"@types/punycode": "2.1.4", "@types/punycode": "2.1.3",
"@types/qrcode": "1.5.5", "@types/qrcode": "1.5.5",
"@types/random-seed": "0.3.5", "@types/random-seed": "0.3.5",
"@types/ratelimiter": "3.4.6", "@types/ratelimiter": "3.4.6",
"@types/rename": "1.0.7", "@types/rename": "1.0.7",
"@types/sanitize-html": "2.11.0", "@types/sanitize-html": "2.9.5",
"@types/semver": "7.5.8", "@types/semver": "7.5.6",
"@types/simple-oauth2": "5.0.7", "@types/simple-oauth2": "5.0.7",
"@types/sinonjs__fake-timers": "8.1.5", "@types/sinonjs__fake-timers": "8.1.5",
"@types/tinycolor2": "1.4.6", "@types/tinycolor2": "1.4.6",
@@ -226,17 +224,17 @@
"@types/vary": "1.1.3", "@types/vary": "1.1.3",
"@types/web-push": "3.6.3", "@types/web-push": "3.6.3",
"@types/ws": "8.5.10", "@types/ws": "8.5.10",
"@typescript-eslint/eslint-plugin": "7.7.1", "@typescript-eslint/eslint-plugin": "6.18.1",
"@typescript-eslint/parser": "7.7.1", "@typescript-eslint/parser": "6.18.1",
"aws-sdk-client-mock": "3.0.1", "aws-sdk-client-mock": "3.0.1",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"eslint": "8.57.0", "eslint": "8.56.0",
"eslint-plugin-import": "2.29.1", "eslint-plugin-import": "2.29.1",
"execa": "8.0.1", "execa": "8.0.1",
"fkill": "^9.0.0", "fkill": "^9.0.0",
"jest": "29.7.0", "jest": "29.7.0",
"jest-mock": "29.7.0", "jest-mock": "29.7.0",
"nodemon": "3.1.0", "nodemon": "3.0.3",
"pid-port": "1.0.0", "pid-port": "1.0.0",
"simple-oauth2": "5.0.0" "simple-oauth2": "5.0.0"
} }

View File

@@ -1,61 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { execa, execaNode } from 'execa';
/** @type {import('execa').ExecaChildProcess | undefined} */
let backendProcess;
async function execBuildAssets() {
await execa('pnpm', ['run', 'build-assets'], {
cwd: '../../',
stdout: process.stdout,
stderr: process.stderr,
})
}
function execStart() {
// pnpm run start を呼び出したいが、windowsだとプロセスグループ単位でのkillが出来ずゾンビプロセス化するので
// 上記と同等の動きをするコマンドで子・孫プロセスを作らないようにしたい
backendProcess = execaNode('./built/boot/entry.js', [], {
stdout: process.stdout,
stderr: process.stderr,
env: {
'NODE_ENV': 'development',
},
});
}
async function killProc() {
if (backendProcess) {
backendProcess.kill();
await new Promise(resolve => backendProcess.on('exit', resolve));
backendProcess = undefined;
}
}
(async () => {
execaNode(
'./node_modules/nodemon/bin/nodemon.js',
[
'-w', 'src',
'-e', 'ts,js,mjs,cjs,json',
'--exec', 'pnpm', 'run', 'build',
],
{
stdio: [process.stdin, process.stdout, process.stderr, 'ipc'],
})
.on('message', async (message) => {
if (message.type === 'exit') {
// かならずbuild->build-assetsの順番で呼び出したいので、
// 少々トリッキーだがnodemonからのexitイベントを利用してbuild-assets->startを行う。
// pnpm restartをbuildが終わる前にbuild-assetsが動いてしまうので、バラバラに呼び出す必要がある
await killProc();
await execBuildAssets();
execStart();
}
})
})();

View File

@@ -1,13 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { loadConfig } from '../built/config.js'
import { genOpenapiSpec } from '../built/server/api/openapi/gen-spec.js'
import { writeFileSync } from "node:fs";
const config = loadConfig();
const spec = genOpenapiSpec(config, true);
writeFileSync('./built/api.json', JSON.stringify(spec), 'utf-8');

View File

@@ -20,6 +20,7 @@ import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js';
import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js'; import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { CacheService } from '@/core/CacheService.js';
import { ProxyAccountService } from '@/core/ProxyAccountService.js'; import { ProxyAccountService } from '@/core/ProxyAccountService.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
@@ -59,6 +60,7 @@ export class AccountMoveService {
private instanceChart: InstanceChart, private instanceChart: InstanceChart,
private metaService: MetaService, private metaService: MetaService,
private relayService: RelayService, private relayService: RelayService,
private cacheService: CacheService,
private queueService: QueueService, private queueService: QueueService,
) { ) {
} }
@@ -82,7 +84,7 @@ export class AccountMoveService {
Object.assign(src, update); Object.assign(src, update);
// Update cache // Update cache
this.globalEventService.publishInternalEvent('localUserUpdated', src); this.cacheService.uriPersonCache.set(srcUri, src);
const srcPerson = await this.apRendererService.renderPerson(src); const srcPerson = await this.apRendererService.renderPerson(src);
const updateAct = this.apRendererService.addContext(this.apRendererService.renderUpdate(srcPerson, src)); const updateAct = this.apRendererService.addContext(this.apRendererService.renderUpdate(srcPerson, src));
@@ -305,7 +307,7 @@ export class AccountMoveService {
let resultUser: MiLocalUser | MiRemoteUser | null = null; let resultUser: MiLocalUser | MiRemoteUser | null = null;
if (this.userEntityService.isRemoteUser(dst)) { if (this.userEntityService.isRemoteUser(dst)) {
if (Date.now() - (dst.lastFetchedAt?.getTime() ?? 0) > 10 * 1000) { if ((new Date()).getTime() - (dst.lastFetchedAt?.getTime() ?? 0) > 10 * 1000) {
await this.apPersonService.updatePerson(dst.uri); await this.apPersonService.updatePerson(dst.uri);
} }
dst = await this.apPersonService.fetchPerson(dst.uri) ?? dst; dst = await this.apPersonService.fetchPerson(dst.uri) ?? dst;
@@ -321,7 +323,7 @@ export class AccountMoveService {
if (!src) continue; // oldAccountを探してもこのサーバーに存在しない場合はフォロー関係もないということなのでスルー if (!src) continue; // oldAccountを探してもこのサーバーに存在しない場合はフォロー関係もないということなのでスルー
if (this.userEntityService.isRemoteUser(dst)) { if (this.userEntityService.isRemoteUser(dst)) {
if (Date.now() - (src.lastFetchedAt?.getTime() ?? 0) > 10 * 1000) { if ((new Date()).getTime() - (src.lastFetchedAt?.getTime() ?? 0) > 10 * 1000) {
await this.apPersonService.updatePerson(srcUri); await this.apPersonService.updatePerson(srcUri);
} }

View File

@@ -92,7 +92,7 @@ export class AntennaService implements OnApplicationShutdown {
} }
@bindThis @bindThis
public async addNoteToAntennas(note: MiNote, noteUser: { id: MiUser['id']; username: string; host: string | null; isBot: boolean; }): Promise<void> { public async addNoteToAntennas(note: MiNote, noteUser: { id: MiUser['id']; username: string; host: string | null; }): Promise<void> {
const antennas = await this.getAntennas(); const antennas = await this.getAntennas();
const antennasWithMatchResult = await Promise.all(antennas.map(antenna => this.checkHitAntenna(antenna, note, noteUser).then(hit => [antenna, hit] as const))); const antennasWithMatchResult = await Promise.all(antennas.map(antenna => this.checkHitAntenna(antenna, note, noteUser).then(hit => [antenna, hit] as const)));
const matchedAntennas = antennasWithMatchResult.filter(([, hit]) => hit).map(([antenna]) => antenna); const matchedAntennas = antennasWithMatchResult.filter(([, hit]) => hit).map(([antenna]) => antenna);
@@ -110,12 +110,10 @@ export class AntennaService implements OnApplicationShutdown {
// NOTE: フォローしているユーザーのノート、リストのユーザーのノート、グループのユーザーのノート指定はパフォーマンス上の理由で無効になっている // NOTE: フォローしているユーザーのノート、リストのユーザーのノート、グループのユーザーのノート指定はパフォーマンス上の理由で無効になっている
@bindThis @bindThis
public async checkHitAntenna(antenna: MiAntenna, note: (MiNote | Packed<'Note'>), noteUser: { id: MiUser['id']; username: string; host: string | null; isBot: boolean; }): Promise<boolean> { public async checkHitAntenna(antenna: MiAntenna, note: (MiNote | Packed<'Note'>), noteUser: { id: MiUser['id']; username: string; host: string | null; }): Promise<boolean> {
if (note.visibility === 'specified') return false; if (note.visibility === 'specified') return false;
if (note.visibility === 'followers') return false; if (note.visibility === 'followers') return false;
if (antenna.excludeBots && noteUser.isBot) return false;
if (antenna.localOnly && noteUser.host != null) return false; if (antenna.localOnly && noteUser.host != null) return false;
if (!antenna.withReplies && note.replyId != null) return false; if (!antenna.withReplies && note.replyId != null) return false;

View File

@@ -128,13 +128,10 @@ export class CacheService implements OnApplicationShutdown {
const { type, body } = obj.message as GlobalEvents['internal']['payload']; const { type, body } = obj.message as GlobalEvents['internal']['payload'];
switch (type) { switch (type) {
case 'userChangeSuspendedState': case 'userChangeSuspendedState':
case 'userChangeDeletedState': case 'remoteUserUpdated': {
case 'remoteUserUpdated':
case 'localUserUpdated': {
const user = await this.usersRepository.findOneBy({ id: body.id }); const user = await this.usersRepository.findOneBy({ id: body.id });
if (user == null) { if (user == null) {
this.userByIdCache.delete(body.id); this.userByIdCache.delete(body.id);
this.localUserByIdCache.delete(body.id);
for (const [k, v] of this.uriPersonCache.cache.entries()) { for (const [k, v] of this.uriPersonCache.cache.entries()) {
if (v.value?.id === body.id) { if (v.value?.id === body.id) {
this.uriPersonCache.delete(k); this.uriPersonCache.delete(k);

View File

@@ -1,8 +1,3 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable, OnModuleInit } from '@nestjs/common'; import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import Redis from 'ioredis'; import Redis from 'ioredis';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';

View File

@@ -116,7 +116,6 @@ import { FlashEntityService } from './entities/FlashEntityService.js';
import { FlashLikeEntityService } from './entities/FlashLikeEntityService.js'; import { FlashLikeEntityService } from './entities/FlashLikeEntityService.js';
import { RoleEntityService } from './entities/RoleEntityService.js'; import { RoleEntityService } from './entities/RoleEntityService.js';
import { ReversiGameEntityService } from './entities/ReversiGameEntityService.js'; import { ReversiGameEntityService } from './entities/ReversiGameEntityService.js';
import { MetaEntityService } from './entities/MetaEntityService.js';
import { ApAudienceService } from './activitypub/ApAudienceService.js'; import { ApAudienceService } from './activitypub/ApAudienceService.js';
import { ApDbResolverService } from './activitypub/ApDbResolverService.js'; import { ApDbResolverService } from './activitypub/ApDbResolverService.js';
@@ -127,7 +126,7 @@ import { ApMfmService } from './activitypub/ApMfmService.js';
import { ApRendererService } from './activitypub/ApRendererService.js'; import { ApRendererService } from './activitypub/ApRendererService.js';
import { ApRequestService } from './activitypub/ApRequestService.js'; import { ApRequestService } from './activitypub/ApRequestService.js';
import { ApResolverService } from './activitypub/ApResolverService.js'; import { ApResolverService } from './activitypub/ApResolverService.js';
import { JsonLdService } from './activitypub/JsonLdService.js'; import { LdSignatureService } from './activitypub/LdSignatureService.js';
import { RemoteLoggerService } from './RemoteLoggerService.js'; import { RemoteLoggerService } from './RemoteLoggerService.js';
import { RemoteUserResolveService } from './RemoteUserResolveService.js'; import { RemoteUserResolveService } from './RemoteUserResolveService.js';
import { WebfingerService } from './WebfingerService.js'; import { WebfingerService } from './WebfingerService.js';
@@ -255,7 +254,6 @@ const $FlashEntityService: Provider = { provide: 'FlashEntityService', useExisti
const $FlashLikeEntityService: Provider = { provide: 'FlashLikeEntityService', useExisting: FlashLikeEntityService }; const $FlashLikeEntityService: Provider = { provide: 'FlashLikeEntityService', useExisting: FlashLikeEntityService };
const $RoleEntityService: Provider = { provide: 'RoleEntityService', useExisting: RoleEntityService }; const $RoleEntityService: Provider = { provide: 'RoleEntityService', useExisting: RoleEntityService };
const $ReversiGameEntityService: Provider = { provide: 'ReversiGameEntityService', useExisting: ReversiGameEntityService }; const $ReversiGameEntityService: Provider = { provide: 'ReversiGameEntityService', useExisting: ReversiGameEntityService };
const $MetaEntityService: Provider = { provide: 'MetaEntityService', useExisting: MetaEntityService };
const $ApAudienceService: Provider = { provide: 'ApAudienceService', useExisting: ApAudienceService }; const $ApAudienceService: Provider = { provide: 'ApAudienceService', useExisting: ApAudienceService };
const $ApDbResolverService: Provider = { provide: 'ApDbResolverService', useExisting: ApDbResolverService }; const $ApDbResolverService: Provider = { provide: 'ApDbResolverService', useExisting: ApDbResolverService };
@@ -266,7 +264,7 @@ const $ApMfmService: Provider = { provide: 'ApMfmService', useExisting: ApMfmSer
const $ApRendererService: Provider = { provide: 'ApRendererService', useExisting: ApRendererService }; const $ApRendererService: Provider = { provide: 'ApRendererService', useExisting: ApRendererService };
const $ApRequestService: Provider = { provide: 'ApRequestService', useExisting: ApRequestService }; const $ApRequestService: Provider = { provide: 'ApRequestService', useExisting: ApRequestService };
const $ApResolverService: Provider = { provide: 'ApResolverService', useExisting: ApResolverService }; const $ApResolverService: Provider = { provide: 'ApResolverService', useExisting: ApResolverService };
const $JsonLdService: Provider = { provide: 'JsonLdService', useExisting: JsonLdService }; const $LdSignatureService: Provider = { provide: 'LdSignatureService', useExisting: LdSignatureService };
const $RemoteLoggerService: Provider = { provide: 'RemoteLoggerService', useExisting: RemoteLoggerService }; const $RemoteLoggerService: Provider = { provide: 'RemoteLoggerService', useExisting: RemoteLoggerService };
const $RemoteUserResolveService: Provider = { provide: 'RemoteUserResolveService', useExisting: RemoteUserResolveService }; const $RemoteUserResolveService: Provider = { provide: 'RemoteUserResolveService', useExisting: RemoteUserResolveService };
const $WebfingerService: Provider = { provide: 'WebfingerService', useExisting: WebfingerService }; const $WebfingerService: Provider = { provide: 'WebfingerService', useExisting: WebfingerService };
@@ -395,7 +393,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
FlashLikeEntityService, FlashLikeEntityService,
RoleEntityService, RoleEntityService,
ReversiGameEntityService, ReversiGameEntityService,
MetaEntityService,
ApAudienceService, ApAudienceService,
ApDbResolverService, ApDbResolverService,
@@ -406,7 +403,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ApRendererService, ApRendererService,
ApRequestService, ApRequestService,
ApResolverService, ApResolverService,
JsonLdService, LdSignatureService,
RemoteLoggerService, RemoteLoggerService,
RemoteUserResolveService, RemoteUserResolveService,
WebfingerService, WebfingerService,
@@ -531,7 +528,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$FlashLikeEntityService, $FlashLikeEntityService,
$RoleEntityService, $RoleEntityService,
$ReversiGameEntityService, $ReversiGameEntityService,
$MetaEntityService,
$ApAudienceService, $ApAudienceService,
$ApDbResolverService, $ApDbResolverService,
@@ -542,7 +538,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$ApRendererService, $ApRendererService,
$ApRequestService, $ApRequestService,
$ApResolverService, $ApResolverService,
$JsonLdService, $LdSignatureService,
$RemoteLoggerService, $RemoteLoggerService,
$RemoteUserResolveService, $RemoteUserResolveService,
$WebfingerService, $WebfingerService,
@@ -667,7 +663,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
FlashLikeEntityService, FlashLikeEntityService,
RoleEntityService, RoleEntityService,
ReversiGameEntityService, ReversiGameEntityService,
MetaEntityService,
ApAudienceService, ApAudienceService,
ApDbResolverService, ApDbResolverService,
@@ -678,7 +673,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ApRendererService, ApRendererService,
ApRequestService, ApRequestService,
ApResolverService, ApResolverService,
JsonLdService, LdSignatureService,
RemoteLoggerService, RemoteLoggerService,
RemoteUserResolveService, RemoteUserResolveService,
WebfingerService, WebfingerService,
@@ -802,7 +797,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$FlashLikeEntityService, $FlashLikeEntityService,
$RoleEntityService, $RoleEntityService,
$ReversiGameEntityService, $ReversiGameEntityService,
$MetaEntityService,
$ApAudienceService, $ApAudienceService,
$ApDbResolverService, $ApDbResolverService,
@@ -813,7 +807,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$ApRendererService, $ApRendererService,
$ApRequestService, $ApRequestService,
$ApResolverService, $ApResolverService,
$JsonLdService, $LdSignatureService,
$RemoteLoggerService, $RemoteLoggerService,
$RemoteUserResolveService, $RemoteUserResolveService,
$WebfingerService, $WebfingerService,

View File

@@ -20,7 +20,7 @@ import { query } from '@/misc/prelude/url.js';
import type { Serialized } from '@/types.js'; import type { Serialized } from '@/types.js';
import { ModerationLogService } from '@/core/ModerationLogService.js'; import { ModerationLogService } from '@/core/ModerationLogService.js';
const parseEmojiStrRegexp = /^([-\w]+)(?:@([\w.-]+))?$/; const parseEmojiStrRegexp = /^(\w+)(?:@([\w.-]+))?$/;
@Injectable() @Injectable()
export class CustomEmojiService implements OnApplicationShutdown { export class CustomEmojiService implements OnApplicationShutdown {
@@ -393,11 +393,6 @@ export class CustomEmojiService implements OnApplicationShutdown {
return this.emojisRepository.findOneBy({ id }); return this.emojisRepository.findOneBy({ id });
} }
@bindThis
public getEmojiByName(name: string): Promise<MiEmoji | null> {
return this.emojisRepository.findOneBy({ name, host: IsNull() });
}
@bindThis @bindThis
public dispose(): void { public dispose(): void {
this.cache.dispose(); this.cache.dispose();

View File

@@ -9,7 +9,6 @@ import { QueueService } from '@/core/QueueService.js';
import { UserSuspendService } from '@/core/UserSuspendService.js'; import { UserSuspendService } from '@/core/UserSuspendService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
@Injectable() @Injectable()
export class DeleteAccountService { export class DeleteAccountService {
@@ -19,7 +18,6 @@ export class DeleteAccountService {
private userSuspendService: UserSuspendService, private userSuspendService: UserSuspendService,
private queueService: QueueService, private queueService: QueueService,
private globalEventService: GlobalEventService,
) { ) {
} }
@@ -41,7 +39,5 @@ export class DeleteAccountService {
await this.usersRepository.update(user.id, { await this.usersRepository.update(user.id, {
isDeleted: true, isDeleted: true,
}); });
this.globalEventService.publishInternalEvent('userChangeDeletedState', { id: user.id, isDeleted: true });
} }
} }

View File

@@ -13,7 +13,7 @@ import type { NotesRepository } from '@/models/_.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { FanoutTimelineName, FanoutTimelineService } from '@/core/FanoutTimelineService.js'; import { FanoutTimelineName, FanoutTimelineService } from '@/core/FanoutTimelineService.js';
import { isUserRelated } from '@/misc/is-user-related.js'; import { isUserRelated } from '@/misc/is-user-related.js';
import { isQuote, isRenote } from '@/misc/is-renote.js'; import { isPureRenote } from '@/misc/is-pure-renote.js';
import { CacheService } from '@/core/CacheService.js'; import { CacheService } from '@/core/CacheService.js';
import { isReply } from '@/misc/is-reply.js'; import { isReply } from '@/misc/is-reply.js';
import { isInstanceMuted } from '@/misc/is-instance-muted.js'; import { isInstanceMuted } from '@/misc/is-instance-muted.js';
@@ -95,7 +95,7 @@ export class FanoutTimelineEndpointService {
if (ps.excludePureRenotes) { if (ps.excludePureRenotes) {
const parentFilter = filter; const parentFilter = filter;
filter = (note) => (!isRenote(note) || isQuote(note)) && parentFilter(note); filter = (note) => !isPureRenote(note) && parentFilter(note);
} }
if (ps.me) { if (ps.me) {
@@ -116,7 +116,7 @@ export class FanoutTimelineEndpointService {
filter = (note) => { filter = (note) => {
if (isUserRelated(note, userIdsWhoBlockingMe, ps.ignoreAuthorFromBlock)) return false; if (isUserRelated(note, userIdsWhoBlockingMe, ps.ignoreAuthorFromBlock)) return false;
if (isUserRelated(note, userIdsWhoMeMuting, ps.ignoreAuthorFromMute)) return false; if (isUserRelated(note, userIdsWhoMeMuting, ps.ignoreAuthorFromMute)) return false;
if (!ps.ignoreAuthorFromMute && isRenote(note) && !isQuote(note) && userIdsWhoMeMutingRenotes.has(note.userId)) return false; if (isPureRenote(note) && isUserRelated(note, userIdsWhoMeMutingRenotes, ps.ignoreAuthorFromMute)) return false;
if (isInstanceMuted(note, userMutedInstances)) return false; if (isInstanceMuted(note, userMutedInstances)) return false;
return parentFilter(note); return parentFilter(note);

View File

@@ -51,35 +51,21 @@ export class FetchInstanceMetadataService {
} }
@bindThis @bindThis
// public for test public async tryLock(host: string): Promise<boolean> {
public async tryLock(host: string): Promise<string | null> { const mutex = await this.redisClient.set(`fetchInstanceMetadata:mutex:${host}`, '1', 'GET');
// TODO: マイグレーションなのであとで消す (2024.3.1) return mutex !== '1';
this.redisClient.del(`fetchInstanceMetadata:mutex:${host}`);
return await this.redisClient.set(
`fetchInstanceMetadata:mutex:v2:${host}`, '1',
'EX', 30, // 30秒したら自動でロック解除 https://github.com/misskey-dev/misskey/issues/13506#issuecomment-1975375395
'GET' // 古い値を返すなかったらnull
);
} }
@bindThis @bindThis
// public for test public unlock(host: string): Promise<'OK'> {
public unlock(host: string): Promise<number> { return this.redisClient.set(`fetchInstanceMetadata:mutex:${host}`, '0');
return this.redisClient.del(`fetchInstanceMetadata:mutex:v2:${host}`);
} }
@bindThis @bindThis
public async fetchInstanceMetadata(instance: MiInstance, force = false): Promise<void> { public async fetchInstanceMetadata(instance: MiInstance, force = false): Promise<void> {
const host = instance.host; const host = instance.host;
// Acquire mutex to ensure no parallel runs
// finallyでunlockされてしまうのでtry内でロックチェックをしない if (!await this.tryLock(host)) return;
// returnであってもfinallyは実行される
if (!force && await this.tryLock(host) === '1') {
// 1が返ってきていたらロックされているという意味なので、何もしない
return;
}
try { try {
if (!force) { if (!force) {
const _instance = await this.federatedInstanceService.fetch(host); const _instance = await this.federatedInstanceService.fetch(host);

View File

@@ -14,12 +14,10 @@ import FFmpeg from 'fluent-ffmpeg';
import isSvg from 'is-svg'; import isSvg from 'is-svg';
import probeImageSize from 'probe-image-size'; import probeImageSize from 'probe-image-size';
import { type predictionType } from 'nsfwjs'; import { type predictionType } from 'nsfwjs';
import { sharpBmp } from '@misskey-dev/sharp-read-bmp'; import sharp from 'sharp';
import { encode } from 'blurhash'; import { encode } from 'blurhash';
import { createTempDir } from '@/misc/create-temp.js'; import { createTempDir } from '@/misc/create-temp.js';
import { AiService } from '@/core/AiService.js'; import { AiService } from '@/core/AiService.js';
import { LoggerService } from '@/core/LoggerService.js';
import type Logger from '@/logger.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
export type FileInfo = { export type FileInfo = {
@@ -50,13 +48,9 @@ const TYPE_SVG = {
@Injectable() @Injectable()
export class FileInfoService { export class FileInfoService {
private logger: Logger;
constructor( constructor(
private aiService: AiService, private aiService: AiService,
private loggerService: LoggerService,
) { ) {
this.logger = this.loggerService.getLogger('file-info');
} }
/** /**
@@ -128,7 +122,7 @@ export class FileInfoService {
'image/avif', 'image/avif',
'image/svg+xml', 'image/svg+xml',
].includes(type.mime)) { ].includes(type.mime)) {
blurhash = await this.getBlurhash(path, type.mime).catch(e => { blurhash = await this.getBlurhash(path).catch(e => {
warnings.push(`getBlurhash failed: ${e}`); warnings.push(`getBlurhash failed: ${e}`);
return undefined; return undefined;
}); });
@@ -322,34 +316,6 @@ export class FileInfoService {
return mime; return mime;
} }
/**
* ビデオファイルにビデオトラックがあるかどうかチェック
* ない場合m4a, webmなど
*
* @param path ファイルパス
* @returns ビデオトラックがあるかどうか(エラー発生時は常に`true`を返す)
*/
@bindThis
private hasVideoTrackOnVideoFile(path: string): Promise<boolean> {
const sublogger = this.logger.createSubLogger('ffprobe');
sublogger.info(`Checking the video file. File path: ${path}`);
return new Promise((resolve) => {
try {
FFmpeg.ffprobe(path, (err, metadata) => {
if (err) {
sublogger.warn(`Could not check the video file. Returns true. File path: ${path}`, err);
resolve(true);
return;
}
resolve(metadata.streams.some((stream) => stream.codec_type === 'video'));
});
} catch (err) {
sublogger.warn(`Could not check the video file. Returns true. File path: ${path}`, err as Error);
resolve(true);
}
});
}
/** /**
* Detect MIME Type and extension * Detect MIME Type and extension
*/ */
@@ -372,20 +338,6 @@ export class FileInfoService {
return TYPE_SVG; return TYPE_SVG;
} }
if ((type.mime.startsWith('video') || type.mime === 'application/ogg') && !(await this.hasVideoTrackOnVideoFile(path))) {
const newMime = `audio/${type.mime.split('/')[1]}`;
if (newMime === 'audio/mp4') {
return {
mime: 'audio/mp4',
ext: 'm4a',
};
}
return {
mime: newMime,
ext: type.ext,
};
}
return { return {
mime: this.fixMime(type.mime), mime: this.fixMime(type.mime),
ext: type.ext, ext: type.ext,
@@ -455,9 +407,9 @@ export class FileInfoService {
* Calculate average color of image * Calculate average color of image
*/ */
@bindThis @bindThis
private getBlurhash(path: string, type: string): Promise<string> { private getBlurhash(path: string): Promise<string> {
return new Promise(async (resolve, reject) => { return new Promise((resolve, reject) => {
(await sharpBmp(path, type)) sharp(path)
.raw() .raw()
.ensureAlpha() .ensureAlpha()
.resize(64, 64, { fit: 'inside' }) .resize(64, 64, { fit: 'inside' })

View File

@@ -69,7 +69,6 @@ export interface MainEventTypes {
file: Packed<'DriveFile'>; file: Packed<'DriveFile'>;
}; };
readAllNotifications: undefined; readAllNotifications: undefined;
notificationFlushed: undefined;
unreadNotification: Packed<'Notification'>; unreadNotification: Packed<'Notification'>;
unreadMention: MiNote['id']; unreadMention: MiNote['id'];
readAllUnreadMentions: undefined; readAllUnreadMentions: undefined;
@@ -210,10 +209,8 @@ type SerializedAll<T> = {
export interface InternalEventTypes { export interface InternalEventTypes {
userChangeSuspendedState: { id: MiUser['id']; isSuspended: MiUser['isSuspended']; }; userChangeSuspendedState: { id: MiUser['id']; isSuspended: MiUser['isSuspended']; };
userChangeDeletedState: { id: MiUser['id']; isDeleted: MiUser['isDeleted']; };
userTokenRegenerated: { id: MiUser['id']; oldToken: string; newToken: string; }; userTokenRegenerated: { id: MiUser['id']; oldToken: string; newToken: string; };
remoteUserUpdated: { id: MiUser['id']; }; remoteUserUpdated: { id: MiUser['id']; };
localUserUpdated: { id: MiUser['id']; };
follow: { followerId: MiUser['id']; followeeId: MiUser['id']; }; follow: { followerId: MiUser['id']; followeeId: MiUser['id']; };
unfollow: { followerId: MiUser['id']; followeeId: MiUser['id']; }; unfollow: { followerId: MiUser['id']; followeeId: MiUser['id']; };
blockingCreated: { blockerId: MiUser['id']; blockeeId: MiUser['id']; }; blockingCreated: { blockerId: MiUser['id']; blockeeId: MiUser['id']; };

View File

@@ -6,11 +6,10 @@
import { URL } from 'node:url'; import { URL } from 'node:url';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import * as parse5 from 'parse5'; import * as parse5 from 'parse5';
import { Window, XMLSerializer } from 'happy-dom'; import { Window } from 'happy-dom';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import { intersperse } from '@/misc/prelude/array.js'; import { intersperse } from '@/misc/prelude/array.js';
import { normalizeForSearch } from '@/misc/normalize-for-search.js';
import type { IMentionedRemoteUsers } from '@/models/Note.js'; import type { IMentionedRemoteUsers } from '@/models/Note.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import * as TreeAdapter from '../../node_modules/parse5/dist/tree-adapters/default.js'; import * as TreeAdapter from '../../node_modules/parse5/dist/tree-adapters/default.js';
@@ -34,8 +33,6 @@ export class MfmService {
// some AP servers like Pixelfed use br tags as well as newlines // some AP servers like Pixelfed use br tags as well as newlines
html = html.replace(/<br\s?\/?>\r?\n/gi, '\n'); html = html.replace(/<br\s?\/?>\r?\n/gi, '\n');
const normalizedHashtagNames = hashtagNames == null ? undefined : new Set<string>(hashtagNames.map(x => normalizeForSearch(x)));
const dom = parse5.parseFragment(html); const dom = parse5.parseFragment(html);
let text = ''; let text = '';
@@ -88,7 +85,7 @@ export class MfmService {
const href = node.attrs.find(x => x.name === 'href'); const href = node.attrs.find(x => x.name === 'href');
// ハッシュタグ // ハッシュタグ
if (normalizedHashtagNames && href && normalizedHashtagNames.has(normalizeForSearch(txt))) { if (hashtagNames && href && hashtagNames.map(x => x.toLowerCase()).includes(txt.toLowerCase())) {
text += txt; text += txt;
// メンション // メンション
} else if (txt.startsWith('@') && !(rel && rel.value.startsWith('me '))) { } else if (txt.startsWith('@') && !(rel && rel.value.startsWith('me '))) {
@@ -247,8 +244,6 @@ export class MfmService {
const doc = window.document; const doc = window.document;
const body = doc.createElement('p');
function appendChildren(children: mfm.MfmNode[], targetElement: any): void { function appendChildren(children: mfm.MfmNode[], targetElement: any): void {
if (children) { if (children) {
for (const child of children.map(x => (handlers as any)[x.type](x))) targetElement.appendChild(child); for (const child of children.map(x => (handlers as any)[x.type](x))) targetElement.appendChild(child);
@@ -459,8 +454,8 @@ export class MfmService {
}, },
}; };
appendChildren(nodes, body); appendChildren(nodes, doc.body);
return new XMLSerializer().serializeToString(body); return `<p>${doc.body.innerHTML}</p>`;
} }
} }

View File

@@ -59,8 +59,6 @@ import { UtilityService } from '@/core/UtilityService.js';
import { UserBlockingService } from '@/core/UserBlockingService.js'; import { UserBlockingService } from '@/core/UserBlockingService.js';
import { isReply } from '@/misc/is-reply.js'; import { isReply } from '@/misc/is-reply.js';
import { trackPromise } from '@/misc/promise-tracker.js'; import { trackPromise } from '@/misc/promise-tracker.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';
type NotificationType = 'reply' | 'renote' | 'quote' | 'mention'; type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
@@ -153,6 +151,8 @@ type Option = {
export class NoteCreateService implements OnApplicationShutdown { export class NoteCreateService implements OnApplicationShutdown {
#shutdownController = new AbortController(); #shutdownController = new AbortController();
public static ContainsProhibitedWordsError = class extends Error {};
constructor( constructor(
@Inject(DI.config) @Inject(DI.config)
private config: Config, private config: Config,
@@ -263,14 +263,8 @@ export class NoteCreateService implements OnApplicationShutdown {
} }
} }
const hasProhibitedWords = await this.checkProhibitedWordsContain({ if (this.utilityService.isKeyWordIncluded(data.cw ?? data.text ?? '', meta.prohibitedWords)) {
cw: data.cw, throw new NoteCreateService.ContainsProhibitedWordsError();
text: data.text,
pollChoices: data.poll?.choices,
}, meta.prohibitedWords);
if (hasProhibitedWords) {
throw new IdentifiableError('689ee33f-f97c-479a-ac49-1b9f8140af99', 'Note contains prohibited words');
} }
const inSilencedInstance = this.utilityService.isSilencedHost(meta.silencedHosts, user.host); const inSilencedInstance = this.utilityService.isSilencedHost(meta.silencedHosts, user.host);
@@ -306,7 +300,7 @@ export class NoteCreateService implements OnApplicationShutdown {
} }
// Check blocking // Check blocking
if (this.isRenote(data) && !this.isQuote(data)) { if (data.renote && !this.isQuote(data)) {
if (data.renote.userHost === null) { if (data.renote.userHost === null) {
if (data.renote.userId !== user.id) { if (data.renote.userId !== user.id) {
const blocked = await this.userBlockingService.checkBlocked(data.renote.userId, user.id); const blocked = await this.userBlockingService.checkBlocked(data.renote.userId, user.id);
@@ -385,10 +379,6 @@ export class NoteCreateService implements OnApplicationShutdown {
} }
} }
if (mentionedUsers.length > 0 && mentionedUsers.length > (await this.roleService.getUserPolicies(user.id)).mentionLimit) {
throw new IdentifiableError('9f466dab-c856-48cd-9e65-ff90ff750580', 'Note contains too many mentions');
}
const note = await this.insertNote(user, data, tags, emojis, mentionedUsers); const note = await this.insertNote(user, data, tags, emojis, mentionedUsers);
setImmediate('post created', { signal: this.#shutdownController.signal }).then( setImmediate('post created', { signal: this.#shutdownController.signal }).then(
@@ -641,7 +631,7 @@ export class NoteCreateService implements OnApplicationShutdown {
} }
// If it is renote // If it is renote
if (this.isRenote(data)) { if (data.renote) {
const type = this.isQuote(data) ? 'quote' : 'renote'; const type = this.isQuote(data) ? 'quote' : 'renote';
// Notify // Notify
@@ -725,20 +715,9 @@ export class NoteCreateService implements OnApplicationShutdown {
} }
@bindThis @bindThis
private isRenote(note: Option): note is Option & { renote: MiNote } { private isQuote(note: Option): note is Option & { renote: MiNote } {
return note.renote != null; // sync with misc/is-quote.ts
} return !!note.renote && (!!note.text || !!note.cw || (!!note.files && !!note.files.length) || !!note.poll);
@bindThis
private isQuote(note: Option & { renote: MiNote }): note is Option & { renote: MiNote } & (
{ text: string } | { cw: string } | { reply: MiNote } | { poll: IPoll } | { files: MiDriveFile[] }
) {
// NOTE: SYNC WITH misc/is-quote.ts
return note.text != null ||
note.reply != null ||
note.cw != null ||
note.poll != null ||
(note.files != null && note.files.length > 0);
} }
@bindThis @bindThis
@@ -806,7 +785,7 @@ export class NoteCreateService implements OnApplicationShutdown {
private async renderNoteOrRenoteActivity(data: Option, note: MiNote) { private async renderNoteOrRenoteActivity(data: Option, note: MiNote) {
if (data.localOnly) return null; if (data.localOnly) return null;
const content = this.isRenote(data) && !this.isQuote(data) const content = data.renote && !this.isQuote(data)
? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note) ? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note)
: this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false), note); : this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false), note);
@@ -838,7 +817,7 @@ export class NoteCreateService implements OnApplicationShutdown {
const mentions = extractMentions(tokens); const mentions = extractMentions(tokens);
let mentionedUsers = (await Promise.all(mentions.map(m => let mentionedUsers = (await Promise.all(mentions.map(m =>
this.remoteUserResolveService.resolveUser(m.username, m.host ?? user.host).catch(() => null), this.remoteUserResolveService.resolveUser(m.username, m.host ?? user.host).catch(() => null),
))).filter(isNotNull); ))).filter(x => x != null) as MiUser[];
// Drop duplicate users // Drop duplicate users
mentionedUsers = mentionedUsers.filter((u, i, self) => mentionedUsers = mentionedUsers.filter((u, i, self) =>
@@ -1012,23 +991,6 @@ export class NoteCreateService implements OnApplicationShutdown {
} }
} }
public async checkProhibitedWordsContain(content: Parameters<UtilityService['concatNoteContentsForKeyWordCheck']>[0], prohibitedWords?: string[]) {
if (prohibitedWords == null) {
prohibitedWords = (await this.metaService.fetch()).prohibitedWords;
}
if (
this.utilityService.isKeyWordIncluded(
this.utilityService.concatNoteContentsForKeyWordCheck(content),
prohibitedWords,
)
) {
return true;
}
return false;
}
@bindThis @bindThis
public dispose(): void { public dispose(): void {
this.#shutdownController.abort(); this.#shutdownController.abort();

View File

@@ -24,7 +24,7 @@ import { bindThis } from '@/decorators.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { SearchService } from '@/core/SearchService.js'; import { SearchService } from '@/core/SearchService.js';
import { ModerationLogService } from '@/core/ModerationLogService.js'; import { ModerationLogService } from '@/core/ModerationLogService.js';
import { isQuote, isRenote } from '@/misc/is-renote.js'; import { isPureRenote } from '@/misc/is-pure-renote.js';
@Injectable() @Injectable()
export class NoteDeleteService { export class NoteDeleteService {
@@ -79,7 +79,7 @@ export class NoteDeleteService {
let renote: MiNote | null = null; let renote: MiNote | null = null;
// if deleted note is renote // if deleted note is renote
if (isRenote(note) && !isQuote(note)) { if (isPureRenote(note)) {
renote = await this.notesRepository.findOneBy({ renote = await this.notesRepository.findOneBy({
id: note.renoteId, id: note.renoteId,
}); });

View File

@@ -88,24 +88,22 @@ export class NoteReadService implements OnApplicationShutdown {
userId: MiUser['id'], userId: MiUser['id'],
notes: (MiNote | Packed<'Note'>)[], notes: (MiNote | Packed<'Note'>)[],
): Promise<void> { ): Promise<void> {
if (notes.length === 0) return; const readMentions: (MiNote | Packed<'Note'>)[] = [];
const readSpecifiedNotes: (MiNote | Packed<'Note'>)[] = [];
const noteIds = new Set<MiNote['id']>();
for (const note of notes) { for (const note of notes) {
if (note.mentions && note.mentions.includes(userId)) { if (note.mentions && note.mentions.includes(userId)) {
noteIds.add(note.id); readMentions.push(note);
} else if (note.visibleUserIds && note.visibleUserIds.includes(userId)) { } else if (note.visibleUserIds && note.visibleUserIds.includes(userId)) {
noteIds.add(note.id); readSpecifiedNotes.push(note);
} }
} }
if (noteIds.size === 0) return; if ((readMentions.length > 0) || (readSpecifiedNotes.length > 0)) {
// Remove the record // Remove the record
await this.noteUnreadsRepository.delete({ await this.noteUnreadsRepository.delete({
userId: userId, userId: userId,
noteId: In(Array.from(noteIds)), noteId: In([...readMentions.map(n => n.id), ...readSpecifiedNotes.map(n => n.id)]),
}); });
// TODO: ↓まとめてクエリしたい // TODO: ↓まとめてクエリしたい
@@ -130,6 +128,7 @@ export class NoteReadService implements OnApplicationShutdown {
} }
})); }));
} }
}
@bindThis @bindThis
public dispose(): void { public dispose(): void {

View File

@@ -122,14 +122,6 @@ export class NotificationService implements OnApplicationShutdown {
return null; return null;
} }
} else if (recieveConfig?.type === 'mutualFollow') { } else if (recieveConfig?.type === 'mutualFollow') {
const [isFollowing, isFollower] = await Promise.all([
this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => Object.hasOwn(followings, notifierId)),
this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => Object.hasOwn(followings, notifieeId)),
]);
if (!(isFollowing && isFollower)) {
return null;
}
} else if (recieveConfig?.type === 'followingOrFollower') {
const [isFollowing, isFollower] = await Promise.all([ const [isFollowing, isFollower] = await Promise.all([
this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => Object.hasOwn(followings, notifierId)), this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => Object.hasOwn(followings, notifierId)),
this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => Object.hasOwn(followings, notifieeId)), this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => Object.hasOwn(followings, notifieeId)),
@@ -163,8 +155,6 @@ export class NotificationService implements OnApplicationShutdown {
const packed = await this.notificationEntityService.pack(notification, notifieeId, {}); const packed = await this.notificationEntityService.pack(notification, notifieeId, {});
if (packed == null) return null;
// Publish notification event // Publish notification event
this.globalEventService.publishMainStream(notifieeId, 'notification', packed); this.globalEventService.publishMainStream(notifieeId, 'notification', packed);
@@ -214,15 +204,6 @@ export class NotificationService implements OnApplicationShutdown {
*/ */
} }
@bindThis
public async flushAllNotifications(userId: MiUser['id']) {
await Promise.all([
this.redisClient.del(`notificationTimeline:${userId}`),
this.redisClient.del(`latestReadNotification:${userId}`),
]);
this.globalEventService.publishMainStream(userId, 'notificationFlushed');
}
@bindThis @bindThis
public dispose(): void { public dispose(): void {
this.#shutdownController.abort(); this.#shutdownController.abort();

View File

@@ -101,7 +101,7 @@ export class PushNotificationService implements OnApplicationShutdown {
type, type,
body: (type === 'notification' || type === 'unreadAntennaNote') ? truncateBody(type, body) : body, body: (type === 'notification' || type === 'unreadAntennaNote') ? truncateBody(type, body) : body,
userId, userId,
dateTime: Date.now(), dateTime: (new Date()).getTime(),
}), { }), {
proxy: this.config.proxy, proxy: this.config.proxy,
}).catch((err: any) => { }).catch((err: any) => {
@@ -115,19 +115,12 @@ export class PushNotificationService implements OnApplicationShutdown {
endpoint: subscription.endpoint, endpoint: subscription.endpoint,
auth: subscription.auth, auth: subscription.auth,
publickey: subscription.publickey, publickey: subscription.publickey,
}).then(() => {
this.refreshCache(userId);
}); });
} }
}); });
} }
} }
@bindThis
public refreshCache(userId: string): void {
this.subscriptionsCache.refresh(userId);
}
@bindThis @bindThis
public dispose(): void { public dispose(): void {
this.subscriptionsCache.dispose(); this.subscriptionsCache.dispose();

View File

@@ -322,36 +322,35 @@ export class ReactionService {
//#endregion //#endregion
} }
/**
* 文字列タイプのレガシーな形式のリアクションを現在の形式に変換しつつ、
* データベース上には存在する「0個のリアクションがついている」という情報を削除する。
*/
@bindThis @bindThis
public convertLegacyReactions(reactions: MiNote['reactions']): MiNote['reactions'] { public convertLegacyReactions(reactions: Record<string, number>) {
return Object.entries(reactions) const _reactions = {} as Record<string, number>;
.filter(([, count]) => {
// `ReactionService.prototype.delete`ではリアクション削除時に、
// `MiNote['reactions']`のエントリの値をデクリメントしているが、
// デクリメントしているだけなのでエントリ自体は0を値として持つ形で残り続ける。
// そのため、この処理がなければ、「0個のリアクションがついている」ということになってしまう。
return count > 0;
})
.map(([reaction, count]) => {
// unchecked indexed access
const convertedReaction = legacies[reaction] as string | undefined;
const key = this.decodeReaction(convertedReaction ?? reaction).reaction; for (const reaction of Object.keys(reactions)) {
if (reactions[reaction] <= 0) continue;
return [key, count] as const; if (Object.keys(legacies).includes(reaction)) {
}) if (_reactions[legacies[reaction]]) {
.reduce<MiNote['reactions']>((acc, [key, count]) => { _reactions[legacies[reaction]] += reactions[reaction];
// unchecked indexed access } else {
const prevCount = acc[key] as number | undefined; _reactions[legacies[reaction]] = reactions[reaction];
}
} else {
if (_reactions[reaction]) {
_reactions[reaction] += reactions[reaction];
} else {
_reactions[reaction] = reactions[reaction];
}
}
}
acc[key] = (prevCount ?? 0) + count; const _reactions2 = {} as Record<string, number>;
return acc; for (const reaction of Object.keys(_reactions)) {
}, {}); _reactions2[this.decodeReaction(reaction).reaction] = _reactions[reaction];
}
return _reactions2;
} }
@bindThis @bindThis

View File

@@ -35,7 +35,6 @@ export type RolePolicies = {
gtlAvailable: boolean; gtlAvailable: boolean;
ltlAvailable: boolean; ltlAvailable: boolean;
canPublicNote: boolean; canPublicNote: boolean;
mentionLimit: number;
canInvite: boolean; canInvite: boolean;
inviteLimit: number; inviteLimit: number;
inviteLimitCycle: number; inviteLimitCycle: number;
@@ -63,7 +62,6 @@ export const DEFAULT_POLICIES: RolePolicies = {
gtlAvailable: true, gtlAvailable: true,
ltlAvailable: true, ltlAvailable: true,
canPublicNote: true, canPublicNote: true,
mentionLimit: 20,
canInvite: false, canInvite: false,
inviteLimit: 0, inviteLimit: 0,
inviteLimitCycle: 60 * 24 * 7, inviteLimitCycle: 60 * 24 * 7,
@@ -202,82 +200,45 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
} }
@bindThis @bindThis
private evalCond(user: MiUser, roles: MiRole[], value: RoleCondFormulaValue): boolean { private evalCond(user: MiUser, value: RoleCondFormulaValue): boolean {
try { try {
switch (value.type) { switch (value.type) {
// ~かつ~
case 'and': { case 'and': {
return value.values.every(v => this.evalCond(user, roles, v)); return value.values.every(v => this.evalCond(user, v));
} }
// ~または~
case 'or': { case 'or': {
return value.values.some(v => this.evalCond(user, roles, v)); return value.values.some(v => this.evalCond(user, v));
} }
// ~ではない
case 'not': { case 'not': {
return !this.evalCond(user, roles, value.value); return !this.evalCond(user, value.value);
} }
// マニュアルロールがアサインされている
case 'roleAssignedTo': {
return roles.some(r => r.id === value.roleId);
}
// ローカルユーザのみ
case 'isLocal': { case 'isLocal': {
return this.userEntityService.isLocalUser(user); return this.userEntityService.isLocalUser(user);
} }
// リモートユーザのみ
case 'isRemote': { case 'isRemote': {
return this.userEntityService.isRemoteUser(user); return this.userEntityService.isRemoteUser(user);
} }
// サスペンド済みユーザである
case 'isSuspended': {
return user.isSuspended;
}
// 鍵アカウントユーザである
case 'isLocked': {
return user.isLocked;
}
// botユーザである
case 'isBot': {
return user.isBot;
}
// 猫である
case 'isCat': {
return user.isCat;
}
// 「ユーザを見つけやすくする」が有効なアカウント
case 'isExplorable': {
return user.isExplorable;
}
// ユーザが作成されてから指定期間経過した
case 'createdLessThan': { case 'createdLessThan': {
return this.idService.parse(user.id).date.getTime() > (Date.now() - (value.sec * 1000)); return this.idService.parse(user.id).date.getTime() > (Date.now() - (value.sec * 1000));
} }
// ユーザが作成されてから指定期間経っていない
case 'createdMoreThan': { case 'createdMoreThan': {
return this.idService.parse(user.id).date.getTime() < (Date.now() - (value.sec * 1000)); return this.idService.parse(user.id).date.getTime() < (Date.now() - (value.sec * 1000));
} }
// フォロワー数が指定値以下
case 'followersLessThanOrEq': { case 'followersLessThanOrEq': {
return user.followersCount <= value.value; return user.followersCount <= value.value;
} }
// フォロワー数が指定値以上
case 'followersMoreThanOrEq': { case 'followersMoreThanOrEq': {
return user.followersCount >= value.value; return user.followersCount >= value.value;
} }
// フォロー数が指定値以下
case 'followingLessThanOrEq': { case 'followingLessThanOrEq': {
return user.followingCount <= value.value; return user.followingCount <= value.value;
} }
// フォロー数が指定値以上
case 'followingMoreThanOrEq': { case 'followingMoreThanOrEq': {
return user.followingCount >= value.value; return user.followingCount >= value.value;
} }
// ノート数が指定値以下
case 'notesLessThanOrEq': { case 'notesLessThanOrEq': {
return user.notesCount <= value.value; return user.notesCount <= value.value;
} }
// ノート数が指定値以上
case 'notesMoreThanOrEq': { case 'notesMoreThanOrEq': {
return user.notesCount >= value.value; return user.notesCount >= value.value;
} }
@@ -311,7 +272,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
const assigns = await this.getUserAssigns(userId); const assigns = await this.getUserAssigns(userId);
const assignedRoles = roles.filter(r => assigns.map(x => x.roleId).includes(r.id)); const assignedRoles = roles.filter(r => assigns.map(x => x.roleId).includes(r.id));
const user = roles.some(r => r.target === 'conditional') ? await this.cacheService.findUserById(userId) : null; const user = roles.some(r => r.target === 'conditional') ? await this.cacheService.findUserById(userId) : null;
const matchedCondRoles = roles.filter(r => r.target === 'conditional' && this.evalCond(user!, assignedRoles, r.condFormula)); const matchedCondRoles = roles.filter(r => r.target === 'conditional' && this.evalCond(user!, r.condFormula));
return [...assignedRoles, ...matchedCondRoles]; return [...assignedRoles, ...matchedCondRoles];
} }
@@ -324,13 +285,13 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
let assigns = await this.roleAssignmentByUserIdCache.fetch(userId, () => this.roleAssignmentsRepository.findBy({ userId })); let assigns = await this.roleAssignmentByUserIdCache.fetch(userId, () => this.roleAssignmentsRepository.findBy({ userId }));
// 期限切れのロールを除外 // 期限切れのロールを除外
assigns = assigns.filter(a => a.expiresAt == null || (a.expiresAt.getTime() > now)); assigns = assigns.filter(a => a.expiresAt == null || (a.expiresAt.getTime() > now));
const assignedRoleIds = assigns.map(x => x.roleId);
const roles = await this.rolesCache.fetch(() => this.rolesRepository.findBy({})); const roles = await this.rolesCache.fetch(() => this.rolesRepository.findBy({}));
const assignedRoles = roles.filter(r => assigns.map(x => x.roleId).includes(r.id)); const assignedBadgeRoles = roles.filter(r => r.asBadge && assignedRoleIds.includes(r.id));
const assignedBadgeRoles = assignedRoles.filter(r => r.asBadge);
const badgeCondRoles = roles.filter(r => r.asBadge && (r.target === 'conditional')); const badgeCondRoles = roles.filter(r => r.asBadge && (r.target === 'conditional'));
if (badgeCondRoles.length > 0) { if (badgeCondRoles.length > 0) {
const user = roles.some(r => r.target === 'conditional') ? await this.cacheService.findUserById(userId) : null; const user = roles.some(r => r.target === 'conditional') ? await this.cacheService.findUserById(userId) : null;
const matchedBadgeCondRoles = badgeCondRoles.filter(r => this.evalCond(user!, assignedRoles, r.condFormula)); const matchedBadgeCondRoles = badgeCondRoles.filter(r => this.evalCond(user!, r.condFormula));
return [...assignedBadgeRoles, ...matchedBadgeCondRoles]; return [...assignedBadgeRoles, ...matchedBadgeCondRoles];
} else { } else {
return assignedBadgeRoles; return assignedBadgeRoles;
@@ -364,7 +325,6 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
gtlAvailable: calc('gtlAvailable', vs => vs.some(v => v === true)), gtlAvailable: calc('gtlAvailable', vs => vs.some(v => v === true)),
ltlAvailable: calc('ltlAvailable', vs => vs.some(v => v === true)), ltlAvailable: calc('ltlAvailable', vs => vs.some(v => v === true)),
canPublicNote: calc('canPublicNote', vs => vs.some(v => v === true)), canPublicNote: calc('canPublicNote', vs => vs.some(v => v === true)),
mentionLimit: calc('mentionLimit', vs => Math.max(...vs)),
canInvite: calc('canInvite', vs => vs.some(v => v === true)), canInvite: calc('canInvite', vs => vs.some(v => v === true)),
inviteLimit: calc('inviteLimit', vs => Math.max(...vs)), inviteLimit: calc('inviteLimit', vs => Math.max(...vs)),
inviteLimitCycle: calc('inviteLimitCycle', vs => Math.max(...vs)), inviteLimitCycle: calc('inviteLimitCycle', vs => Math.max(...vs)),

View File

@@ -30,7 +30,6 @@ import type { Config } from '@/config.js';
import { AccountMoveService } from '@/core/AccountMoveService.js'; import { AccountMoveService } from '@/core/AccountMoveService.js';
import { UtilityService } from '@/core/UtilityService.js'; import { UtilityService } from '@/core/UtilityService.js';
import { FanoutTimelineService } from '@/core/FanoutTimelineService.js'; import { FanoutTimelineService } from '@/core/FanoutTimelineService.js';
import type { ThinUser } from '@/queue/types.js';
import Logger from '../logger.js'; import Logger from '../logger.js';
const logger = new Logger('following/create'); const logger = new Logger('following/create');
@@ -95,35 +94,21 @@ export class UserFollowingService implements OnModuleInit {
this.userBlockingService = this.moduleRef.get('UserBlockingService'); this.userBlockingService = this.moduleRef.get('UserBlockingService');
} }
@bindThis
public async deliverAccept(follower: MiRemoteUser, followee: MiPartialLocalUser, requestId?: string) {
const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee));
this.queueService.deliver(followee, content, follower.inbox, false);
}
@bindThis @bindThis
public async follow( public async follow(
_follower: ThinUser, _follower: { id: MiUser['id'] },
_followee: ThinUser, _followee: { id: MiUser['id'] },
{ requestId, silent = false, withReplies }: { { requestId, silent = false, withReplies }: {
requestId?: string, requestId?: string,
silent?: boolean, silent?: boolean,
withReplies?: boolean, withReplies?: boolean,
} = {}, } = {},
): Promise<void> { ): Promise<void> {
/**
* 必ず最新のユーザー情報を取得する
*/
const [follower, followee] = await Promise.all([ const [follower, followee] = await Promise.all([
this.usersRepository.findOneByOrFail({ id: _follower.id }), this.usersRepository.findOneByOrFail({ id: _follower.id }),
this.usersRepository.findOneByOrFail({ id: _followee.id }), this.usersRepository.findOneByOrFail({ id: _followee.id }),
]) as [MiLocalUser | MiRemoteUser, MiLocalUser | MiRemoteUser]; ]) as [MiLocalUser | MiRemoteUser, MiLocalUser | MiRemoteUser];
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isRemoteUser(followee)) {
// What?
throw new Error('Remote user cannot follow remote user.');
}
// check blocking // check blocking
const [blocking, blocked] = await Promise.all([ const [blocking, blocked] = await Promise.all([
this.userBlockingService.checkBlocked(follower.id, followee.id), this.userBlockingService.checkBlocked(follower.id, followee.id),
@@ -144,24 +129,6 @@ export class UserFollowingService implements OnModuleInit {
if (blocked) throw new IdentifiableError('3338392a-f764-498d-8855-db939dcf8c48', 'blocked'); if (blocked) throw new IdentifiableError('3338392a-f764-498d-8855-db939dcf8c48', 'blocked');
} }
if (await this.followingsRepository.exists({
where: {
followerId: follower.id,
followeeId: followee.id,
},
})) {
// すでにフォロー関係が存在している場合
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
// リモート → ローカル: acceptを送り返しておしまい
this.deliverAccept(follower, followee, requestId);
return;
}
if (this.userEntityService.isLocalUser(follower)) {
// ローカル → リモート/ローカル: 例外
throw new IdentifiableError('ec3f65c0-a9d1-47d9-8791-b2e7b9dcdced', 'already following');
}
}
const followeeProfile = await this.userProfilesRepository.findOneByOrFail({ userId: followee.id }); const followeeProfile = await this.userProfilesRepository.findOneByOrFail({ userId: followee.id });
// フォロー対象が鍵アカウントである or // フォロー対象が鍵アカウントである or
// フォロワーがBotであり、フォロー対象がBotからのフォローに慎重である or // フォロワーがBotであり、フォロー対象がBotからのフォローに慎重である or
@@ -222,7 +189,8 @@ export class UserFollowingService implements OnModuleInit {
await this.insertFollowingDoc(followee, follower, silent, withReplies); await this.insertFollowingDoc(followee, follower, silent, withReplies);
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
this.deliverAccept(follower, followee, requestId); const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee));
this.queueService.deliver(followee, content, follower.inbox, false);
} }
} }
@@ -511,12 +479,6 @@ export class UserFollowingService implements OnModuleInit {
if (blocking) throw new Error('blocking'); if (blocking) throw new Error('blocking');
if (blocked) throw new Error('blocked'); if (blocked) throw new Error('blocked');
// Remove old follow requests before creating a new one.
await this.followRequestsRepository.delete({
followeeId: followee.id,
followerId: follower.id,
});
const followRequest = await this.followRequestsRepository.insert({ const followRequest = await this.followRequestsRepository.insert({
id: this.idService.gen(), id: this.idService.gen(),
followerId: follower.id, followerId: follower.id,
@@ -609,7 +571,8 @@ export class UserFollowingService implements OnModuleInit {
await this.insertFollowingDoc(followee, follower, false, request.withReplies); await this.insertFollowingDoc(followee, follower, false, request.withReplies);
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
this.deliverAccept(follower, followee as MiPartialLocalUser, request.requestId ?? undefined); const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee as MiPartialLocalUser, request.requestId!), followee));
this.queueService.deliver(followee, content, follower.inbox, false);
} }
this.userEntityService.pack(followee.id, followee, { this.userEntityService.pack(followee.id, followee, {

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