1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-05-08 02:15:33 +02:00

Compare commits

..

191 Commits

Author SHA1 Message Date
syuilo
5977b9c1f6 New translations ja-jp.yml (Catalan)
[ci skip]
2026-05-08 08:35:48 +09:00
syuilo
b4da22df8e New translations ja-jp.yml (Spanish)
[ci skip]
2026-05-08 08:35:46 +09:00
syuilo
4290438cf5 New translations ja-jp.yml (Italian)
[ci skip]
2026-05-08 02:59:03 +09:00
syuilo
e2e8c3a95b New translations ja-jp.yml (Chinese Simplified)
[ci skip]
2026-05-08 01:07:04 +09:00
syuilo
4d6a7836a8 New translations ja-jp.yml (Korean)
[ci skip]
2026-05-07 21:02:37 +09:00
syuilo
ede30b94fa New translations ja-jp.yml (Japanese, Kansai)
[ci skip]
2026-05-07 12:43:37 +09:00
syuilo
a7ea5757e0 New translations ja-jp.yml (Indonesian)
[ci skip]
2026-05-07 12:43:26 +09:00
syuilo
e0d3281aee New translations ja-jp.yml (Vietnamese)
[ci skip]
2026-05-07 12:43:25 +09:00
syuilo
be20c18830 New translations ja-jp.yml (Chinese Traditional)
[ci skip]
2026-05-07 12:43:23 +09:00
syuilo
3985e109fc New translations ja-jp.yml (Ukrainian)
[ci skip]
2026-05-07 12:43:21 +09:00
syuilo
543ee41714 New translations ja-jp.yml (Turkish)
[ci skip]
2026-05-07 12:43:19 +09:00
syuilo
d32b163290 New translations ja-jp.yml (Swedish)
[ci skip]
2026-05-07 12:43:17 +09:00
syuilo
0b47ffdeca New translations ja-jp.yml (Slovak)
[ci skip]
2026-05-07 12:43:16 +09:00
syuilo
cd3ceeeca9 New translations ja-jp.yml (Russian)
[ci skip]
2026-05-07 12:43:14 +09:00
syuilo
595df11cef New translations ja-jp.yml (Portuguese)
[ci skip]
2026-05-07 12:43:12 +09:00
syuilo
4f984fa1a8 New translations ja-jp.yml (Polish)
[ci skip]
2026-05-07 12:43:11 +09:00
syuilo
4f5b3a8f33 New translations ja-jp.yml (Dutch)
[ci skip]
2026-05-07 12:43:08 +09:00
syuilo
c952d16c76 New translations ja-jp.yml (Korean)
[ci skip]
2026-05-07 12:43:06 +09:00
syuilo
1d8d5327cd New translations ja-jp.yml (Italian)
[ci skip]
2026-05-07 12:43:04 +09:00
syuilo
49c205b3fa New translations ja-jp.yml (German)
[ci skip]
2026-05-07 12:43:01 +09:00
syuilo
cbc1fabf5f New translations ja-jp.yml (Czech)
[ci skip]
2026-05-07 12:42:58 +09:00
syuilo
b0175c49e7 New translations ja-jp.yml (Catalan)
[ci skip]
2026-05-07 12:42:57 +09:00
syuilo
983841c3fe New translations ja-jp.yml (Arabic)
[ci skip]
2026-05-07 12:42:55 +09:00
syuilo
93f869fb59 New translations ja-jp.yml (French)
[ci skip]
2026-05-07 12:42:53 +09:00
syuilo
d98c6fcf72 New translations ja-jp.yml (Romanian)
[ci skip]
2026-05-07 12:42:51 +09:00
syuilo
599b1592ef New translations ja-jp.yml (Chinese Simplified)
[ci skip]
2026-05-07 12:42:49 +09:00
syuilo
003afb6177 New translations ja-jp.yml (Thai)
[ci skip]
2026-05-07 12:42:47 +09:00
syuilo
e74bd3b7b7 New translations ja-jp.yml (English)
[ci skip]
2026-05-07 12:42:46 +09:00
syuilo
7f745f7767 New translations ja-jp.yml (Spanish)
[ci skip]
2026-05-07 12:42:44 +09:00
syuilo
ca6e99e940 New translations ja-jp.yml (Spanish)
[ci skip]
2026-05-06 19:34:53 +09:00
かっこかり
33f59b3469 Update CHANGELOG.md 2026-05-06 15:08:22 +09:00
syuilo
5b478dda9d New Crowdin updates (#17372)
* New translations ja-jp.yml (Turkish)

[ci skip]

* New translations ja-jp.yml (Thai)

[ci skip]

* New translations ja-jp.yml (Thai)

[ci skip]

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

[ci skip]

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

[ci skip]
2026-05-06 11:12:51 +09:00
かっこかり
90725d6a8c enhance(frontend): MkNoteDetailedの公開範囲表示を改善 (#17374)
* enhance(frontend): 노트 상세 페이지에서 공개 범위를 자세히 표시하도록 개선됨

* Update Changelog

* fix

---------

Co-authored-by: NoriDev <m1nthing2322@gmail.com>
2026-05-05 20:53:27 +09:00
github-actions[bot]
86542f07d3 Bump version to 2026.5.1-beta.0 2026-05-04 14:22:27 +00:00
syuilo
45022bc766 New Crowdin updates (#17324)
* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Thai)

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

[ci skip]

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

[ci skip]

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

[ci skip]

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

[ci skip]

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

[ci skip]

* New translations ja-jp.yml (Korean)

[ci skip]

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

[ci skip]

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

[ci skip]

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

[ci skip]

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

[ci skip]
2026-05-04 20:32:06 +09:00
Wonwoo Choi
35711fc8e1 fix(backend): Acquire lock of Announce object in announceNote even if it is from a relay actor (#17356)
fix(backend): Always acquire lock of Announce object in announceNote
2026-05-03 21:03:25 +09:00
かっこかり
45f140aa86 deps: Update dependencies [ci skip] (#17368)
* update deps

* update deps

* rollback got to v14

* Revert "rollback got to v14"

This reverts commit 780abdf7b6.

* rollback rolldown to v1.0.0-rc.15
2026-05-03 18:24:53 +09:00
renovate[bot]
22ce7b58ca chore(deps): update [docker] update dependencies [ci skip] (#17369)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-03 18:22:37 +09:00
renovate[bot]
37107c9818 chore(deps): update [github actions] update dependencies [ci skip] (#17370)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-03 18:22:02 +09:00
renovate[bot]
a5a43c8c06 chore(deps): update [github actions] update dependencies (major) (#17204)
chore(deps): update [github actions] update dependencies

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-05-03 17:45:12 +09:00
かっこかり
723d8add2f refactor: パスキーまわりのライブラリを更新 (#17354)
* refactor: パスキーまわりのライブラリを更新

* fix
2026-05-03 17:16:06 +09:00
かっこかり
9d20152e05 Update CHANGELOG.md (follow-up of #17121) [ci skip 2026-05-03 17:15:29 +09:00
Copilot
37412f0e1b enhance: Add canCreateChannel role policy (#17121)
* Initial plan

* Add canCreateChannel role policy to control channel creation

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

* Add canCreateChannel to getUserPolicies return value

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

* Add canCreateChannel translations for en-US and ja-JP

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

* Add canCreateChannel to misskey-js rolePolicies array

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

* Add frontend UI for canCreateChannel policy configuration

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

* fix: build autogen files

* 🎨

* migrate

* fix: unnecessary changes to non-Japanese locales

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
2026-05-03 17:10:17 +09:00
kami8
712b51c142 Fix(frontend): ロール設定画面でロールをアサイン/アサイン解除した際、リロードしなくても画面に反映されるよう修正 (#17365)
* ロールの付与、剥奪後にPaginatorのリロードを行って表示を更新する処理を追加

* CHANGELOGを更新
2026-05-03 16:15:03 +09:00
github-actions[bot]
2b4bdbfde7 Bump version to 2026.5.1-alpha.0 2026-05-03 06:54:33 +00:00
かっこかり
39032c4b1b fix: update summaly (#17355)
* fix: update summaly

* Update Changelog
2026-05-03 15:48:22 +09:00
かっこかり
f5a3d8996d fix(backend): 公開範囲がフォロワーの投稿が通知されない問題を修正 (#17363)
* fix(backend): 公開範囲がフォロワーの投稿が通知されない問題を修正

* Udpate Changelog
2026-05-03 15:43:39 +09:00
kami8
d55e936653 devcontainer用dbコンテナのvolumeのマウントパスを変更 (#17360)
* `.devcontainer/compose.yml`のvolumeのマウントパスを修正

* CHANGELOGの更新
2026-05-03 09:23:00 +09:00
mq1
6229ac365e fix(backend): ULID使用時にnotificationTimelineへのXADDが失敗し続け、通知が約10秒遅延する問題を修正 (#17358) 2026-05-02 20:23:10 +09:00
github-actions[bot]
6d9412b338 [skip ci] Update CHANGELOG.md (prepend template) 2026-05-02 03:30:59 +00:00
github-actions[bot]
a23a72b015 Release: 2026.5.0 2026-05-02 03:30:51 +00:00
かっこかり
93bd9d551d fix: review fixes for v2026.5.0 release (#17350)
* fix/perf: NotificationManager in NoteCreateService

* fix: treat skip as successful return in InboxProcessorService

* chore: remove comment

* fix: simplify ReactionPicker/EmojiPicker by importing components directly

* refactor: move filename parsing to setup in MkUploaderItems

* refactor
2026-05-02 10:03:34 +09:00
syuilo
35d6c20828 Update CHANGELOG.md 2026-05-01 14:22:54 +09:00
github-actions[bot]
7c9942f014 Bump version to 2026.5.0-alpha.0 2026-05-01 05:21:43 +00:00
github-actions[bot]
665adfccb7 Bump version to 2026.4.0-beta.2 2026-04-30 02:31:32 +00:00
かっこかり
973b5b50a9 fix(frontend): まれにリアクション・絵文字ピッカーが動作しなくなる問題を修正 (#17349)
* Revert "fix(frontend): popupのりアクティビティがチャンクをまたいで切れる事がある問題を修正"

This reverts commit 0a93f526dd.

* fix: iOS PWA でリアクション・絵文字ピッカーが動作しない問題を修正

Agent-Logs-Url: https://github.com/lqvp/misskey-tempura/sessions/44526368-0e6a-4a94-8991-fcdc094d2b96

Co-authored-by: lqvp <183242690+lqvp@users.noreply.github.com>

* refactor

* fix

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lqvp <183242690+lqvp@users.noreply.github.com>
2026-04-30 11:29:23 +09:00
renovate[bot]
985de915b3 fix(deps): update dependency sanitize-html to v2.17.3 [security] (#17319)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-27 15:17:25 +09:00
かっこかり
0227148c89 Update CHANGELOG for #17347 2026-04-27 10:40:12 +09:00
github-actions[bot]
7bfd85cdba Bump version to 2026.4.0-beta.1 2026-04-27 01:33:17 +00:00
Copilot
21f51be5b7 fix: redirect beta/alpha/rc "what's new" button to GitHub releases page (#17347)
* Initial plan

* fix: redirect beta/alpha/rc update info button to GitHub releases page

Agent-Logs-Url: https://github.com/misskey-dev/misskey/sessions/4ac22dd9-13dd-4ef2-a6f7-d68cfda4a19f

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

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-04-27 10:31:02 +09:00
かっこかり
b45f18cd14 fix(backend): ノート通知で公開範囲を考慮するように (#17335)
* fix(backend): ノート通知で公開範囲を考慮するように

* refactor: remove unused imports

* Update Changelog

* Update Changelog

* fix: フォロワー限定ノートは通知

---------

Co-authored-by: lqvp <183242690+lqvp@users.noreply.github.com>
2026-04-27 10:26:13 +09:00
かっこかり
6176cca0a4 fix(frontend): MenuRadioの指定方法変更 (#17345)
* fix(frontend): MenuRadioの指定方法変更

* fix indent

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-04-27 10:18:03 +09:00
syuilo
9569310adb type: 'radio'なMenuItemが機能しなくなっている問題を修正 (#17344)
* fix

* Update CHANGELOG.md
2026-04-27 10:08:45 +09:00
syuilo
b28338c812 enhance(frontend): 子メニュー表示時のガードがradioでも効くように 2026-04-27 08:42:12 +09:00
かっこかり
0f5da63328 fix(backend): ブロックしたインスタンスのInboxジョブが蓄積し続ける問題を修正 (#17336)
* fix(backend): ブロックしたインスタンスのInboxジョブが蓄積し続ける問題を修正

* refactor

* Upddate changelog

---------

Co-authored-by: lqvp <183242690+lqvp@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-04-26 11:40:55 +09:00
Evan Prodromou
23715c649c fix: change bare activity.actor to getApId(activity.actor) in InboxPr… (#17340)
* fix: change bare activity.actor to getApId(activity.actor) in InboxProcessorService (closes #17338)

* doc: update CHANGELOG.md to note fix for #17338

* fix: additional activity.actor wrappers in ApInboxService

* Update CHANGELOG.md

---------

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-04-26 11:39:16 +09:00
かっこかり
1dc5c60b2b fix(backend): meilisearchを使用していない場合のnoteSearchableScopeの値が誤っている問題を修正 (#17341)
* fix(backend): meilisearchを使用していない場合のnoteSearchableScopeの値が誤っている問題を修正

* Update Changelog
2026-04-26 11:37:26 +09:00
かっこかり
3a3057a1b1 fix(backend): RoleService.getAdministratorIds でユーザーIDが重複する問題を修正 (#17334)
* fix(backend): adminロールが複数付いてても通知が重複しないように

* add tests

* Update Changelog

* ✌️

Co-Authored-by: lqvp <183242690+lqvp@users.noreply.github.com>

---------

Co-authored-by: lqvp <183242690+lqvp@users.noreply.github.com>
2026-04-24 17:56:52 +09:00
github-actions[bot]
8a85ee1d45 Bump version to 2026.4.0-beta.0 2026-04-23 01:13:02 +00:00
かっこかり
c1b73f947c fix(gh): misskey-jsがpublishされない問題を修正 2026-04-22 19:24:31 +09:00
かっこかり
bda98ba1d9 deps: update security dependencies (#17330)
* deps: update security dependencies

* deps: update some major dependencies

* attempt to fix tsconfig

* attempt to fix tsconfig

* attempt to fix tsconfig

* fix build
2026-04-22 11:46:45 +09:00
かっこかり
351fe2f70a fix(frontend): loosen MkButton props type (#17329) 2026-04-21 16:37:59 +09:00
かっこかり
6d15fe32d0 enhance(backend/test): Migrate tests to vitest (#16935)
* wip

* update fake-timers and migrate

* fix

* remove jest-mock

* fix

* fix

* fix

* fix

* attempt to fix unit tests

* attempt to fix e2e tests

* fix federation test [ci skip]

* attempt to fix e2e tests

* fix typecheck

* fix unit tests

* fix

* attempt to fix e2e

* fix

* Revert "attempt to fix e2e"

This reverts commit b7b7b05d85.

* attempt to fix e2e

* revert attempt to fix e2e

* update deps

* update vitest

* migrate

* attempt to fix e2e

* update

* fix

* remove vite swc plugin as oxc parser can handle decorators

* attempt to fix drive/files/create test

* Revert "attempt to fix drive/files/create test"

This reverts commit 4715153375.

* fix: エンドポイントにまつわるテストをunitからe2eに移動

* attempt to fix e2e

* remove swc

* attempt to fix e2e

* Revert "attempt to fix e2e"

This reverts commit 9fb86a4076.

* add logs for debug

* attempt to fix e2e

* Partially revert "attempt to fix e2e"

This reverts commit fb0008c85a.

* attempt to fix test

* fix: attempt to fix test

* Revert "fix: attempt to fix test"

This reverts commit ed2f5c40e8.

* Revert "attempt to fix test"

This reverts commit d7329c46f1.

* attempt to fix e2e

* fix: surpass eventemitter warning by increasing defaultMaxListeners

* attempt to fix e2e

* fix

* fix e2e not ending properly

* exp: add hanging-process reporter for investigation

* Revert "exp: add hanging-process reporter for investigation"

This reverts commit 26851f8282.

* update changelog
2026-04-20 14:57:29 +09:00
かっこかり
1391269a67 Update CHANGELOG.md 2026-04-18 15:02:27 +09:00
github-actions[bot]
86092f2faf Bump version to 2026.4.0-alpha.6 2026-04-16 07:37:51 +00:00
かっこかり
c640aeb27a deps: update security dependencies (#17318) 2026-04-16 16:32:17 +09:00
かっこかり
0be3142d54 fix(backend): devサーバーの起動に失敗することがある問題を修正 (#17317)
* fix(backend): devサーバーの起動に失敗することがある問題を修正?

* fix
2026-04-16 14:33:36 +09:00
かっこかり
37bfcb604f enhance(backend): bundle backend using Rolldown (#17068)
* enhance(backend): bundle backend using rolldown

* fix

* fix [ci skip]

* remove unused build script

* fix

* enhance: 起動からlistenまでかかる時間を減らす (MisskeyIO#1410)

* ✌️

* fix

* update rolldown

* fix(backend): extract static error classes to avoid rolldown design:paramtypes omission

* update rolldown

* Revert "fix(backend): extract static error classes to avoid rolldown design:paramtypes omission"

This reverts commit e2243c9dc3.

* fix

* perf: avoid generating sourcemap in production

* fix

* fix

* fix

* fix paths

* fix

* fix

* fix

* fix

* fix

* enhance: バックエンドの開発サーバー制御をrolldown側で行うように

* remove nodemon

* Update Changelog

* tweak config

* fix

* fix

* fix

* clean up

---------

Co-authored-by: あわわわとーにゅ <17376330+u1-liquid@users.noreply.github.com>
Co-authored-by: bab <mashirohira@gmail.com>
2026-04-16 12:44:50 +09:00
github-actions[bot]
024f8bb102 Bump version to 2026.4.0-alpha.5 2026-04-15 14:12:00 +00:00
Jaehong Kang
277a1ef31f fix(backend): handle relay-delivered Announce activities correctly (#17308)
* fix(backend): handle relay-delivered Announce activities correctly

Relay Announce activities now use the target note URI instead of the
Announce URI for federation allowlist checks, dedup locking, and
existence lookups. Notes delivered via relay are published directly to
the notes stream without creating a renote.

Closes #11056

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

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

---------

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-04-15 23:05:36 +09:00
syuilo
8e536eb4b9 Update CHANGELOG.md 2026-04-15 20:30:23 +09:00
るちーか
360e805638 enhance: アバターデコレーションへのカテゴリの導入 (#17034)
* feat(backend): AvatarDecorationにcategoryを追加し、関連APIのプロパティ・戻り値にも反映

* feat(frontend): アバターデコレーションのカテゴリ設定機能

* chore(frontend): 管理画面とユーザー側の画面で、アバターデコレーションのグループ化のコードをある程度統一

* CHANGELOGを更新

* fix: group-avatar-decorations.tsを使用するよう修正

* chore: コーディング規約への準拠

* 型エラーを解消
2026-04-15 20:29:17 +09:00
かっこかり
c95aef7535 refactor(frontend): ロールポリシーエディタを統合 (#17125)
* refactor(frontend): ロールポリシーエディタを統合

* fix

* fix lint

* clean up

* fix

* fix lint
2026-04-15 17:41:40 +09:00
github-actions[bot]
758a085812 Bump version to 2026.4.0-alpha.4 2026-04-15 02:53:54 +00:00
syuilo
a6de986f83 Update CHANGELOG.md 2026-04-15 11:40:36 +09:00
Copilot
12e590a63f fix(backend): Prevent retry of inbox jobs with role-based validation errors (#17167)
* Initial plan

* Handle too many mentions error in inbox without retry

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

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-04-15 11:39:49 +09:00
かっこかり
a5b1f839ac fix(backend): fix flaky e2e test on recursive drive folder check (#17311) 2026-04-15 11:38:38 +09:00
かっこかり
d7ceaa9c88 fix(backend): attempt to fix flaky e2e test on home timeline streaming (#17312) 2026-04-15 11:37:20 +09:00
かっこかり
55b0fbd172 fix(backend): robots.txtで返却する内容の調整 (#17165)
* fix(backend): robots.txtで返却する内容の調整

* Update Changelog

* fix: add paths

* Update Changleog
2026-04-15 09:56:07 +09:00
かっこかり
6532cb85e7 Update CHANGELOG.md for #17310 [ci skip] 2026-04-15 09:03:53 +09:00
mq1
5dc508346c fix(backend): ULIDを正しく処理できない問題を修正 (#17310)
fix(backend): fix parseUlidFull to correctly handle Crockford Base32 chars W/X/Y/Z
2026-04-15 09:02:43 +09:00
renovate[bot]
c9c6ef2772 chore(deps): update dependency lodash to v4.18.1 [security] (#17278)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-13 23:49:55 +09:00
かっこかり
4d6256e91d deps: Update dependencies (#17304)
* update deps

* update dependencies (major)

* fix: migrate meilisearch

* fix: migrate color-convert types

* fix cypress?

* rollback ts v5 as it is not supported by cypress

* fix fake-timers
2026-04-12 00:57:16 +09:00
github-actions[bot]
cdf0438154 Bump version to 2026.4.0-alpha.3 2026-04-11 05:45:50 +00:00
かっこかり
29cecd750f fix(backend): 存在しないActorに対するDeleteアクティビティは無視するように (#17294)
* fix(backend): 存在しないActorに対するDeleteアクティビティは無視するように

* Update Changelog

* fix

* Revert "fix"

This reverts commit 985feea326.

* fix?

* fix

* fix

* fix

* fix

* refactor: remove unused imports

* fix

* Update CHANGELOG.md [ci skip]
2026-04-11 14:45:11 +09:00
FINEARCHS
68e3476a16 fix(frontend): ドライブへの画像アップロード時にファイル名の変更が無視される不具合を修正 (#17302)
* ドライブの実ファイル名ではなくsuffixを保持するように

* MkUploaderItemsでファイル名が圧縮後の拡張子も含めて表示されるように

* Apply suggestion from @kakkokari-gtyih

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

* changelog

---------

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-04-11 14:23:42 +09:00
かっこかり
3cb003366f fix(frontend): 連合が無効化されたサーバーでInstance Tickerの設定が中途半端に消えている問題を修正 (#17303)
* fix(frontend): 連合が無効化されたサーバーでInstance Tickerの設定が中途半端に消えている問題を修正

* Update Changelog
2026-04-11 13:16:55 +09:00
danominium
787de92c2f fix(frontend): bannerUrl が空の場合に /about ページで /null へのアクセスが発生する問題を修正 (#17299)
fix(frontend): bannerUrl が空の場合に /about ページで /null へのリクエストが発生する問題を修正

bannerUrl が空の場合は 背景画像を設定しない。

about.overview.vue の background-image: url("null"); によって /null へのリクエストが発生してしまうため。
2026-04-11 02:04:39 +09:00
syuilo
22577e2134 perf(frontend): improve about#emojis rendering performance 2026-04-09 14:28:04 +09:00
github-actions[bot]
0355420c81 Bump version to 2026.4.0-alpha.2 2026-04-09 05:23:06 +00:00
かっこかり
4750980cef enhance(frontend): update vite to v8 再 (#17289)
* Revert "Revert "deps: Update vite to v8" (#17283)"

This reverts commit a18c909ba3.

* fix(frontend): popupのりアクティビティがチャンクをまたいで切れる事がある問題を修正

* update vite/rolldown
2026-04-09 14:20:07 +09:00
かっこかり
92e0e8edf7 refactor(frontend): refactor deck events (#17290) 2026-04-08 14:45:30 +09:00
かっこかり
5cb3a91b15 fix(frontend): follow-up of #17282 2026-04-08 10:48:07 +09:00
かっこかり
60018d16da enhance(frontend): niraxにテストを追加 (#17287)
* fix(frontend): follow-up of #13509

* fix: fix use of inappropriate method

* enhance(frontend): niraxにテストを追加
2026-04-07 22:03:08 +09:00
github-actions[bot]
b63984893e Bump version to 2026.4.0-alpha.1 2026-04-07 11:42:38 +00:00
かっこかり
d4a5048aae fix(frontend): routerがmatchAllに入った際に一度 location.href による遷移を試みる挙動に関する修正 (#17281)
* fix(frontend): follow-up of #13509

* fix: fix use of inappropriate method

* Update CHANGELOG.md [ci skip]
2026-04-07 20:35:06 +09:00
syuilo
b9923d0a23 New Crowdin updates (#17260)
* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Lao)

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

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Catalan)

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

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

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Italian)
2026-04-07 19:30:26 +09:00
syuilo
38be94b2a3 enhance(frontend): improve nested popup menu ux (#17187)
* wip

* Update MkMenu.vue

* wip

* wip

* Update MkMenu.vue

* wip

* Update MkMenu.vue

* Update MkMenu.vue

* Update MkMenu.vue

* Update MkMenu.vue

* Update MkMenu.vue

* Update MkMenu.vue

* Update MkMenu.vue

* Update MkMenu.vue

* 💢

* Update MkMenu.vue

* Update MkMenu.vue

* Update MkMenu.vue
2026-04-07 16:52:30 +09:00
かっこかり
ae34578c6f refactor(frontend): MkButtonのprops等整理 (#17282)
* refactor(frontend): MkButtonのprops等整理

* fix
2026-04-06 22:28:44 +09:00
github-actions[bot]
367766d864 Bump version to 2026.4.0-alpha.0 2026-04-06 11:16:40 +00:00
かっこかり
a18c909ba3 Revert "deps: Update vite to v8" (#17283)
Revert "deps: Update vite to v8 (#17238)"

This reverts commit e601fcb729.
2026-04-06 20:15:57 +09:00
かっこかり
0b7b59f1e2 enhance(frontend): チャンネル指定リノートでリノート先のチャンネルに移動できるように (#17280)
* enhance(frontend): チャンネル指定リノートでリノート先のチャンネルに移動できるように

* Update Changelog

* fix condition

* refactor
2026-04-05 17:22:17 +09:00
Evan Prodromou
8169c57bd1 fix(backend): handle array or string in alsoKnownAs (#17275)
* fix: handle array or string in alsoKnownAs, closes #17274

* style: use more idiomatic toArray() for UserEntityService handling of alsoKnownAs

* fix: handle array-valued or unwrapped alsoKnownAs in ApPersonService

* doc: note about bugfix for alsoKnownAs
2026-04-05 00:43:37 +09:00
かっこかり
e601fcb729 deps: Update vite to v8 (#17238)
* deps: Update vite to v8

* fix

* migrate some plugins to rolldown-based

* fix broken lockfile

* wip

* update rolldown

* override rolldown version

* perf

* spdx

* fix

* update vite to 8.0.1

* chore: rewrite rollup-plugin-unwind-css-module-class-name with MagicString

* format

* swap type definitions

* replace using MagicString

* provided magicString

* fix code style

* fix

* fix

* fix

* fix

* fix

---------

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

* fix: lint fixes

* swap sass with sass-embedded

* fix lint

* fix: インライン化されたVue SFC出力に対してCSS Module定義削除が効かないのを修正

* fix

* fix: バックエンドのCSS読み込みの方法が悪いのを修正

* fix: 使用されないpreloadを削除

* fix lint [ci skip]

* Apply suggestion from @syuilo

* Add comment in pnpm-workspace.yaml [ci skip]

* update vite/rolldown

* remove magic-string

---------

Co-authored-by: cm-ayf <cm.ayf2734@gmail.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-04-01 17:05:57 +09:00
Copilot
5361a3819b fix(backend): /api-doc にアクセスできない問題を修正 (#17267)
* Initial plan

* fix: fix /api-doc returning 404 after backend minification (#17266)

Agent-Logs-Url: https://github.com/misskey-dev/misskey/sessions/8d7d0585-55da-412f-a8ee-dde1b6565026

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

* enhance: API DocのHTMLをJSXで生成するように

* Update Changelog

* chore: remove unused imports [ci skip]

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
2026-04-01 14:43:34 +09:00
かっこかり
dbc5fe2454 deps: update dependencies (#17263)
* deps: update dependencies

* fix?

* fix

* Update AiService.ts

* fix

* update deps
2026-04-01 12:16:36 +09:00
github-actions[bot]
7bd7e5c4db [skip ci] Update CHANGELOG.md (prepend template) 2026-03-31 12:14:45 +00:00
github-actions[bot]
b97683cdb2 Release: 2026.3.2 2026-03-31 12:14:38 +00:00
github-actions[bot]
ece9679cc4 Bump version to 2026.3.2-beta.0 2026-03-23 11:14:32 +00:00
かっこかり
c5fd36094d enhance(frontend): ウィンドウの初期サイズを画面サイズから動的に決めるように (#17257)
* enhance(frontend): ウィンドウの初期サイズを画面サイズから動的に決めるように

* Update Changelog

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-03-22 13:32:45 +09:00
かっこかり
b5a6e12439 fix(frontend): ウィンドウのタイトルをクリックしても最前面に出ないのを修正 (#17255)
* fix(frontend): ウィンドウのタイトルをクリックしても最前面に出ないのを修正

* Update Changelog
2026-03-22 13:21:14 +09:00
github-actions[bot]
1d171aeb96 Bump version to 2026.3.2-alpha.2 2026-03-21 03:32:26 +00:00
かっこかり
b826a16231 fix(backend): 初期読込時に必要なフロントエンドのアセットがすべて読み込まれていない問題を修正 (#17254)
* fix: バックエンドのCSS読み込みの方法が悪いのを修正

* fix: 使用されないpreloadを削除

* Update Changelog

* add comments
2026-03-21 12:26:50 +09:00
renovate[bot]
9e38288da5 chore(deps): update [github actions] update dependencies (#17253)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-20 20:24:58 +09:00
かっこかり
57ed2914d1 deps: update dependencies (#17252) [ci skip] 2026-03-20 20:08:58 +09:00
かっこかり
54e94263a8 fix(backend): チャンネルミュートを有効にしている際にノートの閲覧ができなくなることがある問題を修正 (#17251)
* fix(backend): チャンネルミュート使用時にユーザーのノート一覧読み込みに失敗する問題を修正

* more fix

* Update Changelog
2026-03-20 19:11:56 +09:00
4ster1sk
0e4732180f fix(frontend): Unicode絵文字のリアクションが表示に反映されないことがある問題の修正 (#17250) 2026-03-20 17:15:59 +09:00
github-actions[bot]
df1fa8b90a Bump version to 2026.3.2-alpha.1 2026-03-20 07:36:34 +00:00
syuilo
45df44899a New Crowdin updates (#17234)
* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Portuguese)

* New translations ja-jp.yml (Turkish)

* 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 (Thai)

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Turkish)

* New translations ja-jp.yml (Turkish)

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Czech)
2026-03-20 16:35:19 +09:00
かっこかり
2904b5a342 fix(backend): fix streaming note hiding logic (#17248)
* fix(backend): fix streaming note hiding logic

* Update Changelog

* refactor: avoid using generator function

---------

Co-authored-by: Acid Chicken <root@acid-chicken.com>
2026-03-20 14:01:27 +09:00
かっこかり
f16ef2ef56 fix(frontend): 絵文字パレットが空の状態でMisskeyについてのページが閲覧できない問題を修正 (#17243)
* fix(frontend): 絵文字パレットが空の状態でMisskeyについてのページが閲覧できない問題を修正

* Update Changelog

* extension

* add comment
2026-03-18 21:34:28 +09:00
かっこかり
a3b0dc91e8 fix(backend): Acceptヘッダを署名の対象に含めないように (#17240)
* fix(backend): Acceptヘッダを署名の対象に含めないように

* Update Changelog
2026-03-16 13:42:51 +09:00
syuilo
07bbc5ab33 enhance(frontend): improve zoomLines effect 2026-03-11 15:59:00 +09:00
syuilo
bbffa563d9 refactor(frontend): refactor blur.glsl 2026-03-11 10:35:59 +09:00
github-actions[bot]
1eefd8d3f0 Bump version to 2026.3.2-alpha.0 2026-03-09 09:32:58 +00:00
かっこかり
589a3e229b Update CHANGELOG.md 2026-03-09 18:25:04 +09:00
renovate[bot]
9377e94072 chore(deps): update [docker] update dependencies (#17203)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-09 18:22:09 +09:00
かっこかり
bc19359876 fix(backend): follow-up of 47db963 (#17231)
fix(backend): follow-up of 47db963d8d
2026-03-09 18:21:25 +09:00
syuilo
47db963d8d chore(backend): 非ログイン状態のケア 2026-03-09 13:57:59 +09:00
syuilo
277716bc49 fix(backend): 自分の行ったフォロワー限定投稿または指名投稿に自分自身でリアクションなど行った場合のイベントが流れない問題を修正 2026-03-09 13:51:56 +09:00
syuilo
db5cc6c058 Revert "fix(backend): 自分の行ったフォロワー限定投稿または指名投稿に自分自身でリアクションなど行った場合のイベントが流れない問題を修正"
This reverts commit 06f8dd39ca.
2026-03-09 13:51:18 +09:00
syuilo
06f8dd39ca fix(backend): 自分の行ったフォロワー限定投稿または指名投稿に自分自身でリアクションなど行った場合のイベントが流れない問題を修正 2026-03-09 13:50:10 +09:00
syuilo
307e90427a format 2026-03-09 13:48:32 +09:00
github-actions[bot]
d083855f7f [skip ci] Update CHANGELOG.md (prepend template) 2026-03-09 01:03:01 +00:00
github-actions[bot]
4ec56ba9f6 Release: 2026.3.1 2026-03-09 01:02:56 +00:00
かっこかり
5e62ad160e Update CHANGELOG.md 2026-03-09 09:36:02 +09:00
github-actions[bot]
e554e72b55 Bump version to 2026.3.1-alpha.0 2026-03-09 00:34:23 +00:00
かっこかり
25783425e1 deps: update dependencies (#17229)
* deps: update dependencies

* update lockfile
2026-03-09 09:09:09 +09:00
かっこかり
582ebe422c Update CHANGELOG.md 2026-03-09 08:24:52 +09:00
かっこかり
06e74508a2 Merge commit from fork
* Tighten security on channels

* Fix main channel

* add comments, improve typing

* fix indent

* fix: missing membership checks in chat-room

* remove unnecessary check in chat-user

* fix

* refactor: use exists

* fix

---------

Co-authored-by: Julia Johannesen <julia@insertdomain.name>
2026-03-09 08:18:14 +09:00
かっこかり
b361a10c48 Merge commit from fork
* Tighten security in `HashtagChannel`

* Add isNoteVisibleForMe in stream channel

Co-Authored-By: Julia Johannesen <julia@insertdomain.name>

* Tighten note visibility checks in WebSocket (No.1)

* refactor

* Fix main channel

Co-Authored-By: Julia Johannesen <julia@insertdomain.name>

* fix typo

* fix missing lockdown (requireSigninToViewContents) checks

* fix(backend): streamingでのロックダウン挙動修正

* fix: 引用リノートを無条件で隠していた問題を修正

* fix: 引用リノートを単純にリノート場合に内容が見えることがある問題を修正

* refac

* fix

* fix

* fix

* Update docs

---------

Co-authored-by: Julia Johannesen <julia@insertdomain.name>
Co-authored-by: KanariKanaru <93921745+kanarikanaru@users.noreply.github.com>
2026-03-09 08:15:31 +09:00
syuilo
a07dc589e7 Merge commit from fork
Co-authored-by: Julia Johannesen <197614925+juliajohannesen@users.noreply.github.com>
2026-03-09 08:14:12 +09:00
かっこかり
b5d399674a Merge commit from fork
Co-authored-by: Julia Johannesen <julia@insertdomain.name>
2026-03-09 08:12:20 +09:00
かっこかり
e074a91189 Merge commit from fork 2026-03-09 08:11:25 +09:00
renovate[bot]
29c357a988 chore(deps): update [github actions] update dependencies (#17202)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-07 14:39:40 +09:00
かっこかり
ac45781ef9 deps: security dependency updates [ci skip] (#17225) 2026-03-07 14:35:10 +09:00
anatawa12
5d78b320de chore(backend): delete unused ChannelsService (#17218) 2026-03-05 21:57:07 +09:00
syuilo
a025209602 fix(frontend): 意図せず参照渡しになり得る箇所をdeepCloneするように修正 (#17207)
現状は(おそらく)問題は起きていないが今後問題が発現するシチュエーションが出てくる可能性がある
2026-03-05 20:38:42 +09:00
github-actions[bot]
d5b86a8b49 [skip ci] Update CHANGELOG.md (prepend template) 2026-03-05 10:56:52 +00:00
github-actions[bot]
1a62318bcc Release: 2026.3.0 2026-03-05 10:56:46 +00:00
syuilo
9c30c0915a Update CHANGELOG.md 2026-03-05 19:35:06 +09:00
github-actions[bot]
53b9abd098 Bump version to 2026.3.0-alpha.0 2026-03-05 10:28:23 +00:00
かっこかり
3980b2ca55 fix: review fixes (#17208)
* fix: OAuthのContent-Typeを正しく判定するように

* fix(frontend): fix outdated comments

* fix: storagePersistenceのtop-level awaitを解消

* fix

* fix(frontend): add comment

Co-Authored-By: anatawa12 <anatawa12@icloud.com>

* fix

* fix: rename `users/get-following-users-by-birthday`

* fix: fix types

* Update MkForm.vue

* refactor utility/storage.ts

---------

Co-authored-by: anatawa12 <anatawa12@icloud.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-03-05 19:24:30 +09:00
syuilo
810faa8e5d New Crowdin updates (#17097)
* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Korean)

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

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Korean)

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

* New translations ja-jp.yml (Spanish)

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

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Italian)

* 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 (Catalan)

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Thai)

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

* New translations ja-jp.yml (Chinese Traditional)
2026-02-28 15:48:03 +09:00
果物リン
ae1304d645 perf: MFM MkA, MkLink, MkSparkle の slot 指定方法を修正 (#17156) 2026-02-28 15:47:29 +09:00
かっこかり
676e164634 deps: Security dependency updates (#17198)
* update deps

* update security deps
2026-02-28 13:56:34 +09:00
かっこかり
71f50d3280 fix(frontend): secure contextではない場合はストレージ永続化を確認しないように (#17189)
* fix(frontend): secure contextではない場合はストレージ永続化を確認しないように

* Update Changelog
2026-02-23 16:53:41 +09:00
github-actions[bot]
d4cd47f455 Bump version to 2026.2.0-beta.0 2026-02-22 10:11:10 +00:00
かっこかり
22a6935468 deps: update dependencies (#17184)
* update deps

* fix
2026-02-22 19:06:33 +09:00
syuilo
264068c58b chore(frontend): getHexで不正な値が返される可能性があるのを修正 2026-02-22 13:56:20 +09:00
かっこかり
97f7659bac fix(frontend): ウィジェットの表示更新がおかしくなる問題を修正 (#17175)
* fix(frontend): ウィジェットの表示更新がおかしくなる問題を修正

* fix: keyがついていない箇所全てを修正

* Revert "fix: keyがついていない箇所全てを修正"

This reverts commit 7f4d90feea.

* Revert "fix(frontend): ウィジェットの表示更新がおかしくなる問題を修正"

This reverts commit 38a000c904.

* fix
2026-02-16 19:56:48 +09:00
かっこかり
41620600cc fix(frontend): ウィンドウのドラッグ・サイズ変更のポインターをキャプチャするように (#17159)
* fix(frontend): ウィンドウのドラッグ・サイズ変更のポインターをキャプチャするように

* Update Changelog

* fix
2026-02-16 19:23:30 +09:00
かっこかり
b5121dc70e deps: update dependencies (#17174)
* deps: update dependencies

* update

* run pnpm dedupe

* update tsgo

* rollback tsgo
2026-02-16 12:02:36 +09:00
かっこかり
bd992661f4 Update CHANGELOG.md 2026-02-15 15:50:42 +09:00
かっこかり
799f5ab504 enhance(frontend): いくつかのtodoの解消 (#17154) 2026-02-15 12:08:10 +09:00
github-actions[bot]
d4bc753e72 Bump version to 2026.2.0-alpha.0 2026-02-15 03:04:38 +00:00
かっこかり
af40eb4d31 fix: user-tagページでユーザーが重複して読み込まれるのを修正 (#17163)
* fix: user-tagをページネーションに対応させる

* update changelog
2026-02-15 11:50:23 +09:00
かっこかり
a22b82c414 fix(frontend): フォロー承認通知でフォローされた際のメッセージ内の絵文字が表示されない問題を修正 (#17164)
* fix(frontend): フォロー承認通知でフォローされた際のメッセージ内の絵文字が表示されない問題を修正

* update changelog
2026-02-15 11:49:37 +09:00
かっこかり
28f5b2f173 fix(frontend): ぼかし・塗りつぶし・モザイクの画像エフェクトを修正 (#17155)
* fix(frontend): ぼかし・塗りつぶし・モザイクの画像エフェクトを修正

* Update Changelog

* fix changelog [ci skip]

* fix changelog [ci skip]

* tweak

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2026-02-08 09:48:04 +09:00
果物リン
c86cbfcfba worker-multi-dispatch のコメントを抑制 (#17157) 2026-02-07 17:46:17 +09:00
かっこかり
00cbd1e6db fix(frontend): ノートの詳細表示でリアクション一覧が全件表示されない問題を修正 (#17137)
* fix(frontend): ノートの詳細表示でリアクション一覧が全件表示されない問題を修正

* Update Changelog
2026-02-02 22:37:24 +09:00
かっこかり
65e51463c8 fix(frontend): CSSの指定が誤っている問題を修正 (#17135) 2026-01-31 22:38:16 +09:00
Ken_Cir
39362f78a6 fix(backend): inconsistent permissions for /admin/get-user-ips (#17136)
* fix(backend): inconsistent permissions for /admin/get-user-ips

* Update Changelog
2026-01-31 22:37:48 +09:00
renovate[bot]
d2154214ba fix(deps): update dependency tar to v7.5.7 [security] (#17104)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-29 18:18:34 +09:00
renovate[bot]
97312b97f8 chore(deps): update pnpm to v10.28.2 [security] (#17133)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-29 10:53:08 +09:00
poppingmoon
5e2b041f84 fix(frontend): remove ensureSignin from reversi game page (#17130) 2026-01-28 20:44:58 +09:00
syuilo
ec97f49919 Create copilot-instructions.md 2026-01-28 19:42:43 +09:00
かっこかり
4910fff7fb fix(frontend): mCaptchaが動作しない問題を修正 (#17127)
* fix(frontend): mCaptchaが動作しない問題を修正

* Update Changelog

* remove mcaptcha vanila glue
2026-01-28 11:55:35 +09:00
かっこかり
fc7655c808 deps: update dependencies [ci skip] (#17126)
* deps: update dependencies

* update vunerable packages as well
2026-01-24 02:41:10 +09:00
syuilo
ae2ac9d50f fix(frontend): 投稿フォームのアップロードファイルを右クリックしたときの挙動がおかしいのを修正 2026-01-22 20:31:42 +09:00
syuilo
8932492fd3 enhance(frontend): 添付画像のメニューを右クリックでも呼び出せるように 2026-01-22 20:29:11 +09:00
500 changed files with 11376 additions and 23277 deletions

View File

@@ -36,7 +36,7 @@ services:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: misskey
volumes:
- postgres-data:/var/lib/postgresql/data
- postgres-data:/var/lib/postgresql
healthcheck:
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
interval: 5s

View File

@@ -19,7 +19,6 @@
"editorconfig.editorconfig",
"dbaeumer.vscode-eslint",
"Vue.volar",
"Orta.vscode-jest",
"dbaeumer.vscode-eslint",
"mrmlnc.vscode-json5"
]

3
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,3 @@
# Copilot Instructions for Misskey
- en-US.yml を編集しないでください。

View File

@@ -34,9 +34,6 @@ updates:
patterns:
- "storybook*"
- "@storybook/*"
swc-core:
patterns:
- "@swc/core*"
typescript-eslint:
patterns:
- "@typescript-eslint/*"

View File

@@ -16,13 +16,13 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6.0.1
uses: actions/checkout@v6.0.2
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Setup Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'

View File

@@ -12,9 +12,9 @@ jobs:
steps:
- name: Checkout head
uses: actions/checkout@v6.0.1
uses: actions/checkout@v6.0.2
- name: Setup Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'

View File

@@ -18,18 +18,18 @@ jobs:
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
steps:
- name: checkout
uses: actions/checkout@v6.0.1
uses: actions/checkout@v6.0.2
with:
submodules: true
persist-credentials: false
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- name: setup pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@v6
- name: setup node
id: setup-node
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: pnpm
@@ -53,7 +53,7 @@ jobs:
# packages/misskey-js/generator/built/autogen
- name: Upload Generated
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: generated-misskey-js
path: packages/misskey-js/generator/built/autogen
@@ -66,14 +66,14 @@ jobs:
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
steps:
- name: checkout
uses: actions/checkout@v6.0.1
uses: actions/checkout@v6.0.2
with:
submodules: true
persist-credentials: false
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- name: Upload From Merged
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: actual-misskey-js
path: packages/misskey-js/src/autogen
@@ -86,13 +86,13 @@ jobs:
pull-requests: write
steps:
- name: download generated-misskey-js
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
name: generated-misskey-js
path: misskey-js-generated
- name: download actual-misskey-js
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
name: actual-misskey-js
path: misskey-js-actual

View File

@@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6.0.1
uses: actions/checkout@v6.0.2
- name: Check version
run: |
if [ "$(jq -r '.version' package.json)" != "$(jq -r '.version' packages/misskey-js/package.json)" ]; then

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6.0.1
uses: actions/checkout@v6.0.2
- name: Check
run: |
counter=0

View File

@@ -10,7 +10,7 @@ jobs:
check_copyright_year:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
- run: |
if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then
echo "Please change copyright year!"

View File

@@ -28,7 +28,7 @@ jobs:
wait_time: ${{ steps.get-wait-time.outputs.wait_time }}
steps:
- name: Checkout
uses: actions/checkout@v6.0.1
uses: actions/checkout@v6.0.2
- name: Check allowed users
id: check-allowed-users

View File

@@ -27,17 +27,17 @@ jobs:
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Check out the repo
uses: actions/checkout@v6.0.1
uses: actions/checkout@v6.0.2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Log in to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: .
push: true
@@ -53,7 +53,7 @@ jobs:
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
@@ -66,15 +66,15 @@ jobs:
- build
steps:
- name: Download digests
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

View File

@@ -32,23 +32,23 @@ jobs:
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Check out the repo
uses: actions/checkout@v6.0.1
uses: actions/checkout@v6.0.2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY_IMAGE }}
tags: ${{ env.TAGS }}
- name: Log in to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push to Docker Hub
id: build
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: .
push: true
@@ -64,7 +64,7 @@ jobs:
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
@@ -77,21 +77,21 @@ jobs:
- build
steps:
- name: Download digests
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY_IMAGE }}
tags: ${{ env.TAGS }}
- name: Login to Docker Hub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

View File

@@ -17,7 +17,7 @@ jobs:
DOCKLE_VERSION: 0.4.15
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
- name: Download and install dockle v${{ env.DOCKLE_VERSION }}
run: |

View File

@@ -25,14 +25,14 @@ jobs:
ref: refs/pull/${{ github.event.number }}/merge
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
ref: ${{ matrix.ref }}
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Use Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -48,7 +48,7 @@ jobs:
- name: Copy API.json
run: cp packages/backend/built/api.json ${{ matrix.api-json-name }}
- name: Upload Artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: api-artifact-${{ matrix.api-json-name }}
path: ${{ matrix.api-json-name }}
@@ -61,7 +61,7 @@ jobs:
PR_NUMBER: ${{ github.event.number }}
run: |
echo "$PR_NUMBER" > ./pr_number
- uses: actions/upload-artifact@v6
- uses: actions/upload-artifact@v7
with:
name: api-artifact-pr-number
path: pr_number

View File

@@ -35,19 +35,19 @@ jobs:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:7
image: redis:8
ports:
- 56312:6379
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
ref: ${{ matrix.ref }}
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Use Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -67,7 +67,7 @@ jobs:
# Start the server and measure memory usage
node packages/backend/scripts/measure-memory.mjs > ${{ matrix.memory-json-name }}
- name: Upload Artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: memory-artifact-${{ matrix.memory-json-name }}
path: ${{ matrix.memory-json-name }}
@@ -81,7 +81,7 @@ jobs:
PR_NUMBER: ${{ github.event.number }}
run: |
echo "$PR_NUMBER" > ./pr_number
- uses: actions/upload-artifact@v6
- uses: actions/upload-artifact@v7
with:
name: memory-artifact-pr-number
path: pr_number

View File

@@ -15,7 +15,6 @@ on:
- packages/sw/**
- packages/misskey-js/**
- packages/misskey-bubble-game/**
- packages/misskey-mahjong/**
- packages/misskey-reversi/**
- packages/shared/eslint.config.js
- .github/workflows/lint.yml
@@ -30,7 +29,6 @@ on:
- packages/sw/**
- packages/misskey-js/**
- packages/misskey-bubble-game/**
- packages/misskey-mahjong/**
- packages/misskey-reversi/**
- packages/shared/eslint.config.js
- .github/workflows/lint.yml
@@ -38,13 +36,13 @@ jobs:
pnpm_install:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
fetch-depth: 0
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
- uses: actions/setup-node@v6.1.0
uses: pnpm/action-setup@v6.0.3
- uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -66,25 +64,24 @@ jobs:
- sw
- misskey-js
- misskey-bubble-game
- misskey-mahjong
- misskey-reversi
env:
eslint-cache-version: v1
eslint-cache-path: ${{ github.workspace }}/node_modules/.cache/eslint-${{ matrix.workspace }}
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
fetch-depth: 0
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
- uses: actions/setup-node@v6.1.0
uses: pnpm/action-setup@v6.0.3
- uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
- run: pnpm i --frozen-lockfile
- name: Restore eslint cache
uses: actions/cache@v4.3.0
uses: actions/cache@v5.0.5
with:
path: ${{ env.eslint-cache-path }}
key: eslint-${{ env.eslint-cache-version }}-${{ matrix.workspace }}-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ github.ref_name }}-${{ github.sha }}
@@ -103,13 +100,13 @@ jobs:
- sw
- misskey-js
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
fetch-depth: 0
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
- uses: actions/setup-node@v6.1.0
uses: pnpm/action-setup@v6.0.3
- uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'

View File

@@ -16,13 +16,13 @@ jobs:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
fetch-depth: 0
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
- uses: actions/setup-node@v6.1.0
uses: pnpm/action-setup@v6.0.3
- uses: actions/setup-node@v6.4.0
with:
node-version-file: ".node-version"
cache: "pnpm"

View File

@@ -16,18 +16,21 @@ jobs:
id-token: write
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Use Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
# see https://docs.github.com/actions/use-cases-and-examples/publishing-packages/publishing-nodejs-packages#publishing-packages-to-the-npm-registry
registry-url: 'https://registry.npmjs.org'
# Ensure npm 11.5.1 or later is installed
- name: Update npm
run: npm install -g npm@latest
- name: Publish package
run: |
pnpm i --frozen-lockfile

View File

@@ -16,7 +16,7 @@ jobs:
# api-artifact
steps:
- name: Download artifact
uses: actions/github-script@v8.0.0
uses: actions/github-script@v9
with:
script: |
const fs = require('fs');
@@ -60,7 +60,7 @@ jobs:
- name: Echo full diff
run: cat ./api-full.json.diff
- name: Upload full diff to Artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: api-artifact
path: |

View File

@@ -15,7 +15,7 @@ jobs:
steps:
- name: Download artifact
uses: actions/github-script@v8.0.0
uses: actions/github-script@v9
with:
script: |
const fs = require('fs');

View File

@@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- name: Reply
uses: actions/github-script@v8
uses: actions/github-script@v9
with:
script: |
const body = `To dev team (@misskey-dev/dev):

View File

@@ -22,12 +22,12 @@ jobs:
NODE_OPTIONS: "--max_old_space_size=7168"
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
if: github.event_name != 'pull_request_target'
with:
fetch-depth: 0
submodules: true
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
if: github.event_name == 'pull_request_target'
with:
fetch-depth: 0
@@ -37,9 +37,9 @@ jobs:
if: github.event_name == 'pull_request_target'
run: git checkout "$(git rev-list --parents -n1 HEAD | cut -d" " -f3)"
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Use Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -47,7 +47,7 @@ jobs:
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
- name: Build dependent packages
run: pnpm -F misskey-js -F misskey-bubble-game -F misskey-mahjong -F misskey-reversi build
run: pnpm -F misskey-js -F misskey-bubble-game -F misskey-reversi build
- name: Build storybook
run: pnpm --filter frontend build-storybook
- name: Publish to Chromatic
@@ -90,7 +90,7 @@ jobs:
env:
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
- name: Notify that Chromatic detects changes
uses: actions/github-script@v8.0.0
uses: actions/github-script@v9
if: github.event_name != 'pull_request_target' && steps.chromatic_push.outputs.success == 'false'
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -102,7 +102,7 @@ jobs:
body: 'Chromatic detects changes. Please [review the changes on Chromatic](https://www.chromatic.com/builds?appId=6428f7d7b962f0b79f97d6e4).'
})
- name: Upload Artifacts
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: storybook
path: packages/frontend/storybook-static

View File

@@ -45,11 +45,11 @@ jobs:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:7
image: redis:8
ports:
- 56312:6379
meilisearch:
image: getmeili/meilisearch:v1.3.4
image: getmeili/meilisearch:v1.42.1
ports:
- 57712:7700
env:
@@ -57,17 +57,17 @@ jobs:
MEILI_ENV: development
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Get current date
id: current-date
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
- name: Setup and Restore ffmpeg/ffprobe Cache
id: cache-ffmpeg
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: |
/usr/local/bin/ffmpeg
@@ -93,7 +93,7 @@ jobs:
fi
done
- name: Use Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: ${{ matrix.node-version-file }}
cache: 'pnpm'
@@ -107,7 +107,7 @@ jobs:
- name: Test
run: pnpm --filter backend test-and-coverage
- name: Upload to Codecov
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json
@@ -131,18 +131,18 @@ jobs:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:7
image: redis:8
ports:
- 56312:6379
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Use Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: ${{ matrix.node-version-file }}
cache: 'pnpm'
@@ -156,7 +156,7 @@ jobs:
- name: Test
run: pnpm --filter backend test-and-coverage:e2e
- name: Upload to Codecov
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json
@@ -180,16 +180,16 @@ jobs:
POSTGRES_HOST_AUTH_METHOD: trust
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Get current date
id: current-date
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
- name: Use Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: ${{ matrix.node-version-file }}
cache: 'pnpm'

View File

@@ -36,13 +36,13 @@ jobs:
with:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Get current date
id: current-date
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
- name: Setup and Restore ffmpeg/ffprobe Cache
id: cache-ffmpeg
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: |
/usr/local/bin/ffmpeg
@@ -68,7 +68,7 @@ jobs:
fi
done
- name: Use Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: ${{ matrix.node-version-file }}
cache: 'pnpm'

View File

@@ -28,13 +28,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Use Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -48,7 +48,7 @@ jobs:
- name: Test
run: pnpm --filter frontend test-and-coverage
- name: Upload Coverage
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/frontend/coverage/coverage-final.json
@@ -71,12 +71,12 @@ jobs:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:7
image: redis:8
ports:
- 56312:6379
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
submodules: true
# https://github.com/cypress-io/cypress-docker-images/issues/150
@@ -86,9 +86,9 @@ jobs:
#- uses: browser-actions/setup-firefox@latest
# if: ${{ matrix.browser == 'firefox' }}
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Use Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -105,7 +105,7 @@ jobs:
- name: Cypress install
run: pnpm exec cypress install
- name: Cypress run
uses: cypress-io/github-action@v6
uses: cypress-io/github-action@v7.1.9
timeout-minutes: 15
with:
install: false
@@ -113,12 +113,12 @@ jobs:
wait-on: 'http://localhost:61812'
headed: true
browser: ${{ matrix.browser }}
- uses: actions/upload-artifact@v6
- uses: actions/upload-artifact@v7
if: failure()
with:
name: ${{ matrix.browser }}-cypress-screenshots
path: cypress/screenshots
- uses: actions/upload-artifact@v6
- uses: actions/upload-artifact@v7
if: always()
with:
name: ${{ matrix.browser }}-cypress-videos

View File

@@ -22,13 +22,13 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6.0.1
uses: actions/checkout@v6.0.2
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Setup Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -48,7 +48,7 @@ jobs:
CI: true
- name: Upload Coverage
uses: codecov/codecov-action@v5
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/misskey-js/coverage/coverage-final.json

View File

@@ -16,13 +16,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Use Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'

View File

@@ -17,13 +17,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.1
- uses: actions/checkout@v6.0.2
with:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4.2.0
uses: pnpm/action-setup@v6.0.3
- name: Use Node.js
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6.4.0
with:
node-version-file: '.node-version'
cache: 'pnpm'

View File

@@ -1,12 +1,93 @@
## 2026.1.0
### Note
- `users/following``birthday` プロパティは非推奨になりました。代わりに `users/get-following-birthday-users` をご利用ください。
## 2026.5.1
### General
- Enhance: 「もうすぐ誕生日のユーザー」ウィジェットで、誕生日が至近のユーザーも表示できるように
- Enhance: チャンネルの作成の可否をロールポリシーで制御できるように
- Fix: `.devcontainer/compose.yml`のvolumeのマウントパスを修正
### Client
- Enhance: ノートの詳細表示での公開範囲の表示を改善
(Cherry-picked from https://github.com/kokonect-link/cherrypick/commit/ecc75563f4e428b66adccc379bf317b5b21ed8e6)
- Fix: ロール設定画面でロールをアサイン/アサイン解除した際、リロードしなくても画面に反映されるよう修正
### Server
- Fix: ID生成アルゴリズムにULIDを使用している場合に通知が約10秒遅延する問題を修正
- Fix: 公開範囲がフォロワーの投稿が通知されない問題を修正
- Fix: URLプレビューが動作しない問題を修正
## 2026.5.0
### General
- Enhance: アバターデコレーションにカテゴリを設定できるように
### Client
- Enhance: チャンネル指定リノートでリノート先のチャンネルに移動できるように
- Enhance: ベータ版でのアップデート時のダイアログの更新情報リンクをGitHubのReleasesページに遷移するようにし、正しく閲覧できるように
- Fix: 一部のページ内リンクが正しく動作しない問題を修正
- Fix: ドライブへの画像アップロード時にファイル名の変更が無視される不具合を修正
- Fix: 連合が無効化されたサーバーで一部の設定項目が空欄で表示される問題を修正
- Fix: オーディオ、動画の再生速度メニューが開けない問題を修正
### Server
- Enhance: メモリ使用量を削減
- Enhance: 起動の高速化
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1410)
- Enhance: バックエンドの開発モード時の安定性向上
- Enhance: バックエンドビルド・テスト時に使用する依存関係の整理swc/esbuild→Rolldown, Jest→Vitest
- Fix: ファイルシステムを用いる処理におけるパスの取り扱いを改善
- Fix: `/api-doc` にアクセスできない問題を修正
- Fix: support `alsoKnownAs` from remote actors as either array or unwrapped singleton
- Fix: ローカルに存在しないリモートアカウントに対するアカウント削除リクエストを受信した際に、そのユーザーを新規作成して削除する挙動を修正
- Fix: Inboxでの特定のエラーによる失敗はDelayedにしない
- Fix: ID生成アルゴリズムにULIDを使用している場合にMisskeyが正しく動作しない問題を修正
- Fix: リレー経由で届いたノートがリノートとして表示される問題を修正
- Fix: robots.txtの内容を調整
- Fix: 特定のユーザーに管理者権限を持つロールが複数ついている際に、取得できるユーザーIDが重複する問題を修正
(Cherry-picked from https://github.com/lqvp/misskey-tempura/commit/17ed4108cec4b6bd2fd989db5a9091db91fa37a7)
- Fix: ブロックしたサーバーからのInboxジョブが蓄積し続ける問題を修正
(Cherry-picked from https://github.com/lqvp/misskey-tempura/commit/3f0f4bfe923f2b3a7837017b54841598f421c6ef)
- Fix: support activity with `actor` as an id string or embedded object in inbox processor and ActivityPub inbox service
- Fix: コンフィグファイルに `meilisearch` の設定がある状態でほかの検索プロバイダを利用すると、UI上からリモートのートの検索ができない問題を修正
- Fix: ノートに関する通知で公開範囲が考慮されていない問題を修正
(Cherry-picked from https://github.com/lqvp/misskey-tempura/commit/cbce96c520a138b8bcd16890ff6f2952830fa166 originally presented in https://github.com/yojo-art/cherrypick/pull/743)
## 2026.3.2
### General
- 依存関係の更新
### Client
- Enhance: アプリ内ウィンドウの初期サイズを画面サイズに応じて自動で調整するように
- Fix: 絵文字パレットが空の状態でMisskeyについてのページが閲覧できない問題を修正
- Fix: ウィンドウのタイトルをクリックしても最前面に出ないことがある問題を修正
### Server
- Fix: 自分の行ったフォロワー限定投稿または指名投稿に自分自身でリアクションなどを行った場合のイベントが流れない問題を修正
- Fix: 署名付きGETリクエストにおいてAcceptヘッダを署名の対象から除外Acceptヘッダを正規化するCDNやリバースプロキシを使用している際に挙動がおかしくなる問題を修正
- Fix: WebSocket接続におけるートの非表示ロジックを修正
- Fix: チャンネルミュートを有効にしている際に、一部のタイムラインやノート一覧が空になる問題を修正
- Fix: 初期読込時に必要なフロントエンドのアセットがすべて読み込まれていない問題を修正
## 2026.3.1
### General
- 依存関係の更新
### Server
- Fix: セキュリティに関する修正
## 2026.3.0
### Note
- `users/following``birthday` プロパティは非推奨になりました。代わりに `users/get-following-users-by-birthday` をご利用ください。
### General
- Enhance: 「もうすぐ誕生日のユーザー」ウィジェットで、誕生日が至近のユーザーも表示できるように
(Cherry-picked from https://github.com/MisskeyIO/misskey)
- 「今日誕生日のユーザー」は「もうすぐ誕生日のユーザー」に名称変更されました
- Fix: ユーザーハッシュタグページでユーザーの読み込みが重複する問題を修正
- 依存関係の更新
### Client
@@ -23,12 +104,24 @@
- Fix: ファイルタブのセンシティブメディアを開く際に確認ダイアログを出す設定が適用されない問題を修正
- Fix: 2月29日を誕生日に設定している場合、閏年以外は3月1日を誕生日として扱うように修正
- Fix: `Mk:C:container``borderWidth` が正しく反映されない問題を修正
- Fix: mCaptchaが正しく動作しない問題を修正
- Fix: 非ログイン時にリバーシの対局が表示されない問題を修正
- Fix: ノートの詳細表示でリアクションが全件表示されない問題を修正
- Fix: 動画埋め込みプレイヤーなどの一部ウィンドウで、ウィンドウのサイズ変更や移動が正常に行えない問題を修正
- Fix: 画像エフェクトの修正
- 塗りつぶし・モザイク・ぼかしエフェクトを回転させると歪む問題を修正
- モザイクの格子のサイズが画像の縦横比によって長方形となる問題を修正
- モザイクの色味がより自然になるように修正
- ぼかしに不自然な縦線が入る問題を修正
- Fix: フォロー承認通知でフォローされた際のメッセージの絵文字が表示されない問題を修正
- Fix: HTTP環境などSecure Contextのない環境で、設定画面が閲覧できない問題を修正
### Server
- Enhance: OAuthのクライアント情報取得Client Information Discoveryにおいて、IndieWeb Living Standard 11 July 2024で定義されているJSONドキュメント形式に対応しました
- JSONによるClient Information Discoveryを行うには、レスポンスの`Content-Type`ヘッダーが`application/json`である必要があります
- 従来の実装12 February 2022版・HTML Microformat形式も引き続きサポートされます
- Enhance: メモリ使用量を削減
- Fix: `/admin/get-user-ips` エンドポイントのアクセス権限を管理者のみに修正
## 2025.12.2
@@ -47,9 +140,9 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
### Client
- Enhance: デッキのUI説明を追加
- Enhance: 設定がブラウザによって消去されないようにするオプションを追加
- Fix: バージョン表記のないPlayが正しく動作しない問題を修正
- Fix: バージョン表記のないPlayが正しく動作しない問題を修正
バージョン表記のないものは v0.x 系として実行されます。v1.x 系で動作させたい場合は必ずバージョン表記を含めてください。
- Fix: デッキUIでメニュー位置を下にしているとプロファイル削除ボタンが表示されないのを修正
- Fix: デッキUIでメニュー位置を下にしているとプロファイル削除ボタンが表示されないのを修正
- Fix: 一部のUnicode絵文字のリアクションがボタンにならない問題を修正
### Server
@@ -94,11 +187,11 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Fix: ページの内容がはみ出ることがある問題を修正
- Fix: ナビゲーションバーを下に表示しているときに、項目数が多いと表示が崩れる問題を修正
- Fix: ヘッダーメニューのチャンネルの新規作成の項目でチャンネル作成ページに飛べない問題を修正 #16816
- Fix: ラジオボタンに空白の選択肢が表示される問題を修正
- Fix: ラジオボタンに空白の選択肢が表示される問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1105)
- Fix: 一部のシチュエーションで投稿フォームのツアーが正しく表示されない問題を修正
- Fix: 投稿フォームのリセットボタンで注釈がリセットされない問題を修正
- Fix: PlayのAiScriptバージョン判定v0.x系・v1.x系の判定が正しく動作しない問題を修正
- Fix: PlayのAiScriptバージョン判定v0.x系・v1.x系の判定が正しく動作しない問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1129)
- Fix: フォロー申請をキャンセルする際の確認ダイアログの文言が不正確な問題を修正
- Fix: 初回読み込み時にエラーになることがある問題を修正
@@ -108,12 +201,12 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
### Server
- Enhance: メモリ使用量を削減しました
- Enhance: 依存関係の更新
- Fix: ワードミュートの文字数計算を修正
- Fix: ワードミュートの文字数計算を修正
- Fix: チャンネルのリアルタイム更新時に、ロックダウン設定にて非ログイン時にノートを表示しない設定にしている場合でもノートが表示されてしまう問題を修正
- Fix: DeepL APIのAPIキー指定方式変更に対応
- Fix: DeepL APIのAPIキー指定方式変更に対応
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1096)
- 内部実装の変更にて対応可能な更新です。Misskey側の設定方法に変更はありません。
- Fix: DBレプリケーションを利用する環境でクエリーが失敗する問題を修正
- Fix: DBレプリケーションを利用する環境でクエリーが失敗する問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1123)
## 2025.11.0
@@ -156,7 +249,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
## 2025.10.1
### General
- Enhance: リモートユーザーに付与したロールバッジを表示できるように(オプトイン)
- Enhance: リモートユーザーに付与したロールバッジを表示できるように(オプトイン)
パフォーマンス上の問題からデフォルトで無効化されています。「コントロールパネル > パフォーマンス」から有効化できます。
- 依存関係の更新
@@ -283,7 +376,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Enhance: レンダリングパフォーマンスの向上
- Enhance: 依存ソフトウェアの更新
- Fix: 投稿フォームでファイルのアップロードが中止または失敗した際のハンドリングを修正
- Fix: 一部の設定検索結果が存在しないパスになる問題を修正
- Fix: 一部の設定検索結果が存在しないパスになる問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1171)
- Fix: テーマエディタが動作しない問題を修正
- Fix: チャンネルのハイライトページにノートが表示されない問題を修正
@@ -443,7 +536,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Enhance: 画像の高品質なプレースホルダを無効化してパフォーマンスを向上させるオプションを追加
- Enhance: 招待されているが参加していないルームを開いたときに、招待を承認するかどうか尋ねるように
- Enhance: リプライ元にアンケートがあることが表示されるように
- Enhance: ノートのサーバー情報のデザインを改善・パフォーマンス向上
- Enhance: ノートのサーバー情報のデザインを改善・パフォーマンス向上
(Based on https://github.com/taiyme/misskey/pull/198, https://github.com/taiyme/misskey/pull/211, https://github.com/taiyme/misskey/pull/283)
- Enhance: ユーザー設定でURLプレビューを無効化できるように
- Enhance: ヒントとコツを追加
@@ -532,7 +625,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
### Server
- Enhance: ジョブキューの成功/失敗したジョブも一定数・一定期間保存するようにし、後から問題を調査することを容易に
- Enhance: フォローしているユーザーならフォロワー限定投稿のノートでもアンテナで検知できるように
- Enhance: フォローしているユーザーならフォロワー限定投稿のノートでもアンテナで検知できるように
(Cherry-picked from https://github.com/yojo-art/cherrypick/pull/568 and https://github.com/team-shahu/misskey/pull/38)
- Enhance: ユーザーごとにノートの表示が高速化するように
- Fix: システムアカウントの名前がサーバー名と同期されない問題を修正
@@ -638,7 +731,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
### General
- Enhance: プロキシアカウントをシステムアカウントとして作成するように
- Enhance: OAuthで外部アプリからロゴが提供されている場合、それを表示できるように
- Enhance: OAuthで外部アプリからロゴが提供されている場合、それを表示できるように
書式は https://indieauth.spec.indieweb.org/20220212/#example-2 に準じます。
- Fix: システムアカウントが削除できる問題を修正
@@ -652,7 +745,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
### Server
- Fix: 特定のケースでActivityPubの処理がデッドロックになることがあるのを修正
- Fix: S3互換オブジェクトストレージでファイルのアップロードに失敗することがある問題を修正
- Fix: S3互換オブジェクトストレージでファイルのアップロードに失敗することがある問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/895)
@@ -673,7 +766,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Enhance: リアクションする際に確認ダイアログを表示できるように
- Enhance: コントロールパネルのユーザ検索で入力された情報をページ遷移で損なわないように `#15437`
- Enhance: CWの注釈で入力済みの文字数を表示
- Enhance: ノート検索ページのデザイン調整
- Enhance: ノート検索ページのデザイン調整
(Cherry-picked from https://github.com/taiyme/misskey/pull/273)
- Fix: ノートページで、クリップ一覧が表示されないことがある問題を修正
- Fix: コンディショナルロールを手動で割り当てできる導線を削除 `#13529`
@@ -690,7 +783,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Fix: `following/invalidate`でフォロワーを解除しようとしているユーザーの情報を返すように
- Fix: オブジェクトストレージの設定でPrefixを設定していなかった場合nullまたは空文字になる問題を修正
- Fix: HTTPプロキシとその除外設定を行った状態でカスタム絵文字の一括インポートをしたとき、除外設定が効かないのを修正( #8766 )
- Fix: pgroongaでの検索時にはじめのキーワードのみが検索に使用される問題を修正
- Fix: pgroongaでの検索時にはじめのキーワードのみが検索に使用される問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/886)
- Fix: メールアドレスの形式が正しくなければ以降の処理を行わないように
- Fix: `update-meta`でobjectStoragePrefixにS3_SAFEかつURL-safeでない文字列を使えないように
@@ -700,12 +793,12 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
## 2025.2.0
### General
- Fix: Docker のビルドに失敗する問題を修正
- Fix: Docker のビルドに失敗する問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/883)
### Client
- Fix: パスキーでパスワードレスログインが出来ない問題を修正
- Fix: 一部環境でセンシティブなファイルを含むノートの非表示が効かない問題
- Fix: 一部環境でセンシティブなファイルを含むノートの非表示が効かない問題
- Fix: データセーバー有効時にもユーザーページの「ファイル」タブで画像が読み込まれてしまう問題を修正
- Fix: MFMの `sparkle` エフェクトが正しく表示されない問題を修正
- Fix: ページのURLにスラッシュが含まれている場合にページが正しく表示されない問題を修正
@@ -732,14 +825,14 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
* β版として公開のため、旧画面も引き続き利用可能です
### Client
- Enhance: PC画面でチャンネルが複数列で表示されるように
- Enhance: PC画面でチャンネルが複数列で表示されるように
(Cherry-picked from https://github.com/Otaku-Social/maniakey/pull/13)
- Enhance: 照会に失敗した場合、その理由を表示するように
- Enhance: ワードミュートで検知されたワードを表示できるように
- Enhance: リモートのノートのリンクをコピーできるように
- Enhance: 連合がホワイトリスト化・無効化されているサーバー向けのデザイン修正
- Enhance: AiScriptのセーブデータを明示的に削除する関数`Mk:remove`を追加
- Enhance: ノートの添付ファイルを一覧で遡れる「ファイル」タブを追加
- Enhance: ノートの添付ファイルを一覧で遡れる「ファイル」タブを追加
(Based on https://github.com/Otaku-Social/maniakey/pull/14)
- Enhance: AiScriptの拡張API関数において引数の型チェックをより厳格に
- Enhance: クエリパラメータでuiを一時的に変更できるように #15240
@@ -747,26 +840,26 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Fix: 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
- Fix: サーバー情報メニューに区切り線が不足していたのを修正
- Fix: ノートがログインしているユーザーしか見れない場合にログインダイアログを閉じるとその後の動線がなくなる問題を修正
- Fix: 公開範囲がホームのノートの埋め込みウィジェットが読み込まれない問題を修正
- Fix: 公開範囲がホームのノートの埋め込みウィジェットが読み込まれない問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/803)
- Fix: 絵文字管理画面で一部の絵文字が表示されない問題を修正
- Fix: プラグイン `register_note_view_interruptor` でノートのサーバー情報の書き換えができない問題を修正
- Fix: Botプロテクションの設定変更時は実際に検証を通過しないと保存できないように( #15137 )
- Fix: ノート検索が使用できない場合でもチャンネルのノート検索欄がでていた問題を修正
- Fix: `Ui:C:select`で値の変更が画面に反映されない問題を修正
- Fix: MiAuth認可画面で、認可処理に失敗した場合でもコールバックURLに遷移してしまう問題を修正
- Fix: MiAuth認可画面で、認可処理に失敗した場合でもコールバックURLに遷移してしまう問題を修正
(Cherry-picked from https://github.com/TeamNijimiss/misskey/commit/800359623e41a662551d774de15b0437b6849bb4)
- Fix: ノート作成画面でファイルの添付可能個数を超えてもノートボタンが押せていた問題を修正
- Fix: 「アカウントを管理」画面で、ユーザー情報の取得に失敗したアカウント(削除されたアカウントなど)が表示されない問題を修正
- Fix: MacOSでChrome系ブラウザを使用している場合に、Misskeyを閉じた際に他のタブのオーディオ機能と干渉する問題を修正
- Fix: 言語データのキャッシュ状況によっては、埋め込みウィジェットが正しく起動しない問題を修正
- Fix: 「削除して編集」でノートの引用を解除出来なかった問題を修正( #14476 )
- Fix: RSSウィジェットが正しく表示されない問題を修正
- Fix: RSSウィジェットが正しく表示されない問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/857)
- Fix: ワードミュートの保存失敗時にAPIエラーが握りつぶされる事があるのを修正
- Fix: アンケートでリモートの絵文字が正しく描画できない問題の修正
(Cherry-picked from https://github.com/yojo-art/cherrypick/pull/153)
- Fix: 非ログイン時のサーバー概要画面のメニューボタンが押せないことがあるのを修正
- Fix: 非ログイン時のサーバー概要画面のメニューボタンが押せないことがあるのを修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/656)
- Fix: URLにはじめから`#pswp`が含まれている場合に画像ビューワーがブラウザの戻るボタンで閉じられない問題を修正
- Fix: ロール作成画面で設定できるアイコンデコレーションの最大取付個数を16に制限
@@ -775,18 +868,18 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
### Server
- Enhance: pg_bigmが利用できるよう、ートの検索をILIKE演算子でなくLIKE演算子でLOWER()をかけたテキストに対して行うように
- Enhance: ート検索の選択肢としてpgroongaに対応 ( #14730 )
- Enhance: チャート更新時にDBに同時接続しないように
- Enhance: チャート更新時にDBに同時接続しないように
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/830)
- Enhance: config(default.yml)からSQLログ全文を出力するか否かを設定可能に ( #15266 )
- Fix: ユーザーのプロフィール画面をアドレス入力などで直接表示した際に概要タブの描画に失敗する問題の修正( #15032 )
- Fix: 起動前の疎通チェックが機能しなくなっていた問題を修正
- Fix: 起動前の疎通チェックが機能しなくなっていた問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/737)
- Fix: ートの閲覧にログイン必須にしてもFeedでートが表示されてしまう問題を修正
- Fix: 絵文字の連合でライセンス欄を相互にやり取りするように ( #10859, #14109 )
- Fix: ロックダウンされた期間指定のートがStreaming経由でLTLに出現するのを修正 ( #15200 )
- Fix: disableClustering設定時の初期化ロジックを調整( #15223 )
- Fix: URLとURIが異なるエンティティの照会に失敗する問題を修正( #15039 )
- Fix: ActivityPubリクエストかどうかの判定が正しくない問題を修正
- Fix: ActivityPubリクエストかどうかの判定が正しくない問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/869)
- Fix: `/api/pages/update`にて`name`を指定せずにリクエストするとエラーが発生する問題を修正
- Fix: AIセンシティブ判定が arm64 環境で動作しない問題を修正
@@ -812,12 +905,12 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Fix: お知らせ作成時に画像URL入力欄を空欄に変更できないのを修正 ( #14976 )
### Client
- Enhance: Bull DashboardでRelationship Queueの状態も確認できるように
- Enhance: Bull DashboardでRelationship Queueの状態も確認できるように
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/751)
- Enhance: ドライブでソートができるように
- Enhance: アイコンデコレーション管理画面の改善
- Enhance: 「単なるラッキー」の取得条件を変更
- Enhance: 投稿フォームでEscキーを押したときIME入力中ならフォームを閉じないように #10866
- Enhance: 投稿フォームでEscキーを押したときIME入力中ならフォームを閉じないように #10866
- Enhance: MiAuth, OAuthの認可画面の改善
- どのアカウントで認証しようとしているのかがわかるように
- 認証するアカウントを切り替えられるように
@@ -825,29 +918,29 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Enhance: カタルーニャ語 (ca-ES) に対応
- Enhance: 個別お知らせページではMetaタグを出力するように
- Enhance: ノート詳細画面にロールのバッジを表示
- Enhance: 過去に送信したフォローリクエストを確認できるように
- Enhance: 過去に送信したフォローリクエストを確認できるように
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/663)
- Enhance: サイドバーを簡単に展開・折りたたみできるように ( #14981 )
- Enhance: リノートメニューに「リノートの詳細」を追加
- Enhance: 非ログイン状態でMisskeyを開いた際のパフォーマンスを向上
- Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
- Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正
- Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
- Fix: デッキのタイムラインカラムで「センシティブなファイルを含むノートを表示」設定が使用できなかった問題を修正
- Fix: Encode RSS urls with escape sequences before fetching allowing query parameters to be used
- Fix: リンク切れを修正
- Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正
- Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正
(Cherry-picked from https://github.com/taiyme/misskey/pull/305)
- Fix: メールアドレス登録有効化時の「完了」ダイアログボックスの表示条件を修正
- Fix: 画面幅が狭い環境でデザインが崩れる問題を修正
- Fix: 画面幅が狭い環境でデザインが崩れる問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/815)
- Fix: TypeScriptの型チェック対象ファイルを限定してビルドを高速化するように
- Fix: TypeScriptの型チェック対象ファイルを限定してビルドを高速化するように
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/725)
### Server
- Enhance: DockerのNode.jsを22.11.0に更新
- Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)
- Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/715)
- Enhance: リモートユーザーの照会をオリジナルにリダイレクトするように
- Fix: sharedInboxが無いActorに紐づくリモートユーザーを照会できない
@@ -855,18 +948,18 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Fix: フォロワーへのメッセージの絵文字をemojisに含めるように
- Fix: Nested proxy requestsを検出した際にブロックするように
[ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)
- Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正
- Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/706)
- Fix: 連合への配信時に、acctの大小文字が区別されてしまい正しくメンションが処理されないことがある問題を修正
- Fix: 連合への配信時に、acctの大小文字が区別されてしまい正しくメンションが処理されないことがある問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/711)
- Fix: ローカルユーザーへのメンションを含むートが連合される際に正しいURLに変換されないことがある問題を修正
- Fix: ローカルユーザーへのメンションを含むートが連合される際に正しいURLに変換されないことがある問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/712)
- Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正
- Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
- Fix: User Webhookテスト機能のMock Payloadを修正
- Fix: アカウント削除のモデレーションログが動作していないのを修正 (#14996)
- Fix: User Webhookテスト機能のMock Payloadを修正
- Fix: アカウント削除のモデレーションログが動作していないのを修正 (#14996)
- Fix: リノートミュートが新規投稿通知に対して作用していなかった問題を修正
- Fix: Inboxの処理で生じるエラーを誤ってActivityとして処理することがある問題を修正
- Fix: Inboxの処理で生じるエラーを誤ってActivityとして処理することがある問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/730)
- Fix: セキュリティに関する修正
@@ -893,13 +986,13 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Enhance: 個人宛のお知らせは「わかった」を押すと自動的にアーカイブされるように
- Fix: `admin/emoji/update`エンドポイントのidのみ指定した時不正なエラーが発生するバグを修正
- Fix: RBT有効時、リートのリアクションが反映されない問題を修正
- Fix: キューのエラーログを簡略化するように
- Fix: キューのエラーログを簡略化するように
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/649)
## 2024.10.0
### Note
- セキュリティ向上のため、サーバー初期設定時に使用する初期パスワードを設定できるようになりました。今後Misskeyサーバーを新たに設置する際には、初回の起動前にコンフィグファイルの`setupPassword`をコメントアウトし、初期パスワードを設定することをおすすめします。(すでに初期設定を完了しているサーバーについては、この変更に伴い対応する必要はありません)
- セキュリティ向上のため、サーバー初期設定時に使用する初期パスワードを設定できるようになりました。今後Misskeyサーバーを新たに設置する際には、初回の起動前にコンフィグファイルの`setupPassword`をコメントアウトし、初期パスワードを設定することをおすすめします。(すでに初期設定を完了しているサーバーについては、この変更に伴い対応する必要はありません)
- ホスティングサービスを運営している場合は、コンフィグファイルを構築する際に`setupPassword`をランダムな値に設定し、ユーザーに通知するようにシステムを更新することをおすすめします。
- なお、初期パスワードが設定されていない場合でも初期設定を行うことが可能ですUI上で初期パスワードの入力欄を空欄にすると続行できます
- ユーザーデータを読み込む際の型が一部変更されました。
@@ -919,7 +1012,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
### Client
- Enhance: デザインの調整
- Enhance: ログイン画面の認証フローを改善
- Fix: クライアント上での時間ベースの実績獲得動作が実績獲得後も発動していた問題を修正
- Fix: クライアント上での時間ベースの実績獲得動作が実績獲得後も発動していた問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/657)
### Server
@@ -937,7 +1030,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Feat: フォローされた際のメッセージを設定できるように
- Feat: 連合をホワイトリスト制にできるように
- Feat: UserWebhookとSystemWebhookのテスト送信機能を追加 (#14445)
- Feat: モデレーターはユーザーにかかわらずファイルが添付されているノートを検索できるように
- Feat: モデレーターはユーザーにかかわらずファイルが添付されているノートを検索できるように
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/680)
- Feat: データエクスポートが完了した際に通知を発行するように
- Enhance: ユーザーによるコンテンツインポートの可否をロールポリシーで制御できるように
@@ -956,12 +1049,12 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Fix: サーバーメトリクスが2つ以上あるとリロード直後の表示がおかしくなる問題を修正
- Fix: コントロールパネル内のAp requests内のチャートの表示がおかしかった問題を修正
- Fix: 月の違う同じ日はセパレータが表示されないのを修正
- Fix: タッチ画面でレンジスライダーを操作するとツールチップが複数表示される問題を修正
- Fix: タッチ画面でレンジスライダーを操作するとツールチップが複数表示される問題を修正
(Cherry-picked from https://github.com/taiyme/misskey/pull/265)
- Fix: 縦横比が極端なカスタム絵文字を表示する際にレイアウトが崩れる箇所があるのを修正
- Fix: 縦横比が極端なカスタム絵文字を表示する際にレイアウトが崩れる箇所があるのを修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/725)
- Fix: 設定変更時のリロード確認ダイアログが複数個表示されることがある問題を修正
- Fix: ファイルの詳細ページのファイルの説明で改行が正しく表示されない問題を修正
- Fix: ファイルの詳細ページのファイルの説明で改行が正しく表示されない問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/bde6bb0bd2e8b0d027e724d2acdb8ae0585a8110)
- Fix: 一部画面のページネーションが動作しにくくなっていたのを修正 ( #12766 , #11449 )
@@ -970,14 +1063,14 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Fix: アンテナの書き込み時にキーワードが与えられなかった場合のエラーをApiErrorとして投げるように
- この変更により、公式フロントエンドでは入力の不備が内部エラーとして報告される代わりに一般的なエラーダイアログで報告されます
- Fix: ファイルがサイズの制限を超えてアップロードされた際にエラーを返さなかった問題を修正
- Fix: 外部ページを解析する際に、ページに紐づけられた関連リソースも読み込まれてしまう問題を修正
- Fix: 外部ページを解析する際に、ページに紐づけられた関連リソースも読み込まれてしまう問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/26e0412fbb91447c37e8fb06ffb0487346063bb8)
- Fix: Continue importing from file if single emoji import fails
- Fix: `Retry-After`ヘッダーが送信されなかった問題を修正
- Fix: `Retry-After`ヘッダーが送信されなかった問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/8a982c61c01909e7540ff1be9f019df07c3f0624)
- Fix: サーバーサイドのDOM解析完了時にリソースを開放するように
- Fix: サーバーサイドのDOM解析完了時にリソースを開放するように
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/634)
- Fix: `<link rel="alternate">`を追って照会するのはOKレスポンスが返却された場合のみに
- Fix: `<link rel="alternate">`を追って照会するのはOKレスポンスが返却された場合のみに
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/633)
- Fix: メールにスタイルが適用されていなかった問題を修正
@@ -1006,15 +1099,15 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- 通知ページや通知カラム(デッキ)を開いている状態において、新たに発生した通知が既読されない問題が修正されます。
- これにより、プッシュ通知が有効な同条件下の環境において、プッシュ通知が常に発生してしまう問題も修正されます。
- Fix: Play各種エンドポイントの返り値に`visibility`が含まれていない問題を修正
- Fix: サーバー情報取得の際にモデレーター限定の情報が取得できないことがあるのを修正
- Fix: サーバー情報取得の際にモデレーター限定の情報が取得できないことがあるのを修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/582)
- Fix: 公開範囲がダイレクトのノートをユーザーアクティビティのチャート生成に使用しないように
- Fix: 公開範囲がダイレクトのノートをユーザーアクティビティのチャート生成に使用しないように
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/679)
- Fix: ActivityPubのエンティティタイプ判定で不明なタイプを受け取った場合でも処理を継続するように
- キュー処理のつまりが改善される可能性があります
- Fix: リバーシの対局設定の変更が反映されないのを修正
- Fix: 無制限にストリーミングのチャンネルに接続できる問題を修正
- Fix: ベースロールのポリシーを変更した際にモデログに記録されないのを修正
- Fix: ベースロールのポリシーを変更した際にモデログに記録されないのを修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/700)
- Fix: Prevent memory leak from memory caches (#14310)
- Fix: More reliable memory cache eviction (#14311)
@@ -1046,9 +1139,9 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Enhance: 内蔵APIドキュメントのデザイン・パフォーマンスを改善
- Enhance: 非ログイン時に他サーバーに遷移するアクションを追加
- Enhance: 非ログイン時のハイライトTLのデザインを改善
- Enhance: フロントエンドのアクセシビリティ改善
- Enhance: フロントエンドのアクセシビリティ改善
(Based on https://github.com/taiyme/misskey/pull/226)
- Enhance: サーバー情報ページ・お問い合わせページを改善
- Enhance: サーバー情報ページ・お問い合わせページを改善
(Cherry-picked from https://github.com/taiyme/misskey/pull/238)
- Enhance: AiScriptを0.19.0にアップデート
- Enhance: Allow negative delay for MFM animation elements (`tada`, `jelly`, `twitch`, `shake`, `spin`, `jump`, `bounce`, `rainbow`)
@@ -1057,7 +1150,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Enhance: 検索(ノート/ユーザー)において、入力に空白が含まれている場合は照会を行わないように
- Enhance: 検索(ノート/ユーザー)において、照会を行うかどうか、ハッシュタグのノート/ユーザー一覧ページを表示するかどうかの確認ダイアログを出すように
- Enhance: 検索(ノート/ユーザー)で `@` から始まる文字列(`@user@host`など)を入力すると、そのユーザーを照会できるように
- Enhance: ドライブのファイル・フォルダをドラッグしなくても移動できるように
- Enhance: ドライブのファイル・フォルダをドラッグしなくても移動できるように
(Cherry-picked from https://github.com/nafu-at/misskey/commit/b89c2af6945c6a9f9f10e83f54d2bcf0f240b0b4, https://github.com/nafu-at/misskey/commit/8a7d710c6acb83f50c83f050bd1423c764d60a99)
- Enhance: デッキのアンテナ・リスト選択画面からそれぞれを新規作成できるように
- Enhance: ブラウザのコンテキストメニューを使用できるように
@@ -1065,19 +1158,19 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Fix: `/about#federation` ページなどで各インスタンスのチャートが表示されなくなっていた問題を修正
- Fix: ユーザーページの追加情報のラベルを投稿者のサーバーの絵文字で表示する (#13968)
- Fix: リバーシの対局を正しく共有できないことがある問題を修正
- Fix: コントロールパネルでベースロールのポリシーを編集してもUI上では変更が反映されない問題を修正
- Fix: コントロールパネルでベースロールのポリシーを編集してもUI上では変更が反映されない問題を修正
- Fix: アンテナの編集画面のボタンに隙間を追加
- Fix: テーマプレビューが見れない問題を修正
- Fix: ショートカットキーが連打できる問題を修正
- Fix: ショートカットキーが連打できる問題を修正
(Cherry-picked from https://github.com/taiyme/misskey/pull/234)
- Fix: MkSignin.vueのcredentialRequestからReactivityを削除ProxyがPasskey認証処理に渡ることを避けるため
- Fix: 「アニメーション画像を再生しない」がオンのときでもサーバーのバナー画像・背景画像がアニメーションしてしまう問題を修正
- Fix: 「アニメーション画像を再生しない」がオンのときでもサーバーのバナー画像・背景画像がアニメーションしてしまう問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/574)
- Fix: Twitchの埋め込みが開けない問題を修正
- Fix: 子メニューの高さがウィンドウからはみ出ることがある問題を修正
- Fix: 個人宛てのダイアログ形式のお知らせが即時表示されない問題を修正
- Fix: 一部の画像がセンシティブ指定されているときに画面に何も表示されないことがあるのを修正
- Fix: リアクションしたユーザー一覧のユーザー名がはみ出る問題を修正
- Fix: リアクションしたユーザー一覧のユーザー名がはみ出る問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/672)
- Fix: `/share`ページにおいて絵文字ピッカーを開くことができない問題を修正
- Fix: deck uiの通知音が重なる問題 (#14029)
@@ -1120,14 +1213,14 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
4. フォローしていない非アクティブなユーザ
また、自分自身のアカウントもサジェストされるようになりました。
- Fix: 一般ユーザーから見たユーザーのバッジの一覧に公開されていないものが含まれることがある問題を修正
- Fix: 一般ユーザーから見たユーザーのバッジの一覧に公開されていないものが含まれることがある問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/652)
- Fix: ユーザーのリアクション一覧でミュート/ブロックが機能していなかった問題を修正
- Fix: FTT有効時にリモートユーザーのートがHTLにキャッシュされる問題を修正
- Fix: 一部の通知がローカル上のリモートユーザーに対して行われていた問題を修正
- Fix: エラーメッセージの誤字を修正 (#14213)
- Fix: ソーシャルタイムラインにローカルタイムラインに表示される自分へのリプライが表示されない問題を修正
- Fix: リノートのミュートが適用されるまでに時間がかかることがある問題を修正
- Fix: リノートのミュートが適用されるまでに時間がかかることがある問題を修正
(Cherry-picked from https://github.com/Type4ny-Project/Type4ny/commit/e9601029b52e0ad43d9131b555b614e56c84ebc1)
- Fix: Steaming APIが不正なデータを受けた場合の動作が不安定である問題 #14251
- Fix: `users/search`において `@` から始まる文字列が与えられた際の処理が正しくなかった問題を修正
@@ -1154,7 +1247,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
### General
- Feat: エラートラッキングにSentryを使用できるようになりました
- Enhance: URLプレビューの有効化・無効化を設定できるように #13569
- Enhance: アンテナでBotによるートを除外できるように
- Enhance: アンテナでBotによるートを除外できるように
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/545)
- Enhance: クリップのノート数を表示するように
- Enhance: コンディショナルロールの条件として以下を新たに追加 (#13667)
@@ -1173,7 +1266,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
### Client
- Feat: アップロードするファイルの名前をランダム文字列にできるように
- Feat: 個別のお知らせにリンクで飛べるように
- Feat: 個別のお知らせにリンクで飛べるように
(Based on https://github.com/MisskeyIO/misskey/pull/639)
- Enhance: 自分のノートの添付ファイルから直接ファイルの詳細ページに飛べるように
- Enhance: 広告がMisskeyと同一ドメインの場合はRouterで遷移するように
@@ -1203,9 +1296,9 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Fix: 一部のページ内リンクが正しく動作しない問題を修正
- Fix: 周年の実績が閏年を考慮しない問題を修正
- Fix: ローカルURLのプレビューポップアップが左上に表示される
- Fix: WebGL2をサポートしないブラウザで「季節に応じた画面の演出」が有効になっているとき、Misskeyが起動できなくなる問題を修正
- Fix: WebGL2をサポートしないブラウザで「季節に応じた画面の演出」が有効になっているとき、Misskeyが起動できなくなる問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/459)
- Fix: ページタイトルでローカルユーザーとリモートユーザーの区別がつかない問題を修正
- Fix: ページタイトルでローカルユーザーとリモートユーザーの区別がつかない問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/528)
- Fix: コードブロックのシンタックスハイライトで使用される定義ファイルをCDNから取得するように #13177
- CDNから取得せずMisskey本体にバンドルする場合は`pacakges/frontend/vite.config.ts`を修正してください。
@@ -1228,13 +1321,13 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Enhance: ドライブのファイルがNSFWかどうか個別に連合されるように (#13756)
- 可能な場合、ノートの添付ファイルのセンシティブ判定がファイル単位になります
- Fix: リモートから配送されたアクティビティにJSON-LD compactionをかける
- Fix: フォローリクエストを作成する際に既存のものは削除するように
- 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: 登録にメール認証が必須になっている場合、登録されているメールアドレスを削除できないように
- Fix: 登録にメール認証が必須になっている場合、登録されているメールアドレスを削除できないように
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/606)
- Fix: Add Cache-Control to Bull Board
- Fix: nginx経由で/files/にRangeリクエストされた場合に正しく応答できないのを修正
@@ -1427,10 +1520,10 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
### Note
- 依存関係の更新に伴い、Node.js 20.10.0が最小要件になりました
- 絵文字の追加辞書を既にインストールしている場合は、お手数ですが再インストールのほどお願いします
- 絵文字ピッカーにピン留め表示する絵文字設定が「リアクション用」と「絵文字入力用」に分かれました。以前の設定は「リアクション用」として使用されます。
- 絵文字ピッカーにピン留め表示する絵文字設定が「リアクション用」と「絵文字入力用」に分かれました。以前の設定は「リアクション用」として使用されます。
**影響:**
それにより、投稿フォームから表示される絵文字ピッカーのピン留め絵文字がリセットされたように感じるかもしれません(新設された"ピン留め(全般)"の設定が使われるため)。
**影響:**
それにより、投稿フォームから表示される絵文字ピッカーのピン留め絵文字がリセットされたように感じるかもしれません(新設された"ピン留め(全般)"の設定が使われるため)。
投稿用のピン留め絵文字をアップデート前の状態にするには、以下の手順で操作します。
1. 「設定」メニューに移動し、「絵文字ピッカー」タブを選択します。
@@ -1477,7 +1570,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
- Enhance: Unicode 15.0のサポート
- Enhance: コードブロックのハイライト機能を利用するには言語を明示的に指定させるように
- MFMでコードブロックを利用する際に意図しないハイライトが起こらないようになりました
- 逆に、MFMでコードハイライトを利用したい際は言語を明示的に指定する必要があります
- 逆に、MFMでコードハイライトを利用したい際は言語を明示的に指定する必要があります
(例: ` ```js ` → Javascript, ` ```ais ` → AiScript
- Enhance: 絵文字などのオートコンプリートでShift+Tabを押すと前の候補を選択できるように
- Enhance: チャンネルに新規の投稿がある場合にバッジを表示させる
@@ -1884,9 +1977,9 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
### General
- 招待機能を改善しました
* 過去に発行した招待コードを確認できるようになりました
* ロールごとに招待コードの発行数制限と制限対象期間、有効期限を設定できるようになりました
* 招待コードを作成したユーザーと使用したユーザーを確認できるようになりました
* 過去に発行した招待コードを確認できるようになりました
* ロールごとに招待コードの発行数制限と制限対象期間、有効期限を設定できるようになりました
* 招待コードを作成したユーザーと使用したユーザーを確認できるようになりました
- ユーザーにロールが期限付きでアサインされている場合、その期限をユーザーのモデレーションページで確認できるようになりました
- identicon生成を無効にしてパフォーマンスを向上させることができるようになりました
- サーバーのマシン情報の公開を無効にしてパフォーマンスを向上させることができるようになりました
@@ -2049,9 +2142,9 @@ Meilisearchの設定に`index`が必要になりました。値はMisskeyサー
* 「フォロワーのみ」の投稿は検索結果に表示されません。
- 新規登録前に簡潔なルールをユーザーに表示できる、サーバールール機能を追加
- ユーザーへの自分用メモ機能
* ユーザーに対して、自分だけが見られるメモを追加できるようになりました。
* ユーザーに対して、自分だけが見られるメモを追加できるようになりました。
(自分自身に対してもメモを追加できます。)
* ユーザーメニューから追加できます。
* ユーザーメニューから追加できます。
デスクトップ表示ではusernameの右側のボタンからも追加可能
- チャンネルに色を設定できるようになりました。各ノートに設定した色のインジケーターが表示されます。
- チャンネルをアーカイブできるようになりました。

View File

@@ -1,6 +1,6 @@
# syntax = docker/dockerfile:1.20
# syntax = docker/dockerfile:1.23
ARG NODE_VERSION=22.21.1-bookworm
ARG NODE_VERSION=22.22.2-bookworm
# build assets & compile TypeScript
@@ -30,7 +30,6 @@ COPY --link ["packages/sw/package.json", "./packages/sw/"]
COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"]
COPY --link ["packages/misskey-bubble-game/package.json", "./packages/misskey-bubble-game/"]
COPY --link ["packages/misskey-mahjong/package.json", "./packages/misskey-mahjong/"]
ARG NODE_ENV=production
@@ -62,7 +61,6 @@ COPY --link ["packages/backend/package.json", "./packages/backend/"]
COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"]
COPY --link ["packages/misskey-bubble-game/package.json", "./packages/misskey-bubble-game/"]
COPY --link ["packages/misskey-mahjong/package.json", "./packages/misskey-mahjong/"]
ARG NODE_ENV=production
@@ -99,14 +97,11 @@ COPY --chown=misskey:misskey --from=target-builder /misskey/packages/backend/nod
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-js/node_modules ./packages/misskey-js/node_modules
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-reversi/node_modules ./packages/misskey-reversi/node_modules
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-bubble-game/node_modules ./packages/misskey-bubble-game/node_modules
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-mahjong/node_modules ./packages/misskey-mahjong/node_modules
COPY --chown=misskey:misskey --from=native-builder /misskey/built ./built
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-js/built ./packages/misskey-js/built
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-reversi/built ./packages/misskey-reversi/built
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-bubble-game/built ./packages/misskey-bubble-game/built
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-mahjong/built ./packages/misskey-mahjong/built
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/built ./packages/backend/built
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/src-js ./packages/backend/src-js
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/i18n/built ./packages/i18n/built
COPY --chown=misskey:misskey --from=native-builder /misskey/fluent-emojis /misskey/fluent-emojis
COPY --chown=misskey:misskey . ./

View File

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

View File

@@ -1012,6 +1012,7 @@ inMinutes: "د"
inDays: "ي"
widgets: "التطبيقات المُصغّرة"
presets: "إعدادات مسبقة"
previewingThemeRestore: "استرجاع"
_imageEditing:
_vars:
filename: "اسم الملف"

View File

@@ -264,7 +264,7 @@ noJobs: "No hi ha feines"
federating: "Federant"
blocked: "Bloquejat"
suspended: "Anul·lar subscripció "
all: "tot"
all: "Tot"
subscribing: "Subscrit a"
publishing: "S'està publicant"
notResponding: "Sense resposta"
@@ -543,6 +543,7 @@ regenerate: "Regenera"
fontSize: "Mida del text"
mediaListWithOneImageAppearance: "Altura de la llista de fitxers amb una única imatge"
limitTo: "Limita a {x}"
showMediaListByGridInWideArea: "Mostra la llista de medis en vista quadrícula quan l'amplada de la pantalla ho permeti"
noFollowRequests: "No tens sol·licituds de seguiment"
openImageInNewTab: "Obre imatges a una nova pestanya"
dashboard: "Tauler de control"
@@ -1072,8 +1073,8 @@ thisPostMayBeAnnoying: "Aquesta nota pot ser molesta per algú."
thisPostMayBeAnnoyingHome: "Publicar a la línia de temps d'Inici"
thisPostMayBeAnnoyingCancel: "Cancel·lar "
thisPostMayBeAnnoyingIgnore: "Publicar de totes maneres"
collapseRenotes: "Col·lapsar les renotes que ja has vist"
collapseRenotesDescription: "Col·lapse les notes a les quals ja has reaccionat o que ja has renotat"
collapseRenotes: "Col·lapsar els impulsos que ja has vist"
collapseRenotesDescription: "Col·lapse les notes a les quals ja has reaccionat o que ja has impulsat."
internalServerError: "Error intern del servidor"
internalServerErrorDescription: "El servidor ha fallat de manera inexplicable."
copyErrorInfo: "Copiar la informació de l'error "
@@ -1389,7 +1390,7 @@ defaultCompressionLevel_description: "Si el redueixes augmentaràs la qualitat d
inMinutes: "Minut(s)"
inDays: "Di(a)(es)"
safeModeEnabled: "Mode segur activat"
pluginsAreDisabledBecauseSafeMode: "Els afegits no estan activats perquè el mode segur està activat."
pluginsAreDisabledBecauseSafeMode: "Les extensions no estan activades perquè el mode segur està activat."
customCssIsDisabledBecauseSafeMode: "El CSS personalitzat no s'aplica perquè el mode segur es troba activat."
themeIsDefaultBecauseSafeMode: "El tema predeterminat es farà servir mentre el mode segur estigui activat. Una vegada es desactivi el mode segur es restablirà el tema escollit."
thankYouForTestingBeta: "Gràcies per ajudar-nos a provar la versió beta!"
@@ -1407,6 +1408,9 @@ frame: "Marc"
presets: "Predefinit"
zeroPadding: "Sense omplir"
nothingToConfigure: "No hi ha res a configurar"
viewRenotedChannel: "Mirar el canal d'impulsos "
previewingTheme: "Creació de canal"
previewingThemeRestore: "Restaurar"
_imageEditing:
_vars:
caption: "Títol de l'arxiu"
@@ -1686,7 +1690,7 @@ _initialTutorial:
description: "Pots limitar qui pot veure les teves notes."
public: "La teva nota serà visible per a tots els usuaris."
home: "Publicar només a línia de temps d'Inici. La gent que visiti el teu perfil o mitjançant les remotes també la podran veure."
followers: "Només visible per a seguidors. Només els teus seguidors la podran veure i ningú més. Ningú més podrà fer renotes."
followers: "Només visible per a seguidors. Només els teus seguidors la podran veure i ningú més. Ningú més podrà fer impulsos."
direct: "Només visible per a alguns seguidors, el destinatari rebre una notificació. Es pot fer servir com una alternativa als missatges directes."
doNotSendConfidencialOnDirect1: "Tingues cura quan enviïs informació sensible."
doNotSendConfidencialOnDirect2: "Els administradors del servidor poden veure tot el que escrius. Ves compte quan enviïs informació sensible en enviar notes directes a altres usuaris en servidors de poca confiança."
@@ -2096,6 +2100,7 @@ _role:
canSearchNotes: "Pot cercar notes"
canSearchUsers: "Pot cercar usuaris"
canUseTranslator: "Pot fer servir el traductor"
canCreateChannel: "Previsualitzant el tema"
avatarDecorationLimit: "Nombre màxim de decoracions que es poden aplicar els avatars"
canImportAntennas: "Autoritza la importació d'antenes "
canImportBlocking: "Autoritza la importació de bloquejats"
@@ -2184,8 +2189,8 @@ _email:
title: "Has rebut una sol·licitud de seguiment"
_plugin:
install: "Instal·lar un afegit "
installWarn: "Si us plau, no instal·lis afegits que no siguin de confiança."
manage: "Gestionar els afegits"
installWarn: "Si us plau, no instal·lis extensions que no siguin de confiança."
manage: "Gestiona les extensions"
viewSource: "Veure l'origen "
viewLog: "Mostra el registre"
_preferencesBackups:
@@ -3400,11 +3405,9 @@ _imageEffector:
threshold: "Llindar"
centerX: "Centre de X"
centerY: "Centre de Y"
zoomLinesSmoothing: "Suavitzat"
zoomLinesSmoothingDescription: "Els paràmetres de suavitzat i amplada de línia en augmentar no es poden fer servir junts."
zoomLinesThreshold: "Amplada de línia a l'augmentar "
density: "Densitat"
zoomLinesOutlineThickness: "Amplada de les vores exteriors"
zoomLinesMaskSize: "Diàmetre del centre"
zoomLinesBlack: "Obscurir"
circle: "Cercle"
drafts: "Esborrany "
_drafts:

View File

@@ -130,6 +130,7 @@ reactions: "Reakce"
reactionSettingDescription2: "Přetažením změníte pořadí, kliknutím smažete, zmáčkněte \"+\" k přidání"
rememberNoteVisibility: "Zapamatovat nastavení zobrazení poznámky"
attachCancel: "Odstranit přílohu"
deleteFile: "Smazat soubor"
markAsSensitive: "Označit jako NSFW"
unmarkAsSensitive: "Odznačit jako NSFW"
enterFileName: "Zadejte název souboru"
@@ -205,6 +206,7 @@ blockThisInstance: "Blokovat tuto instanci"
silenceThisInstance: "Utišit tuto instanci"
operations: "Operace"
software: "Software"
softwareName: "Software"
version: "Verze"
metadata: "Metadata"
withNFiles: "{n} soubor(ů)"
@@ -231,6 +233,7 @@ noteDeleteConfirm: "Jste si jistí že chcete smazat tuhle poznámku?"
pinLimitExceeded: "Nemůžete připnout další poznámky."
done: "Hotovo"
processing: "Zpracovávám"
preprocessing: "Připravuji..."
preview: "Náhled"
default: "Výchozí"
defaultValueIs: "Základní hodnota: {value}"
@@ -265,6 +268,7 @@ removed: "Smazáno"
removeAreYouSure: "Jste si jistí že chcete smazat \"{x}\"?"
deleteAreYouSure: "Jste si jistí že chcete smazat \"{x}\"?"
resetAreYouSure: "Opravdu resetovat?"
areYouSure: "Jste si jistí?"
saved: "Uloženo"
upload: "Nahrát soubory"
keepOriginalUploading: "Ponechat originální obrázek"
@@ -275,9 +279,12 @@ uploadFromUrl: "Nahrát z URL adresy"
uploadFromUrlDescription: "URL adresa souboru, který chcete nahrát"
uploadFromUrlRequested: "Upload zažádán"
uploadFromUrlMayTakeTime: "Může trvat nějakou dobu, dokud nebude dokončeno nahrávání."
uploadNFiles: "Uploadovat {n} souborů"
explore: "Objevovat"
messageRead: "Přečtené"
readAllChatMessages: "Označit všechny zprávy za přečtené"
noMoreHistory: "To je vše"
startChat: "Začít chat"
nUsersRead: "přečteno {n} uživateli"
agreeTo: "Souhlasím s {0}"
agree: "Souhlasím"
@@ -308,12 +315,15 @@ selectFile: "Vybrat soubor"
selectFiles: "Vybrat soubory"
selectFolder: "Vyberte složku"
selectFolders: "Vyberte složky"
fileNotSelected: "Nebyl vybrán žádný soubor"
renameFile: "Přejmenovat soubor"
folderName: "Název složky"
createFolder: "Vytvořit složku"
renameFolder: "Přejmenovat složku"
deleteFolder: "Odstranit složku"
folder: "Složka "
addFile: "Přidat soubor"
showFile: "Procházet soubory"
emptyDrive: "Váš disk je prázdný"
emptyFolder: "Tato složka je prázdná"
unableToDelete: "Nelze smazat"
@@ -424,6 +434,7 @@ totp: "Ověřovací aplikace"
totpDescription: "Použít ověřovací aplikaci pro použití jednorázových hesel"
moderator: "Moderátor"
moderation: "Moderování"
moderationNote: "Poznámka moderátora"
nUsersMentioned: "{n} uživatelů zmínilo"
securityKeyAndPasskey: "Bezpečnostní klíče a tokeny"
securityKey: "Bezpečnostní klíč"
@@ -479,7 +490,9 @@ uiLanguage: "Jazyk uživatelského rozhraní"
aboutX: "O {x}"
emojiStyle: "Styl emoji"
native: "Výchozí"
menuStyle: "Styl nabídky"
style: "Vzhled"
drawer: "Boční menu"
popup: "Vyskakovací okno"
showNoteActionsOnlyHover: "Zobrazit akce poznámky jenom při naběhnutí myši"
noHistory: "Žádná historie"
@@ -535,6 +548,7 @@ deleteAll: "Smazat vše"
showFixedPostForm: "Zobrazit formulář pro nové příspěvky nad časovou osou"
showFixedPostFormInChannel: "Zobrazit vkládací formulář na vrcholu časové osy (Kanály)"
newNoteRecived: "Jsou k dispozici nové poznámky"
newNote: "Nová poznámka"
sounds: "Zvuky"
sound: "Zvuky"
listen: "Poslouchat"
@@ -614,6 +628,7 @@ medium: "Střední"
small: "Malé"
generateAccessToken: "Vygenerovat přístupový token"
permission: "Oprávnění"
adminPermission: "Administrátorská práva"
enableAll: "Povolit vše"
disableAll: "Vypnout vše"
tokenRequested: "Povolit přístup k účtu"
@@ -889,6 +904,9 @@ oneHour: "1 hodina"
oneDay: "1 den"
oneWeek: "1 týden"
oneMonth: "1 měsíc"
threeMonths: "3 měsíce"
oneYear: "1 rok"
threeDays: "3 dny"
reflectMayTakeTime: "Může trvat nějakou dobu, než se projeví změny."
failedToFetchAccountInformation: "Nepodařily se načíst informace o účtě"
rateLimitExceeded: "Překročení rychlostního limitu"
@@ -1026,6 +1044,8 @@ showClipButtonInNoteFooter: "Přidat \"Připnout\" do akčního menu poznámky"
noteIdOrUrl: "ID nebo URL poznámky"
video: "Video"
videos: "Videa"
audio: "Zvuk"
audioFiles: "Zvuk"
dataSaver: "Spořič dat"
accountMigration: "Migrace účtu"
accountMoved: "Tenhle uživatel se přesunul na nový účet:"
@@ -1053,6 +1073,8 @@ preservedUsernames: "Rezervované uživatelské jména"
preservedUsernamesDescription: "Seznam uživatelských jmén na rezervaci oddělené mezerama. Tyhle jména se potom nebudou moc použít při normálním procesu vytvoření účtu ale můžou být použiti manuálně administratorém. Existujících účtů se to nedotkne."
createNoteFromTheFile: "Vytvořit poznámku z tohodle souboru"
archive: "Archiv"
archived: "Archivované"
unarchive: "Obnovit"
channelArchiveConfirmTitle: "Opravdu chcete archivovat {name}?"
channelArchiveConfirmDescription: "Archivovaný kanál se objeví v seznamu kanálů nebo ve výsledcích hledání. Nové poznámky se nedají vložit do seznamu."
thisChannelArchived: "Tenhle kanál je archivovaný"
@@ -1099,6 +1121,7 @@ doYouAgree: "Souhlasíte?"
beSureToReadThisAsItIsImportant: "Přečtěte si prosím tyto důležité informace."
iHaveReadXCarefullyAndAgree: "Přečetl jsem si text \"{x}\" a souhlasím s ním."
icon: "Avatar"
forYou: "Pro vás"
replies: "Odpovědět"
renotes: "Přeposlat"
sourceCode: "Zdrojový kód"
@@ -1111,6 +1134,7 @@ inMinutes: "Minut"
inDays: "Dnů"
widgets: "Widgety"
presets: "Předvolba"
previewingThemeRestore: "Obnovit"
_imageEditing:
_vars:
filename: "Název souboru"

View File

@@ -543,6 +543,7 @@ regenerate: "Regenerieren"
fontSize: "Schriftgröße"
mediaListWithOneImageAppearance: "Höhe von Medienlisten mit nur einem Bild"
limitTo: "Auf {x} begrenzen"
showMediaListByGridInWideArea: "Medienlisten auf breiteren Bildschirmen nebeneinander anzeigen"
noFollowRequests: "Keine ausstehenden Follow-Anfragen vorhanden"
openImageInNewTab: "Bilder in neuem Tab öffnen"
dashboard: "Dashboard"
@@ -1406,6 +1407,8 @@ youAreAdmin: "Sie sind ein Administrator"
frame: "Rahmen"
presets: "Vorlage"
zeroPadding: "Nullauffüllung"
nothingToConfigure: "Es sind keine Einstellungen verfügbar"
previewingThemeRestore: "Wiederherstellen"
_imageEditing:
_vars:
caption: "Dateibeschriftung"
@@ -1421,12 +1424,40 @@ _imageEditing:
camera_lens_model: "Objektivname"
camera_mm: "Brennweite"
camera_mm_35: "Brennweite (35-mm-Äquivalent)"
camera_f: "Blende"
camera_s: "Verschlusszeit"
camera_iso: "ISO-Empfindlichkeit"
gps_lat: "Breitengrad"
gps_long: "Längengrad"
_imageFrameEditor:
title: "Rahmenbearbeitung"
tip: "Sie können das Bild dekorieren, indem Sie einen Rahmen sowie ein Etikett mit Metadaten hinzufügen."
header: "Kopfzeile"
footer: "Fußzeile"
borderThickness: "Randbreite"
labelThickness: "Beschriftungsbreite"
labelScale: "Etikettenskala"
centered: "Zentriert"
captionMain: "Überschrift (groß)"
captionSub: "Beschriftung (klein)"
availableVariables: "Verfügbare Variablen"
withQrCode: "QR-Code"
backgroundColor: "Hintergrundfarbe"
textColor: "Textfarbe"
font: "Schriftart"
fontSerif: "Serif"
fontSansSerif: "Sans Serif"
quitWithoutSaveConfirm: "Nicht gespeicherte Änderungen verwerfen?"
failedToLoadImage: "Das Laden des Bildes ist fehlgeschlagen."
_compression:
_quality:
high: "Hohe Qualität"
medium: "Mittlere Qualität"
low: "Niedrige Qualität"
_size:
large: "Groß"
medium: "Medium"
small: "Klein"
_order:
newest: "Neueste zuerst"
oldest: "Älteste zuerst"
@@ -1519,6 +1550,12 @@ _settings:
contentsUpdateFrequency_description2: "Wenn der Echtzeitmodus aktiviert ist, werden die Inhalte unabhängig von dieser Einstellung in Echtzeit aktualisiert."
showUrlPreview: "URL-Vorschau anzeigen"
showAvailableReactionsFirstInNote: "Zeige die verfügbaren Reaktionen im oberen Bereich an."
showPageTabBarBottom: "Tab-Leiste der Seite unten anzeigen"
emojiPaletteBanner: "Sie können Voreinstellungen, die im Emoji-Picker dauerhaft angezeigt werden sollen, als Palette registrieren oder die Anzeigeart des Pickers anpassen."
enableAnimatedImages: "Animierte Bilder aktivieren"
settingsPersistence_title: "Persistenz der Einstellungen"
settingsPersistence_description1: "Durch das Aktivieren der persistenten Speicherung der Einstellungen kann verhindert werden, dass Einstellungsinformationen verloren gehen."
settingsPersistence_description2: "Je nach Umgebung ist eine Aktivierung möglicherweise nicht möglich."
_chat:
showSenderName: "Name des Absenders anzeigen"
sendOnEnter: "Eingabetaste sendet Nachricht"
@@ -1527,6 +1564,8 @@ _preferencesProfile:
profileNameDescription: "Lege einen Namen fest, der dieses Gerät identifiziert."
profileNameDescription2: "Beispiel: \"Haupt-PC\", \"Smartphone\""
manageProfiles: "Profile verwalten"
shareSameProfileBetweenDevicesIsNotRecommended: "Es wird nicht empfohlen, dasselbe Profil auf mehreren Geräten zu teilen."
useSyncBetweenDevicesOptionIfYouWantToSyncSetting: "Wenn es Einstellungselemente gibt, die Sie über mehrere Geräte synchronisieren möchten, aktivieren Sie bitte die Option „Über mehrere Geräte synchronisieren“ jeweils einzeln."
_preferencesBackup:
autoBackup: "Automatische Sicherung"
restoreFromBackup: "Wiederherstellen aus der Sicherung"
@@ -1536,6 +1575,7 @@ _preferencesBackup:
youNeedToNameYourProfileToEnableAutoBackup: "Um die automatische Sicherung zu aktivieren, müssen Profilnamen festgelegt werden."
autoPreferencesBackupIsNotEnabledForThisDevice: "Die automatische Sicherung der Einstellungen ist auf diesem Gerät nicht aktiviert."
backupFound: "Konfigurationssicherung gefunden."
forceBackup: "Erzwungenes Backup der Einstellungen"
_accountSettings:
requireSigninToViewContents: "Anmeldung erfordern, um Inhalte anzuzeigen"
requireSigninToViewContentsDescription1: "Erfordere eine Anmeldung, um alle Notizen und andere Inhalte anzuzeigen, die du erstellt hast. Dadurch wird verhindert, dass Crawler deine Informationen sammeln."
@@ -1692,6 +1732,10 @@ _serverSettings:
fanoutTimelineDbFallback: "Auf die Datenbank zurückfallen"
fanoutTimelineDbFallbackDescription: "Ist diese Option aktiviert, wird die Chronik auf zusätzliche Abfragen in der Datenbank zurückgreifen, wenn sich die Chronik nicht im Cache befindet. Eine Deaktivierung führt zu geringerer Serverlast, aber schränkt den Zeitraum der abrufbaren Chronik ein. "
reactionsBufferingDescription: "Wenn diese Option aktiviert ist, kann sie die Leistung beim Erstellen von Reaktionen erheblich verbessern und die Belastung der Datenbank verringern. Allerdings steigt die Speichernutzung von Redis."
remoteNotesCleaning: "Automatische Bereinigung von Remote-Beiträgen"
remoteNotesCleaning_description: "Wenn diese Option aktiviert ist, werden Remote-Beiträge, die eine bestimmte Zeit überschritten haben, regelmäßig bereinigt, um ein Aufblähen der Datenbank zu verhindern."
remoteNotesCleaningMaxProcessingDuration: "Maximale fortlaufende Dauer des Reinigungsverarbeitungsprozesses"
remoteNotesCleaningExpiryDaysForEachNotes: "Mindestaufbewahrungsdauer für Notizen"
inquiryUrl: "Kontakt-URL"
inquiryUrlDescription: "Gib eine URL für das Kontaktformular der Serverbetreiber oder eine Webseite an, die Kontaktinformationen enthält."
openRegistration: "Registrierung von Konten aktivieren"
@@ -1710,6 +1754,11 @@ _serverSettings:
userGeneratedContentsVisibilityForVisitor: "Sichtbarkeit von nutzergenerierten Inhalten für Gäste"
userGeneratedContentsVisibilityForVisitor_description: "Dies ist nützlich, um zu verhindern, dass unangemessene Inhalte, die nicht gut moderiert sind, ungewollt über deinen eigenen Server im Internet veröffentlicht werden."
userGeneratedContentsVisibilityForVisitor_description2: "Die uneingeschränkte Veröffentlichung aller Inhalte des Servers im Internet, einschließlich der vom Server empfangenen Fremdinhalte, birgt Risiken. Dies ist besonders wichtig für Betrachter, die sich des dezentralen Charakters der Inhalte nicht bewusst sind, da sie selbst fremde Inhalte fälschlicherweise als auf dem Server erstellte Inhalte wahrnehmen könnten."
restartServerSetupWizardConfirm_title: "Möchten Sie den Assistenten für die Ersteinrichtung des Servers erneut ausführen?"
restartServerSetupWizardConfirm_text: "Einige aktuelle Einstellungen werden zurückgesetzt."
entrancePageStyle: "Stil der Einstiegsseite"
showTimelineForVisitor: "Zeitleiste anzeigen"
showActivitiesForVisitor: "Aktivitäten anzeigen"
_userGeneratedContentsVisibilityForVisitor:
all: "Alles ist öffentlich"
localOnly: "Nur lokale Inhalte werden veröffentlicht, fremde Inhalte bleiben privat"
@@ -2032,6 +2081,7 @@ _role:
canManageAvatarDecorations: "Profilbilddekorationen verwalten"
driveCapacity: "Drive-Kapazität"
maxFileSize: "Maximale Dateigröße, die hochgeladen werden kann"
maxFileSize_caption: "Bei einem Reverse Proxy oder einem CDN können andere vorgelagerte Konfigurationswerte vorhanden sein."
alwaysMarkNsfw: "Dateien immer als NSFW markieren"
canUpdateBioMedia: "Kann ein Profil- oder ein Bannerbild bearbeiten"
pinMax: "Maximale Anzahl an angehefteten Notizen"
@@ -2046,6 +2096,7 @@ _role:
descriptionOfRateLimitFactor: "Je niedriger desto weniger restriktiv, je höher destro restriktiver."
canHideAds: "Kann Werbung ausblenden"
canSearchNotes: "Nutzung der Notizsuchfunktion"
canSearchUsers: "Nutzung der Benutzersuche"
canUseTranslator: "Verwendung des Übersetzers"
avatarDecorationLimit: "Maximale Anzahl an Profilbilddekorationen, die angebracht werden können"
canImportAntennas: "Importieren von Antennen erlauben"
@@ -2058,6 +2109,7 @@ _role:
uploadableFileTypes_caption: "Gibt die zulässigen MIME-/Dateitypen an. Mehrere MIME-Typen können durch einen Zeilenumbruch getrennt angegeben werden, und Platzhalter können mit einem Sternchen (*) angegeben werden. (z. B. image/*)"
uploadableFileTypes_caption2: "Bei manchen Dateien ist es nicht möglich, den Typ zu bestimmen. Um solche Dateien zuzulassen, füge {x} der Spezifikation hinzu."
noteDraftLimit: "Anzahl der möglichen Entwürfe für serverseitige Notizen"
scheduledNoteLimit: "Maximale Anzahl gleichzeitig erstellbarer geplanter Beiträge"
watermarkAvailable: "Kann die Wasserzeichenfunktion verwenden"
_condition:
roleAssignedTo: "Manuellen Rollen zugewiesen"
@@ -2318,6 +2370,7 @@ _time:
minute: "Minute(n)"
hour: "Stunde(n)"
day: "Tag(en)"
month: "Monat(e)"
_2fa:
alreadyRegistered: "Du hast bereits ein Gerät für Zwei-Faktor-Authentifizierung registriert."
registerTOTP: "Authentifizierungs-App registrieren"
@@ -2447,6 +2500,7 @@ _auth:
scopeUser: "Als folgender Benutzer agieren"
pleaseLogin: "Bitte logge dich ein, um Apps zu authorisieren."
byClickingYouWillBeRedirectedToThisUrl: "Wenn der Zugang gewährt wird, wirst du automatisch zu folgender URL weitergeleitet"
alreadyAuthorized: "Dieser Anwendung wurde bereits Zugriff gewährt."
_antennaSources:
all: "Alle Notizen"
homeTimeline: "Notizen von Benutzern, denen gefolgt wird"
@@ -2495,11 +2549,40 @@ _widgets:
chat: "Mit dem Benutzer chatten"
_widgetOptions:
showHeader: "Kopfzeile anzeigen"
transparent: "Hintergrund transparent machen"
height: "Höhe"
_button:
colored: "Farbig"
_clock:
size: "Größe"
thickness: "Dicke"
thicknessThin: "Dünn"
thicknessMedium: "Normal"
thicknessThick: "Dick"
graduations: "Zifferblattskala"
graduationDots: "Punkt"
graduationArabic: "Zahlen"
fadeGraduations: "Skala ausblenden"
sAnimation: "Zweite Animation"
sAnimationElastic: "Elastisch"
sAnimationEaseOut: "Weich"
twentyFour: "24-Stunden-Format"
labelTime: "Uhrzeit"
labelTz: "Zeitzone"
labelTimeAndTz: "Zeit und Zeitzone"
timezone: "Zeitzone"
showMs: "Millisekunden anzeigen"
showLabel: "Beschriftung anzeigen"
_jobQueue:
sound: "Ton abspielen"
_rss:
url: "RSS-Feed-URL"
refreshIntervalSec: "Aktualisierungsintervall (Sekunden)"
maxEntries: "Maximale Anzahl der angezeigten Einträge"
_rssTicker:
shuffle: "Zufällige Anzeigereihenfolge"
duration: "Banner-Scrollgeschwindigkeit (in Sekunden)"
reverse: "In andere Richtung scrollen"
_birthdayFollowings:
period: "Dauer"
_cw:
@@ -2546,9 +2629,20 @@ _postForm:
replyPlaceholder: "Dieser Notiz antworten …"
quotePlaceholder: "Diese Notiz zitieren …"
channelPlaceholder: "In einen Kanal senden"
showHowToUse: "Formularbeschreibung anzeigen"
_howToUse:
content_title: "Dieser Text"
content_description: "Bitte geben Sie den Inhalt ein, den Sie veröffentlichen möchten."
toolbar_title: "Symbolleiste"
toolbar_description: "Sie können Dateien oder Umfragen anhängen, Anmerkungen und Hashtags festlegen sowie Emojis und Erwähnungen einfügen."
account_title: "Profilmenü"
account_description: "Du kannst das Konto wechseln, von dem du postest, und dir eine Liste der im Konto gespeicherten Entwürfe und geplanten Beiträge anzeigen lassen."
visibility_title: "Sichtbarkeit"
visibility_description: "Sie können den Umfang festlegen, in dem die Notizen veröffentlicht werden."
menu_title: "Menü"
menu_description: "Sie können außerdem weitere Aktionen durchführen, z.B. als Entwurf speichern, das Posten planen oder Reaktionen einstellen."
submit_title: "Senden-Button"
submit_description: "Du kannst die Notiz posten. Du kannst sie auch mit Strg + Enter / Cmd + Enter posten."
_placeholders:
a: "Was machst du momentan?"
b: "Was ist um dich herum los?"
@@ -2694,6 +2788,8 @@ _notification:
youReceivedFollowRequest: "Du hast eine Follow-Anfrage erhalten"
yourFollowRequestAccepted: "Deine Follow-Anfrage wurde akzeptiert"
pollEnded: "Umfrageergebnisse sind verfügbar"
scheduledNotePosted: "Geplante Notiz wurde veröffentlicht"
scheduledNotePostFailed: "Veröffentlichen der geplanten Notiz fehlgeschlagen"
newNote: "Neue Notiz"
unreadAntennaNote: "Antenne {name}"
roleAssigned: "Rolle zugewiesen"
@@ -2723,6 +2819,8 @@ _notification:
quote: "Zitationen"
reaction: "Reaktionen"
pollEnded: "Ende von Umfragen"
scheduledNotePosted: "Der geplante Beitrag wurde erfolgreich veröffentlicht."
scheduledNotePostFailed: "Der geplante Beitrag ist fehlgeschlagen."
receiveFollowRequest: "Erhaltene Follow-Anfragen"
followRequestAccepted: "Akzeptierte Follow-Anfragen"
roleAssigned: "Rolle zugewiesen"
@@ -2762,6 +2860,14 @@ _deck:
usedAsMinWidthWhenFlexible: "Ist \"Automatische Breitenanpassung\" aktiviert, wird hierfür die minimale Breite verwendet"
flexible: "Automatische Breitenanpassung"
enableSyncBetweenDevicesForProfiles: "Aktivieren der Synchronisierung von Profilinformationen zwischen Geräten"
showHowToUse: "Siehe dir die UI-Beschreibung an."
_howToUse:
addColumn_title: "Spalte hinzufügen"
addColumn_description: "Sie können den Spaltentyp auswählen und hinzufügen."
settings_title: "UI-Einstellungen"
settings_description: "Sie können die detaillierten Einstellungen der Deck-UI vornehmen."
switchProfile_title: "Profil wechseln"
switchProfile_description: "Das UI-Layout kann als Profil gespeichert werden, sodass du jederzeit zwischen den Profilen wechseln kannst."
_columns:
main: "Hauptspalte"
widgets: "Widgets"
@@ -2822,6 +2928,8 @@ _abuseReport:
notifiedWebhook: "Zu verwendender Webhook"
deleteConfirm: "Bist du sicher, dass du den Empfänger der Benachrichtigung entfernen möchtest?"
_moderationLogTypes:
clearQueue: "Warteschlange leeren"
promoteQueue: "Warteschlange erneut ausführen"
createRole: "Rolle erstellt"
deleteRole: "Rolle gelöscht"
updateRole: "Rolle aktualisiert"
@@ -2879,6 +2987,7 @@ _fileViewer:
url: "URL"
uploadedAt: "Hochgeladen am"
attachedNotes: "Zugehörige Notizen"
usage: "Nutzung"
thisPageCanBeSeenFromTheAuthor: "Nur der Benutzer, der diese Datei hochgeladen hat, kann diese Seite sehen."
_externalResourceInstaller:
title: "Von externer Seite installieren"
@@ -3131,6 +3240,7 @@ _bootErrors:
otherOption1: "Client-Einstellungen und Cache löschen"
otherOption2: "Einfachen Client starten"
otherOption3: "Starte das Reparaturwerkzeug"
otherOption4: "Misskey im abgesicherten Modus starten"
_search:
searchScopeAll: "Alle"
searchScopeLocal: "Lokal"
@@ -3167,6 +3277,8 @@ _serverSetupWizard:
doYouConnectToFediverse_description1: "Bei Anschluss an ein Netz von verteilten Servern (Fediverse) können Inhalte mit anderen Servern ausgetauscht werden."
doYouConnectToFediverse_description2: "Die Verbindung mit dem Fediverse wird auch als „Föderation“ bezeichnet."
youCanConfigureMoreFederationSettingsLater: "Erweiterte Einstellungen, wie z. B. die Angabe von föderierbaren Servern, können später vorgenommen werden."
remoteContentsCleaning: "Automatische Bereinigung von Remote-Inhalten"
remoteContentsCleaning_description: "Wenn Sie eine Föderation durchführen, empfangen Sie fortlaufend viele Inhalte. Wenn Sie die automatische Bereinigung aktivieren, werden Remote-Inhalte, deren bestimmter Zeitraum abgelaufen ist, automatisch vom Server gelöscht, wodurch Speicherplatz eingespart werden kann."
adminInfo: "Administrator-Informationen"
adminInfo_description: "Legt die Administrator-Informationen fest, die für den Empfang von Anfragen verwendet werden."
adminInfo_mustBeFilled: "Dies ist auf einem offenen Server oder bei aktivierter Föderation erforderlich."
@@ -3191,6 +3303,7 @@ _uploader:
allowedTypes: "Hochladbare Dateitypen"
tip: "Die Datei ist noch nicht hochgeladen worden. In diesem Dialog kannst du die Datei vor dem Hochladen anzeigen, umbenennen, komprimieren und zuschneiden. Wenn du fertig bist, klicke auf „Hochladen“, um den Upload zu starten."
_clientPerformanceIssueTip:
title: "Wenn du das Gefühl hast, dass der Akku sich schnell entlädt."
makeSureDisabledAdBlocker: "Deaktiviere deinen Adblocker"
makeSureDisabledAdBlocker_description: "Adblocker können die Leistung beeinträchtigen; vergewissere dich, ob in deinem Betriebssystem, Browser oder deinen Add-ons Adblocker aktiviert sind."
makeSureDisabledCustomCss: "Benutzerdefiniertes CSS deaktivieren"
@@ -3210,10 +3323,14 @@ _watermarkEditor:
driveFileTypeWarnDescription: "Bilddatei auswählen"
title: "Wasserzeichen bearbeiten"
cover: "Alles bedecken"
repeat: "Wiederholen"
preserveBoundingRect: "So einstellen, dass beim Drehen nichts herausragt"
opacity: "Transparenz"
scale: "Größe"
text: "Text"
qr: "QR-Code"
position: "Position"
margin: "Abstand"
type: "Art"
image: "Bilder"
advanced: "Fortgeschritten"
@@ -3222,35 +3339,71 @@ _watermarkEditor:
stripeWidth: "Linienbreite"
stripeFrequency: "Linienanzahl"
polkadot: "Punktmuster"
checker: "Prüfer"
polkadotMainDotOpacity: "Deckkraft des Hauptpunktes"
polkadotMainDotRadius: "Größe des Hauptpunktes"
polkadotSubDotOpacity: "Deckkraft des Unterpunktes"
polkadotSubDotRadius: "Größe des Unterpunktes"
polkadotSubDotDivisions: "Anzahl der Unterpunkte"
leaveBlankToAccountUrl: "Wenn Sie es leer lassen, wird das Profilbild des Kontos verwendet."
failedToLoadImage: "Bild konnte nicht geladen werden"
_imageEffector:
title: "Effekte"
addEffect: "Effekte hinzufügen"
discardChangesConfirm: "Änderungen verwerfen und beenden?"
failedToLoadImage: "Bild konnte nicht geladen werden"
_fxs:
chromaticAberration: "Chromatische Abweichung"
glitch: "Glitch"
mirror: "Spiegeln"
invert: "Farben umkehren"
grayscale: "Schwarzweiß"
blur: "Verwischen"
pixelate: "Verpixeln"
colorAdjust: "Farbkorrektur"
colorClamp: "Farbkomprimierung"
colorClampAdvanced: "Farbkomprimierung (erweitert)"
distort: "Verzerrung"
threshold: "inarisierun"
zoomLines: "Konzentrationslinien"
stripe: "Streifen"
polkadot: "Punktmuster"
checker: "Prüfer"
blockNoise: "Blockrauschen"
tearing: "Tearing"
fill: "Ausfüllen"
_fxProps:
angle: "Winkel"
scale: "Größe"
size: "Größe"
radius: "Radius"
samples: "Stichprobengröße"
offset: "Position"
color: "Farbe"
opacity: "Transparenz"
normalize: "Normalisierung"
amount: "Menge"
lightness: "Erhellen"
contrast: "Kontrast"
hue: "Farbton"
brightness: "Helligkeit"
saturation: "Sättigung"
max: "Maximum"
min: "Minimum"
direction: "Richtung"
phase: "Sättigung"
frequency: "Häufigkeit"
strength: "Stärke"
glitchChannelShift: "Verschiebung"
seed: "Seed-Wert"
redComponent: "Rot-Anteil"
greenComponent: "Grün-Anteil"
blueComponent: "Blau-Anteil"
threshold: "Schwellenwert"
centerX: "Zentrum X"
centerY: "Zentrum Y"
zoomLinesMaskSize: "Mitteldurchmesser"
circle: "Kreisförmig"
drafts: "Entwurf"
_drafts:
select: "Entwurf auswählen"
@@ -3261,10 +3414,27 @@ _drafts:
noDrafts: "Keine Entwürfe"
replyTo: "Antwort an {user}"
quoteOf: "Zitat von {user}s Notiz"
postTo: "Beitrag im {channel}"
saveToDraft: "Als Entwurf speichern"
restoreFromDraft: "Aus Entwurf wiederherstellen"
restore: "Wiederherstellen"
listDrafts: "Liste der Entwürfe"
schedule: "Beitragsplanung"
listScheduledNotes: "Liste der geplanten Beiträge"
cancelSchedule: "Reservierung stornieren"
qr: "QR-Code"
_qr:
showTabTitle: "Anzeigeart"
readTabTitle: "Auslesen"
shareTitle: "{name} {acct}"
shareText: "Bitte folge mir im Fediverse!"
chooseCamera: "Kamera auswählen"
cannotToggleFlash: "Blitzauswahl nicht möglich"
turnOnFlash: "Blitz einschalten"
turnOffFlash: "Blitz ausschalten"
startQr: "QR-Code-Leser starten"
stopQr: "QR-Code-Leser stoppen"
noQrCodeFound: "QR-Code wurde nicht gefunden"
scanFile: "Gerätebilder scannen"
raw: "Text"
mfm: "MFM"

View File

@@ -543,6 +543,7 @@ regenerate: "Regenerate"
fontSize: "Font size"
mediaListWithOneImageAppearance: "Height of media lists with one image only"
limitTo: "Limit to {x}"
showMediaListByGridInWideArea: "Display the media list in a grid when the screen width is wide"
noFollowRequests: "You don't have any pending follow requests"
openImageInNewTab: "Open images in new tab"
dashboard: "Dashboard"
@@ -1407,6 +1408,8 @@ frame: "Frame"
presets: "Preset"
zeroPadding: "Zero padding"
nothingToConfigure: "No configurable options available"
viewRenotedChannel: "Show renoted channel"
previewingThemeRestore: "Restore"
_imageEditing:
_vars:
caption: "File caption"
@@ -3400,11 +3403,9 @@ _imageEffector:
threshold: "Threshold"
centerX: "Center X"
centerY: "Center Y"
zoomLinesSmoothing: "Smoothing"
zoomLinesSmoothingDescription: "Smoothing and zoom line width cannot be used together."
zoomLinesThreshold: "Zoom line width"
density: "Density"
zoomLinesOutlineThickness: "Outline shadow thickness"
zoomLinesMaskSize: "Center diameter"
zoomLinesBlack: "Make black"
circle: "Circular"
drafts: "Drafts"
_drafts:

View File

@@ -543,6 +543,7 @@ regenerate: "Regenerar"
fontSize: "Tamaño de la letra"
mediaListWithOneImageAppearance: "Altura de la lista de medios con una sola imagen."
limitTo: "{x} hasta un máximo de"
showMediaListByGridInWideArea: "Cuando el ancho de la pantalla sea grande, muestra la lista de multimedia uno al lado del otro."
noFollowRequests: "No hay solicitudes de seguimiento"
openImageInNewTab: "Abrir imagen en nueva pestaña"
dashboard: "Panel de control"
@@ -1237,7 +1238,7 @@ sourceCodeIsNotYetProvided: "El código fuente aún no está disponible. Contact
repositoryUrl: "URL del repositorio"
repositoryUrlDescription: "Si estás usando Misskey tal cual (sin cambios en el código fuente), entra en https://github.com/misskey-dev/misskey"
repositoryUrlOrTarballRequired: "Si no has publicado un repositorio aún, deberás publicar un tarball en su lugar. Mira el archivo .config/example.yml para más información."
feedback: "Comentarios"
feedback: "Enviar sugerencias (Feedback)"
feedbackUrl: "URL de comentarios"
impressum: "Impressum"
impressumUrl: "Impressum URL"
@@ -1407,6 +1408,9 @@ frame: "Marco"
presets: "Predefinido"
zeroPadding: "Relleno cero"
nothingToConfigure: "No hay nada que configurar"
viewRenotedChannel: "Ver el canal al que te has suscrito"
previewingTheme: "Vista previa del tema"
previewingThemeRestore: "Regresar"
_imageEditing:
_vars:
caption: "Título del archivo"
@@ -2096,6 +2100,7 @@ _role:
canSearchNotes: "Uso de la búsqueda de notas"
canSearchUsers: "Uso de la búsqueda de usuarios"
canUseTranslator: "Uso de traductor"
canCreateChannel: "Puede crear canales"
avatarDecorationLimit: "Número máximo de decoraciones de avatar"
canImportAntennas: "Permitir la importación de antenas"
canImportBlocking: "Permitir la importación de bloqueos"
@@ -2213,7 +2218,7 @@ _registry:
domain: "Dominio"
createKey: "Crear una clave"
_aboutMisskey:
about: "Misskey es un software de código abierto, desarrollado por syuilo desde el 2014"
about: "Misskey es un software de código abierto, desarrollado por syuilo desde 2014"
contributors: "Principales colaboradores"
allContributors: "Todos los colaboradores"
source: "Código fuente"
@@ -3311,7 +3316,7 @@ _clientPerformanceIssueTip:
_clip:
tip: "Clip es una función que permite organizar varias notas."
_userLists:
tip: "Las listas pueden contener cualquier usuario que especifiques al crearlas, la lista creada puede mostrarse entonces como una línea de tiempo mostrando solo los usuarios especificados."
tip: "Puedes crear listas que incluyan a cualquier usuario. Las listas creadas se pueden visualizar en forma de cronología."
watermark: "Marca de Agua"
defaultPreset: "Por defecto"
_watermarkEditor:
@@ -3400,11 +3405,9 @@ _imageEffector:
threshold: "Umbral"
centerX: "Centrar X"
centerY: "Centrar Y"
zoomLinesSmoothing: "Suavizado"
zoomLinesSmoothingDescription: "El suavizado y el ancho de línea de zoom no se pueden utilizar juntos."
zoomLinesThreshold: "Ancho de línea del zoom"
density: "Densidad"
zoomLinesOutlineThickness: "Grosor del borde"
zoomLinesMaskSize: "Diámetro del centro"
zoomLinesBlack: "Cambiar color de las líneas de impacto a negro."
circle: "Círculo"
drafts: "Borrador"
_drafts:

View File

@@ -1285,6 +1285,7 @@ inMinutes: "min"
inDays: "j"
widgets: "Widgets"
presets: "Préréglage"
previewingThemeRestore: "Restaurer"
_imageEditing:
_vars:
filename: "Nom du fichier"

View File

@@ -1291,6 +1291,7 @@ inMinutes: "menit"
inDays: "hari"
widgets: "Widget"
presets: "Prasetel"
previewingThemeRestore: "Kembalikan"
_imageEditing:
_vars:
filename: "Nama berkas"

View File

@@ -1,7 +1,7 @@
---
_lang_: "Italiano"
headlineMisskey: "Rete collegata tramite Note"
introMisskey: "Eccoci! Misskey è un servizio di microblogging decentralizzato, libero e aperto. \n\n📡 Puoi pubblicare «Note» per condividere ciò che sta succedendo o per dire a tutti qualcosa su di te. \n\n👍 Puoi reagire inviando emoji rapidi alle «Note» provenienti da altri profili nel Fediverso.\n\n🚀 Esplora un nuovo mondo insieme a noi!"
introMisskey: "Eccoci! Misskey è un servizio di microblogging decentralizzato, libero e aperto. \n📡 Puoi pubblicare «Note» per condividere ciò che sta succedendo o per dire a tutti qualcosa su di te. \n👍 Puoi reagire inviando emoji rapidi alle «Note» provenienti da altri profili nel Fediverso.\n🚀 Esplora un nuovo mondo insieme a noi!"
poweredByMisskeyDescription: "{name} è uno dei servizi (chiamati istanze) che utilizzano la piattaforma open source <b>Misskey</b>."
monthAndDay: "{day}/{month}"
search: "Cerca"
@@ -127,7 +127,7 @@ renoteToOtherChannel: "Rinota a un altro canale"
pinnedNote: "Nota in primo piano"
pinned: "Fissa sul profilo"
you: "Tu"
clickToShow: "Contenuto occultato, cliccare solo se si intende vedere"
clickToShow: "Media nascosto, cliccare solo se si intende vedere"
sensitive: "Esplicito"
add: "Aggiungi"
reaction: "Reazioni"
@@ -543,6 +543,7 @@ regenerate: "Generare di nuovo"
fontSize: "Dimensione carattere"
mediaListWithOneImageAppearance: "Altezza dell'elenco media con una sola immagine "
limitTo: "Limita a {x}"
showMediaListByGridInWideArea: "Quando la larghezza dello schermo è ampia, mostra i media affiancati"
noFollowRequests: "Non ci sono richieste di relazione"
openImageInNewTab: "Apri le immagini in un nuovo tab"
dashboard: "Pannello di controllo"
@@ -556,7 +557,7 @@ clientSettings: "Impostazioni client"
accountSettings: "Impostazioni profilo"
promotion: "Promossa"
promote: "Pubblicizza"
numberOfDays: "Numero di giorni"
numberOfDays: ""
hideThisNote: "Nasconda la nota"
showFeaturedNotesInTimeline: "Mostrare le note di tendenza nella tua timeline"
objectStorage: "Storage S3"
@@ -701,7 +702,7 @@ hardWordMuteDescription: "Ignora le Note con la parola o la regola specificata.
regexpError: "errore regex"
regexpErrorDescription: "Si è verificato un errore nell'espressione regolare alla riga {line} della parola muta {tab}:"
instanceMute: "Silenziare l'istanza"
userSaysSomething: "{name} ha detto qualcosa"
userSaysSomething: "{name} ha scritto qualcosa"
userSaysSomethingAbout: "{name} ha anNotato qualcosa su \"{word}\""
makeActive: "Attiva"
display: "Visualizza"
@@ -1407,6 +1408,9 @@ frame: "Cornice"
presets: "Preimpostato"
zeroPadding: "Al vivo"
nothingToConfigure: "Niente da configurare"
viewRenotedChannel: "Visualizza il canale del Rinota"
previewingTheme: "Anteprima del Tema"
previewingThemeRestore: "Ripristina"
_imageEditing:
_vars:
caption: "Didascalia dell'immagine"
@@ -2070,7 +2074,7 @@ _role:
gtlAvailable: "Disponibilità della Timeline Federata"
ltlAvailable: "Disponibilità della Timeline Locale"
canPublicNote: "Scrivere Note con Visibilità Pubblica"
mentionMax: "Numero massimo di menzioni in una nota"
mentionMax: ""
canInvite: "Generare codici di invito all'istanza"
inviteLimit: "Limite di codici invito"
inviteLimitCycle: "Intervallo di emissione del codice di invito"
@@ -2096,6 +2100,7 @@ _role:
canSearchNotes: "Ricercare nelle Note"
canSearchUsers: "Può cercare profili"
canUseTranslator: "Tradurre le Note"
canCreateChannel: "Può creare canali"
avatarDecorationLimit: "Numero massimo di decorazioni foto profilo installabili"
canImportAntennas: "Può importare Antenne"
canImportBlocking: "Può importare Blocchi"
@@ -2399,59 +2404,59 @@ _2fa:
backupCodesExhaustedWarning: "Hai esaurito i codici usa-e-getta. Se l'App che genera il codice OTP non è più disponibile, non potrai più accedere al tuo profilo. Ripeti la configurazione per l'autenticazione a due fattori."
moreDetailedGuideHere: "Informazioni dettagliate sull'autenticazione multi fattore (2FA/MFA)"
_permissions:
"read:account": "Visualizza le informazioni sul profilo"
"write:account": "Modifica le informazioni sul profilo"
"read:blocks": "Visualizza i profili bloccati"
"write:blocks": "Gestisci i profili bloccati"
"read:drive": "Apri il Drive"
"write:drive": "Gestisci il Drive"
"read:favorites": "Visualizza i tuoi preferiti"
"write:favorites": "Gestisci i tuoi preferiti"
"read:following": "Vedi le informazioni di follow"
"write:following": "Aggiungere e togliere Following"
"read:messaging": "Visualizzare la chat"
"write:messaging": "Gestire la chat"
"read:mutes": "Vedi i profili silenziati"
"write:mutes": "Gestione dei profili silenziati"
"write:notes": "Creare / Eliminare note"
"read:notifications": "Visualizzare notifiche"
"write:notifications": "Gestione delle notifiche"
"read:reactions": "Vedi reazioni"
"write:reactions": "Gestione delle reazioni"
"read:account": "Vedere le informazioni sul profilo"
"write:account": "Modificare le informazioni sul profilo"
"read:blocks": "Vedere i profili bloccati"
"write:blocks": "Gestire il blocco profili"
"read:drive": "Leggere file nel Drive"
"write:drive": "Gestire file nel Drive"
"read:favorites": "Vedere le Note Preferite"
"write:favorites": "Gestire Note Preferite"
"read:following": "Vedere i Following"
"write:following": "Gestire i Following"
"read:messaging": "Vedere Messaggi Privati"
"write:messaging": "Modificare Messaggi Privati"
"read:mutes": "Vedere profili silenziati"
"write:mutes": "Gestire profili silenziati"
"write:notes": "Gestire le Note"
"read:notifications": "Vedere le notifiche"
"write:notifications": "Gestire le notifiche"
"read:reactions": "Vedere le reazioni"
"write:reactions": "Gestire le reazioni"
"write:votes": "Votare"
"read:pages": "Visualizzare pagine"
"write:pages": "Gestire pagine"
"read:page-likes": "Visualizzare i \"Mi piace\" di pagine"
"write:page-likes": "Gestire i \"Mi piace\" di pagine"
"read:pages": "Vedere le pagine"
"write:pages": "Gestire le pagine"
"read:page-likes": "Vedere le Pagine piaciute"
"write:page-likes": "Modificare le Pagine piaciute"
"read:user-groups": "Vedere i gruppi di utenti"
"write:user-groups": "Gestire i gruppi di utenti"
"read:channels": "Visualizza canali"
"write:channels": "Gestione dei canali"
"read:gallery": "Visualizza la galleria."
"write:gallery": "Gestione della galleria"
"read:gallery-likes": "Visualizza i contenuti della galleria."
"write:gallery-likes": "Manipolazione dei \"Mi piace\" della galleria."
"read:flash": "Visualizza Play"
"write:flash": "Modifica Play"
"read:flash-likes": "Visualizza lista di Play piaciuti"
"write:flash-likes": "Modifica lista di Play piaciuti"
"read:admin:abuse-user-reports": "Mostra i report dai profili utente"
"write:admin:delete-account": "Elimina l'account utente"
"write:admin:delete-all-files-of-a-user": "Elimina i file dell'account utente"
"read:admin:index-stats": "Visualizza informazioni sugli indici del database"
"read:admin:table-stats": "Visualizza informazioni sulle tabelle del database"
"read:admin:user-ips": "Visualizza indirizzi IP degli account"
"read:admin:meta": "Visualizza i metadati dell'istanza"
"write:admin:reset-password": "Ripristina la password dell'account utente"
"write:admin:resolve-abuse-user-report": "Risolvere le segnalazioni dagli account utente"
"read:channels": "Vedere i canali"
"write:channels": "Gestire i canali"
"read:gallery": "Vedere le gallerie"
"write:gallery": "Gestire le gallerie"
"read:gallery-likes": "Vedere le Gallerie piaciute"
"write:gallery-likes": "Gestire le Gallerie piaciute"
"read:flash": "Vedere i Play"
"write:flash": "Gestire i Play"
"read:flash-likes": "Vedere la lista di Play piaciuti"
"write:flash-likes": "Modificare la lista di Play piaciuti"
"read:admin:abuse-user-reports": "Vedere le segnalazioni"
"write:admin:delete-account": "Eliminare profili"
"write:admin:delete-all-files-of-a-user": "Eliminare file dal Drive dei profili"
"read:admin:index-stats": "Vedere gli indici del database"
"read:admin:table-stats": "Vedere le statistiche database"
"read:admin:user-ips": "Vedere gli indirizzi IP dei profili"
"read:admin:meta": "Vedere i metadati dell'istanza"
"write:admin:reset-password": "Ripristinare la password del profilo"
"write:admin:resolve-abuse-user-report": "Risolvere le segnalazioni"
"write:admin:send-email": "Spedire email"
"read:admin:server-info": "Vedere le informazioni sul server"
"read:admin:show-moderation-log": "Vedere lo storico di moderazione"
"read:admin:show-user": "Vedere le informazioni private degli account utente"
"read:admin:show-user": "Vedere le informazioni private dei profili"
"write:admin:suspend-user": "Sospendere i profili"
"write:admin:unset-user-avatar": "Rimuovere la foto profilo dai profili"
"write:admin:unset-user-banner": "Rimuovere l'immagine testata dai profili"
"write:admin:unsuspend-user": "Togliere la sospensione ai profili"
"write:admin:unsuspend-user": "Rimuovere la sospensione ai profili"
"write:admin:meta": "Modificare i metadati dell'istanza"
"write:admin:user-note": "Scrivere annotazioni di moderazione"
"write:admin:roles": "Gestire i ruoli"
@@ -2479,11 +2484,11 @@ _permissions:
"read:admin:ad": "Vedere i banner pubblicitari"
"write:invite-codes": "Creare codici di invito"
"read:invite-codes": "Vedere i codici di invito"
"write:clip-favorite": "Impostare Clip preferite"
"write:clip-favorite": "Modificare Clip preferite"
"read:clip-favorite": "Vedere Clip preferite"
"read:federation": "Vedere la federazione"
"write:report-abuse": "Inviare segnalazioni"
"write:chat": "Gestire la chat"
"write:chat": "Modificare Messaggi Privati"
"read:chat": "Visualizzare le chat"
_auth:
shareAccessTitle: "Permessi dell'applicazione"
@@ -2532,19 +2537,19 @@ _widgets:
instanceCloud: "Nuvola di federazione"
postForm: "Finestra di pubblicazione"
slideshow: "Diapositive"
button: "Pulsante"
button: "Bottone"
onlineUsers: "Persone attive adesso"
jobQueue: "Coda di lavoro"
serverMetric: "Statistiche server"
aiscript: "Console AiScript"
aiscriptApp: "App AiScript"
aichan: "Mascotte Ai"
userList: "Elenco utenti"
userList: "Lista profili"
_userList:
chooseList: "Seleziona una lista"
clicker: "Cliccheria"
birthdayFollowings: "Compleanni del giorno"
chat: "Chatta con questa persona"
chat: "Messaggi diretti"
_widgetOptions:
showHeader: "Mostra la testata"
transparent: "Sfondo trasparente"
@@ -2660,7 +2665,7 @@ _profile:
metadataContent: "Contenuto"
changeAvatar: "Modifica immagine profilo"
changeBanner: "Cambia intestazione"
verifiedLinkDescription: "Puoi verificare il tuo profilo mostrando una icona. Devi inserire la URL alla pagina che contiene un link al tuo profilo.\nPer verificare il profilo tramite la spunta di conferma, devi inserire la url alla pagina che contiene un link al tuo profilo Misskey. Deve avere attributo rel='me'."
verifiedLinkDescription: "Come avere i collegamenti verificati: inserisci la URL ad una pagina che contiene un collegamento al tuo profilo.\nVedrai una spunta di conferma se, in quella pagina, il collegamento al tuo profilo Misskey ha attributo rel='me'."
avatarDecorationMax: "Puoi aggiungere fino a {max} decorazioni."
followedMessage: "Messaggio, quando qualcuno ti segue"
followedMessageDescription: "Puoi impostare un breve messaggio da mostrare agli altri profili quando ti seguono."
@@ -2780,7 +2785,7 @@ _notification:
fileUploaded: "File caricato correttamente"
youGotMention: "{name} ti ha menzionato"
youGotReply: "{name} ti ha risposto"
youGotQuote: "{name} ha citato la tua Nota e ha detto"
youGotQuote: "{name} ha scritto citando la tua Nota"
youRenoted: "{name} ha rinotato"
youWereFollowed: "Follower aggiuntivo"
youReceivedFollowRequest: "Hai ricevuto una richiesta di follow"
@@ -2806,7 +2811,7 @@ _notification:
exportOfXCompleted: "Abbiamo completato l'esportazione di {x}"
login: "Autenticazione avvenuta"
createToken: "È stato creato un token di accesso"
createTokenDescription: "In caso contrario, eliminare il token di accesso tramite ({text})."
createTokenDescription: "Se non ne sai nulla, elimina il token di accesso: {text}."
_types:
all: "Tutte"
note: "Nuove Note"
@@ -3337,7 +3342,7 @@ _watermarkEditor:
stripeWidth: "Larghezza della linea"
stripeFrequency: "Il numero di linee"
polkadot: "A pallini"
checker: "revisore"
checker: "Scacchiera"
polkadotMainDotOpacity: "Opacità del punto principale"
polkadotMainDotRadius: "Dimensione del punto principale"
polkadotSubDotOpacity: "Opacità del punto secondario"
@@ -3366,7 +3371,7 @@ _imageEffector:
zoomLines: "Linea di saturazione"
stripe: "Strisce"
polkadot: "A pallini"
checker: "revisore"
checker: "Scacchiera"
blockNoise: "Attenua rumore"
tearing: "Strappa immagine"
fill: "Riempimento"
@@ -3400,11 +3405,9 @@ _imageEffector:
threshold: "Soglia"
centerX: "Centro orizzontale"
centerY: "Centro verticale"
zoomLinesSmoothing: "Levigatura"
zoomLinesSmoothingDescription: "Non si possono usare insieme la levigatura e la larghezza della linea centrale."
zoomLinesThreshold: "Limite delle linee zoom"
density: "Densità"
zoomLinesOutlineThickness: "Spessore del bordo"
zoomLinesMaskSize: "Ampiezza del diametro"
zoomLinesBlack: "Bande nere"
circle: "Circolare"
drafts: "Bozze"
_drafts:

View File

@@ -1408,6 +1408,7 @@ frame: "フレーム"
presets: "プリセット"
zeroPadding: "ゼロ埋め"
nothingToConfigure: "設定項目はありません"
viewRenotedChannel: "リノート先のチャンネルを見る"
_imageEditing:
_vars:
@@ -2121,6 +2122,7 @@ _role:
canSearchNotes: "ノート検索の利用"
canSearchUsers: "ユーザー検索の利用"
canUseTranslator: "翻訳機能の利用"
canCreateChannel: "チャンネルの作成"
avatarDecorationLimit: "アイコンデコレーションの最大取付個数"
canImportAntennas: "アンテナのインポートを許可"
canImportBlocking: "ブロックのインポートを許可"
@@ -3180,79 +3182,6 @@ _reversi:
showBoardLabels: "盤面に行・列番号を表示"
useAvatarAsStone: "石をアイコンにする"
_mahjong:
mahjong: "麻雀"
joinRoom: "ルームに参加"
createRoom: "ルームを作成"
ready: "準備完了"
cancelReady: "準備を再開"
leave: "退室"
addCpu: "CPUを追加"
east: "東"
south: "南"
west: "西"
north: "北"
dora: "ドラ"
redDora: "赤ドラ"
fan: "飜"
_fanNames:
mangan: "満貫"
haneman: "跳満"
baiman: "倍満"
sanbaiman: "三倍満"
yakuman: "役満"
kazoeyakuman: "数え役満"
_yakus:
"riichi": "立直"
"ippatsu": "一発"
"tsumo": "門前清自摸和"
"tanyao": "断么"
"pinfu": "平和"
"iipeko": "一盃口"
"field-wind-e": "東"
"field-wind-s": "南"
"seat-wind-e": "東"
"seat-wind-s": "南"
"seat-wind-w": "西"
"seat-wind-n": "北"
"white": "白"
"green": "發"
"red": "中"
"rinshan": "嶺上開花"
"chankan": "搶槓"
"haitei": "海底摸月"
"hotei": "河底撈魚"
"sanshoku-dojun": "三色同順"
"sanshoku-doko": "三色同刻"
"ittsu": "一気通貫"
"chanta": "混全帯么九"
"chitoitsu": "七対子"
"toitoi": "対々"
"sananko": "三暗刻"
"honroto": "混老頭"
"sankantsu": "三槓子"
"shosangen": "小三元"
"double-riichi": "ダブル立直"
"honitsu": "混一色"
"junchan": "清全帯么九"
"ryampeko": "ニ盃口"
"chinitsu": "清一色"
"kokushi": "国士無双"
"kokushi-13": "国士無双十三面待"
"suanko": "四暗刻"
"suanko-tanki": "四暗刻単騎待"
"daisangen": "大三元"
"tsuiso": "字一色"
"shosushi": "小四喜"
"daisushi": "大四喜"
"ryuiso": "緑一色"
"chinroto": "清老頭"
"sukantsu": "四槓子"
"churen": "九蓮宝燈"
"churen-9": "九連宝灯九面待"
"tenho": "天和"
"chiho": "地和"
_offlineScreen:
title: "オフライン - サーバーに接続できません"
header: "サーバーに接続できません"
@@ -3585,11 +3514,9 @@ _imageEffector:
threshold: "しきい値"
centerX: "中心X"
centerY: "中心Y"
zoomLinesSmoothing: "スムージング"
zoomLinesSmoothingDescription: "スムージングと集中線の幅の設定は併用できません。"
zoomLinesThreshold: "集中線の幅"
density: "密度"
zoomLinesOutlineThickness: "線の影の太さ"
zoomLinesMaskSize: "中心径"
zoomLinesBlack: "黒色にする"
circle: "円形"
drafts: "下書き"

View File

@@ -1355,6 +1355,7 @@ widgets: "ウィジェット"
deviceInfoDescription: "なんか技術的なことで分からんこと聞くときは、下の情報も一緒に書いてもらえると、こっちも分かりやすいし、はよ直ると思います。"
youAreAdmin: "あんた、管理者やで"
presets: "プリセット"
previewingThemeRestore: "元に戻す"
_imageEditing:
_vars:
filename: "ファイル名"

View File

@@ -543,6 +543,7 @@ regenerate: "재생성"
fontSize: "글자 크기"
mediaListWithOneImageAppearance: "이미지가 1개 뿐인 미디어 목록의 높이"
limitTo: "{x}로 제한"
showMediaListByGridInWideArea: "화면 폭이 넓을 때는 미디어 목록을 가로로 표시하기"
noFollowRequests: "처리되지 않은 팔로우 요청이 없습니다"
openImageInNewTab: "새 탭에서 이미지 열기"
dashboard: "대시보드"
@@ -1334,7 +1335,7 @@ markAsSensitiveConfirm: "이 미디어를 민감한 미디어로 설정하시겠
unmarkAsSensitiveConfirm: "이 미디어의 민감한 미디어 지정을 해제하시겠습니까?"
preferences: "환경설정"
accessibility: "접근성"
preferencesProfile: "설정 프로"
preferencesProfile: "설정 프로파일"
copyPreferenceId: "설정한 ID를 복사"
resetToDefaultValue: "기본값으로 되돌리기"
overrideByAccount: "계정으로 덮어쓰기"
@@ -1347,7 +1348,7 @@ preferenceSyncConflictTitle: "서버에 설정값이 존재합니다."
preferenceSyncConflictText: "동기화를 활성화 한 항목의 설정 값은 서버에 저장되지만, 해당 항목은 이미 서버에 설정 값이 저장되어져 있습니다. 어느 쪽의 설정 값을 덮어씌울까요?"
preferenceSyncConflictChoiceMerge: "병합"
preferenceSyncConflictChoiceServer: "서버 설정값"
preferenceSyncConflictChoiceDevice: "장치 설정값"
preferenceSyncConflictChoiceDevice: "장치 설정 값"
preferenceSyncConflictChoiceCancel: "동기화 취소"
paste: "붙여넣기"
emojiPalette: "이모지 팔레트"
@@ -1407,6 +1408,9 @@ frame: "프레임"
presets: "프리셋"
zeroPadding: "0으로 채우기"
nothingToConfigure: "설정 항목이 없습니다."
viewRenotedChannel: "리노트된 채널 보기"
previewingTheme: "테마 미리보기 중"
previewingThemeRestore: "복구"
_imageEditing:
_vars:
caption: "파일 설명"
@@ -1465,17 +1469,17 @@ _chat:
newMessage: "새로운 메시지"
individualChat: "개인 대화"
individualChat_description: "특정 유저와 일대일 채팅을 할 수 있습니다."
roomChat: " 채팅"
roomChat: "그룹 채팅"
roomChat_description: "여러 명이 함께 채팅할 수 있습니다.\n또한, 개인 채팅을 허용하지 않은 유저와도 상대방이 수락하면 채팅을 할 수 있습니다."
createRoom: "룸을 생성"
createRoom: "방 만들기"
inviteUserToChat: "유저를 초대하여 채팅을 시작하세요"
yourRooms: "생성한 룸"
joiningRooms: "참가 중인 "
yourRooms: "만들어진 방"
joiningRooms: "참가 중인 "
invitations: "초대"
noInvitations: "초대장이 없습니다"
history: "이력"
noHistory: "기록이 없습니다"
noRooms: "이 없습니다"
noRooms: "이 없습니다"
inviteUser: "유저를 초대"
sentInvitations: "초대를 보내기"
join: "참여"
@@ -1486,14 +1490,14 @@ _chat:
home: "홈"
send: "전송"
newline: "줄바꿈"
muteThisRoom: "이 을 뮤트"
deleteRoom: "을 삭제"
muteThisRoom: "이 을 뮤트하기"
deleteRoom: "을 삭제하기"
chatNotAvailableForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅이 활성화되어 있지 않습니다."
chatIsReadOnlyForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅은 읽기 전용입니다. 새로 쓰거나 채팅 룸을 만들거나 참가할 수 없습니다."
chatNotAvailableInOtherAccount: "상대방 계정에서 채팅 기능을 사용할 수 없는 상태입니다."
cannotChatWithTheUser: "이 유저와 채팅을 시작할 수 없습니다"
cannotChatWithTheUser_description: "채팅을 사용할 수 없는 상태이거나 상대방이 채팅을 열지 않은 상태입니다."
youAreNotAMemberOfThisRoomButInvited: "당신은 의 참가자가 아닙니다만 초대 신청을 받으셨습니다. 참가하려면 초대를 수락해주십시오."
youAreNotAMemberOfThisRoomButInvited: "이 의 참가자가 아니지만 초대를 받았습니다. 참가하려면 초대를 수락하세요."
doYouAcceptInvitation: "초대를 수락하시겠습니까?"
chatWithThisUser: "채팅하기"
thisUserAllowsChatOnlyFromFollowers: "이 유저는 팔로워만 채팅을 할 수 있습니다."
@@ -1558,11 +1562,11 @@ _settings:
showSenderName: "발신자 이름 표시"
sendOnEnter: "엔터로 보내기"
_preferencesProfile:
profileName: "프로 이름"
profileName: "프로파일 이름"
profileNameDescription: "이 디바이스를 식별할 이름을 설정해 주세요."
profileNameDescription2: "예: '메인PC', '스마트폰' 등"
manageProfiles: "프로파일 관리"
shareSameProfileBetweenDevicesIsNotRecommended: "여러 장치에서 동일한 프로을 공유하는 것은 권장하지 않습니다."
shareSameProfileBetweenDevicesIsNotRecommended: "여러 장치에서 같은 프로파일을 공유하는 것은 권장하지 않습니다."
useSyncBetweenDevicesOptionIfYouWantToSyncSetting: "여러 장치에서 동기화하고 싶은 설정 항목이 있는 경우에는 개별로 '여러 장치에서 동기화' 옵션을 활성화해 주십시오."
_preferencesBackup:
autoBackup: "자동 백업"
@@ -1570,7 +1574,7 @@ _preferencesBackup:
noBackupsFoundTitle: "백업을 찾을 수 없습니다"
noBackupsFoundDescription: "자동으로 생성된 백업은 찾을 수 없었지만, 수동으로 백업 파일을 저장한 경우 해당 파일을 가져와 복원할 수 있습니다."
selectBackupToRestore: "복원할 백업을 선택하세요"
youNeedToNameYourProfileToEnableAutoBackup: "자동 백업을 활성화하려면 프로 이름을 설정해야 합니다."
youNeedToNameYourProfileToEnableAutoBackup: "자동 백업을 활성화하려면 프로파일 이름을 설정해야 합니다."
autoPreferencesBackupIsNotEnabledForThisDevice: "이 장치에서 설정 자동 백업이 활성화되어 있지 않습니다."
backupFound: "설정 백업이 발견되었습니다"
forceBackup: "설정 강제 백업"
@@ -2096,6 +2100,7 @@ _role:
canSearchNotes: "노트 검색 이용 가능 여부"
canSearchUsers: "유저 검색 이용"
canUseTranslator: "번역 기능의 사용"
canCreateChannel: "패널 생성"
avatarDecorationLimit: "아바타 장식의 최대 붙임 개수"
canImportAntennas: "안테나 가져오기 허용"
canImportBlocking: "차단 목록 가져오기 허용"
@@ -2543,7 +2548,7 @@ _widgets:
_userList:
chooseList: "리스트 선택"
clicker: "클리커"
birthdayFollowings: "오늘이 생일인 유저"
birthdayFollowings: " 생일인 사용자"
chat: "채팅하기"
_widgetOptions:
showHeader: "해더를 표시"
@@ -2791,7 +2796,7 @@ _notification:
newNote: "새 게시물"
unreadAntennaNote: "안테나 {name}"
roleAssigned: "역할이 부여 되었습니다."
chatRoomInvitationReceived: "채팅에 초대받았습니다"
chatRoomInvitationReceived: "채팅에 초대되었습니다"
emptyPushNotificationMessage: "푸시 알림이 갱신되었습니다"
achievementEarned: "도전 과제를 달성했습니다"
testNotification: "알림 테스트"
@@ -2822,7 +2827,7 @@ _notification:
receiveFollowRequest: "팔로우 요청을 받았을 때"
followRequestAccepted: "팔로우 요청이 승인되었을 때"
roleAssigned: "역할이 부여됨"
chatRoomInvitationReceived: "채팅에 초대받음"
chatRoomInvitationReceived: "채팅에 초대"
achievementEarned: "도전 과제 획득"
exportCompleted: "추출을 성공함"
login: "로그인"
@@ -2857,15 +2862,15 @@ _deck:
useSimpleUiForNonRootPages: "루트 이외의 페이지로 접속한 경우 UI 간략화하기"
usedAsMinWidthWhenFlexible: "'폭 자동 조정'이 활성화된 경우 최소 폭으로 사용됩니다"
flexible: "폭 자동 조정"
enableSyncBetweenDevicesForProfiles: "프로파일 정보의 디바이스 간 동기화를 활성화"
enableSyncBetweenDevicesForProfiles: "프로파일 정보의 장치 간 동기화를 활성화"
showHowToUse: "UI 설명 보기"
_howToUse:
addColumn_title: "칼럼 추가"
addColumn_description: "칼럼의 종류를 선택해 추가할 수 있습니다."
settings_title: "UI 설정"
settings_description: "덱 UI의 상세 설정을 할 수 있습니다."
switchProfile_title: "프로 전환"
switchProfile_description: "UI의 레이아웃을 프로로 저장하고, 언제 전환할 수 있습니다."
switchProfile_title: "프로파일 전환"
switchProfile_description: "UI의 레이아웃을 프로파일로 저장하고 언제든지 전환할 수 있습니다."
_columns:
main: "메인"
widgets: "위젯"
@@ -2976,7 +2981,7 @@ _moderationLogTypes:
deletePage: "페이지를 삭제"
deleteFlash: "Play를 삭제"
deleteGalleryPost: "갤러리 게시물을 삭제"
deleteChatRoom: "채팅 삭제"
deleteChatRoom: "채팅 삭제하기"
updateProxyAccountDescription: "프록시 계정의 설명 업데이트"
_fileViewer:
title: "파일 상세"
@@ -3400,11 +3405,9 @@ _imageEffector:
threshold: "한계 값"
centerX: "X축 중심"
centerY: "Y축 중심"
zoomLinesSmoothing: "다듬기"
zoomLinesSmoothingDescription: "다듬기와 집중선 폭 설정은 같이 쓸 수 없습니다."
zoomLinesThreshold: "집중선 폭"
density: "밀도"
zoomLinesOutlineThickness: "선 그림자의 굵기"
zoomLinesMaskSize: "중앙 값"
zoomLinesBlack: "검은색으로 하기"
circle: "원형"
drafts: "초안"
_drafts:

View File

@@ -5,6 +5,7 @@ introMisskey: "ຍິນດີຕ້ອນຮັບ! Misskey ເປັນຊອ
poweredByMisskeyDescription: "{name} ແມ່ນສ່ວນໜຶ່ງຂອງການບໍລິການທີ່ຂັບເຄື່ອນໂດຍແພລດຟອມ open source. <b>Misskey</b> (ເອີ້ນວ່າ \"Misskey instance\")"
monthAndDay: "ເດືອນ{month} / ວັນ{day}"
search: "ຄົ້ນຫາ"
reset: "ຣີເຊັດ"
notifications: "ການແຈ້ງເຕືອນ"
username: "ຊື່ຜູ້ໃຊ້"
password: "ລະຫັດຜ່ານ"

View File

@@ -970,6 +970,7 @@ renotes: "Herdelen"
followingOrFollower: "Gevolgd of volger"
confirmShowRepliesAll: "Dit is een onomkeerbare operatie. Weet je zeker dat reacties op anderen van iedereen die je volgt, wil weergeven in je tijdlijn?"
information: "Over"
previewingThemeRestore: "Herstellen"
_imageEditing:
_vars:
filename: "Bestandsnaam"

View File

@@ -1044,6 +1044,7 @@ inMinutes: "minuta"
inDays: "dzień"
widgets: "Widżety"
presets: "Konfiguracja"
previewingThemeRestore: "Przywróć"
_imageEditing:
_vars:
filename: "Nazwa pliku"

View File

@@ -1391,6 +1391,7 @@ schedule: "Agendar"
scheduled: "Agendado"
widgets: "Widgets"
presets: "Predefinições"
previewingThemeRestore: "Restaurar"
_imageEditing:
_vars:
filename: "Nome do Ficheiro"
@@ -3289,11 +3290,7 @@ _imageEffector:
threshold: "Limiar"
centerX: "Centralizar X"
centerY: "Centralizar Y"
zoomLinesSmoothing: "Suavização"
zoomLinesSmoothingDescription: "Suavização e largura das linhas de zoom não podem ser utilizados simultaneamente."
zoomLinesThreshold: "Largura das linhas de zoom"
zoomLinesMaskSize: "Diâmetro do centro"
zoomLinesBlack: "Linhas pretas"
circle: "Circular"
drafts: "Rascunhos"
_drafts:

View File

@@ -1216,6 +1216,7 @@ surrender: "Anulează"
copyPreferenceId: "Copiază ID-ul preferințelor"
information: "Despre"
presets: "Presetate"
previewingThemeRestore: "Restabilește"
_imageEditing:
_vars:
filename: "Nume fișier"

View File

@@ -1231,6 +1231,7 @@ showRepliesToOthersInTimelineAll: "Показывать в ленте ответ
hideRepliesToOthersInTimelineAll: "Скрывать в ленте ответы пользователей, на которых вы подписаны"
confirmShowRepliesAll: "Это нельзя будет отменить. Показать ответы от всех, на кого вы подписаны?"
confirmHideRepliesAll: "Это нельзя будет отменить. Скрыть ответы от всех, на кого вы подписаны?"
externalServices: "Интеграции"
sourceCode: "Исходный код"
sourceCodeIsNotYetProvided: "Исходный код пока не доступен. Свяжитесь с администратором, чтобы исправить эту проблему."
repositoryUrl: "Ссылка на репозиторий"
@@ -1331,7 +1332,9 @@ overrideByAccount: "Переопределить этим аккаунтом"
untitled: "Без названия"
noName: "Имя не указано"
skip: "Пропустить"
restore: "Восстановить"
syncBetweenDevices: "Синхронизировать между устройствами"
paste: "вставить"
postForm: "Форма отправки"
textCount: "Количество символов"
information: "Описание"
@@ -1347,6 +1350,7 @@ frame: "Рамки"
presets: "Шаблоны"
zeroPadding: "Без отступов"
nothingToConfigure: "Нечего менять"
previewingThemeRestore: "Восстановить"
_imageEditing:
_vars:
caption: "Описание файла"
@@ -2394,6 +2398,8 @@ _imageEffector:
opacity: "Непрозрачность"
lightness: "Осветление"
drafts: "Черновик"
_drafts:
restore: "Восстановить"
_qr:
showTabTitle: "Отображение"
raw: "Текст"

View File

@@ -916,6 +916,7 @@ information: "Informácie"
inMinutes: "min"
inDays: "dní"
widgets: "Widgety"
previewingThemeRestore: "Obnoviť"
_imageEditing:
_vars:
filename: "Názov súboru"

View File

@@ -559,6 +559,7 @@ tryAgain: "Försök igen senare"
signinWithPasskey: "Logga in med nyckel"
unknownWebAuthnKey: "Okänd nyckel"
information: "Om"
previewingThemeRestore: "Återställ"
_imageEditing:
_vars:
filename: "Filnamn"

View File

@@ -83,6 +83,8 @@ files: "ไฟล์"
download: "ดาวน์โหลด"
driveFileDeleteConfirm: "ต้องการลบไฟล์ “{name}” ใช่ไหม? โน้ตที่แนบมากับไฟล์นี้ก็จะถูกลบไปด้วย"
unfollowConfirm: "ต้องการเลิกติดตาม {name} ใช่ไหม?"
cancelFollowRequestConfirm: "ยกเลิกคำขอติดตาม {name} ใช่ไหม?"
rejectFollowRequestConfirm: "ปฏิเสธคำขอติดตามจาก {name} ใช่ไหม?"
exportRequested: "คุณได้ร้องขอการส่งออก อาจใช้เวลาสักครู่ และจะถูกเพิ่มในไดรฟ์ของคุณเมื่อเสร็จสิ้นแล้ว"
importRequested: "คุณได้ร้องขอการนำเข้า การดำเนินการนี้อาจใช้เวลาสักครู่"
lists: "รายชื่อ"
@@ -204,7 +206,7 @@ host: "โฮสต์"
selectSelf: "เลือกตัวเอง"
selectUser: "เลือกผู้ใช้งาน"
recipient: "ผู้รับ"
annotation: "หมายเหตุประกอบ"
annotation: "ข้อความเกริ่น"
federation: "สหพันธ์"
instances: "เซิร์ฟเวอร์"
registeredAt: "วันที่ลงทะเบียน"
@@ -222,7 +224,7 @@ operations: "ดำเนินการ"
software: "ซอฟต์แวร์"
softwareName: "ชื่อซอฟต์แวร์"
version: "เวอร์ชั่น"
metadata: "Metadata"
metadata: "เมทาเดต้า"
withNFiles: "{n} ไฟล์"
monitor: "มอนิเตอร์"
jobQueue: "คิวงาน"
@@ -302,6 +304,7 @@ uploadFromUrlMayTakeTime: "การอัปโหลดอาจใช้เ
uploadNFiles: "อัปโหลด {n} ไฟล์"
explore: "สำรวจ"
messageRead: "อ่านแล้ว"
readAllChatMessages: "ทำเครื่องหมายใส่ข้อความทั้งหมดว่าอ่านแล้ว"
noMoreHistory: "ไม่มีประวัติเพิ่มเติม"
startChat: "เริ่มแชต"
nUsersRead: "อ่านโดย {n}"
@@ -334,6 +337,7 @@ fileName: "ชื่อไฟล์"
selectFile: "เลือกไฟล์"
selectFiles: "เลือกไฟล์"
selectFolder: "เลือกโฟลเดอร์"
unselectFolder: "ยกเลิกการเลือกโฟลเดอร์"
selectFolders: "เลือกโฟลเดอร์"
fileNotSelected: "ยังไม่ได้เลือกไฟล์"
renameFile: "เปลี่ยนชื่อไฟล์"
@@ -346,6 +350,7 @@ addFile: "เพิ่มไฟล์"
showFile: "แสดงไฟล์"
emptyDrive: "ไดรฟ์ของคุณว่างเปล่านะ"
emptyFolder: "โฟลเดอร์นี้ว่างเปล่า"
dropHereToUpload: "ดรอปไฟล์ลงที่นี่เพื่ออัปโหลด"
unableToDelete: "ไม่สามารถลบออกได้"
inputNewFileName: "ป้อนชื่อไฟล์ใหม่"
inputNewDescription: "กรุณาใส่แคปชั่นใหม่"
@@ -428,7 +433,7 @@ antennaKeywordsDescription: "คั่นด้วยเว้นวรรคส
notifyAntenna: "แจ้งเตือนเกี่ยวกับโน้ตใหม่"
withFileAntenna: "เฉพาะโน้ตที่มีไฟล์"
excludeNotesInSensitiveChannel: "ไม่รวมโน้ตจากช่องเนื้อหาละเอียดอ่อน"
enableServiceworker: "เปิดใช้งานการแจ้งเตือนแบบพุชไปยังเบราว์เซอร์ของคุณ"
enableServiceworker: "เปิดใช้งานการแจ้งเตือนแบบพุชไปยังเบราว์เซอร์"
antennaUsersDescription: "ระบุหนึ่งชื่อผู้ใช้ต่อบรรทัด"
caseSensitive: "อักษรพิมพ์ใหญ่-พิมพ์เล็กความหมายต่างกัน"
withReplies: "รวมตอบกลับ"
@@ -538,6 +543,7 @@ regenerate: "สร้างอีกครั้ง"
fontSize: "ขนาดตัวอักษร"
mediaListWithOneImageAppearance: "ความสูงของรายการสื่อที่มีเพียงรูปเดียว"
limitTo: "จำกัดไว้ที่ {x}"
showMediaListByGridInWideArea: "เมื่อหน้าจอกว้างยาวขึ้น ให้เรียงรายการสื่อเป็นแนวนอน"
noFollowRequests: "คุณไม่มีคำขอติดตามที่รอดำเนินการ"
openImageInNewTab: "เปิดรูปภาพในแท็บใหม่"
dashboard: "หน้ากระดานหลัก"
@@ -612,7 +618,7 @@ uiInspectorDescription: "คุณสามารถตรวจสอบรา
output: "เอาท์พุต"
script: "สคริปต์"
disablePagesScript: "ปิดการใช้งาน AiScript บนเพจ"
updateRemoteUser: "อัปเดตข้อมูลผู้ใช้งานระยะไกล"
updateRemoteUser: "อัปเดตข้อมูลผู้ใช้ระยะไกล"
unsetUserAvatar: "เลิกตั้งไอคอน"
unsetUserAvatarConfirm: "ต้องการเลิกตั้งไอคอนประจำตัวหรือไม่?"
unsetUserBanner: "เลิกตั้งแบนเนอร์"
@@ -773,6 +779,7 @@ lockedAccountInfo: "แม้ว่าการอนุมัติการต
alwaysMarkSensitive: "ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อนเป็นค่าเริ่มต้น"
loadRawImages: "โหลดภาพต้นฉบับแทนการแสดงภาพขนาดย่อ"
disableShowingAnimatedImages: "ไม่ต้องเล่นภาพเคลื่อนไหว"
disableShowingAnimatedImages_caption: "หากภาพเคลื่อนไหวไม่เล่นแม่จะปิดตั้งค่านี้ไปแล้ว อาจเป็นกรณีที่การตั้งค่าการช่วยการเข้าถึงหรือการประหยัดพลังงาน ของเบราว์เซอร์/OS เข้าแทรกแซง"
highlightSensitiveMedia: "ไฮไลท์สื่อที่มีเนื้อหาละเอียดอ่อน"
verificationEmailSent: "ได้ส่งอีเมลยืนยันแล้ว กรุณาเข้าลิงก์ที่ระบุในอีเมลเพื่อทำการตั้งค่าให้เสร็จสิ้น"
notSet: "ไม่ได้ตั้งค่า"
@@ -887,7 +894,7 @@ low: "ต่ำ"
emailNotConfiguredWarning: "ยังไม่ได้ตั้งค่าที่อยู่อีเมล"
ratio: "อัตราส่วน"
previewNoteText: "แสดงตัวอย่าง"
customCss: "CSS ที่กำหนดเอง"
customCss: "CSS แบบกำหนดเอง"
customCssWarn: "ควรใช้การตั้งค่านี้เฉพาะต่อเมื่อคุณรู้มันใช้ทำอะไร การตั้งค่าที่ไม่เหมาะสมอาจทำให้ไคลเอ็นต์ไม่สามารถใช้งานได้อย่างถูกต้อง"
global: "ทั่วโลก"
squareAvatars: "แสดงไอคอนประจำตัวเป็นสี่เหลี่ยม"
@@ -930,7 +937,7 @@ unmuteThread: "เลิกปิดเสียงเธรด"
followingVisibility: "การมองเห็นที่เรากำลังติดตาม"
followersVisibility: "การมองเห็นผู้ที่กำลังติดตามเรา"
continueThread: "ดูความต่อเนื่องเธรด"
deleteAccountConfirm: "การดำเนินการนี้จะลบบัญชีของคุณอย่างถาวรเลยนะ แน่ใจหรอดำเนินการ?"
deleteAccountConfirm: "บัญชีจะถูกลบ ดำเนินการต่อใช่ไหม?"
incorrectPassword: "รหัสผ่านไม่ถูกต้อง"
incorrectTotp: "รหัสยืนยันตัวตนแบบใช้ครั้งเดียวที่ท่านได้ระบุมานั้น ไม่ถูกต้องหรือหมดอายุลงแล้วค่ะ"
voteConfirm: "ต้องการโหวต “{choice}” ใช่ไหม?"
@@ -991,7 +998,7 @@ pleaseSelect: "ตัวเลือก"
reverse: "พลิก"
colored: "สี"
refreshInterval: "ความถี่ในการอัปเดต"
label: "ป้ายชื่อ"
label: "ป้าย"
type: "รูปแบบ"
speed: "ความเร็ว"
slow: "ช้า"
@@ -1019,6 +1026,9 @@ pushNotificationAlreadySubscribed: "การแจ้งเตือนแบ
pushNotificationNotSupported: "เบราว์เซอร์หรือเซิร์ฟเวอร์ไม่รองรับการแจ้งเตือนแบบพุช"
sendPushNotificationReadMessage: "ลบการแจ้งเตือนแบบพุชเมื่ออ่านการแจ้งเตือนหรือข้อความที่เกี่ยวข้องแล้ว"
sendPushNotificationReadMessageCaption: "อาจทำให้อุปกรณ์ของคุณใช้พลังงานมากขึ้น"
pleaseAllowPushNotification: "โปรดอนุญาตการตั้งค่าการแจ้งเตือนของเบราว์เซอร์"
browserPushNotificationDisabled: "ขอสิทธิ์ส่งการแจ้งเตือนล้มเหลว"
browserPushNotificationDisabledDescription: "ไม่มีสิทธิ์ในการส่งการแจ้งเตือนจาก {serverName} โปรดอนุญาตการแจ้งเตือนในตั้งค่าของเบราว์เซอร์ แล้วลองอีกครั้ง"
windowMaximize: "ขยายใหญ่สุด"
windowMinimize: "ย่อเล็กที่สุด"
windowRestore: "เลิกทำ"
@@ -1099,8 +1109,8 @@ license: "ใบอนุญาต"
unfavoriteConfirm: "ลบออกจากรายการโปรดแน่ใจหรอ?"
myClips: "คลิปของฉัน"
drivecleaner: "ทำความสะอาดไดรฟ์"
retryAllQueuesNow: "ลองเรียกใช้คิวทั้งหมดอีกครั้ง"
retryAllQueuesConfirmTitle: "ลองใหม่ทั้งหมดจริงๆหรอแน่ใจนะ?"
retryAllQueuesNow: "ลองใหม่ทุกคิวทันที"
retryAllQueuesConfirmTitle: "ลองใหม่ทันทีเลยไหม?"
retryAllQueuesConfirmText: "สิ่งนี้จะเพิ่มการโหลดเซิร์ฟเวอร์ชั่วคราวนะ"
enableChartsForRemoteUser: "สร้างแผนภูมิข้อมูลผู้ใช้ระยะไกล"
enableChartsForFederatedInstances: "สร้างแผนภูมิของเซิร์ฟเวอร์ระยะไกล"
@@ -1150,7 +1160,7 @@ initialAccountSetting: "ตั้งค่าโปรไฟล์"
youFollowing: "ติดตามแล้ว"
preventAiLearning: "ปฏิเสธการเรียนรู้ด้วย generative AI"
preventAiLearningDescription: "ส่งคำร้องขอไม่ให้ใช้ ข้อความในโน้ตที่โพสต์, หรือเนื้อหารูปภาพ ฯลฯ ในการเรียนรู้ของเครื่อง(machine learning) / Predictive AI / Generative AI โดยการเพิ่มแฟล็ก “noai” ลง HTML-Response ให้กับเนื้อหาที่เกี่ยวข้อง แต่ทั้งนี้ ไม่ได้ป้องกัน AI จากการเรียนรู้ได้อย่างสมบูรณ์ เนื่องจากมี AI บางตัวเท่านั้นที่จะเคารพคำขอดังกล่าว"
options: "ตัวเลือกบทบาท"
options: "ตัวเลือก"
specifyUser: "ผู้ใช้เฉพาะ"
lookupConfirm: "ต้องการเรียกดูข้อมูลใช่ไหม?"
openTagPageConfirm: "ต้องการเปิดหน้าแฮชแท็กใช่ไหม?"
@@ -1169,6 +1179,7 @@ installed: "ติดตั้งแล้ว"
branding: "แบรนดิ้ง"
enableServerMachineStats: "เผยแพร่สถานะฮาร์ดแวร์ของเซิร์ฟเวอร์"
enableIdenticonGeneration: "เปิดใช้งานผู้ใช้สร้างตัวระบุ"
showRoleBadgesOfRemoteUsers: "แสดงตราบทบาทที่มอบให้กับผู้ใช้ระยะไกล"
turnOffToImprovePerformance: "การปิดส่วนนี้สามารถเพิ่มประสิทธิภาพได้"
createInviteCode: "สร้างรหัสเชิญ"
createWithOptions: "สร้างด้วยตัวเลือก"
@@ -1247,7 +1258,7 @@ refreshing: "กำลังรีเฟรช..."
pullDownToRefresh: "ดึงลงเพื่อรีเฟรช"
useGroupedNotifications: "แสดงผลการแจ้งเตือนแบบกลุ่มแล้ว"
emailVerificationFailedError: "เกิดปัญหาในขณะตรวจสอบอีเมล อาจเป็นไปได้ว่าลิงก์หมดอายุแล้ว"
cwNotationRequired: "หากเปิดใช้งาน “ซ่อนเนื้อหา” จะต้องระบุคำอธิบาย"
cwNotationRequired: "หากเปิดใช้งาน “ซ่อนเนื้อหา” จะต้องระบุข้อความเกริ่น"
doReaction: "เพิ่มรีแอคชั่น"
code: "โค้ด"
reloadRequiredToApplySettings: "จำเป็นต้องมีการโหลดซ้ำเพื่อให้การตั้งค่ามีผล"
@@ -1324,7 +1335,7 @@ markAsSensitiveConfirm: "ต้องการตั้งค่าสื่อ
unmarkAsSensitiveConfirm: "ต้องการยกเลิกการระบุว่าสื่อนี้มีเนื้อหาละเอียดอ่อนหรือไม่?"
preferences: "การตั้งค่าสภาพแวดล้อม"
accessibility: "การช่วยการเข้าถึง"
preferencesProfile: "โปรไฟล์การกำหนดค่า"
preferencesProfile: "โปรไฟล์ของการตั้งค่า"
copyPreferenceId: "คัดลือก ID การตั้งค่า"
resetToDefaultValue: "คืนค่าเป็นค่าเริ่มต้น"
overrideByAccount: "เขียนทับด้วยบัญชี"
@@ -1334,10 +1345,10 @@ skip: "ข้าม"
restore: "กู้คืน"
syncBetweenDevices: "ซิงค์ระหว่างอุปกรณ์"
preferenceSyncConflictTitle: "การตั้งค่ามีอยู่บนเซิร์ฟเวอร์"
preferenceSyncConflictText: "การตั้งค่าที่เปิดใช้งานการซิง์จะบันทึกค่าลงในเซิร์ฟเวอร์ อย่างไรก็ดี พบว่ามีค่าการตั้งค่านี้ที่เคยบันทึกไว้ในเซิร์ฟเวอร์แล้ว ต้องการดำเนินการอย่างไร?"
preferenceSyncConflictText: "รายการตั้งค่าที่เปิดการซิง์จะถูกบันทึกลงเซิร์ฟเวอร์ แต่รายการตั้งค่านี้ได้ถูกบันทึกลงเซิร์ฟเวอร์ไว้อยู่แล้ว ต้องการดำเนินการอย่างไร?"
preferenceSyncConflictChoiceMerge: "รวมเข้าด้วยกัน"
preferenceSyncConflictChoiceServer: "เขียนทับด้วยค่าการตั้งค่าเซิร์ฟเวอร์"
preferenceSyncConflictChoiceDevice: "เขียนทับด้วยค่าการตั้งค่าอุปกรณ์"
preferenceSyncConflictChoiceServer: "เขียนทับด้วยค่าการตั้งค่าของเซิร์ฟเวอร์"
preferenceSyncConflictChoiceDevice: "เขียนทับด้วยค่าการตั้งค่าของอุปกรณ์"
preferenceSyncConflictChoiceCancel: "ยกเลิกการเปิดใช้งานการซิงค์"
paste: "วาง"
emojiPalette: "จานสีเอโมจิ"
@@ -1351,7 +1362,7 @@ migrateOldSettings: "ย้ายข้อมูลการตั้งค่
migrateOldSettings_description: "โดยปกติจะทำโดยอัตโนมัติ แต่หากด้วยเหตุผลบางประการที่ไม่สามารถย้ายได้สำเร็จ สามารถสั่งย้ายด้วยตนเองได้ การตั้งค่าปัจจุบันจะถูกเขียนทับ"
compress: "บีบอัด"
right: "ขวา"
bottom: "ภายใต้"
bottom: "ล่าง"
top: "บน"
embed: "ฝัง"
settingsMigrating: "กำลังย้ายการตั้งค่า กรุณารอสักครู่... (สามารถย้ายด้วยตนเองภายหลังได้ที่ การตั้งค่า → อื่นๆ → ย้ายข้อมูลการตั้งค่าเก่า)"
@@ -1390,17 +1401,55 @@ scheduledToPostOnX: "มีการกำหนดเวลาให้โพ
schedule: "กำหนดเวลา"
scheduled: "กำหนดเวลา"
widgets: "วิดเจ็ต"
deviceInfo: "รายละเอียดอุปกรณ์"
deviceInfoDescription: "เมื่อต้องการรับความช่วยเหลือทางเทคนิค กรุณาระบุข้อมูลต่อไปนี้ซึ่งอาจช่วยแก้ไขปัญหาได้"
youAreAdmin: "คุณคือผู้ดูแลระบบ"
frame: "เฟรม"
presets: "พรีเซ็ต"
zeroPadding: "ห่างเป็น 0"
nothingToConfigure: "ไม่มีอะไรให้ต้ังค่า"
viewRenotedChannel: "แสดงช่องที่ถูกรีโน้ต"
previewingThemeRestore: "เลิกทำ"
_imageEditing:
_vars:
caption: "แคปชั่นของไฟล์"
filename: "ชื่อไฟล์"
filename_without_ext: "ชื่อไฟล์ที่ไม่มีนามสกุล"
year: "ปีที่ถ่าย"
month: "เดือนที่ถ่าย"
day: "วันที่ถ่าย"
hour: "เวลาที่ถ่าย (ชั่วโมง)"
minute: "เวลาที่ถ่าย (นาที)"
second: "เวลาที่ถ่าย (วินาที)"
camera_model: "ชื่อกล้อง"
camera_lens_model: "ชื่อเลนส์"
camera_mm: "ความยาวโฟกัส"
camera_mm_35: "ทางยาวโฟกัส (เทียบเท่า 35 มม.)"
camera_f: "รูรับแสง"
camera_s: "ความเร็วชัตเตอร์"
camera_iso: "ความไวแสง ISO"
gps_lat: "ละติจูด"
gps_long: "ลองจิจูด"
_imageFrameEditor:
title: "แก้ไขเฟรม"
tip: "สามารถตกแต่งภาพโดยการเพิ่มป้ายที่มีเฟรมหรือเมทาเดต้าได้"
header: "ส่วนหัว"
footer: "ท้ายกระดาษ"
borderThickness: "ความกว้างขอบ"
labelThickness: "ความกว้างป้าย"
labelScale: "สเกลของป้าย"
centered: "จัดกึ่งกลาง"
captionMain: "แคปชั่น (ใหญ่)"
captionSub: "แคปชั่น (เล็ก)"
availableVariables: "ตัวแปรที่สามารถใช้ได้"
withQrCode: "QR โค้ด"
backgroundColor: "สีพื้นหลัง"
textColor: "สีตัวอักษร"
font: "แบบอักษร"
fontSerif: "Serif"
fontSansSerif: "Sans Serif"
quitWithoutSaveConfirm: "ต้องการออกโดยไม่บันทึกหรือไม่?"
failedToLoadImage: "โหลดภาพล้มเหลว"
_compression:
_quality:
high: "คุณภาพสูง"
@@ -1503,6 +1552,11 @@ _settings:
showUrlPreview: "แสดงตัวอย่าง URL"
showAvailableReactionsFirstInNote: "แสดงรีแอคชั่นที่ใช้ได้ไว้หน้าสุด"
showPageTabBarBottom: "แสดงแท็บบาร์ของเพจที่ด้านล่าง"
emojiPaletteBanner: "สามารถบันทึกพรีเซ็ตเป็นจานสีเพื่อตรึงไว้ในตัวจิ้มเอโมจิ หรือปรับแต่งวิธีการแสดงผลของตัวจิ้มเอโมจิได้"
enableAnimatedImages: "เปิดใช้งานภาพเคลื่อนไหว"
settingsPersistence_title: "คงสภาพการตั้งค่า"
settingsPersistence_description1: "เมื่อเปิดใช้งานการคงสภาพการตั้งค่า จะช่วยป้องกันไม่ให้ข้อมูลการตั้งค่าสูญหายได้"
settingsPersistence_description2: "แต่ในบางสภาพแวดล้อม อาจไม่สามารถเปิดใช้งานได้"
_chat:
showSenderName: "แสดงชื่อผู้ส่ง"
sendOnEnter: "กด Enter เพื่อส่ง"
@@ -1511,6 +1565,8 @@ _preferencesProfile:
profileNameDescription: "กรุณาตั้งชื่อเพื่อระบุอุปกรณ์นี้"
profileNameDescription2: "เช่น: “คอมเครื่องหลัก”, “มือถือ” ฯลฯ"
manageProfiles: "จัดการโปรไฟล์"
shareSameProfileBetweenDevicesIsNotRecommended: "ไม่แนะนำให้ใช้โปรไฟล์เดียวกันร่วมกันบนหลายอุปกรณ์"
useSyncBetweenDevicesOptionIfYouWantToSyncSetting: "หากมีรายการตั้งค่าที่ต้องการซิงก์ระหว่างหลายอุปกรณ์ โปรดเปิดใช้งานตัวเลือก “ซิงก์ระหว่างหลายอุปกรณ์” ในอุปกรณ์นั้นๆ ด้วย"
_preferencesBackup:
autoBackup: "สำรองโดยอัตโนมัติ"
restoreFromBackup: "คืนค่าจากข้อมูลสำรอง"
@@ -1518,8 +1574,9 @@ _preferencesBackup:
noBackupsFoundDescription: "ไม่พบข้อมูลสำรองที่สร้างโดยอัตโนมัติ แต่หากมีข้อมูลสำรองที่บันทึกด้วยตนเอง สามารถนำเข้ามาเพื่อกู้คืนได้"
selectBackupToRestore: "กรุณาเลือกข้อมูลสำรองที่ต้องการกู้คืน"
youNeedToNameYourProfileToEnableAutoBackup: "จำเป็นต้องตั้งชื่อโปรไฟล์ก่อนจึงจะเปิดใช้งานการสำรองข้อมูลอัตโนมัติได้"
autoPreferencesBackupIsNotEnabledForThisDevice: "ยังไม่ได้เปิดใช้งานการสำรองข้อมูลอัตโนมัติบนอุปกรณ์นี้"
autoPreferencesBackupIsNotEnabledForThisDevice: "ยังไม่ได้เปิดใช้งานการสำรองการตั้งค่าแบบอัตโนมัติบนอุปกรณ์นี้"
backupFound: "พบข้อมูลสำรองของการตั้งค่าแล้ว"
forceBackup: "บังคับสำรองการตั้งค่า"
_accountSettings:
requireSigninToViewContents: "ต้องเข้าสู่ระบบเพื่อดูเนื้อหา"
requireSigninToViewContentsDescription1: "กำหนดให้ต้องเข้าสู่ระบบก่อนจึงจะสามารถดูโน้ตหรือเนื้อหาทั้งหมดที่สร้างไว้ได้ ซึ่งช่วยป้องกันไม่ให้ข้อมูลถูกเก็บโดยบอตหรือ Crawler (โปรแกรมรวบรวมข้อมูล)"
@@ -1587,7 +1644,7 @@ _initialAccountSetting:
theseSettingsCanEditLater: "คุณสามารถเปลี่ยนการตั้งค่าเหล่านี้ได้ในภายหลังได้ตลอดเวลานะ"
youCanEditMoreSettingsInSettingsPageLater: "สามารถตั้งค่าเพิ่มเติมได้ที่หน้า “การตั้งค่า” อย่าลืมไปเยี่ยมชมภายหลังด้วย"
followUsers: "ลองติดตามผู้ใช้ที่สนใจเพื่อสร้างไทม์ไลน์ดูสิ"
pushNotificationDescription: "กำลังเปิดใช้งานการแจ้งเตือนแบบพุชจะช่วยให้คุณได้รับการแจ้งเตือนจาก {name} โดยตรงบนอุปกรณ์ของคุณนะ"
pushNotificationDescription: "เมื่อเปิดใช้งานการแจ้งเตือนแบบพุช จะสามารถรับการแจ้งเตือนจาก {name} บนอุปกรณ์ที่ใช้งานอยู่ได้"
initialAccountSettingCompleted: "ตั้งค่าโปรไฟล์เสร็จสมบูรณ์แล้ว!"
haveFun: "ขอให้สนุกกับ {name}!"
youCanContinueTutorial: "คุณสามารถดำเนินการต่อด้วยบทช่วยสอนเกี่ยวกับวิธีใช้ {name} (Misskey) หรือออกจากบทช่วยสอนแล้วเริ่มใช้งานได้ทันที"
@@ -1639,7 +1696,7 @@ _initialTutorial:
localOnly: "การโพสต์ด้วย flag นี้จะไม่รวมโน้ตไปยังเซิร์ฟเวอร์อื่น ผู้ใช้บนเซิร์ฟเวอร์อื่นจะไม่สามารถดูโน้ตเหล่านี้ได้โดยตรง โดยไม่คำนึงถึงการตั้งค่าการแสดงผลข้างต้น"
_cw:
title: "คำเตือนเกี่ยวกับเนื้อหา"
description: "เนื้อหาที่เขียนใน “คำอธิบายประกอบ” จะแสดงแทนเนื้อหาหลัก ต้องคลิก “ดูเพิ่มเติม” เพื่อให้เนื้อหาหลักแสดง"
description: "เนื้อหาที่เขียนใน “ข้อความเกริ่น” จะแสดงแทนเนื้อหาหลัก ต้องก “ดูเพิ่มเติม” เพื่อให้เนื้อหาหลักแสดง"
_exampleNote:
cw: " ห้ามดู ระวังหิว"
note: "เพิ่งไปกินโดนัทเคลือบช็อคโกแลตมา 🍩😋"
@@ -1991,7 +2048,7 @@ _role:
isConditionalRole: "นี่คือบทบาทที่มีเงื่อนไข"
isPublic: "ทำให้บทบาทเปิดเผยต่อสาธารณะ"
descriptionOfIsPublic: "บทบาทจะปรากฏบนโปรไฟล์ของผู้ใช้และเปิดเผยต่อสาธารณะ (ทุกคนสามารถเห็นได้ว่าผู้ใช้รายนี้มีบทบาทนี้)"
options: "ตัวเลือกบทบาท"
options: "ตัวเลือก"
policies: "นโยบาย"
baseRole: "แม่แบบบทบาท"
useBaseValue: "ใช้ตามแม่แบบบทบาท"
@@ -2025,6 +2082,7 @@ _role:
canManageAvatarDecorations: "จัดการตกแต่งอวตาร"
driveCapacity: "ความจุของไดรฟ์"
maxFileSize: "ขนาดไฟล์สูงสุดที่สามารถอัปโหลดได้"
maxFileSize_caption: "รีเวิร์สพร็อกซี, CDN และคอมโพเนนต์หน้าบ้านอื่นๆ อาจมีค่าการตั้งค่าของตนเอง"
alwaysMarkNsfw: "ทำเครื่องหมายไฟล์ว่าเป็น NSFW เสมอ"
canUpdateBioMedia: "อนุญาตให้เปลี่ยนไอคอนประจำตัวและแบนเนอร์"
pinMax: "จํานวนสูงสุดของโน้ตที่ปักหมุดไว้"
@@ -2041,6 +2099,7 @@ _role:
canSearchNotes: "การใช้การค้นหาโน้ต"
canSearchUsers: "ค้นหาผู้ใช้"
canUseTranslator: "การใช้งานแปล"
canCreateChannel: "สร้างช่องใหม่"
avatarDecorationLimit: "จำนวนของตกแต่งไอคอนสูงสุดที่สามารถติดตั้งได้"
canImportAntennas: "อนุญาตให้นำเข้าเสาอากาศ"
canImportBlocking: "อนุญาตให้นำเข้าการบล็อก"
@@ -2080,7 +2139,7 @@ _sensitiveMediaDetection:
sensitivityDescription: "เมื่อความไวต่ำ Misdetection (ผลบวกลวง) จะลดลง, เมื่อความไวสูง Missed detection (ผลลบลวง) จะลดลง"
setSensitiveFlagAutomatically: "ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน"
setSensitiveFlagAutomaticallyDescription: "ผลลัพธ์ของการตรวจจับภายในนั้นจะยังคงอยู่ ถึงแม้ว่าจะปิดตัวเลือกนี้"
analyzeVideos: "เปิดใช้งานวิเคราะห์ของวิดีโอ"
analyzeVideos: "เปิดใช้งานวิเคราะห์วิดีโอ"
analyzeVideosDescription: "การวิเคราะห์วิดีโอนอกเหนือจากรูปภาพนั้น การทำสิ่งนี้จะทำให้เพิ่มภาระบนเซิร์ฟเวอร์เล็กน้อย"
_emailUnavailable:
used: "ที่อยู่อีเมลนี้ได้ถูกใช้ไปแล้ว"
@@ -2386,7 +2445,7 @@ _permissions:
"read:admin:index-stats": "ดูข้อมูลเกี่ยวกับดัชนีฐานข้อมูล"
"read:admin:table-stats": "ดูข้อมูลเกี่ยวกับตารางในฐานข้อมูล"
"read:admin:user-ips": "ดูที่อยู่ IP ของผู้ใช้"
"read:admin:meta": "ดูข้อมูลอภิพันธุ์ของอินสแตนซ์"
"read:admin:meta": "ดูเมทาเดต้าของอินสแตนซ์"
"write:admin:reset-password": "รีเซ็ตรหัสผ่านของผู้ใช้"
"write:admin:resolve-abuse-user-report": "แก้ไขรายงานจากผู้ใช้"
"write:admin:send-email": "ส่งอีเมล"
@@ -2397,7 +2456,7 @@ _permissions:
"write:admin:unset-user-avatar": "ลบอวตารผู้ใช้"
"write:admin:unset-user-banner": "ลบแบนเนอร์ผู้ใช้"
"write:admin:unsuspend-user": "ยกเลิกการระงับผู้ใช้"
"write:admin:meta": "จัดการข้อมูลอภิพันธุ์ของอินสแตนซ์"
"write:admin:meta": "จัดการเมทาเดต้าของอินสแตนซ์"
"write:admin:user-note": "จัดการโน้ตการกลั่นกรอง"
"write:admin:roles": "จัดการบทบาท"
"read:admin:roles": "ดูบทบาท"
@@ -2443,6 +2502,7 @@ _auth:
scopeUser: "กำลังดำเนินการในฐานะผู้ใช้ต่อไปนี้"
pleaseLogin: "กรุณาเข้าสู่ระบบเพื่ออนุมัติแอปพลิเคชัน"
byClickingYouWillBeRedirectedToThisUrl: "หากอนุญาตการเข้าถึง ระบบจะเปลี่ยนเส้นทางไปยัง URL ด้านล่างโดยอัตโนมัติ"
alreadyAuthorized: "แอปพลิเคชันนี้ได้รับอนุญาตให้เข้าถึงแล้ว"
_antennaSources:
all: "โน้ตทั้งหมด"
homeTimeline: "โน้ตจากผู้ใช้ที่ติดตาม"
@@ -2491,16 +2551,45 @@ _widgets:
chat: "แชตเลย"
_widgetOptions:
showHeader: "แสดงส่วนหัว"
transparent: "ทำพื้นหลังโปรงใส"
height: "ความสูง"
_button:
colored: "สี"
_clock:
size: "ขนาด"
thickness: "ความหนาเข็ม"
thicknessThin: "บาง"
thicknessMedium: "ปานกลาง"
thicknessThick: "หนา"
graduations: "ขีดบอกค่าบนหน้าปัด"
graduationDots: "จุด"
graduationArabic: "เลขอารบิก"
fadeGraduations: "เฟดหน้าปัด"
sAnimation: "การเคลื่อนไหวของเข็มวินาที"
sAnimationElastic: "สมจริง"
sAnimationEaseOut: "ลื่นๆ"
twentyFour: "ระบบ 24 ชั่วโมง"
labelTime: "เวลา"
labelTz: "เขตเวลา"
labelTimeAndTz: "เวลาและเขตเวลา"
timezone: "เขตเวลา"
showMs: "แสดงมิลลิวินาที"
showLabel: "แสดงป้าย"
_jobQueue:
sound: "เล่นเสียง"
_rss:
url: "URL ของฟีด RSS"
refreshIntervalSec: "ห้วงอัปเดต (วินาที)"
maxEntries: "จำนวนที่แสดงได้สูงสุด"
_rssTicker:
shuffle: "สุ่มลำดับ"
duration: "ความเร็วทิกเกอร์ (วินาที)"
reverse: "วิ่งไปอีกทาง"
_birthdayFollowings:
period: "ระยะเวลา"
_cw:
hide: "ซ่อน"
show: "โหลดเพิ่มเติม"
show: "ดเพิ่มเติม"
chars: "{count} ตัวอักษร"
files: "{count} ไฟล์"
_poll:
@@ -2542,9 +2631,20 @@ _postForm:
replyPlaceholder: "ตอบกลับโน้ตนี้..."
quotePlaceholder: "อ้างโน้ตนี้..."
channelPlaceholder: "โพสต์ลงช่อง..."
showHowToUse: "แสดงวิธีใช้ฟอร์ม"
_howToUse:
content_title: "เนื้อความ"
content_description: "ป้อนเนื้อหาที่จะโพสต์"
toolbar_title: "แถบเครื่องมือ"
toolbar_description: "สามารถแนบไฟล์หรือแบบสอบถาม ตั้งข้อความเกริ่นหรือแฮชแท็ก แทรกเอโมจิหรือการกล่าวถึง เป็นต้น"
account_title: "เมนูบัญชี"
account_description: "สามารถสลับบัญชีที่ใช้โพสต์ หรือดูรายการฉบับร่างและโพสต์กำหนดเวลาไว้ซึ่งบันทึกไว้ในบัญชีได้"
visibility_title: "การมองเห็น"
visibility_description: "สามารถตั้งค่าขอบเขตการเผยแพร่โน้ตได้"
menu_title: "เมนู"
menu_description: "สามารถบันทึกเป็นฉบับร่าง ตั้งเวลาการโพสต์ ตั้งค่ารีแอคชั่น และดำเนินการอื่นๆ ได้"
submit_title: "ปุ่มโพสต์"
submit_description: "กดปุ่มนั้นเพื่อโพสต์โน้ต หรือกด Ctrl + Enter / Cmd + Return เพื่อโพสต์ก็ได้เช่นกัน"
_placeholders:
a: "ตอนนี้เป็นยังไงบ้าง?"
b: "มีอะไรเกิดขึ้นหรือเปล่า?"
@@ -2560,7 +2660,7 @@ _profile:
metadata: "ข้อมูลเพิ่มเติม"
metadataEdit: "แก้ไขข้อมูลเพิ่มเติม"
metadataDescription: "ใช้สิ่งเหล่านี้ คุณสามารถแสดงฟิลด์ข้อมูลเพิ่มเติมในโปรไฟล์ของคุณ"
metadataLabel: "ป้ายชื่อ"
metadataLabel: "ป้าย"
metadataContent: "เนื้อหา"
changeAvatar: "เปลี่ยนไอคอนประจำตัว"
changeBanner: "เปลี่ยนแบนเนอร์"
@@ -2721,6 +2821,8 @@ _notification:
quote: "อ้างอิง"
reaction: "รีแอคชั่น"
pollEnded: "โพลสิ้นสุดแล้ว"
scheduledNotePosted: "โพสต์กำหนดเวลาสำเร็จ"
scheduledNotePostFailed: "โพสต์กำหนดเวลาล้มเหลว"
receiveFollowRequest: "ได้รับคำร้องขอติดตาม"
followRequestAccepted: "อนุมัติให้ติดตามแล้ว"
roleAssigned: "ให้บทบาท"
@@ -2760,6 +2862,14 @@ _deck:
usedAsMinWidthWhenFlexible: "ความกว้างขั้นต่ำนั้นจะถูกใช้งานสำหรับสิ่งนี้เมื่อเปิดใช้งานตัวเลือก \"ปรับความกว้างอัตโนมัติ\" หากเลือกเปิดใช้งานแล้ว"
flexible: "ปรับความกว้างอัตโนมัติ"
enableSyncBetweenDevicesForProfiles: "เปิดใช้งานการซิงค์ข้อมูลโปรไฟล์ระหว่างอุปกรณ์"
showHowToUse: "แสดงวิธีใช้ UI"
_howToUse:
addColumn_title: "เพิ่มคอลัมน์"
addColumn_description: "สามารถเลือกประเภทของคอลัมน์แล้วเพิ่มได้"
settings_title: "ตั้งค่า UI"
settings_description: "สามารถตั้งค่ารายละเอียดของ UI แบบเด็คได้"
switchProfile_title: "สลับโปรไฟล์"
switchProfile_description: "สามารถบันทึกเลย์เอาต์ของ UI เป็นโปรไฟล์ และสลับใช้งานได้ทุกเมื่อ"
_columns:
main: "หลัก"
widgets: "วิดเจ็ต"
@@ -2820,6 +2930,8 @@ _abuseReport:
notifiedWebhook: "Webhook ที่ใช้"
deleteConfirm: "ต้องการลบปลายทางการแจ้งเตือนใช่ไหม?"
_moderationLogTypes:
clearQueue: "ล้างคิว"
promoteQueue: "ดันงานในคิวอีกครั้ง"
createRole: "สร้างบทบาทแล้ว"
deleteRole: "ลบบทบาทแล้ว"
updateRole: "อัปเดตบทบาทแล้ว"
@@ -2878,7 +2990,7 @@ _fileViewer:
uploadedAt: "วันที่เข้าร่วม"
attachedNotes: "โน้ตที่แนบมาด้วย"
usage: "ใช้แล้ว"
thisPageCanBeSeenFromTheAuthor: "หน้าเพจนี้จะสามารถปรากฏได้โดยผู้ใช้ที่อัปโหลดไฟล์นี้เท่านั้น"
thisPageCanBeSeenFromTheAuthor: "เฉพาะผู้ใช้ที่อัปโหลดไฟล์นี้เท่านั้นที่สามารถดูหน้าเพจนี้ได้"
_externalResourceInstaller:
title: "ติดตั้งจากไซต์ภายนอก"
checkVendorBeforeInstall: "โปรดตรวจสอบให้แน่ใจว่าแหล่งแจกหน่ายมีความน่าเชื่อถือก่อนทำการติดตั้ง"
@@ -2920,7 +3032,7 @@ _externalResourceInstaller:
description: "เกิดปัญหาระหว่างการติดตั้งธีม กรุณาลองอีกครั้ง. รายละเอียดข้อผิดพลาดสามารถดูได้ในคอนโซล Javascript"
_dataSaver:
_media:
title: "โหลดสื่อ"
title: "ปิดใช้งานการโหลดสื่ออัตโนมัติ"
description: "กันไม่ให้ภาพและวิดีโอโหลดโดยอัตโนมัติ แตะรูปภาพ/วิดีโอที่ซ่อนอยู่เพื่อโหลด"
_avatar:
title: "ปิดใช้งานภาพเคลื่อนไหวของไอคอนประจำตัว"
@@ -3002,7 +3114,7 @@ _urlPreviewSetting:
summaryProxyDescription: "สร้างการแสดงตัวอย่างด้วย summary Proxy แทนที่จะใช้เนื้อหา Misskey"
summaryProxyDescription2: "พารามิเตอร์ต่อไปนี้จะถูกใช้เป็นสตริงการสืบค้นเพื่อเชื่อมต่อกับพร็อกซี หากฝั่งพร็อกซีไม่รองรับการตั้งค่าเหล่านี้จะถูกละเว้น"
_mediaControls:
pip: "รูปภาพในรูปภาม"
pip: "ภาพซ้อนภาพ (PiP)"
playbackRate: "ความเร็วในการเล่น"
loop: "เล่นวนซ้ำ"
_contextMenu:
@@ -3063,7 +3175,7 @@ _customEmojisManager:
uploadSettingDescription: "สามารถกำหนดพฤติกรรมขณะอัปโหลดเอโมจิจากหน้าจอนี้ได้"
directoryToCategoryLabel: "ป้อนชื่อไดเรกทอรีเป็น \"category\""
directoryToCategoryCaption: "เมื่อทำการลากและวางไดเรกทอรี ชื่อจะถูกป้อนเป็น \"category\""
confirmRegisterEmojisDescription: "จะลงทะเบียนเอโมจิที่แสดงในรายการเป็นเอโมจิแบบกำหนดเองใหม่\nดำเนินการต่อหรือไม่? (เพื่อหลีกเลี่ยงภาระโหลดหนัก ระบบจะสามารถลงทะเบียนอโมจิได้สูงสุด {count} รายการต่อครั้ง)"
confirmRegisterEmojisDescription: "จะลงทะเบียนเอโมจิที่แสดงในรายการเป็นเอโมจิแบบกำหนดเองใหม่\nดำเนินการต่อหรือไม่? (เพื่อหลีกเลี่ยงภาระโหลดหนัก ระบบจะสามารถลงทะเบียนอโมจิได้สูงสุด {count} รายการต่อครั้ง)"
confirmClearEmojisDescription: "ต้องการยกเลิกการแก้ไขและล้างรายการเอโมจิที่แสดงอยู่หรือไม่?"
confirmUploadEmojisDescription: "จะอัปโหลดไฟล์ {count} รายการที่ลากและวางไปยังไดรฟ์ ดำเนินการหรือไม่?"
_embedCodeGen:
@@ -3214,6 +3326,7 @@ _watermarkEditor:
title: "แก้ไขลายน้ำ"
cover: "ซ้อนทับทั่วทั้งพื้นที่"
repeat: "ปูให้เต็มพื้นที่"
preserveBoundingRect: "ปรับไม่ให้ล้นขอบเมื่อหมุน"
opacity: "ความทึบแสง"
scale: "ขนาด"
text: "ข้อความ"
@@ -3235,10 +3348,12 @@ _watermarkEditor:
polkadotSubDotRadius: "ขนาดของจุดรอง"
polkadotSubDotDivisions: "จำนวนจุดรอง"
leaveBlankToAccountUrl: "เว้นว่างไว้หากต้องการใช้ URL ของบัญชีแทน"
failedToLoadImage: "โหลดภาพล้มเหลว"
_imageEffector:
title: "เอฟเฟกต์"
addEffect: "เพิ่มเอฟเฟกต์"
discardChangesConfirm: "ต้องการทิ้งการเปลี่ยนแปลงแล้วออกหรือไม่?"
failedToLoadImage: "โหลดภาพล้มเหลว"
_fxs:
chromaticAberration: "ความคลาดสี"
glitch: "กลิตช์"
@@ -3289,11 +3404,9 @@ _imageEffector:
threshold: "เทรชโฮลด์"
centerX: "กลาง X"
centerY: "กลาง Y"
zoomLinesSmoothing: "ทำให้สมูธ"
zoomLinesSmoothingDescription: "ตั้งให้สมูธไม่สามารถใช้ร่วมกับตั้งความกว้างเส้นรวมศูนย์ได้"
zoomLinesThreshold: "ความกว้างเส้นรวมศูนย์"
density: "ความหนาทึบ"
zoomLinesOutlineThickness: "ความหนาของเงาเส้น"
zoomLinesMaskSize: "ขนาดพื้นที่ตรงกลาง"
zoomLinesBlack: "ทำให้ดำ"
circle: "ทรงกลม"
drafts: "ร่าง"
_drafts:

View File

@@ -83,6 +83,8 @@ files: "Dosyalar"
download: "İndir"
driveFileDeleteConfirm: "“{name}” dosyasını silmek istediğinden emin misin? Bu dosyaya ekli tüm notlar da silinecek."
unfollowConfirm: "{name} kullanıcısını cidden takipden çıkmak istiyor musun?"
cancelFollowRequestConfirm: "{name} adlı kişiye gönderdiğiniz takip isteğini iptal etmek ister misiniz?"
rejectFollowRequestConfirm: "{name} adlı kullanıcının takip isteğini reddetmek istiyor musunuz?"
exportRequested: "Dışa aktarma işlemi talep ettin. Bu işlem biraz zaman alabilir. İşlem tamamlandığında Drive'ına eklenecek."
importRequested: "İçe aktarma talebinde bulundun. Bu işlem biraz zaman alabilir."
lists: "Listeler"
@@ -253,6 +255,7 @@ noteDeleteConfirm: "Bu notu silmek istediğinden emin misin?"
pinLimitExceeded: "Artık daha fazla not sabitleyemezsin"
done: "Tamam"
processing: "İşleniyor..."
preprocessing: "Hazırlık aşamasında"
preview: "Önizleme"
default: "Varsayılan"
defaultValueIs: "Varsayılan: {value}"
@@ -301,6 +304,7 @@ uploadFromUrlMayTakeTime: "Yükleme işleminin tamamlanması biraz zaman alabili
uploadNFiles: "{n} dosya yükle"
explore: "Keşfet"
messageRead: "Oku"
readAllChatMessages: "Tüm mesajları okundu olarak işaretle"
noMoreHistory: "Daha fazla geçmiş bilgisi yok."
startChat: "Sohbete başla"
nUsersRead: "{n} tarafından okundu"
@@ -333,6 +337,7 @@ fileName: "Dosya adı"
selectFile: "Dosya seçin"
selectFiles: "Dosyaları seçin"
selectFolder: "Klasör seçin"
unselectFolder: "Klasör seçimini kaldır"
selectFolders: "Klasörleri seçin"
fileNotSelected: "Hiç dosya seçilmedi"
renameFile: "Dosyayı yeniden adlandır"
@@ -345,6 +350,7 @@ addFile: "Bir dosya ekle"
showFile: "Dosyaları göster"
emptyDrive: "Drive boş"
emptyFolder: "Bu klasör boş"
dropHereToUpload: "Yüklemek için dosyalarınızı buraya sürükleyin."
unableToDelete: "Silinemiyor"
inputNewFileName: "Yeni bir dosya adı girin"
inputNewDescription: "Yeni alternatif metin girin"
@@ -537,6 +543,7 @@ regenerate: "Yeniden oluştur"
fontSize: "Yazı tipi boyutu"
mediaListWithOneImageAppearance: "Tek bir resim içeren medya listelerinin yüksekliği"
limitTo: "{x} ile sınırlandır"
showMediaListByGridInWideArea: "Ekran genişliği geniş olduğunda, medya listesi yatay olarak görüntülenecektir."
noFollowRequests: "Bekleyen takip istekleri yok."
openImageInNewTab: "Görüntüleri yeni sekmede aç"
dashboard: "Gösterge paneli"
@@ -772,6 +779,7 @@ lockedAccountInfo: "Notunuzun görünürlüğünü “Yalnızca takipçiler” o
alwaysMarkSensitive: "Varsayılan olarak hassas olarak işaretle"
loadRawImages: "Küçük resimleri göstermek yerine orijinal resimleri yükle"
disableShowingAnimatedImages: "Animasyonlu görüntüleri oynatmayın"
disableShowingAnimatedImages_caption: "Bu ayara rağmen animasyonlu görüntüler oynatılmıyorsa, bunun nedeni tarayıcınızın veya işletim sisteminizin erişilebilirlik ayarları veya güç tasarrufu ayarlarından kaynaklanan parazit olabilir."
highlightSensitiveMedia: "Hassas medyayı vurgulayın"
verificationEmailSent: "Doğrulama e-postası gönderildi. Doğrulamayı tamamlamak için e-postadaki bağlantıyı takip edin."
notSet: "Ayarlı değil"
@@ -1018,6 +1026,9 @@ pushNotificationAlreadySubscribed: "Push bildirimleri zaten açık"
pushNotificationNotSupported: "Push bildirimleri sunucu veya tarayıcı tarafından desteklenmiyor"
sendPushNotificationReadMessage: "Okunduktan sonra push bildirimlerini silin"
sendPushNotificationReadMessageCaption: "Bu, cihazınızın güç tüketimini artırabilir."
pleaseAllowPushNotification: "Lütfen tarayıcı ayarlarınızdan bildirimlere izin verin."
browserPushNotificationDisabled: "Bildirim gönderme izni alınamadı."
browserPushNotificationDisabledDescription: "{serverName} sunucusundan bildirim gönderme izniniz yok. Lütfen tarayıcı ayarlarınızdan bildirimlere izin verin ve tekrar deneyin."
windowMaximize: "Maksimize et"
windowMinimize: "Minimize et"
windowRestore: "Geri yükle"
@@ -1168,6 +1179,7 @@ installed: "Yüklendi"
branding: "Markalaşma"
enableServerMachineStats: "Sunucu donanım istatistiklerini yayınla"
enableIdenticonGeneration: "Kullanıcı identicon oluşturmayı etkinleştir"
showRoleBadgesOfRemoteUsers: "Uzaktan kullanıcılara verilen rol rozetlerini görüntüle"
turnOffToImprovePerformance: "Devre dışı bırakma, daha yüksek performansa yol açabilir."
createInviteCode: "Davet Kodu oluştur"
createWithOptions: "Seçeneklerle oluştur"
@@ -1316,6 +1328,7 @@ acknowledgeNotesAndEnable: "Önlemleri anladıktan sonra açın."
federationSpecified: "Bu sunucu, beyaz liste federasyonunda çalıştırılmaktadır. Yönetici tarafından belirlenen sunucular dışında diğer sunucularla etkileşim kurmak yasaktır."
federationDisabled: "Bu sunucuda federasyon devre dışıdır. Diğer sunuculardaki kullanıcılarla etkileşim kuramazsınız."
draft: "Taslaklar"
draftsAndScheduledNotes: "Taslaklar ve planlanmış gönderiler"
confirmOnReact: "Tepki verirken onaylayın"
reactAreYouSure: "“{emoji}” tepkisini eklemek ister misin?"
markAsSensitiveConfirm: "Bu medyayı hassas olarak ayarlamak ister misin?"
@@ -1344,6 +1357,7 @@ textCount: "Karakter sayısı"
information: "Hakkında"
chat: "Sohbet"
directMessage: "Kullanıcıyla sohbet et"
directMessage_short: "Mesaj"
migrateOldSettings: "Eski istemci ayarlarını taşıma"
migrateOldSettings_description: "Bu işlem otomatik olarak yapılmalıdır, ancak herhangi bir nedenle geçiş başarısız olursa, geçiş işlemini manuel olarak kendin başlatabilirsin. Mevcut yapılandırma bilgileri üzerine yazılacaktır."
compress: "Sıkıştır"
@@ -1371,6 +1385,8 @@ redisplayAllTips: "Tüm “İpucu & Püf Nokta” tekrar göster"
hideAllTips: "Tüm “İpucu & Püf Nokta” gizle"
defaultImageCompressionLevel: "Varsayılan görüntü sıkıştırma düzeyi"
defaultImageCompressionLevel_description: "Düşük seviye görüntü kalitesini korur ancak dosya boyutunu artırır.<br>Yüksek seviye dosya boyutunu azaltır ancak görüntü kalitesini düşürür."
defaultCompressionLevel: "Varsayılan sıkıştırma seviyesi"
defaultCompressionLevel_description: "Ayarı düşürmek kaliteyi koruyacak ancak dosya boyutunu artıracaktır. <br> Ayarı yükseltmek dosya boyutunu küçültecek ancak kaliteyi düşürecektir."
inMinutes: "Dakika(lar)"
inDays: "Gün(ler)"
safeModeEnabled: "Güvenli mod etkinleştirildi"
@@ -1378,21 +1394,76 @@ pluginsAreDisabledBecauseSafeMode: "Güvenli mod etkinleştirildiği için tüm
customCssIsDisabledBecauseSafeMode: "Güvenli mod etkin olduğu için özel CSS uygulanmıyor."
themeIsDefaultBecauseSafeMode: "Güvenli mod etkinken, varsayılan tema kullanılır. Güvenli modu devre dışı bırakmak bu değişiklikleri geri alır."
thankYouForTestingBeta: "Beta sürümünü test ettiğin için teşekkür ederiz!"
createUserSpecifiedNote: "Kullanıcı tarafından belirtilen notlar oluşturun"
schedulePost: "Bir gönderi planla"
scheduleToPostOnX: "{x} için bir gönderi planla"
scheduledToPostOnX: "{x} için bir gönderi planlandı."
schedule: "rezervasyon"
scheduled: "rezervasyon"
widgets: "Widget'lar"
deviceInfo: "Cihaz Bilgileri"
deviceInfoDescription: "Teknik bir sorunuz olduğunda, aşağıdaki bilgileri eklemeniz sorunun çözülmesine yardımcı olabilir."
youAreAdmin: "Siz yöneticisiniz."
frame: "Çerçeve"
presets: "Ön ayar"
zeroPadding: "Sıfır doldurma"
nothingToConfigure: "Ayarlar seçeneği bulunmamaktadır."
viewRenotedChannel: "Show renoted channel"
previewingThemeRestore: "Geri yükle"
_imageEditing:
_vars:
caption: "Dosya başlığı"
filename: "Dosya adı"
filename_without_ext: "Uzantısız dosya adları"
year: "Çekim yılı"
month: "Çekim ayı"
day: "Çekim tarihi"
hour: "Fotoğrafın çekildiği zaman (saat)"
minute: "Çekim süresi (dakika)"
second: "Çekim süresi (saniye)"
camera_model: "Kamera Adı"
camera_lens_model: "Lens adı"
camera_mm: "Odak uzaklığı"
camera_mm_35: "Genişlik (35mm)"
camera_f: "açıklık"
camera_s: "Enstantane hızı"
camera_iso: "ISO hassasiyeti"
gps_lat: "Enlem"
gps_long: "Boylam"
_imageFrameEditor:
title: "Düzenleme kareleri"
tip: "Görselleri, meta verileri içeren çerçeveler ve etiketler ekleyerek süsleyebilirsiniz."
header: "Başlık"
footer: "Alt bilgi"
borderThickness: "jantın genişliği"
labelThickness: "Etiket genişliği"
labelScale: "Etiket ölçeği"
centered: "Merkezlenmiş"
captionMain: "Altyazı (büyük)"
captionSub: "Altyazı (küçük)"
availableVariables: "Mevcut değişkenler"
withQrCode: "2 boyutlu kod"
backgroundColor: "Arka Plan Rengi "
textColor: "Metin Rengi "
font: "Yazı tipi"
fontSerif: "Serif"
fontSansSerif: "Sans Serif"
quitWithoutSaveConfirm: "Kaydedilmemiş değişiklikleri silmek ister misin?"
failedToLoadImage: "Görüntü yükleme başarısız oldu "
_compression:
_quality:
high: "Yüksek Kalite "
medium: "Orta Kalite"
low: "Düşük Kalite "
_size:
large: "Büyük Boyut"
medium: "Orta Boyut"
small: "Küçük Boyut"
_order:
newest: "Önce yeni"
oldest: "Önce eski"
_chat:
messages: "Mesaj"
noMessagesYet: "Henüz mesaj yok"
newMessage: "Yeni mesaj"
individualChat: "Özel Sohbet"
@@ -1481,6 +1552,11 @@ _settings:
showUrlPreview: "URL önizlemesi"
showAvailableReactionsFirstInNote: "Mevcut tepkileri en üstte göster."
showPageTabBarBottom: "Sayfa sekme çubuğunu aşağıda göster"
emojiPaletteBanner: "Emoji seçiciye kalıcı olarak bir palet olarak görüntülenecek ön ayarları kaydedebilir veya seçicinin nasıl görüntüleneceğini özelleştirebilirsiniz."
enableAnimatedImages: "Hareketli görüntüleri etkinleştirin"
settingsPersistence_title: "Ayarların kalıcılığı"
settingsPersistence_description1: "Ayarların kalıcı olarak saklanmasını etkinleştirmek, yapılandırma bilgilerinin kaybolmasını önler."
settingsPersistence_description2: "Ortamınıza bağlı olarak bu özelliği etkinleştirmek mümkün olmayabilir."
_chat:
showSenderName: "Gönderenin adını göster"
sendOnEnter: "Enter tuşuna basarak gönderin"
@@ -1489,6 +1565,8 @@ _preferencesProfile:
profileNameDescription: "Bu cihazı tanımlayan bir ad belirle."
profileNameDescription2: "Örnek: “Ana bilgisayar”, “Akıllı telefon”"
manageProfiles: "Profilleri Yönet"
shareSameProfileBetweenDevicesIsNotRecommended: "Aynı profili birden fazla cihazda kullanmak önerilmez."
useSyncBetweenDevicesOptionIfYouWantToSyncSetting: "Birden fazla cihazda senkronize etmek istediğiniz ayarlarınız varsa, lütfen her bir ayar için \"Birden fazla cihazda senkronize et\" seçeneğini etkinleştirin."
_preferencesBackup:
autoBackup: "Otomatik yedekleme"
restoreFromBackup: "Yedeklemeden geri yükle"
@@ -1498,6 +1576,7 @@ _preferencesBackup:
youNeedToNameYourProfileToEnableAutoBackup: "Otomatik yedeklemeyi etkinleştirmek için bir profil adı ayarlanmalıdır."
autoPreferencesBackupIsNotEnabledForThisDevice: "Bu cihazda ayarların otomatik yedeklemesi etkinleştirilmemiş."
backupFound: "Ayarların yedeği bulundu"
forceBackup: "Ayarların zorunlu yedeklenmesi"
_accountSettings:
requireSigninToViewContents: "İçeriği görüntülemek için oturum açmanız gerekir."
requireSigninToViewContentsDescription1: "Oluşturduğun tüm notları ve diğer içeriği görüntülemek için oturum açman gerekir. Bu, tarayıcıların bilgilerini toplamasına engel olacaktır."
@@ -2003,6 +2082,7 @@ _role:
canManageAvatarDecorations: "Avatar süslerini yönet"
driveCapacity: "Drive kapasitesi"
maxFileSize: "Yükleyebileceğin maksimum dosya boyutu"
maxFileSize_caption: "Önceki aşamada ters proxy veya CDN gibi başka yapılandırma ayarları da olabilir."
alwaysMarkNsfw: "Dosyaları her zaman NSFW olarak işaretle"
canUpdateBioMedia: "Bir simge veya banner görüntüsünü düzenleyebilir"
pinMax: "Sabitlenmiş notların maksimum sayısı"
@@ -2030,6 +2110,7 @@ _role:
uploadableFileTypes_caption: "İzin verilen MIME/dosya türlerini belirtir. Birden fazla MIME türü, yeni bir satırla ayırarak belirtilebilir ve joker karakterler yıldız işareti (*) ile belirtilebilir. (örneğin, image/*)"
uploadableFileTypes_caption2: "Bazı dosya türleri algılanamayabilir. Bu tür dosyalara izin vermek için, spesifikasyona {x} ekle."
noteDraftLimit: "Sunucu notlarının olası taslak sayısı"
scheduledNoteLimit: "Aynı anda oluşturulabilecek planlanmış gönderi sayısı"
watermarkAvailable: "Filigran işlevinin kullanılabilirliği"
_condition:
roleAssignedTo: "Manuel rollere atanmış"
@@ -2420,6 +2501,7 @@ _auth:
scopeUser: "Aşağıdaki kullanıcı olarak çalıştırın"
pleaseLogin: "Uygulamaları yetkilendirmek için lütfen giriş yapın."
byClickingYouWillBeRedirectedToThisUrl: "Erişim izni verildiğinde, otomatik olarak aşağıdaki URL'ye yönlendirileceksin."
alreadyAuthorized: "Bu uygulamaya zaten erişim izinleri verilmiş durumda."
_antennaSources:
all: "Tüm notlar"
homeTimeline: "Takip edilen kullanıcıların notları"
@@ -2468,11 +2550,40 @@ _widgets:
chat: "Sohbet"
_widgetOptions:
showHeader: "Başlığı göster"
transparent: "Arka planı şeffaf yapın"
height: "Yükseklik"
_button:
colored: "Renkli"
_clock:
size: "Boyut"
thickness: "İğne kalınlığı"
thicknessThin: "İnce"
thicknessMedium: "Normal"
thicknessThick: "Kalın"
graduations: "Kadran ölçeği"
graduationDots: "Nokta"
graduationArabic: "Arap rakamları"
fadeGraduations: "ölçeği soluklaştır"
sAnimation: "İkinci el animasyon"
sAnimationElastic: "Gerçek"
sAnimationEaseOut: "Düz"
twentyFour: "24 saat ekran"
labelTime: "Zaman"
labelTz: "Zaman Dilimi"
labelTimeAndTz: "Zaman ve Saat Dilimi"
timezone: "Zaman Dilimi "
showMs: "Milisaniye cinsinden göster"
showLabel: "Etiketi Göster"
_jobQueue:
sound: "Sesleri Çal"
_rss:
url: "RSS beslemesi URL'si"
refreshIntervalSec: "Güncelleme aralığı (saniye)"
maxEntries: "Görüntülenecek maksimum öğe sayısı"
_rssTicker:
shuffle: "Görüntüleme sırasını karıştır"
duration: "Kaydırma yazısı hızı (saniye)"
reverse: "Geriye doğru kaydır"
_birthdayFollowings:
period: "Süre"
_cw:
@@ -2519,9 +2630,20 @@ _postForm:
replyPlaceholder: "Bu notu yanıtla..."
quotePlaceholder: "Bu notu alıntı yap..."
channelPlaceholder: "Bir kanala gönder..."
showHowToUse: "Form açıklamasını göster"
_howToUse:
content_title: "Metin"
content_description: "Yayınlamak istediğiniz içeriği girin."
toolbar_title: "Araç Çubuğu"
toolbar_description: "Dosya ve anket ekleyebilir, açıklamalar ve etiketler ekleyebilir, emoji ve bahsetme mesajları ekleyebilirsiniz."
account_title: "Hesap Menüsü"
account_description: "Paylaşım yaptığınız hesabı değiştirebilir ve hesabınıza kaydedilmiş taslak ve planlanmış paylaşımların listesini görüntüleyebilirsiniz."
visibility_title: "Görünürlük"
visibility_description: "Notlarınıza kimlerin erişebileceğinin kapsamını belirleyebilirsiniz."
menu_title: "Menü"
menu_description: "Taslak olarak kaydetme, gönderi planlama ve tepki ayarlama gibi diğer işlemleri de gerçekleştirebilirsiniz."
submit_title: "Gönder düğmesi"
submit_description: "Bir not paylaşacağım. Ctrl + Enter / Cmd + Enter tuşlarını kullanarak da paylaşım yapabilirsiniz."
_placeholders:
a: "Ne yapıyorsun?"
b: "Çevrende neler oluyor?"
@@ -2667,6 +2789,8 @@ _notification:
youReceivedFollowRequest: "Bir takip isteği aldınız."
yourFollowRequestAccepted: "Takip isteğin kabul edildi."
pollEnded: "Anket sonuçlarııklandı."
scheduledNotePosted: "Rezervasyon defteri yayınlandı."
scheduledNotePostFailed: "Rezervasyon defterine gönderilemedi"
newNote: "Yeni not"
unreadAntennaNote: "{name} anteni"
roleAssigned: "Verilen rol"
@@ -2696,6 +2820,8 @@ _notification:
quote: "Alıntılar"
reaction: "Tepki"
pollEnded: "Anketler sona eriyor"
scheduledNotePosted: "Planlanan gönderi başarılı"
scheduledNotePostFailed: "Planlanan gönderi başarısız oldu"
receiveFollowRequest: "Takip istekleri alındı"
followRequestAccepted: "Kabul edilen takip istekleri"
roleAssigned: "Verilen rol"
@@ -2735,6 +2861,14 @@ _deck:
usedAsMinWidthWhenFlexible: "“Otomatik genişlik ayarı” seçeneği etkinleştirildiğinde, bunun için minimum genişlik kullanılacak."
flexible: "Otomatik genişlik ayarı"
enableSyncBetweenDevicesForProfiles: "Cihazlar arasında profil bilgilerinin senkronizasyonunu etkinleştir"
showHowToUse: "Kullanıcı arayüzü açıklamasını görüntüle"
_howToUse:
addColumn_title: "Sütun ekle"
addColumn_description: "Sütun türlerini seçip ekleyebilirsiniz."
settings_title: "Arayüz Yapılandırması"
settings_description: "Sekme kullanıcı arayüzünü ayrıntılı olarak yapılandırabilirsiniz."
switchProfile_title: "Profili Değiştir"
switchProfile_description: "Kullanıcı arayüzü düzenlerini profil olarak kaydedebilir ve istediğiniz zaman bunlar arasında geçiş yapabilirsiniz."
_columns:
main: "Ana"
widgets: "Widget'lar"
@@ -2795,6 +2929,8 @@ _abuseReport:
notifiedWebhook: "Kullanılacak webhook"
deleteConfirm: "Bildirim alıcısını silmek istediğinden emin misin?"
_moderationLogTypes:
clearQueue: "Kuyruğu temizle"
promoteQueue: "Sıraya alınmış işi yeniden deneyin."
createRole: "Rol oluşturuldu"
deleteRole: "Rol silindi"
updateRole: "Rol güncellendi"
@@ -3189,10 +3325,13 @@ _watermarkEditor:
title: "Filigranı Düzenle"
cover: "Her şeyi örtün"
repeat: "her yere yayılmış"
preserveBoundingRect: "Döndürme sırasında dışarı çıkmayacak şekilde ayarlayın."
opacity: "Opaklık"
scale: "Boyut"
text: "Metin"
qr: "2 boyutlu kod"
position: "Pozisyon"
margin: "Kenar"
type: "Tür"
image: "Görseller"
advanced: "Gelişmiş"
@@ -3207,16 +3346,21 @@ _watermarkEditor:
polkadotSubDotOpacity: "İkincil noktanın opaklığı"
polkadotSubDotRadius: "İkincil noktanın boyutu"
polkadotSubDotDivisions: "Alt nokta sayısı."
leaveBlankToAccountUrl: "Boş bırakılması durumunda hesap URL'si görüntülenecektir."
failedToLoadImage: "Görüntü yükleme başarısız oldu "
_imageEffector:
title: "Effektler"
addEffect: "Efektler Ekle"
discardChangesConfirm: "Cidden çıkmak istiyor musun? Kaydedilmemiş değişikliklerin var."
failedToLoadImage: "Görüntü yükleme başarısız oldu "
_fxs:
chromaticAberration: "Renk Sapması"
glitch: "Bozulma"
mirror: "Ayna"
invert: "Renkleri Ters Çevir"
grayscale: "Gri tonlama"
blur: "Bulanıklık"
pixelate: "Mozaik"
colorAdjust: "Renk Düzeltme"
colorClamp: "Renk Sıkıştırma"
colorClampAdvanced: "Renk Sıkıştırma (Gelişmiş)"
@@ -3228,10 +3372,13 @@ _imageEffector:
checker: "Denetleyici"
blockNoise: "Gürültüyü Engelle"
tearing: "Yırtılma"
fill: "Doldur"
_fxProps:
angle: "Açı"
scale: "Boyut"
size: "Boyut"
radius: "Yarıçap"
samples: "Örnek sayısı"
offset: "Pozisyon"
color: "Renk"
opacity: "Opaklık"
@@ -3256,11 +3403,10 @@ _imageEffector:
threshold: "Eşik"
centerX: "Merkez X"
centerY: "Merkez Y"
zoomLinesSmoothing: "Düzeltme"
zoomLinesSmoothingDescription: "Düzeltme ve yakınlaştırma çizgi genişliği birlikte kullanılamaz."
zoomLinesThreshold: "Zoom çizgi genişliği"
density: "Yoğunluk"
zoomLinesOutlineThickness: "çizgi gölge kalınlığı"
zoomLinesMaskSize: "Merkez çapı"
zoomLinesBlack: "Siyah yap"
circle: "Dairesel"
drafts: "Taslaklar"
_drafts:
select: "Taslak Seç"
@@ -3276,6 +3422,22 @@ _drafts:
restoreFromDraft: "Taslaktan geri yükle"
restore: "Geri yükle"
listDrafts: "Taslaklar Listesi"
schedule: "Planlanmış Gönderi"
listScheduledNotes: "Planlanmış gönderilerin listesi"
cancelSchedule: "Rezervasyonu iptal et"
qr: "2 boyutlu kod"
_qr:
showTabTitle: "Ekran"
readTabTitle: "Okumak"
shareTitle: "{name}{acct}"
shareText: "Beni Fediverse'te takip edin!"
chooseCamera: "Kamera Seç"
cannotToggleFlash: "Işık seçeneği mevcut değil."
turnOnFlash: "Işığıın"
turnOffFlash: "Işığı kapatın"
startQr: "Özgeçmiş Kodu Okuyucu"
stopQr: "Kod okuyucuyu durdurun"
noQrCodeFound: "QR kodu bulunamadı"
scanFile: "Cihazdaki görüntüyü tarayın"
raw: "Metin"
mfm: "MFM"

View File

@@ -922,6 +922,7 @@ information: "Інформація"
inMinutes: "х"
inDays: "д"
widgets: "Віджети"
previewingThemeRestore: "Відновити"
_imageEditing:
_vars:
filename: "Ім'я файлу"

View File

@@ -1,5 +1,5 @@
---
_lang_: "Tiếng Việt "
_lang_: "Tiếng Việt"
headlineMisskey: "Mạng xã hội liên hợp"
introMisskey: "Xin chào! Misskey là một nền tảng tiểu blog phi tập trung mã nguồn mở.\nViết \"tút\" để chia sẻ những suy nghĩ của bạn 📡\nBằng \"biểu cảm\", bạn có thể bày tỏ nhanh chóng cảm xúc của bạn với các tút 👍\nHãy khám phá một thế giới mới! 🚀"
poweredByMisskeyDescription: "{name} là một trong những chủ máy của <b>Misskey</b> là nền tảng mã nguồn mở"
@@ -576,6 +576,7 @@ showFixedPostForm: "Hiện khung soạn tút ở phía trên bảng tin"
showFixedPostFormInChannel: "Hiển thị mẫu bài đăng ở phía trên bản tin"
withRepliesByDefaultForNewlyFollowed: "Mặc định hiển thị trả lời từ những người dùng mới theo dõi trong dòng thời gian"
newNoteRecived: "Đã nhận tút mới"
newNote: "Ghi chú mới"
sounds: "Âm thanh"
sound: "Âm thanh"
notificationSoundSettings: "Cài đặt âm thanh thông báo"
@@ -848,7 +849,7 @@ hideOnlineStatus: "Ẩn trạng thái online"
hideOnlineStatusDescription: "Ẩn trạng thái online của bạn làm giảm sự tiện lợi của một số tính năng như tìm kiếm."
online: "Online"
active: "Hoạt động"
offline: "Offline"
offline: "Ngoại tuyến"
notRecommended: "Không đề xuất"
botProtection: "Bảo vệ Bot"
instanceBlocking: "Máy chủ đã chặn"
@@ -1220,10 +1221,12 @@ information: "Giới thiệu"
chat: "Trò chuyện"
migrateOldSettings: "Di chuyển cài đặt cũ"
migrateOldSettings_description: "Thông thường, quá trình này diễn ra tự động, nhưng nếu vì lý do nào đó mà quá trình di chuyển không thành công, bạn có thể kích hoạt thủ công quy trình di chuyển, quá trình này sẽ ghi đè lên thông tin cấu hình hiện tại của bạn."
driveAboutTip: "Trong Drive, danh sách các tệp bạn đã tải lên trước đây sẽ được hiển thị.<br>\nBạn có thể sử dụng lại chúng khi đính kèm vào ghi chú, hoặc tải lên trước các tệp để đăng sau.<br>\n<b>Lưu ý rằng nếu bạn xóa một tệp, tệp đó cũng sẽ biến mất khỏi tất cả những nơi đã sử dụng tệp đó (ghi chú, trang, ảnh đại diện, biểu ngữ, v.v.).</b><br>\nBạn cũng có thể tạo các thư mục để sắp xếp chúng."
inMinutes: "phút"
inDays: "ngày"
widgets: "Tiện ích"
presets: "Mẫu thiết lập"
previewingThemeRestore: "Khôi phục"
_imageEditing:
_vars:
filename: "Tên tập tin"

View File

@@ -63,7 +63,7 @@ copyUserId: "复制用户 ID"
copyNoteId: "复制帖子 ID"
copyFileId: "复制文件ID"
copyFolderId: "复制文件夹ID"
copyProfileUrl: "复制个人资料URL"
copyProfileUrl: "复制个人资料链接"
searchUser: "搜索用户"
searchThisUsersNotes: "搜索用户帖子"
reply: "回复"
@@ -101,12 +101,12 @@ somethingHappened: "出错了"
retry: "重试"
pageLoadError: "页面加载失败。"
pageLoadErrorDescription: "这通常是由于网络或浏览器缓存的原因。请清除缓存或等待片刻后重试。"
serverIsDead: "没有服务器响应。 请稍后再试。"
serverIsDead: "服务器响应。 请稍后再试。"
youShouldUpgradeClient: "请重新加载并使用新版本的客户端查看此页面。"
enterListName: "输入列表名称"
privacy: "隐私"
makeFollowManuallyApprove: "关注请求需要批准"
defaultNoteVisibility: "默认可见"
defaultNoteVisibility: "默认可见范围"
follow: "关注"
followRequest: "申请关注"
followRequests: "关注请求"
@@ -137,10 +137,10 @@ pinnedEmojisForReactionSettingDescription: "可以设置发表回应时置顶显
pinnedEmojisSettingDescription: "可以设置输入表情符号时置顶显示的表情符号"
emojiPickerDisplay: "选择器显示设置"
overwriteFromPinnedEmojisForReaction: "使用「置顶(回应)」设置覆盖"
overwriteFromPinnedEmojis: "全局设置覆盖"
overwriteFromPinnedEmojis: "使用全局设置覆盖"
reactionSettingDescription2: "拖动重新排序,单击删除,点击 + 添加。"
rememberNoteVisibility: "保存上次设置的可见性"
attachCancel: "取消添加附件"
attachCancel: "移除附件"
deleteFile: "删除文件"
markAsSensitive: "标记为敏感内容"
unmarkAsSensitive: "取消标记为敏感内容"
@@ -149,12 +149,12 @@ mute: "屏蔽"
unmute: "取消隐藏"
renoteMute: "隐藏转帖"
renoteUnmute: "取消隐藏转帖"
block: "屏蔽"
unblock: "取消屏蔽"
block: "禁止对方与我互动"
unblock: "允许对方与我互动"
suspend: "冻结"
unsuspend: "解除冻结"
blockConfirm: "确定要屏蔽吗?"
unblockConfirm: "确定要取消屏蔽吗?"
blockConfirm: "确定要禁止对方与我互动吗?"
unblockConfirm: "确定要允许对方与我互动吗?"
suspendConfirm: "要冻结吗?"
unsuspendConfirm: "要解除冻结吗?"
selectList: "选择列表"
@@ -164,7 +164,7 @@ selectAntenna: "选择天线"
editAntenna: "编辑天线"
createAntenna: "创建天线"
selectWidget: "选择小工具"
editWidgets: "编辑部件"
editWidgets: "编辑小工具"
editWidgetsExit: "完成编辑"
customEmojis: "自定义表情符号"
emoji: "表情符号"
@@ -184,7 +184,7 @@ flagAsCat: "喵!!!!!!!!!!!!"
flagAsCatDescription: "喵喵喵??"
flagShowTimelineReplies: "在时间线上显示帖子的回复"
flagShowTimelineRepliesDescription: "启用时,时间线除了显示用户的帖子外,还会显示其他用户对帖子的回复。"
autoAcceptFollowed: "自动允许回关请求"
autoAcceptFollowed: "自动允许我关注的人的关注请求"
addAccount: "添加账户"
reloadAccountsList: "更新账户列表"
loginFailed: "登录失败"
@@ -207,7 +207,7 @@ selectSelf: "选择自己"
selectUser: "选择用户"
recipient: "收件人"
annotation: "注解"
federation: "联"
federation: "联"
instances: "服务器"
registeredAt: "初次观测"
latestRequestReceivedAt: "上次收到的请求"
@@ -244,11 +244,11 @@ silencedInstances: "被静音的服务器"
silencedInstancesDescription: "设置要静音的服务器,以换行分隔。被静音的服务器内所有的账户都被视为「静音」状态,且关注操作均需要被批准。已被屏蔽的实例不受影响。"
mediaSilencedInstances: "已隐藏媒体文件的服务器"
mediaSilencedInstancesDescription: "设置要隐藏媒体文件的服务器,以换行分隔。被设置的服务器内所有账号的文件均按照「敏感内容」处理,且将无法使用自定义表情符号。已被屏蔽的实例不受影响。"
federationAllowedHosts: "允许联的服务器"
federationAllowedHostsDescription: "设定允许联的服务器,以换行分隔。"
muteAndBlock: "隐藏/屏蔽"
mutedUsers: "已隐藏的用户"
blockedUsers: "已屏蔽的用户"
federationAllowedHosts: "允许联邦交互的服务器"
federationAllowedHostsDescription: "设定允许联邦通信的服务器,以换行分隔。"
muteAndBlock: "屏蔽用户/禁止用户与我互动"
mutedUsers: "已屏蔽的用户"
blockedUsers: "禁止与我互动的用户"
noUsers: "无用户"
editProfile: "编辑资料"
noteDeleteConfirm: "确定要删除该帖子吗?"
@@ -261,7 +261,7 @@ default: "默认"
defaultValueIs: "默认值: {value}"
noCustomEmojis: "没有自定义表情符号"
noJobs: "没有任务"
federating: "联中"
federating: "联邦通信中"
blocked: "已屏蔽"
suspended: "停止投递"
all: "全部"
@@ -277,7 +277,7 @@ retypedNotMatch: "两次输入不一致!"
currentPassword: "现在的密码"
newPassword: "新密码"
newPasswordRetype: "重新输入密码:"
attachFile: "插入附件"
attachFile: "添加附件"
more: "更多!"
featured: "热门"
usernameOrUserId: "用户名或用户 ID"
@@ -342,7 +342,7 @@ selectFolders: "选择多个文件夹"
fileNotSelected: "未选择文件"
renameFile: "重命名文件"
folderName: "文件夹名称"
createFolder: "建文件夹"
createFolder: "建文件夹"
renameFolder: "重命名文件夹"
deleteFolder: "删除文件夹"
folder: "文件夹"
@@ -353,7 +353,7 @@ emptyFolder: "此文件夹中无文件"
dropHereToUpload: "将文件拖动到这里来上传"
unableToDelete: "无法删除"
inputNewFileName: "请输入新文件名"
inputNewDescription: "请输入新标题"
inputNewDescription: "请输入新的描述文本"
inputNewFolderName: "请输入新文件夹名"
circularReferenceFolder: "目标文件夹是要移动的文件夹的子文件夹。"
hasChildFilesOrFolders: "此文件夹中有文件,无法删除。"
@@ -396,10 +396,10 @@ driveCapacityPerLocalAccount: "每个用户的网盘容量"
driveCapacityPerRemoteAccount: "每个远程用户的网盘容量"
inMb: "以兆字节(MegaByte)为单位"
bannerUrl: "横幅 URL"
backgroundImageUrl: "背景图 URL"
backgroundImageUrl: "背景图片的链接"
basicInfo: "基本信息"
pinnedUsers: "置顶用户"
pinnedUsersDescription: "输入您想要固定到“发现页面的用户,一行一个。"
pinnedUsersDescription: "在「发现页面中使用换行标记想要置顶的用户。"
pinnedPages: "固定页面"
pinnedPagesDescription: "输入您要固定到服务器首页的页面路径,以换行符分隔。"
pinnedClipId: "置顶的便签 ID"
@@ -432,7 +432,7 @@ antennaExcludeBots: "排除机器人账户"
antennaKeywordsDescription: "AND 条件用空格分隔OR 条件用换行符分隔。"
notifyAntenna: "开启通知"
withFileAntenna: "仅带有附件的帖子"
excludeNotesInSensitiveChannel: "排除敏感频道的帖子"
excludeNotesInSensitiveChannel: "排除敏感频道的帖子"
enableServiceworker: "启用 ServiceWorker"
antennaUsersDescription: "指定用户名,用换行符进行分隔"
caseSensitive: "区分大小写"
@@ -476,7 +476,7 @@ passwordLessLogin: "无密码登录"
passwordLessLoginDescription: "不使用密码,仅使用安全密钥或 Passkey 登录"
resetPassword: "重置密码"
newPasswordIs: "新的密码是「{password}」"
reduceUiAnimation: "减少 UI 动"
reduceUiAnimation: "减少 UI 动"
share: "分享"
notFound: "未找到"
notFoundDescription: "没有与指定 URL 对应的页面。"
@@ -543,6 +543,7 @@ regenerate: "重新生成"
fontSize: "字体大小"
mediaListWithOneImageAppearance: "仅一张图片的媒体列表高度"
limitTo: "上限为 {x}"
showMediaListByGridInWideArea: "在宽屏上并排显示媒体列表"
noFollowRequests: "没有关注请求"
openImageInNewTab: "在新标签页中打开图片"
dashboard: "管理面板"
@@ -580,7 +581,7 @@ s3ForcePathStyleDesc: "启用 s3ForcePathStyle 会强制将存储桶名称指定
serverLogs: "服务器日志"
deleteAll: "全部删除"
showFixedPostForm: "在时间线顶部显示发帖框"
showFixedPostFormInChannel: "在时间线顶部显示发帖对话框(频道)"
showFixedPostFormInChannel: "在时间线顶部显示发帖框(频道)"
withRepliesByDefaultForNewlyFollowed: "在时间线中默认包含新关注用户的回复"
newNoteRecived: "有新的帖子"
newNote: "新帖子"
@@ -645,7 +646,7 @@ addedRelays: "已添加的中继"
serviceworkerInfo: "您需要启用推送通知"
deletedNote: "已删除的帖子"
invisibleNote: "隐藏的帖子"
enableInfiniteScroll: "启用自动滚动页面模式"
enableInfiniteScroll: "自动加载更多内容"
visibility: "可见性"
poll: "投票"
useCw: "隐藏内容"
@@ -655,7 +656,7 @@ expandTweet: "展开帖子"
themeEditor: "主题编辑器"
description: "描述"
describeFile: "添加描述"
enterFileDescription: "输入标题"
enterFileDescription: "输入描述文本"
author: "作者"
leaveConfirm: "存在未保存的更改。要放弃更改吗?"
manage: "管理"
@@ -663,7 +664,7 @@ plugins: "插件"
preferencesBackups: "备份设置"
deck: "Deck"
undeck: "取消 Deck"
useBlurEffectForModal: "对话框使用模糊效果"
useBlurEffectForModal: "发帖背景使用模糊效果"
useFullReactionPicker: "使用全功能的回应工具栏"
width: "宽度"
height: "高度"
@@ -772,13 +773,13 @@ yes: "是"
no: "否"
driveFilesCount: "网盘的文件数"
driveUsage: "网盘的空间用量"
noCrawle: "要求搜索引擎索引该用户"
noCrawleDescription: "要求搜索引擎不要收录(索引)您的用户页面,帖子,页面等。"
noCrawle: "拒绝搜索引擎索引"
noCrawleDescription: "拒绝搜索引擎收录(索引)您的个人资料,帖子,页面等。"
lockedAccountInfo: "即使启用该功能,只要帖子可见范围不是「仅关注者」,任何人都可以看到您的帖子。"
alwaysMarkSensitive: "默认将媒体文件标记为敏感内容"
loadRawImages: "添加附件图像的缩略图时使用原始图像质量"
disableShowingAnimatedImages: "不播放动"
disableShowingAnimatedImages_caption: "如果即使关闭了此设置但动画仍无法播放,可能是浏览器或操作系统的辅助功能设置,又或者是省电设置等产生了干扰。"
disableShowingAnimatedImages: "不播放动态图像"
disableShowingAnimatedImages_caption: "如果即使禁用了此设置,动态图像仍无法播放,可能是由于浏览器或操作系统的辅助功能设置、省电设置或其他因素所致。"
highlightSensitiveMedia: "高亮显示敏感媒体"
verificationEmailSent: "已发送确认电子邮件。请访问电子邮件中的链接以完成设置。"
notSet: "未设置"
@@ -831,7 +832,7 @@ youAreRunningUpToDateClient: "您所使用的客户端已经是最新的。"
newVersionOfClientAvailable: "新版本的客户端可用。"
usageAmount: "使用量"
capacity: "容量"
inUse: "使用"
inUse: "使用"
editCode: "编辑代码"
apply: "应用"
receiveAnnouncementFromInstance: "从服务器接收通知"
@@ -850,7 +851,7 @@ fullView: "全屏"
quitFullView: "退出全屏"
addDescription: "添加描述"
userPagePinTip: "在帖子的菜单中选择“置顶”,即可显示该条帖子。"
notSpecifiedMentionWarning: "有未指定的提及"
notSpecifiedMentionWarning: "有未添加到收件人的提及"
info: "关于"
userInfo: "用户信息"
unknown: "未知"
@@ -876,9 +877,9 @@ noMaintainerInformationWarning: "尚未设置管理员信息。"
noInquiryUrlWarning: "尚未设置联络地址。"
noBotProtectionWarning: "尚未设置 Bot 防御。"
configure: "设置"
postToGallery: "创建新图集"
postToGallery: "发表相册"
postToHashtag: "发布至该话题"
gallery: "图集"
gallery: "相册"
recentPosts: "最新发布"
popularPosts: "热门投稿"
shareWithNote: "分享到帖文"
@@ -1031,7 +1032,7 @@ browserPushNotificationDisabledDescription: "{serverName}无权限发送通知
windowMaximize: "最大化"
windowMinimize: "最小化"
windowRestore: "还原"
caption: "标题"
caption: "描述文本"
loggedInAsBot: "以 Bot 账户登录"
tools: "工具"
cannotLoad: "无法加载"
@@ -1072,7 +1073,7 @@ thisPostMayBeAnnoying: "这个帖子可能会让其他人感到困扰。"
thisPostMayBeAnnoyingHome: "发到首页"
thisPostMayBeAnnoyingCancel: "取消"
thisPostMayBeAnnoyingIgnore: "就这样发布"
collapseRenotes: "省略显示已经看过的转发内容"
collapseRenotes: "折叠已经看过的转"
collapseRenotesDescription: "折叠显示回应或转发过的帖文。"
internalServerError: "内部服务器错误"
internalServerErrorDescription: "内部服务器发生了预期外的错误"
@@ -1080,9 +1081,9 @@ copyErrorInfo: "复制错误信息"
joinThisServer: "在本服务器上注册"
exploreOtherServers: "探索其他服务器"
letsLookAtTimeline: "看看时间线"
disableFederationConfirm: "确定要禁用联"
disableFederationConfirmWarn: "禁用联不会将帖子设为私有。在大多数情况下,不需要禁用联。"
disableFederationOk: "联合禁用"
disableFederationConfirm: "确定要禁用联邦交互"
disableFederationConfirmWarn: "即使禁用联邦交互,也不会将帖子设为私有。在大多数情况下,没有必要禁用联邦交互。"
disableFederationOk: "禁用联邦"
invitationRequiredToRegister: "此服务器目前只允许拥有邀请码的人注册。"
emailNotSupported: "此服务器不支持发送邮件"
postToTheChannel: "发布到频道"
@@ -1092,7 +1093,7 @@ likeOnly: "仅点赞"
likeOnlyForRemote: "全部(远程仅点赞)"
nonSensitiveOnly: "仅限非敏感内容"
nonSensitiveOnlyForLocalLikeOnlyForRemote: "仅限非敏感内容(远程仅点赞)"
rolesAssignedToMe: "指派给自己的角色"
rolesAssignedToMe: "的角色"
resetPasswordConfirm: "确定重置密码?"
sensitiveWords: "敏感词"
sensitiveWordsDescription: "包含这些词的帖子将只在首页可见。可用换行来设定多个词。"
@@ -1147,7 +1148,7 @@ pleaseAgreeAllToContinue: "必须全部勾选「同意」才能够继续。"
continue: "继续"
preservedUsernames: "保留的用户名"
preservedUsernamesDescription: "列出需要保留的用户名,使用换行来作为分割。被指定的用户名在建立账户时无法使用,但由管理员所创建的账户不受该限制。此外,现有的账户也不会受到影响。"
createNoteFromTheFile: "从文件创建帖子"
createNoteFromTheFile: "使用该文件发帖"
archive: "归档"
archived: "已归档"
unarchive: "取消归档"
@@ -1157,7 +1158,7 @@ thisChannelArchived: "该频道已被归档。"
displayOfNote: "显示帖子"
initialAccountSetting: "初始设定"
youFollowing: "正在关注"
preventAiLearning: "拒绝接受生成式 AI 的学习"
preventAiLearning: "拒绝用于训练生成式 AI"
preventAiLearningDescription: "要求文章生成 AI 或图像生成 AI 不能够以发布的帖子和图像等内容作为学习对象。这是通过在 HTML 响应中包含 noai 标志来实现的,这不能完全阻止 AI 学习你的发布内容,并不是所有 AI 都会遵守这类请求。"
options: "选项"
specifyUser: "指定用户"
@@ -1225,8 +1226,8 @@ notificationRecieveConfig: "通知接收设置"
mutualFollow: "互相关注"
followingOrFollower: "关注中或关注者"
fileAttachedOnly: "仅限媒体"
showRepliesToOthersInTimeline: "在时间线中包含给别人的回复"
hideRepliesToOthersInTimeline: "在时间线中隐藏给别人的回复"
showRepliesToOthersInTimeline: "在时间线中显示对他人的回复"
hideRepliesToOthersInTimeline: "在时间线中隐藏对他人的回复"
showRepliesToOthersInTimelineAll: "在时间线中显示所有现在关注的人的回复"
hideRepliesToOthersInTimelineAll: "在时间线中隐藏所有现在关注的人的回复"
confirmShowRepliesAll: "此操作不可撤销。确认要在时间线中显示所有现在关注的人的回复吗?"
@@ -1324,22 +1325,22 @@ lockdown: "锁定"
pleaseSelectAccount: "请选择帐户"
availableRoles: "可用角色"
acknowledgeNotesAndEnable: "理解注意事项后再开启。"
federationSpecified: "此服务器已开启联白名单。只能与管理员指定的服务器通信。"
federationDisabled: "此服务器已禁用联。无法与其它服务器上的用户通信。"
federationSpecified: "此服务器已开启联白名单模式。只能与管理员指定的服务器通信。"
federationDisabled: "此服务器已禁用联邦功能。无法与其它服务器上的用户通信。"
draft: "草稿"
draftsAndScheduledNotes: "草稿和定时发送"
confirmOnReact: "发送回应前需要确认"
reactAreYouSure: "要用「{emoji}」进行回应吗?"
markAsSensitiveConfirm: "要将此媒体标记为敏感吗?"
unmarkAsSensitiveConfirm: "要将此媒体解除敏感标记吗?"
markAsSensitiveConfirm: "确定标记此媒体为敏感内容吗?"
unmarkAsSensitiveConfirm: "确定取消标记为敏感内容吗?"
preferences: "偏好设置"
accessibility: "辅助功能"
preferencesProfile: "设置的配置文件"
copyPreferenceId: "复制设置 ID"
resetToDefaultValue: "重置为默认值"
overrideByAccount: "覆盖账号"
overrideByAccount: "使用账户设置"
untitled: "未命名"
noName: "没有名字"
noName: "未命名"
skip: "跳过"
restore: "恢复"
syncBetweenDevices: "设备间同步"
@@ -1350,7 +1351,7 @@ preferenceSyncConflictChoiceServer: "服务器上的设定值"
preferenceSyncConflictChoiceDevice: "设备上的设定值"
preferenceSyncConflictChoiceCancel: "取消同步"
paste: "粘贴"
emojiPalette: "表情符号调色板"
emojiPalette: "表情符号选择器"
postForm: "发帖窗口"
textCount: "字数"
information: "关于"
@@ -1367,7 +1368,7 @@ embed: "嵌入"
settingsMigrating: "正在迁移设置,请稍候。(之后也可以在设置 → 其它 → 迁移旧设置来手动迁移)"
readonly: "只读"
goToDeck: "返回至 Deck"
federationJobs: "联作业"
federationJobs: "联作业"
driveAboutTip: "网盘可以显示以前上传的文件。<br>\n也可以在发布帖子时重复使用文件或在发布帖子前预先上传文件。<br>\n<b>删除文件时,其将从至今为止所有用到该文件的地方(如帖子、页面、头像、横幅)消失。</b><br>\n也可以新建文件夹来整理文件。"
scrollToClose: "滑动并关闭"
advice: "建议"
@@ -1381,7 +1382,7 @@ unmuteX: "取消对{x}的隐藏"
abort: "中止"
tip: "提示和技巧"
redisplayAllTips: "重新显示所有的提示和技巧"
hideAllTips: "隐藏所有的提示技巧"
hideAllTips: "隐藏所有的提示技巧"
defaultImageCompressionLevel: "默认图像压缩等级"
defaultImageCompressionLevel_description: "较低的等级可以保持画质,但会增加文件大小。<br>较高的等级可以减少文件大小,但相对应的画质将会降低。"
defaultCompressionLevel: "默认压缩等级"
@@ -1393,7 +1394,7 @@ pluginsAreDisabledBecauseSafeMode: "因启用了安全模式,所有插件均
customCssIsDisabledBecauseSafeMode: "因启用了安全模式,无法应用自定义 CSS。"
themeIsDefaultBecauseSafeMode: "启用安全模式时将使用默认主题。关闭安全模式后将还原。"
thankYouForTestingBeta: "感谢您协助测试 beta 版!"
createUserSpecifiedNote: "创建指定用户的帖子"
createUserSpecifiedNote: "提及该用户并发帖"
schedulePost: "定时发布"
scheduleToPostOnX: "预定在 {x} 发出"
scheduledToPostOnX: "已预定在 {x} 发出"
@@ -1407,6 +1408,9 @@ frame: "边框"
presets: "预设值"
zeroPadding: "填充 0"
nothingToConfigure: "没有项目"
viewRenotedChannel: "查看转帖所属频道"
previewingTheme: "正在预览主题"
previewingThemeRestore: "还原"
_imageEditing:
_vars:
caption: "文件标题"
@@ -1509,10 +1513,10 @@ _chat:
mutual: "仅相互关注"
none: "没有人"
_emojiPalette:
palettes: "调色板"
enableSyncBetweenDevicesForPalettes: "启用调色板的设备间同步"
paletteForMain: "主调色板"
paletteForReaction: "回应用调色板"
palettes: "表情符号托盘"
enableSyncBetweenDevicesForPalettes: "在设备间同步表情符号托盘"
paletteForMain: "主表情符号托盘"
paletteForReaction: "回应时的表情符号托盘"
_settings:
driveBanner: "可在此管理和设置网盘、确认使用量及配置上传文件的设置。"
pluginBanner: "使用插件可以扩展客户端的功能。可以在此安装、单独管理插件。"
@@ -1533,9 +1537,9 @@ _settings:
timelineAndNote: "时间线和帖子"
makeEveryTextElementsSelectable: "使所有的文字均可选择"
makeEveryTextElementsSelectable_description: "若开启,在某些情况下可能降低用户体验。"
useStickyIcons: "使图标跟随滚动"
useStickyIcons: "用户头像跟随页面滚动"
enableHighQualityImagePlaceholders: "显示高质量图像的占位符"
uiAnimations: "UI 动"
uiAnimations: "UI 动"
showNavbarSubButtons: "在导航栏中显示副按钮"
ifOn: "启用时"
ifOff: "关闭时"
@@ -1550,7 +1554,7 @@ _settings:
showAvailableReactionsFirstInNote: "在顶部显示可用的回应"
showPageTabBarBottom: "在下方显示页面标签栏"
emojiPaletteBanner: "可以将固定显示在表情符号选择器中的预设注册为调色板,也可以自定义表情符号选择器的显示方式。"
enableAnimatedImages: "启用动图像"
enableAnimatedImages: "启用动图像"
settingsPersistence_title: "设置持久化"
settingsPersistence_description1: "启用设置持久化可防止设置信息丢失。"
settingsPersistence_description2: "根据环境不同,有可能无法开启。"
@@ -1578,12 +1582,12 @@ _accountSettings:
requireSigninToViewContents: "需要登录才能显示内容"
requireSigninToViewContentsDescription1: "您发布的所有帖子将变成需要登入后才会显示。有望防止爬虫收集各种信息。"
requireSigninToViewContentsDescription2: "没有 URL 预览OGP、内嵌网页、引用帖子的功能的服务器也将无法显示。"
requireSigninToViewContentsDescription3: "这些限制可能不适用于联合到远程服务器的内容。"
requireSigninToViewContentsDescription3: "对于已通过联邦分发到远程服务器的内容,这些限制可能不适用。"
makeNotesFollowersOnlyBefore: "可将过去的帖子设为仅关注者可见"
makeNotesFollowersOnlyBeforeDescription: "开启此设定时,超过设定的时间或日期后,帖子将变为仅关注者可见。关闭后帖子的公开状态将恢复成原本的设定。"
makeNotesHiddenBefore: "将过去的帖子设为私密"
makeNotesHiddenBeforeDescription: "开启此设定时,超过设定的时间或日期后,帖子将变为仅自己可见。关闭后帖子的公开状态将恢复成原本的设定。"
mayNotEffectForFederatedNotes: "远程服务器联合的帖子在远端可能会没有效果。"
mayNotEffectForFederatedNotes: "对于已通过联邦投递到远程服务器的帖子,此操作在远端可能无法生效。"
mayNotEffectSomeSituations: "此限制功能非常简单,在与远程服务器联合等情形时可能不适用。"
notesHavePassedSpecifiedPeriod: "超过指定时间的帖子"
notesOlderThanSpecifiedDateAndTime: "指定日期前的帖子"
@@ -1635,7 +1639,7 @@ _announcement:
_initialAccountSetting:
accountCreated: "账户创建完成了!"
letsStartAccountSetup: "马上来进行账户的初始设定吧。"
letsFillYourProfile: "首先,来设定你的个人档案吧!"
letsFillYourProfile: "首先,设置一下您的个人资料吧!"
profileSetting: "个人资料设置"
privacySetting: "隐私设置"
theseSettingsCanEditLater: "也可以在稍后修改这里的设置。"
@@ -1687,10 +1691,10 @@ _initialTutorial:
public: "向所有用户公开。\n"
home: "仅在首页时间线上发布。 关注者、从个人资料页查看过来的用户、以及通过转帖也能被别的用户看见。"
followers: "仅对关注者可见。 除了您自己之外,没有人可以转贴,并且只有您的关注者可以查看它。\n"
direct: "它将仅向指定用户公开,并且他们也会收到通知。 您可以使用它来代替私信。\n"
direct: "仅对指定用户公开,且收件人将收到通知。"
doNotSendConfidencialOnDirect1: "发送敏感信息时请注意。\n"
doNotSendConfidencialOnDirect2: "目标服务器的管理员可以看到发布的内容,因此如果您向不受信任的服务器上的用户发送私信,则在处理敏感信息时需要小心。"
localOnly: "不将帖子推送到其它服务器。 无论上述公开范围如何,其它服务器的用户将无法看到附加了此设定的帖子。\n"
localOnly: "不将帖子通过联邦推送到其它服务器。 无论上述公开范围如何,其它服务器的用户将无法看到附加了此设定的帖子。\n"
_cw:
title: "隐藏内容 (CW)\n"
description: "显示「注解」里的内容而不是正文。点击「查看更多」将会把正文显示出来。"
@@ -1699,7 +1703,7 @@ _initialTutorial:
note: "茨了带巧克力的甜甜圈🍩😋"
useCases: "用于服务器条款所规定的帖子,或对剧透内容和敏感内容进行自主规制。"
_howToMakeAttachmentsSensitive:
title: "如何将附件标注为敏感内容?"
title: "如何标记附件为敏感内容?"
description: "对于服务器方针所要求要求的,又或者不适合直接展示的附件,请添加「敏感」标记。\n"
tryThisFile: "试试看,将附加到此窗口的图像标注为敏感!"
_exampleNote:
@@ -1744,7 +1748,7 @@ _serverSettings:
singleUserMode: "单用户模式"
singleUserMode_description: "若此服务器只有自己使用,开启此模式将最佳化性能。"
signToActivityPubGet: "对 GET 请求签名"
signToActivityPubGet_description: "通常情况下请保持启用。若遇到联通信方面的问题,将其关闭可能会有所改善,但另一方面有可能会造成无法通信。"
signToActivityPubGet_description: "通常情况下请保持启用。若遇到联通信方面的问题,将其关闭可能会有所改善,但另一方面有可能会造成无法通信。"
proxyRemoteFiles: "代理远程文件"
proxyRemoteFiles_description: "如果启用,远程服务器的文件将由代理提供。可有效保护图像预览缩略图的生成与用户隐私。"
allowExternalApRedirect: "允许通过 ActivityPub 重定向查询"
@@ -1769,7 +1773,7 @@ _accountMigration:
moveTo: "把这个账户迁移到新的账户"
moveToLabel: "迁移后的账户"
moveCannotBeUndone: "一旦迁移账户,就无法撤销。"
moveAccountDescription: "\n迁移到新帐户。\n ・现有的关注者自动关注新帐户\n ・此帐户的所有关注者都将被删除\n ・您将无法再使用此帐户发帖。\n关注者迁移是自动的但关注中迁移必须手动完成。请在迁移前在此帐户上导出关注列表并在迁移后立即在目标帐户上执行导入。\n列表、隐藏、屏蔽也是如此,因此您必须手动迁移它。\n此描述适用于该服务器Misskey v13.12.0 或更高版本)。其他 ActivityPub 软件(例如 Mastodon的行为可能有所不同。"
moveAccountDescription: "\n迁移到新帐户。\n ・现有的关注者自动关注新帐户\n ・此帐户的所有关注者都将被删除\n ・您将无法再使用此帐户发帖。\n关注者迁移是自动的但关注中迁移必须手动完成。请在迁移前在此帐户上导出关注列表并在迁移后立即在目标帐户上执行导入。\n列表、屏蔽列表、禁止与我互动的列表也是如此,因此您必须手动迁移它。\n此描述适用于该服务器Misskey v13.12.0 或更高版本)。其他 ActivityPub 软件(例如 Mastodon的行为可能有所不同。"
moveAccountHowTo: "要进行账户迁移,请现在目标账户中为此账户建立一个别名。\n建立别名后请像这样输入目标账户@username@server.example.com"
startMigration: "迁移"
migrationConfirm: "确定要把此账户迁移到 {account} 吗?一旦确定后,此操作无法取消,此账户也无法以原来的状态使用。\n同时请确认迁移后的账户已创造别名。"
@@ -1887,7 +1891,7 @@ _achievements:
description: "第一次将帖子加入收藏"
_myNoteFavorited1:
title: "想要星星"
description: "自己的帖子被其他人加入收藏了"
description: "自己的帖子被其他人收藏了"
_profileFilled:
title: "整装待发"
description: "设置了个人资料"
@@ -2081,7 +2085,7 @@ _role:
maxFileSize: "可上传的最大文件大小"
maxFileSize_caption: "可能在反向代理或 CDN 等前端存在其它设定值。"
alwaysMarkNsfw: "总是将文件标记为 NSFW"
canUpdateBioMedia: "可以更新头像和横幅"
canUpdateBioMedia: "允许更新头像和横幅"
pinMax: "帖子置顶数量限制"
antennaMax: "可创建的最大天线数量"
wordMuteMax: "折叠词的字数限制"
@@ -2096,9 +2100,10 @@ _role:
canSearchNotes: "是否可以搜索帖子"
canSearchUsers: "使用用户检索"
canUseTranslator: "使用翻译功能"
canCreateChannel: "创建频道"
avatarDecorationLimit: "可添加头像挂件的最大个数"
canImportAntennas: "允许导入天线"
canImportBlocking: "允许导入屏蔽列表"
canImportBlocking: "允许导入禁止与我互动的列表"
canImportFollowing: "允许导入关注列表"
canImportMuting: "允许导入隐藏列表"
canImportUserLists: "允许导入用户列表"
@@ -2106,7 +2111,7 @@ _role:
uploadableFileTypes: "可上传的文件类型"
uploadableFileTypes_caption: "指定 MIME 类型。可用换行指定多个类型,也可以用星号(*)作为通配符。(如 image/*"
uploadableFileTypes_caption2: "文件根据文件的不同,可能无法判断其类型。若要允许此类文件,请在指定中添加 {x}。"
noteDraftLimit: "可在服务器上创建多少草稿"
noteDraftLimit: "可在服务器上创建的草稿数量"
scheduledNoteLimit: "可同时创建的定时帖子数量"
watermarkAvailable: "能否使用水印功能"
_condition:
@@ -2163,7 +2168,7 @@ _ad:
back: "返回"
reduceFrequencyOfThisAd: "减少此广告的频率"
hide: "不显示"
timezoneinfo: "星期几是服务器的时区所指定的。"
timezoneinfo: "星期几是根据服务器的时区定的。"
adsSettings: "广告设置"
notesPerOneAd: "在实时更新时间线中插入广告的间隔(帖子个数)"
setZeroToDisable: "设为 0 将不在实时更新时间线中投放广告"
@@ -2227,7 +2232,7 @@ _aboutMisskey:
_displayOfSensitiveMedia:
respect: "隐藏敏感媒体"
ignore: "显示敏感媒体"
force: "隐藏所有内容"
force: "隐藏所有媒体"
_instanceTicker:
none: "不显示"
remote: "仅远程用户"
@@ -2251,11 +2256,11 @@ _channel:
allowRenoteToExternal: "允许转发到频道外和引用"
_menuDisplay:
sideFull: "横向"
sideIcon: "横向(图标)"
sideIcon: "横向图标"
top: "顶部"
hide: "隐藏"
_wordMute:
muteWords: "要屏蔽的词"
muteWords: "要折叠的词"
muteWordsDescription: "AND 条件用空格分隔OR 条件用换行符分隔。"
muteWordsDescription2: "正则表达式用斜线包裹"
_instanceMute:
@@ -2313,7 +2318,7 @@ _theme:
mention: "提及"
mentionMe: "提及"
renote: "转发"
modalBg: "对话框背景"
modalBg: "发帖背景"
divider: "分割线"
scrollbarHandle: "滚动条"
scrollbarHandleHover: "滚动条(悬停)"
@@ -2332,7 +2337,7 @@ _theme:
fgHighlighted: "高亮显示文本"
_sfx:
note: "帖子"
noteMy: "我的帖子"
noteMy: "发帖"
notification: "通知"
reaction: "选择回应时"
chatMessage: "私信"
@@ -2401,8 +2406,8 @@ _2fa:
_permissions:
"read:account": "查看账户信息"
"write:account": "更改帐户信息"
"read:blocks": "查看屏蔽列表"
"write:blocks": "编辑屏蔽列表"
"read:blocks": "查看禁止与我互动的列表"
"write:blocks": "编辑禁止与我互动的列表"
"read:drive": "查看网盘"
"write:drive": "管理网盘文件"
"read:favorites": "查看收藏夹"
@@ -2427,10 +2432,10 @@ _permissions:
"write:user-groups": "编辑用户组"
"read:channels": "查看频道"
"write:channels": "管理频道"
"read:gallery": "浏览图集"
"write:gallery": "编辑图集"
"read:gallery-likes": "浏览喜欢的图集"
"write:gallery-likes": "管理喜欢的图集"
"read:gallery": "浏览相册"
"write:gallery": "管理相册"
"read:gallery-likes": "浏览喜欢的相册"
"write:gallery-likes": "管理喜欢的相册"
"read:flash": "查看 Play"
"write:flash": "编辑 Play"
"read:flash-likes": "查看 Play 的点赞"
@@ -2454,7 +2459,7 @@ _permissions:
"write:admin:unsuspend-user": "解除用户冻结"
"write:admin:meta": "编辑实例元数据"
"write:admin:user-note": "编辑管理笔记"
"write:admin:roles": "编辑角色"
"write:admin:roles": "管理角色"
"read:admin:roles": "查看角色"
"write:admin:relays": "编辑中继"
"read:admin:relays": "查看中继"
@@ -2464,8 +2469,8 @@ _permissions:
"read:admin:announcements": "查看公告"
"write:admin:avatar-decorations": "编辑头像挂件"
"read:admin:avatar-decorations": "查看头像挂件"
"write:admin:federation": "编辑联相关信息"
"write:admin:account": "编辑用户账户"
"write:admin:federation": "编辑联相关信息"
"write:admin:account": "管理用户账户"
"read:admin:account": "查看用户相关情报"
"write:admin:emoji": "编辑表情符号"
"read:admin:emoji": "查看表情符号"
@@ -2481,7 +2486,7 @@ _permissions:
"read:invite-codes": "获取已发行的邀请码"
"write:clip-favorite": "管理喜欢的便签"
"read:clip-favorite": "查看便签的点赞"
"read:federation": "查看联相关信息"
"read:federation": "查看联相关信息"
"write:report-abuse": "举报用户"
"write:chat": "撰写或删除消息"
"read:chat": "查看私信"
@@ -2528,7 +2533,7 @@ _widgets:
photos: "照片"
digitalClock: "数字时钟"
unixClock: "UNIX 时钟"
federation: "联"
federation: "联"
instanceCloud: "服务器球状列表"
postForm: "发帖窗口"
slideshow: "幻灯片展示"
@@ -2561,7 +2566,7 @@ _widgetOptions:
graduationDots: "点"
graduationArabic: "阿拉伯数字"
fadeGraduations: "淡化表盘"
sAnimation: "秒针动"
sAnimation: "秒针动"
sAnimationElastic: "跳动"
sAnimationEaseOut: "平滑"
twentyFour: "24 小时制"
@@ -2619,11 +2624,11 @@ _visibility:
followersDescription: "仅发送至关注者"
specified: "指定用户"
specifiedDescription: "仅发送至指定用户"
disableFederation: "不参与联合"
disableFederation: "仅限本地"
disableFederationDescription: "不发送到其他服务器"
_postForm:
quitInspiteOfThereAreUnuploadedFilesConfirm: "还有未上传的文件,要丢弃并关闭窗口吗?"
uploaderTip: "文件未上传。可以在文件菜单中进行重命名、裁剪、添加水印、设置是否压缩等操作。文件将在帖时自动上传。"
uploaderTip: "文件未上传。可以在文件菜单中设置重命名、裁剪图片、添加水印以及是否压缩等功能。文件将在帖子发布时自动上传。"
replyPlaceholder: "回复这个帖子..."
quotePlaceholder: "引用这个帖子..."
channelPlaceholder: "发布到频道…"
@@ -2658,12 +2663,12 @@ _profile:
metadataDescription: "最多可以在个人资料中以表格形式显示四条其他信息。"
metadataLabel: "标签"
metadataContent: "内容"
changeAvatar: "修改头像"
changeBanner: "修改横幅"
changeAvatar: "更换头像"
changeBanner: "更换横幅"
verifiedLinkDescription: "如果将内容设置为 URL当链接所指向的网页内包含自己的个人资料链接时可以显示一个已验证图标。"
avatarDecorationMax: "最多可添加 {max} 个挂件"
followedMessage: "被关注时显示的消息"
followedMessageDescription: "可以设置被关注时向对方显示的短消息。"
followedMessage: "被关注时的信息"
followedMessageDescription: "被关注时,可设置向关注者显示的息。"
followedMessageDescriptionForLockedAccount: "需要批准才能关注的情况下,消息会在请求被批准后显示。"
_exportOrImport:
allNotes: "所有帖子"
@@ -2671,13 +2676,13 @@ _exportOrImport:
clips: "便签"
followingList: "关注中"
muteList: "隐藏"
blockingList: "屏蔽"
blockingList: "禁止与我互动的列表"
userLists: "列表"
excludeMutingUsers: "排除已隐藏用户"
excludeInactiveUsers: "排除不活跃用户"
withReplies: "在时间线中包含导入用户的回复"
_charts:
federation: "联"
federation: "联"
apRequest: "请求"
usersIncDec: "用户数量:增加/减少"
usersTotal: "用户总数"
@@ -2975,7 +2980,7 @@ _moderationLogTypes:
deleteAccount: "删除帐户"
deletePage: "删除页面"
deleteFlash: "删除 Play"
deleteGalleryPost: "删除图集内容"
deleteGalleryPost: "删除相册内容"
deleteChatRoom: "删除群聊"
updateProxyAccountDescription: "更新代理账户的简介"
_fileViewer:
@@ -3032,7 +3037,7 @@ _dataSaver:
description: "防止自动加载图像和视频。 点击隐藏的图像/视频即可加载它们。\n"
_avatar:
title: "头像"
description: "停止播放头像的动画。 由于动画图片的文件大小可能比普通图像大,这可以进一步减少数据流量。"
description: "播放头像的动画。 由于动态图像的文件大小远大于一般图像,停止播放能够进一步节省数据流量。"
_urlPreviewThumbnail:
title: "不显示 URL预览缩略图"
description: "将不再加载 URL 预览缩略图。"
@@ -3051,7 +3056,7 @@ _reversi:
gameSettings: "对局设置"
chooseBoard: "选择棋盘"
blackOrWhite: "先手/后手"
blackIs: "{name}执黑(先手)"
blackIs: "{name}执黑先手"
rules: "规则"
thisGameIsStartedSoon: "对局即将开始"
waitingForOther: "等待对手准备"
@@ -3067,7 +3072,7 @@ _reversi:
surrendered: "已认输"
timeout: "超时"
drawn: "平局"
won: "{name}获胜"
won: "{name} 获胜"
black: "黑"
white: "白"
total: "总计"
@@ -3076,7 +3081,7 @@ _reversi:
allGames: "所有对局"
ended: "结束"
playing: "对局中"
isLlotheo: "落子少的一方获胜(又名奥赛罗"
isLlotheo: "落子少的一方获胜(黑白棋规则"
loopedMap: "循环棋盘"
canPutEverywhere: "无限制放置模式"
timeLimitForEachTurn: "1回合的时间限制"
@@ -3086,8 +3091,8 @@ _reversi:
shareToTlTheGameWhenStart: "开始时在时间线发布对局"
iStartedAGame: "对局开始!#MisskeyReversi"
opponentHasSettingsChanged: "对手更改了设定"
allowIrregularRules: "允许非常规规则(完全自由)"
disallowIrregularRules: "禁止非常规规则"
allowIrregularRules: "允许特殊规则(完全自由)"
disallowIrregularRules: "禁止特殊规则"
showBoardLabels: "显示行号和列号"
useAvatarAsStone: "用头像作为棋子"
_offlineScreen:
@@ -3244,7 +3249,7 @@ _search:
searchScopeLocal: "本地"
searchScopeServer: "指定服务器"
searchScopeUser: "指定用户"
pleaseEnterServerHost: "请填写服务器主机名"
pleaseEnterServerHost: "请填写服务器主机名"
pleaseSelectUser: "请选择用户"
serverHostPlaceholder: "如misskey.example.com"
_serverSetupWizard:
@@ -3273,13 +3278,13 @@ _serverSetupWizard:
largeScaleServerAdvice: "运营大规模服务器可能需要高级基础设施知识,如负载均衡和数据库复制。"
doYouConnectToFediverse: "要加入 Fediverse 吗?"
doYouConnectToFediverse_description1: "若加入由分散性服务器所构成的网络Fediverse将能与其它服务器交换内容。"
doYouConnectToFediverse_description2: "加入 Fediverse 在这里被称为「联」。"
youCanConfigureMoreFederationSettingsLater: "可在之后进行如哪些服务器可以进行联等高级设置。"
doYouConnectToFediverse_description2: "加入 Fediverse 在这里被称为「联」。"
youCanConfigureMoreFederationSettingsLater: "可在之后进行如哪些服务器允许进行联邦交互等高级设置。"
remoteContentsCleaning: "自动清理传入内容"
remoteContentsCleaning_description: "加入联合后,服务器将持续接收大量内容。打开自动清理后,将自动删除无法找到的旧内容,可节省存储空间。"
remoteContentsCleaning_description: "开启联邦互通后,服务器将持续接收大量内容。打开自动清理后,将自动删除无法找到的旧内容,可节省存储空间。"
adminInfo: "管理员信息"
adminInfo_description: "设置用于接受询问的管理员信息。"
adminInfo_mustBeFilled: "开放服务器或启了联的情况下必须输入。"
adminInfo_mustBeFilled: "开放服务器或启了联的情况下必须输入。"
followingSettingsAreRecommended: "推荐以下设置"
applyTheseSettings: "使用此设置"
skipSettings: "跳过设置"
@@ -3299,7 +3304,7 @@ _uploader:
doneConfirm: "部分文件尚未上传,是否继续?"
maxFileSizeIsX: "可上传最大 {x} 的文件。"
allowedTypes: "可上传的文件类型"
tip: "文件还没有被上传。在此对话框中进行上传前确认、重命名、压缩裁剪等操作。准备完成后,点击上传即可开始上传。"
tip: "文件尚未上传。在此对话框中,您可以进行上传前确认、重命名、压缩裁剪等操作。准备就绪后,点击上传”按钮即可开始上传。"
_clientPerformanceIssueTip:
title: "如果觉得电池耗电过高"
makeSureDisabledAdBlocker: "请关闭广告拦截器"
@@ -3400,11 +3405,9 @@ _imageEffector:
threshold: "阈值"
centerX: "中心 X "
centerY: "中心 Y"
zoomLinesSmoothing: "平滑"
zoomLinesSmoothingDescription: "平滑和集中线宽度设置不能同时使用。"
zoomLinesThreshold: "集中线宽度"
density: "密度"
zoomLinesOutlineThickness: "线条阴影粗细"
zoomLinesMaskSize: "中心直径"
zoomLinesBlack: "变成黑色"
circle: "圆形"
drafts: "草稿"
_drafts:

View File

@@ -10,7 +10,7 @@ notifications: "通知"
username: "使用者名稱"
password: "密碼"
initialPasswordForSetup: "啟動初始設定的密碼"
initialPasswordIsIncorrect: "啟動初始設定密碼錯誤。"
initialPasswordIsIncorrect: "啟動初始設定密碼錯誤。"
initialPasswordForSetupDescription: "如果您自己安裝了 Misskey請使用您在設定檔中輸入的密碼。\n如果您使用 Misskey 的託管服務之類的服務,請使用提供的密碼。\n如果您尚未設定密碼請將其留空並繼續。"
forgotPassword: "忘記密碼"
fetchingAsApObject: "從聯邦宇宙取得中..."
@@ -297,7 +297,7 @@ keepOriginalUploading: "保留原圖"
keepOriginalUploadingDescription: "上傳圖片時保留原始圖片。關閉時,瀏覽器會在上傳時生成適用於網路傳送的版本。"
fromDrive: "從雲端空間中選擇"
fromUrl: "從 URL 上傳"
uploadFromUrl: "從網址上傳"
uploadFromUrl: "從 URL 上傳"
uploadFromUrlDescription: "您要上傳的檔案網址"
uploadFromUrlRequested: "已請求上傳"
uploadFromUrlMayTakeTime: "還需要一些時間才能完成上傳。"
@@ -543,6 +543,7 @@ regenerate: "再次生成"
fontSize: "字體大小"
mediaListWithOneImageAppearance: "只有一張圖片時的檔案列表高度"
limitTo: "上限為 {x}"
showMediaListByGridInWideArea: "當畫面寬度較寬時,將媒體清單以橫向排列顯示"
noFollowRequests: "沒有追隨您的請求"
openImageInNewTab: "於新分頁中開啟圖片"
dashboard: "儀表板"
@@ -824,7 +825,7 @@ saveConfirm: "您要儲存變更嗎?"
deleteConfirm: "你確定要刪除嗎?"
invalidValue: "輸入值無效。"
registry: "登錄表"
closeAccount: "停用帳戶"
closeAccount: "刪除帳戶"
currentVersion: "目前版本"
latestVersion: "最新版本"
youAreRunningUpToDateClient: "您所使用的客戶端已經是最新的。"
@@ -1407,6 +1408,8 @@ frame: "邊框"
presets: "預設值"
zeroPadding: "補零"
nothingToConfigure: "無可設定的項目"
viewRenotedChannel: "顯示轉發貼文者的頻道"
previewingThemeRestore: "復原"
_imageEditing:
_vars:
caption: "檔案標題"
@@ -2156,7 +2159,7 @@ _accountDelete:
accountDelete: "刪除帳戶"
mayTakeTime: "刪除帳戶的處理負荷較大,如果帳戶發佈的內容以及上傳的檔案數量較多,則需要一段時間才能完成。"
sendEmail: "帳戶刪除完成後,將向其電子郵件地址發送通知。"
requestAccountDelete: "刪除帳戶請求"
requestAccountDelete: "請求刪除帳戶"
started: "已開始刪除作業。"
inProgress: "正在刪除"
_ad:
@@ -2360,7 +2363,7 @@ _timeIn:
minutes: "{n}分鐘後"
hours: "{n}小時後"
days: "{n}天後"
weeks: "{n}後"
weeks: "{n}後"
months: "{n}個月後"
years: "{n}年後"
_time:
@@ -2858,14 +2861,14 @@ _deck:
usedAsMinWidthWhenFlexible: "如果啟用「自動調整寬度」,此為最小寬度"
flexible: "自動調整寬度"
enableSyncBetweenDevicesForProfiles: "啟用裝置與裝置之間的設定檔資料同步化"
showHowToUse: "檢視使用者面說明"
showHowToUse: "檢視使用者面說明"
_howToUse:
addColumn_title: "新增欄位"
addColumn_description: "您可以選擇要新增的欄位類型。"
settings_title: "使用者面設定"
settings_description: "您可以對多欄模式使用者面做詳細設定。"
settings_title: "使用者面設定"
settings_description: "您可以對多欄模式使用者面做詳細設定。"
switchProfile_title: "切換設定檔"
switchProfile_description: "將使用者面佈局儲存為設定檔,就可以隨時切換使用。"
switchProfile_description: "將使用者面佈局儲存為設定檔,就可以隨時切換使用。"
_columns:
main: "主列"
widgets: "小工具"
@@ -3400,11 +3403,9 @@ _imageEffector:
threshold: "閾值"
centerX: "X中心座標"
centerY: "Y中心座標"
zoomLinesSmoothing: "平滑化"
zoomLinesSmoothingDescription: "平滑化與集中線寬度設定不能同時使用。"
zoomLinesThreshold: "集中線的寬度"
density: "密度"
zoomLinesOutlineThickness: "線條陰影的粗細"
zoomLinesMaskSize: "中心直徑"
zoomLinesBlack: "變成黑色"
circle: "圓形"
drafts: "草稿\n"
_drafts:

View File

@@ -1,18 +1,17 @@
{
"name": "misskey",
"version": "2026.1.0-beta.0",
"version": "2026.5.1-beta.0",
"codename": "nasubi",
"repository": {
"type": "git",
"url": "https://github.com/misskey-dev/misskey.git"
},
"packageManager": "pnpm@10.27.0",
"packageManager": "pnpm@10.33.2",
"workspaces": [
"packages/misskey-js",
"packages/i18n",
"packages/misskey-reversi",
"packages/misskey-bubble-game",
"packages/misskey-mahjong",
"packages/icons-subsetter",
"packages/frontend-shared",
"packages/frontend-builder",
@@ -29,9 +28,9 @@
"build": "pnpm build-pre && pnpm -r build && pnpm build-assets",
"build-storybook": "pnpm --filter frontend build-storybook",
"build-misskey-js-with-types": "pnpm build-pre && pnpm --filter backend... --filter=!misskey-js build && pnpm --filter backend generate-api-json --no-build && ncp packages/backend/built/api.json packages/misskey-js/generator/api.json && pnpm --filter misskey-js update-autogen-code && pnpm --filter misskey-js build && pnpm --filter misskey-js api",
"start": "cd packages/backend && pnpm compile-config && node ./built/boot/entry.js",
"start:inspect": "cd packages/backend && pnpm compile-config && node --inspect ./built/boot/entry.js",
"start:test": "ncp ./.github/misskey/test.yml ./.config/test.yml && cd packages/backend && cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./built/boot/entry.js",
"start": "cd packages/backend && pnpm compile-config && node ./built/entry.js",
"start:inspect": "cd packages/backend && pnpm compile-config && node --inspect ./built/entry.js",
"start:test": "ncp ./.github/misskey/test.yml ./.config/test.yml && cd packages/backend && cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./built/entry.js",
"cli": "cd packages/backend && pnpm cli",
"init": "pnpm migrate",
"migrate": "cd packages/backend && pnpm migrate",
@@ -45,51 +44,49 @@
"cy:run": "pnpm cypress run",
"e2e": "pnpm start-server-and-test start:test http://localhost:61812 cy:run",
"e2e-dev-container": "ncp ./.config/cypress-devcontainer.yml ./.config/test.yml && pnpm start-server-and-test start:test http://localhost:61812 cy:run",
"jest": "cd packages/backend && pnpm jest",
"jest-and-coverage": "cd packages/backend && pnpm jest-and-coverage",
"backend-unit-test": "cd packages/backend && pnpm test",
"backend-unit-test-and-coverage": "cd packages/backend && pnpm test-and-coverage",
"test": "pnpm -r test",
"test-and-coverage": "pnpm -r test-and-coverage",
"clean": "node scripts/clean.mjs",
"clean-all": "node scripts/clean-all.mjs",
"cleanall": "pnpm clean-all"
},
"resolutions": {
"chokidar": "5.0.0",
"lodash": "4.17.21"
},
"dependencies": {
"cssnano": "7.1.2",
"esbuild": "0.27.2",
"cssnano": "7.1.7",
"esbuild": "0.28.0",
"execa": "9.6.1",
"ignore-walk": "8.0.0",
"js-yaml": "4.1.1",
"postcss": "8.5.6",
"tar": "7.5.2",
"terser": "5.44.1"
"postcss": "8.5.10",
"tar": "7.5.13",
"terser": "5.46.2"
},
"devDependencies": {
"@eslint/js": "9.39.2",
"@misskey-dev/eslint-plugin": "2.2.0",
"@eslint/js": "9.39.4",
"@misskey-dev/eslint-plugin": "2.1.0",
"@types/js-yaml": "4.0.9",
"@types/node": "24.10.4",
"@typescript-eslint/eslint-plugin": "8.50.1",
"@typescript-eslint/parser": "8.50.1",
"@typescript/native-preview": "7.0.0-dev.20251226.1",
"@types/node": "24.12.2",
"@typescript-eslint/eslint-plugin": "8.59.0",
"@typescript-eslint/parser": "8.59.0",
"@typescript/native-preview": "7.0.0-dev.20260426.1",
"cross-env": "10.1.0",
"cypress": "15.8.1",
"eslint": "9.39.2",
"globals": "16.5.0",
"cypress": "15.14.1",
"eslint": "9.39.4",
"globals": "17.5.0",
"ncp": "2.0.0",
"pnpm": "10.27.0",
"typescript": "5.9.3",
"start-server-and-test": "2.1.3"
"pnpm": "10.33.2",
"start-server-and-test": "3.0.2",
"typescript": "5.9.3"
},
"optionalDependencies": {
"@tensorflow/tfjs-core": "4.22.0"
},
"pnpm": {
"overrides": {
"@aiscript-dev/aiscript-languageserver": "-"
"@aiscript-dev/aiscript-languageserver": "-",
"chokidar": "5.0.0",
"lodash": "4.18.1"
},
"ignoredBuiltDependencies": [
"@sentry-internal/node-cpu-profiler",

View File

@@ -1,29 +0,0 @@
{
"$schema": "https://swc.rs/schema.json",
"jsc": {
"parser": {
"syntax": "typescript",
"jsx": true,
"dynamicImport": true,
"decorators": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true,
"react": {
"runtime": "automatic",
"importSource": "@kitajs/html"
}
},
"experimental": {
"keepImportAssertions": true
},
"baseUrl": "src",
"paths": {
"@/*": ["*"]
},
"target": "es2022"
},
"minify": false,
"sourceMaps": "inline"
}

View File

@@ -1,20 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Misskey API</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script
id="api-reference"
data-url="/api.json"></script>
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -1,4 +0,0 @@
user-agent: *
allow: /
# todo: sitemap

View File

@@ -1,121 +0,0 @@
import fs from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import { build } from 'esbuild';
import { swcPlugin } from 'esbuild-plugin-swc';
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
const resolveTsPathsPlugin = {
name: 'resolve-ts-paths',
setup(build) {
build.onResolve({ filter: /^\.{1,2}\/.*\.js$/ }, (args) => {
if (args.importer) {
const absPath = join(args.resolveDir, args.path);
const tsPath = absPath.slice(0, -3) + '.ts';
if (fs.existsSync(tsPath)) return { path: tsPath };
const tsxPath = absPath.slice(0, -3) + '.tsx';
if (fs.existsSync(tsxPath)) return { path: tsxPath };
}
});
},
};
const externalIpaddrPlugin = {
name: 'external-ipaddr',
setup(build) {
build.onResolve({ filter: /^ipaddr\.js$/ }, (args) => {
return { path: args.path, external: true };
});
},
};
/** @type {import('esbuild').BuildOptions} */
const options = {
entryPoints: ['./src/boot/entry.ts'],
minify: true,
keepNames: true,
bundle: true,
outdir: './built/boot',
target: 'node22',
platform: 'node',
format: 'esm',
sourcemap: 'linked',
packages: 'external',
banner: {
js: 'import { createRequire as topLevelCreateRequire } from "module";' +
'import ___url___ from "url";' +
'const require = topLevelCreateRequire(import.meta.url);' +
'const __filename = ___url___.fileURLToPath(import.meta.url);' +
'const __dirname = ___url___.fileURLToPath(new URL(".", import.meta.url));',
},
plugins: [
externalIpaddrPlugin,
resolveTsPathsPlugin,
swcPlugin({
jsc: {
parser: {
syntax: 'typescript',
decorators: true,
dynamicImport: true,
},
transform: {
legacyDecorator: true,
decoratorMetadata: true,
},
experimental: {
keepImportAssertions: true,
},
baseUrl: join(_dirname, 'src'),
paths: {
'@/*': ['*'],
},
target: 'esnext',
keepClassNames: true,
},
}),
externalIpaddrPlugin,
],
// external: [
// 'slacc-*',
// 'class-transformer',
// 'class-validator',
// '@sentry/*',
// '@nestjs/websockets/socket-module',
// '@nestjs/microservices/microservices-module',
// '@nestjs/microservices',
// '@napi-rs/canvas-win32-x64-msvc',
// 'mock-aws-s3',
// 'aws-sdk',
// 'nock',
// 'sharp',
// 'jsdom',
// 're2',
// '@napi-rs/canvas',
// ],
};
const args = process.argv.slice(2).map(arg => arg.toLowerCase());
if (!args.includes('--no-clean')) {
fs.rmSync('./built', { recursive: true, force: true });
}
await buildSrc();
async function buildSrc() {
console.log(`[${_package.name}] start building...`);
await build(options)
.then(() => {
console.log(`[${_package.name}] build succeeded.`);
})
.catch((err) => {
process.stderr.write(err.stderr || err.message || err);
process.exit(1);
});
console.log(`[${_package.name}] finish building.`);
}

View File

@@ -1,220 +0,0 @@
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/en/configuration.html
*/
module.exports = {
// All imported modules in your tests should be mocked automatically
// automock: false,
// Stop running tests after `n` failures
// bail: 0,
// The directory where Jest should store its cached dependency information
// cacheDirectory: "C:\\Users\\ai\\AppData\\Local\\Temp\\jest",
// Automatically clear mock calls and instances between every test
// clearMocks: false,
// Indicates whether the coverage information should be collected while executing the test
// collectCoverage: false,
// An array of glob patterns indicating a set of files for which coverage information should be collected
collectCoverageFrom: ['src/**/*.ts', '!src/**/*.test.ts'],
// The directory where Jest should output its coverage files
coverageDirectory: "coverage",
// An array of regexp pattern strings used to skip coverage collection
// coveragePathIgnorePatterns: [
// "\\\\node_modules\\\\"
// ],
// Indicates which provider should be used to instrument code for coverage
coverageProvider: "v8",
// A list of reporter names that Jest uses when writing coverage reports
// coverageReporters: [
// "json",
// "text",
// "lcov",
// "clover"
// ],
// An object that configures minimum threshold enforcement for coverage results
// coverageThreshold: undefined,
// A path to a custom dependency extractor
// dependencyExtractor: undefined,
// Make calling deprecated APIs throw helpful error messages
// errorOnDeprecated: false,
// Force coverage collection from ignored files using an array of glob patterns
// forceCoverageMatch: [],
// A path to a module which exports an async function that is triggered once before all test suites
// globalSetup: undefined,
// A path to a module which exports an async function that is triggered once after all test suites
// globalTeardown: undefined,
// A set of global variables that need to be available in all test environments
globals: {
},
// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
// maxWorkers: "50%",
// An array of directory names to be searched recursively up from the requiring module's location
// moduleDirectories: [
// "node_modules"
// ],
// An array of file extensions your modules use
// moduleFileExtensions: [
// "js",
// "json",
// "jsx",
// "ts",
// "tsx",
// "node"
// ],
// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
moduleNameMapper: {
// Do not resolve .wasm.js to .wasm by the rule below
'^(.+)\\.wasm\\.js$': '$1.wasm.js',
// SWC converts @/foo/bar.js to `../../src/foo/bar.js`, and then this rule
// converts it again to `../../src/foo/bar` which then can be resolved to
// `.ts` files.
// See https://github.com/swc-project/jest/issues/64#issuecomment-1029753225
// TODO: Use `--allowImportingTsExtensions` on TypeScript 5.0 so that we can
// directly import `.ts` files without this hack.
'^((?:\\.{1,2}|[A-Z:])*/.*)\\.js$': '$1',
},
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
// modulePathIgnorePatterns: [],
// Activates notifications for test results
// notify: false,
// An enum that specifies notification mode. Requires { notify: true }
// notifyMode: "failure-change",
// A preset that is used as a base for Jest's configuration
//preset: "ts-jest/presets/js-with-ts-esm",
// Run tests from one or more projects
// projects: undefined,
// Use this configuration option to add custom reporters to Jest
// reporters: undefined,
// Automatically reset mock state between every test
// resetMocks: false,
// Reset the module registry before running each individual test
// resetModules: false,
// A path to a custom resolver
// resolver: './jest-resolver.cjs',
// Automatically restore mock state between every test
restoreMocks: true,
// The root directory that Jest should scan for tests and modules within
// rootDir: undefined,
// A list of paths to directories that Jest should use to search for files in
roots: [
"<rootDir>"
],
// Allows you to use a custom runner instead of Jest's default test runner
// runner: "jest-runner",
// The paths to modules that run some code to configure or set up the testing environment before each test
// setupFiles: [],
// A list of paths to modules that run some code to configure or set up the testing framework before each test
// setupFilesAfterEnv: [],
// The number of seconds after which a test is considered as slow and reported as such in the results.
// slowTestThreshold: 5,
// A list of paths to snapshot serializer modules Jest should use for snapshot testing
// snapshotSerializers: [],
// The test environment that will be used for testing
testEnvironment: "node",
// Options that will be passed to the testEnvironment
// testEnvironmentOptions: {},
// Adds a location field to test results
// testLocationInResults: false,
// The glob patterns Jest uses to detect test files
testMatch: [
"<rootDir>/test/unit/**/*.ts",
"<rootDir>/src/**/*.test.ts",
],
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
// testPathIgnorePatterns: [
// "\\\\node_modules\\\\"
// ],
// The regexp pattern or array of patterns that Jest uses to detect test files
// testRegex: [],
// This option allows the use of a custom results processor
// testResultsProcessor: undefined,
// This option allows use of a custom test runner
// testRunner: "jasmine2",
// This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
// testURL: "http://localhost",
// Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
// timers: "real",
// A map from regular expressions to paths to transformers
transform: {
"^.+\\.(t|j)sx?$": ["@swc/jest"],
},
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
// transformIgnorePatterns: [
// "\\\\node_modules\\\\",
// "\\.pnp\\.[^\\\\]+$"
// ],
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
// unmockedModulePathPatterns: undefined,
// Indicates whether each individual test should be reported during the run
// verbose: undefined,
// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
// watchPathIgnorePatterns: [],
// Whether to use watchman for file crawling
// watchman: true,
extensionsToTreatAsEsm: ['.ts', '.tsx'],
testTimeout: 60000,
// Let Jest kill the test worker whenever it grows too much
// (It seems there's a known memory leak issue in Node.js' vm.Script used by Jest)
// https://github.com/facebook/jest/issues/11956
maxWorkers: 1, // Make it use worker (that can be killed and restarted)
logHeapUsage: true, // To debug when out-of-memory happens on CI
workerIdleMemoryLimit: '1GiB', // Limit the worker to 1GB (GitHub Workflows dies at 2GB)
maxConcurrency: 32,
};

View File

@@ -1,15 +0,0 @@
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/en/configuration.html
*/
const base = require('./jest.config.cjs')
module.exports = {
...base,
globalSetup: "<rootDir>/built-test/entry.js",
setupFilesAfterEnv: ["<rootDir>/test/jest.setup.ts"],
testMatch: [
"<rootDir>/test/e2e/**/*.ts",
],
};

View File

@@ -1,13 +0,0 @@
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/en/configuration.html
*/
const base = require('./jest.config.cjs');
module.exports = {
...base,
testMatch: [
'<rootDir>/test-federation/test/**/*.test.ts',
],
};

View File

@@ -1,15 +0,0 @@
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/en/configuration.html
*/
const base = require('./jest.config.cjs')
module.exports = {
...base,
globalSetup: "<rootDir>/test/jest.setup.unit.cjs",
testMatch: [
"<rootDir>/test/unit/**/*.ts",
"<rootDir>/src/**/*.test.ts",
],
};

View File

@@ -1,31 +0,0 @@
#!/usr/bin/env node
import child_process from 'node:child_process';
import path from 'node:path';
import url from 'node:url';
import semver from 'semver';
const __filename = url.fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const args = [];
args.push(...[
...semver.satisfies(process.version, '^20.17.0 || ^22.0.0 || ^24.10.0') ? ['--no-experimental-require-module'] : [],
'--experimental-vm-modules',
'--experimental-import-meta-resolve',
path.join(__dirname, 'node_modules/jest/bin/jest.js'),
...process.argv.slice(2),
]);
const child = child_process.spawn(process.execPath, args, { stdio: 'inherit' });
child.on('error', (err) => {
console.error('Failed to start Jest:', err);
process.exit(1);
});
child.on('exit', (code, signal) => {
if (code === null) {
process.exit(128 + signal);
} else {
process.exit(code);
}
});

View File

@@ -1,24 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class Mahjong1706234054207 {
name = 'Mahjong1706234054207'
async up(queryRunner) {
await queryRunner.query(`CREATE TABLE "mahjong_game" ("id" character varying(32) NOT NULL, "startedAt" TIMESTAMP WITH TIME ZONE, "endedAt" TIMESTAMP WITH TIME ZONE, "user1Id" character varying(32), "user2Id" character varying(32), "user3Id" character varying(32), "user4Id" character varying(32), "isEnded" boolean NOT NULL DEFAULT false, "winnerId" character varying(32), "timeLimitForEachTurn" smallint NOT NULL DEFAULT '90', "logs" jsonb NOT NULL DEFAULT '[]', CONSTRAINT "PK_77db54c0a9785d387e3fbbdd2f0" PRIMARY KEY ("id"))`);
await queryRunner.query(`ALTER TABLE "mahjong_game" ADD CONSTRAINT "FK_b98c78761a845b69e6540401264" FOREIGN KEY ("user1Id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "mahjong_game" ADD CONSTRAINT "FK_f17b0ba519ae28f188a7915ad6f" FOREIGN KEY ("user2Id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "mahjong_game" ADD CONSTRAINT "FK_64314ffd3cb59475b0d06330058" FOREIGN KEY ("user3Id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "mahjong_game" ADD CONSTRAINT "FK_58a75f1ea2a810ae3986f72a0e3" FOREIGN KEY ("user4Id") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "mahjong_game" DROP CONSTRAINT "FK_58a75f1ea2a810ae3986f72a0e3"`);
await queryRunner.query(`ALTER TABLE "mahjong_game" DROP CONSTRAINT "FK_64314ffd3cb59475b0d06330058"`);
await queryRunner.query(`ALTER TABLE "mahjong_game" DROP CONSTRAINT "FK_f17b0ba519ae28f188a7915ad6f"`);
await queryRunner.query(`ALTER TABLE "mahjong_game" DROP CONSTRAINT "FK_b98c78761a845b69e6540401264"`);
await queryRunner.query(`DROP TABLE "mahjong_game"`);
}
}

View File

@@ -0,0 +1,22 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class AddCategoryToAvatarDecorations1766652173085 {
name = 'AddCategoryToAvatarDecorations1766652173085';
/**
* @param {QueryRunner} queryRunner
*/
async up(queryRunner) {
await queryRunner.query('ALTER TABLE "avatar_decoration" ADD "category" character varying(128)');
}
/**
* @param {QueryRunner} queryRunner
*/
async down(queryRunner) {
await queryRunner.query('ALTER TABLE "avatar_decoration" DROP COLUMN "category"');
}
};

View File

@@ -1,6 +1,6 @@
import { DataSource } from 'typeorm';
import { loadConfig } from './src-js/config.js';
import { entities } from './src-js/postgres.js';
import { loadConfig } from './built/config.js';
import { entities } from './built/postgres.js';
const isConcurrentIndexMigrationEnabled = process.env.MISSKEY_MIGRATION_CREATE_INDEX_CONCURRENTLY === '1';

View File

@@ -7,51 +7,33 @@
"node": "^22.15.0 || ^24.10.0"
},
"scripts": {
"start": "pnpm compile-config && node ./built/boot/entry.js",
"start:inspect": "pnpm compile-config && node --inspect ./built/boot/entry.js",
"start:test": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./built/boot/entry.js",
"start": "pnpm compile-config && node ./built/entry.js",
"start:inspect": "pnpm compile-config && node --inspect ./built/entry.js",
"start:test": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./built/entry.js",
"migrate": "pnpm compile-config && pnpm typeorm migration:run -d ormconfig.js",
"revert": "pnpm compile-config && pnpm typeorm migration:revert -d ormconfig.js",
"cli": "pnpm compile-config && node ./src-js/boot/cli.js",
"cli": "pnpm compile-config && node ./built/cli.js",
"check:connect": "pnpm compile-config && node ./scripts/check_connect.js",
"compile-config": "node ./scripts/compile_config.js",
"build": "swc src -d src-js -D --strip-leading-paths && node ./build.js",
"build:test": "swc test-server -d built-test -D --config-file test-server/.swcrc --strip-leading-paths",
"watch:swc": "swc src -d built -D -w --strip-leading-paths",
"build": "rolldown -c",
"build:unit": "rolldown -c --sourcemap",
"build:e2e": "rolldown -c --e2e",
"build:tsc": "tsgo -p tsconfig.json && tsc-alias -p tsconfig.json",
"watch": "pnpm compile-config && node ./scripts/watch.mjs",
"restart": "pnpm build && pnpm start",
"dev": "pnpm compile-config && node ./scripts/dev.mjs",
"dev": "pnpm compile-config && rolldown -c --watch",
"typecheck": "tsgo --noEmit && tsgo -p test --noEmit && tsgo -p test-federation --noEmit",
"eslint": "eslint --quiet \"{src,test-federation}/**/*.ts\"",
"lint": "pnpm typecheck && pnpm eslint",
"jest": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./jest.js --forceExit --config jest.config.unit.cjs",
"jest:e2e": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./jest.js --forceExit --config jest.config.e2e.cjs",
"jest:fed": "pnpm compile-config && node ./jest.js --forceExit --config jest.config.fed.cjs",
"jest-and-coverage": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./jest.js --coverage --forceExit --config jest.config.unit.cjs",
"jest-and-coverage:e2e": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./jest.js --coverage --forceExit --config jest.config.e2e.cjs",
"jest-clear": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./jest.js --clearCache",
"test": "pnpm jest",
"test:e2e": "pnpm build && pnpm build:test && pnpm jest:e2e",
"test:fed": "pnpm jest:fed",
"test-and-coverage": "pnpm jest-and-coverage",
"test-and-coverage:e2e": "pnpm build && pnpm build:test && pnpm jest-and-coverage:e2e",
"test": "pnpm build:unit && cross-env NODE_ENV=test pnpm compile-config && vitest --config vitest.config.unit.ts",
"test:e2e": "pnpm build:e2e && cross-env NODE_ENV=test pnpm compile-config && vitest --config vitest.config.e2e.ts",
"test:fed": "cross-env NODE_ENV=test pnpm compile-config && vitest --config vitest.config.fed.ts",
"test-and-coverage": "pnpm build:unit && cross-env NODE_ENV=test pnpm compile-config && vitest --coverage --config vitest.config.unit.ts",
"test-and-coverage:e2e": "pnpm build:e2e && cross-env NODE_ENV=test pnpm compile-config && vitest --coverage --config vitest.config.e2e.ts",
"check-migrations": "node scripts/check_migrations_clean.js",
"generate-api-json": "pnpm compile-config && node ./scripts/generate_api_json.js"
},
"optionalDependencies": {
"@swc/core-android-arm64": "1.3.11",
"@swc/core-darwin-arm64": "1.15.7",
"@swc/core-darwin-x64": "1.15.7",
"@swc/core-freebsd-x64": "1.3.11",
"@swc/core-linux-arm-gnueabihf": "1.15.7",
"@swc/core-linux-arm64-gnu": "1.15.7",
"@swc/core-linux-arm64-musl": "1.15.7",
"@swc/core-linux-x64-gnu": "1.15.7",
"@swc/core-linux-x64-musl": "1.15.7",
"@swc/core-win32-arm64-msvc": "1.15.7",
"@swc/core-win32-ia32-msvc": "1.15.7",
"@swc/core-win32-x64-msvc": "1.15.7",
"@tensorflow/tfjs": "4.22.0",
"@tensorflow/tfjs-node": "4.22.0",
"bufferutil": "4.1.0",
@@ -71,101 +53,99 @@
"utf-8-validate": "6.0.6"
},
"dependencies": {
"@aws-sdk/client-s3": "3.958.0",
"@aws-sdk/lib-storage": "3.958.0",
"@aws-sdk/client-s3": "3.1037.0",
"@aws-sdk/lib-storage": "3.1037.0",
"@discordapp/twemoji": "16.0.1",
"@fastify/accepts": "5.0.4",
"@fastify/cors": "11.2.0",
"@fastify/express": "4.0.2",
"@fastify/http-proxy": "11.4.1",
"@fastify/multipart": "9.3.0",
"@fastify/static": "8.3.0",
"@kitajs/html": "4.2.11",
"@fastify/express": "4.0.5",
"@fastify/http-proxy": "11.4.4",
"@fastify/multipart": "10.0.0",
"@fastify/static": "9.1.3",
"@kitajs/html": "4.2.13",
"@misskey-dev/sharp-read-bmp": "1.2.0",
"@misskey-dev/summaly": "5.2.5",
"@napi-rs/canvas": "0.1.87",
"@nestjs/common": "11.1.10",
"@nestjs/core": "11.1.10",
"@nestjs/testing": "11.1.10",
"@misskey-dev/summaly": "5.3.0",
"@napi-rs/canvas": "0.1.100",
"@nestjs/common": "11.1.19",
"@nestjs/core": "11.1.19",
"@nestjs/testing": "11.1.19",
"@oxc-project/runtime": "0.127.0",
"@peertube/http-signature": "1.7.0",
"@sentry/node": "10.32.1",
"@sentry/profiling-node": "10.32.1",
"@simplewebauthn/server": "13.2.2",
"@sinonjs/fake-timers": "15.1.0",
"@smithy/node-http-handler": "4.4.7",
"@swc/cli": "0.7.9",
"@swc/core": "1.15.7",
"@sentry/node": "10.50.0",
"@sentry/profiling-node": "10.50.0",
"@simplewebauthn/server": "13.3.0",
"@sinonjs/fake-timers": "15.3.2",
"@smithy/node-http-handler": "4.6.1",
"@twemoji/parser": "16.0.0",
"accepts": "1.3.8",
"ajv": "8.17.1",
"ajv": "8.20.0",
"archiver": "7.0.1",
"async-mutex": "0.5.0",
"bcryptjs": "3.0.3",
"blurhash": "2.0.5",
"body-parser": "2.2.1",
"bullmq": "5.66.3",
"body-parser": "2.2.2",
"bullmq": "5.76.2",
"cacheable-lookup": "7.0.0",
"chalk": "5.6.2",
"chalk-template": "1.1.2",
"chokidar": "5.0.0",
"color-convert": "3.1.3",
"content-disposition": "1.0.1",
"content-disposition": "1.1.0",
"date-fns": "4.1.0",
"deep-email-validator": "0.1.21",
"fastify": "5.6.2",
"deep-email-validator": "0.1.27",
"fastify": "5.8.5",
"fastify-raw-body": "5.0.0",
"feed": "5.1.0",
"file-type": "21.2.0",
"feed": "5.2.1",
"file-type": "22.0.1",
"fluent-ffmpeg": "2.1.3",
"form-data": "4.0.5",
"got": "14.6.5",
"got": "15.0.3",
"hpagent": "1.2.0",
"http-link-header": "1.1.3",
"i18n": "workspace:*",
"ioredis": "5.8.2",
"ioredis": "5.10.1",
"ip-cidr": "4.0.2",
"ipaddr.js": "2.3.0",
"is-svg": "6.1.0",
"json5": "2.2.3",
"jsonld": "9.0.0",
"juice": "11.0.3",
"meilisearch": "0.54.0",
"juice": "11.1.1",
"meilisearch": "0.57.0",
"mfm-js": "0.25.0",
"mime-types": "3.0.2",
"misskey-js": "workspace:*",
"misskey-reversi": "workspace:*",
"misskey-mahjong": "workspace:*",
"ms": "3.0.0-canary.202508261828",
"nanoid": "5.1.6",
"nanoid": "5.1.9",
"nested-property": "4.0.0",
"node-fetch": "3.3.2",
"node-html-parser": "7.0.1",
"nodemailer": "7.0.12",
"nsfwjs": "4.2.0",
"node-html-parser": "7.1.0",
"nodemailer": "8.0.6",
"nsfwjs": "4.3.0",
"oauth2orize": "1.12.0",
"oauth2orize-pkce": "0.1.2",
"os-utils": "0.0.14",
"otpauth": "9.4.1",
"pg": "8.16.3",
"pkce-challenge": "5.0.1",
"otpauth": "9.5.1",
"pg": "8.20.0",
"pkce-challenge": "6.0.0",
"probe-image-size": "7.2.3",
"promise-limit": "2.7.0",
"qrcode": "1.5.4",
"random-seed": "0.3.0",
"ratelimiter": "3.4.1",
"re2": "1.23.0",
"re2": "1.24.0",
"reflect-metadata": "0.2.2",
"rename": "1.0.4",
"rss-parser": "3.13.0",
"rxjs": "7.8.2",
"sanitize-html": "2.17.0",
"sanitize-html": "2.17.3",
"secure-json-parse": "4.1.0",
"semver": "7.7.3",
"semver": "7.7.4",
"sharp": "0.33.5",
"slacc": "0.0.10",
"strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0",
"systeminformation": "5.28.1",
"systeminformation": "5.31.5",
"tinycolor2": "1.6.0",
"tmp": "0.2.5",
"tsc-alias": "1.8.16",
@@ -173,62 +153,60 @@
"ulid": "3.0.2",
"vary": "1.1.2",
"web-push": "3.6.7",
"ws": "8.18.3",
"ws": "8.20.0",
"xev": "3.0.2"
},
"devDependencies": {
"@jest/globals": "29.7.0",
"@kitajs/ts-html-plugin": "4.1.3",
"@nestjs/platform-express": "11.1.10",
"@sentry/vue": "10.32.1",
"@simplewebauthn/types": "12.0.0",
"@swc/jest": "0.2.39",
"@kitajs/ts-html-plugin": "4.1.4",
"@nestjs/platform-express": "11.1.19",
"@rollup/plugin-esm-shim": "0.1.8",
"@sentry/vue": "10.50.0",
"@types/accepts": "1.3.7",
"@types/archiver": "7.0.0",
"@types/body-parser": "1.19.6",
"@types/color-convert": "2.0.4",
"@types/color-convert": "3.0.1",
"@types/content-disposition": "0.5.9",
"@types/fluent-ffmpeg": "2.1.28",
"@types/http-link-header": "1.0.7",
"@types/jest": "29.5.14",
"@types/js-yaml": "4.0.9",
"@types/jsonld": "1.5.15",
"@types/mime-types": "3.0.1",
"@types/ms": "2.1.0",
"@types/node": "24.10.4",
"@types/nodemailer": "7.0.4",
"@types/node": "24.12.2",
"@types/nodemailer": "8.0.0",
"@types/oauth2orize": "1.11.5",
"@types/oauth2orize-pkce": "0.1.2",
"@types/pg": "8.16.0",
"@types/pg": "8.20.0",
"@types/qrcode": "1.5.6",
"@types/random-seed": "0.3.5",
"@types/ratelimiter": "3.4.6",
"@types/rename": "1.0.7",
"@types/sanitize-html": "2.16.0",
"@types/sanitize-html": "2.16.1",
"@types/semver": "7.7.1",
"@types/simple-oauth2": "5.0.8",
"@types/sinonjs__fake-timers": "15.0.1",
"@types/supertest": "6.0.3",
"@types/supertest": "7.2.0",
"@types/tinycolor2": "1.4.6",
"@types/tmp": "0.2.6",
"@types/vary": "1.1.3",
"@types/web-push": "3.6.4",
"@types/ws": "8.18.1",
"@typescript-eslint/eslint-plugin": "8.50.1",
"@typescript-eslint/parser": "8.50.1",
"@typescript-eslint/eslint-plugin": "8.59.0",
"@typescript-eslint/parser": "8.59.0",
"@vitest/coverage-v8": "4.1.5",
"aws-sdk-client-mock": "4.1.0",
"cbor": "10.0.11",
"cbor": "10.0.12",
"cross-env": "10.1.0",
"esbuild-plugin-swc": "1.0.1",
"eslint-plugin-import": "2.32.0",
"execa": "9.6.1",
"fkill": "10.0.1",
"jest": "29.7.0",
"jest-mock": "29.7.0",
"fkill": "10.0.3",
"js-yaml": "4.1.1",
"nodemon": "3.1.11",
"pid-port": "2.0.0",
"pid-port": "2.1.1",
"rolldown": "1.0.0-rc.15",
"simple-oauth2": "5.1.0",
"supertest": "7.1.4",
"vite": "7.3.0"
"supertest": "7.2.2",
"vite": "8.0.10",
"vitest": "4.1.5",
"vitest-mock-extended": "4.0.0"
}
}

View File

@@ -0,0 +1,128 @@
import { defineConfig } from 'rolldown';
import type { Plugin, ExternalOption } from 'rolldown';
import { execa, execaNode } from 'execa';
import type { ResultPromise } from 'execa';
import esmShim from '@rollup/plugin-esm-shim';
/**
* Watchモード時にバックエンドの起動・停止制御を行うプラグイン
*/
function backendDevServerPlugin(): Plugin {
let backendProcess: ResultPromise | null = null;
async function runBuildAssets() {
await execa('pnpm', ['run', 'build-assets'], {
cwd: '../../',
stdout: process.stdout,
stderr: process.stderr,
});
}
async function killBackendProcess() {
if (backendProcess) {
backendProcess.catch(() => {}); // backendProcess.kill()によって発生する例外を無視するためにcatch()を呼び出す
backendProcess.kill();
await new Promise(resolve => backendProcess!.on('exit', resolve));
backendProcess = null;
}
}
return {
name: 'backend-dev-server',
async closeBundle() {
await runBuildAssets();
if (backendProcess) {
await killBackendProcess();
}
backendProcess = execaNode('./built/entry.js', [], {
stdout: process.stdout,
stderr: process.stderr,
env: {
NODE_ENV: 'development',
},
});
},
async watchChange() {
if (backendProcess) {
await killBackendProcess();
await runBuildAssets();
}
},
};
}
export default defineConfig((args) => {
const isWatchMode = args.watch != null && args.watch !== 'false';
const isE2E = args.e2e != null && args.e2e !== 'false';
// 通常のビルド時にexternalとするモジュール
const externalModules: ExternalOption = [
/^slacc-.*/,
'class-transformer',
'class-validator',
/^@sentry\/.*/,
/^@sentry-internal\/.*/,
'@nestjs/websockets/socket-module',
'@nestjs/microservices/microservices-module',
'@nestjs/microservices',
/^@napi-rs\/.*/,
'mock-aws-s3',
'aws-sdk',
'nock',
'sharp',
'jsdom',
're2',
'ipaddr.js',
'oauth2orize',
'file-type',
];
if (isE2E) {
return {
input: './test-server/entry.ts',
platform: 'node',
tsconfig: './test-server/tsconfig.json',
plugins: [
esmShim(),
],
output: {
keepNames: true,
sourcemap: true,
dir: './built-test',
cleanDir: true,
format: 'esm',
},
external: externalModules,
};
} else {
return {
input: [
'./src/boot/entry.ts',
'./src/boot/cli.ts',
'./src/config.ts',
'./src/postgres.ts',
'./src/server/api/openapi/gen-spec.ts',
],
platform: 'node',
tsconfig: true,
plugins: [
esmShim(),
(isWatchMode ? backendDevServerPlugin() : undefined),
],
output: {
keepNames: true,
minify: !isWatchMode,
sourcemap: isWatchMode,
dir: './built',
cleanDir: !isWatchMode,
format: 'esm',
},
watch: {
include: ['src/**/*.{ts,js,mjs,cjs,tsx,json}'],
clearScreen: false,
},
// ビルドの高速化のために、watchモードのときは外部モジュールは全てバンドルしないようにする
external: isWatchMode ? /^(?!@\/)[^.\/](?!:[\/\\])/ : externalModules,
};
}
});

View File

@@ -4,8 +4,8 @@
*/
import Redis from 'ioredis';
import { loadConfig } from '../src-js/config.js';
import { createPostgresDataSource } from '../src-js/postgres.js';
import { loadConfig } from '../built/config.js';
import { createPostgresDataSource } from '../built/postgres.js';
const config = loadConfig();

View File

@@ -1,63 +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.catch(() => {}); // backendProcess.kill()によって発生する例外を無視するためにcatch()を呼び出す
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,tsx,json,pug',
'--exec', 'pnpm', 'run', 'build',
],
{
stdio: [process.stdin, process.stdout, process.stderr, 'ipc'],
serialization: "json",
})
.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

@@ -19,10 +19,10 @@ async function main() {
}
/** @type {import('../src/config.js')} */
const { loadConfig } = await import('../src-js/config.js');
const { loadConfig } = await import('../built/config.js');
/** @type {import('../src/server/api/openapi/gen-spec.js')} */
const { genOpenapiSpec } = await import('../src-js/server/api/openapi/gen-spec.js');
const { genOpenapiSpec } = await import('../built/gen-spec.js');
const config = loadConfig();
const spec = genOpenapiSpec(config, true);

View File

@@ -55,7 +55,7 @@ async function getMemoryUsage(pid) {
async function measureMemory() {
// Start the Misskey backend server using fork to enable IPC
const serverProcess = fork(join(__dirname, '../built/boot/entry.js'), ['expose-gc'], {
const serverProcess = fork(join(__dirname, '../built/entry.js'), ['expose-gc'], {
cwd: join(__dirname, '..'),
env: {
...process.env,

View File

@@ -6,7 +6,7 @@
import { Global, Inject, Module } from '@nestjs/common';
import * as Redis from 'ioredis';
import { DataSource } from 'typeorm';
import { MeiliSearch } from 'meilisearch';
import { Meilisearch } from 'meilisearch';
import { MiMeta } from '@/models/Meta.js';
import { DI } from './di-symbols.js';
import { Config, loadConfig } from './config.js';
@@ -40,10 +40,10 @@ const $meilisearch: Provider = {
useFactory: (config: Config) => {
if (config.fulltextSearch?.provider === 'meilisearch') {
if (!config.meilisearch) {
throw new Error('MeiliSearch is enabled but no configuration is provided');
throw new Error('Meilisearch is enabled but no configuration is provided');
}
return new MeiliSearch({
return new Meilisearch({
host: `${config.meilisearch.ssl ? 'https' : 'http'}://${config.meilisearch.host}:${config.meilisearch.port}`,
apiKey: config.meilisearch.apiKey,
});

View File

@@ -4,16 +4,12 @@
*/
import { NestFactory } from '@nestjs/core';
import { ChartManagementService } from '@/core/chart/ChartManagementService.js';
import { QueueProcessorService } from '@/queue/QueueProcessorService.js';
import { NestLogger } from '@/NestLogger.js';
import { QueueProcessorModule } from '@/queue/QueueProcessorModule.js';
import { QueueStatsService } from '@/daemons/QueueStatsService.js';
import { ServerStatsService } from '@/daemons/ServerStatsService.js';
import { ServerService } from '@/server/ServerService.js';
import { MainModule } from '@/MainModule.js';
export async function server() {
const { MainModule } = await import('../MainModule.js');
const { ServerService } = await import('../server/ServerService.js');
const app = await NestFactory.createApplicationContext(MainModule, {
logger: new NestLogger(),
});
@@ -22,6 +18,10 @@ export async function server() {
await serverService.launch();
if (process.env.NODE_ENV !== 'test') {
const { ChartManagementService } = await import('../core/chart/ChartManagementService.js');
const { QueueStatsService } = await import('../daemons/QueueStatsService.js');
const { ServerStatsService } = await import('../daemons/ServerStatsService.js');
app.get(ChartManagementService).start();
app.get(QueueStatsService).start();
app.get(ServerStatsService).start();
@@ -31,6 +31,10 @@ export async function server() {
}
export async function jobQueue() {
const { QueueProcessorModule } = await import('../queue/QueueProcessorModule.js');
const { QueueProcessorService } = await import('../queue/QueueProcessorService.js');
const { ChartManagementService } = await import('../core/chart/ChartManagementService.js');
const jobQueue = await NestFactory.createApplicationContext(QueueProcessorModule, {
logger: new NestLogger(),
});

View File

@@ -13,8 +13,6 @@ import chalk from 'chalk';
import Xev from 'xev';
import Logger from '@/logger.js';
import { envOption } from '../env.js';
import { masterMain } from './master.js';
import { workerMain } from './worker.js';
import { readyRef } from './ready.js';
import 'reflect-metadata';
@@ -71,10 +69,12 @@ process.on('exit', code => {
if (!envOption.disableClustering) {
if (cluster.isPrimary) {
logger.info(`Start main process... pid: ${process.pid}`);
const { masterMain } = await import('./master.js');
await masterMain();
ev.mount();
} else if (cluster.isWorker) {
logger.info(`Start worker process... pid: ${process.pid}`);
const { workerMain } = await import('./worker.js');
await workerMain();
} else {
throw new Error('Unknown process type');
@@ -82,6 +82,7 @@ if (!envOption.disableClustering) {
} else {
// 非clusterの場合はMasterのみが起動するため、Workerの処理は行わない(cluster.isWorker === trueの状態でこのブロックに来ることはない)
logger.info(`Start main process... pid: ${process.pid}`);
const { masterMain } = await import('./master.js');
await masterMain();
ev.mount();
}

View File

@@ -10,7 +10,6 @@ import { type FastifyServerOptions } from 'fastify';
import type * as Sentry from '@sentry/node';
import type * as SentryVue from '@sentry/vue';
import type { RedisOptions } from 'ioredis';
import type { ManifestChunk } from 'vite';
type RedisOptionsSource = Partial<RedisOptions> & {
host: string;
@@ -189,10 +188,9 @@ export type Config = {
authUrl: string;
driveUrl: string;
userAgent: string;
frontendEntry: ManifestChunk;
frontendManifestExists: boolean;
frontendEmbedEntry: ManifestChunk;
frontendEmbedManifestExists: boolean;
rootDir: string;
mediaProxy: string;
externalMediaProxyEnabled: boolean;
videoThumbnailGenerator: string | null;
@@ -250,12 +248,6 @@ export function loadConfig(): Config {
const frontendManifestExists = fs.existsSync(resolve(projectBuiltDir, '_frontend_vite_/manifest.json'));
const frontendEmbedManifestExists = fs.existsSync(resolve(projectBuiltDir, '_frontend_embed_vite_/manifest.json'));
const frontendManifest = frontendManifestExists ?
JSON.parse(fs.readFileSync(resolve(projectBuiltDir, '_frontend_vite_/manifest.json'), 'utf-8'))
: { 'src/_boot_.ts': { file: null } };
const frontendEmbedManifest = frontendEmbedManifestExists ?
JSON.parse(fs.readFileSync(resolve(projectBuiltDir, '_frontend_embed_vite_/manifest.json'), 'utf-8'))
: { 'src/boot.ts': { file: null } };
const config = JSON.parse(fs.readFileSync(compiledConfigFilePath, 'utf-8')) as Source;
@@ -337,10 +329,9 @@ export function loadConfig(): Config {
config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator
: null,
userAgent: `Misskey/${version} (${config.url})`,
frontendEntry: frontendManifest['src/_boot_.ts'],
frontendManifestExists: frontendManifestExists,
frontendEmbedEntry: frontendEmbedManifest['src/boot.ts'],
frontendEmbedManifestExists: frontendEmbedManifestExists,
rootDir,
perChannelMaxNoteCacheCount: config.perChannelMaxNoteCacheCount ?? 1000,
perUserNotificationsMaxCount: config.perUserNotificationsMaxCount ?? 500,
deactivateAntennaThreshold: config.deactivateAntennaThreshold ?? (1000 * 60 * 60 * 24 * 7),

View File

@@ -4,27 +4,31 @@
*/
import * as fs from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
import { Injectable } from '@nestjs/common';
import { pathToFileURL } from 'node:url';
import { resolve } from 'node:path';
import { Injectable, Inject } from '@nestjs/common';
import { Mutex } from 'async-mutex';
import fetch from 'node-fetch';
import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
import type { NSFWJS, PredictionType } from 'nsfwjs';
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
import type { Config } from '@/config.js';
import type { NSFWJS, PredictionType } from 'nsfwjs/core';
const REQUIRED_CPU_FLAGS_X64 = ['avx2', 'fma'];
let isSupportedCpu: undefined | boolean = undefined;
@Injectable()
export class AiService {
private readonly modelDir: string;
private model: NSFWJS;
private modelLoadMutex: Mutex = new Mutex();
constructor(
@Inject(DI.config)
private config: Config,
) {
const md = resolve(this.config.rootDir, 'packages/backend/nsfw-model');
this.modelDir = md.endsWith('/') ? md : md + '/';
}
@bindThis
@@ -43,10 +47,10 @@ export class AiService {
tf.env().global.fetch = fetch;
if (this.model == null) {
const nsfw = await import('nsfwjs');
const nsfw = await import('nsfwjs/core');
await this.modelLoadMutex.runExclusive(async () => {
if (this.model == null) {
this.model = await nsfw.load(`file://${_dirname}/../../nsfw-model/`, { size: 299 });
this.model = await nsfw.load(pathToFileURL(this.modelDir).toString(), { size: 299 });
}
});
}

View File

@@ -78,7 +78,6 @@ import { ChannelFollowingService } from './ChannelFollowingService.js';
import { ChatService } from './ChatService.js';
import { RegistryApiService } from './RegistryApiService.js';
import { ReversiService } from './ReversiService.js';
import { MahjongService } from './MahjongService.js';
import { PageService } from './PageService.js';
import { ChartLoggerService } from './chart/ChartLoggerService.js';
@@ -229,7 +228,6 @@ const $ChannelMutingService: Provider = { provide: 'ChannelMutingService', useEx
const $ChatService: Provider = { provide: 'ChatService', useExisting: ChatService };
const $RegistryApiService: Provider = { provide: 'RegistryApiService', useExisting: RegistryApiService };
const $ReversiService: Provider = { provide: 'ReversiService', useExisting: ReversiService };
const $MahjongService: Provider = { provide: 'MahjongService', useExisting: MahjongService };
const $PageService: Provider = { provide: 'PageService', useExisting: PageService };
const $ChartLoggerService: Provider = { provide: 'ChartLoggerService', useExisting: ChartLoggerService };
@@ -383,7 +381,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ChatService,
RegistryApiService,
ReversiService,
MahjongService,
PageService,
ChartLoggerService,
@@ -534,7 +531,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$ChatService,
$RegistryApiService,
$ReversiService,
$MahjongService,
$PageService,
$ChartLoggerService,
@@ -685,7 +681,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ChatService,
RegistryApiService,
ReversiService,
MahjongService,
PageService,
FederationChart,
@@ -834,7 +829,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$ChatService,
$RegistryApiService,
$ReversiService,
$MahjongService,
$PageService,
$FederationChart,

View File

@@ -6,7 +6,6 @@
import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis';
import * as Reversi from 'misskey-reversi';
import * as Mmj from 'misskey-mahjong';
import type { MiChannel } from '@/models/Channel.js';
import type { MiUser } from '@/models/User.js';
import type { MiUserProfile } from '@/models/UserProfile.js';
@@ -130,6 +129,9 @@ export interface NoteEventTypes {
type NoteStreamEventTypes = {
[key in keyof NoteEventTypes]: {
id: MiNote['id'];
userId: MiNote['userId'];
visibility: MiNote['visibility'];
visibleUserIds: MiNote['visibleUserIds'];
body: NoteEventTypes[key];
};
};
@@ -202,78 +204,6 @@ export interface ReversiGameEventTypes {
userId: MiUser['id'];
};
}
export interface MahjongRoomEventTypes {
joined: {
index: number;
user: Packed<'UserLite'> | null;
};
changeReadyStates: {
user1: boolean;
user2: boolean;
user3: boolean;
user4: boolean;
};
started: {
room: Packed<'MahjongRoomDetailed'>;
};
nextKyoku: {
room: Packed<'MahjongRoomDetailed'>;
};
tsumo: {
house: Mmj.House;
tile: number;
};
dahai: {
house: Mmj.House;
tile: number;
riichi: boolean;
};
dahaiAndTsumo: {
dahaiHouse: Mmj.House;
dahaiTile: number;
tsumoTile: number;
riichi: boolean;
};
ponned: {
caller: Mmj.House;
callee: Mmj.House;
tiles: readonly [number, number, number];
};
kanned: {
caller: Mmj.House;
callee: Mmj.House;
tiles: readonly [number, number, number, number];
rinsyan: number;
};
ciied: {
caller: Mmj.House;
callee: Mmj.House;
tiles: readonly [number, number, number];
};
ronned: {
callers: Mmj.House[];
callee: Mmj.House;
handTiles: Record<Mmj.House, number[]>;
};
ryuukyoku: object;
ankanned: {
house: Mmj.House;
tiles: readonly [number, number, number, number];
rinsyan: number;
};
kakanned: {
house: Mmj.House;
tiles: readonly [number, number, number, number];
rinsyan: number;
from: Mmj.House;
};
tsumoHora: {
house: Mmj.House;
handTiles: number[];
tsumoTile: number;
};
}
//#endregion
// 辞書(interface or type)から{ type, body }ユニオンを定義
@@ -393,10 +323,6 @@ export type GlobalEvents = {
name: `reversiGameStream:${MiReversiGame['id']}`;
payload: EventTypesToEventPayload<ReversiGameEventTypes>;
};
mahjongRoom: {
name: `mahjongRoomStream:${string}`;
payload: EventUnionFromDictionary<SerializedAll<MahjongRoomEventTypes>>;
};
};
// API event definitions
@@ -455,9 +381,12 @@ export class GlobalEventService {
}
@bindThis
public publishNoteStream<K extends keyof NoteEventTypes>(noteId: MiNote['id'], type: K, value?: NoteEventTypes[K]): void {
this.publish(`noteStream:${noteId}`, type, {
id: noteId,
public publishNoteStream<K extends keyof NoteEventTypes>(note: MiNote, type: K, value?: NoteEventTypes[K]): void {
this.publish(`noteStream:${note.id}`, type, {
id: note.id,
userId: note.userId,
visibility: note.visibility,
visibleUserIds: note.visibleUserIds,
body: value,
});
}
@@ -506,9 +435,4 @@ export class GlobalEventService {
public publishReversiGameStream<K extends keyof ReversiGameEventTypes>(gameId: MiReversiGame['id'], type: K, value?: ReversiGameEventTypes[K]): void {
this.publish(`reversiGameStream:${gameId}`, type, typeof value === 'undefined' ? null : value);
}
@bindThis
public publishMahjongRoomStream<K extends keyof MahjongRoomEventTypes>(roomId: string, type: K, value?: MahjongRoomEventTypes[K]): void {
this.publish(`mahjongRoomStream:${roomId}`, type, typeof value === 'undefined' ? null : value);
}
}

View File

@@ -5,29 +5,25 @@
import * as fs from 'node:fs';
import * as Path from 'node:path';
import { fileURLToPath } from 'node:url';
import { dirname } from 'node:path';
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { bindThis } from '@/decorators.js';
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
const path = Path.resolve(_dirname, '../../../../files');
@Injectable()
export class InternalStorageService {
private readonly path: string;
constructor(
@Inject(DI.config)
private config: Config,
) {
this.path = Path.resolve(this.config.rootDir, 'files');
}
@bindThis
public resolvePath(key: string) {
return Path.resolve(path, key);
return Path.resolve(this.path, key);
}
@bindThis
@@ -37,14 +33,14 @@ export class InternalStorageService {
@bindThis
public saveFromPath(key: string, srcPath: string) {
fs.mkdirSync(path, { recursive: true });
fs.mkdirSync(this.path, { recursive: true });
fs.copyFileSync(srcPath, this.resolvePath(key));
return `${this.config.url}/files/${key}`;
}
@bindThis
public saveFromBuffer(key: string, data: Buffer) {
fs.mkdirSync(path, { recursive: true });
fs.mkdirSync(this.path, { recursive: true });
fs.writeFileSync(this.resolvePath(key), data);
return `${this.config.url}/files/${key}`;
}

View File

@@ -6,7 +6,7 @@
import { Injectable } from '@nestjs/common';
import Logger from '@/logger.js';
import { bindThis } from '@/decorators.js';
import type { KEYWORD } from 'color-convert/conversions.js';
import type { Keyword } from 'color-convert';
@Injectable()
export class LoggerService {
@@ -15,7 +15,7 @@ export class LoggerService {
}
@bindThis
public getLogger(domain: string, color?: KEYWORD | undefined) {
public getLogger(domain: string, color?: Keyword | undefined) {
return new Logger(domain, color);
}
}

View File

@@ -1,734 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis';
import { ModuleRef } from '@nestjs/core';
import { IsNull, LessThan, MoreThan } from 'typeorm';
import * as Mmj from 'misskey-mahjong';
import type {
MiMahjongGame,
MahjongGamesRepository,
} from '@/models/_.js';
import type { MiUser } from '@/models/User.js';
import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
import { CacheService } from '@/core/CacheService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { IdService } from '@/core/IdService.js';
import { NotificationService } from '@/core/NotificationService.js';
import { Serialized } from '@/types.js';
import { Packed } from '@/misc/json-schema.js';
import { ReversiGameEntityService } from './entities/ReversiGameEntityService.js';
import type { OnApplicationShutdown, OnModuleInit } from '@nestjs/common';
const INVITATION_TIMEOUT_MS = 1000 * 20; // 20sec
const CALL_AND_RON_ASKING_TIMEOUT_MS = 1000 * 10; // 10sec
const TURN_TIMEOUT_MS = 1000 * 30; // 30sec
const NEXT_KYOKU_CONFIRMATION_TIMEOUT_MS = 1000 * 15; // 15sec
type Room = {
id: string;
user1Id: MiUser['id'];
user2Id: MiUser['id'] | null;
user3Id: MiUser['id'] | null;
user4Id: MiUser['id'] | null;
user1: Packed<'UserLite'> | null;
user2: Packed<'UserLite'> | null;
user3: Packed<'UserLite'> | null;
user4: Packed<'UserLite'> | null;
user1Ai?: boolean;
user2Ai?: boolean;
user3Ai?: boolean;
user4Ai?: boolean;
user1Ready: boolean;
user2Ready: boolean;
user3Ready: boolean;
user4Ready: boolean;
user1Offline?: boolean;
user2Offline?: boolean;
user3Offline?: boolean;
user4Offline?: boolean;
isStarted?: boolean;
timeLimitForEachTurn: number;
gameState?: Mmj.MasterState;
};
type CallingAnswers = {
pon: null | boolean;
cii: null | false | 'x__' | '_x_' | '__x';
kan: null | boolean;
ron: {
e: null | boolean;
s: null | boolean;
w: null | boolean;
n: null | boolean;
};
};
type NextKyokuConfirmation = {
user1: boolean;
user2: boolean;
user3: boolean;
user4: boolean;
};
function getUserIdOfHouse(room: Room, mj: Mmj.MasterGameEngine, house: Mmj.House): MiUser['id'] {
return mj.user1House === house ? room.user1Id : mj.user2House === house ? room.user2Id : mj.user3House === house ? room.user3Id : room.user4Id;
}
function getHouseOfUserId(room: Room, mj: Mmj.MasterGameEngine, userId: MiUser['id']): Mmj.House {
return userId === room.user1Id ? mj.user1House : userId === room.user2Id ? mj.user2House : userId === room.user3Id ? mj.user3House : mj.user4House;
}
@Injectable()
export class MahjongService implements OnApplicationShutdown, OnModuleInit {
private notificationService: NotificationService;
constructor(
private moduleRef: ModuleRef,
@Inject(DI.redis)
private redisClient: Redis.Redis,
//@Inject(DI.mahjongGamesRepository)
//private mahjongGamesRepository: MahjongGamesRepository,
private cacheService: CacheService,
private userEntityService: UserEntityService,
private globalEventService: GlobalEventService,
private reversiGameEntityService: ReversiGameEntityService,
private idService: IdService,
) {
}
async onModuleInit() {
this.notificationService = this.moduleRef.get(NotificationService.name);
}
@bindThis
private async saveRoom(room: Room) {
await this.redisClient.set(`mahjong:room:${room.id}`, JSON.stringify(room), 'EX', 60 * 30);
}
@bindThis
public async createRoom(user: MiUser): Promise<Room> {
const room: Room = {
id: this.idService.gen(),
user1Id: user.id,
user2Id: null,
user3Id: null,
user4Id: null,
user1: await this.userEntityService.pack(user),
user1Ready: false,
user2Ready: false,
user3Ready: false,
user4Ready: false,
timeLimitForEachTurn: 30,
};
await this.saveRoom(room);
return room;
}
@bindThis
public async getRoom(id: Room['id']): Promise<Room | null> {
const room = await this.redisClient.get(`mahjong:room:${id}`);
if (!room) return null;
const parsed = JSON.parse(room);
return {
...parsed,
};
}
@bindThis
public async joinRoom(roomId: Room['id'], user: MiUser): Promise<Room | null> {
const room = await this.getRoom(roomId);
if (!room) return null;
if (room.user1Id === user.id) return room;
if (room.user2Id === user.id) return room;
if (room.user3Id === user.id) return room;
if (room.user4Id === user.id) return room;
if (room.user2Id === null) {
room.user2Id = user.id;
room.user2 = await this.userEntityService.pack(user);
await this.saveRoom(room);
this.globalEventService.publishMahjongRoomStream(room.id, 'joined', { index: 2, user: room.user2 });
return room;
}
if (room.user3Id === null) {
room.user3Id = user.id;
room.user3 = await this.userEntityService.pack(user);
await this.saveRoom(room);
this.globalEventService.publishMahjongRoomStream(room.id, 'joined', { index: 3, user: room.user3 });
return room;
}
if (room.user4Id === null) {
room.user4Id = user.id;
room.user4 = await this.userEntityService.pack(user);
await this.saveRoom(room);
this.globalEventService.publishMahjongRoomStream(room.id, 'joined', { index: 4, user: room.user4 });
return room;
}
return null;
}
@bindThis
public async addAi(roomId: Room['id'], user: MiUser): Promise<Room | null> {
const room = await this.getRoom(roomId);
if (!room) return null;
if (room.user1Id !== user.id) throw new Error('access denied');
if (room.user2Id == null && !room.user2Ai) {
room.user2Ai = true;
room.user2Ready = true;
await this.saveRoom(room);
this.globalEventService.publishMahjongRoomStream(room.id, 'joined', { index: 2, user: null });
return room;
}
if (room.user3Id == null && !room.user3Ai) {
room.user3Ai = true;
room.user3Ready = true;
await this.saveRoom(room);
this.globalEventService.publishMahjongRoomStream(room.id, 'joined', { index: 3, user: null });
return room;
}
if (room.user4Id == null && !room.user4Ai) {
room.user4Ai = true;
room.user4Ready = true;
await this.saveRoom(room);
this.globalEventService.publishMahjongRoomStream(room.id, 'joined', { index: 4, user: null });
return room;
}
return null;
}
@bindThis
public async leaveRoom(roomId: Room['id'], user: MiUser): Promise<Room | null> {
const room = await this.getRoom(roomId);
if (!room) return null;
if (room.user1Id === user.id) {
room.user1Id = null;
room.user1 = null;
await this.saveRoom(room);
return room;
}
if (room.user2Id === user.id) {
room.user2Id = null;
room.user2 = null;
await this.saveRoom(room);
return room;
}
if (room.user3Id === user.id) {
room.user3Id = null;
room.user3 = null;
await this.saveRoom(room);
return room;
}
if (room.user4Id === user.id) {
room.user4Id = null;
room.user4 = null;
await this.saveRoom(room);
return room;
}
return null;
}
@bindThis
public async changeReadyState(roomId: Room['id'], user: MiUser, ready: boolean): Promise<void> {
const room = await this.getRoom(roomId);
if (!room) return;
if (room.user1Id === user.id) {
room.user1Ready = ready;
await this.saveRoom(room);
}
if (room.user2Id === user.id) {
room.user2Ready = ready;
await this.saveRoom(room);
}
if (room.user3Id === user.id) {
room.user3Ready = ready;
await this.saveRoom(room);
}
if (room.user4Id === user.id) {
room.user4Ready = ready;
await this.saveRoom(room);
}
this.globalEventService.publishMahjongRoomStream(room.id, 'changeReadyStates', {
user1: room.user1Ready,
user2: room.user2Ready,
user3: room.user3Ready,
user4: room.user4Ready,
});
if (room.user1Ready && room.user2Ready && room.user3Ready && room.user4Ready) {
await this.startGame(room);
}
}
@bindThis
public async startGame(room: Room) {
if (!room.user1Ready || !room.user2Ready || !room.user3Ready || !room.user4Ready) {
throw new Error('Not ready');
}
room.gameState = Mmj.MasterGameEngine.createInitialState();
room.isStarted = true;
await this.saveRoom(room);
this.globalEventService.publishMahjongRoomStream(room.id, 'started', { room: room });
this.kyokuStarted(room);
}
@bindThis
private kyokuStarted(room: Room) {
const mj = new Mmj.MasterGameEngine(room.gameState);
this.waitForTurn(room, mj.turn, mj);
}
@bindThis
private async answer(room: Room, mj: Mmj.MasterGameEngine, answers: CallingAnswers) {
const res = mj.commit_resolveCallingInterruption({
pon: answers.pon ?? false,
cii: answers.cii ?? false,
kan: answers.kan ?? false,
ron: [...(answers.ron.e ? ['e'] : []), ...(answers.ron.s ? ['s'] : []), ...(answers.ron.w ? ['w'] : []), ...(answers.ron.n ? ['n'] : [])] as Mmj.House[],
});
room.gameState = mj.getState();
await this.saveRoom(room);
switch (res.type) {
case 'tsumo':
this.globalEventService.publishMahjongRoomStream(room.id, 'tsumo', { house: res.house, tile: res.tile });
this.waitForTurn(room, res.turn, mj);
break;
case 'ponned':
this.globalEventService.publishMahjongRoomStream(room.id, 'ponned', { caller: res.caller, callee: res.callee, tiles: res.tiles });
this.waitForTurn(room, res.turn, mj);
break;
case 'kanned':
this.globalEventService.publishMahjongRoomStream(room.id, 'kanned', { caller: res.caller, callee: res.callee, tiles: res.tiles, rinsyan: res.rinsyan });
this.waitForTurn(room, res.turn, mj);
break;
case 'ciied':
this.globalEventService.publishMahjongRoomStream(room.id, 'ciied', { caller: res.caller, callee: res.callee, tiles: res.tiles });
this.waitForTurn(room, res.turn, mj);
break;
case 'ronned':
this.globalEventService.publishMahjongRoomStream(room.id, 'ronned', {
callers: res.callers,
callee: res.callee,
handTiles: {
e: mj.handTiles.e,
s: mj.handTiles.s,
w: mj.handTiles.w,
n: mj.handTiles.n,
},
});
this.endKyoku(room, mj);
break;
case 'ryuukyoku':
this.globalEventService.publishMahjongRoomStream(room.id, 'ryuukyoku', {
});
this.endKyoku(room, mj);
break;
}
}
@bindThis
private async endKyoku(room: Room, mj: Mmj.MasterGameEngine) {
const confirmation: NextKyokuConfirmation = {
user1: false,
user2: false,
user3: false,
user4: false,
};
this.redisClient.set(`mahjong:gameNextKyokuConfirmation:${room.id}`, JSON.stringify(confirmation));
const waitingStartedAt = Date.now();
const interval = setInterval(async () => {
const confirmationRaw = await this.redisClient.get(`mahjong:gameNextKyokuConfirmation:${room.id}`);
if (confirmationRaw == null) {
clearInterval(interval);
return;
}
const confirmation = JSON.parse(confirmationRaw) as NextKyokuConfirmation;
const allConfirmed = confirmation.user1 && confirmation.user2 && confirmation.user3 && confirmation.user4;
if (allConfirmed || (Date.now() - waitingStartedAt > NEXT_KYOKU_CONFIRMATION_TIMEOUT_MS)) {
await this.redisClient.del(`mahjong:gameNextKyokuConfirmation:${room.id}`);
clearInterval(interval);
this.nextKyoku(room, mj);
}
}, 2000);
}
@bindThis
private async nextKyoku(room: Room, mj: Mmj.MasterGameEngine) {
const res = mj.commit_nextKyoku();
room.gameState = mj.getState();
await this.saveRoom(room);
this.globalEventService.publishMahjongRoomStream(room.id, 'nextKyoku', {
room: room,
});
this.kyokuStarted(room);
}
@bindThis
private async dahai(room: Room, mj: Mmj.MasterGameEngine, house: Mmj.House, tile: Mmj.TileId, riichi = false) {
const res = mj.commit_dahai(house, tile, riichi);
room.gameState = mj.getState();
await this.saveRoom(room);
const aiHouses = [[1, room.user1Ai], [2, room.user2Ai], [3, room.user3Ai], [4, room.user4Ai]].filter(([id, ai]) => ai).map(([id, ai]) => mj.getHouse(id));
if (res.ryuukyoku) {
this.endKyoku(room, mj);
this.globalEventService.publishMahjongRoomStream(room.id, 'ryuukyoku', {
});
} else if (res.asking) {
const answers: CallingAnswers = {
pon: null,
cii: null,
kan: null,
ron: {
e: null,
s: null,
w: null,
n: null,
},
};
// リーチ中はポン、チー、カンできない
if (res.canPonHouse != null && mj.riichis[res.canPonHouse]) {
answers.pon = false;
}
if (res.canCiiHouse != null && mj.riichis[res.canCiiHouse]) {
answers.cii = false;
}
if (res.canKanHouse != null && mj.riichis[res.canKanHouse]) {
answers.kan = false;
}
if (aiHouses.includes(res.canPonHouse)) {
// TODO: ちゃんと思考するようにする
answers.pon = Math.random() < 0.25;
}
if (aiHouses.includes(res.canCiiHouse)) {
// TODO: ちゃんと思考するようにする
//answers.cii = Math.random() < 0.25;
answers.cii = false;
}
if (aiHouses.includes(res.canKanHouse)) {
// TODO: ちゃんと思考するようにする
answers.kan = Math.random() < 0.25;
}
for (const h of res.canRonHouses) {
if (aiHouses.includes(h)) {
// TODO: ちゃんと思考するようにする
}
}
this.redisClient.set(`mahjong:gameCallingAsking:${room.id}`, JSON.stringify(answers));
const waitingStartedAt = Date.now();
const interval = setInterval(async () => {
const current = await this.redisClient.get(`mahjong:gameCallingAsking:${room.id}`);
if (current == null) throw new Error('arienai (gameCallingAsking)');
const currentAnswers = JSON.parse(current) as CallingAnswers;
const allAnswered = !(
(res.canPonHouse != null && currentAnswers.pon == null) ||
(res.canCiiHouse != null && currentAnswers.cii == null) ||
(res.canKanHouse != null && currentAnswers.kan == null) ||
(res.canRonHouses.includes('e') && currentAnswers.ron.e == null) ||
(res.canRonHouses.includes('s') && currentAnswers.ron.s == null) ||
(res.canRonHouses.includes('w') && currentAnswers.ron.w == null) ||
(res.canRonHouses.includes('n') && currentAnswers.ron.n == null)
);
if (allAnswered || (Date.now() - waitingStartedAt > CALL_AND_RON_ASKING_TIMEOUT_MS)) {
console.log(allAnswered ? 'ask all answerd' : 'ask timeout');
await this.redisClient.del(`mahjong:gameCallingAsking:${room.id}`);
clearInterval(interval);
this.answer(room, mj, currentAnswers);
return;
}
}, 1000);
this.globalEventService.publishMahjongRoomStream(room.id, 'dahai', { house: house, tile, riichi });
} else {
this.globalEventService.publishMahjongRoomStream(room.id, 'dahaiAndTsumo', { dahaiHouse: house, dahaiTile: tile, tsumoTile: res.tsumoTile, riichi });
this.waitForTurn(room, res.next, mj);
}
}
@bindThis
public async confirmNextKyoku(roomId: Room['id'], user: MiUser) {
const room = await this.getRoom(roomId);
if (room == null) return;
if (room.gameState == null) return;
// TODO: この辺の処理はアトミックに行いたいけどJSONサポートはRedis Stackが必要
const confirmationRaw = await this.redisClient.get(`mahjong:gameNextKyokuConfirmation:${room.id}`);
if (confirmationRaw == null) return;
const confirmation = JSON.parse(confirmationRaw) as NextKyokuConfirmation;
if (user.id === room.user1Id) confirmation.user1 = true;
if (user.id === room.user2Id) confirmation.user2 = true;
if (user.id === room.user3Id) confirmation.user3 = true;
if (user.id === room.user4Id) confirmation.user4 = true;
await this.redisClient.set(`mahjong:gameNextKyokuConfirmation:${room.id}`, JSON.stringify(confirmation));
}
@bindThis
public async commit_dahai(roomId: MiMahjongGame['id'], user: MiUser, tile: Mmj.TileId, riichi = false) {
const room = await this.getRoom(roomId);
if (room == null) return;
if (room.gameState == null) return;
const mj = new Mmj.MasterGameEngine(room.gameState);
const myHouse = getHouseOfUserId(room, mj, user.id);
await this.clearTurnWaitingTimer(room.id);
await this.dahai(room, mj, myHouse, tile, riichi);
}
@bindThis
public async commit_ankan(roomId: MiMahjongGame['id'], user: MiUser, tile: Mmj.TileId) {
const room = await this.getRoom(roomId);
if (room == null) return;
if (room.gameState == null) return;
const mj = new Mmj.MasterGameEngine(room.gameState);
const myHouse = getHouseOfUserId(room, mj, user.id);
await this.clearTurnWaitingTimer(room.id);
const res = mj.commit_ankan(myHouse, tile);
room.gameState = mj.getState();
await this.saveRoom(room);
this.globalEventService.publishMahjongRoomStream(room.id, 'ankanned', { house: myHouse, tiles: res.tiles, rinsyan: res.rinsyan });
this.waitForTurn(room, myHouse, mj);
}
@bindThis
public async commit_kakan(roomId: MiMahjongGame['id'], user: MiUser, tile: Mmj.TileId) {
const room = await this.getRoom(roomId);
if (room == null) return;
if (room.gameState == null) return;
const mj = new Mmj.MasterGameEngine(room.gameState);
const myHouse = getHouseOfUserId(room, mj, user.id);
await this.clearTurnWaitingTimer(room.id);
const res = mj.commit_kakan(myHouse, tile);
room.gameState = mj.getState();
await this.saveRoom(room);
this.globalEventService.publishMahjongRoomStream(room.id, 'kakanned', { house: myHouse, tiles: res.tiles, rinsyan: res.rinsyan, from: res.from });
}
@bindThis
public async commit_tsumoHora(roomId: MiMahjongGame['id'], user: MiUser) {
const room = await this.getRoom(roomId);
if (room == null) return;
if (room.gameState == null) return;
const mj = new Mmj.MasterGameEngine(room.gameState);
const myHouse = getHouseOfUserId(room, mj, user.id);
await this.clearTurnWaitingTimer(room.id);
const res = mj.commit_tsumoHora(myHouse);
room.gameState = mj.getState();
await this.saveRoom(room);
this.globalEventService.publishMahjongRoomStream(room.id, 'tsumoHora', { house: myHouse, handTiles: res.handTiles, tsumoTile: res.tsumoTile });
this.endKyoku(room, mj);
}
@bindThis
public async commit_ronHora(roomId: MiMahjongGame['id'], user: MiUser) {
const room = await this.getRoom(roomId);
if (room == null) return;
if (room.gameState == null) return;
const mj = new Mmj.MasterGameEngine(room.gameState);
const myHouse = getHouseOfUserId(room, mj, user.id);
// TODO: 自分に回答する権利がある状態かバリデーション
// TODO: この辺の処理はアトミックに行いたいけどJSONサポートはRedis Stackが必要
const current = await this.redisClient.get(`mahjong:gameCallingAsking:${room.id}`);
if (current == null) throw new Error('no asking found');
const currentAnswers = JSON.parse(current) as CallingAnswers;
currentAnswers.ron[myHouse] = true;
await this.redisClient.set(`mahjong:gameCallingAsking:${room.id}`, JSON.stringify(currentAnswers));
}
@bindThis
public async commit_pon(roomId: MiMahjongGame['id'], user: MiUser) {
const room = await this.getRoom(roomId);
if (room == null) return;
if (room.gameState == null) return;
// TODO: 自分に回答する権利がある状態かバリデーション
// TODO: この辺の処理はアトミックに行いたいけどJSONサポートはRedis Stackが必要
const current = await this.redisClient.get(`mahjong:gameCallingAsking:${room.id}`);
if (current == null) throw new Error('no asking found');
const currentAnswers = JSON.parse(current) as CallingAnswers;
currentAnswers.pon = true;
await this.redisClient.set(`mahjong:gameCallingAsking:${room.id}`, JSON.stringify(currentAnswers));
}
@bindThis
public async commit_kan(roomId: MiMahjongGame['id'], user: MiUser) {
const room = await this.getRoom(roomId);
if (room == null) return;
if (room.gameState == null) return;
// TODO: 自分に回答する権利がある状態かバリデーション
// TODO: この辺の処理はアトミックに行いたいけどJSONサポートはRedis Stackが必要
const current = await this.redisClient.get(`mahjong:gameCallingAsking:${room.id}`);
if (current == null) throw new Error('no asking found');
const currentAnswers = JSON.parse(current) as CallingAnswers;
currentAnswers.kan = true;
await this.redisClient.set(`mahjong:gameCallingAsking:${room.id}`, JSON.stringify(currentAnswers));
}
@bindThis
public async commit_cii(roomId: MiMahjongGame['id'], user: MiUser, pattern: 'x__' | '_x_' | '__x') {
const room = await this.getRoom(roomId);
if (room == null) return;
if (room.gameState == null) return;
// TODO: 自分に回答する権利がある状態かバリデーション
// TODO: この辺の処理はアトミックに行いたいけどJSONサポートはRedis Stackが必要
const current = await this.redisClient.get(`mahjong:gameCallingAsking:${room.id}`);
if (current == null) throw new Error('no asking found');
const currentAnswers = JSON.parse(current) as CallingAnswers;
currentAnswers.cii = pattern;
await this.redisClient.set(`mahjong:gameCallingAsking:${room.id}`, JSON.stringify(currentAnswers));
}
@bindThis
public async commit_nop(roomId: MiMahjongGame['id'], user: MiUser) {
const room = await this.getRoom(roomId);
if (room == null) return;
if (room.gameState == null) return;
const mj = new Mmj.MasterGameEngine(room.gameState);
const myHouse = getHouseOfUserId(room, mj, user.id);
// TODO: この辺の処理はアトミックに行いたいけどJSONサポートはRedis Stackが必要
const current = await this.redisClient.get(`mahjong:gameCallingAsking:${room.id}`);
if (current == null) throw new Error('no asking found');
const currentAnswers = JSON.parse(current) as CallingAnswers;
if (mj.askings.pon?.caller === myHouse) currentAnswers.pon = false;
if (mj.askings.cii?.caller === myHouse) currentAnswers.cii = false;
if (mj.askings.kan?.caller === myHouse) currentAnswers.kan = false;
if (mj.askings.ron != null && mj.askings.ron.callers.includes(myHouse)) currentAnswers.ron[myHouse] = false;
await this.redisClient.set(`mahjong:gameCallingAsking:${room.id}`, JSON.stringify(currentAnswers));
}
/**
* プレイヤーの行動(打牌、加槓、暗槓、ツモ和了)を待つ
* 制限時間が過ぎたらツモ切り
* NOTE: 時間切れチェックが行われたときにタイミングによっては次のwaitingが始まっている場合があることを考慮し、Setに一意のIDを格納する構造としている
* @param room
* @param house
* @param mj
*/
@bindThis
private async waitForTurn(room: Room, house: Mmj.House, mj: Mmj.MasterGameEngine) {
const aiHouses = [[1, room.user1Ai], [2, room.user2Ai], [3, room.user3Ai], [4, room.user4Ai]].filter(([id, ai]) => ai).map(([id, ai]) => mj.getHouse(id));
if (mj.riichis[house]) {
// リーチ時はアガリ牌でない限りツモ切り
if (!Mmj.isAgarikei(mj.handTileTypes[house])) {
setTimeout(() => {
this.dahai(room, mj, house, mj.handTiles[house].at(-1));
}, 500);
return;
}
}
if (aiHouses.includes(house)) {
setTimeout(() => {
this.dahai(room, mj, house, mj.handTiles[house].at(-1));
}, 500);
return;
}
const id = Math.random().toString(36).slice(2);
console.log('waitForTurn', house, id);
this.redisClient.sadd(`mahjong:gameTurnWaiting:${room.id}`, id);
const waitingStartedAt = Date.now();
const interval = setInterval(async () => {
const waiting = await this.redisClient.sismember(`mahjong:gameTurnWaiting:${room.id}`, id);
if (waiting === 0) {
clearInterval(interval);
return;
}
if (Date.now() - waitingStartedAt > TURN_TIMEOUT_MS) {
await this.redisClient.srem(`mahjong:gameTurnWaiting:${room.id}`, id);
console.log('turn timeout', house, id);
clearInterval(interval);
const handTiles = mj.handTiles[house];
await this.dahai(room, mj, house, handTiles.at(-1));
return;
}
}, 2000);
}
/**
* プレイヤーが行動(打牌、加槓、暗槓、ツモ和了)したら呼ぶ
* @param roomId
*/
@bindThis
private async clearTurnWaitingTimer(roomId: Room['id']) {
await this.redisClient.del(`mahjong:gameTurnWaiting:${roomId}`);
}
@bindThis
public packState(room: Room, me: MiUser) {
const mj = new Mmj.MasterGameEngine(room.gameState);
const myIndex = room.user1Id === me.id ? 1 : room.user2Id === me.id ? 2 : room.user3Id === me.id ? 3 : 4;
return mj.createPlayerState(myIndex);
}
@bindThis
public async packRoom(room: Room, me: MiUser) {
if (room.gameState) {
return {
...room,
gameState: this.packState(room, me),
};
} else {
return {
...room,
};
}
}
@bindThis
public dispose(): void {
}
@bindThis
public onApplicationShutdown(signal?: string | undefined): void {
this.dispose();
}
}

View File

@@ -63,20 +63,21 @@ type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
class NotificationManager {
private notifier: { id: MiUser['id']; };
private note: MiNote;
private queue: {
private queue: Map<MiLocalUser['id'], {
target: MiLocalUser['id'];
reason: NotificationType;
}[];
}>;
constructor(
private mutingsRepository: MutingsRepository,
private notificationService: NotificationService,
private followingsRepository: FollowingsRepository,
notifier: { id: MiUser['id']; },
note: MiNote,
) {
this.notifier = notifier;
this.note = note;
this.queue = [];
this.queue = new Map();
}
@bindThis
@@ -84,7 +85,7 @@ class NotificationManager {
// 自分自身へは通知しない
if (this.notifier.id === notifiee) return;
const exist = this.queue.find(x => x.target === notifiee);
const exist = this.queue.get(notifiee);
if (exist) {
// 「メンションされているかつ返信されている」場合は、メンションとしての通知ではなく返信としての通知にする
@@ -92,7 +93,7 @@ class NotificationManager {
exist.reason = reason;
}
} else {
this.queue.push({
this.queue.set(notifiee, {
reason: reason,
target: notifiee,
});
@@ -101,7 +102,50 @@ class NotificationManager {
@bindThis
public async notify() {
for (const x of this.queue) {
if (this.queue.size === 0) {
return;
}
let visibleUserIds: Set<MiUser['id']> | null;
switch (this.note.visibility) {
case 'public':
case 'home':
visibleUserIds = null;
break;
case 'specified':
visibleUserIds = new Set(this.note.visibleUserIds);
break;
case 'followers': {
// TODO: フォロワー限定ノートにフォロワーではない人がメンションされた場合通知されるのが正しい挙動なのか確認(一部に挙動の不一致がありそう)。現状は通知されるためフィルタしない
// const targetUserIds = this.queue.map(x => x.target);
// const followers = await this.followingsRepository.find({
// where: {
// followeeId: this.note.userId,
// followerId: In(targetUserIds),
// isFollowerHibernated: false,
// },
// select: ['followerId'],
// });
// visibleUserIds = new Set(followers.map(f => f.followerId));
visibleUserIds = null;
break;
}
default:
visibleUserIds = new Set();
break;
}
for (const x of this.queue.values()) {
const isVisibleToTarget = visibleUserIds === null || visibleUserIds.has(x.target);
if (!isVisibleToTarget) {
continue;
}
if (x.reason === 'renote') {
this.notificationService.createNotification(x.target, 'renote', {
noteId: this.note.id,
@@ -772,7 +816,7 @@ export class NoteCreateService implements OnApplicationShutdown {
this.webhookService.enqueueUserWebhook(user.id, 'note', { note: noteObj });
const nm = new NotificationManager(this.mutingsRepository, this.notificationService, user, note);
const nm = new NotificationManager(this.mutingsRepository, this.notificationService, this.followingsRepository, user, note);
await this.createMentionedEvents(mentionedUsers, note, nm);

View File

@@ -68,7 +68,7 @@ export class NoteDeleteService {
}
if (!quiet) {
this.globalEventService.publishNoteStream(note.id, 'deleted', {
this.globalEventService.publishNoteStream(note, 'deleted', {
deletedAt: deletedAt,
});

View File

@@ -246,7 +246,8 @@ export class NotificationService implements OnApplicationShutdown {
private toXListId(id: string): string {
const { date, additional } = this.idService.parseFull(id);
return date.toString() + '-' + additional.toString();
// Redis Stream sequenceはunit64制約があるため、収まらない場合は下位64bitを取る
return date.toString() + '-' + BigInt.asUintN(64, additional).toString();
}
@bindThis

View File

@@ -83,7 +83,7 @@ export class PollService {
const index = choice + 1; // In SQL, array index is 1 based
await this.pollsRepository.query(`UPDATE poll SET votes[${index}] = votes[${index}] + 1 WHERE "noteId" = '${poll.noteId}'`);
this.globalEventService.publishNoteStream(note.id, 'pollVoted', {
this.globalEventService.publishNoteStream(note, 'pollVoted', {
choice: choice,
userId: user.id,
});

View File

@@ -259,7 +259,7 @@ export class QueryService {
@bindThis
public generateVisibilityQuery(q: SelectQueryBuilder<any>, me?: { id: MiUser['id'] } | null): void {
// This code must always be synchronized with the checks in Notes.isVisibleForMe.
// This code must always be synchronized with the checks in NoteEntityService.isVisibleForMe and Stream abstract class Channel.isNoteVisibleForMe.
if (me == null) {
q.andWhere(new Brackets(qb => {
qb

View File

@@ -244,7 +244,7 @@ export class ReactionService {
},
});
this.globalEventService.publishNoteStream(note.id, 'reacted', {
this.globalEventService.publishNoteStream(note, 'reacted', {
reaction: decodedReaction.reaction,
emoji: customEmoji != null ? {
name: customEmoji.host ? `${customEmoji.name}@${customEmoji.host}` : `${customEmoji.name}@.`,
@@ -318,7 +318,7 @@ export class ReactionService {
.execute();
}
this.globalEventService.publishNoteStream(note.id, 'unreacted', {
this.globalEventService.publishNoteStream(note, 'unreacted', {
reaction: this.decodeReaction(exist.reaction).reaction,
userId: user.id,
});

View File

@@ -91,13 +91,27 @@ export class RelayService {
return JSON.stringify(result);
}
@bindThis
private getAcceptedRelays(): Promise<MiRelay[]> {
return this.relaysCache.fetch(() => this.relaysRepository.findBy({
status: 'accepted',
}));
}
@bindThis
public async isRelayActor(actor: { inbox: string | null; sharedInbox: string | null }): Promise<boolean> {
const relays = await this.getAcceptedRelays();
return relays.some(relay =>
(actor.inbox != null && relay.inbox === actor.inbox)
|| (actor.sharedInbox != null && relay.inbox === actor.sharedInbox),
);
}
@bindThis
public async deliverToRelays(user: { id: MiUser['id']; host: null; }, activity: any): Promise<void> {
if (activity == null) return;
const relays = await this.relaysCache.fetch(() => this.relaysRepository.findBy({
status: 'accepted',
}));
const relays = await this.getAcceptedRelays();
if (relays.length === 0) return;
const copy = deepClone(activity);

View File

@@ -47,6 +47,7 @@ export type RolePolicies = {
canSearchUsers: boolean;
canUseTranslator: boolean;
canHideAds: boolean;
canCreateChannel: boolean;
driveCapacityMb: number;
maxFileSizeMb: number;
alwaysMarkNsfw: boolean;
@@ -88,6 +89,7 @@ export const DEFAULT_POLICIES: RolePolicies = {
canSearchUsers: true,
canUseTranslator: true,
canHideAds: false,
canCreateChannel: true,
driveCapacityMb: 100,
maxFileSizeMb: 30,
alwaysMarkNsfw: false,
@@ -410,6 +412,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
canSearchUsers: calc('canSearchUsers', vs => vs.some(v => v === true)),
canUseTranslator: calc('canUseTranslator', vs => vs.some(v => v === true)),
canHideAds: calc('canHideAds', vs => vs.some(v => v === true)),
canCreateChannel: calc('canCreateChannel', vs => vs.some(v => v === true)),
driveCapacityMb: calc('driveCapacityMb', vs => Math.max(...vs)),
maxFileSizeMb: calc('maxFileSizeMb', vs => Math.max(...vs)),
alwaysMarkNsfw: calc('alwaysMarkNsfw', vs => vs.some(v => v === true)),
@@ -533,7 +536,8 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
roleId: In(administratorRoles.map(r => r.id)),
}) : [];
// TODO: isRootなアカウントも含める
return assigns.map(a => a.userId);
// Setを経由して重複を除去ユーザIDは重複する可能性があるので
return [...new Set(assigns.map(a => a.userId))].sort((x, y) => x.localeCompare(y));
}
@bindThis

View File

@@ -17,7 +17,7 @@ import { CacheService } from '@/core/CacheService.js';
import { QueryService } from '@/core/QueryService.js';
import { IdService } from '@/core/IdService.js';
import { LoggerService } from '@/core/LoggerService.js';
import type { Index, MeiliSearch } from 'meilisearch';
import type { Index, Meilisearch } from 'meilisearch';
type K = string;
type V = string | number | boolean;
@@ -85,7 +85,7 @@ export class SearchService {
private config: Config,
@Inject(DI.meilisearch)
private meilisearch: MeiliSearch | null,
private meilisearch: Meilisearch | null,
@Inject(DI.notesRepository)
private notesRepository: NotesRepository,
@@ -187,7 +187,7 @@ export class SearchService {
return this.searchNoteByLike(q, me, opts, pagination);
}
case 'meilisearch': {
return this.searchNoteByMeiliSearch(q, me, opts, pagination);
return this.searchNoteByMeilisearch(q, me, opts, pagination);
}
default: {
const _: never = this.provider;
@@ -239,14 +239,14 @@ export class SearchService {
}
@bindThis
private async searchNoteByMeiliSearch(
private async searchNoteByMeilisearch(
q: string,
me: MiUser | null,
opts: SearchOpts,
pagination: SearchPagination,
): Promise<MiNote[]> {
if (!this.meilisearch || !this.meilisearchNoteIndex) {
throw new Error('MeiliSearch is not available');
throw new Error('Meilisearch is not available');
}
const filter: Q = {

View File

@@ -164,4 +164,3 @@ export class SignupService {
return { account, secret };
}
}

View File

@@ -24,7 +24,7 @@ import type {
PublicKeyCredentialCreationOptionsJSON,
PublicKeyCredentialRequestOptionsJSON,
RegistrationResponseJSON,
} from '@simplewebauthn/types';
} from '@simplewebauthn/server';
@Injectable()
export class WebAuthnService {

View File

@@ -259,7 +259,7 @@ export class ApInboxService {
@bindThis
private async add(actor: MiRemoteUser, activity: IAdd, resolver?: Resolver): Promise<string | void> {
if (actor.uri !== activity.actor) {
if (actor.uri !== getApId(activity.actor)) {
return 'invalid actor';
}
@@ -302,16 +302,19 @@ export class ApInboxService {
@bindThis
private async announceNote(actor: MiRemoteUser, activity: IAnnounce, target: IPost, resolver?: Resolver): Promise<string | void> {
const uri = getApId(activity);
if (actor.isSuspended) {
return;
}
// リレーからのAnnounceかチェック
const fromRelay = await this.relayService.isRelayActor(actor);
const uri = getApId(fromRelay ? target : activity);
// アナウンス先が許可されているかチェック
if (!this.utilityService.isFederationAllowedUri(uri)) return;
const unlock = await acquireApObjectLock(this.redisClient, uri);
const activityUri = getApId(activity);
const unlock = await acquireApObjectLock(this.redisClient, activityUri);
try {
// 既に同じURIを持つものが登録されていないかチェック
@@ -336,6 +339,14 @@ export class ApInboxService {
throw err;
}
// リレーからのAnnounceはリートを作成せず、ートを直接公開する
if (fromRelay) {
this.logger.info(`Publishing relay-delivered note: ${uri}`);
const noteObj = await this.noteEntityService.pack(renote, null, { skipHide: true, withReactionAndUserPairCache: true });
this.globalEventService.publishNotesStream(noteObj);
return;
}
if (!await this.noteEntityService.isVisibleForMe(renote, actor.id)) {
return 'skip: invalid actor for this activity';
}
@@ -459,7 +470,7 @@ export class ApInboxService {
@bindThis
private async delete(actor: MiRemoteUser, activity: IDelete): Promise<string> {
if (actor.uri !== activity.actor) {
if (actor.uri !== getApId(activity.actor)) {
return 'invalid actor';
}
@@ -613,7 +624,7 @@ export class ApInboxService {
@bindThis
private async remove(actor: MiRemoteUser, activity: IRemove, resolver?: Resolver): Promise<string | void> {
if (actor.uri !== activity.actor) {
if (actor.uri !== getApId(activity.actor)) {
return 'invalid actor';
}
@@ -633,7 +644,7 @@ export class ApInboxService {
@bindThis
private async undo(actor: MiRemoteUser, activity: IUndo, resolver?: Resolver): Promise<string> {
if (actor.uri !== activity.actor) {
if (actor.uri !== getApId(activity.actor)) {
return 'invalid actor';
}
@@ -767,7 +778,7 @@ export class ApInboxService {
@bindThis
private async update(actor: MiRemoteUser, activity: IUpdate, resolver?: Resolver): Promise<string> {
if (actor.uri !== activity.actor) {
if (actor.uri !== getApId(activity.actor)) {
return 'skip: invalid actor';
}

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