Compare commits

...
Sign in to create a new pull request.

737 commits

Author SHA1 Message Date
Hazelnoot
5af1197f75 check tenants before showing "remote user" warning 2025-04-04 11:09:30 -04:00
Hazelnoot
aa8a1e8440 support tenants in users/show, i/move, and i/update 2025-04-04 10:44:55 -04:00
Hazelnoot
f101831082 support tenants in renderPersonRedacted 2025-04-04 10:22:06 -04:00
Hazelnoot
cb119d9215 simplify URI logic in ApRendererService.ts 2025-04-04 10:20:46 -04:00
Hazelnoot
3a94e778ac reflect tenant in WellKnownServerService.ts 2025-04-04 10:17:18 -04:00
Hazelnoot
8b41489a79 return tenant URL in api/meta 2025-04-04 10:01:28 -04:00
Hazelnoot
ea7d0746d1 expose request hostname to API endpoints 2025-04-04 09:59:48 -04:00
Hazelnoot
b9ba966f44 add utility to get self tenant 2025-04-04 09:25:41 -04:00
Hazelnoot
0b65b225fc rename alt utilities to avoid ambiguity 2025-04-04 09:22:49 -04:00
Hazelnoot
d742e4087d check alts in ClientServerService.ts 2025-04-03 23:10:18 -04:00
Hazelnoot
d5e3752174 move tenant utility functions to UtilityService 2025-04-03 23:03:54 -04:00
Hazelnoot
1ff6c997ad don't serve remote Like objects 2025-04-03 22:57:59 -04:00
Hazelnoot
5c9558b928 check alts in additional note fetch 2025-04-03 22:54:58 -04:00
Hazelnoot
0f1b523884 check alts in follow requests 2025-04-03 22:53:49 -04:00
Hazelnoot
dca73796e3 check alts in emoji fetch 2025-04-03 22:53:02 -04:00
Hazelnoot
44332a935c check alts in user lookup 2025-04-03 22:52:32 -04:00
Hazelnoot
36a29cd07f check alts in notes and replies collection 2025-04-03 22:49:02 -04:00
Hazelnoot
15bfe7f05f check alts in following, followers, featured, and outbox collections 2025-04-03 22:48:21 -04:00
Hazelnoot
60cb37cec9 check alts in inbox 2025-04-03 22:45:32 -04:00
Hazelnoot
66cbe6f32a *actually* check alts in authorized fetch 2025-04-03 22:41:43 -04:00
Hazelnoot
21d1436642 fix lint errors in ActivityPubServerService.ts 2025-04-03 22:36:32 -04:00
Hazelnoot
6322a9d0f7 check altUrls for unsigned fetch 2025-04-03 22:36:20 -04:00
Hazelnoot
202510e597 add configuration option "altUrls" 2025-04-03 22:27:59 -04:00
Hazelnoot
2d34cb7317 fix type error in ApRendererService.ts 2025-04-03 22:18:05 -04:00
Hazelnoot
a70386cac5 render remote URIs 2025-04-03 22:16:37 -04:00
Hazelnoot
3eeb53ff63 Merge branch 'misskey-develop' into merge/2025-03-24
# Conflicts:
#	package.json
#	packages/backend/src/core/AccountMoveService.ts
#	packages/frontend/src/components/MkDateSeparatedList.vue
#	packages/misskey-js/etc/misskey-js.api.md
#	pnpm-lock.yaml
2025-04-03 22:06:37 -04:00
Hazelnoot
967f31daa7 refactor bubble-timeline.ts to match global-timeline.ts and local-timeline.ts 2025-04-03 22:02:32 -04:00
syuilo
ea9d85a0cc
New Crowdin updates (#15740)
* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Portuguese)

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

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Arabic)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Polish)

* New translations ja-jp.yml (Slovak)

* New translations ja-jp.yml (Ukrainian)

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

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Bengali)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Uzbek)

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

* New translations ja-jp.yml (Catalan)

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

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

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Chinese Traditional)
2025-04-03 21:29:45 +09:00
github-actions[bot]
96b21484db Bump version to 2025.4.0-rc.0 2025-04-03 10:28:38 +00:00
anatawa12
cab82452ec
Copy role on move (#15745)
* feat(backend): copyOnMoveAccount

* feat(endpoints): copyOnMoveAccount

* feat(frontend): copyOnMoveAccount

* docs(changelog): アカウントのマイグレーション時に古いアカウントからロールをコピーできるようになりました。

* fix: spdx header for migration

* Update locales/ja-JP.yml

* copyOnMoveAccount -> preserveAssignmentOnMoveAccount

* fix: check for preserveAssignmentOnMoveAccount

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-04-03 19:22:49 +09:00
syuilo
440a4a4d8b refactor(frontend): refactor MkDateSeparatedList 2025-04-03 15:42:25 +09:00
syuilo
4be9b25185 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-04-03 15:34:15 +09:00
syuilo
8b7cba1ede 🎨 2025-04-03 15:34:13 +09:00
github-actions[bot]
1188ec458d Bump version to 2025.4.0-beta.2 2025-04-03 06:32:20 +00:00
かっこかり
e07bb1dcbc
fix: チャット周りの修正 (#15741)
* fix(misskey-js): チャットのChannel型定義を追加

* fix(backend); canChatで塞いでいない書き込み系のAPIを塞ぐ

* fix(frontend): チャット周りのフロントエンド型修正

* lint fix

* fix broken lockfile

* fix

* refactor

* wip

* wip

* wip

* clean up

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-04-03 15:28:10 +09:00
syuilo
7cecaa5c54 perf(frontend): avoid main thread scroll repaint 2025-04-03 14:32:42 +09:00
syuilo
1779a23e25 🎨 2025-04-03 13:31:13 +09:00
zyoshoka
d7365eb126
fix(storybook): update obsolete method for preferences (#15750) 2025-04-03 12:54:08 +09:00
Hazelnoot
5ee7049fad fix lint error in e2e/antennas.ts 2025-04-02 22:38:37 -04:00
syuilo
455be80b4f fix(backend): 非ログインでタイムラインのストリームに接続した際、表示にログイン必須のノートが流れる場合がある問題を修正 2025-04-03 11:32:55 +09:00
Hazelnoot
db58f4dda7 fix type error in NotificationService.ts 2025-04-02 22:31:53 -04:00
Hazelnoot
5e941385db Merge branch 'misskey-develop' into merge/2025-03-24 2025-04-02 22:29:37 -04:00
Hazelnoot
dab9b518e4 merge from misskey-develop 2025-04-02 22:29:14 -04:00
Hazelnoot
676c78c71e fix vue warning about render functions 2025-04-02 22:16:39 -04:00
syuilo
1a3866c4f6 fix(backend/chat): 自分が作ったチャットルームに他人がメッセージを送ったときに未読にならない
Fix #15748
2025-04-03 11:15:16 +09:00
Hazelnoot
36ba07ae9b assign name to MkMfm component 2025-04-02 22:13:46 -04:00
Hazelnoot
662153dee7 fix vue error from disableNotes in home.vue 2025-04-02 22:00:55 -04:00
Hazelnoot
39470fb0f8 Revert "optimize MFM rendering and fix Vue warning"
This reverts commit 5239d59f44.
2025-04-02 21:55:16 -04:00
Hazelnoot
7c49b633a6 fix vue errors from dynamic note components 2025-04-02 21:55:08 -04:00
Hazelnoot
a7179928bc fix type errors involving use-note-capture.vue 2025-04-02 21:47:11 -04:00
Hazelnoot
1eb8ca1cfd fix type error in MkTimeline.vue 2025-04-02 21:46:59 -04:00
Hazelnoot
44a82cb57a fix imports in common.ts 2025-04-02 21:46:46 -04:00
Hazelnoot
022a9c7676 fix vue errors in overview.stats.vue 2025-04-02 21:27:23 -04:00
Hazelnoot
d7784ea4ff improve debugging stack traces in MkPagination.vue 2025-04-02 21:27:05 -04:00
Hazelnoot
b5a3066a06 fix vue error from missing import in preferences.vue 2025-04-02 21:10:41 -04:00
Hazelnoot
379f43568a fix imports 2025-04-02 21:04:41 -04:00
Hazelnoot
74a4a5ae48 add missing v-else to MkNotes.vue 2025-04-02 21:04:32 -04:00
Hazelnoot
297666ac82 remove unused parameter from get-note-versions-menu.ts 2025-04-02 21:04:17 -04:00
Hazelnoot
7f577bd0a9 fix Vue warning from MkCustomEmoji.vue 2025-04-02 21:02:20 -04:00
Hazelnoot
5239d59f44 optimize MFM rendering and fix Vue warning 2025-04-02 14:37:45 -04:00
Hazelnoot
774f3c5d3a fix Vue errors from WidgetFederation.vue 2025-04-02 14:37:26 -04:00
Hazelnoot
65792d9b75 fix oneko setting 2025-04-02 14:24:11 -04:00
Hazelnoot
811d8a87ef fix import errors in MkNotification.vue 2025-04-02 14:18:00 -04:00
Hazelnoot
344b51f447 fix weird directory errors when running pnpm under certain versions of powershell core on windows 2025-04-02 11:02:57 -04:00
Hazelnoot
74d301dcf1 fix frontend lint errors 2025-04-02 10:59:23 -04:00
Hazelnoot
33b9f998da exclude storybook components from restricted globals rule 2025-04-02 10:42:04 -04:00
Hazelnoot
f9c1535147 fix backend lint errors 2025-04-02 10:35:11 -04:00
Hazelnoot
9dffb13be7 fix test errors in MfmService.ts 2025-04-02 09:47:49 -04:00
Hazelnoot
2eae1797cb fix lint errors in SkRemoteFollowersWarning.vue and MkInfo.vue 2025-04-02 09:36:18 -04:00
Hazelnoot
1840aad741 replace ti-caret-down icon 2025-04-02 09:33:10 -04:00
syuilo
d07552424c 🎨 2025-04-02 19:48:32 +09:00
syuilo
e4ceab5f6c Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-04-02 19:16:18 +09:00
syuilo
e1dc1e5111 🎨 2025-04-02 19:16:16 +09:00
syuilo
3a16af4b4b
Update CHANGELOG.md 2025-04-02 16:01:48 +09:00
Nanashi.
98eadd7093
feat: アンテナでセンシティブなチャンネルからのノートを除外できるように (#15346)
* feat(db): マイグレーションを追加

* feat(backend): カラムの定義を追加

* wip

* feat: フラグを設定出来るように

* feat: /notesエンドポイントを対応

* feat: websocketを対応

* test: テストを追加

* docs: CHANGELOGを更新

* docs: CHANGELOGの追加場所を修正

* chore: api.jsonを更新

* docs(CHANGELOG): General欄に移動

* docs: フォーマットを揃える

* chore: クエリを削除

* revert: 英訳を消す

* chore: note.channelを追加するところを変える

* docs: CHANGELOGを更新する

* docs(CHANGELOG): 2025.3.2に移動

* chore: changelogを下に移動

* ci: CI再実行用の空コミット

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-04-02 16:01:24 +09:00
zyoshoka
0bf49818c4
enhance: implement sentryForFrontend (#15433)
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-04-02 15:44:04 +09:00
syuilo
d0a98f6e6c fix(frontend): Fix #15744 2025-04-02 13:04:03 +09:00
anatawa12
102578712b
fix: iPadでdeck uiでマウスホイールでスクロールできない (#15244)
* fix: ipadでdeck uiでスクロールできない

* docs(changelog): iPadOSでdeck uiをマウスカーソルによってスクロールできない問題を修正

* chore: remove pointermove listener

* lint: use window.document

* chore: use passive pointerdown event
2025-04-02 10:48:57 +09:00
github-actions[bot]
2e0c80bc21 Bump version to 2025.4.0-beta.1 2025-04-02 01:47:33 +00:00
Hazelnoot
fa12f4c9b0 fix type error in check-word-mute.ts 2025-04-01 21:39:57 -04:00
Hazelnoot
c9186236f9 replace new icons 2025-04-01 21:38:40 -04:00
Hazelnoot
35649b03c7 fix type errors in SkFollowingRecentNotes.vue and SkUserRecentNotes.vue 2025-04-01 21:38:26 -04:00
syuilo
d44fd87b69
Update CHANGELOG.md 2025-04-02 10:37:48 +09:00
anatawa12
55d835ad51
Fix: 通知のページネーションで2つ以上読み込めなくなることがある問題 (#15277)
* fix: notifications-groupedのinclude/exclude typesに:groupedを指定できてしまう問題

* refactor: 通知の取得処理を Notification Service に移動

* feat: add function to parse additional part of id

* fix: 通知のページネーションが正しく動かない問題

Redisにのページネーションで使用する時間及びidとRedis上のものが混同されていたので、Misskeyが生成するものに寄せました。

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

* chore: XADDをretryするように

* fix: notifications-groupedでxrevrangeしているのを消し忘れていた
2025-04-02 10:37:16 +09:00
syuilo
3ec5bf114b 🎨 2025-04-02 10:25:53 +09:00
Hazelnoot
a4a53e03db fix type errors in WidgetSearch.vue 2025-04-01 21:10:16 -04:00
syuilo
a5f9eba974 enhance(frontend): インストールしたテーマをデバイス間で同期できるように 2025-04-02 10:09:25 +09:00
Hazelnoot
6b2ef370b0 fix type errors in approvals.vue 2025-04-01 21:08:04 -04:00
Hazelnoot
65ddf9ba8a fix imports in recent-notes.vue 2025-04-01 21:06:45 -04:00
Hazelnoot
dbcfbad196 fix $i imports 2025-04-01 21:03:45 -04:00
Hazelnoot
c6e775302b fix import errors in following-feed.vue 2025-04-01 21:02:14 -04:00
Hazelnoot
7fe17de5cf fix import of sfm-js 2025-04-01 20:56:58 -04:00
Hazelnoot
6ac37b4d6c lint and type fixes 2025-04-01 20:47:04 -04:00
Hazelnoot
54071efaea fix typo in check_connect.js 2025-04-01 16:07:36 -04:00
Hazelnoot
dcc6e68c08 docs: add instructions to update chart/files/default.yml 2025-04-01 16:04:48 -04:00
Hazelnoot
5b6262da66 update chart/files/default.yml 2025-04-01 16:04:35 -04:00
Hazelnoot
fb4dc62b7b fix lint errors in store.ts 2025-04-01 16:01:53 -04:00
Hazelnoot
77ae3e188b fix lint errors in theme.ts 2025-04-01 16:01:41 -04:00
Hazelnoot
4bdbbecc77 fix following feed save 2025-04-01 15:43:04 -04:00
Hazelnoot
4d42107acb docs: add instructions to regenerate assets and search index 2025-04-01 15:40:29 -04:00
Hazelnoot
491c5afa63 regenerate settings search index 2025-04-01 15:40:12 -04:00
Hazelnoot
906bbb4baa correct references to removed _ghost class 2025-04-01 15:22:04 -04:00
Hazelnoot
3b9de1c4bb fix type errors in auth.vue 2025-04-01 15:21:42 -04:00
Hazelnoot
126d2119a3 fix type errors in SkNoteDetailed.vue 2025-04-01 14:41:04 -04:00
Hazelnoot
ffe0ecb4c5 fix import order in MkPostForm 2025-04-01 14:28:45 -04:00
Hazelnoot
d8b692fd3b fix lint error in MkPageHeader 2025-04-01 12:50:03 -04:00
Hazelnoot
8b5768f848 add DynamicNoteSimple.vue 2025-04-01 12:49:53 -04:00
Hazelnoot
61019158ce add DynamicNoteDetailed.vue 2025-04-01 12:49:30 -04:00
Hazelnoot
d272d6f224 fix software name in boot.embed.js, boot.js, and error.js 2025-04-01 12:30:35 -04:00
Hazelnoot
d39e4babd1 fix development link in error.pug 2025-04-01 12:29:08 -04:00
Hazelnoot
2e2ae21a09 remove no-op Connection.cachedNotes and Connection.cacheNote 2025-04-01 12:28:16 -04:00
Hazelnoot
3455223fec replace email validation regex with a simpler alternative 2025-04-01 12:20:49 -04:00
Hazelnoot
ddbf5f354c improve result message in ApPersonService.updatePerson 2025-04-01 12:10:17 -04:00
Hazelnoot
1c5df0e8e2 add TODO reminder to ApRendererService.ts 2025-04-01 12:10:03 -04:00
Hazelnoot
02fa8f03e5 docs: add instructions to update toMastoApiHtml 2025-04-01 12:09:54 -04:00
Hazelnoot
3034c94c24 copy changes from toHtml to toMastoApiHtml 2025-04-01 12:09:43 -04:00
Hazelnoot
067d56ba03 docs: add instructions for updating ci.yml 2025-04-01 11:54:08 -04:00
Hazelnoot
6aab189ad1 copy changes to ci.yml 2025-04-01 11:53:56 -04:00
Hazelnoot
6ad9d20b02 docs: add instructions for updating DynamicNote 2025-04-01 11:50:41 -04:00
Hazelnoot
67cecda7fb fix store in warning-external-website.ts 2025-04-01 11:44:00 -04:00
Hazelnoot
de279a86b2 fix store in privacy.vue 2025-04-01 11:43:05 -04:00
Hazelnoot
8a43465a7b fix store in DynamicNote.vue 2025-04-01 11:38:48 -04:00
Hazelnoot
bf32cf85b8 fix errors in timeline.vue 2025-04-01 11:37:27 -04:00
Hazelnoot
66f4976c5e copy changes to SkNoteSub.vue 2025-04-01 11:34:30 -04:00
Hazelnoot
7549f24702 fix errors in MkNoteSub.vue 2025-04-01 11:34:19 -04:00
Hazelnoot
3482570169 copy changes to SkNoteSimple.vue 2025-04-01 11:30:12 -04:00
Hazelnoot
d44ccdda59 copy changes to SkNoteHeader.vue 2025-04-01 11:28:53 -04:00
Hazelnoot
577facfb2e copy changes to SkNoteDetailed.vue 2025-04-01 11:22:41 -04:00
Hazelnoot
b22e7aa2e9 fix import order in MkNoteDetailed.vue 2025-04-01 11:22:33 -04:00
Hazelnoot
927198f3be docs: enumerate Mk/Sk note components to sync 2025-04-01 11:14:47 -04:00
Hazelnoot
6f0a8fd9dd copy changes from MkNote to SkNote 2025-04-01 11:11:01 -04:00
Hazelnoot
cdfc446cc7 fix store error in MkNote.vue 2025-04-01 11:10:54 -04:00
Hazelnoot
6ad0669a51 reformat upstream merge instructions 2025-04-01 10:56:08 -04:00
Hazelnoot
fffa6c97fe copy changes to notes/edit.ts 2025-04-01 10:55:56 -04:00
Hazelnoot
e37c2611f7 fix missing import in UserEntityService.ts 2025-04-01 10:31:45 -04:00
Hazelnoot
ea0371de34 copy changes to NoteEditService.ts 2025-04-01 10:29:58 -04:00
Hazelnoot
0e3f2a90cf copy changes to ApNoteService.updateNote 2025-04-01 10:17:29 -04:00
Hazelnoot
383633873d fix backend type errors 2025-04-01 10:12:59 -04:00
Hazelnoot
7ff15816d1 Merge branch 'misskey-develop' into merge/2025-03-24
# Conflicts:
#	.github/workflows/api-misskey-js.yml
#	.github/workflows/changelog-check.yml
#	.github/workflows/check-misskey-js-autogen.yml
#	.github/workflows/get-api-diff.yml
#	.github/workflows/lint.yml
#	.github/workflows/locale.yml
#	.github/workflows/on-release-created.yml
#	.github/workflows/storybook.yml
#	.github/workflows/test-backend.yml
#	.github/workflows/test-federation.yml
#	.github/workflows/test-frontend.yml
#	.github/workflows/test-misskey-js.yml
#	.github/workflows/test-production.yml
#	.github/workflows/validate-api-json.yml
#	locales/index.d.ts
#	package.json
#	packages/misskey-js/generator/package.json
#	packages/misskey-js/package.json
#	pnpm-lock.yaml
#	scripts/changelog-checker/package-lock.json
#	scripts/changelog-checker/package.json
2025-04-01 09:59:46 -04:00
github-actions[bot]
bd8162c2bd Bump version to 2025.4.0-beta.0 2025-04-01 08:19:26 +00:00
かっこかり
4f206eea9f
refactor(frontend): intl-stringの処理のパフォーマンス向上 (#15737)
* refactor(frontend): intl-stringの処理のパフォーマンス向上

* ✌️
2025-04-01 17:15:22 +09:00
syuilo
f4f9832f8b 🎨 2025-04-01 17:13:58 +09:00
syuilo
70133a88f2 🎨 2025-04-01 16:52:59 +09:00
renovate[bot]
20bc80728c
chore(deps): update [misskey-js] update dependencies (#15692)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-01 16:20:52 +09:00
renovate[bot]
1d9810627e
chore(deps): update [tools] update dependencies (#15689)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-01 15:51:46 +09:00
renovate[bot]
eb5061db29
chore(deps): update [github actions] update dependencies (#15688)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-01 15:49:36 +09:00
renovate[bot]
b0c3ec3267
fix(deps): update dependency vite to v6.2.4 [security] (#15733)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-01 15:48:48 +09:00
syuilo
3a6de462bb
Update CHANGELOG.md 2025-04-01 14:04:46 +09:00
github-actions[bot]
b0cdf2feff Bump version to 2025.4.0-alpha.0 2025-04-01 04:52:38 +00:00
github-actions[bot]
4e1e8ff238 Bump version to 2025.3.2-beta.21 2025-04-01 04:33:36 +00:00
syuilo
d04acf04a6
New Crowdin updates (#15725)
* New translations ja-jp.yml (Catalan)

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

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

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

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

* New translations ja-jp.yml (Catalan)

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

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (German)
2025-04-01 13:29:28 +09:00
syuilo
165c7993e6 fix(frontend): fix PageWithAnimBg style 2025-04-01 13:28:13 +09:00
syuilo
500a5615f0 enhance(frontend): 壁紙をデッキ設定の一部に 2025-04-01 13:18:49 +09:00
Hazelnoot
2983092c06 Merge branch 'misskey-develop' into merge/2025-03-24 2025-03-31 16:07:55 -04:00
Hazelnoot
e7632c83dc Merge branch 'develop' into merge/2025-03-24
# Conflicts:
#	packages/backend/src/server/api/StreamingApiServerService.ts
#	packages/backend/src/server/api/stream/Connection.ts
2025-03-31 15:02:52 -04:00
Hazelnoot
c371af34e8 copy sharkey settings into new frontend preferences model 2025-03-31 14:53:02 -04:00
Hazelnoot
59ce4d6c28 regenerate misskey-js 2025-03-31 14:30:29 -04:00
Hazelnoot
08b8d50124 fix type errors from notes/versions endpoint 2025-03-31 14:30:18 -04:00
Hazelnoot
000b1f4fe2 fix type errors from SponsorsService 2025-03-31 14:29:48 -04:00
Hazelnoot
ebbf167f57 synchronize eslint versions to fix build error 2025-03-31 10:13:23 -04:00
Hazelnoot
b0e908e6c6 fix type errors from os.apiWithDialog 2025-03-31 09:48:23 -04:00
Hazelnoot
42d887819d regenerate package-lock.yaml 2025-03-31 09:31:40 -04:00
syuilo
5aca91251a fix missing import 2025-03-31 20:48:16 +09:00
syuilo
1c683c3fcc fix(frontend): インストールしたテーマがテーマ一覧にすぐ反映されない 2025-03-31 20:36:49 +09:00
syuilo
08072e294b 🎨 2025-03-31 20:17:48 +09:00
github-actions[bot]
f637d0dff9 Bump version to 2025.3.2-beta.20 2025-03-31 08:34:36 +00:00
かっこかり
15a5bb17e3
fix(frontend): チャットのデザイン調整 (#15708)
* fix(frontend): チャットのデザイン調整

* remove unused locales

* 🎨

* Update XMessage.vue

* Update XMessage.vue

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-03-31 17:33:00 +09:00
syuilo
888e04ce82 fix(frontend): tweak deck onboarding 2025-03-31 16:40:44 +09:00
github-actions[bot]
3a028abea5 Bump version to 2025.3.2-beta.19 2025-03-31 04:26:53 +00:00
syuilo
ff59089ad9 🎨 2025-03-31 13:24:20 +09:00
syuilo
93214862b1 🎨 2025-03-31 13:18:50 +09:00
syuilo
ea722b8360 🎨 2025-03-31 13:00:34 +09:00
syuilo
49f1f7194d 🎨 2025-03-31 11:13:02 +09:00
syuilo
8baf54e629 fix(frontend): fix ad rendering of timeline 2025-03-31 11:01:32 +09:00
syuilo
393f893a2c 🎨 2025-03-30 20:51:27 +09:00
syuilo
87a7238976 enhance(frontend): デッキのオプションを追加 2025-03-30 20:44:00 +09:00
Marie
865a9c4906 merge: Prevent streaming API denial-of-service (resolves #1019) (!951)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/951

Closes #1019

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Marie <github@yuugi.dev>
2025-03-30 10:40:56 +00:00
dakkar
3a6bba3306 merge: Remove visibility of DMs for non-recipient users (!912)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/912

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Marie <github@yuugi.dev>
2025-03-30 09:20:54 +00:00
syuilo
e0d8702839 perf(frontend): tweak MkRange 2025-03-30 18:13:39 +09:00
syuilo
6e929ece6f fix(frontend): suppress inject warn 2025-03-30 18:13:08 +09:00
Hazelnoot
1bf6cdc17f restore login rate-limit checks 2025-03-30 02:15:51 -04:00
Hazelnoot
a2062c6469 Revert "revert 7bfada9792: enhance: remove bull-board support"
This reverts commit d41d77fcd7.
2025-03-30 02:14:03 -04:00
Hazelnoot
f13f4ac972 show correct source repository link in visitor.vue 2025-03-30 02:10:30 -04:00
Hazelnoot
b6b0a54101 restore following column type 2025-03-30 02:08:28 -04:00
Hazelnoot
ea2a3be70f Merge branch 'develop' into merge/2025-03-24
# Conflicts:
#	packages/backend/src/core/activitypub/models/ApPersonService.ts
2025-03-30 01:58:43 -04:00
Hazelnoot
4ae26e6e18 Merge branch 'misskey-develop' into merge/2025-03-24 2025-03-30 01:58:17 -04:00
syuilo
303b62aff3
New Crowdin updates (#15721)
* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Catalan)

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

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (German)

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

* New translations ja-jp.yml (English)
2025-03-30 14:34:32 +09:00
syuilo
45b8423429 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-03-30 14:34:14 +09:00
syuilo
0655c8a29b clean up 2025-03-30 14:33:52 +09:00
syuilo
17f3113b92 🎨 2025-03-30 14:30:04 +09:00
syuilo
4f4cb6738c fix(frontend): drop classic ui 2025-03-30 14:25:56 +09:00
github-actions[bot]
591175b42e Bump version to 2025.3.2-beta.18 2025-03-30 02:54:21 +00:00
syuilo
c03f9bff0a 🎨 2025-03-30 11:52:51 +09:00
syuilo
88c743aa33 chore(frontend): remove unused style 2025-03-30 11:45:41 +09:00
syuilo
c06d0b9b42 enhance(frontend): organize settings page 2025-03-30 11:27:35 +09:00
syuilo
4af49e8385 enhance(frontend): organize settings page 2025-03-30 11:16:38 +09:00
syuilo
aeda34e5e7 fix(frontend): 広告が無い場合の表示を修正 2025-03-30 09:11:59 +09:00
syuilo
7d842c1a95 fix(frontend): avoid naming confliction of MkAd 2025-03-30 09:07:15 +09:00
syuilo
93fc2456b3 refactor(frontend): refactor base styles 2025-03-30 08:59:18 +09:00
syuilo
a420a95fae perf(frontend): アニメーション無効時のパフォーマンスを向上 2025-03-30 08:49:14 +09:00
renovate[bot]
2618585a25
fix(deps): update dependency vite to v6.2.3 [security] (#15710)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-30 08:39:40 +09:00
syuilo
61846a04b2
Update CHANGELOG.md 2025-03-29 23:07:46 +09:00
Hazelnoot
922a7ba1d4 track the number of concurrent requests to redis, and bypass if the request is guaranteed to reject 2025-03-29 09:47:05 -04:00
Hazelnoot
47ea8527fd fix wsmessage rate limit definition 2025-03-29 09:44:38 -04:00
syuilo
cce88c904b
Update CHANGELOG.md 2025-03-29 22:16:22 +09:00
syuilo
d866ab12e9
perf(frontend): reduce stacking context in deck 2025-03-29 22:00:01 +09:00
github-actions[bot]
df75715d29 Bump version to 2025.3.2-beta.17 2025-03-29 12:23:35 +00:00
syuilo
02da241ec9 Revert "(test)"
This reverts commit eb4062cf63.
2025-03-29 21:16:25 +09:00
syuilo
eb4062cf63 (test) 2025-03-29 21:02:31 +09:00
syuilo
d9012740a1 enhance(frontend): アイコンのスクロール追従を無効化してパフォーマンス向上できるように 2025-03-29 20:56:59 +09:00
syuilo
1b776a7e7e perf(frontend): reduce stack contexts 2025-03-29 20:02:51 +09:00
syuilo
e0b7c56458 Revert "test"
This reverts commit 2787158a04.
2025-03-29 19:23:30 +09:00
syuilo
2787158a04 test 2025-03-29 18:41:52 +09:00
syuilo
2bbc0878e7 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-03-29 18:03:34 +09:00
syuilo
fb1542429f 🎨 2025-03-29 18:03:31 +09:00
github-actions[bot]
05b23eda59 Bump version to 2025.3.2-beta.16 2025-03-29 09:01:05 +00:00
syuilo
ddd6d72dd7
New Crowdin updates (#15716)
* New translations ja-jp.yml (Chinese Traditional)

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (English)

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

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

* New translations ja-jp.yml (Italian)
2025-03-29 17:59:40 +09:00
syuilo
25db8c2fa9 🎨 2025-03-29 17:59:09 +09:00
syuilo
2ad7b010e4 🎨 2025-03-29 17:57:03 +09:00
syuilo
7c06ffc422 refactor 2025-03-29 17:28:20 +09:00
syuilo
df3ed93f84 clean up 2025-03-29 17:15:47 +09:00
syuilo
b030e33856 perf(frontend): improve performance of timeline page 2025-03-29 17:15:31 +09:00
syuilo
7fd3adedee fix tests 2025-03-29 17:00:01 +09:00
syuilo
ae59578115 refactor 2025-03-29 16:55:12 +09:00
syuilo
609a37742c clean up 2025-03-29 16:11:15 +09:00
syuilo
d9d796b204 lint fixes 2025-03-29 16:09:27 +09:00
syuilo
6c2c3f08be refactor(frontend): use symbol for di 2025-03-29 16:04:01 +09:00
syuilo
e5e4390494 fix(frontend): suppress inject warn 2025-03-29 16:01:51 +09:00
syuilo
5a09e7a8b4 lint 2025-03-29 15:57:34 +09:00
syuilo
88e6bd1533 Update eslint.config.js 2025-03-29 15:55:22 +09:00
syuilo
7d8c98767a lint 2025-03-29 15:53:44 +09:00
syuilo
490222fb78 perf(frontend): avoid needless AsyncComponentWrapper 2025-03-29 15:33:19 +09:00
syuilo
1af4081090 enhance(frontend): disable horizontal swipe for timeline/notifications to improve ux 2025-03-29 15:00:29 +09:00
syuilo
33e76f9dfc Revert "🎨"
This reverts commit 3451c9a0de.
2025-03-29 13:55:05 +09:00
syuilo
8dd8f636dc 🎨 2025-03-29 13:52:15 +09:00
syuilo
3451c9a0de 🎨 2025-03-29 13:39:44 +09:00
syuilo
fc88410c0d refactor(frontend): tweak MkNotes and MkNotifications 2025-03-29 13:34:53 +09:00
syuilo
3682c0069c Revert "test"
This reverts commit 2b42e8f171.
2025-03-29 12:27:13 +09:00
syuilo
2b42e8f171 test 2025-03-29 11:18:49 +09:00
Hazelnoot
fafb811333 increase limits on WS note subscriptions and cached notes 2025-03-28 11:44:29 -04:00
Hazelnoot
86e34175d3 SkRateLimiterService revision 3: cache lockouts in memory to avoid redis calls 2025-03-28 11:43:30 -04:00
Hazelnoot
c41d617e63 limit the number of active connections per client, and limit upgrade requests by user 2025-03-28 11:03:31 -04:00
Hazelnoot
eff7321860 avoid duplicate channels in WS connection 2025-03-28 11:03:31 -04:00
Hazelnoot
14a7309cfb avoid leaking cached notes in WS connection 2025-03-28 11:03:31 -04:00
Hazelnoot
045ff5d2c0 make sure that note subscriptions can't stay above limit 2025-03-28 11:03:31 -04:00
Hazelnoot
b8fd9d0bc0 clear subscriptions when connection closes 2025-03-28 11:03:31 -04:00
Hazelnoot
831329499d limit the number of note subscriptions per connection 2025-03-28 11:03:31 -04:00
Hazelnoot
bf1c9b67d6 close websocket when rate limit exceeded 2025-03-28 11:03:31 -04:00
Hazelnoot
18655386f3 convert streaming rate limit to bucket 2025-03-28 11:03:31 -04:00
dakkar
920bf71eb5 merge: More Mastodon API fixes (resolves #405, #471, and #984) (!954)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/954

Closes #405, #471, and #984

Approved-by: Marie <github@yuugi.dev>
Approved-by: dakkar <dakkar@thenautilus.net>
2025-03-28 12:45:54 +00:00
dakkar
cc4236e643 merge: Fix actor key rotation (!953)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/953

Approved-by: Marie <github@yuugi.dev>
Approved-by: dakkar <dakkar@thenautilus.net>
2025-03-28 12:45:49 +00:00
github-actions[bot]
e990831a09 Bump version to 2025.3.2-beta.15 2025-03-28 07:39:15 +00:00
syuilo
18355a0838 perf(frontend): avoid main thread scroll repaint 2025-03-28 16:34:21 +09:00
syuilo
811077ca66 perf(frontend): avoid main thread scroll repaint 2025-03-28 15:26:15 +09:00
syuilo
1c26dae39f enhance(frontend): リモートアカウントでチャットが使えるかどうか知る術がないため表示を改善 2025-03-28 11:00:45 +09:00
syuilo
c37f9d38a3 enhance(frontend): チャットが開放されていない場合のUIを改善 2025-03-28 10:48:13 +09:00
syuilo
dec3e86e5e enhance(backend): アカウントでチャットが有効になっているかどうかをユーザーのレスポンスに含めるように 2025-03-28 10:48:03 +09:00
syuilo
0c14250678 enhance(frontend): チャットが開放されていない場合のUIを改善 2025-03-28 10:34:25 +09:00
github-actions[bot]
30e0259062 Bump version to 2025.3.2-beta.14 2025-03-28 00:53:31 +00:00
syuilo
26aa7c6ca1
New Crowdin updates (#15707)
* New translations ja-jp.yml (Chinese Simplified)

* New translations ja-jp.yml (Catalan)

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

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Italian)
2025-03-28 09:49:59 +09:00
syuilo
29f5e5ca32 fix(frontend): classic uiが表示できない
Fix #15715
2025-03-28 09:49:47 +09:00
syuilo
a25fa62d64 enhance(frontend): ファイルアップロード処理のリファクタと設定の簡略化 2025-03-28 09:47:34 +09:00
Hazelnoot
6dc3c36ba5 fix megalodon tests 2025-03-27 20:39:23 -04:00
Hazelnoot
848a07a170 Ignore notifications that reference missing notes 2025-03-27 20:30:04 -04:00
syuilo
61e09d483e refactor 2025-03-28 09:22:37 +09:00
Hazelnoot
a92416904f use exclusive ranges in api/i/notifications and /api/v1/notifications 2025-03-27 20:20:42 -04:00
Hazelnoot
876ecb28f0 strip "@." from local reaction names 2025-03-27 19:51:43 -04:00
Hazelnoot
58cdee77d5 convert notification types in mastodon API 2025-03-27 19:51:43 -04:00
Hazelnoot
8a9979b3d3 don't render CW as HTML for mastodon 2025-03-27 19:51:43 -04:00
Hazelnoot
dcdc249e77 fix reaction emoji mapping in mastodon API 2025-03-27 19:51:43 -04:00
Hazelnoot
ebc3abea54 hide sensitive content from Discord previews 2025-03-27 19:51:43 -04:00
Hazelnoot
36dee5ff20 render profile bios in masto API 2025-03-27 19:51:43 -04:00
Hazelnoot
81f7346f80 fixes to CW and quote conversion for mastodon 2025-03-27 19:51:43 -04:00
Hazelnoot
1fa290c3eb handle errors in mastodon search endpoints 2025-03-27 19:51:43 -04:00
Hazelnoot
971bc6fd3e improve mastodon API error handling 2025-03-27 19:51:43 -04:00
Hazelnoot
a81a00e94d rename MastodonConverters.ts to matching naming scheme 2025-03-27 19:51:43 -04:00
Hazelnoot
4754942301 add additional required CORS headers for masto-api requests 2025-03-27 19:51:43 -04:00
Hazelnoot
984be9e7aa enable local timeline in Phanpy clients 2025-03-27 19:51:43 -04:00
Hazelnoot
3c54680860 support reactions in mastodon API 2025-03-27 19:51:43 -04:00
Hazelnoot
fbdee815da remove unused async from toMastoApiHtml / fromMastoApiHtml 2025-03-27 19:51:43 -04:00
Hazelnoot
8d67a8c9ae don't log query parameters from mastodon API 2025-03-27 19:51:43 -04:00
Hazelnoot
fc1d0c958c support Mastodon v4 "link header" pagination 2025-03-27 19:51:43 -04:00
Hazelnoot
3d8930f070 implement /api/v1/favourites 2025-03-27 19:51:43 -04:00
Hazelnoot
aaf49eadee implement /api/v1/bookmarks 2025-03-27 19:51:43 -04:00
Hazelnoot
cac8377e4e fix empty response from /api/v1/notifications 2025-03-27 19:51:43 -04:00
Hazelnoot
178fe16f68 fix empty response from /api/v1/blocks 2025-03-27 19:51:43 -04:00
Hazelnoot
c69f7b87f0 fix empty response from /api/v1/mutes 2025-03-27 19:51:43 -04:00
Hazelnoot
2b03f51315 don't return httpStatusCode in mastodon errors 2025-03-27 19:51:43 -04:00
Hazelnoot
f00a0fee45 minor fixes to /v1/accounts/verify_credentials 2025-03-27 19:51:42 -04:00
Hazelnoot
759e7f05c4 fix megalodon getRelationship function 2025-03-27 19:51:42 -04:00
Hazelnoot
de26ffd60b improve performance of /v1/accounts/relationships 2025-03-27 19:51:42 -04:00
Hazelnoot
f5be341acc normalize mastodon API query parameters to strip [] suffix 2025-03-27 19:51:42 -04:00
Hazelnoot
8b0555cab8 fix /api/v1/instance response 2025-03-27 19:51:42 -04:00
Hazelnoot
4a1dd7165e normalize mastodon BAD_REQUEST errors 2025-03-27 19:51:42 -04:00
Hazelnoot
67e57ab50a fix several mastodon converters 2025-03-27 19:51:42 -04:00
Hazelnoot
75b6c63f44 remove unused megalodon components 2025-03-27 19:51:42 -04:00
Hazelnoot
cb9079208a format mastodon API endpoints 2025-03-27 19:51:42 -04:00
Hazelnoot
da25595ba3 de-duplicate mastodon API logging 2025-03-27 19:51:42 -04:00
Hazelnoot
03edc33424 fix logger Data type 2025-03-27 19:51:42 -04:00
Hazelnoot
f61d71ac8c refactor mastodon API and preserve remote user agent for requests 2025-03-27 19:51:42 -04:00
Hazelnoot
1e3e0caa20 don't cache stale actor keys 2025-03-27 19:47:55 -04:00
Hazelnoot
b4e3062083 restore following feed deck UI 2025-03-27 10:30:04 -04:00
syuilo
e40846c46b fix e2e test 2025-03-27 19:50:03 +09:00
syuilo
a78db27a3c Update CHANGELOG.md 2025-03-27 17:30:06 +09:00
syuilo
f7e901deb2 test fixes 2025-03-27 17:30:04 +09:00
syuilo
b95da9c9a4 enhance(backend): ミュートしているユーザーをユーザー検索の結果から除外するように 2025-03-27 17:12:23 +09:00
syuilo
c29a5764d3 refactor(backend): better method name 2025-03-27 16:51:08 +09:00
Hazelnoot
86bfafe27f restore http lookup 2025-03-26 21:01:07 -04:00
Hazelnoot
28bf01ab4a restore AiScript error handling 2025-03-26 20:54:15 -04:00
Hazelnoot
0e28b8a1f5 restore following feed routes 2025-03-26 20:53:06 -04:00
Hazelnoot
0c34bf26dc restore import/export settings 2025-03-26 20:27:27 -04:00
Hazelnoot
f840b75fe2 Merge branch 'develop' into merge/2025-03-24
# Conflicts:
#	packages/frontend/src/pages/timeline.vue
2025-03-26 10:55:48 -04:00
Hazelnoot
11e578c10d Merge branch 'misskey-develop' into merge/2025-03-24
# Conflicts:
#	.github/workflows/storybook.yml
2025-03-26 10:54:55 -04:00
Hazelnoot
1da580c20d restore sharkey-specific settings 2025-03-26 10:54:28 -04:00
Marie
92382b2ed4 merge: fix: bubble timeline not being selectable when logged out (!950)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/950

Closes #1018

Approved-by: Hazelnoot <acomputerdog@gmail.com>
Approved-by: dakkar <dakkar@thenautilus.net>
2025-03-26 11:23:24 +00:00
Acid Chicken
ed86b1706d
ci(storybook): prevent running for bots 2025-03-26 12:17:56 +09:00
syuilo
36865a5771 enhance(frontend): improve chat ux 2025-03-26 10:49:36 +09:00
syuilo
5e90679916 lint 2025-03-26 10:26:48 +09:00
syuilo
ac49a3e992 typo 2025-03-26 09:06:34 +09:00
Hazelnoot
9fd94cd23e restore like button settings 2025-03-25 17:57:39 -04:00
Marie
3d27e5ce3e
fix: bubble timeline not being selectable when logged out 2025-03-25 22:40:19 +01:00
Hazelnoot
f861bec1a7 update references from /scripts/ to /utility/ 2025-03-25 17:32:18 -04:00
Hazelnoot
949baa9b8b Revert "feat: google analytics (#15451)"
This reverts commit 2b6638e1
2025-03-25 17:30:28 -04:00
Hazelnoot
d41d77fcd7 revert 7bfada9792: enhance: remove bull-board support 2025-03-25 17:25:30 -04:00
Hazelnoot
7ea710b314 remerge: remove FetchAllowSoftFailMask in favor of our same-authority checks 2025-03-25 17:19:38 -04:00
Hazelnoot
82e2952e3c add utility methods to get instance actor, relay actor, and proxy actor 2025-03-25 17:19:04 -04:00
Hazelnoot
76b1cf0526 remerge: auto-approve and allow unsigned fetch for system users 2025-03-25 16:22:39 -04:00
Hazelnoot
40975719ec Merge branch 'misskey-develop' into merge/2025-03-24
# Conflicts:
#	package.json
#	packages/backend/src/core/entities/NotificationEntityService.ts
#	packages/backend/src/types.ts
#	packages/frontend/src/pages/admin/modlog.ModLog.vue
#	packages/misskey-js/src/consts.ts
#	packages/misskey-js/src/entities.ts
2025-03-25 16:17:34 -04:00
Hazelnoot
d8908ef2d8 merge upstream 2025-03-25 16:14:53 -04:00
syuilo
f0ac0aa84d Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-03-25 20:06:49 +09:00
syuilo
97fddf2a80 🎨 2025-03-25 20:06:46 +09:00
かっこかり
2a5922836c
fix(frontend): コントロールパネルのナビゲーションバーが画面に張り付かない問題を修正 (#15706) 2025-03-25 19:50:40 +09:00
github-actions[bot]
0e417e51ac Bump version to 2025.3.2-beta.13 2025-03-25 09:40:08 +00:00
syuilo
c5cd3dd373
New Crowdin updates (#15685)
* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Portuguese)

* New translations ja-jp.yml (Turkish)

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

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (Romanian)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Arabic)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Greek)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Dutch)

* New translations ja-jp.yml (Norwegian)

* New translations ja-jp.yml (Polish)

* New translations ja-jp.yml (Slovak)

* New translations ja-jp.yml (Swedish)

* New translations ja-jp.yml (Ukrainian)

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

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Bengali)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Uzbek)

* New translations ja-jp.yml (Lao)

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (German)

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (German)

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

* New translations ja-jp.yml (Catalan)

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

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Portuguese)

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

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (Romanian)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Arabic)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Norwegian)

* New translations ja-jp.yml (Polish)

* New translations ja-jp.yml (Slovak)

* New translations ja-jp.yml (Swedish)

* New translations ja-jp.yml (Ukrainian)

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

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Bengali)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Uzbek)

* New translations ja-jp.yml (Catalan)

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Chinese Traditional)
2025-03-25 18:35:28 +09:00
syuilo
fc576ebc64 fix(backend): 承認したチャットルームへの招待の通知が存在するとエラーになる問題を修正 2025-03-25 18:34:25 +09:00
syuilo
22f99b42f6 enhance(frontend): refactor and improve ux 2025-03-25 18:30:28 +09:00
syuilo
de76a66c03 enhance(frontend): タブレットでの表示時にウィジェットボタンでページ下部が隠れないように 2025-03-25 18:15:54 +09:00
syuilo
185f290373 🎨 2025-03-25 18:03:50 +09:00
syuilo
88b48b1d8e fix(backend): チャットのページネーションが機能しない問題を修正 2025-03-25 17:57:34 +09:00
syuilo
ef0b97b2dc fix(frontend): コンパネ>通報 の各通報のユーザー詳細が表示できない問題を修正
Fix #15704
2025-03-25 16:17:10 +09:00
syuilo
98554579ea enhance: チャットのリアクションを削除できるように 2025-03-25 16:09:19 +09:00
syuilo
8e72c68205 follow up of a01ae38a07 2025-03-25 15:55:09 +09:00
syuilo
a01ae38a07 enhance: モデレーターがチャットルームの内容を確認・削除できるように 2025-03-25 15:51:45 +09:00
syuilo
304d0eb83b enhance: チャットルームに招待されたときの通知を追加 2025-03-25 15:25:43 +09:00
github-actions[bot]
2fc3baa988 Bump version to 2025.3.2-beta.12 2025-03-25 04:45:07 +00:00
syuilo
c51e862b7d enhance: 送信したチャットルームへの招待を確認できるように 2025-03-25 13:41:12 +09:00
syuilo
1736955694 fix(backend): 自分がオーナーではない参加中のルームにメッセージを送信すると不必要な通知が発生するのを修正 2025-03-25 13:29:03 +09:00
syuilo
2272eceffa enhance(frontend): Enterでチャットのメッセージを送信できるように 2025-03-25 13:19:54 +09:00
syuilo
8c1fc85d00 enhance(frontend): チャットの送信者名を表示できるように 2025-03-25 12:36:21 +09:00
syuilo
9f4fa6d3f5 enhance(frontend): チャットのホームの表示を定期的に更新するように 2025-03-25 12:19:59 +09:00
syuilo
023ab02e59 🎨 2025-03-25 12:08:17 +09:00
syuilo
1318a10af8 🎨 2025-03-25 11:37:38 +09:00
syuilo
18bb831777 🎨 2025-03-25 11:33:40 +09:00
github-actions[bot]
e6bc887d6c Bump version to 2025.3.2-beta.11 2025-03-25 02:19:28 +00:00
syuilo
8cbcbd462c enhance(frontend): チャット画面で確実に最下部へスクロール追従するように 2025-03-25 11:11:24 +09:00
syuilo
600bb34172 enhance(frontend): 設定のインデックス更新 2025-03-25 09:54:23 +09:00
syuilo
26b2cfe518 enhance(frontend): ナビゲーションバーの副ボタンを非表示にできるように 2025-03-25 09:50:59 +09:00
syuilo
72734fe365 enhance(frontend): バックグラウンドでチャットメッセージが届いたときにサウンドを再生できるように 2025-03-25 09:36:59 +09:00
syuilo
2370b55a27 enhance(frontend): チャットルームを削除できるように 2025-03-25 09:30:14 +09:00
syuilo
5d3e8253c4 fix(frontend): チャットを全員に許可している場合に誰も許可していないと表示されるのを修正 2025-03-25 09:24:01 +09:00
syuilo
8d6573fbec enhance(frontend): 設定の移行を手動でトリガーできるように 2025-03-25 08:38:53 +09:00
syuilo
8da1368a0b fix(backend): 既存のルームメンバーを改めて招待できないように 2025-03-25 08:05:59 +09:00
かっこかり
5513337198
fix(frontend): 本番環境で不必要なconsole.logを出さないように (#15702) 2025-03-25 08:02:06 +09:00
github-actions[bot]
3f7a2bf5b5 Bump version to 2025.3.2-beta.10 2025-03-24 12:34:25 +00:00
syuilo
f1f24e39d2
Feat: Chat (#15686)
* wip

* wip

* wip

* wip

* wip

* wip

* Update types.ts

* Create 1742203321812-chat.js

* wip

* wip

* Update room.vue

* Update home.vue

* Update home.vue

* Update ja-JP.yml

* Update index.d.ts

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Update CHANGELOG.md

* wip

* Update home.vue

* clean up

* Update misskey-js.api.md

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* lint fixes

* lint

* Update UserEntityService.ts

* search

* wip

* 🎨

* wip

* Update home.ownedRooms.vue

* wip

* Update CHANGELOG.md

* Update style.scss

* wip

* improve performance

* improve performance

* Update timeline.test.ts
2025-03-24 21:32:46 +09:00
dakkar
aebc6b4112 merge: enhance: Update de-DE.yml (!949)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/949

Approved-by: Marie <github@yuugi.dev>
Approved-by: dakkar <dakkar@thenautilus.net>
2025-03-24 08:19:46 +00:00
Daniel Ares
3b568c26f7 Update de-DE.yml 2025-03-23 21:38:50 +00:00
Marie
cbafabcffd merge: Fixing en-US.yml (!948)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/948

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Marie <github@yuugi.dev>
2025-03-23 18:34:09 +00:00
Daniel Ares
070f30965e Fixing en-US.yml 2025-03-23 14:07:21 +00:00
dakkar
b1467989a5 merge: Accept announce activities (resolves #797 and #460) (!916)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/916

Closes #797 and #460

Approved-by: Marie <github@yuugi.dev>
Approved-by: dakkar <dakkar@thenautilus.net>
2025-03-23 13:45:13 +00:00
Daniel Ares
ba5856eedd Update de-DE.yml 2025-03-23 12:52:01 +00:00
syuilo
0471e457fe fix(frontend): fix broken styles 2025-03-23 21:23:52 +09:00
syuilo
260d35e2f0
Update CHANGELOG.md 2025-03-22 18:37:41 +09:00
syuilo
3ff9d9f4fd
Update CHANGELOG.md 2025-03-22 18:34:56 +09:00
syuilo
27991a3bc8
Update CHANGELOG.md 2025-03-22 18:28:51 +09:00
syuilo
b5f86e5210 refactor(frontend): refactor page styles 2025-03-22 18:25:45 +09:00
syuilo
16cde5568d
Update CHANGELOG.md 2025-03-22 15:12:24 +09:00
syuilo
bf07796b6b
Update CHANGELOG.md 2025-03-22 15:08:19 +09:00
syuilo
08b131ec33 refactor(backend): better prop name 2025-03-22 08:16:15 +09:00
syuilo
1312fe34c1
Update CHANGELOG.md 2025-03-22 08:12:32 +09:00
Marie
aa1691295b merge: Make confirm follow prompt not show up when cancelling a follow request (!941)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/941

Closes #822

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Hazelnoot <acomputerdog@gmail.com>
2025-03-21 16:46:47 +00:00
Hazelnoot
73e70f7449 fix unit tests in activitypub.ts 2025-03-21 12:37:06 -04:00
Hazelnoot
770e0bbcdc document changes to updateInstanceQueue in merge instructions 2025-03-21 12:37:06 -04:00
Hazelnoot
27e8289126 fix lint errors in mock-resolver.ts and activitypub.ts 2025-03-21 12:37:06 -04:00
Hazelnoot
3958b71f4e don't discard the target of announce activities, in case it's a private note that can't be re-fetched 2025-03-21 12:37:06 -04:00
Hazelnoot
f88430aebc add IObjectWithId type for APIs that work with objects required to have an ID. 2025-03-21 12:37:06 -04:00
Hazelnoot
ad49faa956 implement ApResolver.secureResolve to use a provided object only if the authority matches 2025-03-21 12:37:06 -04:00
Hazelnoot
1ed2f207f7 fix startup crash caused by circular reference (SWC is not compatible with forwardRef) 2025-03-21 12:37:06 -04:00
Hazelnoot
f2bb01f7da support Announce(Activity) activities 2025-03-21 12:37:06 -04:00
Hazelnoot
1eb9070e39 allow overriding AP resolver recursion limit 2025-03-21 12:37:06 -04:00
Hazelnoot
c2740cbe73 add isActivity method to check for AP Activities 2025-03-21 12:37:06 -04:00
Hazelnoot
f18d402ce6 fix typo in activity signature mismatch error 2025-03-21 12:37:06 -04:00
github-actions[bot]
97563910fa Bump version to 2025.3.2-beta.9 2025-03-21 12:05:52 +00:00
syuilo
96a7c4a568 fix(frontend): チャンネルのフッターが表示されない問題を修正 2025-03-21 21:04:38 +09:00
syuilo
fee6f9fcc2 Update def.ts 2025-03-21 21:04:17 +09:00
renovate[bot]
50724b6ab8
fix(deps): update [frontend] update dependencies (#15625)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-21 19:41:26 +09:00
renovate[bot]
e61263cff0
fix(deps): update [backend] update dependencies (#15596)
* fix(deps): update [backend] update dependencies

* fix(backend/types): ensure to use nodejs-provided stream api

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
2025-03-21 19:38:11 +09:00
github-actions[bot]
d073fe6b02 Bump version to 2025.3.2-beta.8 2025-03-20 12:18:50 +00:00
syuilo
ce858a676b refactor(frontend): use PageWithHeader instead of MkStickyContainer+MkPageHeader combination 2025-03-20 21:04:37 +09:00
syuilo
733a391d86 follow up of 1fd87bd2e4
コミットし忘れ
2025-03-20 20:29:46 +09:00
syuilo
0e25a0fb81 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-03-20 20:28:29 +09:00
syuilo
1fd87bd2e4 fix(frontend): prevent transition glitch of MkHorizontalSwipe 2025-03-20 20:28:16 +09:00
github-actions[bot]
ebc54b1f82 Bump version to 2025.3.2-beta.7 2025-03-20 10:07:37 +00:00
syuilo
6015254e59 lint fixes 2025-03-20 19:00:09 +09:00
syuilo
c02f0b3b33 Update eslint.config.js 2025-03-20 18:59:10 +09:00
syuilo
abddd40c09 enhance(frontend): 通常のRouterViewにTransitionを追加 2025-03-20 18:55:32 +09:00
かっこかり
a865a949b5
fix(frontend): MkRoleSelectDialogでのpopupの使い方が誤っているのを修正 (#15683) 2025-03-20 16:36:37 +09:00
syuilo
0007723405 fix lint 2025-03-20 16:34:50 +09:00
syuilo
71188b3463 fix lint 2025-03-20 16:10:38 +09:00
syuilo
7f534a41a6 fix lint 2025-03-20 16:07:52 +09:00
syuilo
f25963e2c2 Update eslint.config.js 2025-03-20 16:06:32 +09:00
syuilo
dfab6b1b8d lint(frontend): force window prefix 2025-03-20 15:44:06 +09:00
syuilo
fac59d75e2 lint(frontend): relax id-denylist rule 2025-03-20 15:43:35 +09:00
syuilo
fd3e28812e clean up console 2025-03-20 15:15:46 +09:00
syuilo
6a90b7e04b add todo 2025-03-20 15:09:50 +09:00
syuilo
8d8414687a enhance(frontend): improve preference manager stability 2025-03-20 14:57:14 +09:00
syuilo
0c682dd027 🎨 2025-03-20 13:34:57 +09:00
syuilo
3399c786a8 refactor(frontend): refactor components 2025-03-20 13:33:01 +09:00
syuilo
64cf101fe7 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-03-20 13:16:23 +09:00
syuilo
8b6d90b7a4 🎨 2025-03-20 13:16:08 +09:00
github-actions[bot]
070749bdc8 Bump version to 2025.3.2-beta.6 2025-03-20 04:03:25 +00:00
syuilo
161706c5e2
New Crowdin updates (#15680)
* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Portuguese)

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

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (Romanian)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Arabic)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Greek)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Dutch)

* New translations ja-jp.yml (Norwegian)

* New translations ja-jp.yml (Polish)

* New translations ja-jp.yml (Slovak)

* New translations ja-jp.yml (Swedish)

* New translations ja-jp.yml (Ukrainian)

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

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Bengali)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Uzbek)

* New translations ja-jp.yml (Lao)

* New translations ja-jp.yml (Korean (Gyeongsang))
2025-03-20 13:01:20 +09:00
syuilo
596e517f77 fix(frontend): minimum uiが表示できない 2025-03-20 12:58:18 +09:00
syuilo
91670caca0 enhance(frontend): tweak install-extensions behaviour 2025-03-20 12:58:01 +09:00
syuilo
fccaadacf0 lint(frontend): improve id-denylist rule 2025-03-20 12:47:51 +09:00
syuilo
282caa0b7e 🎨 for install-extensions 2025-03-20 12:36:48 +09:00
syuilo
9529867630 fix(frontend): dev buildでpreferencesのタブ同期が不必要に行われるのを修正 2025-03-20 12:02:50 +09:00
github-actions[bot]
d06fadd095 Bump version to 2025.3.2-beta.5 2025-03-20 00:06:04 +00:00
zyoshoka
9dd13f364b
fix(backend): mismatch in emojis param of test WebHook payload (#15675)
* fix(backend): mismatch in `emojis` param of test WebHook payload

* fix: test

* fix: type
2025-03-20 09:00:58 +09:00
syuilo
b067d4dcd6 follow up of 7b323031b7 2025-03-20 08:59:54 +09:00
syuilo
acac759d87 fix(frontend): モバイルレイアウト時にホームを押しても最上部へスクロールされない
Fix #15679
2025-03-20 08:35:45 +09:00
Hazelnoot
51c6c763e3 merge: Make sure that scheduledNote* types are only showing on and off options. (!947)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/947

Closes #1013

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Hazelnoot <acomputerdog@gmail.com>
2025-03-19 22:29:09 +00:00
Marie
026012062e fix: missing character 2025-03-19 22:19:41 +00:00
Marie
1b70e90744 upd: add scheduledNote notification types to only on and off types 2025-03-19 22:17:06 +00:00
Marie
65d5f1e081 merge: Optionally enable websocket compression (!921)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/921

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Marie <github@yuugi.dev>
2025-03-19 17:40:49 +00:00
Marie
4c1ad27acc merge: fix notification dot (!946)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/946

Approved-by: Hazelnoot <acomputerdog@gmail.com>
Approved-by: Marie <github@yuugi.dev>
2025-03-19 17:40:35 +00:00
Hazelnoot
9fa3be8246 merge: Implement replies collection for posts (resolves #738 and #948) (!918)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/918

Closes #738 and #948

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Marie <github@yuugi.dev>
2025-03-19 17:39:53 +00:00
Hazelnoot
5182f17d32 implement replies collection for posts 2025-03-19 09:52:55 -04:00
syuilo
b37622fa64 🎨 2025-03-19 20:54:07 +09:00
syuilo
c17a104de6 fix(frontend): router view stacking有効時にinstall-extensionsが動かない 2025-03-19 20:53:48 +09:00
syuilo
4ab9f66356 Update deep-equal.ts 2025-03-19 20:32:15 +09:00
zyoshoka
aed95a765d
chore(storybook): fix storybook build (#15678) 2025-03-19 10:52:05 +00:00
Sayamame-beans
71841e365e
Enhance: 2段階認証時のリカバリーコードのファイル名にサーバーURLを含めるように (#15677)
* enhance(frontend): include server hostname and port in 2fa recovery code filename

* chore(frontend): fix mistake(use `@` for indicate server hostname)

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-03-19 19:34:57 +09:00
github-actions[bot]
3b20279e20 Bump version to 2025.3.2-beta.4 2025-03-19 10:27:14 +00:00
Yuri Lee
21dc7aebe7
Fix: Don't delete remote emoji when import zip (#15674)
* Fix: Don't delete remote emoji when import zip

* Update packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts

Co-authored-by: zyoshoka <107108195+zyoshoka@users.noreply.github.com>

---------

Co-authored-by: zyoshoka <107108195+zyoshoka@users.noreply.github.com>
2025-03-19 10:23:50 +00:00
syuilo
aff03708a7
New Crowdin updates (#15667)
* New translations ja-jp.yml (Chinese Traditional)

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

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Catalan)
2025-03-19 19:18:14 +09:00
syuilo
69ad3cf89b
Update CHANGELOG.md 2025-03-19 19:17:33 +09:00
syuilo
7b323031b7 refactor(frontend): use useTemplateRef for DOM referencing 2025-03-19 18:46:03 +09:00
syuilo
81ac71f7e5 refactor(frontend): router refactoring 2025-03-19 18:06:22 +09:00
syuilo
2c76018b7f better import paths 2025-03-19 17:27:18 +09:00
syuilo
2dc2d2e4fe refactor 2025-03-19 16:04:01 +09:00
syuilo
409cd4fbd3 refactor(frontend): router refactoring 2025-03-19 15:54:30 +09:00
syuilo
7d4045e8b4 refactor(frontend): router refactoring 2025-03-19 15:24:56 +09:00
syuilo
bdc72e5817 clean up 2025-03-19 15:17:41 +09:00
syuilo
11378b17c5 🎨 2025-03-19 09:31:01 +09:00
dakkar
663072ec47 nicer catches 2025-03-18 20:15:10 +00:00
dakkar
a9bad939ba fix notification dot
1) the `crossOrigin='anonymous'` tells the browser to actually honour
	 CORS on the image

2) the dot is now always 1/5 of the icon, even for large icons

3) we use `toBlob` instead of `toDataURL` because
	 https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
	 says so

4) the test now blinks the dot, so it tests the actual code

5) if there's a problem during the test, we log the error, so people
	 can tell it to us

Thanks to Ares on Discord for reporting the problems.
2025-03-18 19:38:10 +00:00
PrivateGER
c08c8502e3
adjust compression fallback 2025-03-18 14:21:31 +01:00
syuilo
62bf0d53d3 🎨 2025-03-18 22:21:28 +09:00
syuilo
05391f59a5 enhance(frontend): improve StackingRouterView 2025-03-18 20:55:19 +09:00
syuilo
d609f41f61 🎨 2025-03-18 17:31:25 +09:00
syuilo
0a295e1bb0 🎨 2025-03-18 15:23:50 +09:00
syuilo
474155b677 follow up of 6c8f21b608 2025-03-17 13:27:47 +09:00
syuilo
6c8f21b608 fix(backend): 連合無しモードでも外部から照会可能だった問題を修正 2025-03-17 13:21:09 +09:00
ikasoba
7d5daa4b00
fix (#15671) 2025-03-17 03:40:10 +00:00
Hazelnoot
62d35a56c1 merge: Convert Authorized Fetch to a setting and add support for hybrid mode (!917)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/917

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Marie <github@yuugi.dev>
2025-03-16 17:55:17 +00:00
Hazelnoot
bb3d710927 allow unsigned fetch for all system users 2025-03-16 10:49:16 -04:00
Hazelnoot
97da78b46c fix lint errors in activitypub.ts 2025-03-16 10:07:57 -04:00
Hazelnoot
e0f3780885 fix typescript error in WebhookTestService.ts (this is the WORST class and needs to be removed please /sob) 2025-03-16 10:07:57 -04:00
Hazelnoot
a35c2f214b convert Authorized Fetch to a setting and add support for hybrid mode (essential metadata only) 2025-03-16 10:07:57 -04:00
syuilo
1ce81f243e Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-03-16 19:04:16 +09:00
syuilo
a773f2976d refactor(frontend): signinRequired -> ensureSignin 2025-03-16 19:04:14 +09:00
github-actions[bot]
467c68fb98 Bump version to 2025.3.2-beta.3 2025-03-16 08:51:58 +00:00
syuilo
22b0ace8b4 enhance(frontend): 投稿フォームの設定メニューを改良 (改)
This reverts commit a814395127.
2025-03-16 17:48:16 +09:00
syuilo
a814395127 Revert "enhance(frontend): 投稿フォームの設定メニューを改良 (#14804)"
This reverts commit ce6b2448ce.
2025-03-16 17:21:20 +09:00
syuilo
81a0cbd294 chore(frontend): use toast to show message when call copyToClipboard 2025-03-16 15:04:38 +09:00
syuilo
32844e4775 🎨 2025-03-16 14:56:27 +09:00
github-actions[bot]
fbd9f47182 Bump version to 2025.3.2-beta.2 2025-03-16 05:18:29 +00:00
syuilo
1c9e25470a refactor 2025-03-16 14:15:09 +09:00
かっこかり
ce6b2448ce
enhance(frontend): 投稿フォームの設定メニューを改良 (#14804)
* enhance(frontend): 投稿フォームの設定メニューを改良

* Update Changelog

* indent

* MkMenuのitemを切り出して共通化

* remove unused expose

* fix: ドロワーなどのOptionが当たらない問題を修正

* 他のpopupMenuの項目選択時と挙動をあわせる

* チュートリアルで詰む問題を修正

* Revert "MkMenuのitemを切り出して共通化"

This reverts commit ce3679798c5b642dd0e47056f70657e46b382b5e.

* enhance: slotで共通化

* Update MkPostFormOtherMenu.vue

* remove duplicated locale key

* refactor: メニューの定義をMkPostForm側で行うように

* Update CHANGELOG.md

* [ci skip] Update MkPostFormOtherMenu.vue

* Update MkPostForm.vue

* Update CHANGELOG.md

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-03-16 05:05:58 +00:00
syuilo
7d44b47fdf
New Crowdin updates (#15662)
* New translations ja-jp.yml (Catalan)

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

* New translations ja-jp.yml (German)

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

* New translations ja-jp.yml (Chinese Simplified)
2025-03-16 13:59:22 +09:00
syuilo
dca42fd6e6 enhance(frontend): improve ux for touch devices 2025-03-16 13:59:08 +09:00
syuilo
43153311c6 🎨 2025-03-16 13:43:47 +09:00
syuilo
2b23c7e7f5 chore(frontend): remove duplicated warn 2025-03-16 13:30:08 +09:00
syuilo
2d4e85b466 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-03-16 13:03:04 +09:00
syuilo
7bfada9792 enhance: remove bull-board support 2025-03-16 13:03:02 +09:00
lqvp
4fef9c670a
fix(i18n): 通知タイプのcreateTokenが抜けていたのを修正 (#15663) 2025-03-16 02:27:41 +00:00
syuilo
9599261fc3 fix(frontend): fix settings-search-index of webhook 2025-03-16 11:02:54 +09:00
syuilo
c2940fd77c enhance(frontend): improve usability on touch device 2025-03-16 10:58:06 +09:00
Hazelnoot
e3d949ced6 merge: fetch linked notes manually, unless we have them in DB - fixes 1006 (!945)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/945

Closes #1006

Approved-by: Marie <github@yuugi.dev>
Approved-by: Hazelnoot <acomputerdog@gmail.com>
2025-03-15 20:46:28 +00:00
dakkar
c9874f72b1 fix indent 2025-03-15 19:36:28 +00:00
dakkar
d0a074ac89 fetch linked notes manually, unless we have them in DB - fixes 1006 2025-03-15 19:17:36 +00:00
Hazelnoot
8e62aa9814 merge: Add external url warning to url previews (!944)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/944

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Hazelnoot <acomputerdog@gmail.com>
2025-03-15 17:48:04 +00:00
Marie
bb0010db27 upd: add warning prompt to previews 2025-03-14 22:14:36 +00:00
Hazelnoot
4184d7d726 merge: Remove our addition of copy remote link (!943)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/943

Closes #1005

Approved-by: dakkar <dakkar@thenautilus.net>
Approved-by: Hazelnoot <acomputerdog@gmail.com>
2025-03-14 21:28:02 +00:00
Marie
9782f2a415 upd: remove old leftover copy link (origin) 2025-03-14 18:46:29 +00:00
syuilo
2ddedd0ce6 refactor 2025-03-14 19:54:30 +09:00
syuilo
c88f5f5195
Update CHANGELOG.md 2025-03-14 17:00:02 +09:00
github-actions[bot]
30de6d80bb Bump version to 2025.3.2-beta.1 2025-03-14 07:39:14 +00:00
syuilo
63993dace6 fix(frontend): fix pref migration
Fix #15661
2025-03-14 16:37:25 +09:00
syuilo
0929410d36 enhance(frontend): improve pref manager 2025-03-14 15:43:56 +09:00
github-actions[bot]
96866d37cd Bump version to 2025.3.2-beta.0 2025-03-14 03:49:32 +00:00
syuilo
35b66276ff
New Crowdin updates (#15621)
* New translations ja-jp.yml (Catalan)

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

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (German)

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

* New translations ja-jp.yml (English)

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

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

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Portuguese)

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

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Italian)

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

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Catalan)

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

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Italian)

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

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Portuguese)

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

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Arabic)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Greek)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Polish)

* New translations ja-jp.yml (Slovak)

* New translations ja-jp.yml (Ukrainian)

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

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Bengali)

* New translations ja-jp.yml (Thai)

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

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Chinese Traditional)
2025-03-14 12:09:38 +09:00
syuilo
daa16d184f 🎨 2025-03-14 11:58:41 +09:00
syuilo
833a232262 enhance(frontend): clear all client data when logout 2025-03-14 11:55:42 +09:00
github-actions[bot]
bcb891e4fd Bump version to 2025.3.2-alpha.11 2025-03-14 01:29:38 +00:00
syuilo
152660fcf2 enhance(frontend): re-organize settings page 2025-03-14 09:53:44 +09:00
syuilo
a1204f5e3e 🎨 2025-03-14 09:42:53 +09:00
かっこかり
7acd3d1a88
fix(frontend): fix test 2025-03-13 22:32:26 +09:00
syuilo
8c9ec5827f enhance(frontend): improve accounts management 2025-03-13 22:12:23 +09:00
syuilo
44073736de enhance(frontend): improve preferences 2025-03-13 19:44:23 +09:00
syuilo
0126dba475 enhance(frontend): re-organize settings page 2025-03-13 19:30:35 +09:00
github-actions[bot]
3280a3d661 Bump version to 2025.3.2-alpha.10 2025-03-13 09:07:37 +00:00
syuilo
bdf80c49d8 fix(frontend): better migration detection
Fix #15656
2025-03-13 18:05:44 +09:00
syuilo
59169a6450 🎨 2025-03-13 17:42:35 +09:00
syuilo
5d228fb0f3 enhance(frontend): re-organize settings page 2025-03-13 17:39:53 +09:00
syuilo
10b67e1b3a enhance(frontend): improve emoji picker settings 2025-03-13 16:56:47 +09:00
syuilo
3ced310f77 refactor(frontend): organize use functions 2025-03-13 14:05:04 +09:00
syuilo
010ec113c2 refactor(frontend): cond -> scope 2025-03-13 13:45:23 +09:00
syuilo
30005ba959 enhance(frontend): tweak search index 2025-03-13 09:26:04 +09:00
syuilo
6b69588c03 enhance(frontend): improve deck setting page 2025-03-13 09:24:15 +09:00
syuilo
8593aa1418 refactor 2025-03-13 09:10:09 +09:00
syuilo
9876ff9a7a Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-03-13 09:07:25 +09:00
syuilo
ce6eba77d9 🎨 2025-03-13 09:07:22 +09:00
syuilo
9b2af53025 enhance(frontend): improve pref manager 2025-03-13 09:02:38 +09:00
syuilo
7b6ff19ea3
Update CHANGELOG.md 2025-03-12 21:49:23 +09:00
github-actions[bot]
c9fa95429a Bump version to 2025.3.2-alpha.9 2025-03-12 12:45:35 +00:00
饺子w (Yumechi)
e5d117dc98
fix(backend): tighten an overly relaxed criteria and remove capability of matching multiple final URLs in URL authority checking (#15655)
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
2025-03-12 12:39:24 +00:00
syuilo
4a73feb041 enhance(frontend): make deck profiles syncable 2025-03-12 21:12:08 +09:00
syuilo
a06b9eefaa enhance(frontend): suppress needless confirmation when turn on pref sync 2025-03-12 21:05:39 +09:00
syuilo
3129fcf164 fix(frontend): fix type errors 2025-03-12 20:17:54 +09:00
syuilo
35a4544477 add todo 2025-03-12 18:54:36 +09:00
zyoshoka
aa1cc2f817
fix(storybook): use type-only imports in generated stories (#15654) 2025-03-12 16:51:10 +09:00
github-actions[bot]
15685be4cc Bump version to 2025.3.2-alpha.8 2025-03-12 06:10:35 +00:00
syuilo
8508c4dadc refactor 2025-03-12 15:07:45 +09:00
かっこかり
e594fb0037
enhance(dev): frontendの検索インデックス作成を単独のコマンドで行えるように (#15653) 2025-03-12 14:37:57 +09:00
syuilo
a369721791 remove todo 2025-03-12 14:35:22 +09:00
syuilo
f8e244f48d enhance(frontend): アカウントオーバーライド設定とデバイス間同期の併用に対応 2025-03-12 14:34:10 +09:00
syuilo
8410611512 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-03-12 13:04:44 +09:00
syuilo
caab1ec7c3 🎨 2025-03-12 13:04:41 +09:00
github-actions[bot]
ffade9740e Bump version to 2025.3.2-alpha.7 2025-03-12 03:03:37 +00:00
syuilo
b03bcf26cd enhance(frontend): 設定値の同期を実装(実験的) 2025-03-12 11:39:05 +09:00
syuilo
ddbc83b2e4 chore(frontend): tweak settings page 2025-03-11 20:42:06 +09:00
syuilo
d185785f20 enhance(frontend): improve settings page 2025-03-11 14:52:04 +09:00
syuilo
02d7fbefc4 🎨 2025-03-11 12:08:15 +09:00
syuilo
f7ea92c68c chore: remove unused files 2025-03-11 12:02:41 +09:00
syuilo
e891d5c5d3 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-03-11 11:44:34 +09:00
syuilo
57a6b630b7 chore: add note 2025-03-11 11:44:25 +09:00
github-actions[bot]
eda768a08c Bump version to 2025.3.2-alpha.6 2025-03-11 02:43:27 +00:00
syuilo
1f345eb839 enhance(frontend): deckをpreferences管理に 2025-03-11 11:14:55 +09:00
syuilo
1f2801af02 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-03-10 21:42:30 +09:00
syuilo
a4ba096e2a chore(frontend): improve preference store stability 2025-03-10 21:42:17 +09:00
ろむねこ
6841cdfa76
enhance(frontend): CWの注釈テキストが入力されていない場合はPostボタンを非アクティブに (#15639)
* add condition to disable post button when CW text is empty

* standardize condition by using 1<= inserted of 0<

* unify CW text length condition to improve readability

* add missing CW state check

* fix state check, add empty/null check, improve max length validation

* simplify CW validation by removing minimum length check

* Update CHANGELOG

* remove CW text validation in post()

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-03-10 10:35:37 +00:00
github-actions[bot]
794f360bc2 Bump version to 2025.3.2-alpha.5 2025-03-10 09:40:41 +00:00
かっこかり
f797765b1d
enhance(frontend): テーマ設定で簡易プレビューを表示するように (#15643)
* enhance(frontend): テーマ設定で簡易プレビューを表示するように

* Update Changelog

* fix lint

* 🎨

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-03-10 09:35:51 +00:00
syuilo
9dce512fbb enhance(frontend): add navbar transition animation 2025-03-10 15:47:00 +09:00
syuilo
9e91f85370 refactor(frontend): use Symbol for vue provide/inject 2025-03-10 15:08:40 +09:00
syuilo
9998cb84e8 refactor(frontend): page-metadata -> page 2025-03-10 13:47:38 +09:00
renovate[bot]
5ed1101bbd
chore(deps): update [root] update dependencies (#15624)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 12:30:37 +09:00
syuilo
6c9153300d chore(frontend): tweak lockdown setting 2025-03-10 12:03:54 +09:00
syuilo
7957ee5191 fix(frontend): rename pizzax fields 2025-03-10 11:28:54 +09:00
syuilo
b200743845 refactor(frontend): rename store.set -> store.commit 2025-03-10 11:27:07 +09:00
syuilo
08f7e7d9b3 refactor(frontend): rename pizzax fields 2025-03-10 10:51:54 +09:00
github-actions[bot]
16ad6b3f6c Bump version to 2025.3.2-alpha.4 2025-03-10 01:09:42 +00:00
syuilo
4df9083bf0 fix(frontend): テーマ切り替え時に一部の色が変わらない問題を修正 2025-03-10 10:05:50 +09:00
taichan
6419af2179
fix(frontend, dev): storybookのビルドエラー修正のため、as構文にリファクタ (#15640) 2025-03-10 09:34:45 +09:00
syuilo
d9858b03c9 enhance(frontend): improve plugin management 2025-03-10 09:28:07 +09:00
taichan
88efc0a3be
fix(dev): 検索インデックス対象ファイルでHMRが効かない問題を修正 (#15638) 2025-03-09 22:45:17 +00:00
github-actions[bot]
ac21fa7194 Bump version to 2025.3.2-alpha.3 2025-03-09 13:01:46 +00:00
syuilo
c76afce9a7 enhance(frontend): improve plugin management 2025-03-09 21:57:56 +09:00
github-actions[bot]
8e3304344f Bump version to 2025.3.2-alpha.2 2025-03-09 12:32:54 +00:00
饺子w (Yumechi)
db5c127cdd
fix(backend): fix handling of invalid urls in user profile (#15635)
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
2025-03-09 12:28:47 +00:00
syuilo
0402866b43 enhance(frontend): improve plugin management 2025-03-09 21:23:36 +09:00
syuilo
6cefabc6b6 chore(frontend): remove unused binding 2025-03-09 17:19:21 +09:00
syuilo
c9c04d8391 enhance(frontend): migrate overridedDeviceKind to preference 2025-03-09 17:14:48 +09:00
syuilo
27e8805dcb refactor(frontend): relocate plugin consts 2025-03-09 17:02:46 +09:00
github-actions[bot]
933abedc90 Bump version to 2025.3.2-alpha.1 2025-03-09 06:16:49 +00:00
syuilo
69eee9f050 enhance(frontend): ウィジェットもpreference管理に 2025-03-09 15:13:49 +09:00
syuilo
2918fb2609 refactor(frontend): relocate theme script 2025-03-09 14:32:29 +09:00
syuilo
fcd7fa62ba Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2025-03-09 14:28:06 +09:00
syuilo
be7e3b9a0c refactor(frontend): scripts -> utility 2025-03-09 14:28:01 +09:00
github-actions[bot]
06e7272ca1 Bump version to 2025.3.2-alpha.0 2025-03-09 05:22:26 +00:00
かっこかり
f35eb0f6d9
enhnace(frontend): 文字列比較のためのローマナイズを強化(設定の検索) (#15632)
* enhnace(frontend): 文字列比較のためのローマナイズを強化

* docs

* fix

* fix

* fix

* comment

* wanakanaの初回ロードをコンポーネント内に移動

* comment

* fix

* add tests

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-03-09 14:21:23 +09:00
syuilo
bdb74539d4 enhance(frontend): tweak settings page 2025-03-09 14:18:50 +09:00
syuilo
abc1e9168d refactor 2025-03-09 12:39:43 +09:00
syuilo
d30ddd4c2e
Refine preferences (#15597)
* wip

* wip

* wip

* test

* wip rollup pluginでsearchIndexの情報生成

* wip

* SPDX

* wip: markerIdを自動付与

* rollupでビルド時・devモード時に毎回uuidを生成するように

* 開発サーバーでだけ必要な挙動は開発サーバーのみで

* 条件が逆

* wip: childrenの生成

* update comment

* update comment

* rename auto generated file

* hashをパスと行数から決定

* Update privacy.vue

* Update privacy.vue

* wip

* Update general.vue

* Update general.vue

* wip

* wip

* Update SearchMarker.vue

* wip

* Update profile.vue

* Update mute-block.vue

* Update mute-block.vue

* Update general.vue

* Update general.vue

* childrenがduplicate key errorを吐く問題をいったん解決

* マーカーの形を成形

* loggerを置きかえ

* とりあえず省略記法に対応

* Refactor and Format codes

* wip

* Update settings-search-index.ts

* wip

* wip

* とりあえず不確定要因の仮置きidを削除

* hashの生成を正規化(絶対パスになっていたのを緩和)

* pathの入力を省略可能に

* adminでもパス生成できるように

* Update settings-search-index.ts

* Update privacy.vue

* wip

* build searchIndex

* wip

* build

* Update general.vue

* build

* Update sounds.vue

* build

* build

* Update sounds.vue

* 🎨

* 🎨

* Update privacy.vue

* Update privacy.vue

* Update security.vue

* create-search-indexを多少改善

* build

* Update 2fa.vue

* wip

* 必ずtransformCodeCacheを利用するように, キャッシュの明確な受け渡しを定義

* キャッシュはdevServerでなくても更新

* Revert "wip"

This reverts commit 41bffd3a13f55618bf939dc1c9acb2a77ead4054.

* inlining

* wip

* Update theme.vue

* 🎨

* wip normalize

* Update theme.vue

* キャッシュのパス変換

* build

* wip

* wip

* Update SearchMarker.vue

* i18n.ts['key'] の形式が取り出せない問題のFix

* build

* 仮でpath入れ

* 必ず絶対パスが使われるように

* wip

* 🎨

* storybookビルド時はcreateSearchIndexをしない

* inliningの構造化

* format code

* Update index.vue

* wip

* wip

* 🎨

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* clean up

* wip

* wip

* wip

* Update rollup-plugin-unwind-css-module-class-name.test.ts

* Update navbar.vue

* clean up

* wip

* wip

* wip

* wip

* wip

* Update preferences-backups.vue

* Update common.ts

* Update preferences.ts

* wip

* wip

* wip

* wip

* Update MkPreferenceContainer.vue

* Update MkPreferenceContainer.vue

* Update MkPreferenceContainer.vue

* enhance: 検索で上下矢印を使用することで検索結果を移動できるように

* Update main-boot.ts

* refactor

* wip

* Update sounds.vue

* fix(frontend): PageWindowでSearchMarkerが動作するように

* enhance(frontend): SearchMarkerの点滅を一定時間で止める

* wip

* lint fix

* fix: 子要素監視が抜けていたのを修正

* アニメーションの回数はCSSで制御するように

* refactor

* enhance(frontend): 検索インデックス作成時のログを削減

* revert

* fix

* fix

* Update preferences.ts

* Update preferences.ts

* wip

* Update preferences.ts

* wip

* 🎨

* wip

* Update MkPreferenceContainer.vue

* wip

* Update preferences.ts

* wip

* Update preferences.ts

* Update preferences.ts

* wip

* wip

* Update preferences.ts

* wip

* wip

* Update preferences.ts

* Update CHANGELOG.md

* Update preferences.ts

* Update deck-store.ts

* deckStoreをdefaultStoreに統合

* wip

* defaultStore -> store

* Update profile.ts

* wip

* refactor

* wip: plugin

* plugin

* plugin

* plugin

* Update plugin.ts

* wip

* Update plugin.vue

* Update preferences.ts

* Update main-boot.ts

* wip

* fix test

* Update plugin.vue

* Update plugin.vue

* Update utility.ts

* wip

* wip

* Update utility.ts

* wip

* wip

* clean up

* Update utility.ts

---------

Co-authored-by: tai-cha <dev@taichan.site>
Co-authored-by: taichan <40626578+tai-cha@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
2025-03-09 12:34:08 +09:00
github-actions[bot]
05cdc095c0 [skip ci] Update CHANGELOG.md (prepend template) 2025-03-09 03:30:00 +00:00
github-actions[bot]
7c1dc3d632 Release: 2025.3.1 2025-03-09 03:29:54 +00:00
github-actions[bot]
c53349c3b4 Bump version to 2025.3.1-beta.3 2025-03-09 00:33:40 +00:00
饺子w (Yumechi)
a710af54ed
fix(backend): fix ApPersonService unsound type cast (#15629)
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
2025-03-09 00:11:34 +00:00
Marie
add1c71786 chore: lint 2025-03-08 11:56:21 +00:00
Marie
91e15fafbf upd: confirm dialog for undoing follow request 2025-03-08 11:54:19 +00:00
Marie
19fc0a9351 fix: Confirm follow prompt showing up when cancelling follow request 2025-03-08 10:52:43 +00:00
github-actions[bot]
ac07bb8d92 Bump version to 2025.3.1-beta.2 2025-03-08 10:15:42 +00:00
かっこかり
698505030e
fix(test): fix federation test (#15630) 2025-03-08 19:11:09 +09:00
かっこかり
e16a14dcef
fix(deps): pnpm v10でre2のインストールに失敗することがある問題を修正 (#15627)
* fix(deps): pnpm v10でre2のインストールに失敗することがある問題を修正

* fix

* fix docker build

* fix build failure on Windows
2025-03-08 18:56:53 +09:00
github-actions[bot]
6d93725084 Bump version to 2025.3.1-beta.1 2025-03-08 01:03:17 +00:00
おさむのひと
cb9981d4eb
fix: Dockerのrunnerにpnpmのインストール手順が欠けていたのを修正 (#15623) 2025-03-08 10:02:15 +09:00
かっこかり
bee4db82bb
fix(backend): follow-up of #15620
Removes unnecessary arg `disableGlobbing` from chokidar FSWatcher, as it is no longer supports globging
2025-03-07 20:10:32 +09:00
renovate[bot]
d7706ef1b5
fix(deps): update [root] update dependencies (major) (#15620)
* fix(deps): update [root] update dependencies

* fix: migrate tar library

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
2025-03-07 19:42:39 +09:00
renovate[bot]
baf3f4a1d1
chore(deps): update [frontend] update dependencies to v10 (#15619)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-07 19:41:34 +09:00
renovate[bot]
c7a56c2c2b
fix(deps): update [root] update dependencies (#15543)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-07 19:12:50 +09:00
github-actions[bot]
8dfff79ca2 Bump version to 2025.3.1-beta.0 2025-03-07 07:07:13 +00:00
かっこかり
83c3bb839f
deps: update pnpm to v10 (#15588)
* Revert "fix(build): corepackのバグの回避 (#15387)"

This reverts commit 9c70a4e631.

* deps: update pnpm to v10

* fix broken lockfile

* update changelog

* fix

* fix

* Revert "fix"

This reverts commit 4abc6c194edc20989f5ec97d343307a4b8c9047d.

* fix

* fix

* attempt to fix docker build

* lint fixes

* fix: revertしすぎた

* detect pnpm version and install it

* fix: そもそもpnpmを2回入れる必要がないかも

* fix

* refactor

* fix

* refactor: remove unnecessary arg

* Update Dockerfile

* update pnpm to v10.6.1

* Update Changelog

* chore: use node to avoid installing jq
2025-03-07 07:03:52 +00:00
syuilo
a9fe7eff0a
New translations ja-jp.yml (Chinese Traditional) (#15618) 2025-03-07 16:01:32 +09:00
syuilo
d49ecab792
Update CHANGELOG.md 2025-03-07 14:46:10 +09:00
renovate[bot]
56459bbe68
chore(deps): update [tools] update dependencies (#15616)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-07 11:44:20 +09:00
renovate[bot]
6c150ef1fb
fix(deps): update [frontend] update dependencies (#15617)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-07 11:44:04 +09:00
syuilo
c78f45ea20
Update CHANGELOG.md 2025-03-07 09:12:18 +09:00
syuilo
82481c01e0 tweak MkDisableSection style 🎨 2025-03-07 09:11:51 +09:00
syuilo
741cbc34e6 Update CHANGELOG.md 2025-03-07 08:53:03 +09:00
github-actions[bot]
5e86550de3 Bump version to 2025.3.1-alpha.0 2025-03-06 23:51:21 +00:00
syuilo
92aef300ee
New Crowdin updates (#15611)
* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (Italian)
2025-03-07 08:50:54 +09:00
syuilo
9ce1b68fd7 Update CHANGELOG.md 2025-03-07 08:50:32 +09:00
饺子w (Yumechi)
5be5c8bec4
fix(backend): fixup migration for incorrect extraction on system accounts table (#15613)
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
2025-03-06 23:47:30 +00:00
syuilo
0214a0001f
feat(frontend): 設定の検索 (#15505)
* wip

* wip

* wip

* test

* wip rollup pluginでsearchIndexの情報生成

* wip

* SPDX

* wip: markerIdを自動付与

* rollupでビルド時・devモード時に毎回uuidを生成するように

* 開発サーバーでだけ必要な挙動は開発サーバーのみで

* 条件が逆

* wip: childrenの生成

* update comment

* update comment

* rename auto generated file

* hashをパスと行数から決定

* Update privacy.vue

* Update privacy.vue

* wip

* Update general.vue

* Update general.vue

* wip

* wip

* Update SearchMarker.vue

* wip

* Update profile.vue

* Update mute-block.vue

* Update mute-block.vue

* Update general.vue

* Update general.vue

* childrenがduplicate key errorを吐く問題をいったん解決

* マーカーの形を成形

* loggerを置きかえ

* とりあえず省略記法に対応

* Refactor and Format codes

* wip

* Update settings-search-index.ts

* wip

* wip

* とりあえず不確定要因の仮置きidを削除

* hashの生成を正規化(絶対パスになっていたのを緩和)

* pathの入力を省略可能に

* adminでもパス生成できるように

* Update settings-search-index.ts

* Update privacy.vue

* wip

* build searchIndex

* wip

* build

* Update general.vue

* build

* Update sounds.vue

* build

* build

* Update sounds.vue

* 🎨

* 🎨

* Update privacy.vue

* Update privacy.vue

* Update security.vue

* create-search-indexを多少改善

* build

* Update 2fa.vue

* wip

* 必ずtransformCodeCacheを利用するように, キャッシュの明確な受け渡しを定義

* キャッシュはdevServerでなくても更新

* Revert "wip"

This reverts commit 41bffd3a13f55618bf939dc1c9acb2a77ead4054.

* inlining

* wip

* Update theme.vue

* 🎨

* wip normalize

* Update theme.vue

* キャッシュのパス変換

* build

* wip

* wip

* Update SearchMarker.vue

* i18n.ts['key'] の形式が取り出せない問題のFix

* build

* 仮でpath入れ

* 必ず絶対パスが使われるように

* wip

* 🎨

* storybookビルド時はcreateSearchIndexをしない

* inliningの構造化

* format code

* Update index.vue

* wip

* wip

* 🎨

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* clean up

* Update navbar.vue

* enhance: 検索で上下矢印を使用することで検索結果を移動できるように

* refactor

* fix(frontend): PageWindowでSearchMarkerが動作するように

* enhance(frontend): SearchMarkerの点滅を一定時間で止める

* lint fix

* fix: 子要素監視が抜けていたのを修正

* アニメーションの回数はCSSで制御するように

* refactor

* enhance(frontend): 検索インデックス作成時のログを削減

* revert

* fix

* fix

---------

Co-authored-by: tai-cha <dev@taichan.site>
Co-authored-by: taichan <40626578+tai-cha@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
2025-03-06 23:15:19 +09:00
github-actions[bot]
46067f6e17 [skip ci] Update CHANGELOG.md (prepend template) 2025-03-06 10:31:36 +00:00
github-actions[bot]
2b71bdf114 Release: 2025.3.0 2025-03-06 10:31:30 +00:00
github-actions[bot]
9d6b521351 Bump version to 2025.3.0-beta.2 2025-03-06 08:19:56 +00:00
syuilo
ad708d896b
Merge pull request #15562 from misskey-dev/l10n_develop
New Crowdin updates
2025-03-06 17:06:09 +09:00
かっこかり
22228b6756
enhance: OAuth2 (IndieAuth) でロゴが提供されている場合は表示するように (#15578)
* enhance: OAuthでロゴが提供されている場合は表示するように

* Update Changelog

* refactor

* fix

* fix test
2025-03-06 08:05:14 +00:00
かっこかり
f7ea0c6991
fix(backend): S3互換オブジェクトストレージでファイルのアップロードに失敗することがある問題を修正 (#15583)
* fix(backend/object-storage): disable data integrity protections (MisskeyIO#895)

Cloudflare R2 does not support 'x-amz-checksum-*'

* Update Changelog

---------

Co-authored-by: あわわわとーにゅ <17376330+u1-liquid@users.noreply.github.com>
2025-03-06 08:03:57 +00:00
Sayamame-beans
60a3513cfc
enhance(frontend): invert how to show the number of attachments(remains) on postform (#15599)
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-03-06 07:45:46 +00:00
github-actions[bot]
377f002d68 Bump version to 2025.3.0-beta.1 2025-03-06 07:31:52 +00:00
syuilo
896bde1005 revert https://github.com/misskey-dev/misskey/pull/15545
see https://github.com/misskey-dev/misskey/issues/14498
2025-03-06 16:28:25 +09:00
かっこかり
6d0242277d
fix(frontend): tabler-iconsが読み込めない問題を修正(正式リリースに差し替え) (#15608) 2025-03-06 05:34:24 +00:00
renovate[bot]
60f90ca649
chore(deps): update [misskey-js] update dependencies (#15594)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-06 07:09:01 +09:00
renovate[bot]
f3be426383
fix(deps): update [frontend] update dependencies (#15595)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-05 21:01:44 +09:00
かっこかり
e8a6629cb5
fix(backend): システムアカウント系のマイグレーション不足を修正 (#15586)
* fix(backend): プロキシアカウントのロールバック用マイグレーションを追加

* fix

* separate newly-added `up` command

* drop backwards-compatibility

* docs
2025-03-05 16:49:49 +09:00
github-actions[bot]
44658ae981 Bump version to 2025.3.0-beta.0 2025-03-05 07:44:38 +00:00
syuilo
19384efbc5 clean up 2025-03-04 18:48:14 +09:00
かっこかり
adf22143aa
Revert "enhance(frontend): チャンネル投稿をユーザーページと前後ノートに表示する" (#15589)
* Revert "enhance(frontend): チャンネル投稿をユーザーページと前後ノートに表示する (#15532)"

This reverts commit a4711ab4c1.

* Update CHANGELOG.md
2025-03-03 21:05:50 +09:00
renovate[bot]
a17acf647b
fix(deps): update [frontend] update dependencies (#15587)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-03 17:48:17 +09:00
かっこかり
01a3eabc4e
enhance(frontend): アニメーション設定で画面上のエフェクトも考慮するように (#15576)
* enhance(frontend): アニメーション設定で画面上のエフェクトも考慮するように

* Update Changelog
2025-03-03 08:46:38 +00:00
かっこかり
59567a7ccc
fix(frontend): 照会処理を統一 (#15536)
* fix(frontend): 照会処理を統一

* fix

* doLookup -> apLookup
2025-03-03 08:45:04 +00:00
かっこかり
7fb8fccd57
Update CHANGELOG.md for #15532 2025-03-03 17:29:49 +09:00
鴇峰 朔華
a4711ab4c1
enhance(frontend): チャンネル投稿をユーザーページと前後ノートに表示する (#15532)
* enhance(frontend): ユーザーページで常にチャンネル投稿が含まれるように

* enhance(frontend): ノート詳細の前後の投稿にチャンネル投稿を含めるように

* ログイン有無の削除
2025-03-03 08:28:29 +00:00
かっこかり
bbe404a0b2
fix(frontend): 投稿フォームがオーバーフローした際にスクロールできるように (#15571)
* fix(frontend): 投稿フォームがオーバーフローした際にスクロールできるように

* Update Changelog

* remove unused props
2025-03-03 08:17:20 +00:00
かっこかり
0610bd657f
fix(frontend): フォローされたときのメッセージのshadowがちらつくことがある問題を修正 (#15584)
* fix(frontend): フォローされたときのメッセージがちらつく問題を修正

* Update Changelog
2025-03-03 08:09:41 +00:00
かっこかり
77667cf80d
enhance(frontend): モデレーターがセンシティブ設定を変更する際に確認ダイアログを出すように (#15462)
* enhance(frontend): モデレーターがセンシティブ設定を変更する際に確認ダイアログを出すように

* use MkSwitch

* Update Changelog
2025-03-03 08:06:34 +00:00
tetsuya-ki
801a2ec1db
fix(frontend): 削除して編集の削除タイミングを投稿後になるように #14498 (#15545)
* fix #14498

- 「削除して編集」の削除タイミングを投稿したタイミングへ変更

* update CHANGELOG.md

* 指摘対応

- InitialNoteがあれば必ず削除するべきものでもないため、投稿後にノートを削除するフラグをプロパティに追加

* 指摘対応のミス修正

- フラグを条件に追加
- 実績のdateが数値になってなかった点を修正

---------

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
2025-03-03 08:05:18 +00:00
github-actions[bot]
2a96e39bb3 Bump version to 2025.3.0-alpha.0 2025-03-02 12:12:06 +00:00
syuilo
616cccf251
enhance(backend): refine system account (#15530)
* wip

* wip

* wip

* Update SystemAccountService.ts

* Update 1740121393164-system-accounts.js

* Update DeleteAccountService.ts

* wip

* wip

* wip

* wip

* Update 1740121393164-system-accounts.js

* Update RepositoryModule.ts

* wip

* wip

* wip

* Update ApRendererService.ts

* wip

* wip

* Update SystemAccountService.ts

* fix tests

* fix tests

* fix tests

* fix tests

* fix tests

* fix tests

* add print logs

* ログが長すぎて出てないかもしれない

* fix migration

* refactor

* fix fed-tests

* Update RelayService.ts

* merge

* Update user.test.ts

* chore: emit log

* fix: tweak sleep duration

* fix: exit 1

* fix: wait for misskey processes to become healthy

* fix: longer sleep for user deletion

* fix: make sleep longer again

* デッドロック解消の試み

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

* Revert "デッドロック解消の試み"

This reverts commit 266141f66fb584371bbb56ef7eba04e14bcff94d.

* wip

* Update SystemAccountService.ts

---------

Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com>
Co-authored-by: zyoshoka <107108195+zyoshoka@users.noreply.github.com>
2025-03-02 20:06:20 +09:00
syuilo
7114523d84
Update CHANGELOG.md 2025-03-01 17:02:52 +09:00
syuilo
5d683728f3
デッドロック解消の試み (#15574)
https://github.com/misskey-dev/misskey/issues/15005

Co-authored-by: 饺子w (Yumechi) <35571479+eternal-flame-AD@users.noreply.github.com>
2025-03-01 16:12:42 +09:00
おさむのひと
b8632f389d
chore(ci): Renovateが作ったprにラベルつける (#15573) 2025-03-01 04:37:11 +00:00
renovate[bot]
830da5e9f1
fix(deps): update [frontend] update dependencies (#15566)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-01 13:11:09 +09:00
renovate[bot]
e2eddd5b1a
chore(deps): update actions/cache action to v4.2.2 (#15564)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-01 13:07:59 +09:00
renovate[bot]
d4f9bf1f11
chore(deps): update [misskey-js] update dependencies (#15565)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-01 13:07:47 +09:00
renovate[bot]
734c78ddd1
chore(deps): update [tools] update dependencies (#15563)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-01 13:07:36 +09:00
syuilo
c63c3462dd refactor 2025-02-28 09:34:21 +09:00
github-actions[bot]
a3bba23b7d [skip ci] Update CHANGELOG.md (prepend template) 2025-02-27 08:58:46 +00:00
github-actions[bot]
94a3e37ba8 Release: 2025.2.1 2025-02-27 08:58:40 +00:00
syuilo
cc09de7b27
New Crowdin updates (#15560)
* New translations ja-jp.yml (Russian)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Portuguese)

* New translations ja-jp.yml (Turkish)

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

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (Romanian)

* New translations ja-jp.yml (French)

* New translations ja-jp.yml (Spanish)

* New translations ja-jp.yml (Arabic)

* New translations ja-jp.yml (Czech)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Greek)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (Dutch)

* New translations ja-jp.yml (Norwegian)

* New translations ja-jp.yml (Polish)

* New translations ja-jp.yml (Slovak)

* New translations ja-jp.yml (Swedish)

* New translations ja-jp.yml (Ukrainian)

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

* New translations ja-jp.yml (Vietnamese)

* New translations ja-jp.yml (Indonesian)

* New translations ja-jp.yml (Bengali)

* New translations ja-jp.yml (Thai)

* New translations ja-jp.yml (Uzbek)

* New translations ja-jp.yml (Lao)

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

* New translations ja-jp.yml (Catalan)
2025-02-27 16:13:37 +09:00
かっこかり
da66079c29
enhance(frontend): ノート検索ページのデザイン調整 (#14780)
* enhance(frontend): 検索ページのホスト指定とユーザー指定を統合する (#273)

(cherry picked from commit c79392c88d6bf58ede39d8bba9ca2778c58521ef)

* fix

* 🎨

* Update Changelog

* Update Changelog

* refactor

---------

Co-authored-by: taiy <53635909+taiyme@users.noreply.github.com>
2025-02-27 02:56:17 +00:00
syuilo
ec83815227
fix(frontend): MkSelectの初期値が表示されない場合がある (#15559)
* fix

* Update CHANGELOG.md
2025-02-27 00:32:39 +00:00
PrivateGER
aa6bc9c9d0
linter fix 2025-02-26 12:13:13 +01:00
PrivateGER
15e9c0a576
Add warning about memory fragmentation 2025-02-26 12:04:38 +01:00
syuilo
6199139307
Update CHANGELOG.md 2025-02-26 16:30:25 +09:00
おさむのひと
15b0345335
enhance(frontend): コントロールパネルのユーザ検索で入力された情報をページ遷移で損なわないように (#15438)
* enhance(frontend): コントロールパネルのユーザ検索で入力された情報をページ遷移で損なわないように

* sessionStorageよりも更に短命な方法で持つように変更

* add comment

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-02-26 07:28:35 +00:00
かっこかり
28b40691d5
fix(frontend): リノート経由でノートの詳細情報を見るとき、クリップ一覧がappearNoteのものになるように (#15417)
* fix(frontend): リノート経由でノートの詳細情報を見るとき、クリップ一覧がappearNoteのものになるように

* Update Changelog

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-02-26 06:51:28 +00:00
syuilo
a778a63a12
New Crowdin updates (#15421)
* New translations ja-jp.yml (Spanish)

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

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

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

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)

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

* New translations ja-jp.yml (Korean)

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

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

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

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (German)

* New translations ja-jp.yml (Italian)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (English)

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Korean)

* New translations ja-jp.yml (Portuguese)

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

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (Italian)

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

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

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

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

* New translations ja-jp.yml (English)

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

* New translations ja-jp.yml (Catalan)

* New translations ja-jp.yml (Catalan)
2025-02-26 14:58:18 +09:00
github-actions[bot]
96fc7e307a Bump version to 2025.2.1-beta.2 2025-02-26 02:23:02 +00:00
Esurio/1673beta
bd13fb626c
fix(backend): S3_SAFEかつURL_SAFEでない文字列をprefixに使えないように (#15455)
* fix(backend): S3_SAFEかつURL_SAFEでない文字列をprefixに使えないように

* update CHANGELOG

* fix validation

* fix: remove unused import

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-02-26 01:56:23 +00:00
おさむのひと
d87488a5f0
fix(frontend): ユーザのサジェスト中に@を入力してもサジェスト結果が消えないように (#15435)
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-02-26 01:51:23 +00:00
おさむのひと
495db27433
fix(backend): カスタム絵文字の一括インポートをした時にHTTPプロキシの除外設定が効かないのを修正 (#15431)
* pxory

* fix

* fix CHANGELOG.md

* allow localAddress

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-02-26 01:48:38 +00:00
鴇峰 朔華
39c487e1d1
fix(backend): ローカル判定でisUriLocalを使用していない箇所を修正 (#15069)
* fix(backend): ローカル判定でisUriLocalを使用していない箇所を修正

* fix(test backend): RelayServiceでUtilityServiceを使う
2025-02-26 01:28:53 +00:00
かっこかり
b5799351d0
fix(backend): clips/updateのdescriptionで空文字を許容するように (#15429)
* fix(backend): clips/updateのdescriptionで空文字を許容するように

* Update Changelog

* fix: createの際も空文字を許容するように

* fix test

* fix test

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-02-26 01:27:38 +00:00
github-actions[bot]
7f31fd24b1 Bump version to 2025.2.1-beta.1 2025-02-26 00:47:08 +00:00
zyoshoka
389ec6350b
fix(backend): send Delete activity of a note to users who renoted or replied to it (#15554)
* fix(backend): send Delete activity of a note to users who renoted or replied to it

* Update CHANGELOG.md
2025-02-26 00:29:12 +00:00
PrivateGER
9ed9ed86af
override compression from env vars 2025-02-25 23:53:53 +01:00
PrivateGER
2b919c4eb0
Optionally enable websocket compression 2025-02-25 22:07:59 +01:00
syuilo
2b6638e160
feat: google analytics (#15451)
* wip backend

* wip frontend

* build misskey-js

* implement control panel

* fix

* introduce analytics wrapper

* spdx

* Update analytics.ts

* Update common.ts

* wip

* wip

* wip

* wip

* wip

* Update CHANGELOG.md

---------

Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
2025-02-25 11:51:23 +00:00
renovate[bot]
20cc6d3049
chore(config): migrate renovate config (#15550)
* chore(config): migrate config renovate.json5

* Update renovate.json5

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 14:24:34 +09:00
かっこかり
1b44954dcb
enhance(frontend): サーバーエラー画面の多言語対応 (#15549)
* enhance(frontend): サーバーエラー画面の多言語対応

* indent
2025-02-24 05:23:20 +00:00
renovate[bot]
5dc99e6f89
fix(deps): update [frontend] update dependencies (#15542)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 14:13:44 +09:00
renovate[bot]
d1504a5a83
fix(deps): update dependency shiki to v3 (#15544)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 14:07:32 +09:00
renovate[bot]
5a97f040c7
chore(deps): update actions/cache action to v4.2.1 (#15541)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 14:06:41 +09:00
renovate[bot]
0456c0f3c2
chore(deps): update [tools] update dependencies (#15540)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 14:06:30 +09:00
renovate[bot]
524adda2a6
chore(deps): update [misskey-js] update dependencies (#15539)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-24 14:06:17 +09:00
おさむのひと
426940bea7
2025.2.1-beta.0のlintがコケているのを修正 (#15546) 2025-02-23 21:21:58 +09:00
github-actions[bot]
9a619c621d Bump version to 2025.2.1-beta.0 2025-02-23 10:35:39 +00:00
饺子w (Yumechi)
25052164c0
Merge commit from fork
* fix(backend): Fix an issue where the origin of ActivityPub lookup response was not validated correctly.

[GHSA-6w2c-vf6f-xf26](https://github.com/misskey-dev/misskey/security/advisories/GHSA-6w2c-vf6f-xf26)

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>

* Enhance: Add configuration option to disable all external redirects when responding to an ActivityPub lookup (config.disallowExternalApRedirect)

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>

* fixup! fix(backend): Fix an issue where the origin of ActivityPub lookup response was not validated correctly.

* docs & one edge case

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>

* apply suggestions

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>

* remove stale frontend reference to _responseInvalidIdHostNotMatch

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>

* apply suggestions

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>

---------

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
2025-02-23 19:21:34 +09:00
Jacob Hall
21eff6df66
do not make a DM visible if user is mentioned but not a recipient 2025-02-21 13:33:36 -05:00
Jacob Hall
187c98e5ac
do not notify mentioned users if a DM is not visible to them 2025-02-20 15:09:48 -05:00
ikasoba
7c87dec6ee
ignore js-built (#15523) 2025-02-18 16:46:37 +09:00
syuilo
34f8345bc8 clean up dev logs 2025-02-17 14:38:15 +09:00
syuilo
93e7aad44e tweak error log 2025-02-17 13:34:17 +09:00
claustra01
9ffe504c7f
enhance(frontend): CWの注釈で入力済みの文字数を表示する (#15070)
* enhance: CW注釈の文字数表示

* update: CHANGELOG.md

* chore: maxCwTextLengthをただのconstにする

* fix: 投稿ボタンのdisable判定条件

---------

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
2025-02-16 10:34:50 +00:00
かっこかり
b965240da4
fix(deps): broken lockfile (#15508) 2025-02-16 19:08:48 +09:00
renovate[bot]
bacc212f81
fix(deps): update dependency bullmq to v5.41.1 (#15503)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-16 18:58:13 +09:00
github-actions[bot]
5991282e23 Bump version to 2025.2.1-alpha.0 2025-02-16 09:45:52 +00:00
鴇峰 朔華
f3a4434830
fix(backend): メールアドレスの形式が正しくなければ以降の処理を行わないように (#15320)
* Mod: バリデーションを追加

* 条件の修正

notつけわすれ

* Update CHANGELOG.md
2025-02-16 09:41:33 +00:00
renovate[bot]
e2a55e2a31
fix(deps): update [frontend] update dependencies (#15504)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-16 16:47:04 +09:00
renovate[bot]
05d41f2a7a
chore(deps): update [tools] update dependencies (#15498)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-16 11:57:41 +09:00
renovate[bot]
994f8b556d
fix(deps): update [frontend] update dependencies (major) (#15497)
* fix(deps): update [frontend] update dependencies

* remove uuid types (v11 is typescript)

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
2025-02-15 19:48:49 +09:00
かっこかり
88900492a4
fix(backend): pgroongaでの検索時にはじめのキーワード以外が検索に使用されない問題を修正 (#15496)
* fix pgroona note.text query

* Update Changelog

---------

Co-authored-by: Hazelnoot <acomputerdog@gmail.com>
2025-02-15 19:26:02 +09:00
かっこかり
9611bfbbf7
Update CHANGELOG.md 2025-02-15 17:28:22 +09:00
renovate[bot]
1c48d50bf2
fix(deps): update [backend] update dependencies (#15494)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com>
2025-02-15 17:02:11 +09:00
renovate[bot]
ab9b807cd2
fix(deps): update [root] update dependencies (#15495)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com>
2025-02-15 16:26:32 +09:00
renovate[bot]
c9ab7eab92
chore(deps): update [tools] update dependencies (#15493)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-15 15:46:12 +09:00
renovate[bot]
019f04292c
chore(deps): update [misskey-js] update dependencies (#15492)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-15 15:17:55 +09:00
renovate[bot]
8dc01e9421
chore(deps): update pnpm to v9.15.0 [security] (#15474)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-15 14:59:41 +09:00
renovate[bot]
280f465769
fix(deps): update [frontend] update dependencies (#15489)
* fix(deps): update [frontend] update dependencies

* fix type error

* fix

* Revert "fix"

This reverts commit de27d254f413b6938f7c42a5954c88da7da95b02.

* fix version

* attempt to fix test

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com>
Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
2025-02-15 14:54:45 +09:00
おさむのひと
57e86fe609
fix(frontend): カスタム絵文字管理画面(beta)にてisSensitive/localOnlyの絞り込みが上手くいかない問題の修正 (#15461)
Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
2025-02-15 04:01:51 +00:00
かっこかり
d8c4908aa5
enhance(frontend): リアクション時に確認ダイアログを出せるように (#15174)
* enhance(frontend): リアクション時に確認ダイアログを出せるように

* Update Changelog

* indent

* fix
2025-02-15 04:01:06 +00:00
renovate[bot]
208b201776
chore(deps): update [github actions] update dependencies (#15490)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-15 12:43:00 +09:00
renovate[bot]
4de33aca8c
chore(deps): update dependency vitest to v1.6.1 [security] (#15473)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-15 11:01:32 +09:00
renovate[bot]
49d7bc5faf
fix(deps): update dependency esbuild to v0.25.0 [security] (#15476)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-15 10:58:03 +09:00
renovate[bot]
6bb4669242
fix(deps): update dependency vite [security] (#15472)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-15 10:55:51 +09:00
renovate[bot]
5d82e1b2d0
fix(deps): update deps @fastify/multipart to v9.0.3 [security] (#15469)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-15 10:52:39 +09:00
syuilo
ffd8cf07e6
update deps (#15311)
* wip

* bump misskey-dev/eslint-plugin

* lint fixes (backend)

* lint fixes (frontend)

* lint fixes (frontend-embed)

* rollback nsfwjs to 4.2.0

ref: infinitered/nsfwjs#904

* rollback openapi-typescript to v6

v7でOpenAPIのバリデーションが入るようになった関係でスコープ外での変更が避けられないため一時的に戻した

* lint fixes (misskey-js)

* temporarily disable errored lint rule (frontend-shared)

* fix lint

* temporarily ignore errored file for lint (frontend-shared)

* rollback simplewebauthn/server to 12.0.0

v13 contains breaking changes that require some decision making

* lint fixes (frontend-shared)

* build misskey-js with types

* fix(backend): migrate simplewebauthn/server to v12

* fix(misskey-js/autogen): ignore indent rules to generate consistent output

* attempt to fix test

changes due to capricorn86/happy-dom#1617 (XMLSerializer now produces valid XML)

* attempt to fix test

changes due to capricorn86/happy-dom#1617 (XMLSerializer now produces valid XML)

* fix test

* fix test

* fix test

* Apply suggestions from code review

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

* bump summaly to v5.2.0

* update tabler-icons to v3.30.0-based

---------

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Co-authored-by: anatawa12 <anatawa12@icloud.com>
2025-02-15 10:24:22 +09:00
ikasoba
1e88aa9d81
fix(frontend): Play の再読込時に UI が以前の状態を引き継いでしまう問題を修正 (#15479)
* fix

* update change log
2025-02-14 03:42:21 +00:00
renovate[bot]
d893fbc5af
chore: Configure Renovate (#15468)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com>
2025-02-14 07:31:28 +09:00
おさむのひと
4d562e7439
enhance(frontend): ノートに埋め込まれたメディアのコンテキストメニューから管理者用のファイル管理画面を開けるように (#15460)
* enhance(frontend): ノートに埋め込まれたメディアのコンテキストメニューから管理者用のファイル管理画面を開けるように

* fix icon

* fix menu

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-02-13 11:09:04 +00:00
syuilo
30df768d26 Update about-misskey.vue 2025-02-12 20:55:12 +09:00
Esurio/1673beta
ebd06becbf
fix(backend): オブジェクトストレージの設定でPrefixを設定していなかった場合、nullが文字列として展開・ドメインの1つ後ろに'/'が挿入されないように (#15432) 2025-02-11 11:45:31 +00:00
かっこかり
cf35208777
fix(frontend-test): Update url-preview.test.ts 2025-02-11 12:49:22 +09:00
かっこかり
d1eddf0d88
fix(frontend): 埋め込みiframeから外部ページに移動できない問題を修正 (#15453)
* fix(frontend): 埋め込みiframeから外部ページに移動できない問題を修正

* Update Changelog
2025-02-11 03:33:15 +00:00
かっこかり
d5ad953c9e
Update CHANGELOG.md (入れる場所が違うのを修正) 2025-02-11 11:23:39 +09:00
lqvp
e339293673
feat: アクセストークン発行時に通知するように (#15422)
* feat: アクセストークン発行時に通知するように (misskey-dev/misskey#13353)

* fix: 不要な翻訳を削除/インデントを揃えるように

* chore(backend): 不要なawaitを削除

* chore: changelogへ追加
2025-02-11 01:15:33 +00:00
おさむのひと
a1ca68aadd
fix(frontend): コンディショナルロールを手動で割り当てできる導線を削除 (#15436)
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-02-11 01:10:05 +00:00
おさむのひと
420365c17f
enhance(frontend): 開発者モードでメニューからファイルIDをコピー出来るようにする (#15444) 2025-02-10 08:20:38 +00:00
zyoshoka
dc608aada0
fix(backend): correct admin/meta response schema (#15434) 2025-02-09 07:17:48 +00:00
Esurio/1673beta
231c2c2e54
fix(backend): following/invalidateでフォロワーを解除しようとしているユーザーの情報を返すように (#15430) 2025-02-08 12:51:30 +00:00
taichan
2f8d02024a
feat(frontend): 画像を投稿前にプレビュー可能に (#15341)
* feat(client): 画像をプレビュー可能に

* Update Changelog

* SPDX

* 消えてたのFix

* Add storybook for MkImgPreviewDialog

* backgroundのスタイル変更

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

* Add MkImgPreviewDialog to storybook generator

* Update packages/frontend/.storybook/generate.tsx

---------

Co-authored-by: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com>
2025-02-08 08:33:09 +00:00
かっこかり
4b98b446be
enhance(frontend): クライアントエラー画面の多言語対応 (#15411)
* enhance(frontend): クライアントエラー画面のマルチリンガル対応

* Update Changelog

* update message
2025-02-08 08:31:28 +00:00
Esurio/1673beta
026ec40b3b
fix(dev): devcontainerのcorepackのバージョンを指定するように (#15415) 2025-02-08 08:29:51 +00:00
zyoshoka
54fc232a23
fix(backend): use unique operationId in the OpenAPI schema (#15420)
* fix(backend): use unique `operationId` in the OpenAPI schema

* fix: read with UTF-8 encoding
2025-02-08 08:29:24 +00:00
おさむのひと
a3cc865e11
fix(ci): oktetoの導線を削除 (#15427) 2025-02-08 08:28:05 +00:00
zyoshoka
d7b443d1f0
chore: update .swcrc schema link (#15428) 2025-02-08 17:21:32 +09:00
anatawa12
607bf60007
enhance(frontend): アンテナ、リスト等の名前をdeckのカラム名のデフォルト値にするように (#13992)
* refactor: remove type errors from deck.vue and deck-store.ts

* feat: アンテナ、リスト等の名前をカラム名のデフォルト値にするように

* docs: アンテナ、リスト等の名前をカラム名のデフォルト値にするように

* lint: fix

* chore: カラム名が指定されている場合にはチャンネル名を取得しないように

* chore: チャンネルについては投稿でも使用されてる channel 変数を使用するように

* docs: fix changelog

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
Co-authored-by: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>
Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
2025-02-07 06:57:14 +00:00
かっこかり
d008394eb7
enhance(frontend): PostFormのannoying判定でCWを考慮するように (#15405)
* enhance(frontend): PostFormのannoying判定でCWを考慮するように

* Update Changelog

* Update CHANGELOG.md
2025-02-07 06:54:52 +00:00
Esurio/1673beta
47a76bbc4c
fix: swcのjson-schemaのurlを変更 (#15409)
Co-authored-by: Esurio <esurio@esurio1673.net>
2025-02-07 02:36:58 +00:00
syuilo
cfb61289a9
refactor(frontend): remove X theme properties (#15376)
* refactor(frontend): remove X theme properties

* Update MkAutocomplete.vue

* Update WidgetCalendar.vue
2025-02-05 11:17:48 +00:00
かっこかり
c548ec9906
refactor(frontend): verbatimModuleSyntaxを有効化 (#15323)
* wip

* wip

* wip

* wip

* revert unnecessary changes

* wip

* refactor(frontend): enforce verbatimModuleSyntax

* fix

* refactor(frontend-shared): enforce verbatimModuleSyntax

* wip

* refactor(frontend-embed): enforce verbatimModuleSyntax

* enforce consistent-type-imports

* fix lint config

* attemt to fix ci

* fix lint

* fix

* fix

* fix
2025-02-05 10:01:44 +00:00
github-actions[bot]
c634ae37e5 [skip ci] Update CHANGELOG.md (prepend template) 2025-02-05 08:58:47 +00:00
1366 changed files with 43010 additions and 37283 deletions

View file

@ -1,13 +1,92 @@
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Misskey configuration
# Sharkey configuration
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# ┌──────────────────────────────┐
#───┘ a boring but important thing └────────────────────────────
#
# First of all, let me tell you a story that may possibly be
# boring to you and possibly important to you.
#
# Sharkey is licensed under the AGPLv3 license. This license is
# known to be often misunderstood. Please read the following
# instructions carefully and select the appropriate option so
# that you do not negligently cause a license violation.
#
# --------
# Option 1: If you host Sharkey AS-IS (without any changes to
# the source code. forks are not included).
#
# Step 1: Congratulations! You don't need to do anything.
# --------
# Option 2: If you have made changes to the source code (forks
# are included) and publish a Git repository of source
# code. There should be no access restrictions on
# this repository. Strictly speaking, it doesn't have
# to be a Git repository, but you'll probably use Git!
#
# Step 1: Build and run the Sharkey server first.
# Step 2: Open <https://your.sharkey.example/admin/settings> in
# your browser with the administrator account.
# Step 3: Enter the URL of your Git repository in the
# "Repository URL" field.
# --------
# Option 3: If neither of the above applies to you.
# (In this case, the source code should be published
# on the Sharkey interface. IT IS NOT ENOUGH TO
# DISCLOSE THE SOURCE CODE WHEN A USER REQUESTS IT BY
# E-MAIL OR OTHER MEANS. If you are not satisfied
# with this, it is recommended that you read the
# license again carefully. Anyway, enabling this
# option will automatically generate and publish a
# tarball at build time, protecting you from
# inadvertent license violations. (There is no legal
# guarantee, of course.) The tarball will generated
# from the root directory of your codebase. So it is
# also recommended to check <built/tarball> directory
# once after building and before activating the server
# to avoid ACCIDENTAL LEAKING OF SENSITIVE INFORMATION.
# To prevent certain files from being included in the
# tarball, add a glob pattern after line 15 in
# <scripts/tarball.mjs>. DO NOT FORGET TO BUILD AFTER
# ENABLING THIS OPTION!)
#
# Step 1: Uncomment the following line.
#
# publishTarballInsteadOfProvideRepositoryUrl: true
# ┌────────────────────────┐
#───┘ Initial Setup Password └─────────────────────────────────────────────────────
# Password to initiate setting up admin account.
# It will not be used after the initial setup is complete.
#
# Be sure to change this when you set up Sharkey via the Internet.
#
# The provider of the service who sets up Sharkey on behalf of the customer should
# set this value to something unique when generating the Sharkey config file,
# and provide it to the customer.
#
# setupPassword: example_password_please_change_this_or_you_will_get_hacked
# ┌─────┐
#───┘ URL └─────────────────────────────────────────────────────
# Final accessible URL seen by a user.
url: http://misskey.local
# Other public URLs that are served by this instance.
# If you've migrated to a new domain using an existing database, then add your previous URL here to continue serving those posts and profiles via federation.
# Requires reverse-proxy configuration to forward requests with HOST header preserved.
# For advanced usage only!
#altUrls:
# - https://example.com/
# - https://legacy.tld/
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
# URL SETTINGS AFTER THAT!
@ -15,11 +94,11 @@ url: http://misskey.local
#───┘ Port and TLS settings └───────────────────────────────────
#
# Misskey requires a reverse proxy to support HTTPS connections.
# Sharkey requires a reverse proxy to support HTTPS connections.
#
# +----- https://example.tld/ ------------+
# +------+ |+-------------+ +----------------+|
# | User | ---> || Proxy (443) | ---> | Misskey (3000) ||
# | User | ---> || Proxy (443) | ---> | Sharkey (3000) ||
# +------+ |+-------------+ +----------------+|
# +---------------------------------------+
#
@ -27,7 +106,7 @@ url: http://misskey.local
# An encrypted connection with HTTPS is highly recommended
# because tokens may be transferred in GET requests.
# The port that your Misskey server should listen on.
# The port that your Sharkey server should listen on.
port: 3000
# ┌──────────────────────────┐
@ -232,7 +311,7 @@ proxyRemoteFiles: true
# Movie Thumbnail Generation URL
# There is no reference implementation.
# For example, Misskey will point to the following URL:
# For example, Sharkey will point to the following URL:
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
#videoThumbnailGenerator: https://example.com
@ -243,8 +322,6 @@ signToActivityPubGet: true
# When using authorized fetch, this is often undesired as any signed activity can be forwarded to a blocked instance by relays and other instances.
# This setting allows admins to disable LD signatures for increased privacy, at the expense of fewer relayed activities and additional inbound fetch (GET) requests.
attachLdSignatureForRelays: true
# check that inbound ActivityPub GET requests are signed ("authorized fetch")
checkActivityPubGetSignature: false
# For security reasons, uploading attachments from the intranet is prohibited,
# but exceptions can be made from the following settings. Default value is "undefined".
@ -255,6 +332,11 @@ checkActivityPubGetSignature: false
#customMOTD: ['Hello World', 'The sharks rule all', 'Shonks']
# Disable automatic redirect for ActivityPub object lookup. (default: false)
# This is a strong defense against potential impersonation attacks if the viewer instance has inadequate validation.
# However it will make it impossible for other instances to lookup third-party user and notes through your URL.
#disallowExternalApRedirect: true
# Upload or download file size limits (bytes)
#maxFileSize: 262144000

View file

@ -21,6 +21,14 @@ setupPassword: example_password_please_change_this_or_you_will_get_hacked
# Final accessible URL seen by a user.
url: 'http://misskey.local'
# Other public URLs that are served by this instance.
# If you've migrated to a new domain using an existing database, then add your previous URL here to continue serving those posts and profiles via federation.
# Requires reverse-proxy configuration to forward requests with HOST header preserved.
# For advanced usage only!
#altUrls:
# - https://example.com/
# - https://legacy.tld/
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
# URL SETTINGS AFTER THAT!
@ -197,6 +205,11 @@ id: 'aidx'
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
#sentryForFrontend:
# vueIntegration:
# tracingOptions:
# trackComponents: true
# browserTracingIntegration:
# replayIntegration:
# options:
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
@ -265,6 +278,11 @@ allowedPrivateNetworks: [
'127.0.0.1/32'
]
# Disable automatic redirect for ActivityPub object lookup. (default: false)
# This is a strong defense against potential impersonation attacks if the viewer instance has inadequate validation.
# However it will make it impossible for other instances to lookup third-party user and notes through your URL.
#disallowExternalApRedirect: true
# Upload or download file size limits (bytes)
#maxFileSize: 262144000

View file

@ -1,5 +1,5 @@
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Misskey configuration
# Sharkey configuration
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# ┌──────────────────────────────┐
@ -9,14 +9,14 @@
# First of all, let me tell you a story that may possibly be
# boring to you and possibly important to you.
#
# Misskey is licensed under the AGPLv3 license. This license is
# Sharkey is licensed under the AGPLv3 license. This license is
# known to be often misunderstood. Please read the following
# instructions carefully and select the appropriate option so
# that you do not negligently cause a license violation.
#
# --------
# Option 1: If you host Misskey AS-IS (without any changes to
# Option 1: If you host Sharkey AS-IS (without any changes to
# the source code. forks are not included).
#
# Step 1: Congratulations! You don't need to do anything.
@ -28,8 +28,8 @@
# this repository. Strictly speaking, it doesn't have
# to be a Git repository, but you'll probably use Git!
#
# Step 1: Build and run the Misskey server first.
# Step 2: Open <https://your.misskey.example/admin/settings> in
# Step 1: Build and run the Sharkey server first.
# Step 2: Open <https://your.sharkey.example/admin/settings> in
# your browser with the administrator account.
# Step 3: Enter the URL of your Git repository in the
# "Repository URL" field.
@ -37,7 +37,7 @@
# --------
# Option 3: If neither of the above applies to you.
# (In this case, the source code should be published
# on the Misskey interface. IT IS NOT ENOUGH TO
# on the Sharkey interface. IT IS NOT ENOUGH TO
# DISCLOSE THE SOURCE CODE WHEN A USER REQUESTS IT BY
# E-MAIL OR OTHER MEANS. If you are not satisfied
# with this, it is recommended that you read the
@ -66,6 +66,14 @@
# You can set url from an environment variable instead.
url: https://example.tld/
# Other public URLs that are served by this instance.
# If you've migrated to a new domain using an existing database, then add your previous URL here to continue serving those posts and profiles via federation.
# Requires reverse-proxy configuration to forward requests with HOST header preserved.
# For advanced usage only!
#altUrls:
# - https://example.com/
# - https://legacy.tld/
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
# URL SETTINGS AFTER THAT!
@ -73,11 +81,11 @@ url: https://example.tld/
#───┘ Port and TLS settings └───────────────────────────────────
#
# Misskey requires a reverse proxy to support HTTPS connections.
# Sharkey requires a reverse proxy to support HTTPS connections.
#
# +----- https://example.tld/ ------------+
# +------+ |+-------------+ +----------------+|
# | User | ---> || Proxy (443) | ---> | Misskey (3000) ||
# | User | ---> || Proxy (443) | ---> | Sharkey (3000) ||
# +------+ |+-------------+ +----------------+|
# +---------------------------------------+
#
@ -85,7 +93,7 @@ url: https://example.tld/
# An encrypted connection with HTTPS is highly recommended
# because tokens may be transferred in GET requests.
# The port that your Misskey server should listen on.
# The port that your Sharkey server should listen on.
port: 3000
# ┌──────────────────────────┐
@ -244,6 +252,11 @@ id: 'aidx'
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
#sentryForFrontend:
# vueIntegration:
# tracingOptions:
# trackComponents: true
# browserTracingIntegration:
# replayIntegration:
# options:
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
@ -326,8 +339,6 @@ signToActivityPubGet: true
# When using authorized fetch, this is often undesired as any signed activity can be forwarded to a blocked instance by relays and other instances.
# This setting allows admins to disable LD signatures for increased privacy, at the expense of fewer relayed activities and additional inbound fetch (GET) requests.
attachLdSignatureForRelays: true
# check that inbound ActivityPub GET requests are signed ("authorized fetch")
checkActivityPubGetSignature: false
# For security reasons, uploading attachments from the intranet is prohibited,
# but exceptions can be made from the following settings. Default value is "undefined".
@ -338,6 +349,11 @@ checkActivityPubGetSignature: false
#customMOTD: ['Hello World', 'The sharks rule all', 'Shonks']
# Disable automatic redirect for ActivityPub object lookup. (default: false)
# This is a strong defense against potential impersonation attacks if the viewer instance has inadequate validation.
# However it will make it impossible for other instances to lookup third-party user and notes through your URL.
#disallowExternalApRedirect: true
# Upload or download file size limits (bytes)
#maxFileSize: 262144000

View file

@ -1,5 +1,5 @@
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Misskey configuration
# Sharkey configuration
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# ┌──────────────────────────────┐
@ -9,14 +9,14 @@
# First of all, let me tell you a story that may possibly be
# boring to you and possibly important to you.
#
# Misskey is licensed under the AGPLv3 license. This license is
# Sharkey is licensed under the AGPLv3 license. This license is
# known to be often misunderstood. Please read the following
# instructions carefully and select the appropriate option so
# that you do not negligently cause a license violation.
#
# --------
# Option 1: If you host Misskey AS-IS (without any changes to
# Option 1: If you host Sharkey AS-IS (without any changes to
# the source code. forks are not included).
#
# Step 1: Congratulations! You don't need to do anything.
@ -28,8 +28,8 @@
# this repository. Strictly speaking, it doesn't have
# to be a Git repository, but you'll probably use Git!
#
# Step 1: Build and run the Misskey server first.
# Step 2: Open <https://your.misskey.example/admin/settings> in
# Step 1: Build and run the Sharkey server first.
# Step 2: Open <https://your.sharkey.example/admin/settings> in
# your browser with the administrator account.
# Step 3: Enter the URL of your Git repository in the
# "Repository URL" field.
@ -37,7 +37,7 @@
# --------
# Option 3: If neither of the above applies to you.
# (In this case, the source code should be published
# on the Misskey interface. IT IS NOT ENOUGH TO
# on the Sharkey interface. IT IS NOT ENOUGH TO
# DISCLOSE THE SOURCE CODE WHEN A USER REQUESTS IT BY
# E-MAIL OR OTHER MEANS. If you are not satisfied
# with this, it is recommended that you read the
@ -65,10 +65,10 @@
# Password to initiate setting up admin account.
# It will not be used after the initial setup is complete.
#
# Be sure to change this when you set up Misskey via the Internet.
# Be sure to change this when you set up Sharkey via the Internet.
#
# The provider of the service who sets up Misskey on behalf of the customer should
# set this value to something unique when generating the Misskey config file,
# The provider of the service who sets up Sharkey on behalf of the customer should
# set this value to something unique when generating the Sharkey config file,
# and provide it to the customer.
#
# setupPassword: example_password_please_change_this_or_you_will_get_hacked
@ -79,6 +79,14 @@
# Final accessible URL seen by a user.
url: https://example.tld/
# Other public URLs that are served by this instance.
# If you've migrated to a new domain using an existing database, then add your previous URL here to continue serving those posts and profiles via federation.
# Requires reverse-proxy configuration to forward requests with HOST header preserved.
# For advanced usage only!
#altUrls:
# - https://example.com/
# - https://legacy.tld/
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
# URL SETTINGS AFTER THAT!
@ -86,11 +94,11 @@ url: https://example.tld/
#───┘ Port and TLS settings └───────────────────────────────────
#
# Misskey requires a reverse proxy to support HTTPS connections.
# Sharkey requires a reverse proxy to support HTTPS connections.
#
# +----- https://example.tld/ ------------+
# +------+ |+-------------+ +----------------+|
# | User | ---> || Proxy (443) | ---> | Misskey (3000) ||
# | User | ---> || Proxy (443) | ---> | Sharkey (3000) ||
# +------+ |+-------------+ +----------------+|
# +---------------------------------------+
#
@ -98,13 +106,13 @@ url: https://example.tld/
# An encrypted connection with HTTPS is highly recommended
# because tokens may be transferred in GET requests.
# The port that your Misskey server should listen on.
# The port that your Sharkey server should listen on.
port: 3000
# the address to bind to, defaults to "every address"
# address: '0.0.0.0'
# You can also use UNIX domain socket.
# socket: /path/to/misskey.sock
# socket: /path/to/sharkey.sock
# chmodSocket: '777'
# ┌──────────────────────────┐
@ -284,6 +292,11 @@ id: 'aidx'
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
#sentryForFrontend:
# vueIntegration:
# tracingOptions:
# trackComponents: true
# browserTracingIntegration:
# replayIntegration:
# options:
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
@ -358,7 +371,7 @@ proxyRemoteFiles: true
# Movie Thumbnail Generation URL
# There is no reference implementation.
# For example, Misskey will point to the following URL:
# For example, Sharkey will point to the following URL:
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
#videoThumbnailGenerator: https://example.com
@ -369,8 +382,6 @@ signToActivityPubGet: true
# When using authorized fetch, this is often undesired as any signed activity can be forwarded to a blocked instance by relays and other instances.
# This setting allows admins to disable LD signatures for increased privacy, at the expense of fewer relayed activities and additional inbound fetch (GET) requests.
attachLdSignatureForRelays: true
# check that inbound ActivityPub GET requests are signed ("authorized fetch")
checkActivityPubGetSignature: false
# For security reasons, uploading attachments from the intranet is prohibited,
# but exceptions can be made from the following settings. Default value is "undefined".
@ -381,6 +392,11 @@ checkActivityPubGetSignature: false
#customMOTD: ['Hello World', 'The sharks rule all', 'Shonks']
# Disable automatic redirect for ActivityPub object lookup. (default: false)
# This is a strong defense against potential impersonation attacks if the viewer instance has inadequate validation.
# However it will make it impossible for other instances to lookup third-party user and notes through your URL.
#disallowExternalApRedirect: true
# Upload or download file size limits (bytes)
#maxFileSize: 262144000
@ -421,3 +437,9 @@ checkActivityPubGetSignature: false
# How long to save each log entry before deleting it.
# Default: 2592000000 (1 week)
#maxAge: 2592000000
# Transparently compress every websocket message on clients that support it.
# Trades server CPU usage for reduced bandwidth usage and a faster frontend on the client.
# If you're not using jemalloc, this may cause memory fragmentation and performance issues! (https://www.npmjs.com/package/ws#websocket-compression)
# jemalloc is used by default in the Sharkey Docker image and may be set up manually otherwise: https://github.com/jemalloc/jemalloc/wiki/getting-started
websocketCompression: false

View file

@ -7,7 +7,9 @@
"ghcr.io/devcontainers/features/node:1": {
"version": "22.11.0"
},
"ghcr.io/devcontainers-contrib/features/corepack:1": {}
"ghcr.io/devcontainers-extra/features/pnpm:2": {
"version": "10.6.1"
}
},
"forwardPorts": [3000],
"postCreateCommand": "/bin/bash .devcontainer/init.sh",

View file

@ -152,6 +152,11 @@ id: 'aidx'
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
#sentryForFrontend:
# vueIntegration:
# tracingOptions:
# trackComponents: true
# browserTracingIntegration:
# replayIntegration:
# options:
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'

View file

@ -7,8 +7,6 @@ sudo apt-get update
sudo apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb
git config --global --add safe.directory /workspace
git submodule update --init
corepack install
corepack enable
pnpm config set store-dir /home/node/.local/share/pnpm/store
pnpm install --frozen-lockfile
cp .devcontainer/devcontainer.yml .config/default.yml

2
.npmrc
View file

@ -1,2 +1,4 @@
@transfem-org:registry=https://activitypub.software/api/v4/packages/npm/
engine-strict = true
save-exact = true
shell-emulator = true

View file

@ -1,3 +1,155 @@
## 2025.4.0
### General
- Feat: チャットがリニューアルして復活しました(beta)
- 既存のDM機能よりも便利で効率的な実装になっています
- チャットを受け付ける相手を制限可能です
- 誰でも / フォローユーザーのみ / フォロワーのみ / 相互のみ / 受け付けない から選択できます
- 自分からメッセージを送った相手とは上記の設定に関わらずチャット可能です
- チャット機能を開放するかどうかをロールで制御可能です
- ルームを作成して、複数人でのチャットも可能です
- 過去自分が送ったメッセージ・自分に送られたメッセージの検索が可能です
- 参加中のルームをミュートして通知が来ないように設定可能です
- メッセージにはリアクションも可能です
- Feat: アカウントのマイグレーション時に古いアカウントからロールをコピーできるようになりました。
- 管理者がロールの設定でマイグレーション時にコピーするかを指定できるようになります。
- Enhance: セキュリティを強化するため、ジョブキューのダッシュボード(bull-board)統合が削除されました。
- Misskeyネイティブでダッシュボードを実装予定です
- Enhance: フロントエンドのエラートラッキングができるように
- `.config/default.yml`中の項目`sentryForFrontend`を適宜設定してください。
- 外部サービスであるSentryへエラー情報が送信されます。ご利用の地域の法令に従い、適切なプライバシーポリシーを策定の上で運用してください。
- Enhance: ミュートしているユーザーをユーザー検索の結果から除外するように
- Enhance: アンテナでセンシティブなチャンネルのノートを除外できるように `#14177`
- Fix: 通知のページネーションで2つ以上読み込めなくなることがある問題を修正
### Client
- Feat: 設定の管理が強化されました
- 内部処理が一新され、安定性とパフォーマンスが向上しました
- 全てのクライアント設定がエクスポート(バックアップ)/インポート対象に含まれるようになりました
- プラグイン、テーマ、クライアントに追加されたすべてのアカウント情報も含まれるようになりました
- 自動で設定データをサーバーにバックアップできるように
- 設定→設定のプロファイル→自動バックアップ で有効にできます
- 新しいデバイスからログインしたり、ブラウザから設定データが消えてしまったときに自動で復元されます(復元をスキップすることも可能)
- 任意の設定項目をデバイス間で同期できるように
- 設定項目の「...」メニュー→「デバイス間で同期」
- 同期をオンにした際にサーバーに保存された値とローカルの値が競合する場合はどちらを優先するか選択できます
- 任意の設定項目を初期値にリセットできるように
- 設定項目の「...」メニュー→「初期値にリセット」
- アカウントごとに設定値が分離される設定とそうでないクライアント設定が混在していた(かつ分離するかどうかを設定不可だった)のを、基本的に一律でクライアント全体に適用されるようにし、個別でアカウントごとに異なる設定を行えるように
- 設定項目の「...」メニュー→「アカウントで上書き」をオンにすることで、設定値をそのアカウントでだけ適用するようにできます
- ログアウトすると設定データもブラウザから消去されるようになりプライバシーが向上しました
- 再度ログインすればサーバーのバックアップから設定データを復元可能です
- エクスポートした設定データを他のサーバーでインポートして適用すること(設定の持ち運び)が可能になりました
- 設定情報の移行は自動で行われますが、何らかの理由で失敗した場合、設定→その他→旧設定情報を移行 で再試行可能です
- Feat: 画面を重ねて表示するオプションを実装(実験的)
- 設定 → その他 → 実験的機能 → Enable stacking router view
- Enhance: プラグインの管理が強化されました
- インストール/アンインストール/設定の変更時にリロード不要になりました
- Enhance: ログアウト時、ブラウザに保存されたWebクライアントのデータを全て消去するように
- Enhance: デッキUIでカラム間のマージンを設定できるように
- Enhance: デッキUIでデッキメニューの位置を設定できるように
- Enhance: デッキUIでナビゲーションバーの位置を設定できるように
- Enhance: アイコンのスクロール追従を無効化してパフォーマンス向上できるように
- Enhance: CWの注釈テキストが入力されていない場合, Postボタンを非アクティブに
- Enhance: CWを無効にした場合, 注釈テキストが最大入力文字数を超えていても投稿できるように
- Enhance: テーマ設定画面のデザインを改善
- Enhance: 投稿フォームの設定メニューを改良
- 投稿フォームをリセットできるように
- 文字数カウントを復活
- Enhance: 2段階認証時のリカバリーコードのファイル名にサーバーURLを含めるように
- Enhance: 全体的なブラッシュアップ
- Enhance 全体的なパフォーマンス向上
- Fix: 読み込み直後にスクロールしようとすると途中で止まる場合があるのを修正
- Fix: テーマ切り替え時に一部の色が変わらない問題を修正
- NOTE: 構造上クラシックUIを新しいデザインシステムに移行することが困難なため、クラシックUIが削除されました
- デッキUIでカラムを中央寄せにし、メインカラムの左右にウィジェットカラムを配置し、ナビゲーションバーを上部に表示することである程度クラシックUIを再現できます
- Fix: iPadOSでdeck uiをマウスカーソルによってスクロールできない問題を修正
### Server
- Enhance 全体的なパフォーマンス向上
- Fix: プロフィール追加情報で無効なURLに入力された場合に照会エラーを出るのを修正
- Fix: ActivityPubリクエストURLチェック実装は仕様に従っていないのを修正
- Fix: 連合無しモードでも外部から照会可能だった問題を修正
- Fix: テスト用WebHookのペイロードの`emojis`パラメータが実際のものと異なる問題を修正
- Fix: 非ログインでタイムラインのストリームに接続した際、表示にログイン必須のノートが流れる場合がある問題を修正
## 2025.3.1
### General
- pnpmをv10に更新
- Corepackを削除
### Client
- Feat: 設定の検索を追加(実験的)
- Enhance: 設定項目の再配置
### Server
- Fix: DBマイグレーション際にシステムアカウントのユーザーID判定が正しくない問題を修正
- Fix: user.featured列が状況によってJSON文字列になっていたのを修正
## 2025.3.0
### General
- Enhance: プロキシアカウントをシステムアカウントとして作成するように
- Enhance: OAuthで外部アプリからロゴが提供されている場合、それを表示できるように
書式は https://indieauth.spec.indieweb.org/20220212/#example-2 に準じます。
- Fix: システムアカウントが削除できる問題を修正
### Client
- Enhance: モデレーターがセンシティブ設定を変更する際に確認ダイアログを出すように
- Enhance: 「UIのアニメーションを減らす」で画面上のエフェクトも減らせるように
- Enhance: 投稿フォームにおける、メディアの添付可能個数のカウントを反転しました
- これまでの表示は`添付可能残り個数/上限数`でしたが、`添付個数/上限数`としました
- Fix: フォローされたときのメッセージがちらつくことがある問題を修正
- Fix: 投稿ダイアログがサイズ限界を超えた際にスクロールできない問題を修正
### Server
- Fix: 特定のケースでActivityPubの処理がデッドロックになることがあるのを修正
- Fix: S3互換オブジェクトストレージでファイルのアップロードに失敗することがある問題を修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/895)
## 2025.2.1
### General
- Feat: アクセストークン発行時に通知するように
- 依存関係の更新
### Client
- Feat: 投稿フォームで画像をプレビュー可能に
- Enhance: 投稿フォームの「迷惑になる可能性があります」のダイアログを表示する条件においてCWを考慮するように
- Enhance: アンテナ、リスト等の名前をカラム名のデフォルト値にするように `#13992`
- Enhance: クライアントエラー画面の多言語対応
- Enhance: 開発者モードでメニューからファイルIDをコピー出来るように `#15441'
- Enhance: ノートに埋め込まれたメディアのコンテキストメニューから管理者用のファイル管理画面を開けるように ( #15440 )
- Enhance: リアクションする際に確認ダイアログを表示できるように
- Enhance: コントロールパネルのユーザ検索で入力された情報をページ遷移で損なわないように `#15437`
- Enhance: CWの注釈で入力済みの文字数を表示
- Enhance: ノート検索ページのデザイン調整
(Cherry-picked from https://github.com/taiyme/misskey/pull/273)
- Fix: ノートページで、クリップ一覧が表示されないことがある問題を修正
- Fix: コンディショナルロールを手動で割り当てできる導線を削除 `#13529`
- Fix: 埋め込みプレイヤーから外部ページに移動できない問題を修正
- Fix: Play の再読込時に UI が以前の状態を引き継いでしまう問題を修正 `#14378`
- Fix: カスタム絵文字管理画面(beta)にてisSensitive/localOnlyの絞り込みが上手くいかない問題の修正 ( #15445 )
- Fix: ユーザのサジェスト中に@を入力してもサジェスト結果が消えないように `#14385`
- Fix: CWの注釈が100文字を超えている場合、ート投稿ボタンを非アクティブに
- Fix: テーマ選択で現在のテーマが初期表示されていない問題を修正
- 翻訳の更新
### Server
- Enhance: 成り済まし対策として、ActivityPub照会された時にリモートのリダイレクトを拒否できるように (config.disallowExternalApRedirect)
- Fix: `following/invalidate`でフォロワーを解除しようとしているユーザーの情報を返すように
- Fix: オブジェクトストレージの設定でPrefixを設定していなかった場合nullまたは空文字になる問題を修正
- Fix: HTTPプロキシとその除外設定を行った状態でカスタム絵文字の一括インポートをしたとき、除外設定が効かないのを修正( #8766 )
- Fix: pgroongaでの検索時にはじめのキーワードのみが検索に使用される問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/886)
- Fix: メールアドレスの形式が正しくなければ以降の処理を行わないように
- Fix: `update-meta`でobjectStoragePrefixにS3_SAFEかつURL-safeでない文字列を使えないように
- Fix: クリップの説明欄を更新する際に空にできない問題を修正
- Fix: フォロワーではないユーザーにリートもしくは返信された場合にートのDeleteアクティビティが送られていない問題を修正
## 2025.2.0
### General

View file

@ -281,7 +281,6 @@ niraxは、Misskeyで使用しているオリジナルのフロントエンド
query?: Record<string, string>;
loginRequired?: boolean;
hash?: string;
globalCacheKey?: string;
children?: RouteDef[];
}
```
@ -660,54 +659,44 @@ seems to do a decent job)
*after that commit*, do all the extra work, on the same branch:
* copy all changes (commit after each step):
* in
`packages/backend/src/core/activitypub/models/ApNoteService.ts`,
from `createNote` to `updateNote`
* from `packages/backend/src/core/NoteCreateService.ts` to
`packages/backend/src/core/NoteEditService.ts`
* from `packages/backend/src/server/api/endpoints/notes/create.ts`
to `packages/backend/src/server/api/endpoints/notes/edit.ts`
* from `packages/frontend/src/components/MkNote*.vue` to
`packages/frontend/src/components/SkNote*.vue` (if sensible)
* in `packages/backend/src/core/activitypub/models/ApNoteService.ts`, from `createNote` to `updateNote`
* from `packages/backend/src/core/NoteCreateService.ts` to `packages/backend/src/core/NoteEditService.ts`
* from `packages/backend/src/server/api/endpoints/notes/create.ts` to `packages/backend/src/server/api/endpoints/notes/edit.ts`
* from MK note components to SK note components (if sensible)
* from `packages/frontend/src/components/MkNote.vue` to `packages/frontend/src/components/SkNote.vue`
* from `packages/frontend/src/components/MkNoteDetailed.vue` to `packages/frontend/src/components/SkNoteDetailed.vue`
* from `packages/frontend/src/components/MkNoteHeader.vue` to `packages/frontend/src/components/SkNoteHeader.vue`
* from `packages/frontend/src/components/MkNoteSimple.vue` to `packages/frontend/src/components/SkNoteSimple.vue`
* from `packages/frontend/src/components/MkNoteSub.vue` to `packages/frontend/src/components/SkNoteSub.vue`
* from MK note components to Dynamic note components (if the public signature changed)
* from `packages/frontend/src/components/MkNote.vue` to `packages/frontend/src/components/DynamicNote.vue`
* from `packages/frontend/src/components/MkNoteDetailed.vue` to `packages/frontend/src/components/DynamicNoteDetailed.vue`
* from `packages/frontend/src/components/MkNoteSimple.vue` to `packages/frontend/src/components/DynamicNoteSimple.vue`
* from the global timeline to the bubble timeline
(`packages/backend/src/server/api/stream/channels/global-timeline.ts`,
`packages/backend/src/server/api/stream/channels/bubble-timeline.ts`,
`packages/frontend/src/timelines.ts`,
`packages/frontend/src/components/MkTimeline.vue`,
`packages/frontend/src/pages/timeline.vue`,
`packages/frontend/src/ui/deck/tl-column.vue`,
`packages/frontend/src/widgets/WidgetTimeline.vue`)
* if there have been any changes to the federated user data (the
`renderPerson` function in
`packages/backend/src/core/activitypub/ApRendererService.ts`), make
sure that the set of fields in `userNeedsPublishing` and
`profileNeedsPublishing` in
`packages/backend/src/server/api/endpoints/i/update.ts` are still
correct
* check the changes against our `develop` (`git diff develop`) and
against Misskey (`git diff misskey/develop`)
* `packages/backend/src/server/api/stream/channels/global-timeline.ts`
* `packages/backend/src/server/api/stream/channels/bubble-timeline.ts`
* `packages/frontend/src/timelines.ts`
* `packages/frontend/src/components/MkTimeline.vue`
* `packages/frontend/src/pages/timeline.vue`
* `packages/frontend/src/ui/deck/tl-column.vue`
* `packages/frontend/src/widgets/WidgetTimeline.vue`
* from `packages/backend/src/queue/processors/InboxProcessorService.ts` to `packages/backend/src/core/UpdateInstanceQueue.ts`, where `updateInstanceQueue` is impacted
* from `.config/example.yml` to `.config/ci.yml` and `chart/files/default.yml`
* in `packages/backend/src/core/MfmService.ts`, from `toHtml` to `toMastoApiHtml`
* if there have been any changes to the federated user data (the `renderPerson` function in `packages/backend/src/core/activitypub/ApRendererService.ts`), make sure that the set of fields in `userNeedsPublishing` and `profileNeedsPublishing` in `packages/backend/src/server/api/endpoints/i/update.ts` are still correct.
* check the changes against our `develop` (`git diff develop`) and against Misskey (`git diff misskey/develop`)
* re-generate `misskey-js` (`pnpm build-misskey-js-with-types`) and commit
* build the frontend: `rm -rf built/; NODE_ENV=development pnpm
--filter=frontend --filter=frontend-embed --filter=frontend-shared
build` (the `development` tells it to keep some of the original
filenames in the built files)
* make sure there aren't any new `ti-*` classes (Tabler Icons), and
replace them with appropriate `ph-*` ones (Phosphor Icons) in
[`vite.replaceicons.ts`](packages/frontend/vite.replaceIcons.ts).
This command should show you want to change: `grep -ohrP
'(?<=["'\'']ti )(ti-(?!fw)[\w\-]+)' --exclude \*.map -- built/ |
sort -u`.
* re-generate locales (`pnpm run build-assets`) and commit
* re-generate search index (`pnpm run build-frontend-search-index`) and commit
* build the frontend: `rm -rf built/; NODE_ENV=development pnpm --filter=frontend --filter=frontend-embed --filter=frontend-shared build` (the `development` tells it to keep some of the original filenames in the built files)
* make sure there aren't any new `ti-*` classes (Tabler Icons), and replace them with appropriate `ph-*` ones (Phosphor Icons) in [`vite.replaceicons.ts`](packages/frontend/vite.replaceIcons.ts).
* This command should show you want to change: `grep -ohrP '(?<=["'\'']ti )(ti-(?!fw)[\w\-]+)' --exclude \*.map -- built/ | sort -u`.
* NOTE: `ti-fw` is a special class that's defined by Misskey, leave it alone.
* After every change, re-build the frontend and check again, until
there are no more `ti-*` classes in the built files.
* After every change, re-build the frontend and check again, until there are no more `ti-*` classes in the built files.
* Commit!
* double-check the new migration, that they won't conflict with our db
changes: `git diff develop -- packages/backend/migration/`
* double-check the new migration, that they won't conflict with our db changes: `git diff develop -- packages/backend/migration/`
* `pnpm clean; pnpm build`
* run tests `pnpm test; pnpm --filter backend test:e2e` (requires a
test database, [see above](#testing)) and fix as much as you can
* run lint `pnpm --filter=backend --filter=frontend-shared lint` +
`pnpm --filter=frontend --filter=frontend-embed eslint` and fix as
much as you can
* run tests `pnpm test; pnpm --filter backend test:e2e` (requires a test database, [see above](#testing)) and fix as much as you can.
* run lint `pnpm --filter=backend --filter=frontend-shared lint` + `pnpm --filter=frontend --filter=frontend-embed eslint` and fix as much as you can.
Then push and open a Merge Request.

View file

@ -1,5 +1,14 @@
# Upgrade Notes
## 2025.X.X
### Authorized Fetch
This version retires the configuration entry `checkActivityPubGetSignature`, which is now replaced with the new "Authorized Fetch" settings under Control Panel/Security.
The database migrations will automatically import the value of this configuration file, but it will never be read again after upgrading.
To avoid confusion and possible mis-configuration, please remove the entry **after** completing the upgrade.
Do not remove it before migration, or else the setting will reset to default (disabled)!
## 2024.10.0
### Hellspawns

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

View file

@ -1,7 +1,78 @@
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Misskey configuration
# Sharkey configuration
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# ┌──────────────────────────────┐
#───┘ a boring but important thing └────────────────────────────
#
# First of all, let me tell you a story that may possibly be
# boring to you and possibly important to you.
#
# Sharkey is licensed under the AGPLv3 license. This license is
# known to be often misunderstood. Please read the following
# instructions carefully and select the appropriate option so
# that you do not negligently cause a license violation.
#
# --------
# Option 1: If you host Sharkey AS-IS (without any changes to
# the source code. forks are not included).
#
# Step 1: Congratulations! You don't need to do anything.
# --------
# Option 2: If you have made changes to the source code (forks
# are included) and publish a Git repository of source
# code. There should be no access restrictions on
# this repository. Strictly speaking, it doesn't have
# to be a Git repository, but you'll probably use Git!
#
# Step 1: Build and run the Sharkey server first.
# Step 2: Open <https://your.sharkey.example/admin/settings> in
# your browser with the administrator account.
# Step 3: Enter the URL of your Git repository in the
# "Repository URL" field.
# --------
# Option 3: If neither of the above applies to you.
# (In this case, the source code should be published
# on the Sharkey interface. IT IS NOT ENOUGH TO
# DISCLOSE THE SOURCE CODE WHEN A USER REQUESTS IT BY
# E-MAIL OR OTHER MEANS. If you are not satisfied
# with this, it is recommended that you read the
# license again carefully. Anyway, enabling this
# option will automatically generate and publish a
# tarball at build time, protecting you from
# inadvertent license violations. (There is no legal
# guarantee, of course.) The tarball will generated
# from the root directory of your codebase. So it is
# also recommended to check <built/tarball> directory
# once after building and before activating the server
# to avoid ACCIDENTAL LEAKING OF SENSITIVE INFORMATION.
# To prevent certain files from being included in the
# tarball, add a glob pattern after line 15 in
# <scripts/tarball.mjs>. DO NOT FORGET TO BUILD AFTER
# ENABLING THIS OPTION!)
#
# Step 1: Uncomment the following line.
#
# publishTarballInsteadOfProvideRepositoryUrl: true
# ┌────────────────────────┐
#───┘ Initial Setup Password └─────────────────────────────────────────────────────
# Password to initiate setting up admin account.
# It will not be used after the initial setup is complete.
#
# Be sure to change this when you set up Sharkey via the Internet.
#
# The provider of the service who sets up Sharkey on behalf of the customer should
# set this value to something unique when generating the Sharkey config file,
# and provide it to the customer.
#
# setupPassword: example_password_please_change_this_or_you_will_get_hacked
# ┌─────┐
#───┘ URL └─────────────────────────────────────────────────────
@ -15,14 +86,14 @@
#───┘ Port and TLS settings └───────────────────────────────────
#
# Misskey supports two deployment options for public.
# Sharkey supports two deployment options for public.
#
# Option 1: With Reverse Proxy
#
# +----- https://example.tld/ ------------+
# +------+ |+-------------+ +----------------+|
# | User | ---> || Proxy (443) | ---> | Misskey (3000) ||
# | User | ---> || Proxy (443) | ---> | Sharkey (3000) ||
# +------+ |+-------------+ +----------------+|
# +---------------------------------------+
#
@ -33,15 +104,15 @@
#
# +- https://example.tld/ -+
# +------+ | +---------------+ |
# | User | ---> | | Misskey (443) | |
# | User | ---> | | Sharkey (443) | |
# +------+ | +---------------+ |
# +------------------------+
#
# You need to run Misskey as root.
# You need to run Sharkey as root.
# You need to set Certificate in 'https' section.
# To use option 1, uncomment below line.
port: 3000 # A port that your Misskey server should listen.
port: 3000 # A port that your Sharkey server should listen.
# To use option 2, uncomment below lines.
#port: 443
@ -173,6 +244,11 @@ id: "aidx"
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
#sentryForFrontend:
# vueIntegration:
# tracingOptions:
# trackComponents: true
# browserTracingIntegration:
# replayIntegration:
# options:
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
@ -245,6 +321,11 @@ checkActivityPubGetSignature: false
#customMOTD: ['Hello World', 'The sharks rule all', 'Shonks']
# Disable automatic redirect for ActivityPub object lookup. (default: false)
# This is a strong defense against potential impersonation attacks if the viewer instance has inadequate validation.
# However it will make it impossible for other instances to lookup third-party user and notes through your URL.
#disallowExternalApRedirect: true
# Upload or download file size limits (bytes)
#maxFileSize: 262144000

View file

@ -233,7 +233,7 @@ describe('After user setup', () => {
cy.get('[data-cy-post-form-text]').type('Hello, Misskey!');
cy.get('[data-cy-open-post-form-submit]').click();
cy.contains('Hello, Misskey!');
cy.contains('Hello, Misskey!', { timeout: 15000 });
});
it('open note form with hotkey', () => {

View file

@ -251,7 +251,6 @@ removeAreYouSure: "متأكد من أنك تريد حذف {x}؟"
deleteAreYouSure: "متأكد من أنك تريد حذف {x}؟"
resetAreYouSure: "هل تريد إعادة التعيين؟"
saved: "حُفظ"
messaging: "المحادثة"
upload: "ارفع"
keepOriginalUploading: "ابق الصورة الأصلية"
keepOriginalUploadingDescription: "يحفظ الصور المرفوعة على حالتها الأصلية، وان عطّل ستولد نسخة مخصصة من الصورة."
@ -264,7 +263,6 @@ uploadFromUrlMayTakeTime: "سيستغرق بعض الوقت لاتمام الر
explore: "استكشاف"
messageRead: "مقروءة"
noMoreHistory: "لا يوجد المزيد من التاريخ"
startMessaging: "ابدأ محادثة"
nUsersRead: "قرأه {n}"
agreeTo: "اوافق على {0}"
agree: "أقبل"
@ -436,8 +434,6 @@ retype: "أعد الكتابة"
noteOf: "ملاحظات {user}"
quoteAttached: "اِقتُبسَ"
quoteQuestion: "أتريد تضمينها كاقتباس"
noMessagesYet: "ليس هناك رسائل بعد"
newMessageExists: "لقد تلقيت رسالة جديدة"
onlyOneFileCanBeAttached: "يمكنك إرفاق ملف واحد بالرسالة"
signinRequired: "رجاءً لِج"
invitations: "دعوة"
@ -1012,6 +1008,14 @@ sourceCode: "الشفرة المصدرية"
flip: "اقلب"
lastNDays: "آخر {n} أيام"
surrender: "ألغِ"
postForm: "أنشئ ملاحظة"
information: "عن"
_chat:
invitations: "دعوة"
noHistory: "السجل فارغ"
members: "الأعضاء"
home: "الرئيسي"
send: "أرسل"
_delivery:
stop: "مُعلّق"
_initialAccountSetting:
@ -1236,7 +1240,6 @@ _theme:
shadow: "الظل"
navBg: "خلفية الشريط الجانبي"
navFg: "نص الشريط الجانبي"
navHoverFg: "نص الشريط الجانبي (عند التمرير فوقه)"
link: "رابط"
hashtag: "وسم"
mention: "أشر الى"
@ -1311,6 +1314,7 @@ _permissions:
"read:gallery": "اعرض المعرض"
"write:gallery": "عدّل المعرض"
"read:gallery-likes": "يعرض ما أعجبك من مشاركات المعرض"
"write:chat": "اكتب أو احذف رسائل محادثة"
_auth:
shareAccess: "أتريد التفويض لـ \"{name}\" بالوصول لحسابك؟"
shareAccessAsk: "هل تخول لهذا التطبيق الوصول لحسابك؟"
@ -1584,3 +1588,7 @@ _offlineScreen:
_remoteLookupErrors:
_noSuchObject:
title: "غير موجود"
_search:
searchScopeAll: "الكل"
searchScopeLocal: "المحلي"
searchScopeUser: "مستخدم محدد"

View file

@ -252,7 +252,6 @@ removeAreYouSure: "আপনি কি \"{x}\" সরানোর ব্যা
deleteAreYouSure: "আপনি কি \"{x}\" সরানোর ব্যাপারে নিশ্চিত?"
resetAreYouSure: "রিসেট করার ব্যাপারে নিশ্চিত?"
saved: "সংরক্ষিত হয়েছে"
messaging: "চ্যাট"
upload: "আপলোড"
keepOriginalUploading: "আসল ছবি রাখুন"
keepOriginalUploadingDescription: "ছবিটি আপলোড করার সময় আসল সংস্করণটি রাখুন। অপশনটি বন্ধ থাকলে, আপলোডের সময় ওয়েব প্রকাশনার জন্য ছবি ব্রাউজারে তৈরি করা হবে।"
@ -265,7 +264,6 @@ uploadFromUrlMayTakeTime: "URL হতে আপলোড হতে কিছু
explore: "ঘুরে দেখুন"
messageRead: "পড়া"
noMoreHistory: "আর কোন ইতিহাস নেই"
startMessaging: "চ্যাট শুরু করুন"
nUsersRead: "{n} জন পড়েছেন"
agreeTo: "{0} এর প্রতি আমি সম্মত"
start: "শুরু করুন"
@ -427,8 +425,6 @@ retype: "পুনঃ প্রবেশ"
noteOf: "{user} এর নোট"
quoteAttached: "উদ্ধৃত"
quoteQuestion: "উদ্ধৃতি হিসাবে সংযুক্ত করবেন?"
noMessagesYet: "কোন মেসেজ নেই"
newMessageExists: "নতুন মেসেজ পেয়েছেন"
onlyOneFileCanBeAttached: "আপনি মেসেজের সাথে সর্বোচ্চ একটি ফাইল যুক্ত করতে পারবেন"
signinRequired: "দয়া করে লগ ইন করুন"
invitations: "আমন্ত্রণ"
@ -852,6 +848,14 @@ replies: "জবাব"
renotes: "রিনোট"
sourceCode: "সোর্স কোড"
flip: "উল্টান"
postForm: "নোট লিখুন"
information: "আপনার সম্পর্কে"
_chat:
invitations: "আমন্ত্রণ"
noHistory: "কোনো ইতিহাস নেই"
members: "সদস্যবৃন্দ"
home: "মূল পাতা"
send: "পাঠান"
_delivery:
stop: "স্থগিত করা হয়েছে"
_type:
@ -994,7 +998,6 @@ _theme:
header: "হেডার"
navBg: "সাইডবারের পটভূমি"
navFg: "সাইডবারের পাঠ্য"
navHoverFg: "সাইডবারের পাঠ্য (হভার)"
navActive: "সাইডবারের পাঠ্য (অ্যাকটিভ)"
navIndicator: "সাইডবারের ইনডিকেটর"
link: "লিংক"
@ -1017,11 +1020,8 @@ _theme:
buttonHoverBg: "বাটনের পটভূমি (হভার)"
inputBorder: "ইনপুট ফিল্ডের বর্ডার"
driveFolderBg: "ড্রাইভ ফোল্ডারের পটভূমি"
wallpaperOverlay: "ওয়ালপেপার ওভারলে"
badge: "ব্যাজ"
messageBg: "চ্যাটের পটভূমি"
accentDarken: "অ্যাকসেন্ট (গাঢ়)"
accentLighten: "অ্যাকসেন্ট (হাল্কা)"
fgHighlighted: "হাইলাইট করা পাঠ্য"
_sfx:
note: "নোটগুলি"
@ -1084,6 +1084,7 @@ _permissions:
"write:gallery": "গ্যালারী সম্পাদনা করুন"
"read:gallery-likes": "গ্যালারীর পছন্দগুলি দেখুন"
"write:gallery-likes": "গ্যালারীর পছন্দগুলি সম্পাদনা করুন"
"write:chat": "চ্যাটগুলি সম্পাদনা করুন"
_auth:
shareAccess: "\"{name}\" কে অ্যাকাউন্টের অ্যাক্সেস দিবেন?"
shareAccessAsk: "অ্যাপ্লিকেশনটিকে অ্যাকাউন্টের অ্যাক্সেস দিবেন?"
@ -1348,3 +1349,6 @@ _reversi:
_remoteLookupErrors:
_noSuchObject:
title: "পাওয়া যায়নি"
_search:
searchScopeAll: "সবগুলো"
searchScopeLocal: "স্থানীয়"

View file

@ -66,7 +66,7 @@ copyFolderId: "Copiar ID de la carpeta"
copyProfileUrl: "Copiar adreça URL del perfil"
searchUser: "Cercar un usuari"
searchThisUsersNotes: "Cercar les publicacions de l'usuari"
reply: "Respon"
reply: "Respostes"
loadMore: "Carregar més"
showMore: "Veure més"
showLess: "Mostrar menys"
@ -111,7 +111,7 @@ followRequests: "Peticions de seguiment"
unfollow: "Deixar de seguir"
followRequestPending: "Sol·licituds de seguiment pendents"
enterEmoji: "Introduir un emoji"
renote: "Impulsar "
renote: "Impulsar"
unrenote: "Anul·la l'impuls"
renoted: "S'ha impulsat"
renotedToX: "Impulsat per {name}."
@ -260,7 +260,7 @@ noCustomEmojis: "No hi ha emojis personalitzats"
noJobs: "No hi ha feines"
federating: "Federant"
blocked: "Bloquejat"
suspended: "Suspés"
suspended: "Anul·lar subscripció "
all: "tot"
subscribing: "Subscrit a"
publishing: "S'està publicant"
@ -289,7 +289,6 @@ deleteAreYouSure: "Segur que vols esborrar «{x}»?"
resetAreYouSure: "Segur que vols restablir-ho?"
areYouSure: "Estàs segur?"
saved: "S'ha desat"
messaging: "Xat"
upload: "Puja"
keepOriginalUploading: "Guarda la imatge original"
keepOriginalUploadingDescription: "Guarda la imatge pujada sense modificar. Si està desactivat, es generarà una versió per visualitzar a la web en pujar la imatge."
@ -302,7 +301,7 @@ uploadFromUrlMayTakeTime: "La càrrega des de l'enllaç pot trigar un temps"
explore: "Explora"
messageRead: "Vist"
noMoreHistory: "No hi ha res més per veure"
startMessaging: "Comença a xatejar"
startChat: "Comença a xatejar "
nUsersRead: "Vist per {n}"
agreeTo: "Accepto que {0}"
agree: "Hi estic d'acord"
@ -425,6 +424,7 @@ antennaExcludeBots: "Exclou els bots"
antennaKeywordsDescription: "Separar amb espais per la condició AND o amb salts de línia per la condició OR."
notifyAntenna: "Notifica'm les publicacions noves"
withFileAntenna: "Només les publicacions amb fitxers"
hideNotesInSensitiveChannel: "Amaga les notes a canals sensibles "
enableServiceworker: "Activar les notificacions al navegador"
antennaUsersDescription: "Llistar un nom d'usuari per línia"
caseSensitive: "Sensible a majúscules i minúscules "
@ -491,8 +491,6 @@ noteOf: "Publicació de: {user}"
quoteAttached: "Frase adjunta"
quoteQuestion: "Vols annexar-la com a cita?"
attachAsFileQuestion: "El text copiat és massa llarg. Vols adjuntar-lo com un fitxer de text?"
noMessagesYet: "Encara no hi ha missatges"
newMessageExists: "Has rebut un nou missatge"
onlyOneFileCanBeAttached: "Només pots adjuntar un fitxer a un missatge"
signinRequired: "Si us plau, Registra't o inicia la sessió abans de continuar"
signinOrContinueOnRemote: "Per continuar necessites moure el teu servidor o registrar-te / iniciar sessió en aquest servidor."
@ -646,7 +644,7 @@ disablePlayer: "Tanca el reproductor de vídeo"
expandTweet: "Expandir post"
themeEditor: "Editor de temes"
description: "Descripció"
describeFile: "Afegir subtitulació"
describeFile: "Afegeix una descripció "
enterFileDescription: "Escriu un peu de foto"
author: "Autor"
leaveConfirm: "Hi ha canvis sense guardar. Els vols descartar?"
@ -698,6 +696,7 @@ userSaysSomethingAbout: "{name} està parlant sobre \"{word}\""
makeActive: "Activar"
display: "Veure"
copy: "Copiar"
copiedToClipboard: "Copiat al porta papers"
metrics: "Mètriques"
overview: "Visió General"
logs: "Registres"
@ -1114,7 +1113,7 @@ forceShowAds: "Mostra els anuncis sempre "
addMemo: "Afegir recordatori"
editMemo: "Editar recordatori"
reactionsList: "Reaccions"
renotesList: "Impulsos"
renotesList: "Llistat d'impulsos "
notificationDisplay: "Notificacions"
leftTop: "Dalt a l'esquerra "
rightTop: "Dalt a la dreta "
@ -1130,7 +1129,7 @@ pleaseAgreeAllToContinue: "Has d'acceptar tots els camps de dalt per poder conti
continue: "Continuar"
preservedUsernames: "Noms d'usuaris reservats"
preservedUsernamesDescription: "Llistat de noms d'usuaris que no es poden fer servir separats per salts de linia. Aquests noms d'usuaris no estaran disponibles quan es creï un compte d'usuari normal, però els administradors els poden fer servir per crear comptes manualment. Per altre banda els comptes ja creats amb aquests noms d'usuari no es veure'n afectats."
createNoteFromTheFile: "Compon una nota des d'aquest fitxer"
createNoteFromTheFile: "Escriu una nota incloent aquest fitxer"
archive: "Arxiu"
archived: "Arxivat"
unarchive: "Desarxivar"
@ -1139,7 +1138,7 @@ channelArchiveConfirmDescription: "Un Canal arxivat no apareixerà a la llista d
thisChannelArchived: "Aquest Canal ha sigut arxivat."
displayOfNote: "Mostrar notes"
initialAccountSetting: "Configuració del perfil"
youFollowing: "Seguint"
youFollowing: "Segueixes "
preventAiLearning: "Descartar l'ús d'aprenentatge automàtic (IA Generativa)"
preventAiLearningDescription: "Demanar els indexadors no fer servir els texts, imatges, etc. en cap conjunt de dades per alimentar l'aprenentatge automàtic (IA Predictiva/ Generativa). Això s'aconsegueix afegint la etiqueta \"noai\" com a resposta HTML al contingut corresponent. Prevenir aquest ús totalment pot ser que no sigui aconseguit, ja que molts indexadors poden obviar aquesta etiqueta."
options: "Opcions"
@ -1189,8 +1188,8 @@ currentAnnouncements: "Informes actuals"
pastAnnouncements: "Informes passats"
youHaveUnreadAnnouncements: "Tens informes per llegir."
useSecurityKey: "Segueix les instruccions del teu navegador O dispositiu per fer servir el teu passkey."
replies: "Respon"
renotes: "Impulsar "
replies: "Respostes"
renotes: "Impulsos"
loadReplies: "Mostrar les respostes"
loadConversation: "Mostrar la conversació "
pinnedList: "Llista fixada"
@ -1309,6 +1308,130 @@ availableRoles: "Roles disponibles "
acknowledgeNotesAndEnable: "Activa'l després de comprendre els possibles perills."
federationSpecified: "Aquest servidor treballa amb una federació de llistes blanques. No pot interactuar amb altres servidors que no siguin els especificats per l'administrador."
federationDisabled: "La unió es troba deshabilitada en aquest servidor. No es pot interactuar amb usuaris d'altres servidors."
confirmOnReact: "Confirmar en reaccionar"
reactAreYouSure: "Vols reaccionar amb \"{emoji}\"?"
markAsSensitiveConfirm: "Vols marcar aquest contingut com a sensible?"
unmarkAsSensitiveConfirm: "Vols deixar de marcar com a sensible aquest contingut?"
preferences: "Preferències "
accessibility: "Accessibilitat "
preferencesProfile: "Perfil de configuració "
copyPreferenceId: "Copiar l'ID de la configuració "
resetToDefaultValue: "Restaura al valor per defecte "
overrideByAccount: "Anul·lar per compte"
untitled: "Sense títol "
noName: "No hi ha un nom disponible "
skip: "Ometre "
restore: "Restaurar "
syncBetweenDevices: "Sincronització entre dispositius"
preferenceSyncConflictTitle: "Els valors de la configuració ja existeixen al dispositiu"
preferenceSyncConflictText: "Un element de la configuració amb sincronització activada desa els seus valors al servidor, però s'ha trobat un valor a la configuració desat al servidor per aquest element de la configuració. Quin valor us sobreescriure?"
preferenceSyncConflictChoiceServer: "Valors de configuració del servidor"
preferenceSyncConflictChoiceDevice: "Punts d'ajustos del dispositiu "
preferenceSyncConflictChoiceCancel: "Cancel·lar l'activació de la sincronització "
paste: "Pegar"
emojiPalette: "Calaix d'emojis"
postForm: "Formulari de publicació"
textCount: "Nombre de caràcters "
information: "Informació"
chat: "Xat"
migrateOldSettings: "Migració de la configuració antiga "
migrateOldSettings_description: "Normalment això es fa automàticament, però si la transició no es fa, el procés es pot iniciar manualment. S'esborrarà la configuració actual."
compress: "Comprimir "
right: "Dreta"
bottom: "A baix "
top: "A dalt "
embed: "Incrustar"
_chat:
noMessagesYet: "Encara no tens missatges "
newMessage: "Missatge nou"
individualChat: "Xat individual "
individualChat_description: "Pots mantenir converses individuals amb usuaris concrets."
roomChat: "Sala de xat"
roomChat_description: "Pots xatejar amb diverses persones.\nTambé pots xatejar amb usuaris que no poden fer xats privats, si ells accepten."
createRoom: "Crear una sala"
inviteUserToChat: "Invita usuaris per començar a xatejar"
yourRooms: "Sales creades"
joiningRooms: "Sales a les quals participes"
invitations: "Convida"
noInvitations: "No tens cap invitació "
history: "Historial de converses "
noHistory: "No hi ha un registre previ"
noRooms: "No hi ha habitacions"
inviteUser: "Invitar usuaris"
sentInvitations: "Enviar invitacions"
join: "Afegir-se "
ignore: "Ignorar "
leave: "Marxar"
members: "Membres"
searchMessages: "Buscar missatges "
home: "Inici"
send: "Envia"
newline: "Línia nova "
muteThisRoom: "Silenciar aquesta sala"
deleteRoom: "Esborrar la sala"
chatNotAvailableForThisAccountOrServer: "El xat no està disponible per aquest servidor o aquest compte."
chatNotAvailableInOtherAccount: "La funció de xat es troba desactivada al compte de l'altre usuari."
cannotChatWithTheUser: "No pots xatejar amb aquest usuari"
cannotChatWithTheUser_description: "El xat està desactivat o l'altra part encara no l'ha obert."
chatWithThisUser: "Xateja amb aquest usuari"
thisUserAllowsChatOnlyFromFollowers: "Aquest usuari només accepta xats d'usuaris que el segueixen."
thisUserAllowsChatOnlyFromFollowing: "Aquest usuari només accepta xats d'usuaris que segueix."
thisUserAllowsChatOnlyFromMutualFollowing: "Aquest usuari només accepta xats d'usuaris que segueixes i et segueixen."
thisUserNotAllowedChatAnyone: "Aquest usuari no accepta xats de ningú."
chatAllowedUsers: "Usuaris que poden xatejar"
chatAllowedUsers_note: "Pots xatejar amb qualsevol usuari a qui hagis enviat un missatge de xat, independentment d'aquesta configuració."
_chatAllowedUsers:
everyone: "Tothom"
followers: "Només els teus seguidors"
following: "Només usuaris als que segueixes"
mutual: "Només seguidors mutus"
none: "Ningú "
_emojiPalette:
palettes: "Calaixos d'emojis"
enableSyncBetweenDevicesForPalettes: "Activa la sincronització dels calaixos d'emojis entre dispositius"
paletteForMain: "Calaix d'emojis principal"
paletteForReaction: "Calaix d'emojis per reaccions"
_settings:
driveBanner: "Pots gestionar i configurar el Disc, comprovar el seu ús i establir una configuració per a la càrrega d'arxius."
pluginBanner: "Els complements poden fer-se servir per ampliar les funcionalitats del client. Els complements poden instal·lar-se, configurar-se individualment i gestionar-se."
notificationsBanner: "Pots configurar el tipus i l'abast de les notificacions que es rebran del servidor, també les notificacions emergents."
api: "API"
webhook: "Webhook"
serviceConnection: "Relació entre serveis"
serviceConnectionBanner: "Pots configurar i gestionar tokens d'accés i webhooks per integrar serveis i aplicacions externes."
accountData: "Dades del compte"
accountDataBanner: "Exportació/Importació i gestió d'arxius amb dades del compte."
muteAndBlockBanner: "Pots configurar i gestionar els continguts que desitges amagar i restringir les accions de determinats usuaris."
accessibilityBanner: "Els clients poden personalitzar-se i configurar-se per un ús òptim en funció de la seva visió i comportament."
privacyBanner: "Pots establir la configuració de privacitat del compte, com el grau de visibilitat del teu contingut, la facilitat per trobar-ho i si es pot aprovar els seguidors."
securityBanner: "Configura les opcions relacionades amb la seguretat del teu compte com ara contrasenyes, mètodes per iniciar sessió, aplicacions d'autentificació i claus d'accés."
preferencesBanner: "Pots configurar el comportament general del client segons les teves preferències."
appearanceBanner: "Pots configurar les preferències relacionades amb la visualització i l'aspecte del client segons el teu parer."
soundsBanner: "Configuració dels sons que reproduirà el client."
timelineAndNote: "Línia de temps i nota"
makeEveryTextElementsSelectable: "Fes que tots els elements del text siguin seleccionables"
makeEveryTextElementsSelectable_description: "L'activació pot reduir la usabilitat en determinades ocasions."
useStickyIcons: "Utilitza icones fixes"
showNavbarSubButtons: "Mostrar sub botons a la barra de navegació "
ifOn: "Quan s'encén "
ifOff: "Quan s'apaga "
enableSyncThemesBetweenDevices: "Sincronitzar els temes instal·lats entre dispositius"
_chat:
showSenderName: "Mostrar el nom del remitent"
sendOnEnter: "Introdueix per enviar"
_preferencesProfile:
profileName: "Nom del perfil"
profileNameDescription: "Estableix un nom que identifiqui aquest dispositiu."
profileNameDescription2: "Per exemple: \"PC Principal\", \"Smartphone\", etc"
_preferencesBackup:
autoBackup: "Còpia de seguretat automàtica "
restoreFromBackup: "Restaurar des d'una còpia de seguretat"
noBackupsFoundTitle: "No s'ha trobat cap còpia de seguretat"
noBackupsFoundDescription: "No s'han trobat còpies de seguretat creades automàticament, però si has desat, manualment, un arxiu de còpia de seguretat, pots importar-lo i carregar-lo."
selectBackupToRestore: "Seleccionar la còpia de seguretat que vols restaurar"
youNeedToNameYourProfileToEnableAutoBackup: "Has de posar-li un nom al teu perfil per poder activar les còpies de seguretat automàtiques."
autoPreferencesBackupIsNotEnabledForThisDevice: "La còpia de seguretat automàtica no es troba activada en aquest dispositiu."
backupFound: "Còpia de seguretat de la configuració trobada"
_accountSettings:
requireSigninToViewContents: "És obligatori l'inici de sessió per poder veure el contingut"
requireSigninToViewContentsDescription1: "Es requereix l'inici de sessió per poder veure totes les notes i el contingut que has creat. Amb això esperem evitar que els rastrejadors recopilin informació."
@ -1319,6 +1442,7 @@ _accountSettings:
makeNotesHiddenBefore: "Fes que les notes antigues siguin privades"
makeNotesHiddenBeforeDescription: "Mentres aquesta funció estigui activada les notes que hagin superat una data i hora fixada o hagi passat el temps establert només seran visibles per a tu. Si la desactives es restablirà també l'estat públic de les notes."
mayNotEffectForFederatedNotes: "Això pot ser que no afecti les notes federades."
mayNotEffectSomeSituations: "Aquestes restriccions són simplificades. Pot ser que no s'apliquin en determinades situacions, com quan es modera o visualitza un servidor remot."
notesHavePassedSpecifiedPeriod: "Notes publicades durant un període de temps especificat."
notesOlderThanSpecifiedDateAndTime: "Notes més antigues de la data i temps especificat "
_abuseUserReport:
@ -1330,7 +1454,7 @@ _abuseUserReport:
resolveTutorial: "Si l'informe és legítim selecciona \"Acceptar\" per resoldre'l positivament. Però si l'informe no és legítim selecciona \"Rebutjar\" per resoldre'l negativament."
_delivery:
status: "Estat d'entrega "
stop: "Suspés"
stop: "Anul·lar subscripció "
resume: "Torna a enviar"
_type:
none: "S'està publicant"
@ -1804,6 +1928,7 @@ _role:
canImportFollowing: "Autoritza la importació de seguidors"
canImportMuting: "Autoritza la importació de silenciats"
canImportUserLists: "Autoritza la importació de llistes d'usuaris "
canChat: "Pot xatejar"
_condition:
roleAssignedTo: "Assignat a rols manuals"
isLocal: "Usuari local"
@ -1967,6 +2092,7 @@ _theme:
installed: "{name} Instal·lat "
installedThemes: "Temes instal·lats "
builtinThemes: "Temes integrats"
instanceTheme: "Tema de la instància "
alreadyInstalled: "Aquest tema ja es troba instal·lat "
invalid: "El format d'aquest tema no és correcte"
make: "Crear un tema"
@ -1999,14 +2125,13 @@ _theme:
header: "Capçalera"
navBg: "Fons de la barra lateral"
navFg: "Text de la barra lateral"
navHoverFg: "Text barra lateral (en passar per sobre)"
navActive: "Text barra lateral (actiu)"
navIndicator: "Indicador barra lateral"
link: "Enllaç"
hashtag: "Etiqueta"
mention: "Menció"
mentionMe: "Mencions (jo)"
renote: "Renotar"
renote: "Impulsar"
modalBg: "Fons del modal"
divider: "Divisor"
scrollbarHandle: "Maneta de la barra de desplaçament"
@ -2022,17 +2147,15 @@ _theme:
buttonHoverBg: "Fons botó (en passar-hi per sobre)"
inputBorder: "Contorn del cap d'introducció "
driveFolderBg: "Fons de la carpeta Disc"
wallpaperOverlay: "Superposició del fons de pantalla "
badge: "Insígnia "
messageBg: "Fons del xat"
accentDarken: "Accent (fosc)"
accentLighten: "Accent (clar)"
fgHighlighted: "Text ressaltat"
_sfx:
note: "Notes"
noteMy: "Nota (per mi)"
notification: "Notificacions"
reaction: "Quan se selecciona una reacció "
chatMessage: "Missatges del xat"
_soundSettings:
driveFile: "Fer servir un fitxer d'àudio del disc"
driveFileWarn: "Seleccionar un fitxer d'àudio del disc"
@ -2179,6 +2302,8 @@ _permissions:
"read:clip-favorite": "Veure clips favorits"
"read:federation": "Veure dades de federació"
"write:report-abuse": "Informar d'un abús"
"write:chat": "Crear o esborrar missatges de xat"
"read:chat": "Explorar xats"
_auth:
shareAccessTitle: "Concedeix permisos a l'aplicació"
shareAccess: "Vols que {name} pugui accedir al vostre compte?"
@ -2427,6 +2552,7 @@ _notification:
newNote: "Nota nova"
unreadAntennaNote: "Antena {name}"
roleAssigned: "Rol assignat "
chatRoomInvitationReceived: "T'han invitat a una sala de xat"
emptyPushNotificationMessage: "Les notificacions han sigut actualitzades"
achievementEarned: "Aconseguiment desblocat"
testNotification: "Notificació de prova"
@ -2440,31 +2566,38 @@ _notification:
flushNotification: "Netejar notificacions"
exportOfXCompleted: "Completada l'exportació de {x}"
login: "Algú ha iniciat sessió "
createToken: "Token d'accés generat"
createTokenDescription: "Si no saps què és, esborra el token des de {text}."
_types:
all: "Tots"
note: "Notes noves"
follow: "Segueix-me"
mention: "Menció"
reply: "Respostes"
renote: "Renotar"
renote: "Impulsos"
quote: "Citar"
reaction: "Reaccions"
pollEnded: "Enquesta terminada"
receiveFollowRequest: "Rebuda una petició de seguiment"
followRequestAccepted: "Petició de seguiment acceptada"
roleAssigned: "Rol donat"
chatRoomInvitationReceived: "Invitat a la sala de xat"
achievementEarned: "Assoliment desbloquejat"
exportCompleted: "Exportació completada"
login: "Iniciar sessió"
createToken: "Creació de tokens d'accés "
test: "Prova la notificació"
app: "Notificacions d'aplicacions"
_actions:
followBack: "També et segueix"
reply: "Respondre"
renote: "Renotar"
renote: "Impulsar"
_deck:
alwaysShowMainColumn: "Mostrar sempre la columna principal"
columnAlign: "Alinea les columnes"
columnGap: "Espai entre columnes"
deckMenuPosition: "Posició del menú del tauler"
navbarPosition: "Posició de la barra de navegació "
addColumn: "Afig una columna"
newNoteNotificationSettings: "Configuració de notificacions per a notes noves"
configureColumn: "Configuració de columnes"
@ -2483,6 +2616,7 @@ _deck:
useSimpleUiForNonRootPages: "Usa una interfície senzilla per a les pàgines navegades"
usedAsMinWidthWhenFlexible: "L'amplada mínima es farà servir quan \"Ajust automàtic de l'amplada\" estigui activat"
flexible: "Ajust automàtic de l'amplada"
enableSyncBetweenDevicesForProfiles: "Activar la sincronització de la informació de perfils de dispositiu a dispositiu"
_columns:
main: "Principal"
widgets: "Ginys"
@ -2590,6 +2724,8 @@ _moderationLogTypes:
deletePage: "Esborrar la pàgina"
deleteFlash: "Esborrar el guió"
deleteGalleryPost: "Esborrar la publicació de la galeria"
deleteChatRoom: "Esborra la sala de xat"
updateProxyAccountDescription: "Actualitzar descripció del compte proxy"
_fileViewer:
title: "Detall del fitxer"
type: "Tipus de fitxer"
@ -2603,10 +2739,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "Assegura't que qui distribueix aquest recurs és fiable abans d'instal·lar-ho."
_plugin:
title: "Vols instal·lar aquest afegit?"
metaTitle: "Informació de l'afegit "
_theme:
title: "Vols instal·lar aquest tema?"
metaTitle: "Informació del tema"
_meta:
base: "Paleta de colors base"
_vendorInfo:
@ -2822,8 +2956,6 @@ _remoteLookupErrors:
_responseInvalid:
title: "La resposta no és correcta "
description: "Hem pogut comunicar-nos amb aquest servidor, però les dades rebudes no són correctes."
_responseInvalidIdHostNotMatch:
description: "El domini de l'adreça introduïda no és el mateix que el domini de l'adreça final obtinguda. Si estàs consultant continguts remots mitjançant servidors tercers, torna a fer la consulta fent servir l'adreça que es pot obtenir en el servidor origen."
_noSuchObject:
title: "No s'ha trobat"
description: "No es pot trobar el recurs sol·licitat, si us plau comprova l'adreça una altra vegada."
@ -2840,3 +2972,23 @@ _captcha:
_unknown:
title: "Error CAPTCHA"
text: "S'ha produït un error inesperat."
_bootErrors:
title: "Hi ha hagut en error en carregar"
serverError: "Si el problema persisteix després d'esperar una mica i recarregar, posa't en contacte amb l'administrador del servidor amb el següent codi d'error."
solution: "Per intentar resoldre el problema pots fer el següent."
solution1: "Actualitza el navegador i el sistema operatiu a l'última versió "
solution2: "Desactiva els adblockers"
solution3: "Esborra la memòria cau del navegador"
solution4: "(Navegador Tor) configura dom.webaudio.enabled a true"
otherOption: "Altres opcions"
otherOption1: "Esborrar la configuració i la memòria cau del client"
otherOption2: "Iniciar client senzill"
otherOption3: "Iniciar l'eina de reparació "
_search:
searchScopeAll: "Tot"
searchScopeLocal: "Local"
searchScopeServer: "Instància "
searchScopeUser: "Especificar usuari"
pleaseEnterServerHost: "Introdueix l'adreça de la instància "
pleaseSelectUser: "Selecciona un usuari"
serverHostPlaceholder: "Ex: misskey.example.com"

View file

@ -5,9 +5,13 @@ introMisskey: "Vítejte! Misskey je otevřený a decentralizovaný microblogový
poweredByMisskeyDescription: "{name} je jeden ze serverů využívající open source platformu <b>Misskey<b> (nazývaná \"Misskey instance\")."
monthAndDay: "{day}. {month}."
search: "Vyhledávání"
reset: "Obnovit"
notifications: "Oznámení"
username: "Uživatelské jméno"
password: "Heslo"
initialPasswordForSetup: "Počáteční heslo pro nastavení"
initialPasswordIsIncorrect: "Počáteční heslo pro nastavení je nesprávné"
initialPasswordForSetupDescription: "Použijte heslo, které jste nastavili v konfiguračním souboru, pokud jste Misskey instalovali ručně.\nPokud užíváte Misskey hostovací službu, použijte poskytnuté heslo.\nPokud jste heslo nenastavovali, zanechte prázdné."
forgotPassword: "Zapomenuté heslo"
fetchingAsApObject: "Načítám data z Fediversu..."
ok: "Potvrdit"
@ -45,6 +49,8 @@ pin: "Připnout"
unpin: "Odepnout"
copyContent: "Zkopírovat obsah"
copyLink: "Kopírovat odkaz"
copyRemoteLink: "Zkoprírovat vzdálený odkaz"
copyLinkRenote: "Zkopírovat odkaz renotu"
delete: "Smazat"
deleteAndEdit: "Smazat a upravit"
deleteAndEditConfirm: "Jste si jistí že chcete smazat tuto poznámku a editovat ji? Ztratíte tím všechny reakce, sdílení a odpovědi na ni."
@ -168,6 +174,9 @@ addAccount: "Přidat účet"
reloadAccountsList: "Obnovit list účtů"
loginFailed: "Přihlášení se nezdařilo."
showOnRemote: "Více na původním profilu"
continueOnRemote: "Pokračujte na původní profil"
chooseServerOnMisskeyHub: "Vyberete si server z Misskey Hubu"
inputHostName: "Zadejte doménu"
general: "Obecně"
wallpaper: "Obrázek na pozadí"
setWallpaper: "Nastavení obrázku na pozadí"
@ -192,6 +201,7 @@ perHour: "za hodinu"
perDay: "za den"
stopActivityDelivery: "Přestat zasílat aktivitu"
blockThisInstance: "Blokovat tuto instanci"
silenceThisInstance: "Utišit tuto instanci"
operations: "Operace"
software: "Software"
version: "Verze"
@ -256,7 +266,6 @@ removeAreYouSure: "Jste si jistí že chcete smazat \"{x}\"?"
deleteAreYouSure: "Jste si jistí že chcete smazat \"{x}\"?"
resetAreYouSure: "Opravdu resetovat?"
saved: "Uloženo"
messaging: "Zprávy"
upload: "Nahrát soubory"
keepOriginalUploading: "Ponechat originální obrázek"
keepOriginalUploadingDescription: "Uloží původní nahraný obrázek jak je. Pokud je to vypnuté, vygeneruje se zobrazení verze na webu při nahrátí."
@ -269,7 +278,6 @@ uploadFromUrlMayTakeTime: "Může trvat nějakou dobu, dokud nebude dokončeno n
explore: "Objevovat"
messageRead: "Přečtené"
noMoreHistory: "To je vše"
startMessaging: "Zahájit chat"
nUsersRead: "přečteno {n} uživateli"
agreeTo: "Souhlasím s {0}"
agree: "Souhlasím"
@ -365,8 +373,11 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Aktivovat hCaptchu"
hcaptchaSiteKey: "Klíč stránky"
hcaptchaSecretKey: "Tajný Klíč (Secret Key)"
mcaptcha: "mCaptcha"
enableMcaptcha: "Aktivovat mCaptchu"
mcaptchaSiteKey: "Klíč stránky"
mcaptchaSecretKey: "Tajný Klíč (Secret Key)"
mcaptchaInstanceUrl: "URL mCaptcha serveru"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Zapnout ReCAPTCHu"
recaptchaSiteKey: "Klíč stránky"
@ -445,8 +456,6 @@ retype: "Zadejte znovu"
noteOf: "{user} poznámky"
quoteAttached: "Citace"
quoteQuestion: "Přiložit jako citaci?"
noMessagesYet: "Zatím tu nejsou žádné zprávy"
newMessageExists: "Máte novou zprávu"
onlyOneFileCanBeAttached: "Ke zprávě můžete přiložit jenom jeden soubor"
signinRequired: "Přihlašte se, prosím"
invitations: "Pozvat"
@ -470,6 +479,8 @@ uiLanguage: "Jazyk uživatelského rozhraní"
aboutX: "O {x}"
emojiStyle: "Styl emoji"
native: "Výchozí"
style: "Vzhled"
popup: "Vyskakovací okno"
showNoteActionsOnlyHover: "Zobrazit akce poznámky jenom při naběhnutí myši"
noHistory: "Žádná historie"
signinHistory: "Historie přihlášení"
@ -532,6 +543,7 @@ showInPage: "Zobrazit na stránce"
popout: "Pop-out"
volume: "Hlasitost"
masterVolume: "Celková hlasitost"
notUseSound: "Zakázat zvuk"
details: "Detaily"
chooseEmoji: "Vybrat emotikon"
unableToProcess: "Operace nebyla dokončena."
@ -1094,6 +1106,14 @@ sourceCode: "Zdrojový kód"
flip: "Otočit"
lastNDays: "Posledních {n} dnů"
surrender: "Zrušit"
postForm: "Formulář pro odeslání"
information: "Informace"
_chat:
invitations: "Pozvat"
noHistory: "Žádná historie"
members: "Členové"
home: "Domů"
send: "Odeslat"
_delivery:
stop: "Suspendováno"
_type:
@ -1606,7 +1626,6 @@ _theme:
header: "Nadpis"
navBg: "Pozadí postranního panelu"
navFg: "Text na postranním panelu"
navHoverFg: "Text na postranním panelu (Hover)"
navActive: "Text na postranním panelu (Aktivní)"
navIndicator: "Indikátor na postranním panelu"
link: "Odkaz"
@ -1629,11 +1648,8 @@ _theme:
buttonHoverBg: "Pozadí tlačítka (Hover)"
inputBorder: "Ohraničení vstupního pole"
driveFolderBg: "Pozadí složky disku"
wallpaperOverlay: "Překrytí tapety"
badge: "Odznak"
messageBg: "Pozadí chatu"
accentDarken: "Akcent (Ztmavený)"
accentLighten: "Akcent (Zesvětlený)"
fgHighlighted: "Zvýrazněný text"
_sfx:
note: "Poznámky"
@ -1709,6 +1725,7 @@ _permissions:
"write:gallery": "Upravit galerii"
"read:gallery-likes": "Zobrazit seznam to se mi líbí příspěvků v galerii"
"write:gallery-likes": "Upravit seznam to se mi líbí příspěvků v galerii"
"write:chat": "Sestavit nebo mazat zprávy chatu"
_auth:
shareAccessTitle: "Udělovat oprávnění k aplikacím"
shareAccess: "Chcete autorizovat \"{name}\" pro přístup k tomuto účtu?"
@ -2024,3 +2041,7 @@ _reversi:
_remoteLookupErrors:
_noSuchObject:
title: "Nenalezeno"
_search:
searchScopeAll: "Vše"
searchScopeLocal: "Místní"
searchScopeUser: "Upřesnit uživatele"

View file

@ -49,7 +49,7 @@ pin: "An dein Profil anheften"
unpin: "Von deinem Profil lösen"
copyContent: "Inhalt kopieren"
copyLink: "Link kopieren"
copyRemoteLink: "Renote-Link kopieren"
copyRemoteLink: "Remote-Link kopieren"
copyLinkRenote: "Renote-Link kopieren"
delete: "Löschen"
deleteAndEdit: "Löschen und Bearbeiten"
@ -289,7 +289,6 @@ deleteAreYouSure: "Möchtest du „{x}“ wirklich löschen?"
resetAreYouSure: "Wirklich zurücksetzen?"
areYouSure: "Bist du sicher?"
saved: "Erfolgreich gespeichert"
messaging: "Chat"
upload: "Hochladen"
keepOriginalUploading: "Originalbild speichern"
keepOriginalUploadingDescription: "Speichert das Originalbild so, wie es ist. Ist dies deaktiviert, wird eine Version zum Anzeigen im Internet generiert."
@ -302,7 +301,7 @@ uploadFromUrlMayTakeTime: "Es kann eine Weile dauern, bis das Hochladen abgeschl
explore: "Erkunden"
messageRead: "Gelesen"
noMoreHistory: "Kein weiterer Verlauf vorhanden"
startMessaging: "Neuen Chat erstellen"
startChat: "Chat starten"
nUsersRead: "Von {n} Benutzern gelesen"
agreeTo: "Ich stimme {0} zu"
agree: "Zustimmen"
@ -491,8 +490,6 @@ noteOf: "Notiz von {user}"
quoteAttached: "Zitat"
quoteQuestion: "Als Zitat anhängen?"
attachAsFileQuestion: "Der Text in der Zwischenablage ist lang. Möchtest du ihn als Textdatei anhängen?"
noMessagesYet: "Noch keine Nachrichten vorhanden"
newMessageExists: "Du hast eine neue Nachricht"
onlyOneFileCanBeAttached: "Es kann pro Nachricht nur eine Datei angehängt werden"
signinRequired: "Bitte registriere oder melde dich an, um fortzufahren"
signinOrContinueOnRemote: "Um fortzufahren, gehe zu deiner Instanz oder registriere bzw. melde dich an dieser Instanz an. "
@ -698,6 +695,7 @@ userSaysSomethingAbout: "{name} sagt etwas über '{word}'"
makeActive: "Aktivieren"
display: "Anzeigeart"
copy: "Kopieren"
copiedToClipboard: "In die Zwischenablage kopiert"
metrics: "Metriken"
overview: "Übersicht"
logs: "Protokolle"
@ -863,7 +861,7 @@ administration: "Verwaltung"
accounts: "Benutzerkonten"
switch: "Wechseln"
noMaintainerInformationWarning: "Betreiberinformationen sind nicht konfiguriert."
noInquiryUrlWarning: "Keine gültige URL."
noInquiryUrlWarning: "Keine gültige Kontakt-URL."
noBotProtectionWarning: "Schutz vor Bots ist nicht konfiguriert."
configure: "Konfigurieren"
postToGallery: "Neuen Galeriebeitrag erstellen"
@ -964,8 +962,8 @@ cropImageAsk: "Möchtest du das Bild zuschneiden?"
cropYes: "Zuschneiden"
cropNo: "Unbearbeitet verwenden"
file: "Datei"
recentNHours: "Letzten {n} Stunden"
recentNDays: "Letzten {n} Tage"
recentNHours: "Letzte {n} Stunden"
recentNDays: "Letzte {n} Tage"
noEmailServerWarning: "Es ist kein Email-Server konfiguriert."
thereIsUnresolvedAbuseReportWarning: "Es liegen ungelöste Meldungen vor."
recommended: "Empfehlung"
@ -973,7 +971,7 @@ check: "Check"
driveCapOverrideLabel: "Die Drive-Kapazität dieses Nutzers verändern"
driveCapOverrideCaption: "Gib einen Wert von 0 oder weniger ein, um die Kapazität auf den Standard zurückzusetzen."
requireAdminForView: "Melde dich mit einem Administratorkonto an, um dies einzusehen."
isSystemAccount: "Ein Benutzerkonto, dass durch das System erstellt und automatisch kontrolliert wird."
isSystemAccount: "Ein Benutzerkonto, das durch das System erstellt und automatisch verwaltet wird."
typeToConfirm: "Bitte gib zur Bestätigung {x} ein"
deleteAccount: "Benutzerkonto löschen"
document: "Dokumentation"
@ -1144,7 +1142,7 @@ preventAiLearning: "Verwendung in machinellem Lernen (Generative bzw. Prediktive
preventAiLearningDescription: "Fordert Crawler auf, gepostetes Text- oder Bildmaterial usw. nicht in Datensätzen für maschinelles Lernen (Generative bzw. Prediktive AI/KI) zu verwenden. Dies wird durch das Hinzufügen einer \"noai\"-Flag in der HTML-Antwort des jeweiligen Inhalts erreicht. Da diese Flag jedoch ignoriert werden kann, ist eine vollständige Verhinderung hierdurch nicht möglich."
options: "Optionen"
specifyUser: "Spezifischer Benutzer"
lookupConfirm: "Zustimmen?"
lookupConfirm: "Bist du sicher, dass du das nachschlagen möchtest?"
openTagPageConfirm: "Hashtag Seite wirklich öffnen?"
specifyHost: "Host"
failedToPreviewUrl: "Vorschau nicht anzeigbar"
@ -1259,7 +1257,7 @@ replaying: "Aufzeichnung"
endReplay: "Aufzeichnung verlassen"
copyReplayData: "Aufzeichnung kopieren"
ranking: "Rangliste"
lastNDays: "Letzten {n} Tage"
lastNDays: "Letzte {n} Tage"
backToTitle: "Zurück zum Startbildschirm"
hemisphere: "Hemisphäre"
withSensitive: "Zeige \"sensitive Inhalte\" an"
@ -1308,15 +1306,127 @@ pleaseSelectAccount: "Bitte Konto auswählen"
availableRoles: "Verfügbare Rollen"
federationSpecified: "Dieser Server arbeitet mit Whitelist-Föderation. Er kann nicht mit anderen als den vom Administrator angegebenen Servern interagieren."
federationDisabled: "Föderation ist auf diesem Server deaktiviert. Es ist nicht möglich, mit Benutzern auf anderen Servern zu interagieren."
confirmOnReact: "Reagieren bestätigen"
reactAreYouSure: "Willst du eine \"{emoji}\"-Reaktion hinzufügen?"
markAsSensitiveConfirm: "Möchtest du dieses Medium als sensibel kennzeichnen?"
unmarkAsSensitiveConfirm: "Möchtest du die Kennzeichnung dieses Mediums als sensibel aufheben?"
preferences: "Einstellungen"
preferencesProfile: "Einstellungsprofil"
copyPreferenceId: "Kopiere die Einstellungs-ID"
resetToDefaultValue: "Auf Standard zurücksetzen"
untitled: "Unbenannt"
noName: "Kein Name"
skip: "Überspringen"
restore: "Wiederherstellen"
syncBetweenDevices: "Zwischen Geräten synchronisieren"
preferenceSyncConflictTitle: "Der konfigurierte Wert ist auf dem Server bereits vorhanden."
preferenceSyncConflictText: "Die Einstellungen mit aktivierter Synchronisierung werden ihre Werte auf dem Server speichern. Es gibt jedoch bereits Werte auf dem Server. Welche Einstellungswerte sollen überschrieben werden?"
preferenceSyncConflictChoiceServer: "Konfigurierte Werte auf dem Server"
preferenceSyncConflictChoiceDevice: "Konfigurierte Werte auf dem Gerät"
preferenceSyncConflictChoiceCancel: "Einrichten der Synchronisierung abbrechen"
paste: "Einfügen"
emojiPalette: "Emoji-Palette"
postForm: "Notizfenster"
textCount: "Zeichenanzahl"
information: "Über"
chat: "Chat"
migrateOldSettings: "Alte Client-Einstellungen migrieren"
migrateOldSettings_description: "Dies sollte normalerweise automatisch geschehen, aber wenn die Migration aus irgendeinem Grund nicht erfolgreich war, kannst du den Migrationsprozess selbst manuell auslösen. Die aktuellen Konfigurationsinformationen werden dabei überschrieben."
compress: "Komprimieren"
_chat:
noMessagesYet: "Noch keine Nachrichten"
newMessage: "Neue Nachricht"
individualChat: "Privater Chat"
individualChat_description: "Führe einen privaten Chat mit einer anderen Person."
roomChat_description: "Ein Chat-Raum, an dem mehrere Personen teilnehmen können.\nDu kannst auch Personen einladen, die keine privaten Chats zulassen, wenn sie die Einladung annehmen."
createRoom: "Raum erstellen"
inviteUserToChat: "Lade Benutzer ein, um mit dem Chatten zu beginnen"
yourRooms: "Erstellte Räume"
invitations: "Einladen"
noInvitations: "Keine Einladungen"
history: "Verlauf"
noHistory: "Kein Verlauf gefunden"
noRooms: "Keine Räume gefunden"
inviteUser: "Benutzer einladen"
sentInvitations: "Verschickte Einladungen"
join: "Beitreten"
ignore: "Ignorieren"
leave: "Raum verlassen"
members: "Mitglieder"
searchMessages: "Nachrichten suchen"
home: "Startseite"
send: "Senden"
newline: "Neue Zeile"
muteThisRoom: "Raum stummschalten"
deleteRoom: "Raum löschen"
chatNotAvailableForThisAccountOrServer: "Der Chat ist auf diesem Server oder für dieses Konto nicht aktiviert."
chatNotAvailableInOtherAccount: "Die Chatfunktion wurde vom anderen Benutzer deaktiviert."
cannotChatWithTheUser: "Starten eines Chats mit diesem Benutzer nicht möglich"
cannotChatWithTheUser_description: "Der Chat ist entweder nicht verfügbar oder die andere Seite hat den Chat nicht aktiviert."
chatWithThisUser: "Mit dem Benutzer chatten"
thisUserAllowsChatOnlyFromFollowers: "Dieser Benutzer nimmt nur Chats von Followern an."
thisUserAllowsChatOnlyFromFollowing: "Dieser Benutzer nimmt nur Chats von Benutzern an, denen er folgt."
thisUserAllowsChatOnlyFromMutualFollowing: "Dieser Benutzer akzeptiert nur Chats von Benutzern, die sich gegenseitig folgen."
thisUserNotAllowedChatAnyone: "Dieser Benutzer nimmt keine Chats von anderen Benutzern an."
chatAllowedUsers: "Wem das Chatten erlaubt werden soll"
chatAllowedUsers_note: "Du kannst unabhängig von dieser Einstellung mit allen Personen chatten, denen du eine Chat-Nachricht gesendet hast."
_chatAllowedUsers:
everyone: "Jeder"
followers: "Nur deine Follower"
following: "Nur Benutzer, denen du folgst"
mutual: "Nur Benutzer, die sich gegenseitig folgen"
none: "Niemand"
_emojiPalette:
palettes: "Palette"
enableSyncBetweenDevicesForPalettes: "Synchronisierung der Paletten zwischen Geräten aktivieren"
paletteForMain: "Hauptpalette"
paletteForReaction: "Reaktions-Palette"
_settings:
driveBanner: "Du kannst den Drive verwalten und konfigurieren, die Auslastung überprüfen und Einstellungen für das Hochladen von Dateien vornehmen."
pluginBanner: "Du kannst die Funktionen des Clients mit Plugins erweitern. Plugins können installiert, individuell konfiguriert und verwaltet werden."
api: "API"
webhook: "Webhook"
serviceConnectionBanner: "Du kannst Zugriffstoken und Webhooks für die Integration mit externen Anwendungen und Diensten verwalten und konfigurieren."
accountData: "Kontodaten"
accountDataBanner: "Export/Import und Verwaltung von Kontodatenarchiven."
muteAndBlockBanner: "Du kannst Einstellungen konfigurieren und verwalten, um Inhalte auszublenden und Aktionen für bestimmte Benutzer zu beschränken."
accessibilityBanner: "Die Clients können personalisiert und für eine optimale Nutzung im Hinblick auf ihre Darstellung und ihr Verhalten eingerichtet werden."
privacyBanner: "Du kannst Einstellungen für die Privatsphäre deines Kontos vornehmen, z. B. inwieweit Inhalte veröffentlicht werden, wie leicht sie zu finden sind und ob Follower genehmigt werden müssen."
securityBanner: "Du kannst Einstellungen für die Kontosicherheit konfigurieren, z. B. Passwörter, Anmeldemethoden, Authentifizierungs-Apps und Passkeys."
appearanceBanner: "Du kannst das Erscheinungsbild und die Anzeigeeinstellungen für den Client nach deinen Wünschen konfigurieren."
soundsBanner: "Du kannst die Einstellungen für die Wiedergabe von Klängen im Client konfigurieren."
timelineAndNote: "Chroniken und Notizen"
makeEveryTextElementsSelectable: "Alle Textelemente auswählbar machen"
makeEveryTextElementsSelectable_description: "Die Aktivierung kann in manchen Situationen die Benutzerfreundlichkeit beeinträchtigen."
ifOn: "Wenn eingeschaltet"
ifOff: "Wenn ausgeschaltet"
_chat:
showSenderName: "Name des Absenders anzeigen"
sendOnEnter: "Eingabetaste sendet Nachricht"
_preferencesProfile:
profileName: "Profilname"
profileNameDescription: "Lege einen Namen fest, der dieses Gerät identifiziert."
profileNameDescription2: "Beispiel: \"Haupt-PC\", \"Smartphone\""
_preferencesBackup:
autoBackup: "Automatische Sicherung"
restoreFromBackup: "Wiederherstellen aus der Sicherung"
noBackupsFoundTitle: "Keine Sicherungen gefunden"
noBackupsFoundDescription: "Es wurden keine automatisch erstellten Sicherungen gefunden, aber wenn du eine Sicherungsdatei manuell gespeichert hast, kannst du diese importieren und wiederherstellen."
selectBackupToRestore: "Wähle die wiederherzustellende Sicherung"
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."
_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."
requireSigninToViewContentsDescription2: "Der Inhalt wird nicht in URL-Vorschauen (OGP), eingebettet in Webseiten oder auf Servern, die keine Zitate unterstützen, angezeigt."
requireSigninToViewContentsDescription3: "Diese Einschränkungen gelten möglicherweise nicht für föderierte Inhalte von anderen Servern."
makeNotesFollowersOnlyBefore: "Macht frühere Notizen nur für Follower sichtbar"
makeNotesFollowersOnlyBeforeDescription: "Solange diese Funktion aktiviert ist, sind Notizen, die nach dem eingestellten Datum und der eingestellten Zeit liegen oder die eingestellte Zeit abgelaufen ist, nur für Follower sichtbar. Bei Deaktivierung wird auch der öffentliche Status der Notiz wiederhergestellt."
makeNotesHiddenBefore: "Frühere Notizen privat machen"
makeNotesHiddenBeforeDescription: ""
mayNotEffectForFederatedNotes: "Dies hat möglicherweise keine Auswirkungen auf Notizen, die an andere Server föderiert werden."
mayNotEffectSomeSituations: "Diese Einschränkungen sind vereinfacht. Sie gelten möglicherweise nicht in allen Situationen, z. B. bei der Anzeige auf einem fremden Server oder während der Moderation."
notesOlderThanSpecifiedDateAndTime: "Notizen vor einem bestimmtem Datum und Uhrzeit"
_abuseUserReport:
forward: "Weiterleiten"
@ -1324,11 +1434,15 @@ _abuseUserReport:
resolve: "lösen"
accept: "Akzeptieren"
reject: "Ablehnen"
resolveTutorial: "Wenn der Inhalt der Meldung rechtmäßig ist, wähle „Akzeptieren“, um sie als gelöst zu markieren.\nWenn der Inhalt der Meldung unzulässig ist, wähle „Ablehnen“, um sie zu ignorieren."
_delivery:
status: "Auslieferungsstatus"
stop: "Gesperrt"
_type:
none: "Wird veröffentlicht"
manuallySuspended: "Manuell gesperrt"
goneSuspended: "Gesperrt wegen Löschung des Servers"
autoSuspendedForNotResponding: "Gesperrt, weil der Server nicht antwortet"
_bubbleGame:
howToPlay: "Wie man spielt"
hold: "Halten"
@ -1338,6 +1452,8 @@ _bubbleGame:
highScore: "Höchstpunktzahl"
maxChain: "Maximale Anzahl an Verkettungen"
yen: "{yen} Yen"
estimatedQty: "{qty} Stück"
scoreSweets: "{onigiriQtyWithUnit} Onigiri"
_howToPlay:
section1: "Passe die Position an und lasse das Objekt in das Spielfeld fallen."
section2: "Wenn sich zwei Objekte der gleichen Art berühren, verwandeln sie sich in ein anderes Objekt und du bekommst Punkte."
@ -1383,6 +1499,9 @@ _initialTutorial:
title: "Was sind Notizen?"
description: "Beiträge auf Misskey heißen \"Notizen\". Notizen werden chronologisch in der Chronik angeordnet und in Echtzeit aktualisiert."
reply: "Klicke auf diesen Button, um auf eine Nachricht zu antworten. Es ist auch möglich, auf Antworten zu antworten und die Unterhaltung wie einen Thread fortzusetzen."
renote: "Du kannst diese Notiz in deiner eigenen Chronik teilen. Du kannst sie auch mit deinen Kommentaren zitieren."
reaction: "Du kannst der Notiz Reaktionen hinzufügen. Weitere Einzelheiten werden auf der nächsten Seite erläutert."
menu: "Du kannst Details zu Notizen anzeigen, Links kopieren und verschiedene andere Aktionen durchführen."
_reaction:
title: "Was sind Reaktionen?"
description: "Auf Notizen kann mit verschiedenen Emojis reagiert werden. Reaktionen ermöglichen es dir, Nuancen auszudrücken, die mit einem einfachen „Gefällt mir“ vielleicht nicht ausgedrückt werden können."
@ -1392,22 +1511,37 @@ _initialTutorial:
reactDone: "Du kannst eine Reaktion zurücknehmen, indem du auf den '-' Button drückst."
_timeline:
title: "So funktionieren die Chroniken"
description1: "Misskey stellt mehrere Chroniken bereit (einige können je nach den Richtlinien des Servers nicht verfügbar sein)."
home: "Du kannst Beiträge von den Konten sehen, denen du folgst."
local: "Du kannst Beiträge aller Benutzer auf diesem Server sehen."
social: "Notizen von der Startseite und der lokalen Chronik werden angezeigt."
global: "Du kannst Notizen von allen föderierten Servern sehen."
description2: "Du kannst jederzeit am oberen Rand des Bildschirms zwischen den jeweiligen Chroniken wechseln."
description3: "Darüber hinaus gibt es Listen-Chroniken und Kanal-Chroniken. Weitere Einzelheiten findest du unter {link}."
_postNote:
description1: "Wenn du eine Notiz auf Misskey veröffentlichst, stehen dir verschiedene Optionen zur Verfügung. Die Oberfläche sieht folgendermaßen aus."
_visibility:
description: "Du kannst einschränken, wer deine Notiz sehen kann."
public: "Deine Notiz wird für alle Nutzer sichtbar sein."
home: "Nur auf der Startseite sichtbar. Kann von Followern, Profilbesuchern und durch Renotes gesehen werden."
followers: "Nur für Follower sichtbar. Nur Follower können es sehen und niemand sonst, und es kann nicht von anderen gerenoted werden."
direct: "Die Notiz wird nur für den angegebenen Benutzer veröffentlicht und der Empfänger wird benachrichtigt. Kann anstelle von Direktnachrichten verwendet werden."
doNotSendConfidencialOnDirect1: "Sei vorsichtig, wenn du sensible Informationen verschickst!"
doNotSendConfidencialOnDirect2: "Die Administratoren des Servers können den Inhalt der Notiz sehen. Sei vorsichtig mit sensiblen Informationen, wenn du Direktnachrichten an Benutzer auf nicht vertrauenswürdigen Servern sendest."
localOnly: "Wenn du eine Notiz mit dieser Einstellung veröffentlichst, wird sie nicht an andere Server weitergeleitet. Benutzer auf anderen Servern können diese Notizen nicht direkt sehen, unabhängig von den obigen Anzeigeeinstellungen."
_cw:
title: "Inhaltswarnung"
description: "Anstelle des Textes wird das angezeigt, was du im Abschnitt „Anmerkungen“ angibst. Drücke auf „Inhalt anzeigen“, um den vollständigen Text zu sehen."
_exampleNote:
cw: "Das wird dich bestimmt hungrig machen!"
note: "Ich hatte gerade einen Donut mit Schokoladenüberzug 🍩😋"
useCases: "Dient zur Kennzeichnung von Notizen, wie sie in den Serverrichtlinien vorgeschrieben sind, oder zur eigenen Festlegung von Spoiler-Beiträgen oder sensiblem Text."
_howToMakeAttachmentsSensitive:
title: "Wie markiert man Anhänge als sensibel?"
description: "Markiere Anhänge als sensibel, die aufgrund von den Serverregeln nicht sichtbar sein sollen."
tryThisFile: "Versuche, das angehängte Bild als sensibel zu markieren!"
_exampleNote:
note: "Ups, ich habe es vergeigt, den Natto-Deckel zu öffnen..."
method: "Um einen Anhang als sensibel zu kennzeichnen, klicke auf das Vorschaubild der Datei, um das Menü zu öffnen, und klicke auf „Als sensibel markieren“."
sensitiveSucceeded: "Wenn du Dateien anhängst, stelle bitte die Sensibilität entsprechend der Serverrichtlinien ein."
doItToContinue: "Markiere die angehängte Datei als sensibel, um fortzufahren."
@ -1415,7 +1549,9 @@ _initialTutorial:
title: "Du hast das Tutorial abgeschlossen! 🎉"
description: "Die hier beschriebenen Funktionen sind nur ein kleiner Teil dessen, was Misskey zu bieten hat; um mehr darüber zu erfahren, wie du Misskey benutzen kannst, besuche bitte {link}."
_timelineDescription:
home: "In der Startseiten-Chronik kannst du Notizen von Konten sehen, denen du folgst."
local: "In der lokalen Chronik siehst du Notizen von allen Benutzern auf diesem Server."
social: "Die soziale Chronik zeigt Notizen von der Startseite und der lokalen Chronik."
global: "In der globalen Chronik siehst du Notizen von allen föderierten Servern."
_serverRules:
description: "Eine Reihe von Regeln, die vor der Registrierung angezeigt werden. Eine Zusammenfassung der Nutzungsbedingungen anzuzeigen ist empfohlen."
@ -1431,6 +1567,10 @@ _serverSettings:
fanoutTimelineDescription: "Ist diese Option aktiviert, kann eine erhebliche Verbesserung im Abrufen von Chroniken und eine Reduzierung der Datenbankbelastung erzielt werden, im Gegenzug zu einer Steigerung in der Speichernutzung von Redis. Bei geringem Serverspeicher oder Serverinstabilität kann diese Option deaktiviert werden."
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."
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"
openRegistrationWarning: "Das Aktivieren von Registrierungen ist riskant. Es wird empfohlen, sie nur dann zu aktivieren, wenn der Server ständig überwacht wird und im Falle eines Problems sofort reagiert werden kann."
thisSettingWillAutomaticallyOffWhenModeratorsInactive: "Wenn über einen bestimmten Zeitraum keine Moderatorenaktivität festgestellt wird, wird diese Einstellung automatisch deaktiviert, um Spam zu verhindern."
_accountMigration:
@ -1695,8 +1835,10 @@ _achievements:
description: "Tutorial abgeschlossen"
_bubbleGameExplodingHead:
title: "🤯"
description: "Das größte Objekt im Bubble Game"
_bubbleGameDoubleExplodingHead:
title: "Doppel🤯"
description: "Zwei der größten Objekte im Bubble Game zur gleichen Zeit"
_role:
new: "Rolle erstellen"
edit: "Rolle bearbeiten"
@ -1746,6 +1888,7 @@ _role:
canManageAvatarDecorations: "Profilbilddekorationen verwalten"
driveCapacity: "Drive-Kapazität"
alwaysMarkNsfw: "Dateien immer als NSFW markieren"
canUpdateBioMedia: "Kann ein Profil- oder ein Bannerbild bearbeiten"
pinMax: "Maximale Anzahl an angehefteten Notizen"
antennaMax: "Maximale Anzahl an Antennen"
wordMuteMax: "Maximale Zeichenlänge für Wortstummschaltungen"
@ -1761,11 +1904,20 @@ _role:
canUseTranslator: "Verwendung des Übersetzers"
avatarDecorationLimit: "Maximale Anzahl an Profilbilddekorationen, die angebracht werden können"
canImportAntennas: "Importieren von Antennen erlauben"
canImportBlocking: "Importieren von Blockierungen zulassen"
canImportFollowing: "Importieren von Gefolgten zulassen"
canImportMuting: "Importieren von Stummgeschalteten zulassen"
canImportUserLists: "Importieren von Listen erlauben"
canChat: "Chatten erlauben"
_condition:
roleAssignedTo: "Manuellen Rollen zugewiesen"
isLocal: "Lokaler Benutzer"
isRemote: "Benutzer fremder Instanz"
isCat: "Katzen-Benutzer"
isBot: "Bot-Benutzer"
isSuspended: "Gesperrter Benutzer"
isLocked: "Private Konten"
isExplorable: "Benutzer, die ihr Konto im \"Erkunden\"-Bereich sichtbar machen"
createdLessThan: "Kontoerstellung liegt weniger als X zurück"
createdMoreThan: "Kontoerstellung liegt mehr als X zurück"
followersLessThanOrEq: "Hat X oder weniger Follower"
@ -1835,6 +1987,7 @@ _plugin:
installWarn: "Installiere bitte nur vertrauenswürdige Plugins."
manage: "Plugins verwalten"
viewSource: "Quelltext anzeigen"
viewLog: "Protokoll anzeigen"
_preferencesBackups:
list: "Erstellte Backups"
saveNew: "Neu erstellen"
@ -1864,6 +2017,8 @@ _aboutMisskey:
contributors: "Hauptmitwirkende"
allContributors: "Alle Mitwirkenden"
source: "Quellcode"
original: "Original"
thisIsModifiedVersion: "{name} verwendet eine modifizierte Version des ursprünglichen Misskey."
translation: "Misskey übersetzen"
donate: "An Misskey spenden"
morePatrons: "Wir schätzen ebenso die Unterstützung vieler anderer hier nicht gelisteter Personen sehr. Danke! 🥰"
@ -1917,6 +2072,7 @@ _theme:
installed: "{name} wurde installiert"
installedThemes: "Installierte Farbschemata"
builtinThemes: "Eingebaute Farbschemata"
instanceTheme: "Server-Thema"
alreadyInstalled: "Dieses Farbschema ist bereits installiert"
invalid: "Der Code dieses Farbschemas ist ungültig"
make: "Farbschema erstellen"
@ -1949,7 +2105,6 @@ _theme:
header: "Kopfzeile"
navBg: "Hintergrund der Seitenleiste"
navFg: "Text der Seitenleiste"
navHoverFg: "Text der Seitenleiste (Mouseover)"
navActive: "Text der Seitenleiste (Aktiv)"
navIndicator: "Indikator der Seitenleiste"
link: "Link"
@ -1972,23 +2127,23 @@ _theme:
buttonHoverBg: "Hintergrund von Schaltflächen (Mouseover)"
inputBorder: "Rahmen von Eingabefeldern"
driveFolderBg: "Hintergrund von Drive-Ordnern"
wallpaperOverlay: "Hintergrundbild-Overlay"
badge: "Wappen"
messageBg: "Hintergrund von Chats"
accentDarken: "Akzent (Verdunkelt)"
accentLighten: "Akzent (Erhellt)"
fgHighlighted: "Hervorgehobener Text"
_sfx:
note: "Notizen"
noteMy: "Meine Notizen"
notification: "Benachrichtigungen"
reaction: "Auswählen einer Reaktion"
chatMessage: "Chat-Nachrichten"
_soundSettings:
driveFile: "Audiodatei aus dem Drive verwenden"
driveFileWarn: "Wähle eine Audiodatei aus dem Drive"
driveFileTypeWarn: "Diese Datei wird nicht unterstützt"
driveFileTypeWarnDescription: "Bitte wähle eine Audiodatei"
driveFileDurationWarn: "Audio zu lang."
driveFileDurationWarnDescription: "Lange Töne kann die Verwendung von Misskey stören. Trotzdem fortfahren?"
driveFileError: "Audio konnte nicht geladen werden. Bitte ändere die Einstellung."
_ago:
future: "Zukunft"
justNow: "Gerade eben"
@ -2000,6 +2155,14 @@ _ago:
monthsAgo: "vor {n} Monat(en)"
yearsAgo: "vor {n} Jahr(en)"
invalid: "Ungültig"
_timeIn:
seconds: "In {n}s"
minutes: "In {n} Min."
hours: "In {n} Std."
days: "In {n} Tagen"
weeks: "In {n} Wochen"
months: "In {n} Monaten"
years: "In {n} Jahren"
_time:
second: "Sekunde(n)"
minute: "Minute(n)"
@ -2033,6 +2196,7 @@ _2fa:
backupCodesDescription: "Verwende diese Codes, falls du nicht mehr auf deine App zur Zweifaktorauthentifizierung zugreifen kannst. Jeder Code kann nur einmal verwendet werden. Bewahre sie an einem sicheren Ort auf."
backupCodeUsedWarning: "Ein Backup-Code wurde verwendet. Falls du den Zugriff zu deiner Zweifaktorauthentifizierungsapp verloren hast, konfiguriere diese bitte möglichst bald erneut."
backupCodesExhaustedWarning: "Alle Backup-Codes wurden verwendet. Falls du den Zugang zu deiner Zweifaktorauthentifizierungsapp verlierst, wirst du dich nicht mehr in dieses Konto einloggen können. Bitte konfiguriere diese App erneut."
moreDetailedGuideHere: "Hier ist eine ausführliche Anleitung"
_permissions:
"read:account": "Deine Benutzerkontoinformationen lesen"
"write:account": "Deine Benutzerkontoinformationen bearbeiten"
@ -2070,6 +2234,7 @@ _permissions:
"write:flash": "Deine Plays bearbeiten oder löschen"
"read:flash-likes": "Liste der Plays, die mir gefallen, lesen"
"write:flash-likes": "Liste der Plays, die mir gefallen, bearbeiten"
"read:admin:abuse-user-reports": "Meldungen von Benutzern ansehen"
"write:admin:delete-account": "Benutzerkonto löschen"
"write:admin:delete-all-files-of-a-user": "Alle Dateien eines Benutzers löschen"
"read:admin:index-stats": "Statistiken zu Datenbankindizes einsehen"
@ -2077,10 +2242,17 @@ _permissions:
"read:admin:user-ips": "IP-Adressen von Benutzern anzeigen"
"read:admin:meta": "Metadaten der Instanz einsehen"
"write:admin:reset-password": "Benutzerpasswort zurücksetzen"
"write:admin:resolve-abuse-user-report": "Meldungen von Benutzern lösen"
"write:admin:send-email": "E-Mail versenden"
"read:admin:server-info": "Serverinformationen anzeigen"
"read:admin:show-moderation-log": "Moderationsprotokoll einsehen"
"read:admin:show-user": "Private Benutzerinformationen einsehen"
"write:admin:suspend-user": "Benutzer sperren"
"write:admin:unset-user-avatar": "Benutzer-Profilbild entfernen"
"write:admin:unset-user-banner": "Benutzer-Banner entfernen"
"write:admin:unsuspend-user": "Benutzer entsperren"
"write:admin:meta": "Metadaten der Instanz verwalten"
"write:admin:user-note": "Moderationsvermerke verwalten"
"write:admin:roles": "Rollen verwalten"
"read:admin:roles": "Rollen anzeigen"
"write:admin:relays": "Relays verwalten"
@ -2097,6 +2269,17 @@ _permissions:
"read:admin:emoji": "Emojis anzeigen"
"write:admin:queue": "Job-Warteschlange verwalten"
"read:admin:queue": "Job-Warteschlange anzeigen"
"write:admin:drive": "Benutzer-Drive verwalten"
"read:admin:drive": "Benutzer-Drive ansehen"
"read:admin:stream": "Verwendung der Websocket-API für Administratoren"
"write:admin:ad": "Werbung verwalten"
"read:admin:ad": "Werbung ansehen"
"write:invite-codes": "Einladungscodes erstellen"
"read:invite-codes": "Einladungscodes anzeigen"
"read:federation": "Informationen zur Föderation einsehen"
"write:report-abuse": "Verstöße melden"
"write:chat": "Chats bedienen"
"read:chat": "Chats durchsuchen"
_auth:
shareAccessTitle: "Verteilung von App-Berechtigungen"
shareAccess: "Möchtest du „{name}“ authorisieren, auf dieses Benutzerkonto zugreifen zu können?"
@ -2105,8 +2288,10 @@ _auth:
permissionAsk: "Diese Anwendung fordert folgende Berechtigungen"
pleaseGoBack: "Bitte kehre zur Anwendung zurück"
callback: "Es wird zur Anwendung zurückgekehrt"
accepted: "Zugriff gewährt"
denied: "Zugriff verweigert"
pleaseLogin: "Bitte logge dich ein, um Apps zu authorisieren."
byClickingYouWillBeRedirectedToThisUrl: "Wenn der Zugang gewährt wird, wirst du automatisch zu folgender URL weitergeleitet"
_antennaSources:
all: "Alle Notizen"
homeTimeline: "Notizen von Benutzern, denen gefolgt wird"
@ -2215,7 +2400,9 @@ _profile:
changeBanner: "Banner ändern"
verifiedLinkDescription: "Gibst du hier eine URL ein, die einen Link zu deinem Profile enthält, wird neben diesem Feld ein Icon zur Besitzbestätigung angezeigt."
avatarDecorationMax: "Du kannst bis zu {max} Dekorationen hinzufügen."
followedMessage: "Nachricht, wenn dir jemand folgt"
followedMessageDescription: "Du kannst eine kurze Nachricht festlegen, die dem Empfänger angezeigt wird, wenn er dir folgt."
followedMessageDescriptionForLockedAccount: "Wenn Folgeanfragen deine Genehmigung brauchen, wird dies beim Genehmigen einer Anfrage angezeigt."
_exportOrImport:
allNotes: "Alle Notizen"
favoritedNotes: "Als Favorit markierte Notizen"
@ -2273,6 +2460,7 @@ _play:
title: "Titel"
script: "Skript"
summary: "Beschreibung"
visibilityDescription: "Wenn du die Sichtbarkeit auf Privat stellst, wird der Play nicht auf deinem Profil sichtbar sein, aber jeder, der die URL hat, kann ihn trotzdem aufrufen."
_pages:
newPage: "Seite erstellen"
editPage: "Seite bearbeiten"
@ -2304,6 +2492,7 @@ _pages:
eyeCatchingImageSet: "Vorschaubild festlegen"
eyeCatchingImageRemove: "Vorschaubild entfernen"
chooseBlock: "Block hinzufügen"
enterSectionTitle: "Titel des Abschnitts eingeben"
selectType: "Typ auswählen"
contentBlocks: "Inhalt"
inputBlocks: "Eingabe"
@ -2314,6 +2503,8 @@ _pages:
section: "Abschnitt"
image: "Bild"
button: "Knopf"
dynamic: "Dynamische Bausteine"
dynamicDescription: "Dieser Baustein wurde abgeschafft. Bitte verwende von nun an {play}."
note: "Eingebettete Notiz"
_note:
id: "Notiz-ID"
@ -2336,6 +2527,7 @@ _notification:
newNote: "Neue Notiz"
unreadAntennaNote: "Antenne {name}"
roleAssigned: "Rolle zugewiesen"
chatRoomInvitationReceived: "Du wurdest in einen Chatraum eingeladen"
emptyPushNotificationMessage: "Push-Benachrichtigungen wurden aktualisiert"
achievementEarned: "Errungenschaft freigeschaltet"
testNotification: "Testbenachrichtigung"
@ -2343,9 +2535,13 @@ _notification:
sendTestNotification: "Testbenachrichtigung senden"
notificationWillBeDisplayedLikeThis: "Benachrichtigungen sehen so aus"
reactedBySomeUsers: "{n} Benutzer haben eine Reaktion geschickt"
likedBySomeUsers: "{n} Benutzer mochten deine Notiz"
renotedBySomeUsers: "Renote von {n} Benutzern"
followedBySomeUsers: "Von {n} Benutzern gefolgt"
flushNotification: "Benachrichtigungen löschen"
exportOfXCompleted: "Der Export von {x} ist abgeschlossen"
login: "Neue Anmeldung erfolgt"
createToken: "Ein Zugangstoken wurde erstellt"
_types:
all: "Alle"
note: "Neue Notizen"
@ -2359,8 +2555,12 @@ _notification:
receiveFollowRequest: "Erhaltene Follow-Anfragen"
followRequestAccepted: "Akzeptierte Follow-Anfragen"
roleAssigned: "Rolle zugewiesen"
chatRoomInvitationReceived: "Einladungen zum Chatraum"
achievementEarned: "Errungenschaft freigeschaltet"
login: "Anmelden"
exportCompleted: "Der Export ist abgeschlossen"
login: "Anmeldung"
createToken: "Erstellung von Zugriffstokens"
test: "Test-Benachrichtigungen"
app: "Benachrichtigungen von Apps"
_actions:
followBack: "folgt dir nun auch"
@ -2370,6 +2570,7 @@ _deck:
alwaysShowMainColumn: "Hauptspalte immer zeigen"
columnAlign: "Spaltenausrichtung"
addColumn: "Spalte hinzufügen"
newNoteNotificationSettings: "Benachrichtigungseinstellungen für neue Notizen"
configureColumn: "Spalteneinstellungen"
swapLeft: "Mit linker Spalte tauschen"
swapRight: "Mit rechter Spalte tauschen"
@ -2386,6 +2587,7 @@ _deck:
useSimpleUiForNonRootPages: "Simple Benutzeroberfläche für navigierte Seiten verwenden"
usedAsMinWidthWhenFlexible: "Ist \"Automatische Breitenanpassung\" aktiviert, wird hierfür die minimale Breite verwendet"
flexible: "Automatische Breitenanpassung"
enableSyncBetweenDevicesForProfiles: "Aktivieren der Synchronisierung von Profilinformationen zwischen Geräten"
_columns:
main: "Hauptspalte"
widgets: "Widgets"
@ -2408,6 +2610,7 @@ _drivecleaner:
orderByCreatedAtAsc: "Aufsteigendes Erstelldatum"
_webhookSettings:
createWebhook: "Webhook erstellen"
modifyWebhook: "Webhook bearbeiten"
name: "Name"
secret: "Secret"
trigger: "Auslöser"
@ -2420,12 +2623,29 @@ _webhookSettings:
renote: "Wenn du ein Renote erhältst"
reaction: "Wenn du eine Reaktion erhältst"
mention: "Wenn du erwähnt wirst"
_systemEvents:
abuseReport: "Wenn eine neue Meldung eingeht"
abuseReportResolved: "Wenn eine Meldung gelöst wird"
userCreated: "Beim Anlegen eines Benutzers"
inactiveModeratorsWarning: "Wenn Moderatoren für eine gewisse Zeit inaktiv sind"
inactiveModeratorsInvitationOnlyChanged: "Wenn ein Moderator über einen gewissen Zeitraum inaktiv war und der Server auf Einladungsbasis umgestellt wird"
deleteConfirm: "Bist du sicher, dass du den Webhook löschen willst?"
testRemarks: "Klicke auf die Schaltfläche rechts neben dem Schalter, um einen Test-Webhook mit Dummy-Daten zu senden."
_abuseReport:
_notificationRecipient:
createRecipient: "Meldungsempfänger hinzufügen"
modifyRecipient: "Bearbeite einen Empfänger für Meldungen"
recipientType: "Art der Benachrichtigung"
_recipientType:
mail: "Email"
webhook: "Webhook"
_captions:
mail: "Die Benachrichtigung wird bei Eingang einer Meldung an die E-Mail-Adressen der Moderatoren gesendet"
webhook: "Sendet eine Benachrichtigung an den System Webhook, wenn eine Meldung eingegangen ist oder gelöst wurde"
keywords: "Schlüsselwort"
notifiedUser: "Zu benachrichtigender Benutzer"
notifiedWebhook: "Zu verwendender Webhook"
deleteConfirm: "Bist du sicher, dass du den Empfänger der Benachrichtigung entfernen möchtest?"
_moderationLogTypes:
createRole: "Rolle erstellt"
deleteRole: "Rolle gelöscht"
@ -2450,9 +2670,12 @@ _moderationLogTypes:
resetPassword: "Passwort zurückgesetzt"
suspendRemoteInstance: "Fremde Instanz gesperrt"
unsuspendRemoteInstance: "Fremde Instanz entsperrt"
updateRemoteInstanceNote: "Aktualisierung der Moderationshinweise für fremde Server."
markSensitiveDriveFile: "Datei als sensitiv markiert"
unmarkSensitiveDriveFile: "Datei als nicht sensitiv markiert"
resolveAbuseReport: "Meldung bearbeitet"
forwardAbuseReport: "Meldung weitergeleitet"
updateAbuseReportNote: "Moderationsnotiz einer Meldung aktualisiert"
createInvitation: "Einladung erstellt"
createAd: "Werbung erstellt"
deleteAd: "Werbung gelöscht"
@ -2465,8 +2688,15 @@ _moderationLogTypes:
createSystemWebhook: "System-Webhook erstellt"
updateSystemWebhook: "System-Webhook aktualisiert"
deleteSystemWebhook: "System-Webhook gelöscht"
createAbuseReportNotificationRecipient: "Empfänger für Meldungen erstellt"
updateAbuseReportNotificationRecipient: "Empfänger für Meldungen aktualisiert"
deleteAbuseReportNotificationRecipient: "Empfänger für Meldungen entfernt"
deleteAccount: "Benutzerkonto gelöscht"
deletePage: "Seite gelöscht"
deleteFlash: "Play gelöscht"
deleteGalleryPost: "Galeriebeitrag gelöscht"
deleteChatRoom: "Chatraum gelöscht"
updateProxyAccountDescription: "Beschreibung des Proxy-Benutzerkontos aktualisiert"
_fileViewer:
title: "Dateiinformationen"
type: "Dateityp"
@ -2480,10 +2710,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "Überprüfe vor Installation die Vertrauenswürdigkeit des Vertreibers."
_plugin:
title: "Möchtest du dieses Plugin installieren?"
metaTitle: "Plugininformation"
_theme:
title: "Möchten du dieses Farbschema installieren?"
metaTitle: "Farbschemainfo"
_meta:
base: "Farbschemavorlage"
_vendorInfo:
@ -2516,16 +2744,64 @@ _externalResourceInstaller:
_themeInstallFailed:
title: "Das Farbschema konnte nicht installiert werden"
description: "Während der Installation des Farbschemas ist ein Problem aufgetreten. Bitte versuche es erneut. Detaillierte Fehlerinformationen können über die Javascript-Konsole abgerufen werden."
_dataSaver:
_media:
title: "Laden von Medien verhindern"
description: "Verhindert, dass Bilder/Videos automatisch geladen werden. Ausgeblendete Bilder/Videos werden geladen, wenn du auf sie tippst."
_avatar:
title: "Animierte Profilbilder deaktivieren"
description: "Die Animation von Profilbildern wird angehalten. Da animierte Bilder eine größere Dateigröße haben können als normale Bilder, kann dies den Datenverkehr weiter reduzieren."
_urlPreview:
title: "URL-Vorschaubilder ausblenden"
description: "URL-Vorschaubilder werden nicht mehr geladen."
_code:
title: "Code-Hervorhebungen ausblenden"
description: "Wenn Code-Hervorhebungen in MFM usw. verwendet werden, werden sie erst geladen, wenn sie angetippt werden. Die Syntaxhervorhebung erfordert das Herunterladen der Definitionsdateien für jede Programmiersprache. Es ist daher zu erwarten, dass die Deaktivierung des automatischen Ladens dieser Dateien die Menge des Datenverkehrs reduziert."
_hemisphere:
N: "Nördliche Erdhalbkugel"
S: "Südliche Erdhalbkugel"
caption: "Wird in einigen Client-Einstellungen zur Bestimmung der Jahreszeit verwendet."
_reversi:
reversi: "Reversi"
gameSettings: "Spieleinstellungen"
chooseBoard: "Spielbrett auswählen"
blackOrWhite: "Schwarz/Weiß"
blackIs: "{name} spielt Schwarz"
rules: "Regeln"
thisGameIsStartedSoon: "Das Spiel wird in Kürze beginnen"
waitingForOther: "Warte auf den Zug des Gegenspielers"
waitingForMe: "Warte auf deinen Zug"
waitingBoth: "Mach dich bereit"
ready: "Bereit"
cancelReady: "Nicht bereit"
opponentTurn: "Dein Gegner ist an der Reihe"
myTurn: "Du bist am Zug"
turnOf: "{name} ist am Zug"
pastTurnOf: "Zug von {name}"
surrender: "Aufgeben"
surrendered: "Aufgegeben"
timeout: "Zeit abgelaufen"
drawn: "Unentschieden"
won: "{name} hat gewonnen"
black: "Schwarz"
white: "Weiß"
total: "Gesamt"
turnCount: " Zug {count}"
myGames: "Meine Runden"
allGames: "Alle Runden"
ended: "Beendet"
playing: "Partie läuft"
timeLimitForEachTurn: "Zeitlimit eines Zugs"
freeMatch: "Freies Spiel"
lookingForPlayer: "Gegner werden gesucht..."
gameCanceled: "Das Spiel wurde abgesagt."
shareToTlTheGameWhenStart: "Spiel in der Chronik teilen, wenn es gestartet wurde"
iStartedAGame: "Das Spiel hat begonnen! #MisskeyReversi"
opponentHasSettingsChanged: "Der Gegner hat seine Einstellungen geändert."
allowIrregularRules: "Irreguläre Regeln (völlig frei)"
disallowIrregularRules: "Keine irregulären Regeln"
showBoardLabels: "Anzeige der Zeilen- und Spaltennummern am Spielbrett"
useAvatarAsStone: "Steine in Benutzeravatare umwandeln"
_offlineScreen:
title: "Offline - keine Verbindung zum Server möglich"
header: "Verbindung zum Server nicht möglich"
@ -2539,14 +2815,68 @@ _urlPreviewSetting:
requireContentLength: "Vorschau nur generieren, wenn Content-Length verfügbar ist"
requireContentLengthDescription: "Wenn der Server keine Content-Length zurückgibt, wird keine Vorschau erzeugt."
userAgent: "User-Agent"
userAgentDescription: "Legt den User-Agent fest, der beim Abrufen der Vorschau verwendet werden soll. Bleibt er leer, wird der Standard-User-Agent verwendet."
summaryProxy: "Proxy-Endpunkte, die Vorschaubilder erzeugen"
summaryProxyDescription: "Generierung von Vorschaubildern mit Summaly Proxy anstelle von Misskey selbst."
summaryProxyDescription2: "Die folgenden Parameter werden als Abfrage-Strings mit dem Proxy verknüpft. Wenn der Proxy sie nicht unterstützt, werden die Werte ignoriert."
_mediaControls:
pip: "Bild-in-Bild"
playbackRate: "Wiedergabegeschwindigkeit"
loop: "Endloswiedergabe"
_contextMenu:
title: "Kontextmenü"
app: "Anwendung"
appWithShift: "Anwendung per Umschalttaste"
native: "Natives Browsermenü"
_gridComponent:
_error:
requiredValue: "Dieser Wert ist ein Pflichtfeld"
columnTypeNotSupport: "Die Validierung regulärer Ausdrücke wird nur für Spalten vom Typ \"Text\" unterstützt."
patternNotMatch: "Dieser Wert stimmt nicht mit dem Schema in {pattern} überein"
notUnique: "Dieser Wert muss eindeutig sein"
_roleSelectDialog:
notSelected: "Nicht ausgewählt"
_customEmojisManager:
_gridCommon:
copySelectionRows: "Ausgewählte Zeilen kopieren"
copySelectionRanges: "Auswahl kopieren"
deleteSelectionRows: "Ausgewählte Zeilen löschen"
searchSettings: "Sucheinstellungen"
searchSettingCaption: "Detaillierte Suchkriterien festlegen."
searchLimit: "Anzahl der Ergebnisse"
sortOrder: "Sortierung"
registrationLogs: "Registrierungsprotokoll"
registrationLogsCaption: "Protokolle werden beim Aktualisieren oder Löschen von Emojis angezeigt. Sie verschwinden nach dem Aktualisieren oder Löschen, dem Wechsel zu einer neuen Seite oder dem Neuladen."
alertEmojisRegisterFailedDescription: "Emoji konnte nicht aktualisiert oder gelöscht werden. Bitte prüfe das Registrierungsprotokoll für Details."
_logs:
failureLogNothing: "Es gibt kein Fehlerprotokoll."
logNothing: "Keine Protokoll-Einträge."
_remote:
selectionRowDetail: "Details der ausgewählten Zeile"
importSelectionRangesRows: "Zeilen in der Auswahl importieren"
importEmojisButton: "Ausgewählte Emojis importieren"
confirmImportEmojisTitle: "Emojis importieren"
confirmImportEmojisDescription: "Importiere {count} Emoji(s), die von entfernten Server empfangen wurden. Bitte achte genau auf die Lizenz der Emojis. Bist du sicher, dass du fortfahren möchtest?"
_local:
tabTitleList: "Hinzugefügte Emojis"
tabTitleRegister: "Emojis hinzufügen"
_list:
emojisNothing: "Es wurden keine Emojis hinzugefügt."
alertUpdateEmojisNothingDescription: "Es wurden keine Emojis geändert."
alertDeleteEmojisNothingDescription: "Es gibt keine zu löschenden Emojis."
confirmUpdateEmojisDescription: "Aktualisiere {count} Emoji(s). Willst du fortfahren?"
confirmDeleteEmojisDescription: "Lösche {count} ausgewählte Emoji(s). Willst du fortfahren?"
confirmMovePageDesciption: "An den Emojis auf dieser Seite wurden Änderungen vorgenommen.\nWenn du die Seite verlässt, ohne zu speichern, werden alle auf dieser Seite vorgenommenen Änderungen verworfen."
_register:
uploadSettingDescription: "Hier kannst du das Verhalten beim Hochladen von Emojis konfigurieren."
directoryToCategoryLabel: "Gib den Namen des Verzeichnisses in das Feld „Kategorie“ ein"
directoryToCategoryCaption: "Wenn du ein Verzeichnis ziehst und ablegst, gib den Verzeichnisnamen in das Feld „Kategorie“ ein."
emojiInputAreaList1: "Ziehe Bilddateien oder Verzeichnisse per Drag-and-drop in diesen Rahmen"
emojiInputAreaList2: "Klicke auf diesen Link, um von deinem PC aus zu wählen"
emojiInputAreaList3: "Klicke auf diesen Link, um vom Drive aus zu wählen"
confirmRegisterEmojisDescription: "Füge die in der Liste aufgeführten Emojis als neue benutzerdefinierte Emojis hinzu. Bist du sicher? (Um eine Überlastung zu vermeiden, können nur {count} Emoji(s) in einem Vorgang hinzugefügt werden)"
confirmClearEmojisDescription: "Verwerfe die Bearbeitungen und lösche die Emojis aus der Liste. Bist du sicher, dass du fortfahren möchtest?"
confirmUploadEmojisDescription: "Lade die {count} abgelegte(n) Datei(en) in das Drive hoch. Bist du sicher, dass du fortfahren möchtest?"
_embedCodeGen:
title: "Einbettungscode anpassen"
header: "Kopfzeile anzeigen"
@ -2554,6 +2884,9 @@ _embedCodeGen:
maxHeight: "Maximale Höhe"
maxHeightDescription: "Der Wert 0 deaktiviert die Einstellung der maximalen Höhe. Gib einen Wert an, um zu verhindern, dass das Widget weiterhin vertikal vergrößert wird."
maxHeightWarn: "Die Begrenzung der maximalen Höhe ist deaktiviert (0). Wenn dies nicht beabsichtigt war, setze die maximale Höhe auf einen Wert fest."
previewIsNotActual: "Die Anzeige weicht von der tatsächlichen Einbettung ab, da sie den auf dem Vorschaufenster angezeigten Bereich überschreitet."
rounded: "Ecken abrunden"
border: "Dem äußeren Rand einen Rahmen hinzufügen"
applyToPreview: "Auf die Vorschau anwenden"
generateCode: "Einbettungscode generieren"
codeGenerated: "Der Code wurde generiert"
@ -2562,7 +2895,11 @@ _selfXssPrevention:
warning: "WARNUNG"
title: "„Füge in diesen Bereich etwas ein“ ist eine Betrugsmasche."
description1: "Wenn du hier etwas einfügst, könnte ein böswilliger Benutzer dein Konto übernehmen oder deine persönlichen Daten stehlen."
description2: "Wenn du das nicht genau verstehst, was du einfügst, %csolltest du die Eingabe abbrechen und das Fenster schließen."
description3: "Weitere Informationen findest du hier. {link}"
_followRequest:
recieved: "Anfrage erhalten"
sent: "Anfrage gesendet"
_remoteLookupErrors:
_federationNotAllowed:
title: "Kommunikation mit diesem Server nicht möglich"
@ -2570,6 +2907,45 @@ _remoteLookupErrors:
_uriInvalid:
title: "URI ist fehlerhaft"
description: "Es gibt ein Problem mit der von dir eingegebenen URI. Bitte prüfe, ob du Zeichen eingegeben hast, die in der URI nicht verwendet werden können."
_requestFailed:
title: "Anfrage fehlgeschlagen"
description: "Die Kommunikation mit diesem Server ist fehlgeschlagen. Der Server ist möglicherweise nicht erreichbar. Bitte vergewissere dich auch, dass du keine ungültige oder nicht existierende URI eingegeben hast."
_responseInvalid:
title: "Die Antwort ist ungültig"
description: "Die Kommunikation mit dem Server war erfolgreich, aber die erhaltenen Daten waren nicht korrekt. Wenn du Remote-Inhalte über einen Server eines Dritten abfragst, verwende bitte erneut eine URI, die vom Ursprungsserver abgerufen werden kann."
_noSuchObject:
title: "Nicht gefunden"
description: "Die angeforderte Ressource konnte nicht gefunden werden, bitte überprüfe die URI erneut."
_captcha:
verify: "Bitte beantworte das CAPTCHA"
testSiteKeyMessage: "Du kannst die Vorschau prüfen, indem du die Testwerte für den Site- und Secret-Key eingibst. Weitere Informationen findest du auf der folgenden Seite."
_error:
_requestFailed:
title: "CAPTCHA-Anfrage fehlgeschlagen."
text: "Bitte probiere es später noch einmal oder überprüfe die Einstellungen erneut."
_verificationFailed:
title: "CAPTCHA-Prüfung fehlgeschlagen"
text: "Bitte überprüfe nochmals, ob die Einstellungen korrekt sind."
_unknown:
title: "CAPTCHA-Fehler"
text: "Es ist ein unerwarteter Fehler aufgetreten."
_bootErrors:
title: "Laden fehlgeschlagen"
serverError: "Wenn das Problem nach kurzem Warten und erneutem Laden immer noch nicht behoben ist, wende dich bitte an den Serveradministrator und gib die folgende Fehler-ID an."
solution: "Folgendes könnte das Problem lösen."
solution1: "Aktualisiere deinen Browser und dein Betriebssystem auf die neueste Version"
solution2: "Deaktiviere den Werbeblocker"
solution3: "Leere den Browser-Cache"
solution4: "(Tor Browser) Setze dom.webaudio.enabled auf true"
otherOption: "Weitere Optionen"
otherOption1: "Client-Einstellungen und Cache löschen"
otherOption2: "Einfachen Client starten"
otherOption3: "Starte das Reparaturwerkzeug"
_search:
searchScopeAll: "Alle"
searchScopeLocal: "Lokal"
searchScopeServer: "Bestimmter Server"
searchScopeUser: "Spezifischer Benutzer"
pleaseEnterServerHost: "Gib den Server-Host ein"
pleaseSelectUser: "Benutzer auswählen"
serverHostPlaceholder: "Beispiel: misskey.example.com"

View file

@ -162,14 +162,12 @@ imageUrl: "URL εικόνας"
remove: "Διαγραφή"
removed: "Η διαγραφή ολοκληρώθηκε επιτυχώς"
saved: "Αποθηκεύτηκε"
messaging: "Συνομιλία"
upload: "Ανεβάστε"
fromDrive: "Από τον Αποθηκευτικό Χώρο"
fromUrl: "Από URL"
uploadFromUrl: "Ανεβάστε από URL"
explore: "Εξερευνήστε"
messageRead: "Διαβάστηκε"
startMessaging: "Ξεκινήστε μία συνομιλία"
nUsersRead: "διαβάστηκε από {n}"
start: "Ας αρχίσουμε"
home: "Κεντρικό"
@ -288,6 +286,11 @@ cannotUploadBecauseNoFreeSpace: "Το ανέβασμα απέτυχε λόγω
icon: "Εικονίδιο"
replies: "Απάντηση"
renotes: "Κοινοποίηση σημειώματος"
postForm: "Φόρμα δημοσίευσης"
information: "Πληροφορίες"
_chat:
members: "Μέλη"
home: "Κεντρικό"
_email:
_follow:
title: "Έχετε ένα νέο ακόλουθο"
@ -321,6 +324,7 @@ _permissions:
"write:notifications": "Διαχειριστείτε τις ειδοποιήσεις σας"
"read:pages": "Δείτε τις Σελίδες σας"
"write:pages": "Επεξεργαστείτε ή διαγράψτε τις σελίδες σας"
"write:chat": "Γράψτε ή διαγράψτε μηνύματα συνομιλίας"
_antennaSources:
all: "Όλα τα σημειώματα"
homeTimeline: "Σημειώματα από μέλη που ακολουθείτε"
@ -397,3 +401,5 @@ _moderationLogTypes:
suspend: "Αποβολή"
_reversi:
total: "Σύνολο"
_search:
searchScopeLocal: "Τοπικό"

View file

@ -132,7 +132,7 @@ reaction: "Reactions"
reactions: "Reactions"
emojiPicker: "Emoji picker"
pinnedEmojisForReactionSettingDescription: "Set the emojis to be pinned and displayed when reacting."
pinnedEmojisSettingDescription: "Set the emojis to be pinned and displayed when viewing emoji picker."
pinnedEmojisSettingDescription: "Set the emojis to be pinned and displayed when viewing emoji picker"
emojiPickerDisplay: "Emoji picker display"
overwriteFromPinnedEmojisForReaction: "Override from reaction settings"
overwriteFromPinnedEmojis: "Override from general settings"
@ -289,7 +289,6 @@ deleteAreYouSure: "Are you sure that you want to delete \"{x}\"?"
resetAreYouSure: "Really reset?"
areYouSure: "Are you sure?"
saved: "Saved"
messaging: "Chat"
upload: "Upload"
keepOriginalUploading: "Keep original image"
keepOriginalUploadingDescription: "Saves the originally uploaded image as-is. If turned off, a version to display on the web will be generated on upload."
@ -302,7 +301,7 @@ uploadFromUrlMayTakeTime: "It may take some time until the upload is complete."
explore: "Explore"
messageRead: "Read"
noMoreHistory: "There is no further history"
startMessaging: "Start a new chat"
startChat: "Start chat"
nUsersRead: "read by {n}"
agreeTo: "I agree to {0}"
agree: "Agree"
@ -346,7 +345,7 @@ emptyDrive: "Your Drive is empty"
emptyFolder: "This folder is empty"
unableToDelete: "Unable to delete"
inputNewFileName: "Enter a new filename"
inputNewDescription: "Enter new caption"
inputNewDescription: "Enter new alt text"
inputNewFolderName: "Enter a new folder name"
circularReferenceFolder: "The destination folder is a subfolder of the folder you wish to move."
hasChildFilesOrFolders: "Since this folder is not empty, it can not be deleted."
@ -425,6 +424,7 @@ antennaExcludeBots: "Exclude bot accounts"
antennaKeywordsDescription: "Separate with spaces for an AND condition or with line breaks for an OR condition."
notifyAntenna: "Notify about new notes"
withFileAntenna: "Only notes with files"
hideNotesInSensitiveChannel: "Hide notes from sensitive channels"
enableServiceworker: "Enable Push-Notifications for your Browser"
antennaUsersDescription: "List one username per line"
caseSensitive: "Case sensitive"
@ -491,8 +491,6 @@ noteOf: "Note by {user}"
quoteAttached: "Quote"
quoteQuestion: "Append as quote?"
attachAsFileQuestion: "The text in clipboard is long. Would you want to attach it as text file?"
noMessagesYet: "No messages yet"
newMessageExists: "There are new messages"
onlyOneFileCanBeAttached: "You can only attach one file to a message"
signinRequired: "Please register or sign in before continuing"
signinOrContinueOnRemote: "To continue, you need to move your server or sign up / log in to this server."
@ -586,7 +584,7 @@ popout: "Pop-out"
volume: "Volume"
masterVolume: "Master volume"
notUseSound: "Disable sound"
useSoundOnlyWhenActive: "Output sounds only if Misskey is active."
useSoundOnlyWhenActive: "Output sounds only if Misskey is active"
details: "Details"
renoteDetails: "Renote details"
chooseEmoji: "Select an emoji"
@ -646,8 +644,8 @@ disablePlayer: "Close video player"
expandTweet: "Expand post"
themeEditor: "Theme editor"
description: "Description"
describeFile: "Add caption"
enterFileDescription: "Enter caption"
describeFile: "Add alt text"
enterFileDescription: "Enter alt text"
author: "Author"
leaveConfirm: "There are unsaved changes. Do you want to discard them?"
manage: "Management"
@ -698,6 +696,7 @@ userSaysSomethingAbout: "{name} said something about \"{word}\""
makeActive: "Activate"
display: "Display"
copy: "Copy"
copiedToClipboard: "Copied to clipboard"
metrics: "Metrics"
overview: "Overview"
logs: "Logs"
@ -1016,7 +1015,7 @@ sendPushNotificationReadMessageCaption: "This may increase the power consumption
windowMaximize: "Maximize"
windowMinimize: "Minimize"
windowRestore: "Restore"
caption: "Caption"
caption: "Alt text"
loggedInAsBot: "Currently logged in as bot"
tools: "Tools"
cannotLoad: "Unable to load"
@ -1261,7 +1260,7 @@ copyReplayData: "Copy replay data"
ranking: "Ranking"
lastNDays: "Last {n} days"
backToTitle: "Go back to title"
hemisphere: "Where are you located"
hemisphere: "Where you live"
withSensitive: "Include notes with sensitive files"
userSaysSomethingSensitive: "Post by {name} contains sensitive content"
enableHorizontalSwipe: "Swipe to switch tabs"
@ -1309,6 +1308,130 @@ availableRoles: "Available roles"
acknowledgeNotesAndEnable: "Turn on after understanding the precautions."
federationSpecified: "This server is operated in an allowlist federation. Interacting with servers other than those designated by the administrator is not allowed."
federationDisabled: "Federation is disabled on this server. You cannot interact with users on other servers."
confirmOnReact: "Confirm when reacting"
reactAreYouSure: "Would you like to add a \"{emoji}\" reaction?"
markAsSensitiveConfirm: "Do you want to set this media as sensitive?"
unmarkAsSensitiveConfirm: "Do you want to remove the sensitive designation for this media?"
preferences: "Preferences"
accessibility: "Accessibility"
preferencesProfile: "Preferences profile"
copyPreferenceId: "Copy the preference ID"
resetToDefaultValue: "Revert to default"
overrideByAccount: "Override by the account"
untitled: "Untitled"
noName: "No name"
skip: "Skip"
restore: "Restore"
syncBetweenDevices: "Sync between devices"
preferenceSyncConflictTitle: "The configured value exists on the server."
preferenceSyncConflictText: "The sync enabled settings will save their values to the server. However, there are existing values on the server. Which set of values would you like to overwrite?"
preferenceSyncConflictChoiceServer: "Configured value on server"
preferenceSyncConflictChoiceDevice: "Configured value on device"
preferenceSyncConflictChoiceCancel: "Cancel enabling sync"
paste: "Paste"
emojiPalette: "Emoji palette"
postForm: "Posting form"
textCount: "Character count"
information: "About"
chat: "Chat"
migrateOldSettings: "Migrate old client settings"
migrateOldSettings_description: "This should be done automatically but if for some reason the migration was not successful, you can trigger the migration process yourself manually. The current configuration information will be overwritten."
compress: "Compress"
right: "Right"
bottom: "Bottom"
top: "Top"
embed: "Embed"
_chat:
noMessagesYet: "No messages yet"
newMessage: "New message"
individualChat: "Private Chat"
individualChat_description: "Have a private chat with another person."
roomChat: "Room Chat"
roomChat_description: "A chat room which can have multiple people.\nYou can also invite people who don't allow private chats if they accept the invite."
createRoom: "Create Room"
inviteUserToChat: "Invite users to start chatting"
yourRooms: "Created rooms"
joiningRooms: "Joined rooms"
invitations: "Invite"
noInvitations: "No invitations"
history: "History"
noHistory: "No history available"
noRooms: "No rooms found"
inviteUser: "Invite Users"
sentInvitations: "Sent Invites"
join: "Join"
ignore: "Ignore"
leave: "Leave room"
members: "Members"
searchMessages: "Search messages"
home: "Home"
send: "Send"
newline: "New line"
muteThisRoom: "Mute room"
deleteRoom: "Delete room"
chatNotAvailableForThisAccountOrServer: "Chat is not enabled on this server or for this account."
chatNotAvailableInOtherAccount: "The chat function is disabled for the other user."
cannotChatWithTheUser: "Cannot start a chat with this user"
cannotChatWithTheUser_description: "Chat is either unavailable or the other party has not enabled chat."
chatWithThisUser: "Chat with user"
thisUserAllowsChatOnlyFromFollowers: "This user accepts chats from followers only."
thisUserAllowsChatOnlyFromFollowing: "This user accepts chats only from users they follow."
thisUserAllowsChatOnlyFromMutualFollowing: "This user only accepts chats from users who are mutual followers."
thisUserNotAllowedChatAnyone: "This user is not accepting chats from anyone."
chatAllowedUsers: "Who to allow chatting with"
chatAllowedUsers_note: "You can chat with anyone to whom you have sent a chat message regardless of this setting."
_chatAllowedUsers:
everyone: "Everyone"
followers: "Only your followers"
following: "Only users you are following"
mutual: "Mutual followers only"
none: "Nobody"
_emojiPalette:
palettes: "Palette"
enableSyncBetweenDevicesForPalettes: "Enable palette sync between devices"
paletteForMain: "Main palette"
paletteForReaction: "Reaction palette"
_settings:
driveBanner: "You can manage and configure the drive, check usage, and configure file upload settings."
pluginBanner: "You can extend client features with plugins. You can install plugins, configure and manage individually."
notificationsBanner: "You can configure the types and range of notifications from the server and push notifications."
api: "API"
webhook: "Webhook"
serviceConnection: "Service integration"
serviceConnectionBanner: "Manage and configure access tokens and Webhooks to integrate with external apps or services."
accountData: "Account data"
accountDataBanner: "Export and import to manage account data."
muteAndBlockBanner: "You can configure and manage settings to hide content and restrict actions from specific users."
accessibilityBanner: "You can personalize the client's visuals and behavior, and configure settings to optimize usage."
privacyBanner: "You can configure settings related to account privacy, such as content visibility, discoverability, and follow approval."
securityBanner: "You can configure settings related to account security, such as password, login methods, authentication apps, and Passkeys."
preferencesBanner: "You can configure the overall behavior of the client according to your preferences."
appearanceBanner: "You can configure the appearance and display settings for the client according to your preferences."
soundsBanner: "You can configure the sound settings for playback in the client."
timelineAndNote: "Timeline and note"
makeEveryTextElementsSelectable: "Make all text elements selectable"
makeEveryTextElementsSelectable_description: "Enabling this may reduce usability in some situations."
useStickyIcons: "Make icons follow while scrolling"
showNavbarSubButtons: "Show sub-buttons on the navigation bar"
ifOn: "When turned on"
ifOff: "When turned off"
enableSyncThemesBetweenDevices: "Synchronize installed themes across devices"
_chat:
showSenderName: "Show sender's name"
sendOnEnter: "Press Enter to send"
_preferencesProfile:
profileName: "Profile name"
profileNameDescription: "Set a name that identifies this device."
profileNameDescription2: "Example: \"Main PC\", \"Smartphone\""
_preferencesBackup:
autoBackup: "Auto backup"
restoreFromBackup: "Restore from backup"
noBackupsFoundTitle: "No backups found"
noBackupsFoundDescription: "No auto-created backups were found, but if you have manually saved a backup file, you can import and restore it."
selectBackupToRestore: "Select a backup to restore"
youNeedToNameYourProfileToEnableAutoBackup: "A profile name must be set to enable auto backup."
autoPreferencesBackupIsNotEnabledForThisDevice: "Settings auto backup is not enabled on this device."
backupFound: "Settings backup is found"
_accountSettings:
requireSigninToViewContents: "Require sign-in to view contents"
requireSigninToViewContentsDescription1: "Require login to view all notes and other content you have created. This will have the effect of preventing crawlers from collecting your information."
@ -1319,6 +1442,7 @@ _accountSettings:
makeNotesHiddenBefore: "Make past notes private"
makeNotesHiddenBeforeDescription: "While this feature is enabled, notes that are past the set date and time or have been visible only to you. When it is deactivated, the note publication status will also be restored."
mayNotEffectForFederatedNotes: "Notes federated to a remote server may not be affected."
mayNotEffectSomeSituations: "These restrictions are simplified. They may not apply in some situations, such as when viewing on a remote server or during moderation."
notesHavePassedSpecifiedPeriod: "Note that the specified time has passed"
notesOlderThanSpecifiedDateAndTime: "Notes before the specified date and time"
_abuseUserReport:
@ -1327,7 +1451,7 @@ _abuseUserReport:
resolve: "Resolve"
accept: "Accept"
reject: "Reject"
resolveTutorial: "If the report is legitimate in content, select \"Accept\" to mark the case as resolved in the affirmative.\nIf the content of the report is not legitimate, select \"Reject\" to mark the case as resolved in the negative."
resolveTutorial: "If the report's content is legitimate, select \"Accept\" to mark it as resolved.\nIf the report's content is illegitimate, select \"Reject\" to ignore it."
_delivery:
status: "Delivery status"
stop: "Suspended"
@ -1804,6 +1928,7 @@ _role:
canImportFollowing: "Allow importing following"
canImportMuting: "Allow importing muting"
canImportUserLists: "Allow importing lists"
canChat: "Allow Chat"
_condition:
roleAssignedTo: "Assigned to manual roles"
isLocal: "Local user"
@ -1967,6 +2092,7 @@ _theme:
installed: "{name} has been installed"
installedThemes: "Installed themes"
builtinThemes: "Built-in themes"
instanceTheme: "Server theme"
alreadyInstalled: "This theme is already installed"
invalid: "The format of this theme is invalid"
make: "Make a theme"
@ -1999,7 +2125,6 @@ _theme:
header: "Header"
navBg: "Sidebar background"
navFg: "Sidebar text"
navHoverFg: "Sidebar text (Hover)"
navActive: "Sidebar text (Active)"
navIndicator: "Sidebar indicator"
link: "Link"
@ -2022,17 +2147,15 @@ _theme:
buttonHoverBg: "Button background (Hover)"
inputBorder: "Input field border"
driveFolderBg: "Drive folder background"
wallpaperOverlay: "Wallpaper overlay"
badge: "Badge"
messageBg: "Chat background"
accentDarken: "Accent (Darkened)"
accentLighten: "Accent (Lightened)"
fgHighlighted: "Highlighted Text"
_sfx:
note: "New note"
noteMy: "Own note"
notification: "Notifications"
reaction: "On choosing a reaction"
chatMessage: "Chat Messages"
_soundSettings:
driveFile: "Use an audio file in Drive."
driveFileWarn: "Select an audio file from Drive."
@ -2179,6 +2302,8 @@ _permissions:
"read:clip-favorite": "View favorited clips"
"read:federation": "Get federation data"
"write:report-abuse": "Report violation"
"write:chat": "Compose or delete chat messages"
"read:chat": "Browse Chat"
_auth:
shareAccessTitle: "Granting application permissions"
shareAccess: "Would you like to authorize \"{name}\" to access this account?"
@ -2427,6 +2552,7 @@ _notification:
newNote: "New note"
unreadAntennaNote: "Antenna {name}"
roleAssigned: "Role given"
chatRoomInvitationReceived: "You have been invited to a chat room"
emptyPushNotificationMessage: "Push notifications have been updated"
achievementEarned: "Achievement unlocked"
testNotification: "Test notification"
@ -2440,6 +2566,8 @@ _notification:
flushNotification: "Clear notifications"
exportOfXCompleted: "Export of {x} has been completed"
login: "Someone logged in"
createToken: "An access token has been created"
createTokenDescription: "If you have no idea, delete the access token through \"{text}\"."
_types:
all: "All"
note: "New notes"
@ -2453,9 +2581,11 @@ _notification:
receiveFollowRequest: "Received follow requests"
followRequestAccepted: "Accepted follow requests"
roleAssigned: "Role given"
chatRoomInvitationReceived: "Invited to chat room"
achievementEarned: "Achievement unlocked"
exportCompleted: "The export has been completed"
login: "Sign In"
createToken: "Create access token"
test: "Notification test"
app: "Notifications from linked apps"
_actions:
@ -2465,6 +2595,9 @@ _notification:
_deck:
alwaysShowMainColumn: "Always show main column"
columnAlign: "Align columns"
columnGap: "Margin between columns"
deckMenuPosition: "Deck menu position"
navbarPosition: "Navigation bar position"
addColumn: "Add column"
newNoteNotificationSettings: "Notification setting for new notes"
configureColumn: "Column settings"
@ -2478,11 +2611,12 @@ _deck:
newProfile: "New profile"
deleteProfile: "Delete profile"
introduction: "Create the perfect interface for you by arranging columns freely!"
introduction2: "Click on the + on the right of the screen to add new colums whenever you want."
introduction2: "Click on the + on the right of the screen to add new columns whenever you want."
widgetsIntroduction: "Please select \"Edit widgets\" in the column menu and add a widget."
useSimpleUiForNonRootPages: "Use simple UI for navigated pages"
usedAsMinWidthWhenFlexible: "Minimum width will be used for this when the \"Auto-adjust width\" option is enabled"
flexible: "Auto-adjust width"
enableSyncBetweenDevicesForProfiles: "Enable profile information sync between devices"
_columns:
main: "Main"
widgets: "Widgets"
@ -2528,7 +2662,7 @@ _webhookSettings:
testRemarks: "Click the button to the right of the switch to send a test Webhook with dummy data."
_abuseReport:
_notificationRecipient:
createRecipient: "Add a recipient for reports"
createRecipient: "Add recipient for reports"
modifyRecipient: "Edit a recipient for reports"
recipientType: "Notification type"
_recipientType:
@ -2590,6 +2724,8 @@ _moderationLogTypes:
deletePage: "Page deleted"
deleteFlash: "Play deleted"
deleteGalleryPost: "Gallery post deleted"
deleteChatRoom: "Deleted Chat Room"
updateProxyAccountDescription: "Update the description of the proxy account"
_fileViewer:
title: "File details"
type: "File type"
@ -2603,10 +2739,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "Make sure the distributor of this resource is trustworthy before installation."
_plugin:
title: "Do you want to install this plugin?"
metaTitle: "Plugin information"
_theme:
title: "Do you want to install this theme?"
metaTitle: "Theme information"
_meta:
base: "Base color scheme"
_vendorInfo:
@ -2645,7 +2779,7 @@ _dataSaver:
description: "Prevents images/videos from being loaded automatically. Hidden images/videos will be loaded when tapped."
_avatar:
title: "Avatar image"
description: "Stop avatar image animation. Animated images can be larger in file size than normal images, potentially leading to further reductions in data traffic."
description: "Stop avatar image animation. Animated images can be larger in file size than normal images, potentially leading to further reductions in data traffic."
_urlPreview:
title: "URL preview thumbnails"
description: "URL preview thumbnail images will no longer be loaded."
@ -2737,7 +2871,7 @@ _roleSelectDialog:
_customEmojisManager:
_gridCommon:
copySelectionRows: "Copy selected rows"
copySelectionRanges: "Copy selected ranges"
copySelectionRanges: "Copy selection"
deleteSelectionRows: "Delete selected rows"
deleteSelectionRanges: "Delete rows in the selection"
searchSettings: "Search settings"
@ -2759,7 +2893,7 @@ _customEmojisManager:
confirmImportEmojisTitle: "Import Emojis"
confirmImportEmojisDescription: "Import {count} Emoji(s) received from the remote server. Please pay close attention to the license of the Emoji. Are you sure to continue?"
_local:
tabTitleList: "List of registered Emojis"
tabTitleList: "Registered emojis"
tabTitleRegister: "Emoji registration"
_list:
emojisNothing: "There are no registered Emojis."
@ -2807,8 +2941,8 @@ _selfXssPrevention:
description2: "If you do not understand exactly what you are trying to paste, %cstop working right now and close this window."
description3: "For more information, please refer to this. {link}"
_followRequest:
recieved: "Received"
sent: "Sent"
recieved: "Received request"
sent: "Sent request"
_remoteLookupErrors:
_federationNotAllowed:
title: "Unable to communicate with this server"
@ -2822,8 +2956,6 @@ _remoteLookupErrors:
_responseInvalid:
title: "Response is invalid"
description: "It could communicate with this server, but the data obtained was incorrect."
_responseInvalidIdHostNotMatch:
description: "The domain of the entered URI differs from the domain of the final obtained URI. If you are looking up remote content through a third-party server, please look up again using a URI that can be obtained from the origin server."
_noSuchObject:
title: "Not found"
description: "The requested resource was not found, please recheck the URI."
@ -2840,3 +2972,23 @@ _captcha:
_unknown:
title: "CAPTCHA error"
text: "An unexpected error occurred."
_bootErrors:
title: "Failed to load"
serverError: "If the problem persists after waiting a moment and reloading, please contact the server administrator with the following Error ID."
solution: "The following may solve the problem."
solution1: "Update your browser and OS to the latest version"
solution2: "Disable ad blocker"
solution3: "Clear the browser cache"
solution4: "Set the dom.webaudio.enabled to true for Tor Browser"
otherOption: "Other options"
otherOption1: "Delete client settings and cache"
otherOption2: "Start the simple client"
otherOption3: "Launch the repair tool"
_search:
searchScopeAll: "All"
searchScopeLocal: "Local"
searchScopeServer: "Specific server"
searchScopeUser: "Specific user"
pleaseEnterServerHost: "Enter the server host"
pleaseSelectUser: "Select user"
serverHostPlaceholder: "Example: misskey.example.com"

View file

@ -289,7 +289,6 @@ deleteAreYouSure: "¿Desea borrar \"{x}\"?"
resetAreYouSure: "¿Desea reestablecer?"
areYouSure: "¿Estás conforme?"
saved: "Guardado"
messaging: "Chat"
upload: "Subir"
keepOriginalUploading: "Mantener la imagen original"
keepOriginalUploadingDescription: "Mantener la versión original al cargar imágenes. Si está desactivado, el navegador generará imágenes para la publicación web en el momento de recargar la página"
@ -302,7 +301,6 @@ uploadFromUrlMayTakeTime: "Subir el fichero puede tardar un tiempo."
explore: "Explorar"
messageRead: "Ya leído"
noMoreHistory: "El historial se ha acabado"
startMessaging: "Iniciar chat"
nUsersRead: "Leído por {n} personas"
agreeTo: "De acuerdo con {0}"
agree: "De acuerdo."
@ -491,8 +489,6 @@ noteOf: "Notas de {user}"
quoteAttached: "Cita añadida"
quoteQuestion: "¿Quiere añadir una cita?"
attachAsFileQuestion: "El texto del portapapeles es demasiado grande ¿Desea adjuntarlo como archivo de texto?"
noMessagesYet: "Aún no hay chat"
newMessageExists: "Tienes un mensaje nuevo"
onlyOneFileCanBeAttached: "Solo se puede añadir un archivo al mensaje"
signinRequired: "Iniciar sesión"
signinOrContinueOnRemote: "Para continuar, tendrá que ir a su servidor o registrarse e iniciar sesión en este servidor"
@ -605,6 +601,7 @@ descendingOrder: "Descendente"
scratchpad: "Scratch pad"
scratchpadDescription: "Scratchpad proporciona un entorno experimental para AiScript. Puede escribir, ejecutar y verificar los resultados que interactúan con Misskey."
uiInspector: "Inspector de UI"
uiInspectorDescription: "Puedes visualizar una lista de elementos UI presentes en la memoria. Los componentes de la interfaz de usuario son generados por las funciones UI:C:"
output: "Salida"
script: "Script"
disablePagesScript: "Deshabilitar AiScript en Páginas"
@ -693,6 +690,7 @@ regexpError: "Error de la expresión regular"
regexpErrorDescription: "Ocurrió un error en la expresión regular en la linea {line} de las palabras muteadas {tab}"
instanceMute: "Instancias silenciadas"
userSaysSomething: "{name} dijo algo"
userSaysSomethingAbout: "{name} dijo algo sobre {word}"
makeActive: "Activar"
display: "Apariencia"
copy: "Copiar"
@ -861,6 +859,7 @@ administration: "Administrar"
accounts: "Cuentas"
switch: "Cambiar"
noMaintainerInformationWarning: "No se ha establecido la información del administrador"
noInquiryUrlWarning: "No se ha guardado la URL de consulta."
noBotProtectionWarning: "La protección contra los bots no está configurada"
configure: "Configurar"
postToGallery: "Crear una nueva publicación en la galería"
@ -925,6 +924,7 @@ followersVisibility: "Visibilidad de seguidores"
continueThread: "Ver la continuación del hilo"
deleteAccountConfirm: "La cuenta será borrada. ¿Está seguro?"
incorrectPassword: "La contraseña es incorrecta"
incorrectTotp: "La contraseña de un solo uso es incorrecta o ha caducado."
voteConfirm: "¿Confirma su voto a {choice}?"
hide: "Ocultar"
useDrawerReactionPickerForMobile: "Mostrar panel de reacciones en móviles"
@ -1053,6 +1053,7 @@ thisPostMayBeAnnoyingHome: "Publicar en línea de tiempo 'Inicio'"
thisPostMayBeAnnoyingCancel: "detener"
thisPostMayBeAnnoyingIgnore: "Publicar de todos modos"
collapseRenotes: "Colapsar renotas que ya hayas visto"
collapseRenotesDescription: "Contrae notas a las que ya has reaccionado o renotado "
internalServerError: "Error interno del servidor"
internalServerErrorDescription: "El servidor tuvo un error inesperado."
copyErrorInfo: "Copiar detalles del error"
@ -1091,6 +1092,7 @@ retryAllQueuesConfirmTitle: "Desea ¿reintentar inmediatamente todas las colas?"
retryAllQueuesConfirmText: "La carga del servidor está incrementándose temporalmente "
enableChartsForRemoteUser: "Generar gráficas de usuarios remotos."
enableChartsForFederatedInstances: "Generar gráficos de servidores remotos"
enableStatsForFederatedInstances: "Activar las estadísticas de las instancias remotas federadas"
showClipButtonInNoteFooter: "Añadir \"Clip\" al menú de notas"
reactionsDisplaySize: "Tamaño de las reacciones"
limitWidthOfReaction: "Limitar ancho de las reacciones"
@ -1139,6 +1141,7 @@ preventAiLearningDescription: "Pedirle a las arañas (crawlers) no usar los text
options: "Opción"
specifyUser: "Especificar usuario"
lookupConfirm: "¿Quiere informarse?"
openTagPageConfirm: "¿Quieres abrir la página de etiquetas?"
specifyHost: "Especificar Host"
failedToPreviewUrl: "No se pudo generar la vista previa"
update: "Actualizar"
@ -1267,15 +1270,42 @@ useBackupCode: "Usar códigos de respaldo"
launchApp: "Ejecutar la app"
useNativeUIForVideoAudioPlayer: "Usar la interfaz del navegador cuando se reproduce audio y vídeo"
keepOriginalFilename: "Mantener el nombre original del archivo"
keepOriginalFilenameDescription: "Si desactivas esta opción, los nombres de los archivos serán remplazados por una cadena de caracteres aleatoria cuando subas los archivos."
noDescription: "No hay descripción"
alwaysConfirmFollow: "Confirmar siempre cuando se sigue a alguien"
inquiry: "Contacto"
tryAgain: "Por favor , inténtalo de nuevo"
confirmWhenRevealingSensitiveMedia: "Confirmación cuando se revele contenido sensible"
sensitiveMediaRevealConfirm: "Esto puede contener contenido sensible. ¿Estás seguro/a de querer mostrarlo?"
createdLists: "Listas creadas"
createdAntennas: "Antenas creadas"
fromX: "De {x}"
genEmbedCode: "Obtener el código para incrustar"
noteOfThisUser: "Notas de este usuario"
clipNoteLimitExceeded: "No se pueden añadir más notas a este clip."
performance: "Rendimiento"
modified: "Modificado"
discard: "Descartar"
thereAreNChanges: "Hay {n} cambio(s)"
signinWithPasskey: "Iniciar sesión con clave de acceso"
unknownWebAuthnKey: "Esto no se ha registrado llave maestra."
passkeyVerificationFailed: "La verificación de la clave de acceso ha fallado."
passkeyVerificationSucceededButPasswordlessLoginDisabled: "La verificación de la clave de acceso ha sido satisfactoria pero se ha deshabilitado el inicio de sesión sin contraseña."
messageToFollower: "Mensaje a seguidores"
target: "Para"
federationSpecified: "Este servidor opera en una federación de listas blancas. No puede interactuar con otros servidores que no sean los especificados por el administrador."
federationDisabled: "La federación está desactivada en este servidor. No puede interactuar con usuarios de otros servidores"
preferences: "Preferencias"
postForm: "Formulario"
information: "Información"
_chat:
invitations: "Invitar"
noHistory: "No hay datos en el historial"
members: "Miembros"
home: "Inicio"
send: "Enviar"
_settings:
webhook: "Webhook"
_accountSettings:
requireSigninToViewContents: "Se requiere iniciar sesión para ver el contenido"
requireSigninToViewContentsDescription1: "Requiere iniciar sesión para ver todas las notas y otros contenidos que hayas creado. Se espera que esto evite que los rastreadores recopilen información."
@ -1935,7 +1965,6 @@ _theme:
header: "Cabezal"
navBg: "Fondo de la barra lateral"
navFg: "Texto de la barra lateral"
navHoverFg: "Texto de la barra lateral (hover)"
navActive: "Texto de la barra lateral (activo)"
navIndicator: "Indicador de la barra lateral"
link: "Vínculo"
@ -1958,11 +1987,8 @@ _theme:
buttonHoverBg: "Fondo de botón (hover)"
inputBorder: "Borde de los campos de entrada"
driveFolderBg: "Fondo de capeta del drive"
wallpaperOverlay: "Transparencia del fondo de pantalla"
badge: "Medalla"
messageBg: "Fondo de chat"
accentDarken: "Acento (oscuro)"
accentLighten: "Acento (claro)"
fgHighlighted: "Texto resaltado"
_sfx:
note: "Notas"
@ -2114,6 +2140,7 @@ _permissions:
"read:clip-favorite": "Ver los clips que me gustan"
"read:federation": "Ver instancias federadas"
"write:report-abuse": "Crear reportes de usuario"
"write:chat": "Administrar chat"
_auth:
shareAccessTitle: "Permisos de la aplicación"
shareAccess: "¿Desea permitir el acceso a la cuenta \"{name}\"?"
@ -2495,10 +2522,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "Asegúrate de que el distribuidor de este recurso es de confianza antes de proceder a la instalación."
_plugin:
title: "¿Quieres instalar este plugin?"
metaTitle: "Información del plugin"
_theme:
title: "¿Quieres instalar este tema?"
metaTitle: "Información del tema"
_meta:
base: "Esquema de color base"
_vendorInfo:
@ -2560,6 +2585,13 @@ _mediaControls:
pip: "Picture in Picture"
playbackRate: "Velocidad de reproducción"
loop: "Reproducción en bucle"
_followRequest:
recieved: "Petición de seguimiento recibida"
sent: "Petición de seguimiento enviada"
_remoteLookupErrors:
_noSuchObject:
title: "No se encuentra"
_search:
searchScopeAll: "Todo"
searchScopeLocal: "Local"
searchScopeUser: "Especificar usuario"

View file

@ -277,7 +277,6 @@ deleteAreYouSure: "Êtes-vous sûr·e de vouloir supprimer « {x} » ?"
resetAreYouSure: "Voulez-vous réinitialiser ?"
areYouSure: "Êtes-vous sûr·e ?"
saved: "Enregistré"
messaging: "Discuter"
upload: "Téléverser"
keepOriginalUploading: "Garder limage dorigine"
keepOriginalUploadingDescription: "Conserve la version originale lors du téléchargement d'images. S'il est désactivé, le navigateur génère l'image pour la publication web lors du téléchargement."
@ -290,7 +289,6 @@ uploadFromUrlMayTakeTime: "Le téléversement de votre fichier peut prendre un c
explore: "Découvrir"
messageRead: "Lu"
noMoreHistory: "Il ny a plus dhistorique"
startMessaging: "Commencer à discuter"
nUsersRead: "Lu par {n} personnes"
agreeTo: "Jaccepte {0}"
agree: "Accepter"
@ -477,8 +475,6 @@ retype: "Confirmation"
noteOf: "Notes de {user}"
quoteAttached: "Avec citation"
quoteQuestion: "Souhaitez-vous ajouter une citation ?"
noMessagesYet: "Pas encore de discussion"
newMessageExists: "Vous avez un nouveau message"
onlyOneFileCanBeAttached: "Vous ne pouvez joindre quun seul fichier au message"
signinRequired: "Veuillez vous connecter"
invitations: "Invitations"
@ -1277,6 +1273,14 @@ prohibitedWordsForNameOfUser: "Mots interdits pour les noms d'utilisateur·rices
lockdown: "Verrouiller"
pleaseSelectAccount: "Sélectionner un compte"
availableRoles: "Rôles disponibles"
postForm: "Formulaire de publication"
information: "Informations"
_chat:
invitations: "Inviter"
noHistory: "Pas d'historique"
members: "Membres"
home: "Principal"
send: "Envoyer"
_abuseUserReport:
forward: "Transférer"
forwardDescription: "Transférer le signalement vers une instance distante en tant qu'anonyme."
@ -1812,7 +1816,6 @@ _theme:
header: "Entête"
navBg: "Fond de la barre latérale"
navFg: "Texte de la barre latérale"
navHoverFg: "Texte de la barre latérale (survolé)"
navActive: "Texte de la barre latérale (actif)"
navIndicator: "Indicateur de barre latérale"
link: "Lien"
@ -1835,11 +1838,8 @@ _theme:
buttonHoverBg: "Arrière-plan du bouton (survolé)"
inputBorder: "Cadre de la zone de texte"
driveFolderBg: "Arrière-plan du dossier de disque"
wallpaperOverlay: "Superposition de fond d'écran"
badge: "Badge"
messageBg: "Arrière plan de la discussion"
accentDarken: "Plus sombre"
accentLighten: "Plus clair"
fgHighlighted: "Texte mis en évidence"
_sfx:
note: "Nouvelle note"
@ -1949,6 +1949,7 @@ _permissions:
"write:admin:unsuspend-user": "Lever la suspension d'un utilisateur"
"write:admin:meta": "Gérer les métadonnées de l'instance"
"write:admin:roles": "Gérer les rôles"
"write:chat": "Gérer les discussions"
_auth:
shareAccess: "Autoriser \"{name}\" à accéder à votre compte ?"
shareAccessAsk: "Voulez-vous vraiment autoriser cette application à accéder à votre compte?"
@ -2294,10 +2295,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "Veuillez confirmer que le distributeur est fiable avant l'installation."
_plugin:
title: "Voulez-vous installer cette extension ?"
metaTitle: "Informations sur l'extension"
_theme:
title: "Voulez-vous installer ce thème ?"
metaTitle: "Informations sur le thème"
_meta:
base: "Palette de couleurs de base"
_vendorInfo:
@ -2364,3 +2363,7 @@ _embedCodeGen:
_remoteLookupErrors:
_noSuchObject:
title: "Non trouvé"
_search:
searchScopeAll: "Tous"
searchScopeLocal: "Local"
searchScopeUser: "Spécifier l'utilisateur·rice"

View file

@ -280,7 +280,6 @@ deleteAreYouSure: "Apakah kamu yakin ingin menghapus \"{x}\"?"
resetAreYouSure: "Yakin mau atur ulang?"
areYouSure: "Apakah kamu yakin?"
saved: "Telah disimpan"
messaging: "Pesan"
upload: "Unggah"
keepOriginalUploading: "Simpan gambar asli"
keepOriginalUploadingDescription: "Simpan gambar yang diunggah sebagaimana gambar aslinya. Bila dimatikan, versi tampilan web akan dihasilkan pada saat diunggah."
@ -293,7 +292,6 @@ uploadFromUrlMayTakeTime: "Membutuhkan beberapa waktu hingga pengunggahan selesa
explore: "Jelajahi"
messageRead: "Telah dibaca"
noMoreHistory: "Tidak ada sejarah lagi"
startMessaging: "Mulai mengirim pesan"
nUsersRead: "Dibaca oleh {n}"
agreeTo: "Saya setuju kepada {0}"
agree: "Setuju"
@ -481,8 +479,6 @@ noteOf: "Catatan milik {user}"
quoteAttached: "Dikutip"
quoteQuestion: "Apakah kamu ingin menambahkan kutipan?"
attachAsFileQuestion: "Teks dalam papan klip terlalu panjang. Apakah kamu ingin melampirkannya sebagai berkas teks?"
noMessagesYet: "Tidak ada pesan"
newMessageExists: "Kamu mendapatkan pesan baru"
onlyOneFileCanBeAttached: "Kamu hanya dapat melampirkan satu berkas ke dalam pesan"
signinRequired: "Silahkan login"
invitations: "Undangan"
@ -1261,6 +1257,16 @@ performance: "Kinerja"
modified: "Diubah"
thereAreNChanges: "Ada {n} perubahan"
prohibitedWordsForNameOfUser: "Kata yang dilarang untuk nama pengguna"
postForm: "Buat catatan"
information: "Informasi"
_chat:
invitations: "Undang"
noHistory: "Tidak ada riwayat"
members: "Anggota"
home: "Beranda"
send: "Kirim"
_settings:
webhook: "Webhook"
_abuseUserReport:
accept: "Setuju"
reject: "Tolak"
@ -1925,7 +1931,6 @@ _theme:
header: "Header"
navBg: "Latar belakang bilah samping"
navFg: "Teks bilah samping"
navHoverFg: "Teks bilah samping (Mengambang)"
navActive: "Teks bilah samping (Aktif)"
navIndicator: "Indikator bilah samping"
link: "Tautan"
@ -1948,11 +1953,8 @@ _theme:
buttonHoverBg: "Latar belakang tombol (Mengambang)"
inputBorder: "Batas bidang masukan"
driveFolderBg: "Latar belakang folder drive"
wallpaperOverlay: "Lapisan wallpaper"
badge: "Lencana"
messageBg: "Latar belakang obrolan"
accentDarken: "Aksen (Gelap)"
accentLighten: "Aksen (Terang)"
fgHighlighted: "Teks yang disorot"
_sfx:
note: "Catatan"
@ -2105,6 +2107,7 @@ _permissions:
"read:clip-favorite": "Lihat klip yang difavoritkan"
"read:federation": "Mendapatkan data federasi"
"write:report-abuse": "Melaporkan pelanggaran"
"write:chat": "Buat atau hapus obrolan"
_auth:
shareAccessTitle: "Mendapatkan ijin akses aplikasi"
shareAccess: "Apakah kamu ingin mengijinkan \"{name}\" untuk mengakses akun ini?"
@ -2489,10 +2492,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "Pastikan sumber dari sumber daya ini terpercaya sebelum melakukan pemasangan."
_plugin:
title: "Apakah kamu ingin memasang plugin ini?"
metaTitle: "Informasi plugin"
_theme:
title: "Apakah kamu ingin memasang tema ini?"
metaTitle: "Informasi tema"
_meta:
base: "Skema warna dasar"
_vendorInfo:
@ -2610,3 +2611,7 @@ _mediaControls:
_remoteLookupErrors:
_noSuchObject:
title: "Tidak dapat ditemukan"
_search:
searchScopeAll: "Semua"
searchScopeLocal: "Lokal"
searchScopeUser: "Pengguna spesifik"

775
locales/index.d.ts vendored
View file

@ -1174,10 +1174,6 @@ export interface Locale extends ILocale {
*
*/
"saved": string;
/**
*
*/
"messaging": string;
/**
*
*/
@ -1227,9 +1223,9 @@ export interface Locale extends ILocale {
*/
"noMoreHistory": string;
/**
*
*
*/
"startMessaging": string;
"startChat": string;
/**
* {n}
*/
@ -1718,6 +1714,10 @@ export interface Locale extends ILocale {
*
*/
"withFileAntenna": string;
/**
*
*/
"hideNotesInSensitiveChannel": string;
/**
*
*/
@ -1982,14 +1982,6 @@ export interface Locale extends ILocale {
* The text in clipboard is long. Would you like to attach it as a text file?
*/
"attachAsFileQuestion": string;
/**
*
*/
"noMessagesYet": string;
/**
*
*/
"newMessageExists": string;
/**
*
*/
@ -2810,6 +2802,10 @@ export interface Locale extends ILocale {
*
*/
"copy": string;
/**
*
*/
"copiedToClipboard": string;
/**
*
*/
@ -4972,7 +4968,7 @@ export interface Locale extends ILocale {
*/
"disableStreamingTimeline": string;
/**
*
*
*/
"useGroupedNotifications": string;
/**
@ -5255,6 +5251,489 @@ export interface Locale extends ILocale {
*
*/
"federationDisabled": string;
/**
*
*/
"confirmOnReact": string;
/**
* " {emoji} "
*/
"reactAreYouSure": ParameterizedString<"emoji">;
/**
*
*/
"markAsSensitiveConfirm": string;
/**
*
*/
"unmarkAsSensitiveConfirm": string;
/**
*
*/
"preferences": string;
/**
*
*/
"accessibility": string;
/**
*
*/
"preferencesProfile": string;
/**
* IDをコピー
*/
"copyPreferenceId": string;
/**
*
*/
"resetToDefaultValue": string;
/**
*
*/
"overrideByAccount": string;
/**
*
*/
"untitled": string;
/**
*
*/
"noName": string;
/**
*
*/
"skip": string;
/**
*
*/
"restore": string;
/**
*
*/
"syncBetweenDevices": string;
/**
*
*/
"preferenceSyncConflictTitle": string;
/**
*
*/
"preferenceSyncConflictText": string;
/**
*
*/
"preferenceSyncConflictChoiceServer": string;
/**
*
*/
"preferenceSyncConflictChoiceDevice": string;
/**
*
*/
"preferenceSyncConflictChoiceCancel": string;
/**
*
*/
"paste": string;
/**
*
*/
"emojiPalette": string;
/**
* 稿
*/
"postForm": string;
/**
*
*/
"textCount": string;
/**
*
*/
"information": string;
/**
*
*/
"chat": string;
/**
*
*/
"migrateOldSettings": string;
/**
*
*/
"migrateOldSettings_description": string;
/**
*
*/
"compress": string;
/**
*
*/
"right": string;
/**
*
*/
"bottom": string;
/**
*
*/
"top": string;
/**
*
*/
"embed": string;
"_chat": {
/**
*
*/
"noMessagesYet": string;
/**
*
*/
"newMessage": string;
/**
*
*/
"individualChat": string;
/**
*
*/
"individualChat_description": string;
/**
*
*/
"roomChat": string;
/**
*
*
*/
"roomChat_description": string;
/**
*
*/
"createRoom": string;
/**
*
*/
"inviteUserToChat": string;
/**
*
*/
"yourRooms": string;
/**
*
*/
"joiningRooms": string;
/**
*
*/
"invitations": string;
/**
*
*/
"noInvitations": string;
/**
*
*/
"history": string;
/**
*
*/
"noHistory": string;
/**
*
*/
"noRooms": string;
/**
*
*/
"inviteUser": string;
/**
*
*/
"sentInvitations": string;
/**
*
*/
"join": string;
/**
*
*/
"ignore": string;
/**
* 退
*/
"leave": string;
/**
*
*/
"members": string;
/**
*
*/
"searchMessages": string;
/**
*
*/
"home": string;
/**
*
*/
"send": string;
/**
*
*/
"newline": string;
/**
*
*/
"muteThisRoom": string;
/**
*
*/
"deleteRoom": string;
/**
*
*/
"chatNotAvailableForThisAccountOrServer": string;
/**
* 使
*/
"chatNotAvailableInOtherAccount": string;
/**
*
*/
"cannotChatWithTheUser": string;
/**
* 使
*/
"cannotChatWithTheUser_description": string;
/**
*
*/
"chatWithThisUser": string;
/**
*
*/
"thisUserAllowsChatOnlyFromFollowers": string;
/**
*
*/
"thisUserAllowsChatOnlyFromFollowing": string;
/**
*
*/
"thisUserAllowsChatOnlyFromMutualFollowing": string;
/**
*
*/
"thisUserNotAllowedChatAnyone": string;
/**
*
*/
"chatAllowedUsers": string;
/**
*
*/
"chatAllowedUsers_note": string;
"_chatAllowedUsers": {
/**
*
*/
"everyone": string;
/**
*
*/
"followers": string;
/**
*
*/
"following": string;
/**
*
*/
"mutual": string;
/**
*
*/
"none": string;
};
};
"_emojiPalette": {
/**
*
*/
"palettes": string;
/**
*
*/
"enableSyncBetweenDevicesForPalettes": string;
/**
* 使
*/
"paletteForMain": string;
/**
* 使
*/
"paletteForReaction": string;
};
"_settings": {
/**
* 使
*/
"driveBanner": string;
/**
*
*/
"pluginBanner": string;
/**
*
*/
"notificationsBanner": string;
/**
* API
*/
"api": string;
/**
* Webhook
*/
"webhook": string;
/**
*
*/
"serviceConnection": string;
/**
* Webhookの管理と設定が行えます
*/
"serviceConnectionBanner": string;
/**
*
*/
"accountData": string;
/**
* /
*/
"accountDataBanner": string;
/**
*
*/
"muteAndBlockBanner": string;
/**
* 使
*/
"accessibilityBanner": string;
/**
*
*/
"privacyBanner": string;
/**
*
*/
"securityBanner": string;
/**
*
*/
"preferencesBanner": string;
/**
*
*/
"appearanceBanner": string;
/**
*
*/
"soundsBanner": string;
/**
*
*/
"timelineAndNote": string;
/**
*
*/
"makeEveryTextElementsSelectable": string;
/**
*
*/
"makeEveryTextElementsSelectable_description": string;
/**
*
*/
"useStickyIcons": string;
/**
*
*/
"showNavbarSubButtons": string;
/**
*
*/
"ifOn": string;
/**
*
*/
"ifOff": string;
/**
*
*/
"enableSyncThemesBetweenDevices": string;
"_chat": {
/**
*
*/
"showSenderName": string;
/**
* Enterで送信
*/
"sendOnEnter": string;
};
};
"_preferencesProfile": {
/**
*
*/
"profileName": string;
/**
*
*/
"profileNameDescription": string;
/**
* : PC
*/
"profileNameDescription2": string;
};
"_preferencesBackup": {
/**
*
*/
"autoBackup": string;
/**
*
*/
"restoreFromBackup": string;
/**
*
*/
"noBackupsFoundTitle": string;
/**
*
*/
"noBackupsFoundDescription": string;
/**
*
*/
"selectBackupToRestore": string;
/**
*
*/
"youNeedToNameYourProfileToEnableAutoBackup": string;
/**
*
*/
"autoPreferencesBackupIsNotEnabledForThisDevice": string;
/**
*
*/
"backupFound": string;
};
"_accountSettings": {
/**
*
@ -5292,6 +5771,10 @@ export interface Locale extends ILocale {
*
*/
"mayNotEffectForFederatedNotes": string;
/**
*
*/
"mayNotEffectSomeSituations": string;
/**
*
*/
@ -6902,6 +7385,14 @@ export interface Locale extends ILocale {
* UI上で先頭に表示されます
*/
"descriptionOfDisplayOrder": string;
/**
*
*/
"preserveAssignmentOnMoveAccount": string;
/**
*
*/
"preserveAssignmentOnMoveAccount_description": string;
/**
*
*/
@ -7057,6 +7548,10 @@ export interface Locale extends ILocale {
*
*/
"canImportUserLists": string;
/**
*
*/
"canChat": string;
/**
* Can view the bubble timeline
*/
@ -7706,6 +8201,10 @@ export interface Locale extends ILocale {
*
*/
"builtinThemes": string;
/**
*
*/
"instanceTheme": string;
/**
*
*/
@ -7824,23 +8323,19 @@ export interface Locale extends ILocale {
*/
"header": string;
/**
*
*
*/
"navBg": string;
/**
*
*
*/
"navFg": string;
/**
* ()
*/
"navHoverFg": string;
/**
* ()
* ()
*/
"navActive": string;
/**
*
*
*/
"navIndicator": string;
/**
@ -7923,10 +8418,6 @@ export interface Locale extends ILocale {
*
*/
"driveFolderBg": string;
/**
*
*/
"wallpaperOverlay": string;
/**
*
*/
@ -7935,14 +8426,6 @@ export interface Locale extends ILocale {
*
*/
"messageBg": string;
/**
* ()
*/
"accentDarken": string;
/**
* ()
*/
"accentLighten": string;
/**
* 調
*/
@ -7966,6 +8449,10 @@ export interface Locale extends ILocale {
*
*/
"reaction": string;
/**
*
*/
"chatMessage": string;
};
"_soundSettings": {
/**
@ -8538,6 +9025,14 @@ export interface Locale extends ILocale {
*
*/
"write:report-abuse": string;
/**
*
*/
"write:chat": string;
/**
*
*/
"read:chat": string;
/**
* Approve new users
*/
@ -8551,7 +9046,7 @@ export interface Locale extends ILocale {
*/
"write:admin:nsfw-user": string;
/**
* Mark users an not NSFW
* Mark users as not NSFW
*/
"write:admin:unnsfw-user": string;
/**
@ -9576,6 +10071,10 @@ export interface Locale extends ILocale {
*
*/
"roleAssigned": string;
/**
*
*/
"chatRoomInvitationReceived": string;
/**
*
*/
@ -9628,6 +10127,14 @@ export interface Locale extends ILocale {
*
*/
"login": string;
/**
*
*/
"createToken": string;
/**
* {text}
*/
"createTokenDescription": ParameterizedString<"text">;
"_types": {
/**
*
@ -9677,6 +10184,10 @@ export interface Locale extends ILocale {
*
*/
"roleAssigned": string;
/**
*
*/
"chatRoomInvitationReceived": string;
/**
*
*/
@ -9689,6 +10200,10 @@ export interface Locale extends ILocale {
*
*/
"login": string;
/**
*
*/
"createToken": string;
/**
*
*/
@ -9746,6 +10261,18 @@ export interface Locale extends ILocale {
*
*/
"columnAlign": string;
/**
*
*/
"columnGap": string;
/**
*
*/
"deckMenuPosition": string;
/**
*
*/
"navbarPosition": string;
/**
*
*/
@ -9799,7 +10326,7 @@ export interface Locale extends ILocale {
*/
"introduction": string;
/**
* +
* +
*/
"introduction2": string;
/**
@ -9818,6 +10345,10 @@ export interface Locale extends ILocale {
* 調
*/
"flexible": string;
/**
*
*/
"enableSyncBetweenDevicesForProfiles": string;
"_columns": {
/**
*
@ -10226,6 +10757,14 @@ export interface Locale extends ILocale {
* 稿
*/
"deleteGalleryPost": string;
/**
*
*/
"deleteChatRoom": string;
/**
*
*/
"updateProxyAccountDescription": string;
/**
* Approved
*/
@ -10243,7 +10782,7 @@ export interface Locale extends ILocale {
*/
"setRemoteInstanceNSFW": string;
/**
* Set remote instance as NSFW
* Unset remote instance as NSFW
*/
"unsetRemoteInstanceNSFW": string;
/**
@ -10367,20 +10906,12 @@ export interface Locale extends ILocale {
*
*/
"title": string;
/**
*
*/
"metaTitle": string;
};
"_theme": {
/**
*
*/
"title": string;
/**
*
*/
"metaTitle": string;
};
"_meta": {
/**
@ -11114,11 +11645,11 @@ export interface Locale extends ILocale {
};
"_followRequest": {
/**
*
* Received
*/
"recieved": string;
/**
*
* Sent
*/
"sent": string;
};
@ -11160,13 +11691,7 @@ export interface Locale extends ILocale {
*/
"title": string;
/**
*
*/
"description": string;
};
"_responseInvalidIdHostNotMatch": {
/**
* URIのドメインと最終的に得られたURIのドメインとが異なりますURIを使用して照会し直してください
* URIを使用して照会し直してください
*/
"description": string;
};
@ -11224,6 +11749,82 @@ export interface Locale extends ILocale {
};
};
};
"_bootErrors": {
/**
*
*/
"title": string;
/**
* Error IDを添えてサーバー管理者に連絡してください
*/
"serverError": string;
/**
*
*/
"solution": string;
/**
* OSを最新バージョンに更新する
*/
"solution1": string;
/**
*
*/
"solution2": string;
/**
*
*/
"solution3": string;
/**
* (Tor Browser) dom.webaudio.enabledをtrueに設定する
*/
"solution4": string;
/**
*
*/
"otherOption": string;
/**
*
*/
"otherOption1": string;
/**
*
*/
"otherOption2": string;
/**
*
*/
"otherOption3": string;
};
"_search": {
/**
*
*/
"searchScopeAll": string;
/**
*
*/
"searchScopeLocal": string;
/**
*
*/
"searchScopeServer": string;
/**
*
*/
"searchScopeUser": string;
/**
*
*/
"pleaseEnterServerHost": string;
/**
*
*/
"pleaseSelectUser": string;
/**
* : misskey.example.com
*/
"serverHostPlaceholder": string;
};
/**
* Approvals
*/
@ -11637,6 +12238,10 @@ export interface Locale extends ILocale {
* Pending follow requests
*/
"pendingFollowRequests": string;
/**
* Are you sure you want to cancel your follow request?
*/
"undoFollowRequestConfirm": string;
/**
* Show quotes
*/
@ -12221,12 +12826,72 @@ export interface Locale extends ILocale {
* Applies a content warning to all posts created by this user. If the post already has a CW, then this is appended to the end.
*/
"mandatoryCWDescription": string;
/**
* Fetch linked note
*/
"fetchLinkedNote": string;
"_processErrors": {
/**
* Unable to process quote. This post may be missing context.
*/
"quoteUnavailable": string;
};
/**
* Authorized Fetch
*/
"authorizedFetchSection": string;
/**
* Allow unsigned ActivityPub requests:
*/
"authorizedFetchLabel": string;
/**
* This setting controls the behavior when a remote instance or user attempts to access your content without verifying their identity. If disabled, any remote user can access your profile and posts - even one who has been blocked or defederated.
*/
"authorizedFetchDescription": string;
"_authorizedFetchValue": {
/**
* Never
*/
"never": string;
/**
* Always
*/
"always": string;
/**
* Only for essential metadata
*/
"essential": string;
/**
* Use staff recommendation
*/
"staff": string;
};
"_authorizedFetchValueDescription": {
/**
* Block all unsigned requests. Improves privacy and makes blocks more effective, but is not compatible with some very old or uncommon instance software.
*/
"never": string;
/**
* Allow all unsigned requests. Provides the greatest compatibility with other instances, but reduces privacy and weakens blocks.
*/
"always": string;
/**
* Allow some limited unsigned requests. Provides a hybrid between "Never" and "Always" by exposing only the minimum profile metadata that is required for federation with older software.
*/
"essential": string;
/**
* Use the default value of "{value}" recommended by the instance staff.
*/
"staff": ParameterizedString<"value">;
};
/**
* The configuration property 'checkActivityPubGetSignature' has been deprecated and replaced with the new Authorized Fetch setting. Please remove it from your configuration file.
*/
"authorizedFetchLegacyWarning": string;
/**
* Deleted
*/
"deleted": string;
}
declare const locales: {
[lang: string]: Locale;

View file

@ -126,7 +126,7 @@ pinnedNote: "Nota in primo piano"
pinned: "Fissa sul profilo"
you: "Tu"
clickToShow: "Contenuto occultato, cliccare solo se si intende vedere"
sensitive: "Allegato esplicito"
sensitive: "Esplicito"
add: "Aggiungi"
reaction: "Reazioni"
reactions: "Reazioni"
@ -228,7 +228,7 @@ jobQueue: "Coda di lavoro"
cpuAndMemory: "CPU e Memoria"
network: "Rete"
disk: "Disco"
instanceInfo: "Informazioni sull'istanza"
instanceInfo: "Informazioni sul server"
statistics: "Statistiche"
clearQueue: "Svuota coda"
clearQueueConfirmTitle: "Vuoi davvero svuotare la coda?"
@ -289,7 +289,6 @@ deleteAreYouSure: "Vuoi davvero eliminare \"{x}\"?"
resetAreYouSure: "Ripristinare?"
areYouSure: "Confermi?"
saved: "Salvato"
messaging: "Messaggi"
upload: "Carica"
keepOriginalUploading: "Conservare l'immagine originale."
keepOriginalUploadingDescription: "Conserva la versione originale quando si caricano le immagini. Se è disattivato, il browser genera l'immagine per la pubblicazione sul Web durante il caricamento."
@ -302,7 +301,7 @@ uploadFromUrlMayTakeTime: "Il caricamento del file può richiedere tempo."
explore: "Esplora"
messageRead: "Visualizzato"
noMoreHistory: "Non c'è più cronologia da visualizzare"
startMessaging: "Nuovo messaggio"
startChat: "Inizia a chattare"
nUsersRead: "Letto da {n} persone"
agreeTo: "Sono d'accordo con {0}"
agree: "Accetto"
@ -425,6 +424,7 @@ antennaExcludeBots: "Escludere i Bot"
antennaKeywordsDescription: "Sparando con uno spazio indichi la condizione E (and). Separando con un a capo, indichi la condizione O (or)."
notifyAntenna: "Invia notifiche delle nuove note"
withFileAntenna: "Solo note con file in allegato"
hideNotesInSensitiveChannel: "Nascondere le Note dai canali espliciti"
enableServiceworker: "Abilita ServiceWorker"
antennaUsersDescription: "Elenca un nome utente per riga"
caseSensitive: "Sensibile alla distinzione tra maiuscole e minuscole"
@ -445,7 +445,7 @@ exploreFediverse: "Esplora il Fediverso"
popularTags: "Hashtag popolari"
userList: "Liste"
about: "Informazioni"
aboutMisskey: "Informazioni di Misskey"
aboutMisskey: "A proposito di Misskey"
administrator: "Amministratore"
token: "Token"
2fa: "Autenticazione a due fattori"
@ -491,8 +491,6 @@ noteOf: "Note di {user}"
quoteAttached: "Citazione allegata"
quoteQuestion: "Vuoi aggiungere una citazione?"
attachAsFileQuestion: "Il testo copiato eccede le dimensioni, vuoi allegarlo?"
noMessagesYet: "Ancora nessuna chat"
newMessageExists: "Hai ricevuto un nuovo messaggio"
onlyOneFileCanBeAttached: "È possibile allegare al messaggio soltanto uno file"
signinRequired: "Occorre avere un profilo registrato su questa istanza"
signinOrContinueOnRemote: "Per continuare, devi accedere alla tua istanza o registrarti su questa e poi accedere"
@ -606,7 +604,7 @@ scratchpad: "ScratchPad"
scratchpadDescription: "Lo Scratchpad offre un ambiente per esperimenti di AiScript. È possibile scrivere, eseguire e confermare i risultati dell'interazione del codice con Misskey."
uiInspector: "UI Inspector"
uiInspectorDescription: "Puoi visualizzare un elenco di elementi UI presenti in memoria. I componenti dell'interfaccia utente vengono generati dalle funzioni Ui:C:."
output: "Uscita"
output: "Output"
script: "Script"
disablePagesScript: "Disabilita AiScript nelle pagine"
updateRemoteUser: "Aggiorna dati dal profilo remoto"
@ -698,6 +696,7 @@ userSaysSomethingAbout: "{name} ha Notato a riguardo di \"{word}\""
makeActive: "Attiva"
display: "Visualizza"
copy: "Copia"
copiedToClipboard: "Copiato negli appunti"
metrics: "Statistiche"
overview: "Anteprima"
logs: "Log"
@ -766,7 +765,7 @@ driveUsage: "Utilizzazione del Drive"
noCrawle: "Rifiuta l'indicizzazione dai robot."
noCrawleDescription: "Richiedi che i motori di ricerca non indicizzino la tua pagina di profilo, le tue note, pagine, ecc."
lockedAccountInfo: "A meno che non imposti la visibilità delle tue note su \"Solo ai follower\", le tue note sono visibili da tutti, anche se hai configurato l'account per confermare manualmente le richieste di follow."
alwaysMarkSensitive: "Segnare gli allegati come espliciti come opzione predefinita"
alwaysMarkSensitive: "Segnare automaticamente come espliciti gli allegati"
loadRawImages: "Visualizza le intere immagini allegate invece delle miniature."
disableShowingAnimatedImages: "Disabilita le immagini animate"
highlightSensitiveMedia: "Evidenzia i media espliciti"
@ -893,7 +892,7 @@ searchResult: "Risultati della Ricerca"
hashtags: "Hashtag"
troubleshooting: "Risoluzione problemi"
useBlurEffect: "Utilizza effetto sfocatura"
learnMore: "Più dettagli"
learnMore: "Per saperne di più"
misskeyUpdated: "Misskey è stato aggiornato!"
whatIsNew: "Informazioni sull'aggiornamento"
translate: "Traduci"
@ -901,7 +900,7 @@ translatedFrom: "Traduzione da {x}"
accountDeletionInProgress: "È in corso l'eliminazione del profilo"
usernameInfo: "Un nome per identificare univocamente il tuo profilo sull'istanza. Puoi utilizzare caratteri alfanumerici maiuscoli, minuscoli e il trattino basso (_). Non potrai cambiare nome utente in seguito."
aiChanMode: "Modalità Ai"
devMode: "Modalità sviluppatori"
devMode: "Modalità sviluppo"
keepCw: "Mostra i contenuti espliciti"
pubSub: "Publish/Subscribe del profilo"
lastCommunication: "La comunicazione più recente"
@ -973,7 +972,7 @@ check: "Verifica"
driveCapOverrideLabel: "Modificare la capienza del Drive per questo profilo"
driveCapOverrideCaption: "Se viene specificato meno di 0, viene annullato."
requireAdminForView: "Per visualizzarli, è necessario aver effettuato l'accesso con un profilo amministratore."
isSystemAccount: "Questi profili vengono creati e gestiti automaticamente dal sistema"
isSystemAccount: "Si tratta di un profilo creato e gestito automaticamente dal sistema."
typeToConfirm: "Digita {x} per continuare"
deleteAccount: "Eliminazione profilo"
document: "Documentazione"
@ -1049,7 +1048,7 @@ permissionDeniedError: "Errore, attività non autorizzata"
permissionDeniedErrorDescription: "Non si dispone dell'autorizzazione per eseguire questa operazione."
preset: "Preimpostato"
selectFromPresets: "Seleziona preimpostato"
achievements: "Obiettivi raggiunti"
achievements: "Conquiste"
gotInvalidResponseError: "Risposta del server non valida"
gotInvalidResponseErrorDescription: "Il server potrebbe essere irraggiungibile o in manutenzione. Riprova più tardi."
thisPostMayBeAnnoying: "Questa nota potrebbe essere offensiva"
@ -1090,7 +1089,7 @@ notesSearchNotAvailable: "Non è possibile cercare tra le Note."
license: "Licenza"
unfavoriteConfirm: "Vuoi davvero rimuovere la preferenza?"
myClips: "Le mie Clip"
drivecleaner: "Drive cleaner"
drivecleaner: "Pulizia del Drive"
retryAllQueuesNow: "Ritenta di consumare tutte le code"
retryAllQueuesConfirmTitle: "Vuoi ritentare adesso?"
retryAllQueuesConfirmText: "Potrebbe sovraccaricare il server temporaneamente."
@ -1309,6 +1308,130 @@ availableRoles: "Ruoli disponibili"
acknowledgeNotesAndEnable: "Attivare dopo averne compreso il comportamento."
federationSpecified: "Questo server è federato solo con istanze specifiche del Fediverso. Puoi interagire solo con quelle scelte dall'amministrazione."
federationDisabled: "Questo server ha la federazione disabilitata. Non puoi interagire con profili provenienti da altri server."
confirmOnReact: "Confermare le reazioni"
reactAreYouSure: "Vuoi davvero reagire con {emoji} ?"
markAsSensitiveConfirm: "Vuoi davvero indicare questo contenuto multimediale come esplicito?"
unmarkAsSensitiveConfirm: "Vuoi davvero indicare come non esplicito il contenuto multimediale?"
preferences: "Preferenze"
accessibility: "Accessibilità"
preferencesProfile: "Profilo preferenze"
copyPreferenceId: "Copia ID preferenze"
resetToDefaultValue: "Ripristina a predefinito"
overrideByAccount: "Sovrascrivere col profilo"
untitled: "Senza titolo"
noName: "Senza nome"
skip: "Salta"
restore: "Ripristina"
syncBetweenDevices: "Sincronizzazione tra i dispositivi"
preferenceSyncConflictTitle: "Sul server esiste già il valore impostato"
preferenceSyncConflictText: "Le impostazione sincronizzata salverà il valore sul server. Però, bada che esiste già un valore sul server. Quale vorresti sovrascrivere?"
preferenceSyncConflictChoiceServer: "Valore del server"
preferenceSyncConflictChoiceDevice: "Valore del dispositivo"
preferenceSyncConflictChoiceCancel: "Annulla la sincronizzazione"
paste: "Incolla"
emojiPalette: "Tavolozza emoji"
postForm: "Finestra di pubblicazione"
textCount: "Il numero di caratteri"
information: "Informazioni"
chat: "Chat"
migrateOldSettings: "Migrare le vecchie impostazioni"
migrateOldSettings_description: "Di solito, viene fatto automaticamente. Se per qualche motivo non fossero migrate con successo, è possibile avviare il processo di migrazione manualmente, sovrascrivendo le configurazioni attuali."
compress: "Comprimi"
right: "Destra"
bottom: "Sotto"
top: "Sopra"
embed: "Incorporare"
_chat:
noMessagesYet: "Ancora nessun messaggio"
newMessage: "Nuovo messaggio"
individualChat: "Chat individuale"
individualChat_description: "Puoi chattare con una persona specifica."
roomChat: "Stanza di chat"
roomChat_description: "Puoi chattare con più persone.\nInoltre, anche le persone che non consentono chat personalizzate possono chattare se gli altri accettano."
createRoom: "Crea stanza"
inviteUserToChat: "Invita a chattare altre persone"
yourRooms: "Le tue stanze"
joiningRooms: "Stanze a cui partecipi"
invitations: "Invita"
noInvitations: "Nessun invito"
history: "Cronologia"
noHistory: "Nessuna cronologia"
noRooms: "Nessuna stanza"
inviteUser: "Invita"
sentInvitations: "Inviti spediti"
join: "Entra"
ignore: "Ignora"
leave: "Esci"
members: "Membri"
searchMessages: "Cerca messaggi"
home: "Home"
send: "Inviare"
newline: "Nuova riga"
muteThisRoom: "Silenzia stanza"
deleteRoom: "Elimina stanza"
chatNotAvailableForThisAccountOrServer: "Questo server, o questo profilo ha disabilitato la chat."
chatNotAvailableInOtherAccount: "La chat non è disponibile nel profilo dell'altra persona."
cannotChatWithTheUser: "Impossibile chattare con questa persona"
cannotChatWithTheUser_description: "La chat potrebbe non essere disponibile, oppure l'altra persona potrebbe non esserlo."
chatWithThisUser: "Chatta con questa persona"
thisUserAllowsChatOnlyFromFollowers: "Questa persona permette di chattare soltanto i propri Follower."
thisUserAllowsChatOnlyFromFollowing: "Questa persona permette di chattare soltanto ai suoi Follow."
thisUserAllowsChatOnlyFromMutualFollowing: "Questa persona permette di chattare solo a relazioni reciproche."
thisUserNotAllowedChatAnyone: "Questa persona non permette di chattare a nessuno."
chatAllowedUsers: "Persone ammesse alla chat"
chatAllowedUsers_note: "Puoi chattare con le persone a cui hai già inviato un messaggio, indipendentemente da questa impostazione."
_chatAllowedUsers:
everyone: "Chiunque"
followers: "Solo i tuoi Follower"
following: "Solo i tuoi Follow"
mutual: "Solo relazioni reciproche"
none: "Nessuno"
_emojiPalette:
palettes: "Tavolozza"
enableSyncBetweenDevicesForPalettes: "Attiva la sincronizzazione tra dispositivi"
paletteForMain: "Tavolozza principale"
paletteForReaction: "Tavolozza per reazioni"
_settings:
driveBanner: "Permette di gestire e configurare il Drive, controllare il consumo di spazio e configurare il caricamento dei file."
pluginBanner: "Consentono di migliorare le funzionalità. Le estensioni si possono configurare e gestire singolarmente."
notificationsBanner: "Puoi impostare il tipo di notifiche da ricevere dal server e anche le notifiche push."
api: "API"
webhook: "Webhook"
serviceConnection: "Integrazione servizi"
serviceConnectionBanner: "Puoi gestire i codici di accesso e i Webhook per collegare App o servizi esterni."
accountData: "Dati del profilo"
accountDataBanner: "Puoi gestire i dati del tuo profilo, esportando e importando."
muteAndBlockBanner: "Puoi configurare la visibiltà dei contenuti e limitare le attività provenienti da profili specifici."
accessibilityBanner: "Puoi personalizzare e migliorare la lettura sul tuo dispositivo in modo che sia più chiaro e reattivo."
privacyBanner: "Puoi configurare la privacy del tuo profilo, come la visibilità delle Note, la visibilità del profilo nelle ricerche e l'approvazione delle relazioni tra profili."
securityBanner: "Puoi gestire la sicurezza del tuo account, la password, i modi di accesso, la generazione di codici OTP per accesso multi fattore (MFA/2FA) e la passkey."
preferencesBanner: "Puoi personalizzare il comportamento del tuo dispositivo."
appearanceBanner: "Puoi personalizzare l'aspetto nel dispositivo, in base alle tue preferenze."
soundsBanner: "Puoi personalizzare i suoni emessi dagli eventi sul tuo dispositivo."
timelineAndNote: "Note e Timeline"
makeEveryTextElementsSelectable: "Imposta ogni elemento come selezionabile"
makeEveryTextElementsSelectable_description: "Potrebbe ridurre l'usabilità in alcune situazioni."
useStickyIcons: "Fissa le icone durante lo scorrimento"
showNavbarSubButtons: "Mostra i pulsanti secondari nella barra di navigazione"
ifOn: "Quando attivato"
ifOff: "Quando disattivato"
enableSyncThemesBetweenDevices: "Sincronizzare il tema tra i dispositivi"
_chat:
showSenderName: "Mostra il nome del mittente"
sendOnEnter: "Invio spedisce"
_preferencesProfile:
profileName: "Nome del profilo"
profileNameDescription: "Impostare il nome che indentifica questo dispositivo."
profileNameDescription2: "Es: \"PC principale\" o \"Cellulare\""
_preferencesBackup:
autoBackup: "Backup automatico"
restoreFromBackup: "Ripristinare da backup"
noBackupsFoundTitle: "Nessun backup trovato"
noBackupsFoundDescription: "Impossibile trovare un backup creato automaticamente. Se se hai salvato il file di backup manualmente, puoi importarlo e ripristinarlo."
selectBackupToRestore: "Seleziona un backup da ripristinare"
youNeedToNameYourProfileToEnableAutoBackup: "Per abilitare i backup automatici, è necessario indicare il nome del profilo."
autoPreferencesBackupIsNotEnabledForThisDevice: "Su questo dispositivo non è stato attivato il backup automatico delle preferenze."
backupFound: "Esiste il Backup delle preferenze"
_accountSettings:
requireSigninToViewContents: "Per vedere il contenuto, è necessaria l'iscrizione"
requireSigninToViewContentsDescription1: "Richiedere l'iscrizione per visualizzare tutte le Note e gli altri contenuti che hai creato. Probabilmente l'effetto è impedire la raccolta di informazioni da parte dei bot crawler."
@ -1319,6 +1442,7 @@ _accountSettings:
makeNotesHiddenBefore: "Nascondi le Note pubblicate in precedenza"
makeNotesHiddenBeforeDescription: "Mentre questa funzione è abilitata, le Note antecedenti al momento impostato, saranno visibili soltanto a te (private). Disabilitandola nuovamente, verrà ripristinata anche la visibilità pubblica della Nota."
mayNotEffectForFederatedNotes: "Le Note già federate su server remoti potrebbero non essere modificate."
mayNotEffectSomeSituations: "Queste restrizioni sono semplificate. In alcuni casi, potrebbero anche non avvenire. Ad esempio visionando un server remoto o durante la moderazione."
notesHavePassedSpecifiedPeriod: "Note antecedenti al periodo specificato"
notesOlderThanSpecifiedDateAndTime: "Note antecedenti al momento specificato"
_abuseUserReport:
@ -1445,9 +1569,9 @@ _initialTutorial:
description: "Queste sono solamente alcune delle funzionalità principali di Misskey. Per ulteriori informazioni, {link}."
_timelineDescription:
home: "Nella Timeline Home, la tua cronologia principale, puoi vedere le Note provenienti dai profili che segui (Following)."
local: "La Timeline Locale, è una cronologia di Note pubblicate da tutti i profili iscritti su questo server."
social: "La Timeline Sociale, unisce in ordine cronologico l'elenco di Note presenti nella Timeline Home e quella Locale."
global: "La Timeline Federata ti consente di vedere le Note pubblicate dai profili di tutti gli altri server federati a questo."
local: "La Timeline Locale è un flusso di Note pubblicate dai profili iscritti a questo server."
social: "La Timeline Sociale elenca, in ordine cronologico, il flusso di Note nella Timeline Home e Locale."
global: "Nella Timeline Federata trovi il flusso di Note provenienti da profili iscritti ad altri server, federati a questo."
_serverRules:
description: "In Europa è necessario mostrare l'informativa sul trattamento dei dati personali, prima della registrazione al servizio."
_serverSettings:
@ -1471,8 +1595,8 @@ _serverSettings:
_accountMigration:
moveFrom: "Migra un altro profilo dentro a questo"
moveFromSub: "Crea un alias verso un altro profilo remoto"
moveFromLabel: "Profilo da cui migrare #{n}"
moveFromDescription: "Se desideri spostare i Follower da un altro profilo a questo, devi prima creare un alias qui. Assicurati averlo creato PRIMA di eseguire l'attività! Inserisci l'indirizzo del profilo mittente in questo modo: @persona@istanza.it"
moveFromLabel: "Profilo da cui migrare n. {n}"
moveFromDescription: "Se desideri spostare i Follower da un altro profilo a questo, devi prima creare un alias qui. Assicurati averlo creato PRIMA di eseguire l'attività! Inserisci l'indirizzo del profilo mittente in questo modo: @persona@vecchia.istanza.it"
moveTo: "Migrare questo profilo verso un un altro"
moveToLabel: "Profilo verso cui migrare"
moveCannotBeUndone: "La migrazione è irreversibile, non può essere interrotta o annullata."
@ -1548,13 +1672,13 @@ _achievements:
title: "Principiante III"
description: "Hai totalizzato 15 accessi!"
_login30:
title: "Misskist I"
title: "Missalcolista I"
description: "Hai totalizzato 30 accessi!"
_login60:
title: "Misskeist II"
title: "Missalcolista II"
description: "Hai totalizzato 60 accessi!"
_login100:
title: "Misskeist III"
title: "Missalcolista III"
description: "Hai totalizzato 100 accessi!"
flavor: "Violent Misskeist"
_login200:
@ -1640,10 +1764,10 @@ _achievements:
description: "Hai superato i 1.000 profili Follower"
_collectAchievements30:
title: "Collezionista di successi"
description: "Hai raggiunto 30 obiettivi"
description: "Hai raggiunto 30 conquiste"
_viewAchievements3min:
title: "Mi piacciono i risultati"
description: "Guarda la tua collezione di obiettivi per almeno 3 minuti"
description: "Ammira la tua collezione di conquiste per almeno 3 minuti"
_iLoveMisskey:
title: "I LOVE Misskey"
description: "Pubblica «I ♥ #Misskey»"
@ -1804,6 +1928,7 @@ _role:
canImportFollowing: "Può importare Following"
canImportMuting: "Può importare Silenziati"
canImportUserLists: "Può importare liste di Profili"
canChat: "Chat consentita"
_condition:
roleAssignedTo: "Assegnato a ruoli manualmente"
isLocal: "Profilo locale"
@ -1908,7 +2033,7 @@ _registry:
domain: "Dominio"
createKey: "Crea chiave"
_aboutMisskey:
about: "Misskey è un software libero e open source, sviluppato da syuilo dal 2014."
about: "Misskey è software libero, open source, sviluppato da Syuilo fin dal lontano 2014."
contributors: "Principali sostenitori"
allContributors: "Tutti i sostenitori"
source: "Codice sorgente"
@ -1967,6 +2092,7 @@ _theme:
installed: "{name} è installato"
installedThemes: "Temi installati"
builtinThemes: "Temi integrati"
instanceTheme: "Tema dell'istanza"
alreadyInstalled: "Questo tema è già installato"
invalid: "Il formato tema non è valido"
make: "Crea un tema"
@ -1999,14 +2125,13 @@ _theme:
header: "Intestazione"
navBg: "Sfondo della barra laterale"
navFg: "Testo della barra laterale"
navHoverFg: "Testo della barra laterale (al passaggio del mouse)"
navActive: "Testo della barra laterale (attivo)"
navIndicator: "Indicatore di barra laterale"
link: "Link"
hashtag: "Hashtag"
mention: "Menzioni"
mentionMe: "Menzioni (di me)"
renote: "Rinota"
renote: "Renota"
modalBg: "Sfondo modale."
divider: "Interruzione di linea"
scrollbarHandle: "Maniglie della barra di scorrimento"
@ -2022,17 +2147,15 @@ _theme:
buttonHoverBg: "Sfondo del pulsante (sorvolato)"
inputBorder: "Inquadra casella di testo"
driveFolderBg: "Sfondo della cartella di disco"
wallpaperOverlay: "Sovrapposizione dello sfondo"
badge: "Distintivo"
messageBg: "Sfondo della chat"
accentDarken: "Temi (scuri)"
accentLighten: "Temi (luminosi)"
fgHighlighted: "Testo in evidenza."
_sfx:
note: "Nota"
noteMy: "Mia nota"
notification: "Notifiche"
reaction: "Quando seleziono una reazione"
chatMessage: "Messaggio di chat"
_soundSettings:
driveFile: "Suoni del Drive"
driveFileWarn: "Seleziona file dal dispositivo"
@ -2179,6 +2302,8 @@ _permissions:
"read:clip-favorite": "Vedere Clip preferite"
"read:federation": "Vedere la federazione"
"write:report-abuse": "Inviare segnalazioni"
"write:chat": "Gestire la chat"
"read:chat": "Visualizzare le chat"
_auth:
shareAccessTitle: "Permessi dell'applicazione"
shareAccess: "Vuoi autorizzare {name} ad accedere al tuo profilo?"
@ -2235,7 +2360,7 @@ _widgets:
userList: "Elenco utenti"
_userList:
chooseList: "Seleziona una lista"
clicker: "Cliccaggio"
clicker: "Cliccheria"
birthdayFollowings: "Compleanni del giorno"
_cw:
hide: "Nascondere"
@ -2298,7 +2423,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."
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'."
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."
@ -2427,6 +2552,7 @@ _notification:
newNote: "Nuove Note"
unreadAntennaNote: "Antenna {name}"
roleAssigned: "Ruolo assegnato"
chatRoomInvitationReceived: "Invito in una stanza di chat"
emptyPushNotificationMessage: "Le notifiche push sono state aggiornate."
achievementEarned: "Obiettivo raggiunto"
testNotification: "Provare la notifica"
@ -2440,6 +2566,8 @@ _notification:
flushNotification: "Azzera le notifiche"
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})."
_types:
all: "Tutto"
note: "Nuove Note"
@ -2453,9 +2581,11 @@ _notification:
receiveFollowRequest: "Richieste di follow in arrivo"
followRequestAccepted: "Richieste di follow accettate"
roleAssigned: "Ruolo concesso"
chatRoomInvitationReceived: "Invito in una stanza di chat"
achievementEarned: "Risultato raggiunto"
exportCompleted: "Esportazione completata"
login: "Accessi"
createToken: "Creare un token di accesso"
test: "Notifiche di test"
app: "Notifiche da applicazioni"
_actions:
@ -2465,6 +2595,9 @@ _notification:
_deck:
alwaysShowMainColumn: "Mostra sempre la colonna principale"
columnAlign: "Allineare colonne"
columnGap: "Margine tra le colonne"
deckMenuPosition: "Posizione del menu Deck"
navbarPosition: "Posizione barra di navigazione"
addColumn: "Aggiungi colonna"
newNoteNotificationSettings: "Preferenze per le notifiche di nuove Note"
configureColumn: "Impostazioni colonna"
@ -2483,6 +2616,7 @@ _deck:
useSimpleUiForNonRootPages: "Visualizza sotto pagine con interfaccia web semplice"
usedAsMinWidthWhenFlexible: "Se \"larghezza flessibile\" è abilitato, questa diventa la larghezza minima"
flexible: "Larghezza flessibile"
enableSyncBetweenDevicesForProfiles: "Abilita la sincronizzazione delle informazioni profilo tra dispositivi"
_columns:
main: "Principale"
widgets: "Riquadri"
@ -2501,8 +2635,8 @@ _disabledTimeline:
title: "Timeline disabilitata"
description: "Il ruolo in cui sei non ti permette di leggere questa timeline"
_drivecleaner:
orderBySizeDesc: "Dal più grande al più piccolo"
orderByCreatedAtAsc: "Dal più vecchio al più recente"
orderBySizeDesc: "Dal file più grosso al più piccolo"
orderByCreatedAtAsc: "Dal file più vecchio al più recente"
_webhookSettings:
createWebhook: "Creazione Webhook"
modifyWebhook: "Modifica Webhook"
@ -2590,6 +2724,8 @@ _moderationLogTypes:
deletePage: "Pagina eliminata"
deleteFlash: "Play eliminato"
deleteGalleryPost: "Eliminazione pubblicazione nella Galleria"
deleteChatRoom: "Elimina chat"
updateProxyAccountDescription: "Aggiornata la descrizione del profilo proxy"
_fileViewer:
title: "Dettagli del file"
type: "Tipo di file"
@ -2603,10 +2739,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "Prima di installare, assicurati che la fonte sia affidabile."
_plugin:
title: "Vuoi davvero installare questo componente aggiuntivo?"
metaTitle: "Informazioni sul componente aggiuntivo"
_theme:
title: "Vuoi davvero installare questa variazione grafica?"
metaTitle: "Informazioni sulla variazione grafica"
_meta:
base: "Combinazione base di colori"
_vendorInfo:
@ -2807,8 +2941,8 @@ _selfXssPrevention:
description2: "Se non sai esattamente cosa stai facendo, %c smetti subito e chiudi questa finestra."
description3: "Per favore, controlla questo collegamento per avere maggiori dettagli. {link}"
_followRequest:
recieved: "Ricezione richiesta di Follow"
sent: "Richiesta di Follow, inviata"
recieved: "Richieste in ingresso"
sent: "Richieste in uscita"
_remoteLookupErrors:
_federationNotAllowed:
title: "Server irraggiungibile"
@ -2822,8 +2956,6 @@ _remoteLookupErrors:
_responseInvalid:
title: "Risposta non valida"
description: "La comunicazione col server è andata a buon fine, ma abbiamo ricevuto dati non validi."
_responseInvalidIdHostNotMatch:
description: "L'indirizzo immesso non coincide con la URL finale. Interrogando i server per un contenuto remoto, assicurarsi di utilizzare la URL finale e non quella di un server intermedio."
_noSuchObject:
title: "Non trovato"
description: "La risorsa richiesta non è stata trovata. Verificare nuovamente la URL."
@ -2840,3 +2972,23 @@ _captcha:
_unknown:
title: "Errore CAPTCHA"
text: "Si è verificato un errore imprevisto."
_bootErrors:
title: "Caricamento non riuscito"
serverError: "Dopo una breve attesa, e dopo aver ricaricato la pagina, se il problema persiste, contatta l'amministrazione comunicando il seguente ID di errore."
solution: "Di seguito, alcune probabili soluzioni al problema."
solution1: "Aggiornare browser e il sistema operativo all'ultima versione"
solution2: "Disattivare gli adblocker"
solution3: "Cancellare la cache del browser"
solution4: "(Per chi utilizza il Browser Tor) Impostare dom.webaudio.enabled = vero"
otherOption: "Altre opzioni"
otherOption1: "Nelle impostazioni, cancellare le impostazioni del client e svuotare la cache"
otherOption2: "Avviare il client predefinito"
otherOption3: "Avviare lo strumento di riparazione"
_search:
searchScopeAll: "Tutte"
searchScopeLocal: "Locale"
searchScopeServer: "Specifiche del server"
searchScopeUser: "Profilo specifico"
pleaseEnterServerHost: "Inserire il nome host"
pleaseSelectUser: "Per favore, seleziona un profilo"
serverHostPlaceholder: "Es: misskey.example.com"

View file

@ -289,7 +289,6 @@ deleteAreYouSure: "「{x}」を削除しますか?"
resetAreYouSure: "リセットしますか?"
areYouSure: "よろしいですか?"
saved: "保存しました"
messaging: "チャット"
upload: "アップロード"
keepOriginalUploading: "オリジナル画像を保持"
keepOriginalUploadingDescription: "画像をアップロードする時にオリジナル版を保持します。オフにするとアップロード時にブラウザでWeb公開用画像を生成します。"
@ -302,7 +301,7 @@ uploadFromUrlMayTakeTime: "アップロードが完了するまで時間がか
explore: "みつける"
messageRead: "既読"
noMoreHistory: "これより過去の履歴はありません"
startMessaging: "チャットを開始"
startChat: "チャットを始める"
nUsersRead: "{n}人が読みました"
agreeTo: "{0}に同意"
agree: "同意する"
@ -425,6 +424,7 @@ antennaExcludeBots: "Botアカウントを除外"
antennaKeywordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります"
notifyAntenna: "新しいノートを通知する"
withFileAntenna: "ファイルが添付されたノートのみ"
hideNotesInSensitiveChannel: "センシティブなチャンネルのノートを非表示"
enableServiceworker: "ブラウザへのプッシュ通知を有効にする"
antennaUsersDescription: "ユーザー名を改行で区切って指定します"
caseSensitive: "大文字小文字を区別する"
@ -491,8 +491,6 @@ noteOf: "{user}のノート"
quoteAttached: "引用付き"
quoteQuestion: "引用として添付しますか?"
attachAsFileQuestion: "クリップボードのテキストが長いです。テキストファイルとして添付しますか?"
noMessagesYet: "まだチャットはありません"
newMessageExists: "新しいメッセージがあります"
onlyOneFileCanBeAttached: "メッセージに添付できるファイルはひとつです"
signinRequired: "続行する前に、登録またはログインが必要です"
signinOrContinueOnRemote: "続行するには、お使いのサーバーに移動するか、このサーバーに登録・ログインする必要があります"
@ -698,6 +696,7 @@ userSaysSomethingAbout: "{name}が「{word}」について何かを言いまし
makeActive: "アクティブにする"
display: "表示"
copy: "コピー"
copiedToClipboard: "クリップボードにコピーされました"
metrics: "メトリクス"
overview: "概要"
logs: "ログ"
@ -1238,7 +1237,7 @@ releaseToRefresh: "離してリロード"
refreshing: "リロード中"
pullDownToRefresh: "引っ張ってリロード"
disableStreamingTimeline: "タイムラインのリアルタイム更新を無効にする"
useGroupedNotifications: "通知をグルーピングして表示する"
useGroupedNotifications: "通知をグルーピング"
signupPendingError: "メールアドレスの確認中に問題が発生しました。リンクの有効期限が切れている可能性があります。"
cwNotationRequired: "「内容を隠す」がオンの場合は注釈の記述が必要です。"
doReaction: "リアクションする"
@ -1309,6 +1308,136 @@ availableRoles: "利用可能なロール"
acknowledgeNotesAndEnable: "注意事項を理解した上でオンにします。"
federationSpecified: "このサーバーはホワイトリスト連合で運用されています。管理者が指定したサーバー以外とやり取りすることはできません。"
federationDisabled: "このサーバーは連合が無効化されています。他のサーバーのユーザーとやり取りすることはできません。"
confirmOnReact: "リアクションする際に確認する"
reactAreYouSure: "\" {emoji} \" をリアクションしますか?"
markAsSensitiveConfirm: "このメディアをセンシティブとして設定しますか?"
unmarkAsSensitiveConfirm: "このメディアのセンシティブ指定を解除しますか?"
preferences: "環境設定"
accessibility: "アクセシビリティ"
preferencesProfile: "設定のプロファイル"
copyPreferenceId: "設定IDをコピー"
resetToDefaultValue: "初期値に戻す"
overrideByAccount: "アカウントで上書き"
untitled: "無題"
noName: "名前はありません"
skip: "スキップ"
restore: "復元"
syncBetweenDevices: "デバイス間で同期"
preferenceSyncConflictTitle: "サーバーに設定値が存在します"
preferenceSyncConflictText: "同期が有効にされた設定項目は設定値をサーバーに保存しますが、この設定項目のサーバーに保存された設定値が見つかりました。どちらの設定値で上書きしますか?"
preferenceSyncConflictChoiceServer: "サーバーの設定値"
preferenceSyncConflictChoiceDevice: "デバイスの設定値"
preferenceSyncConflictChoiceCancel: "同期の有効化をキャンセル"
paste: "ペースト"
emojiPalette: "絵文字パレット"
postForm: "投稿フォーム"
textCount: "文字数"
information: "情報"
chat: "チャット"
migrateOldSettings: "旧設定情報を移行"
migrateOldSettings_description: "通常これは自動で行われていますが、何らかの理由により上手く移行されなかった場合は手動で移行処理をトリガーできます。現在の設定情報は上書きされます。"
compress: "圧縮"
right: "右"
bottom: "下"
top: "上"
embed: "埋め込み"
_chat:
noMessagesYet: "まだメッセージはありません"
newMessage: "新しいメッセージ"
individualChat: "個人チャット"
individualChat_description: "特定ユーザーとの一対一のチャットができます。"
roomChat: "ルームチャット"
roomChat_description: "複数人でのチャットができます。\nまた、個人チャットを許可していないユーザーとでも、相手が受け入れればチャットができます。"
createRoom: "ルームを作成"
inviteUserToChat: "ユーザーを招待してチャットを始めましょう"
yourRooms: "作成したルーム"
joiningRooms: "参加中のルーム"
invitations: "招待"
noInvitations: "招待はありません"
history: "履歴"
noHistory: "履歴はありません"
noRooms: "ルームはありません"
inviteUser: "ユーザーを招待"
sentInvitations: "送信した招待"
join: "参加"
ignore: "無視"
leave: "ルームから退出"
members: "メンバー"
searchMessages: "メッセージを検索"
home: "ホーム"
send: "送信"
newline: "改行"
muteThisRoom: "このルームをミュート"
deleteRoom: "ルームを削除"
chatNotAvailableForThisAccountOrServer: "このサーバー、またはこのアカウントでチャットは有効化されていません。"
chatNotAvailableInOtherAccount: "相手のアカウントでチャット機能が使えない状態になっています。"
cannotChatWithTheUser: "このユーザーとのチャットを開始できません"
cannotChatWithTheUser_description: "チャットが使えない状態になっているか、相手がチャットを開放していません。"
chatWithThisUser: "チャットする"
thisUserAllowsChatOnlyFromFollowers: "このユーザーはフォロワーからのみチャットを受け付けています。"
thisUserAllowsChatOnlyFromFollowing: "このユーザーは、このユーザーがフォローしているユーザーからのみチャットを受け付けています。"
thisUserAllowsChatOnlyFromMutualFollowing: "このユーザーは相互フォローのユーザーからのみチャットを受け付けています。"
thisUserNotAllowedChatAnyone: "このユーザーは誰からもチャットを受け付けていません。"
chatAllowedUsers: "チャットを許可する相手"
chatAllowedUsers_note: "自分からチャットメッセージを送った相手とはこの設定に関わらずチャットが可能です。"
_chatAllowedUsers:
everyone: "誰でも"
followers: "自分のフォロワーのみ"
following: "自分がフォローしているユーザーのみ"
mutual: "相互フォローのユーザーのみ"
none: "誰も許可しない"
_emojiPalette:
palettes: "パレット"
enableSyncBetweenDevicesForPalettes: "パレットのデバイス間同期を有効にする"
paletteForMain: "メインで使用するパレット"
paletteForReaction: "リアクションで使用するパレット"
_settings:
driveBanner: "ドライブの管理と設定、使用量の確認、ファイルをアップロードする際の設定を行えます。"
pluginBanner: "プラグインを利用するとクライアントの機能を拡張することができます。プラグインのインストール、個別の設定と管理が行えます。"
notificationsBanner: "サーバーからの受信する通知の種類と範囲や、プッシュ通知の設定が行えます。"
api: "API"
webhook: "Webhook"
serviceConnection: "サービス連携"
serviceConnectionBanner: "外部のアプリ・サービスと連携するためのアクセストークンやWebhookの管理と設定が行えます。"
accountData: "アカウントのデータ"
accountDataBanner: "アカウントデータのアーカイブをエクスポート/インポートして管理できます。"
muteAndBlockBanner: "非表示にするコンテンツの設定や、特定のユーザーからのアクションを制限する設定と管理を行えます。"
accessibilityBanner: "クライアントの視覚や動作に関するパーソナライズを行い、より最適に使用できるように設定できます。"
privacyBanner: "コンテンツの公開範囲、見つけやすさ、フォローの承認制などアカウントのプライバシーに関する設定を行えます。"
securityBanner: "パスワード、ログイン方法、認証アプリ、パスキーなどアカウントのセキュリティに関する設定を行えます。"
preferencesBanner: "好みに応じた、クライアントの全体的な動作の設定が行えます。"
appearanceBanner: "好みに応じた、クライアントの見た目・表示方法に関する設定が行えます。"
soundsBanner: "クライアントで再生するサウンドの設定が行えます。"
timelineAndNote: "タイムラインとノート"
makeEveryTextElementsSelectable: "全てのテキスト要素を選択可能にする"
makeEveryTextElementsSelectable_description: "有効にすると、一部のシチュエーションでのユーザビリティが低下する場合があります。"
useStickyIcons: "アイコンをスクロールに追従させる"
showNavbarSubButtons: "ナビゲーションバーに副ボタンを表示"
ifOn: "オンのとき"
ifOff: "オフのとき"
enableSyncThemesBetweenDevices: "デバイス間でインストールしたテーマを同期"
_chat:
showSenderName: "送信者の名前を表示"
sendOnEnter: "Enterで送信"
_preferencesProfile:
profileName: "プロファイル名"
profileNameDescription: "このデバイスを識別する名前を設定してください。"
profileNameDescription2: "例: 「メインPC」、「スマホ」など"
_preferencesBackup:
autoBackup: "自動バックアップ"
restoreFromBackup: "バックアップから復元"
noBackupsFoundTitle: "バックアップが見つかりませんでした"
noBackupsFoundDescription: "自動で作成されたバックアップは見つかりませんでしたが、バックアップファイルを手動で保存している場合、それをインポートして復元することはできます。"
selectBackupToRestore: "復元するバックアップを選択してください"
youNeedToNameYourProfileToEnableAutoBackup: "自動バックアップを有効にするにはプロファイル名の設定が必要です。"
autoPreferencesBackupIsNotEnabledForThisDevice: "このデバイスで設定の自動バックアップは有効になっていません。"
backupFound: "設定のバックアップが見つかりました"
_accountSettings:
requireSigninToViewContents: "コンテンツの表示にログインを必須にする"
@ -1320,6 +1449,7 @@ _accountSettings:
makeNotesHiddenBefore: "過去のノートを非公開化する"
makeNotesHiddenBeforeDescription: "この機能が有効になっている間、設定された日時より過去、または設定された時間を経過しているノートが自分のみ表示可能(非公開化)になります。無効に戻すと、ノートの公開状態も元に戻ります。"
mayNotEffectForFederatedNotes: "リモートサーバーに連合されたノートには効果が及ばない場合があります。"
mayNotEffectSomeSituations: "これらの制限は簡易的なものです。リモートサーバーでの閲覧やモデレーション時など、一部のシチュエーションでは適用されない場合があります。"
notesHavePassedSpecifiedPeriod: "指定した時間を経過しているノート"
notesOlderThanSpecifiedDateAndTime: "指定した日時より前のノート"
@ -1777,6 +1907,8 @@ _role:
descriptionOfIsExplorable: "オンにすると、「みつける」でメンバー一覧が公開されるほか、ロールのタイムラインが利用可能になります。"
displayOrder: "表示順"
descriptionOfDisplayOrder: "数値が大きいほどUI上で先頭に表示されます。"
preserveAssignmentOnMoveAccount: "アサイン状態を移行先アカウントにも引き継ぐ"
preserveAssignmentOnMoveAccount_description: "オンにすると、このロールが付与されたアカウントが移行された際に、移行先アカウントにもこのロールが引き継がれるようになります。"
canEditMembersByModerator: "モデレーターのメンバー編集を許可"
descriptionOfCanEditMembersByModerator: "オンにすると、管理者に加えてモデレーターもこのロールへユーザーをアサイン/アサイン解除できるようになります。オフにすると管理者のみが行えます。"
priority: "優先度"
@ -1817,6 +1949,7 @@ _role:
canImportFollowing: "フォローのインポートを許可"
canImportMuting: "ミュートのインポートを許可"
canImportUserLists: "リストのインポートを許可"
canChat: "チャットを許可"
_condition:
roleAssignedTo: "マニュアルロールにアサイン済み"
isLocal: "ローカルユーザー"
@ -2001,6 +2134,7 @@ _theme:
installed: "{name}をインストールしました"
installedThemes: "インストールされたテーマ"
builtinThemes: "標準のテーマ"
instanceTheme: "サーバーのテーマ"
alreadyInstalled: "そのテーマは既にインストールされています"
invalid: "テーマの形式が間違っています"
make: "テーマを作る"
@ -2032,16 +2166,15 @@ _theme:
panel: "パネル"
shadow: "影"
header: "ヘッダー"
navBg: "サイドバーの背景"
navFg: "サイドバーの文字"
navHoverFg: "サイドバー文字(ホバー)"
navActive: "サイドバー文字(アクティブ)"
navIndicator: "サイドバーのインジケーター"
navBg: "ナビゲーションバーの背景"
navFg: "ナビゲーションバーの文字"
navActive: "ナビゲーションバー文字(アクティブ)"
navIndicator: "ナビゲーションバーのインジケーター"
link: "リンク"
hashtag: "ハッシュタグ"
mention: "メンション"
mentionMe: "あなた宛てメンション"
renote: "Renote"
renote: "リノート"
modalBg: "モーダルの背景"
divider: "分割線"
scrollbarHandle: "スクロールバーの取っ手"
@ -2057,11 +2190,8 @@ _theme:
buttonHoverBg: "ボタンの背景 (ホバー)"
inputBorder: "入力ボックスの縁取り"
driveFolderBg: "ドライブフォルダーの背景"
wallpaperOverlay: "壁紙のオーバーレイ"
badge: "バッジ"
messageBg: "チャットの背景"
accentDarken: "アクセント (暗め)"
accentLighten: "アクセント (明るめ)"
fgHighlighted: "強調された文字"
_sfx:
@ -2069,6 +2199,7 @@ _sfx:
noteMy: "ノート(自分)"
notification: "通知"
reaction: "リアクション選択時"
chatMessage: "チャットのメッセージ"
_soundSettings:
driveFile: "ドライブの音声を使用"
@ -2221,6 +2352,8 @@ _permissions:
"read:clip-favorite": "クリップのいいねを見る"
"read:federation": "連合に関する情報を取得する"
"write:report-abuse": "違反を報告する"
"write:chat": "チャットを操作する"
"read:chat": "チャットを閲覧する"
_auth:
shareAccessTitle: "アプリへのアクセス許可"
@ -2487,6 +2620,7 @@ _notification:
newNote: "新しい投稿"
unreadAntennaNote: "アンテナ {name}"
roleAssigned: "ロールが付与されました"
chatRoomInvitationReceived: "チャットルームへ招待されました"
emptyPushNotificationMessage: "プッシュ通知の更新をしました"
achievementEarned: "実績を獲得"
testNotification: "通知テスト"
@ -2500,6 +2634,8 @@ _notification:
flushNotification: "通知の履歴をリセットする"
exportOfXCompleted: "{x}のエクスポートが完了しました"
login: "ログインがありました"
createToken: "アクセストークンが作成されました"
createTokenDescription: "心当たりがない場合は「{text}」を通じてアクセストークンを削除してください。"
_types:
all: "すべて"
@ -2514,9 +2650,11 @@ _notification:
receiveFollowRequest: "フォロー申請を受け取った"
followRequestAccepted: "フォローが受理された"
roleAssigned: "ロールが付与された"
chatRoomInvitationReceived: "チャットルームへ招待された"
achievementEarned: "実績の獲得"
exportCompleted: "エクスポートが完了した"
login: "ログイン"
createToken: "アクセストークンの作成"
test: "通知のテスト"
app: "連携アプリからの通知"
@ -2528,6 +2666,9 @@ _notification:
_deck:
alwaysShowMainColumn: "常にメインカラムを表示"
columnAlign: "カラムの寄せ"
columnGap: "カラム間のマージン"
deckMenuPosition: "デッキメニューの位置"
navbarPosition: "ナビゲーションバーの位置"
addColumn: "カラムを追加"
newNoteNotificationSettings: "新着ノート通知の設定"
configureColumn: "カラムの設定"
@ -2541,11 +2682,12 @@ _deck:
newProfile: "新規プロファイル"
deleteProfile: "プロファイルを削除"
introduction: "カラムを組み合わせて自分だけのインターフェイスを作りましょう!"
introduction2: "画面の右にある + を押して、いつでもカラムを追加できます。"
introduction2: "カラムを追加するには、画面の + をクリックします。"
widgetsIntroduction: "カラムのメニューから、「ウィジェットの編集」を選択してウィジェットを追加してください"
useSimpleUiForNonRootPages: "非ルートページは簡易UIで表示"
usedAsMinWidthWhenFlexible: "「幅を自動調整」が有効の場合、これが幅の最小値となります"
flexible: "幅を自動調整"
enableSyncBetweenDevicesForProfiles: "プロファイル情報のデバイス間同期を有効にする"
_columns:
main: "メイン"
@ -2660,6 +2802,8 @@ _moderationLogTypes:
deletePage: "ページを削除"
deleteFlash: "Playを削除"
deleteGalleryPost: "ギャラリーの投稿を削除"
deleteChatRoom: "チャットルームを削除"
updateProxyAccountDescription: "プロキシアカウントの説明を更新"
_fileViewer:
title: "ファイルの詳細"
@ -2675,10 +2819,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "配布元が信頼できるかを確認した上でインストールしてください。"
_plugin:
title: "このプラグインをインストールしますか?"
metaTitle: "プラグイン情報"
_theme:
title: "このテーマをインストールしますか?"
metaTitle: "テーマ情報"
_meta:
base: "基本のカラースキーム"
_vendorInfo:
@ -2907,9 +3049,7 @@ _remoteLookupErrors:
description: "このサーバーとの通信に失敗しました。相手サーバーがダウンしている可能性があります。また、不正なURIや存在しないURIを入力していないか確認してください。"
_responseInvalid:
title: "レスポンスが不正です"
description: "このサーバーと通信することはできましたが、得られたデータが不正なものでした。"
_responseInvalidIdHostNotMatch:
description: "入力されたURIのドメインと最終的に得られたURIのドメインとが異なります。第三者のサーバーを介してリモートのコンテンツを照会している場合は、発信元のサーバーで取得できるURIを使用して照会し直してください。"
description: "このサーバーと通信することはできましたが、得られたデータが不正なものでした。第三者のサーバーを介してリモートのコンテンツを照会している場合は、発信元のサーバーで取得できるURIを使用して照会し直してください。"
_noSuchObject:
title: "見つかりません"
description: "要求されたリソースは見つかりませんでした。URIをもう一度お確かめください。"
@ -2927,3 +3067,25 @@ _captcha:
_unknown:
title: "CAPTCHAエラー"
text: "想定外のエラーが発生しました。"
_bootErrors:
title: "読み込みに失敗しました"
serverError: "少し待ってからリロードしてもまだ問題が解決されない場合、以下のError IDを添えてサーバー管理者に連絡してください。"
solution: "以下を行うと解決する可能性があります。"
solution1: "ブラウザおよびOSを最新バージョンに更新する"
solution2: "アドブロッカーを無効にする"
solution3: "ブラウザのキャッシュをクリアする"
solution4: "(Tor Browser) dom.webaudio.enabledをtrueに設定する"
otherOption: "その他のオプション"
otherOption1: "クライアント設定とキャッシュを削除"
otherOption2: "簡易クライアントを起動"
otherOption3: "修復ツールを起動"
_search:
searchScopeAll: "全て"
searchScopeLocal: "ローカル"
searchScopeServer: "サーバー指定"
searchScopeUser: "ユーザー指定"
pleaseEnterServerHost: "サーバーのホストを入力してください"
pleaseSelectUser: "ユーザーを選択してください"
serverHostPlaceholder: "例: misskey.example.com"

View file

@ -5,6 +5,7 @@ introMisskey: "ようお越しMisskeyは、オープンソースの分散型
poweredByMisskeyDescription: "{name}は、オープンソースのプラットフォーム<b>Misskey</b>のサーバーのひとつなんやで。"
monthAndDay: "{month}月 {day}日"
search: "探す"
reset: "リセット"
notifications: "通知"
username: "ユーザー名"
password: "パスワード"
@ -48,6 +49,7 @@ pin: "ピン留めしとく"
unpin: "ピン留めやめる"
copyContent: "内容をコピー"
copyLink: "リンクをコピー"
copyRemoteLink: "リモートのリンクをコピーするで?"
copyLinkRenote: "リノートのリンクをコピーするで?"
delete: "ほかす"
deleteAndEdit: "ほかして直す"
@ -287,7 +289,6 @@ deleteAreYouSure: "「{x}」はほかしてええか?"
resetAreYouSure: "リセットしてええん?"
areYouSure: "いいん?"
saved: "保存したで!"
messaging: "チャット"
upload: "アップロード"
keepOriginalUploading: "オリジナル画像のまんま"
keepOriginalUploadingDescription: "画像を上げるときにオリジナル版のまんまにするで。オフにしたら、上げたときにブラウザでWeb公開用の画像を生成するで。 "
@ -300,7 +301,6 @@ uploadFromUrlMayTakeTime: "アップロード終わるんにちょい時間か
explore: "みつける"
messageRead: "もう読んだ"
noMoreHistory: "これより昔のんはあらへんで"
startMessaging: "チャットやるで"
nUsersRead: "{n}人が読んでもうた"
agreeTo: "{0}に同意したで"
agree: "せやな"
@ -489,8 +489,6 @@ noteOf: "{user}はんのノート"
quoteAttached: "引用付いとるで"
quoteQuestion: "引用として添付してもええか?"
attachAsFileQuestion: "クリップボードのテキストが長すぎるからテキストファイルとして添付してもええか?"
noMessagesYet: "まだチャットはあらへんで"
newMessageExists: "新しいメッセージがきたで"
onlyOneFileCanBeAttached: "ごめんな、メッセージに添付できるファイルはひとつだけなんよ。"
signinRequired: "ログインしてくれへん?"
signinOrContinueOnRemote: "続行するには、お使いのサーバーに移動するか、このサーバーに登録・ログインする必要があるで"
@ -684,11 +682,15 @@ smtpSecure: "SMTP 接続に暗黙的なSSL/TLSを使用する"
smtpSecureInfo: "STARTTLS使っとる時はオフにしてや。"
testEmail: "配信テスト"
wordMute: "ワードミュート"
wordMuteDescription: "指定した語句が入ってるノートを最小化するで。最小化されたノートをクリックしたら、表示できるようになるで。"
hardWordMute: "ハードワードミュート"
showMutedWord: "ミュートされたワードを表示するで"
hardWordMuteDescription: "指定した語句が入ってるノートを隠すで。ワードミュートとちゃうて、ノートは完全に表示されんようになるで。"
regexpError: "正規表現エラー"
regexpErrorDescription: "{tab}ワードミュートの{line}行目の正規表現にエラーが出てきたで:"
instanceMute: "サーバーミュート"
userSaysSomething: "{name}が何か言うとるわ"
userSaysSomethingAbout: "{name}が「{word}」についてなんか言うてたで"
makeActive: "使うで"
display: "表示"
copy: "コピー"
@ -1301,6 +1303,20 @@ lockdown: "ロックダウン"
pleaseSelectAccount: "アカウント選んでや"
availableRoles: "使えるロール"
acknowledgeNotesAndEnable: "注意事項をわかった上でオンにする。"
federationSpecified: "このサーバーはホワイトリスト連合で運用されてるで。管理者が指定したサーバー以外とはやり取りできひんで。"
federationDisabled: "このサーバーは連合が無効化されてるで。他のサーバーのユーザーとやり取りすることはできひんで。"
confirmOnReact: "ツッコむときに確認とる"
reactAreYouSure: "\" {emoji} \" でツッコむ?"
postForm: "投稿フォーム"
information: "情報"
_chat:
invitations: "来てや"
noHistory: "履歴はないわ。"
members: "メンバーはん"
home: "ホーム"
send: "送信"
_settings:
webhook: "Webhook"
_accountSettings:
requireSigninToViewContents: "ログインしてもらってからコンテンツ見てもらう"
requireSigninToViewContentsDescription1: "あなたが作成した全部のノートとかのコンテンツを見れるようにするのにログインがいるようにするで。クローラーにいろいろ収集されるんを防げるかもしれん。"
@ -1991,7 +2007,6 @@ _theme:
header: "ヘッダー"
navBg: "サイドバーの背景"
navFg: "サイドバーの文字"
navHoverFg: "サイドバー文字(ホバー)"
navActive: "サイドバー文字(アクティブ)"
navIndicator: "サイドバーのインジケーター"
link: "リンク"
@ -2014,11 +2029,8 @@ _theme:
buttonHoverBg: "ボタンの背景 (ホバー)"
inputBorder: "入力ボックスの縁取り"
driveFolderBg: "ドライブフォルダーの背景"
wallpaperOverlay: "壁紙のオーバーレイ"
badge: "バッジ"
messageBg: "チャットの背景"
accentDarken: "アクセント (暗め)"
accentLighten: "アクセント (明るめ)"
fgHighlighted: "強調されとる文字"
_sfx:
note: "ノート"
@ -2171,6 +2183,7 @@ _permissions:
"read:clip-favorite": "クリップのいいね見る"
"read:federation": "連合の情報取得"
"write:report-abuse": "違反報告"
"write:chat": "チャットを操作するで"
_auth:
shareAccessTitle: "アプリへのアクセス許してやったらどうや"
shareAccess: "「{name}」がアカウントにアクセスすることを許可してええか?"
@ -2432,6 +2445,8 @@ _notification:
flushNotification: "通知の履歴をリセットする"
exportOfXCompleted: "{x}のエクスポートが終わったわ"
login: "ログインしとったで"
createToken: "アクセストークンが作成されたで"
createTokenDescription: "心当たりないんやったら「{text}」でアクセストークンを削除してやって。"
_types:
all: "すべて"
note: "あんたらの新規投稿"
@ -2595,10 +2610,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "配ってるとこが信頼できるか確認した上でインストールしてな。"
_plugin:
title: "このプラグイン、インストールする?"
metaTitle: "プラグイン情報"
_theme:
title: "このテーマインストールする?"
metaTitle: "テーマ情報"
_meta:
base: ""
_vendorInfo:
@ -2718,6 +2731,66 @@ _contextMenu:
app: "アプリ"
appWithShift: "Shiftキーでアプリ"
native: "ブラウザのUI"
_gridComponent:
_error:
requiredValue: "この値は必須項目やで"
columnTypeNotSupport: "正規表現によるバリデーションはtype:textのカラムだけサポートしてるで"
patternNotMatch: "この値は{pattern}のパターンに一致しいひんで"
notUnique: "この値は一意でなあかんで"
_roleSelectDialog:
notSelected: "選択されとらんで"
_customEmojisManager:
_gridCommon:
copySelectionRows: "選択行をコピーするで"
copySelectionRanges: "選択範囲をコピーするで"
deleteSelectionRows: "選択行を削除するで"
deleteSelectionRanges: "選択範囲の値をクリアするで"
searchSettings: "検索設定"
searchSettingCaption: "検索条件を詳しく設定するで。"
searchLimit: "表示件数"
sortOrder: "並び順"
registrationLogs: "登録ログ"
registrationLogsCaption: "絵文字更新・削除時のログが表示されるで。更新・削除操作をしたり、ページを遷移・リロードしたら消えるから気ぃつけてな。"
alertEmojisRegisterFailedDescription: "絵文字の更新・削除に失敗したで。詳細は登録ログを確認してな。"
_logs:
showSuccessLogSwitch: "成功ログを表示するで"
failureLogNothing: "失敗ログはあらへん。"
logNothing: "失敗ログはあらへん。"
_remote:
selectionRowDetail: "選択行の詳細やで"
importSelectionRows: "選択行をインポートするで"
importSelectionRangesRows: "選択範囲の行をインポートするで"
importEmojisButton: "チェックされた絵文字をインポートするで"
confirmImportEmojisTitle: "絵文字のインポートするで"
confirmImportEmojisDescription: "リモートから受信した{count}個の絵文字をインポートするで。絵文字のライセンスには十分気ぃつけてな。実行してもええか?"
_local:
tabTitleList: "登録済み絵文字一覧"
tabTitleRegister: "絵文字の登録"
_list:
emojisNothing: "登録された絵文字はないで。"
markAsDeleteTargetRows: "選択行を削除対象にするで"
markAsDeleteTargetRanges: "選択範囲の行を削除対象にするで"
alertUpdateEmojisNothingDescription: "変更された絵文字はないで。"
alertDeleteEmojisNothingDescription: "削除対象の絵文字はないで。"
confirmMovePage: "ページを移動してもええんか?"
confirmChangeView: "表示を変更してもええんか?"
confirmUpdateEmojisDescription: "{count}個の絵文字を更新するで。実行してもええか?"
confirmDeleteEmojisDescription: "チェックがつけられた{count}個の絵文字を削除するで。ほんまにええか?"
confirmResetDescription: "今までやった変更が全部リセットされるで。"
confirmMovePageDesciption: "このページの絵文字に変更が加えられてるで。\n保存せずページを移動してまうと、このページで加えた変更が全てパーになるで。"
dialogSelectRoleTitle: "絵文字に設定されたロールで検索"
_register:
uploadSettingTitle: "アップロード設定"
uploadSettingDescription: "この画面で絵文字アップロードするときの動きを設定できるで。"
directoryToCategoryLabel: "ディレクトリ名を\"category\"に入力する"
directoryToCategoryCaption: "ディレクトリをドラッグ・ドロップした時に、ディレクトリ名を\"category\"に入力します。"
emojiInputAreaCaption: "どれかの方法で登録する絵文字を選択して。"
emojiInputAreaList1: "この枠に画像ファイルかディレクトリをドラッグ&ドロップ"
emojiInputAreaList2: "このリンクをクリックしてPCから選択する"
emojiInputAreaList3: "このリンクをクリックしてドライブから選択する"
confirmRegisterEmojisDescription: "リストに表示されてる絵文字を新たなカスタム絵文字として登録するで。ほんまにええか? (サーバーがしんどくなるから、一回で登録できる絵文字は{count}件までやで)"
confirmClearEmojisDescription: "編集内容をほかして、リストに表示されている絵文字をクリアするで。ほんまにええか?"
confirmUploadEmojisDescription: "ドラッグ&ドロップされた{count}個のファイルをドライブにアップロードするで。ほんまにええか?"
_embedCodeGen:
title: "埋め込みコードをカスタム"
header: "ヘッダー出す"
@ -2754,8 +2827,35 @@ _remoteLookupErrors:
_responseInvalid:
title: "レスポンスがおかしいで"
description: "このサーバーと通信することはできたけど、もらったデータがおかしかったで。"
_responseInvalidIdHostNotMatch:
description: "入力されたURIのドメインと最終的に得られたURIのドメインとが違うで。第三者のサーバーを介してリモートのコンテンツを照会してるんやったら、発信元のサーバーで取得できるURIを使って照会し直して。"
_noSuchObject:
title: "見つからへんね"
description: "求められたリソースが見つからんかったで。URIをもっかい確かめてや。"
_captcha:
verify: "CAPTCHAしばいたって"
testSiteKeyMessage: "サイトキーとシークレットキーにテスト用の値を入力することでプレビューを確認できるで。\n詳細は下記ページを確認してな。"
_error:
_requestFailed:
title: "CAPTCHAのリクエストに失敗してもうた"
text: "しばらく後で実行するか、設定をもっかい確認してや。"
_verificationFailed:
title: "CAPTCHAのリクエストに失敗してもうた"
text: "設定がほんまに合ってるかもっかい確認してや。"
_unknown:
title: "CAPTCHAエラー"
text: "思いもせんかったエラーが起きたわ。"
_bootErrors:
title: "読み込みに失敗したで"
serverError: "少し待ってからリロードしてもまだ問題が解決されんのやったら、以下のError IDを添えてサーバー管理者に連絡して。"
solution: "以下のことやったら解決するかもやで。"
solution1: "ブラウザとかOSを最新バージョンに更新する"
solution2: "アドブロッカーを無効にする"
solution3: "ブラウザのキャッシュをクリアする"
solution4: "(Tor Browser) dom.webaudio.enabledをtrueに設定する"
otherOption: "ほかのオプション"
otherOption1: "クライアント設定とキャッシュをほかす"
otherOption2: "簡易クライアントを起動"
otherOption3: "修復ツールを起動"
_search:
searchScopeAll: "みんな"
searchScopeLocal: "ローカル"
searchScopeUser: "ユーザー指定"

View file

@ -263,7 +263,6 @@ deleteAreYouSure: "{x}(얼)럴 뭉캡니꺼?"
resetAreYouSure: "아시로 데돌립니꺼?"
areYouSure: "갠찮십니꺼?"
saved: "저장햇십니다"
messaging: "대화"
upload: "올리기"
keepOriginalUploading: "온본 두기"
keepOriginalUploadingDescription: "이미지럴 올릴 때 온본얼 고대로 둡니다. 꺼모 올릴 때 브라우저서 웹 공개 이미지럴 맨겁니다."
@ -276,7 +275,6 @@ uploadFromUrlMayTakeTime: "올리기가 껕날라먼 시간이 쪼매 걸릴 깁
explore: "살펴보기"
messageRead: "이럿어예"
noMoreHistory: "요카마 옛날 기록이 어ᇝ십니다"
startMessaging: "대화하기"
nUsersRead: "{n}멩이 이럿십니다"
agreeTo: "{0}에 동이하기"
agree: "동이합니다"
@ -457,8 +455,6 @@ retype: "다시 서기"
noteOf: "{user}님으 노트"
quoteAttached: "따옴"
quoteQuestion: "따와가 작성하겠십니까?"
noMessagesYet: "아직 대화가 없십니다"
newMessageExists: "새 메시지가 있십니다"
onlyOneFileCanBeAttached: "메시지엔 파일 하나까제밖에 몬 넣십니다"
invitations: "초대하기"
invitationCode: "초대장"
@ -655,6 +651,12 @@ replies: "답하기"
renotes: "리노트"
attach: "옇기"
surrender: "아이예"
information: "정보"
_chat:
invitations: "초대하기"
noHistory: "기록이 없십니다"
members: "구성원"
home: "덜머리"
_delivery:
stop: "고만 보내예"
_type:
@ -745,6 +747,7 @@ _theme:
description: "설멩"
keys:
mention: "멘션"
renote: "리노트"
_sfx:
note: "새 노트"
notification: "알림"
@ -843,3 +846,6 @@ _reversi:
_remoteLookupErrors:
_noSuchObject:
title: "몬 찾앗십니다"
_search:
searchScopeAll: "말캉"
searchScopeUser: "사용자 지정"

View file

@ -289,7 +289,6 @@ deleteAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
resetAreYouSure: "초기화 하시겠습니까?"
areYouSure: "계속 진행하시겠습니까?"
saved: "저장했습니다"
messaging: "대화"
upload: "업로드"
keepOriginalUploading: "원본 이미지를 유지"
keepOriginalUploadingDescription: "이미지를 업로드할 때에 원본을 그대로 유지합니다. 비활성화하면 업로드할 때 브라우저에서 웹 공개용 이미지를 생성합니다."
@ -302,7 +301,6 @@ uploadFromUrlMayTakeTime: "업로드가 완료될 때까지 시간이 소요될
explore: "둘러보기"
messageRead: "읽음"
noMoreHistory: "이것보다 과거의 기록이 없습니다"
startMessaging: "대화 시작하기"
nUsersRead: "{n}명이 읽음"
agreeTo: "{0}에 동의"
agree: "동의합니다"
@ -491,8 +489,6 @@ noteOf: "{user}의 노트"
quoteAttached: "인용함"
quoteQuestion: "인용해서 작성하시겠습니까?"
attachAsFileQuestion: "붙여넣으려는 글이 너무 깁니다. 텍스트 파일로 첨부하시겠습니까?"
noMessagesYet: "아직 대화가 없습니다"
newMessageExists: "새 메시지가 있습니다"
onlyOneFileCanBeAttached: "메시지에 첨부할 수 있는 파일은 하나까지입니다"
signinRequired: "진행하기 전에 로그인을 해 주세요"
signinOrContinueOnRemote: "계속하려면 사용하는 서버로 이동하거나 이 서버에 로그인해야 합니다."
@ -698,6 +694,7 @@ userSaysSomethingAbout: "{name}님이 \"{word}\"를 언급했습니다."
makeActive: "활성화"
display: "보기"
copy: "복사"
copiedToClipboard: "클립보드에 복사되었습니다."
metrics: "통계"
overview: "요약"
logs: "로그"
@ -1294,7 +1291,7 @@ thereAreNChanges: "{n}건 변경이 있습니다."
signinWithPasskey: "패스키로 로그인"
unknownWebAuthnKey: "등록되지 않은 패스키입니다."
passkeyVerificationFailed: "패스키 검증을 실패했습니다."
passkeyVerificationSucceededButPasswordlessLoginDisabled: "패스키를 검증했으나, 비밀번호 없이 로그인하기가 꺼져 있습니다."
passkeyVerificationSucceededButPasswordlessLoginDisabled: "입력된 패스키는 정상적이나, 비밀번호 없이 로그인 하는 기능이 비활성화 되어있습니다."
messageToFollower: "팔로워에게 보낼 메시지"
target: "대상"
testCaptchaWarning: "CAPTCHA를 테스트하기 위한 기능입니다. <strong>실제 환경에서는 사용하지 마세요.</strong>"
@ -1309,6 +1306,75 @@ availableRoles: "사용 가능한 역할"
acknowledgeNotesAndEnable: "활성화 하기 전에 주의 사항을 확인했습니다."
federationSpecified: "이 서버는 화이트 리스트 제도로 운영 중 입니다. 정해진 리모트 서버가 아닌 경우 연합되지 않습니다."
federationDisabled: "이 서버는 연합을 하지 않고 있습니다. 리모트 서버 유저와 통신을 할 수 없습니다."
confirmOnReact: "리액션할 때 확인"
reactAreYouSure: "\" {emoji} \"로 리액션하시겠습니까?"
markAsSensitiveConfirm: "이 미디어를 민감한 미디어로 설정하시겠습니까?"
unmarkAsSensitiveConfirm: "이 미디어의 민감한 미디어 지정을 해제하시겠습니까?"
preferences: "환경설정"
accessibility: "접근성"
preferencesProfile: "설정 프로필"
copyPreferenceId: "설정한 ID를 복사"
resetToDefaultValue: "기본값으로 되돌리기"
overrideByAccount: "계정으로 덮어쓰기"
untitled: "제목 없음"
noName: "이름이 없습니다."
skip: "건너뛰기"
restore: "복원"
syncBetweenDevices: "장치간 동기화"
preferenceSyncConflictTitle: "서버에 설정값이 존재합니다."
preferenceSyncConflictText: "동기화를 활성화 한 항목의 설정 값은 서버에 저장되지만, 해당 항목은 이미 서버에 설정 값이 저장되어져 있습니다. 어느 쪽의 설정 값을 덮어씌울까요?"
preferenceSyncConflictChoiceServer: "서버 설정값"
preferenceSyncConflictChoiceDevice: "장치 설정값"
preferenceSyncConflictChoiceCancel: "동기화 취소"
paste: "붙여넣기"
emojiPalette: "이모지 팔레트"
postForm: "글 입력란"
textCount: "문자 수"
information: "정보"
_chat:
invitations: "초대"
noHistory: "기록이 없습니다"
members: "멤버"
home: "홈"
send: "전송"
_emojiPalette:
palettes: "팔레트"
enableSyncBetweenDevicesForPalettes: "팔레트의 디바이스 간 동기화를 활성화"
paletteForMain: "메인으로 사용할 팔레트"
paletteForReaction: "리액션으로 사용할 팔레트"
_settings:
driveBanner: "드라이브 관리, 사용량 확인, 파일 업로드에 관한 설정을 합니다."
pluginBanner: "플러그인을 사용하면 클라이언트 기능을 확장할 수 있습니다. 플러그인 설치와 개별적인 설정을 합니다."
notificationsBanner: "서버에서 받는 알림의 종류 및 범위, 푸시 알림 설정을 합니다."
api: "API"
webhook: "Webhook"
serviceConnection: "서비스 연동"
serviceConnectionBanner: "외부 앱, 서비스와 연결하기 위한 액세스 토큰과 웹 훅 관리 설정을 합니다."
accountData: "계정 데이터"
accountDataBanner: "계정 데이터의 아카이브를 추출하기/가져오기 하여 관리할 수 있습니다."
muteAndBlockBanner: "숨길 컨텐츠의 설정과, 특정 유저의 리액션을 제한하는 설정을 관리합니다."
accessibilityBanner: "좀 더 쾌적하게 사용할 수 있도록 클라이언트의 시각 및 움직임에 관한 개인화 설정을 합니다."
privacyBanner: "컨텐츠, 계정의 발견 범위, 팔로우 승인제 등의 계정의 프라이버시에 관한 설정을 합니다."
securityBanner: "비밀번호, 로그인 방법, OTP, 패스 키 등의 계정의 보안에 관련된 설정을 합니다."
preferencesBanner: "취향에 알맞는 클라이언트의 전체적인 동작을 설정합니다."
appearanceBanner: "취향에 알맞는 클라이언트의 디스플레이, 표시 방법에 관한 설정을 합니다."
soundsBanner: "클라이언트에서 재생할 소리에 대한 설정을 합니다."
timelineAndNote: "타임라인과 노트"
makeEveryTextElementsSelectable: "모든 텍스트 요소를 선택할 수 있도록 함"
makeEveryTextElementsSelectable_description: "활성화 시, 일부 동작에서 사용자의 접근성이 나빠질 수도 있습니다."
_preferencesProfile:
profileName: "프로필 이름"
profileNameDescription: "이 디바이스를 식별할 이름을 설정해 주세요."
profileNameDescription2: "예: '메인PC', '스마트폰' 등"
_preferencesBackup:
autoBackup: "자동 백업"
restoreFromBackup: "백업으로 복구"
noBackupsFoundTitle: "백업을 찾을 수 없습니다"
noBackupsFoundDescription: "자동으로 생성된 백업은 찾을 수 없었지만, 수동으로 백업 파일을 저장한 경우 해당 파일을 가져와 복원할 수 있습니다."
selectBackupToRestore: "복원할 백업을 선택하세요"
youNeedToNameYourProfileToEnableAutoBackup: "자동 백업을 활성화하려면 프로필 이름을 설정해야 합니다."
autoPreferencesBackupIsNotEnabledForThisDevice: "이 장치에서 설정 자동 백업이 활성화되어 있지 않습니다."
backupFound: "설정 백업이 발견되었습니다"
_accountSettings:
requireSigninToViewContents: "콘텐츠 열람을 위해 로그인을 필수로 설정하기"
requireSigninToViewContentsDescription1: "자신이 작성한 모든 노트 등의 콘텐츠를 보기 위해 로그인을 필수로 설정합니다. 크롤러가 정보 수집하는 것을 방지하는 효과를 기대할 수 있습니다."
@ -1319,6 +1385,7 @@ _accountSettings:
makeNotesHiddenBefore: "과거 노트 비공개로 전환하기"
makeNotesHiddenBeforeDescription: "이 기능이 활성화되어 있는 동안 설정한 날짜 및 시간보다 과거 또는 설정한 시간이 지난 노트는 본인만 볼 수 있게(비공개로 전환) 됩니다. 비활성화하면 노트의 공개 상태도 원래대로 돌아갑니다."
mayNotEffectForFederatedNotes: "원격 서버에 연합된 노트에는 효과가 없을 수도 있습니다."
mayNotEffectSomeSituations: "여기서 설정하는 제한은 모더레이션이나 리모트 서버에서 볼 때 등 일부 환경에서는 적용되지 않을 수도 있습니다."
notesHavePassedSpecifiedPeriod: "지정한 시간이 경과된 노트"
notesOlderThanSpecifiedDateAndTime: "지정된 날짜 및 시간 이전의 노트"
_abuseUserReport:
@ -1967,6 +2034,7 @@ _theme:
installed: "{name} 테마가 설치되었습니다"
installedThemes: "설치된 테마"
builtinThemes: "표준 테마"
instanceTheme: "서버 테마"
alreadyInstalled: "이미 설치된 테마입니다"
invalid: "테마 형식이 올바르지 않습니다"
make: "테마 만들기"
@ -1999,7 +2067,6 @@ _theme:
header: "헤더"
navBg: "사이드바 배경"
navFg: "사이드바 텍스트"
navHoverFg: "사이드바 텍스트 (호버)"
navActive: "사이드바 텍스트 (활성)"
navIndicator: "사이드바 인디케이터"
link: "링크"
@ -2022,11 +2089,8 @@ _theme:
buttonHoverBg: "버튼 배경 (호버)"
inputBorder: "입력 필드 테두리"
driveFolderBg: "드라이브 폴더 배경"
wallpaperOverlay: "배경화면 오버레이"
badge: "배지"
messageBg: "대화 배경"
accentDarken: "강조 색상 (어두움)"
accentLighten: "강조 색상 (밝음)"
fgHighlighted: "강조된 텍스트"
_sfx:
note: "새 노트"
@ -2179,6 +2243,7 @@ _permissions:
"read:clip-favorite": "클립의 좋아요 보기"
"read:federation": "연합 정보 불러오기"
"write:report-abuse": "위반 내용 신고하기"
"write:chat": "대화를 시작하거나 메시지를 보냅니다"
_auth:
shareAccessTitle: "어플리케이션의 접근 허가"
shareAccess: "{name}’에서 계정에 접근하는 것을 허용하시겠습니까?"
@ -2440,6 +2505,8 @@ _notification:
flushNotification: "알림 이력을 초기화"
exportOfXCompleted: "{x} 추출에 성공했습니다."
login: "로그인 알림이 있습니다"
createToken: "액세스 토큰이 생성되었습니다"
createTokenDescription: "만약 기억이 나지 않는다면 '{text}'를 통해 액세스 토큰을 삭제해 주세요."
_types:
all: "전부"
note: "사용자의 새 글"
@ -2456,6 +2523,7 @@ _notification:
achievementEarned: "도전 과제 획득"
exportCompleted: "추출을 성공함"
login: "로그인"
createToken: "액세스 토큰 만들기"
test: "알림 테스트"
app: "연동된 앱을 통한 알림"
_actions:
@ -2483,6 +2551,7 @@ _deck:
useSimpleUiForNonRootPages: "루트 이외의 페이지로 접속한 경우 UI 간략화하기"
usedAsMinWidthWhenFlexible: "'폭 자동 조정'이 활성화된 경우 최소 폭으로 사용됩니다"
flexible: "폭 자동 조정"
enableSyncBetweenDevicesForProfiles: "프로파일 정보의 디바이스 간 동기화를 활성화"
_columns:
main: "메인"
widgets: "위젯"
@ -2590,6 +2659,7 @@ _moderationLogTypes:
deletePage: "페이지를 삭제"
deleteFlash: "Play를 삭제"
deleteGalleryPost: "갤러리 포스트를 삭제"
updateProxyAccountDescription: "프록시 계정의 설명 업데이트"
_fileViewer:
title: "파일 상세"
type: "파일 유형"
@ -2603,10 +2673,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "제공자를 신뢰할 수 있는 경우에만 설치하십시오."
_plugin:
title: "이 플러그인을 설치하시겠습니까?"
metaTitle: "플러그인 정보"
_theme:
title: "이 테마를 설치하시겠습니까?"
metaTitle: "테마 정보"
_meta:
base: "기본 컬러 스키마"
_vendorInfo:
@ -2822,8 +2890,6 @@ _remoteLookupErrors:
_responseInvalid:
title: "유효하지 않은 반응입니다."
description: "이 서버와 통신할 수 있지만, 데이터가 올바르지 않습니다."
_responseInvalidIdHostNotMatch:
description: "입력된 URI과 실제 URI가 다릅니다. 제 3자 서버를 통한 리모트 컨텐츠를 조회하는 경우, 원래 서버 측에서 받아올 수 있는 URI를 사용하여 조회하시길 바랍니다."
_noSuchObject:
title: "찾을 수 없습니다"
description: "요구된 리소스를 찾을 수 없습니다. URI를 다시 한 번 확인해보세요."
@ -2840,3 +2906,23 @@ _captcha:
_unknown:
title: "CAPTCHA 에러"
text: "알 수 없는 에러가 발생했습니다."
_bootErrors:
title: "로딩이 실패함"
serverError: "잠시 기다렸다가 다시 로드해도 여전히 문제가 해결되지 않으면 아래 Error ID와 함께 서버 관리자에게 연락해 주세요."
solution: "다음과 같은 방법으로 해결할 수 있습니다."
solution1: "브라우저 및 OS를 최신 버전으로 업데이트하기"
solution2: "광고 차단 비활성화하기"
solution3: "브라우저 캐시 지우기"
solution4: "(Tor Browser) dom.webaudio.enabled를 true로 설정하세요"
otherOption: "기타 옵션"
otherOption1: "클라이언트 설정 및 캐시 삭제"
otherOption2: "간편 클라이언트 실행"
otherOption3: "복구 툴 실행"
_search:
searchScopeAll: "전체"
searchScopeLocal: "로컬"
searchScopeServer: "서버 지정"
searchScopeUser: "사용자 지정"
pleaseEnterServerHost: "서버의 호스트를 입력해 주세요."
pleaseSelectUser: "유저를 선택해주세요"
serverHostPlaceholder: "예: misskey.example.com"

View file

@ -223,7 +223,6 @@ remove: "ລຶບ"
removed: "ລຶບແລ້ວ"
resetAreYouSure: "ຣີ​ເຊັດບໍ?"
saved: "ບັນທຶກແລ້ວ"
messaging: "ແຊັຕ"
upload: "ອັບໂຫຼດ"
keepOriginalUploading: "ຮັກສາຮູບພາບຕົ້ນສະບັບ"
fromDrive: "ຈາກ Drive"
@ -233,7 +232,6 @@ uploadFromUrlDescription: "URL ຂອງໄຟລ໌ທີ່ທ່ານຕ້
uploadFromUrlRequested: "ຮ້ອງຂໍການອັບໂຫລດແລ້ວ"
explore: "ສຳຫຼວດ"
messageRead: "ອ່ານແລ້ວ"
startMessaging: "ເລີ່ມການສົນທະນາໃໝ່"
nUsersRead: "ອ່ານໂດຍ {n}"
agree: "ຍອມຮັບ"
termsOfService: "ເງື່ອນໄຂການບໍລິການ"
@ -394,6 +392,12 @@ searchByGoogle: "ຄົ້ນຫາ"
file: "ໄຟລ໌"
replies: "ຕອບ​ກັບ"
renotes: "Renote"
information: "ກ່ຽວກັບ"
_chat:
invitations: "ເຊີນ"
noHistory: "​ບໍ່​ມີປະຫວັດ"
members: "ສະມາຊິກ"
home: "ໜ້າຫຼັກ"
_delivery:
stop: "ໂຈະ"
_type:
@ -477,3 +481,5 @@ _moderationLogTypes:
_remoteLookupErrors:
_noSuchObject:
title: "ບໍ່ພົບ"
_search:
searchScopeAll: "ທັງໝົດ"

View file

@ -256,7 +256,6 @@ removeAreYouSure: "Weet je zeker dat je \"{x}\" wil verwijderen?"
deleteAreYouSure: "Weet je zeker dat je \"{x}\" wil verwijderen?"
resetAreYouSure: "Resetten?"
saved: "Opgeslagen"
messaging: "Chat"
upload: "Uploaden"
keepOriginalUploading: "Origineel beeld behouden."
keepOriginalUploadingDescription: "Bewaar de originele versie bij het uploaden van afbeeldingen. Indien uitgeschakeld, wordt bij het uploaden een alternatieve versie voor webpublicatie genereert."
@ -269,7 +268,6 @@ uploadFromUrlMayTakeTime: "Het kan even duren voordat het uploaden voltooid is."
explore: "Verkennen"
messageRead: "Lezen"
noMoreHistory: "Er is geen verdere geschiedenis"
startMessaging: "Start een gesprek"
nUsersRead: "gelezen door {n}"
agreeTo: "Ik stem in met {0}"
start: "Aan de slag"
@ -462,6 +460,11 @@ loggedInAsBot: "Momenteel als bot ingelogd"
icon: "Avatar"
replies: "Antwoord"
renotes: "Herdelen"
information: "Over"
_chat:
invitations: "Uitnodigen"
members: "Leden"
home: "Startpagina"
_delivery:
stop: "Opgeschort"
_type:
@ -540,3 +543,5 @@ _reversi:
_remoteLookupErrors:
_noSuchObject:
title: "Niet gevonden"
_search:
searchScopeAll: "Alle"

View file

@ -299,8 +299,6 @@ text: "Tekst"
next: "Neste"
retype: "Gjenta"
quoteAttached: "Sitat"
noMessagesYet: "Ingen meldinger ennå"
newMessageExists: "Det er nye meldinger"
onlyOneFileCanBeAttached: "Du kan bare legge ved én fil i en melding"
invitations: "Inviter"
available: "Tilgjengelig"
@ -463,6 +461,12 @@ icon: "Avatar"
replies: "Svar"
renotes: "Renote"
surrender: "Avbryt"
information: "Informasjon"
_chat:
invitations: "Inviter"
members: "Medlemmer"
home: "Hjem"
send: "Send"
_delivery:
stop: "Suspendert"
_initialAccountSetting:
@ -730,3 +734,5 @@ _moderationLogTypes:
_remoteLookupErrors:
_noSuchObject:
title: "Ikke funnet"
_search:
searchScopeAll: "Alle"

View file

@ -269,7 +269,6 @@ deleteAreYouSure: "Czy na pewno chcesz usunąć „{x}”?"
resetAreYouSure: "Czy na pewno chcesz zresetować?"
areYouSure: "Na pewno?"
saved: "Zapisano"
messaging: "Wiadomości"
upload: "Wyślij"
keepOriginalUploading: "Zachowaj oryginalny obraz"
keepOriginalUploadingDescription: "Zapisuje oryginalnie przesłany obraz w niezmienionej postaci. Jeśli ta opcja jest wyłączona, po przesłaniu zostanie wygenerowana wersja do wyświetlenia w Internecie."
@ -282,7 +281,6 @@ uploadFromUrlMayTakeTime: "Wysyłanie może chwilę potrwać."
explore: "Eksploruj"
messageRead: "Przeczytano"
noMoreHistory: "Nie ma dalszej historii"
startMessaging: "Rozpocznij czat"
nUsersRead: "przeczytano przez {n}"
agreeTo: "Wyrażam zgodę na {0}"
agree: "Zatwierdź"
@ -466,8 +464,6 @@ retype: "Wprowadź ponownie"
noteOf: "Wpisy {user}"
quoteAttached: "Zacytowano"
quoteQuestion: "Czy na pewno chcesz umieścić cytat?"
noMessagesYet: "Nie napisano jeszcze wiadomości"
newMessageExists: "Masz nową wiadomość"
onlyOneFileCanBeAttached: "Możesz załączyć tylko jeden plik do wiadomości"
signinRequired: "Proszę się zalogować"
invitations: "Zaproś"
@ -1044,6 +1040,14 @@ flip: "Odwróć"
lastNDays: "W ciągu ostatnich {n} dni"
surrender: "Odrzuć"
gameRetry: "Spróbuj ponownie"
postForm: "Formularz tworzenia wpisu"
information: "Informacje"
_chat:
invitations: "Zaproś"
noHistory: "Brak historii"
members: "Członkowie"
home: "Strona główna"
send: "Wyślij"
_delivery:
stop: "Zawieszono"
_type:
@ -1208,7 +1212,6 @@ _theme:
header: "Nagłówek"
navBg: "Tło paska bocznego"
navFg: "Tekst paska bocznego"
navHoverFg: "Tekst paska bocznego (zbliżenie)"
navActive: "Tekst paska bocznego (aktywny)"
navIndicator: "Wskaźnik paska bocznego"
link: "Odnośnik"
@ -1231,11 +1234,8 @@ _theme:
buttonHoverBg: "Tło przycisku (po najechaniu)"
inputBorder: "Obramowanie pola wejścia"
driveFolderBg: "Tło folderu na dysku"
wallpaperOverlay: "Nakładka tapety"
badge: "Odznaka"
messageBg: "Tło czatu"
accentDarken: "Akcent (ciemniejszy)"
accentLighten: "Akcent (jaśniejszy)"
fgHighlighted: "Wyróżniony tekst"
_sfx:
note: "Wpisy"
@ -1300,6 +1300,7 @@ _permissions:
"write:gallery": "Edytuj swoją galerię"
"read:gallery-likes": "Wyświetlanie listy polubionych postów w galerii"
"write:gallery-likes": "Edytowanie listy polubionych postów w galerii"
"write:chat": "Tworzenie lub usuwanie wiadomości czatu"
_auth:
shareAccessTitle: "Przyznawanie uprawnień aplikacji"
shareAccess: "Czy chcesz autoryzować „{name}” do dostępu do tego konta?"
@ -1583,3 +1584,6 @@ _reversi:
_remoteLookupErrors:
_noSuchObject:
title: "Nie znaleziono"
_search:
searchScopeAll: "Wszystkie"
searchScopeLocal: "Lokalne"

View file

@ -287,7 +287,6 @@ deleteAreYouSure: "Deseja excluir \"{x}\"?"
resetAreYouSure: "Deseja reiniciar?"
areYouSure: "Tem certeza?"
saved: "Salvo"
messaging: "Chat"
upload: "Fazer upload"
keepOriginalUploading: "Manter a imagem original"
keepOriginalUploadingDescription: "Ao fazer o upload de uma imagem, ela será mantida em sua versão original. Caso desative esta opção, o navegador irá gerar uma versão da imagem otimizada para publicação na web durante o upload."
@ -300,7 +299,6 @@ uploadFromUrlMayTakeTime: "Pode levar algum tempo para que o upload seja conclu
explore: "Explorar"
messageRead: "Lida"
noMoreHistory: "Não existe histórico anterior"
startMessaging: "Iniciar conversação"
nUsersRead: "{n} pessoas leram"
agreeTo: "Eu concordo com {0}"
agree: "Concordar"
@ -489,8 +487,6 @@ noteOf: "Publicação de {user}"
quoteAttached: "Com citação"
quoteQuestion: "Anexar como citação?"
attachAsFileQuestion: "O texto na área de transferência é muito longo. Você gostaria de anexá-lo como um arquivo de texto?"
noMessagesYet: "Sem conversas até o momento"
newMessageExists: "Há uma nova mensagem"
onlyOneFileCanBeAttached: "Apenas um arquivo pode ser anexado a uma mensagem"
signinRequired: "É necessário se inscrever ou fazer login antes de continuar"
signinOrContinueOnRemote: "Para continuar, você precisa mover o seu servidor ou entrar/cadastrar-se nesse servidor."
@ -1301,6 +1297,16 @@ lockdown: "Lockdown"
pleaseSelectAccount: "Selecione uma conta"
availableRoles: "Cargos disponíveis"
acknowledgeNotesAndEnable: "Ative após compreender as precauções."
postForm: "Campo de postagem"
information: "Informações"
_chat:
invitations: "Convidar"
noHistory: "Ainda não há histórico"
members: "Membros"
home: "Início"
send: "Enviar"
_settings:
webhook: "Webhook"
_accountSettings:
requireSigninToViewContents: "Exigir cadastro para ver o conteúdo"
requireSigninToViewContentsDescription1: "Exigir cadastro para ver todas as notas e outro conteúdo que você criou. Isso previne 'crawlers' de coletar os seus dados."
@ -1991,7 +1997,6 @@ _theme:
header: "Cabeçalho"
navBg: "Plano de fundo da barra lateral"
navFg: "Texto da barra lateral"
navHoverFg: "Texto da coluna lateral (Selecionado)"
navActive: "Texto da coluna lateral (Ativa)"
navIndicator: "Indicador da coluna lateral"
link: "Link"
@ -2014,11 +2019,8 @@ _theme:
buttonHoverBg: "Plano de fundo de botão (Selecionado)"
inputBorder: "Borda de campo digitável"
driveFolderBg: "Plano de fundo da pasta no Drive"
wallpaperOverlay: "Sobreposição do papel de parede."
badge: "Emblema"
messageBg: "Plano de fundo do chat"
accentDarken: "Cor de destaque (Escurecida)"
accentLighten: "Cor de destaque (Esclarecida)"
fgHighlighted: "Texto Destacado"
_sfx:
note: "Posts"
@ -2171,6 +2173,7 @@ _permissions:
"read:clip-favorite": "Ver Clipes favoritados"
"read:federation": "Ver dados de federação"
"write:report-abuse": "Reportar violação"
"write:chat": "Compor ou editar mensagens de chat"
_auth:
shareAccessTitle: "Conceder permissões do aplicativo"
shareAccess: "Você gostaria de autorizar \"{name}\" para acessar essa conta?"
@ -2595,10 +2598,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "Tenha certeza de que o distribuidor desse recurso é confiável antes da instalação."
_plugin:
title: "Deseja instalar esse plugin?"
metaTitle: "Informações do plugin"
_theme:
title: "Deseja instalar esse tema?"
metaTitle: "Informações do tema"
_meta:
base: "Paleta de cores base"
_vendorInfo:
@ -2754,8 +2755,10 @@ _remoteLookupErrors:
_responseInvalid:
title: "Resposta inválida"
description: "Foi possível comunicar com o servidor, porém os dados obtidos foram incorretos."
_responseInvalidIdHostNotMatch:
description: "O domínio do endereço inserido difere do domínio do endereço final. Se você estiver pesquisando por um servidor de terceiros, tente buscar novamente com um endereço que pode ser obtido através do servidor original."
_noSuchObject:
title: "Não encontrado"
description: "O recurso solicitado não foi encontrado, confira o endereço."
_search:
searchScopeAll: "Todos"
searchScopeLocal: "Local"
searchScopeUser: "Usuário específico"

View file

@ -254,7 +254,6 @@ removeAreYouSure: "Ești sigur că vrei să înlături {x}?"
deleteAreYouSure: "Ești sigur că vrei să ștergi {x}?"
resetAreYouSure: "Sigur vrei să resetezi?"
saved: "Salvat"
messaging: "Chat"
upload: "Încarcă"
keepOriginalUploading: "Păstrează imaginea originală"
keepOriginalUploadingDescription: "Salvează imaginea originala încărcată fără modificări. Dacă e oprită, o versiune pentru afișarea pe web va fi generată la încărcare."
@ -267,7 +266,6 @@ uploadFromUrlMayTakeTime: "S-ar putea să ia puțin până se finalizează înc
explore: "Explorează"
messageRead: "Citit"
noMoreHistory: "Nu există mai mult istoric"
startMessaging: "Începe un chat nou"
nUsersRead: "citit de {n}"
agreeTo: "Sunt de acord cu {0}"
start: "Să începem"
@ -429,8 +427,6 @@ retype: "Introdu din nou"
noteOf: "Notă de {user}"
quoteAttached: "Citat"
quoteQuestion: "Vrei să adaugi ca citat?"
noMessagesYet: "Niciun mesaj încă"
newMessageExists: "Ai mesaje noi"
onlyOneFileCanBeAttached: "Poți atașa un singur fișier la un mesaj"
signinRequired: "Te rog autentifică-te"
invitations: "Invită"
@ -646,6 +642,13 @@ show: "Arată"
icon: "Avatar"
replies: "Răspunde"
renotes: "Re-notează"
information: "Despre"
_chat:
invitations: "Invită"
noHistory: "Nu există istoric"
members: "Membri"
home: "Acasă"
send: "Trimite"
_delivery:
stop: "Suspendat"
_type:
@ -736,3 +739,5 @@ _reversi:
_remoteLookupErrors:
_noSuchObject:
title: "Nu a fost găsit"
_search:
searchScopeAll: "Tot"

View file

@ -282,7 +282,6 @@ deleteAreYouSure: "Хотите удалить «{x}»?"
resetAreYouSure: "На самом деле сбросить?"
areYouSure: "Вы уверены?"
saved: "Сохранено"
messaging: "Сообщения"
upload: "Загрузить"
keepOriginalUploading: "Сохранить исходное изображение"
keepOriginalUploadingDescription: "Сохраняет исходную версию при загрузке изображений. Если выключить, то при загрузке браузер генерирует изображение для публикации."
@ -295,7 +294,6 @@ uploadFromUrlMayTakeTime: "Загрузка может занять некото
explore: "Обзор"
messageRead: "Прочитали"
noMoreHistory: "История закончилась"
startMessaging: "Начать общение"
nUsersRead: "Прочитали {n}"
agreeTo: "Я соглашаюсь с {0}"
agree: "Согласен"
@ -482,8 +480,6 @@ noteOf: "Что пишет {user}"
quoteAttached: "Цитата"
quoteQuestion: "Хотите добавить цитату?"
attachAsFileQuestion: "Текста в буфере обмена слишком много. Прикрепить как текстовый файл?"
noMessagesYet: "Пока ни одного сообщения"
newMessageExists: "Новое сообщение"
onlyOneFileCanBeAttached: "К сообщению можно прикрепить только один файл"
signinRequired: "Пожалуйста, войдите"
signinOrContinueOnRemote: "Чтобы продолжить, вам необходимо войти в аккаунт на своём сервере или зарегистрироваться / войти в аккаунт на этом."
@ -1181,6 +1177,16 @@ keepOriginalFilenameDescription: "Если вы выключите данную
alwaysConfirmFollow: "Всегда подтверждать подписку"
inquiry: "Связаться"
messageToFollower: "Сообщение подписчикам"
postForm: "Форма отправки"
information: "Описание"
_chat:
invitations: "Пригласить"
noHistory: "История пока пуста"
members: "Участники"
home: "Главная"
send: "Отправить"
_settings:
webhook: "Вебхук"
_delivery:
stop: "Заморожено"
_type:
@ -1683,7 +1689,6 @@ _theme:
header: "Заголовок"
navBg: "Фон боковой панели"
navFg: "Текст на боковой панели"
navHoverFg: "Текст на боковой панели (под указателем)"
navActive: "Текст на боковой панели (активирован)"
navIndicator: "Индикатор на боковой панели"
link: "Ссылка"
@ -1706,11 +1711,8 @@ _theme:
buttonHoverBg: "Текст кнопки"
inputBorder: "Рамка поля ввода"
driveFolderBg: "Фон папки «Диска»"
wallpaperOverlay: "Слой обоев"
badge: "Значок"
messageBg: "Фон беседы"
accentDarken: "Фон (затемнённый)"
accentLighten: "Фон (осветлённый)"
fgHighlighted: "Подсвеченный текст"
_sfx:
note: "Заметки"
@ -1799,6 +1801,7 @@ _permissions:
"read:gallery-likes": "Просмотр списка понравившегося в галерее"
"write:gallery-likes": "Изменение списка понравившегося в галерее"
"write:admin:reset-password": "Сбросить пароль пользователю"
"write:chat": "Писать и удалять сообщения"
_auth:
shareAccessTitle: "Разрешения для приложений"
shareAccess: "Дать доступ для «{name}» к вашей учётной записи?"
@ -2147,3 +2150,7 @@ _reversi:
_remoteLookupErrors:
_noSuchObject:
title: "Не найдено"
_search:
searchScopeAll: "Все"
searchScopeLocal: "Местная"
searchScopeUser: "Указанный пользователь"

View file

@ -242,7 +242,6 @@ removeAreYouSure: "Naozaj chcete odstrániť \"{x}\"?"
deleteAreYouSure: "Naozaj chcete odstrániť \"{x}\"?"
resetAreYouSure: "Naozaj resetovať?"
saved: "Uložené"
messaging: "Chat"
upload: "Nahrať súbor"
keepOriginalUploading: "Zachovať pôvodný obrázok"
keepOriginalUploadingDescription: "Uloží pôvodný obrázok ako je. Ak je vypnuté, verzia pre web sa vygeneruje pri nahratí."
@ -255,7 +254,6 @@ uploadFromUrlMayTakeTime: "Nahrávanie môže nejaký čas trvať."
explore: "Objavovať"
messageRead: "Prečítané"
noMoreHistory: "To je všetko"
startMessaging: "Začať chat"
nUsersRead: "prečítané {n} používateľmi"
agreeTo: "Súhlasím s {0}"
agreeBelow: "Súhlasím s nasledovným"
@ -428,8 +426,6 @@ retype: "Zadajte znovu"
noteOf: "Poznámky používateľa {user}"
quoteAttached: "Citované"
quoteQuestion: "Pripojiť ako citát?"
noMessagesYet: "Zatiaľ žiadne správy"
newMessageExists: "Máte novú správu"
onlyOneFileCanBeAttached: "Ku správe môžete priložiť len jeden súbor"
signinRequired: "Prihláste sa, prosím!"
invitations: "Pozvať"
@ -917,6 +913,14 @@ renotes: "Preposlať"
sourceCode: "Zdrojový kód"
flip: "Preklopiť"
lastNDays: "Posledných {n} dní"
postForm: "Napísať poznámku"
information: "Informácie"
_chat:
invitations: "Pozvať"
noHistory: "Žiadna história"
members: "Členovia"
home: "Domov"
send: "Poslať"
_delivery:
stop: "Zmrazené"
_type:
@ -1085,7 +1089,6 @@ _theme:
header: "Hlavička"
navBg: "Pozadie bočného panela"
navFg: "Text bočného panela"
navHoverFg: "Text bočného panela (pod kurzorom)"
navActive: "Text bočného panela (aktívny)"
navIndicator: "Indikátor bočného panela"
link: "Odkaz"
@ -1108,11 +1111,8 @@ _theme:
buttonHoverBg: "Pozadie tlačidla (pod kurzorom)"
inputBorder: "Okraj vstupného poľa"
driveFolderBg: "Pozadie priečinu disku"
wallpaperOverlay: "Vrstvenie pozadia"
badge: "Odznak"
messageBg: "Pozadie chatu"
accentDarken: "Akcent (stmavené)"
accentLighten: "Akcent (zosvetlené)"
fgHighlighted: "Zvýraznený text"
_sfx:
note: "Poznámky"
@ -1176,6 +1176,7 @@ _permissions:
"write:gallery": "Upravovať vašu galériu"
"read:gallery-likes": "Vidieť zoznam obľúbených príspevkov z galérie"
"write:gallery-likes": "Upraviť zoznam obľúbených príspevov z galérie"
"write:chat": "Písať alebo odstraňovať správy v chate"
_auth:
shareAccess: "Prajete si povoliť \"{name}\", aby mal prístup k tomuto účtu?"
shareAccessAsk: "Naozaj chcete povoliť tejto aplikácii prístup k tomuto účtu?"
@ -1449,3 +1450,6 @@ _reversi:
_remoteLookupErrors:
_noSuchObject:
title: "Nenájdené"
_search:
searchScopeAll: "Všetko"
searchScopeLocal: "Lokálne"

View file

@ -249,7 +249,6 @@ removeAreYouSure: "Är du säker att du vill radera \"{x}\"?"
deleteAreYouSure: "Är du säker att du vill radera \"{x}\"?"
resetAreYouSure: "Vill du återställa?"
saved: "Sparad"
messaging: "Chatt"
upload: "Ladda upp"
keepOriginalUploading: "Behåll originalbild"
keepOriginalUploadingDescription: "Sparar den originellt uppladdade bilden i sitt i befintliga skick. Om avstängd, kommer en webbversion bli genererad vid uppladdning."
@ -262,7 +261,6 @@ uploadFromUrlMayTakeTime: "Det kan ta tid tills att uppladdningen blir klar."
explore: "Utforska"
messageRead: "Läs"
noMoreHistory: "Det finns ingen mer historik"
startMessaging: "Starta en chatt"
nUsersRead: "läst av {n}"
agreeTo: "Jag accepterar {0}"
agree: "Överens"
@ -394,7 +392,6 @@ text: "Text"
enable: "Aktivera"
next: "Nästa"
retype: "Ange igen"
noMessagesYet: "Inga meddelanden än"
invitations: "Inbjudan"
invitationCode: "Inbjudningskod"
available: "Tillgängligt"
@ -562,6 +559,12 @@ inquiry: "Kontakt"
tryAgain: "Försök igen senare"
signinWithPasskey: "Logga in med nyckel"
unknownWebAuthnKey: "Okänd nyckel"
information: "Om"
_chat:
invitations: "Inbjudan"
members: "Medlemmar"
home: "Hem"
send: "Skicka"
_delivery:
stop: "Suspenderad"
_type:
@ -707,3 +710,5 @@ _reversi:
white: "Vit"
_selfXssPrevention:
warning: "VARNING"
_search:
searchScopeAll: "Allt"

View file

@ -287,7 +287,6 @@ deleteAreYouSure: "ต้องการลบ “{x}” ใช่ไหม?"
resetAreYouSure: "รีเซ็ตเลยไหม?"
areYouSure: "แน่ใจแล้วใช่ไหมคะ?"
saved: "บันทึกแล้ว"
messaging: "แชท"
upload: "อัปโหลด"
keepOriginalUploading: "เก็บภาพต้นฉบับ"
keepOriginalUploadingDescription: "เก็บภาพต้นฉบับไว้เมื่ออัปโหลดภาพ หากปิด รูปภาพสำหรับการเผยแพร่ทางเว็บจะถูกสร้างขึ้นในเบราว์เซอร์เมื่อทำการอัปโหลด"
@ -300,7 +299,6 @@ uploadFromUrlMayTakeTime: "การอัปโหลดอาจใช้เ
explore: "สำรวจ"
messageRead: "อ่านแล้ว"
noMoreHistory: "ไม่มีประวัติเพิ่มเติม"
startMessaging: "เริ่มการสนทนา"
nUsersRead: "อ่านโดย {n}"
agreeTo: "ฉันยอมรับ {0}"
agree: "ยอมรับ"
@ -489,8 +487,6 @@ noteOf: "โน้ตของ {user}"
quoteAttached: "อ้างอิง"
quoteQuestion: "ต้องการที่จะแนบมันเพื่ออ้างอิงใช่ไหม?"
attachAsFileQuestion: "ข้อความในคลิปบอร์ดยาวเกินไป คุณต้องการแนบเป็นไฟล์ข้อความหรือไม่?"
noMessagesYet: "ยังไม่มีข้อความ"
newMessageExists: "คุณมีข้อความใหม่"
onlyOneFileCanBeAttached: "สามารถแนบไฟล์ได้เพียงไฟล์เดียวต่อ 1 ข้อความ"
signinRequired: "ก่อนดำเนินการต่อ กรุณาลงทะเบียนหรือเข้าสู่ระบบ"
signinOrContinueOnRemote: "เพื่อดำเนินการต่อได้ คุณต้องไปที่เซิร์ฟเวอร์ที่คุณใช้งานอยู่ หรือลงทะเบียน/เข้าสู่ระบบเซิร์ฟเวอร์นี้"
@ -1292,6 +1288,16 @@ prohibitedWordsForNameOfUser: "คำนี้ไม่สามารถใช
prohibitedWordsForNameOfUserDescription: "หากมีสตริงใดๆ ในรายการนี้ปรากฏอยู่ในชื่อของผู้ใช้ ชื่อนั้นจะถูกปฏิเสธ ผู้ใช้ที่มีสิทธิ์แต่ผู้ดูแลระบบนั้นจะไม่ได้รับผลกระทบใดๆจากข้อจำกัดนี้ค่ะ"
yourNameContainsProhibitedWords: "ชื่อของคุณนั้นมีคำที่ต้องห้าม"
yourNameContainsProhibitedWordsDescription: "ถ้าหากคุณต้องการใช้ชื่อนี้ กรุณาติดต่อผู้ดูแลระบบของเซิร์ฟเวอร์นะค่ะ"
postForm: "แบบฟอร์มการโพสต์"
information: "เกี่ยวกับ"
_chat:
invitations: "คำเชิญ"
noHistory: "ไม่มีประวัติ"
members: "สมาชิก"
home: "หน้าหลัก"
send: "ส่ง"
_settings:
webhook: "Webhook"
_abuseUserReport:
forward: "ส่ง​ต่อ"
forwardDescription: "ส่งรายงานไปยังเซิร์ฟเวอร์ระยะไกลโดยใช้บัญชีระบบที่ไม่ระบุตัวตน"
@ -1968,7 +1974,6 @@ _theme:
header: "ส่วนหัว"
navBg: "พื้นหลังแถบด้านข้าง"
navFg: "ข้อความแถบด้านข้าง"
navHoverFg: "ข้อความแถบด้านข้าง (โฮเวอร์)"
navActive: "ข้อความแถบด้านข้าง (ใช้งานอยู่)"
navIndicator: "ตัวระบุแถบด้านข้าง"
link: "ลิงก์"
@ -1991,11 +1996,8 @@ _theme:
buttonHoverBg: "ปุ่มพื้นหลัง (โฮเวอร์)"
inputBorder: "เส้นขอบของช่องป้อนข้อมูล"
driveFolderBg: "พื้นหลังโฟลเดอร์ไดรฟ์"
wallpaperOverlay: "วอลล์เปเปอร์ซ้อนทับ"
badge: "ตรา"
messageBg: "พื้นหลังแชท"
accentDarken: "สีหลัก (มืด)"
accentLighten: "สีหลัก (สว่าง)"
fgHighlighted: "ข้อความที่ไฮไลต์"
_sfx:
note: "โน้ต"
@ -2148,6 +2150,7 @@ _permissions:
"read:clip-favorite": "ดูคลิปที่ถูกใจ"
"read:federation": "รับข้อมูลเกี่ยวกับสหพันธ์"
"write:report-abuse": "รายงานการละเมิด"
"write:chat": "เขียนหรือลบข้อความแชท"
_auth:
shareAccessTitle: "การให้สิทธิ์แอปพลิเคชัน"
shareAccess: "คุณต้องการอนุญาตให้ \"{name}\" เข้าถึงบัญชีนี้เลยมั้ย?"
@ -2569,10 +2572,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "โปรดตรวจสอบให้แน่ใจว่าแหล่งแจกหน่ายมีความน่าเชื่อถือก่อนทำการติดตั้ง"
_plugin:
title: "ต้องการติดตั้งปลั๊กอินนี้ใช่ไหม?"
metaTitle: "ข้อมูลส่วนเสริม"
_theme:
title: "ต้องการติดตั้งธีมนี้ใช่ไหม?"
metaTitle: "ข้อมูลธีม"
_meta:
base: "โทนสีพื้นฐาน"
_vendorInfo:
@ -2709,3 +2710,7 @@ _embedCodeGen:
_remoteLookupErrors:
_noSuchObject:
title: "ไม่พบหน้าที่ต้องการ"
_search:
searchScopeAll: "ทั้งหมด"
searchScopeLocal: "ท้องถิ่น"
searchScopeUser: "ผู้ใช้เฉพาะ"

View file

@ -261,7 +261,6 @@ removeAreYouSure: "\"{x}\" silmek istediğinizden emin misiniz?"
deleteAreYouSure: "\"{x}\" silmek istediğinizden emin misiniz?"
resetAreYouSure: "Sıfırlansın mı?"
saved: "Kaydedildi"
messaging: "Mesajlar"
upload: "Yükle"
keepOriginalUploading: "Orijinal görseli koru"
keepOriginalUploadingDescription: "Orijinal olarak yüklenen görüntüyü olduğu gibi kaydeder. Kapatılırsa, yükleme sırasında web'de görüntülenecek bir sürüm oluşturulur."
@ -274,7 +273,6 @@ uploadFromUrlMayTakeTime: "Yüklemenin tamamlanması biraz süre alabilir."
explore: "Keşfet"
messageRead: "Okundu"
noMoreHistory: "Bundan öncesi yok"
startMessaging: "Yeni bir sohbet başlat"
nUsersRead: "{n} kişi okudu"
agreeTo: "Kabul Ediyorum: {0}"
agree: "Kabul Et"
@ -351,7 +349,6 @@ pinnedNotes: "Sabitlenen"
manageAntennas: "Anten ayarları"
userList: "Listeler"
resetPassword: "Şifre sıfırlama"
noMessagesYet: "Şimdilik mesaj yok"
details: "Detaylar"
deck: "Güverte"
smtpHost: "Sağlayıcı"
@ -378,6 +375,8 @@ addMemo: "Kısa not ekle"
icon: "Avatar"
replies: "yanıt"
renotes: "vazgeçme"
_chat:
home: "Ana sayfa"
_delivery:
stop: "Askıya alınmış"
_type:
@ -460,3 +459,5 @@ _deck:
_moderationLogTypes:
suspend: "askıya al"
resetPassword: "Şifre sıfırlama"
_search:
searchScopeAll: "Tümü"

View file

@ -246,7 +246,6 @@ removeAreYouSure: "Ви впевнені, що хочете видалити \"{
deleteAreYouSure: "Ви впевнені, що хочете видалити \"{x}\"?"
resetAreYouSure: "Справді скинути?"
saved: "Збережено"
messaging: "Чати"
upload: "Завантажити"
keepOriginalUploading: "Зберегти оригінальне зображення"
keepOriginalUploadingDescription: "Зберігає початково завантажене зображення як є. Якщо вимкнено, версія для відображення в Інтернеті буде створена під час завантаження."
@ -259,7 +258,6 @@ uploadFromUrlMayTakeTime: "Завантаження може зайняти де
explore: "Огляд"
messageRead: "Прочитано"
noMoreHistory: "Подальшої історії немає"
startMessaging: "Розпочати діалог"
nUsersRead: "Прочитали {n}"
agreeTo: "Я погоджуюсь з {0}"
agreeBelow: "Я погоджуюся з наведеним нижче"
@ -427,8 +425,6 @@ retype: "Введіть ще раз"
noteOf: "Нотатка {user}"
quoteAttached: "Цитата"
quoteQuestion: "Ви хочете додати цитату?"
noMessagesYet: "Ще немає повідомлень"
newMessageExists: "Є нові повідомлення"
onlyOneFileCanBeAttached: "До повідомлення можна вкласти лише один файл"
signinRequired: "Будь ласка, авторизуйтесь"
invitations: "Запрошення"
@ -909,6 +905,14 @@ renotes: "Поширити"
sourceCode: "Вихідний код"
flip: "Перевернути"
lastNDays: "Останні {n} днів"
postForm: "Створення нотатки"
information: "Інформація"
_chat:
invitations: "Запросити"
noHistory: "Історія порожня"
members: "Учасники"
home: "Домівка"
send: "Відправити"
_delivery:
stop: "Призупинено"
_type:
@ -1279,7 +1283,6 @@ _theme:
header: "Заголовок"
navBg: "Фон бокової панелі"
navFg: "Текст бокової панелі"
navHoverFg: "Текст бокової панелі (під курсором)"
navActive: "Текст бокової панелі (активне)"
navIndicator: "Індикатор бокової панелі"
link: "Посилання"
@ -1302,11 +1305,8 @@ _theme:
buttonHoverBg: "Фон кнопки (при наведенні)"
inputBorder: "Край поля вводу"
driveFolderBg: "Фон папки на диску"
wallpaperOverlay: "Накладання шпалер"
badge: "Значок"
messageBg: "Фон переписки"
accentDarken: "Акцент (Затемлений)"
accentLighten: "Акцент (Освітлений)"
fgHighlighted: "Виділений текст"
_sfx:
note: "Нотатки"
@ -1365,6 +1365,7 @@ _permissions:
"read:channels": "Переглядати канали"
"write:channels": "Змінювати канали"
"read:gallery": "Перегляд галереї"
"write:chat": "Створювати та видаляти повідомлення"
_auth:
shareAccess: "Ви хочете надати \"{name}\" доступ до цього акаунту?"
shareAccessAsk: "Ви впевнені, що хочете надати цій програмі доступ до вашого акаунту?"
@ -1624,3 +1625,6 @@ _reversi:
_remoteLookupErrors:
_noSuchObject:
title: "Не знайдено"
_search:
searchScopeAll: "Всі"
searchScopeLocal: "Локальна"

View file

@ -257,7 +257,6 @@ removeAreYouSure: "“{x}”ni olib tashlamoqchi ekanligingizga ishonchingiz kom
deleteAreYouSure: "“{x}”ni chindan ham yo'q qilmoqchimisiz?"
resetAreYouSure: "Haqiqatan ham qayta tiklansinmi?"
saved: "Saqlandi"
messaging: "Suhbat"
upload: "Yuklash"
keepOriginalUploading: "Asl rasmni saqlang"
keepOriginalUploadingDescription: "Rasmlarni yuklashda asl nusxasini saqlaydi. Agar o'chirilgan bo'lsa, brauzer yuklangandan keyin nashr qilish uchun rasm yaratadi."
@ -270,7 +269,6 @@ uploadFromUrlMayTakeTime: "Yuklash tugallanishi uchun biroz vaqt ketishi mumkin.
explore: "Ko'rib chiqish"
messageRead: "Oqildi"
noMoreHistory: "Buning ortida hech qanday hikoya yo'q"
startMessaging: "Yangi suhbatni boshlash"
nUsersRead: "{n} tomonidan o'qildi"
agreeTo: "Men {0} ga roziman"
agree: "Rozi bo'lish"
@ -445,8 +443,6 @@ retype: "Qayta kiriting"
noteOf: "{user} tomonidan joylandi\n"
quoteAttached: "Iqtibos"
quoteQuestion: "Iqtibos sifatida qo'shilsinmi?"
noMessagesYet: "Bu yerda xabarlar yo'q"
newMessageExists: "Yangi xabarlar bor"
onlyOneFileCanBeAttached: "Faqat bitta faylni biriktirish mumkin"
signinRequired: "Davom etishdan oldin ro'yhatdan o'tishingiz yoki tizimga kirishingiz kerak"
invitations: "Taklif qilish"
@ -841,6 +837,13 @@ icon: "Avatar"
replies: "Javob berish"
renotes: "Qayta qayd etish"
flip: "Teskari"
information: "Haqida"
_chat:
invitations: "Taklif qilish"
noHistory: "Tarix yo'q"
members: "A'zolar"
home: "Bosh sahifa"
send: "Yuborish"
_delivery:
stop: "To'xtatilgan"
_type:
@ -904,8 +907,6 @@ _theme:
mention: "Murojat"
renote: "Qayta qayd etish"
divider: "Ajratrmoq"
accentDarken: "Urg'u (Qoraytirilgan)"
accentLighten: "Urg'u (Yoritilgan)"
fgHighlighted: "Belgilangan matn"
_sfx:
note: "Qaydlar"
@ -1094,3 +1095,6 @@ _reversi:
_remoteLookupErrors:
_noSuchObject:
title: "Topilmadi"
_search:
searchScopeAll: "Barcha"
searchScopeLocal: "Mahalliy"

View file

@ -264,7 +264,6 @@ deleteAreYouSure: "Bạn có chắc muốn xóa \"{x}\"?"
resetAreYouSure: "Bạn có chắc muốn đặt lại?"
areYouSure: "Bạn chắc chứ?"
saved: "Đã lưu"
messaging: "Trò chuyện"
upload: "Tải lên"
keepOriginalUploading: "Giữ hình ảnh gốc"
keepOriginalUploadingDescription: "Giữ nguyên như hình ảnh được tải lên ban đầu. Nếu tắt, một phiên bản để hiển thị trên web sẽ được tạo khi tải lên."
@ -277,7 +276,6 @@ uploadFromUrlMayTakeTime: "Sẽ mất một khoảng thời gian để tải lê
explore: "Khám phá"
messageRead: "Đã đọc"
noMoreHistory: "Không còn gì để đọc"
startMessaging: "Bắt đầu trò chuyện"
nUsersRead: "đọc bởi {n}"
agreeTo: "Tôi đồng ý {0}"
agree: "Đồng ý"
@ -463,8 +461,6 @@ noteOf: "Tút của {user}"
quoteAttached: "Trích dẫn"
quoteQuestion: "Trích dẫn lại?"
attachAsFileQuestion: "Văn bản ở trong bộ nhớ tạm rất dài. Bạn có muốn đăng nó dưới dạng một tệp văn bản không?"
noMessagesYet: "Chưa có tin nhắn"
newMessageExists: "Bạn có tin nhắn mới"
onlyOneFileCanBeAttached: "Bạn chỉ có thể đính kèm một tập tin"
signinRequired: "Vui lòng đăng nhập"
invitations: "Mời"
@ -1119,6 +1115,14 @@ pullDownToRefresh: "Kéo xuống để làm mới"
cwNotationRequired: "Nếu \"Ẩn nội dung\" được bật thì cần phải có chú thích."
lastNDays: "{n} ngày trước"
surrender: "Từ chối"
postForm: "Mẫu đăng"
information: "Giới thiệu"
_chat:
invitations: "Mời"
noHistory: "Không có dữ liệu"
members: "Thành viên"
home: "Trang chính"
send: "Gửi"
_delivery:
stop: "Đã vô hiệu hóa"
_type:
@ -1526,7 +1530,6 @@ _theme:
header: "Ảnh bìa"
navBg: "Nền thanh bên"
navFg: "Chữ thanh bên"
navHoverFg: "Chữ thanh bên (Khi chạm)"
navActive: "Chữ thanh bên (Khi chọn)"
navIndicator: "Chỉ báo thanh bên"
link: "Đường dẫn"
@ -1549,11 +1552,8 @@ _theme:
buttonHoverBg: "Nền nút (Chạm)"
inputBorder: "Đường viền khung soạn thảo"
driveFolderBg: "Nền thư mục Ổ đĩa"
wallpaperOverlay: "Lớp phủ hình nền"
badge: "Huy hiệu"
messageBg: "Nền chat"
accentDarken: "Màu phụ (Tối)"
accentLighten: "Màu phụ (Sáng)"
fgHighlighted: "Chữ nổi bật"
_sfx:
note: "Tút"
@ -1628,6 +1628,7 @@ _permissions:
"write:gallery": "Sửa kho ảnh của tôi"
"read:gallery-likes": "Xem danh sách các tút đã thích trong thư viện của tôi"
"write:gallery-likes": "Sửa danh sách các tút đã thích trong thư viện của tôi"
"write:chat": "Soạn hoặc xóa tin nhắn"
_auth:
shareAccessTitle: "Cho phép truy cập app"
shareAccess: "Bạn có muốn cho phép \"{name}\" truy cập vào tài khoản này không?"
@ -1930,3 +1931,7 @@ _reversi:
_remoteLookupErrors:
_noSuchObject:
title: "Không tìm thấy"
_search:
searchScopeAll: "Tất cả"
searchScopeLocal: "Máy chủ này"
searchScopeUser: "Người dùng chỉ định"

View file

@ -289,7 +289,6 @@ deleteAreYouSure: "要删掉「{x}」吗?"
resetAreYouSure: "恢复默认设置?"
areYouSure: "你确定吗?"
saved: "已保存"
messaging: "聊天"
upload: "本地上传"
keepOriginalUploading: "保留原图"
keepOriginalUploadingDescription: "上传图片时保留原始图片。关闭时浏览器会在上传时生成一张用于web发布的图片。"
@ -302,7 +301,7 @@ uploadFromUrlMayTakeTime: "上传可能需要一些时间完成。"
explore: "发现"
messageRead: "已读"
noMoreHistory: "没有更多的历史记录"
startMessaging: "添加聊天"
startChat: "开始聊天"
nUsersRead: "{n} 人已读"
agreeTo: "勾选则表示已阅读并同意 {0}"
agree: "同意"
@ -425,6 +424,7 @@ antennaExcludeBots: "排除机器人账户"
antennaKeywordsDescription: "AND 条件用空格分隔OR 条件用换行符分隔。"
notifyAntenna: "开启通知"
withFileAntenna: "仅带有附件的帖子"
hideNotesInSensitiveChannel: "隐藏敏感频道内的帖子"
enableServiceworker: "启用 ServiceWorker"
antennaUsersDescription: "指定用户名,一行一个"
caseSensitive: "区分大小写"
@ -491,8 +491,6 @@ noteOf: "{user} 的帖子"
quoteAttached: "已引用"
quoteQuestion: "是否引用此链接内容?"
attachAsFileQuestion: "剪贴板内的文字过长。要转换为文本文件并添加吗?"
noMessagesYet: "现在没有新的聊天"
newMessageExists: "新信息"
onlyOneFileCanBeAttached: "只能添加一个附件"
signinRequired: "请先登录"
signinOrContinueOnRemote: "若要继续,需要转到您所使用的实例,或者在此服务器上注册或登录。"
@ -698,6 +696,7 @@ userSaysSomethingAbout: "{name} 说了关于「{word}」的什么"
makeActive: "启用"
display: "显示"
copy: "复制"
copiedToClipboard: "已复制到剪贴板"
metrics: "指标"
overview: "概览"
logs: "日志"
@ -746,7 +745,7 @@ confirmToUnclipAlreadyClippedNote: "本帖已包含在便签 \"{name}\" 里。
public: "公开"
private: "私密"
i18nInfo: "Misskey 已经被志愿者们翻译成了各种语言。如果你也有兴趣,可以通过 {link} 帮助翻译。"
manageAccessTokens: "管理 Access Tokens"
manageAccessTokens: "管理访问令牌"
accountInfo: "账户信息"
notesCount: "帖子数量"
repliesCount: "回复数量"
@ -1309,6 +1308,129 @@ availableRoles: "可用角色"
acknowledgeNotesAndEnable: "理解注意事项后再开启。"
federationSpecified: "此服务器已开启联合白名单。只能与管理员指定的服务器通信。"
federationDisabled: "此服务器已禁用联合。无法与其它服务器上的用户通信。"
confirmOnReact: "发送回应前需要确认"
reactAreYouSure: "要用「{emoji}」进行回应吗?"
markAsSensitiveConfirm: "要将此媒体标记为敏感吗?"
unmarkAsSensitiveConfirm: "要将此媒体解除敏感标记吗?"
preferences: "设置"
accessibility: "辅助功能"
preferencesProfile: "设置的配置"
copyPreferenceId: "复制设置 ID"
resetToDefaultValue: "重置为默认值"
overrideByAccount: "用账户覆盖"
untitled: "未命名"
noName: "没有名字"
skip: "跳过"
restore: "恢复"
syncBetweenDevices: "设备间同步"
preferenceSyncConflictTitle: "服务器上已存在设定值"
preferenceSyncConflictText: "服务器上已有此设置的设定值。要覆盖哪个设定值?"
preferenceSyncConflictChoiceServer: "服务器上的设定值"
preferenceSyncConflictChoiceDevice: "设备上的设定值"
preferenceSyncConflictChoiceCancel: "取消同步"
paste: "粘贴"
emojiPalette: "表情符号调色板"
postForm: "投稿窗口"
textCount: "字数"
information: "关于"
chat: "聊天"
migrateOldSettings: "迁移旧设置信息"
migrateOldSettings_description: "通常设置信息将自动迁移。但如果由于某种原因迁移不成功,则可以手动触发迁移过程。当前的配置信息将被覆盖。"
compress: "压缩"
right: "右"
bottom: "下"
top: "上"
embed: "嵌入"
_chat:
noMessagesYet: "还没有消息"
newMessage: "新消息"
individualChat: "私聊"
individualChat_description: "可以与特定用户进行一对一聊天。"
roomChat: "群聊"
roomChat_description: "可以进行多人聊天。\n就算用户未允许私聊只要接受了邀请仍可以聊天。"
createRoom: "创建房间"
inviteUserToChat: "邀请用户来开始聊天"
yourRooms: "已创建的房间"
joiningRooms: "已加入的房间"
invitations: "邀请"
noInvitations: "没有邀请"
history: "历史"
noHistory: "没有历史记录"
noRooms: "没有房间"
inviteUser: "邀请用户"
sentInvitations: "已发送的邀请"
join: "加入"
ignore: "忽略"
leave: "退出房间"
members: "成员"
searchMessages: "搜索消息"
home: "首页"
send: "发送"
newline: "换行"
muteThisRoom: "静音此房间"
deleteRoom: "删除房间"
chatNotAvailableForThisAccountOrServer: "此服务器或者账户还未开启聊天功能。"
chatNotAvailableInOtherAccount: "对方账户目前处于无法使用聊天的状态。"
cannotChatWithTheUser: "无法与此用户聊天"
cannotChatWithTheUser_description: "可能现在无法使用聊天,或者对方未开启聊天。"
chatWithThisUser: "聊天"
thisUserAllowsChatOnlyFromFollowers: "此用户仅接受关注者发起的聊天。"
thisUserAllowsChatOnlyFromFollowing: "此用户仅接受关注的人发起的聊天。"
thisUserAllowsChatOnlyFromMutualFollowing: "此用户仅接受互相关注的人发起的聊天。"
thisUserNotAllowedChatAnyone: "此用户不接受任何人发起的聊天。"
chatAllowedUsers: "谁可以发起聊天"
chatAllowedUsers_note: "主动发起聊天时,对方将不受此设置限制。"
_chatAllowedUsers:
everyone: "任何人"
followers: "仅关注者"
following: "仅关注的人"
mutual: "仅相互关注"
none: "没有人"
_emojiPalette:
palettes: "调色板"
enableSyncBetweenDevicesForPalettes: "启用调色板的设备间同步"
paletteForMain: "主调色板"
paletteForReaction: "回应用调色板"
_settings:
driveBanner: "可在此管理和设置网盘、确认使用量及配置上传文件的设置。"
pluginBanner: "使用插件可以扩展客户端的功能。可以在此安装、单独管理插件。"
notificationsBanner: "可在此设置从服务器接收的通知的种类和范围,以及推送通知的设置。"
api: "API"
webhook: "Webhook"
serviceConnection: "连接服务"
serviceConnectionBanner: "可在此管理用于连接外部应用或服务的访问令牌及 Webhook。"
accountData: "账户数据"
accountDataBanner: "可在此导入或导出帐户数据的存档。"
muteAndBlockBanner: "可在此设置隐藏内容,或限制指定用户能进行的操作。"
accessibilityBanner: "可在此设置客户端的显示及动态效果等辅助设置。"
privacyBanner: "可在此设置如内容可见性、可发现性、批准关注请求等账户隐私设置。"
securityBanner: "可在此设置如密码、登入方式、验证器、Passkey 等账户安全性设置。"
preferencesBanner: "可在此设置客户端的整体运作行为。"
appearanceBanner: "可在此设置客户端的外观及显示方式。"
soundsBanner: "可在此设置客户端播放的声音。"
timelineAndNote: "时间线和帖子"
makeEveryTextElementsSelectable: "使所有的文字均可选择"
makeEveryTextElementsSelectable_description: "若开启,在某些情况下可能降低用户体验。"
useStickyIcons: "使图标跟随滚动"
showNavbarSubButtons: "在导航栏中显示副按钮"
ifOn: "启用时"
ifOff: "关闭时"
_chat:
showSenderName: "显示发送者的名字"
sendOnEnter: "回车键发送"
_preferencesProfile:
profileName: "配置名"
profileNameDescription: "请指定用于识别此设备的名称"
profileNameDescription2: "如「PC」、「手机」等"
_preferencesBackup:
autoBackup: "自动备份"
restoreFromBackup: "从备份恢复"
noBackupsFoundTitle: "没有找到备份"
noBackupsFoundDescription: "没有找到自动备份。若有手动保存备份文件,可将其导入来恢复。"
selectBackupToRestore: "请选择要恢复的备份"
youNeedToNameYourProfileToEnableAutoBackup: "需指定配置名以开启自动备份。"
autoPreferencesBackupIsNotEnabledForThisDevice: "此设备未开启自动备份"
backupFound: "已找到备份"
_accountSettings:
requireSigninToViewContents: "需要登录才能显示内容"
requireSigninToViewContentsDescription1: "您发布的所有帖子将变成需要登入后才会显示。有望防止爬虫收集各种信息。"
@ -1319,6 +1441,7 @@ _accountSettings:
makeNotesHiddenBefore: "将过去的帖子设为私密"
makeNotesHiddenBeforeDescription: "开启此设定时,超过设定的时间或日期后,帖子将变为仅自己可见。关闭后帖子的公开状态将恢复成原本的设定。"
mayNotEffectForFederatedNotes: "与远程服务器联合的帖子在远端可能会没有效果。"
mayNotEffectSomeSituations: "此限制功能非常简单,在与远程服务器联合等情形时可能不适用。"
notesHavePassedSpecifiedPeriod: "超过指定时间的帖子"
notesOlderThanSpecifiedDateAndTime: "指定日期前的帖子"
_abuseUserReport:
@ -1804,6 +1927,7 @@ _role:
canImportFollowing: "允许导入关注列表"
canImportMuting: "允许导入隐藏列表"
canImportUserLists: "允许导入用户列表"
canChat: "允许聊天"
_condition:
roleAssignedTo: "已分配给手动角色"
isLocal: "是本地用户"
@ -1967,6 +2091,7 @@ _theme:
installed: "{name} 已安装"
installedThemes: "已安装的主题"
builtinThemes: "标准主题"
instanceTheme: "服务器主题"
alreadyInstalled: "此主题已经安装"
invalid: "主题格式错误"
make: "制作主题"
@ -1999,7 +2124,6 @@ _theme:
header: "顶栏"
navBg: "侧边栏背景"
navFg: "侧栏文本"
navHoverFg: "侧栏文本(悬停)"
navActive: "侧栏文本(活动)"
navIndicator: "侧栏标记"
link: "链接"
@ -2022,17 +2146,15 @@ _theme:
buttonHoverBg: "按钮背景(悬停)"
inputBorder: "输入框边框"
driveFolderBg: "网盘的文件夹背景"
wallpaperOverlay: "壁纸叠加层"
badge: "徽章"
messageBg: "聊天背景"
accentDarken: "强调色(深)"
accentLighten: "强调色(浅)"
fgHighlighted: "高亮显示文本"
_sfx:
note: "帖子"
noteMy: "我的帖子"
notification: "通知"
reaction: "选择回应时"
chatMessage: "聊天信息"
_soundSettings:
driveFile: "使用网盘内的音频"
driveFileWarn: "选择网盘上的文件"
@ -2179,6 +2301,8 @@ _permissions:
"read:clip-favorite": "查看便签的点赞"
"read:federation": "查看联合相关信息"
"write:report-abuse": "举报用户"
"write:chat": "撰写或删除消息"
"read:chat": "查看聊天"
_auth:
shareAccessTitle: "应用程序授权许可"
shareAccess: "您要授权允许 “{name}” 访问您的帐户吗?"
@ -2427,6 +2551,7 @@ _notification:
newNote: "新的帖子"
unreadAntennaNote: "天线 {name}"
roleAssigned: "授予的角色"
chatRoomInvitationReceived: "受邀加入聊天室"
emptyPushNotificationMessage: "推送通知已更新"
achievementEarned: "获得成就"
testNotification: "测试通知"
@ -2440,6 +2565,8 @@ _notification:
flushNotification: "重置通知历史"
exportOfXCompleted: "已完成 {x} 的导出"
login: "有新的登录"
createToken: "访问令牌已创建"
createTokenDescription: "如果不明白其用途,请遵循「{text}」的指示删除访问令牌。"
_types:
all: "全部"
note: "用户的新帖子"
@ -2453,9 +2580,11 @@ _notification:
receiveFollowRequest: "收到关注请求"
followRequestAccepted: "关注请求已通过"
roleAssigned: "授予的角色"
chatRoomInvitationReceived: "受邀加入聊天室"
achievementEarned: "取得的成就"
exportCompleted: "已完成导出"
login: "登录"
createToken: "创建访问令牌"
test: "测试通知"
app: "关联应用的通知"
_actions:
@ -2465,6 +2594,9 @@ _notification:
_deck:
alwaysShowMainColumn: "总是显示主列"
columnAlign: "列对齐"
columnGap: "列间距"
deckMenuPosition: "Deck 菜单位置"
navbarPosition: "导航栏位置"
addColumn: "添加列"
newNoteNotificationSettings: "新帖子通知设定"
configureColumn: "列设置"
@ -2478,11 +2610,12 @@ _deck:
newProfile: "新建配置文件"
deleteProfile: "删除配置文件"
introduction: "将各列进行组合以创建您自己的界面!"
introduction2: "可以随时通过屏幕右侧的 + 来添加列"
introduction2: "可以随时通过屏幕右侧的 + 来添加列"
widgetsIntroduction: "从列菜单中,选择“小工具编辑”来添加小工具"
useSimpleUiForNonRootPages: "用简易UI表示非根页面"
usedAsMinWidthWhenFlexible: "「自适应宽度」被启用的时候,这就是最小的宽度"
flexible: "自适应宽度"
enableSyncBetweenDevicesForProfiles: "启用个人资料信息跨设备同步"
_columns:
main: "主列"
widgets: "小工具"
@ -2590,6 +2723,8 @@ _moderationLogTypes:
deletePage: "删除了页面"
deleteFlash: "删除了 Play"
deleteGalleryPost: "删除了图库稿件"
deleteChatRoom: "删除聊天室"
updateProxyAccountDescription: "更新代理账户的简介"
_fileViewer:
title: "文件信息"
type: "文件类型"
@ -2603,10 +2738,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "请在安装前确保来源可靠"
_plugin:
title: "要安装此插件吗?"
metaTitle: "插件信息"
_theme:
title: "要安装此主题吗?"
metaTitle: "主题信息"
_meta:
base: "基本配色方案"
_vendorInfo:
@ -2777,8 +2910,8 @@ _customEmojisManager:
_register:
uploadSettingTitle: "上传设置"
uploadSettingDescription: "可以在此页面设置上传表情符号时的行为。"
directoryToCategoryLabel: "目录名请输入「category」"
directoryToCategoryCaption: "拖放目录时,目录名请输入「category」"
directoryToCategoryLabel: "将目录名设为「category」"
directoryToCategoryCaption: "拖放目录时,将目录名设置为「category」"
emojiInputAreaCaption: "请使用其中一种方法选择要注册的表情符号。"
emojiInputAreaList1: "在此区域内拖放图像文件或者目录"
emojiInputAreaList2: "单击此链接以从电脑中选择"
@ -2822,8 +2955,6 @@ _remoteLookupErrors:
_responseInvalid:
title: "响应无效"
description: "成功与此服务器通信,但返回的数据无效。"
_responseInvalidIdHostNotMatch:
description: "输入 URI 的域名和最终取得的 URI 的域名不同。如果是通过第三方服务器获取远程内容,请使用可以从原始服务器获取内容的 URI 再试一次。"
_noSuchObject:
title: "未找到"
description: "未找到请求的资源。请再次检查 URI。"
@ -2840,3 +2971,23 @@ _captcha:
_unknown:
title: "CAPTCHA 错误"
text: "发生意外错误。"
_bootErrors:
title: "加载失败"
serverError: "请稍等片刻再重试。若问题仍无法解决,请将以下 Error ID 一起发送给管理员。"
solution: "以下方法或许可以解决问题:"
solution1: "将浏览器及操作系统更新到最新版本"
solution2: "禁用广告屏蔽插件"
solution3: "清除浏览器缓存"
solution4: "Tor Browser将 dom.webaudio.enabled 设定为 true"
otherOption: "其它选项"
otherOption1: "清除客户端设定与缓存"
otherOption2: "使用简易客户端"
otherOption3: "启动修复工具"
_search:
searchScopeAll: "全部"
searchScopeLocal: "本地"
searchScopeServer: "指定服务器"
searchScopeUser: "指定用户"
pleaseEnterServerHost: "请填写服务器主机名"
pleaseSelectUser: "请选择用户"
serverHostPlaceholder: "如misskey.example.com"

View file

@ -103,7 +103,7 @@ serverIsDead: "伺服器沒有回應。請稍等片刻再試。"
youShouldUpgradeClient: "請重新載入以使用新版客戶端顯示此頁面。"
enterListName: "輸入清單名稱"
privacy: "隱私"
makeFollowManuallyApprove: "手動審核追隨請求"
makeFollowManuallyApprove: "追隨需要核准"
defaultNoteVisibility: "預設可見性"
follow: "追隨"
followRequest: "追隨請求"
@ -289,7 +289,6 @@ deleteAreYouSure: "確定要刪掉「{x}」嗎?"
resetAreYouSure: "確定要重設嗎?"
areYouSure: "是否確定?"
saved: "已儲存"
messaging: "聊天"
upload: "上傳"
keepOriginalUploading: "保留原圖"
keepOriginalUploadingDescription: "上傳圖片時保留原始圖片。關閉時,瀏覽器會在上傳時生成適用於網路傳送的版本。"
@ -302,7 +301,7 @@ uploadFromUrlMayTakeTime: "還需要一些時間才能完成上傳。"
explore: "探索"
messageRead: "已讀"
noMoreHistory: "沒有更多歷史紀錄"
startMessaging: "開始聊天"
startChat: "開始聊天"
nUsersRead: "{n} 人已讀"
agreeTo: "我同意{0}"
agree: "同意"
@ -368,7 +367,7 @@ normal: "正常"
instanceName: "伺服器名稱"
instanceDescription: "伺服器介紹"
maintainerName: "管理員名稱"
maintainerEmail: "管理員箱"
maintainerEmail: "管理員箱"
tosUrl: "服務條款 URL"
thisYear: "本年"
thisMonth: "本月"
@ -425,6 +424,7 @@ antennaExcludeBots: "排除機器人帳戶"
antennaKeywordsDescription: "空格代表「以及」AND換行代表「或者」OR"
notifyAntenna: "通知有新貼文"
withFileAntenna: "僅帶有附件的貼文"
hideNotesInSensitiveChannel: "隱藏敏感頻道的貼文"
enableServiceworker: "啟用瀏覽器的推播通知"
antennaUsersDescription: "填寫使用者名稱,以換行分隔"
caseSensitive: "區分大小寫"
@ -459,13 +459,13 @@ moderationNoteDescription: "您可以編寫僅在審查員之間共用的註解
addModerationNote: "新增管理筆記"
moderationLogs: "管理日誌"
nUsersMentioned: "被 {n} 個人提及"
securityKeyAndPasskey: "安全金鑰、Passkey"
securityKeyAndPasskey: "安全金鑰、通行金鑰"
securityKey: "安全金鑰"
lastUsed: "上次使用"
lastUsedAt: "上次使用:{t}"
unregister: "註銷"
passwordLessLogin: "設置無密碼登入"
passwordLessLoginDescription: "不使用密碼,以安全金鑰或 Passkey 登入"
passwordLessLogin: "無密碼登入"
passwordLessLoginDescription: "不使用密碼,以安全金鑰或通行金鑰登入"
resetPassword: "重設密碼"
newPasswordIs: "新密碼為「{password}」"
reduceUiAnimation: "減少介面的動態視覺"
@ -491,8 +491,6 @@ noteOf: "{user}的貼文"
quoteAttached: "引用"
quoteQuestion: "是否要引用?"
attachAsFileQuestion: "剪貼簿的文字較長。請問是否要將其以文字檔的方式附加呢?"
noMessagesYet: "沒有訊息"
newMessageExists: "有新的訊息"
onlyOneFileCanBeAttached: "只能加入一個附件"
signinRequired: "請先登入"
signinOrContinueOnRemote: "若要繼續,需前往您所在的伺服器,或者註冊並登入此伺服器"
@ -521,7 +519,7 @@ menuStyle: "選單風格"
style: "風格"
drawer: "側邊欄"
popup: "彈出式視窗"
showNoteActionsOnlyHover: "僅在游標停留時顯示貼文的"
showNoteActionsOnlyHover: "僅於游標懸停時顯示貼文選項"
showReactionsCount: "顯示貼文的反應數目"
noHistory: "沒有歷史紀錄"
signinHistory: "登入歷史"
@ -558,12 +556,12 @@ useObjectStorage: "使用物件儲存"
objectStorageBaseUrl: "Base URL"
objectStorageBaseUrlDesc: "用於引用的 URL。如果您使用的是 CDN 或反向代理,請指定其 URL例如 S3https://<bucket>.s3.amazonaws.com、GCShttps://storage.googleapis.com/<bucket>)。"
objectStorageBucket: "儲存空間Bucket"
objectStorageBucketDesc: "請填寫所用服務的儲存空間Bucket名稱。 "
objectStorageBucketDesc: "請填寫所用服務的儲存Bucket名稱。 "
objectStoragePrefix: "前綴"
objectStoragePrefixDesc: "它儲存在此前綴目錄下。"
objectStorageEndpoint: "端點Endpoint"
objectStorageEndpointDesc: "如使用 AWS S3請留空。如使用其他服務請按照其說明文件以「<host>」或「<host>:<port>」的形式設定端點Endpoint。"
objectStorageRegion: "Region"
objectStorageRegion: "Region"
objectStorageRegionDesc: "請填寫一個分區例如「xx-east-1」。 如果您使用的服務不設分區請留空或填寫「us-east-1」。"
objectStorageUseSSL: "使用 SSL"
objectStorageUseSSLDesc: "請在不使用 https 連接 API 時關閉"
@ -586,7 +584,7 @@ popout: "彈出式視窗"
volume: "音量"
masterVolume: "主音量"
notUseSound: "關閉音效"
useSoundOnlyWhenActive: "瀏覽器在前景運作時Misskey 才會發出音效"
useSoundOnlyWhenActive: "僅在 Misskey 於前景運作時發出音效"
details: "詳細資訊"
renoteDetails: "轉發貼文的細節"
chooseEmoji: "選擇您的表情符號"
@ -681,7 +679,7 @@ smtpHost: "主機"
smtpPort: "埠"
smtpUser: "使用者名稱"
smtpPass: "密碼"
emptyToDisableSmtpAuth: "留空使用者名稱和密碼以關閉SMTP驗證。"
emptyToDisableSmtpAuth: "將使用者名稱和密碼留空以關閉 SMTP 驗證。"
smtpSecure: "在 SMTP 連接中使用隱式 SSL/TLS"
smtpSecureInfo: "使用 STARTTLS 時關閉。"
testEmail: "測試郵件發送"
@ -698,6 +696,7 @@ userSaysSomethingAbout: "{name} 說了一些關於「{word}」的話"
makeActive: "啟用"
display: "檢視"
copy: "複製"
copiedToClipboard: "已複製到剪貼簿"
metrics: "指標"
overview: "概覽"
logs: "日誌"
@ -711,7 +710,7 @@ useGlobalSetting: "使用全域設定"
useGlobalSettingDesc: "啟用時,將使用帳戶通知設定。停用時,則可以單獨設定。"
other: "其他"
regenerateLoginToken: "重新產生登入權杖"
regenerateLoginTokenDescription: "重新產生用於登入的內部權杖。一般情況下是不需要這樣做的。重新產生後,所有裝置將會被登出。"
regenerateLoginTokenDescription: "重新產生用於登入的內部權杖。通常不需要使用此功能。重新產生後,所有裝置都將被登出。"
theKeywordWhenSearchingForCustomEmoji: "這是搜尋自訂表情符號時的關鍵字"
setMultipleBySeparatingWithSpace: "您可以使用空格分隔多個項目。"
fileIdOrUrl: "檔案 ID 或 URL"
@ -745,7 +744,7 @@ unclip: "解除摘錄"
confirmToUnclipAlreadyClippedNote: "此貼文已包含在摘錄「{name}」中。 你想將貼文從這個摘錄中排除嗎?"
public: "公開"
private: "私密"
i18nInfo: "Misskey 已被志願者們翻譯成各種語言版本。您可以瀏覽 {link} 幫助翻譯。"
i18nInfo: "Misskey 已被志願者們翻譯成各種語言版本。您可以前往 {link} 以協助翻譯。"
manageAccessTokens: "管理存取權杖"
accountInfo: "帳戶資訊"
notesCount: "貼文數量"
@ -765,7 +764,7 @@ driveFilesCount: "雲端硬碟檔案數量"
driveUsage: "雲端硬碟使用量"
noCrawle: "拒絕搜尋引擎索引"
noCrawleDescription: "要求網路搜尋引擎不要索引你的個人資料頁、貼文及頁面等。"
lockedAccountInfo: "即使你通過了追隨者請求,除非你將貼文的可見性設定為 「追隨者」,否則任何人都能看見你的貼文。"
lockedAccountInfo: "即使追隨需要核准,除非你將貼文的可見性設定為 「追隨者」,否則任何人都能看見你的貼文。"
alwaysMarkSensitive: "預設標記檔案為敏感內容"
loadRawImages: "以原始圖檔顯示附件圖檔的縮圖"
disableShowingAnimatedImages: "不播放動態圖檔"
@ -781,7 +780,7 @@ useSystemFont: "使用系統預設的字型"
clips: "摘錄"
experimentalFeatures: "實驗中的功能"
experimental: "實驗性"
thisIsExperimentalFeature: "這是實驗性的功能。可能會有變更規格和不能正常動作的可能性。"
thisIsExperimentalFeature: "這是一項實驗性功能,其行為會隨需要進行調整,也可能無法正常運作。"
developer: "開發者"
makeExplorable: "使自己的帳戶更容易被找到"
makeExplorableDescription: "如果關閉,帳戶將不會被顯示在「探索」頁面中。"
@ -1188,7 +1187,7 @@ forYou: "給您"
currentAnnouncements: "最新公告"
pastAnnouncements: "歷史公告"
youHaveUnreadAnnouncements: "有未讀的公告。"
useSecurityKey: "請按照瀏覽器或裝置上的說明來使用安全金鑰或 Passkey。"
useSecurityKey: "請按照瀏覽器或裝置上的說明來使用安全金鑰或通行金鑰。"
replies: "回覆"
renotes: "轉發"
loadReplies: "閱覽回覆"
@ -1205,9 +1204,9 @@ showRenotes: "顯示其他人的轉發貼文"
edited: "已編輯"
notificationRecieveConfig: "接受通知的設定"
mutualFollow: "互相追隨"
followingOrFollower: "追隨中或追隨者"
followingOrFollower: "追隨中或追隨者"
fileAttachedOnly: "只顯示包含附件的貼文"
showRepliesToOthersInTimeline: "顯示給其他人的回覆"
showRepliesToOthersInTimeline: "在時間軸上顯示給其他人的回覆"
hideRepliesToOthersInTimeline: "在時間軸上隱藏給其他人的回覆"
showRepliesToOthersInTimelineAll: "在時間軸包含追隨中所有人的回覆"
hideRepliesToOthersInTimelineAll: "在時間軸不包含追隨中所有人的回覆"
@ -1247,7 +1246,7 @@ reloadRequiredToApplySettings: "需要重新載入頁面設定才能生效。"
remainingN: "剩餘:{n}"
overwriteContentConfirm: "確定要覆蓋目前的內容嗎?"
seasonalScreenEffect: "隨季節變換畫面的呈現"
decorate: "設置頭像裝飾"
decorate: "裝飾"
addMfmFunction: "插入 MFM 功能語法"
enableQuickAddMfmFunction: "顯示進階 MFM 選擇器"
bubbleGame: "氣泡遊戲"
@ -1274,7 +1273,7 @@ useBackupCode: "使用備用驗證碼"
launchApp: "啟動 APP"
useNativeUIForVideoAudioPlayer: "使用瀏覽器的 UI 播放影片與音訊"
keepOriginalFilename: "保留原始檔名"
keepOriginalFilenameDescription: "如果關閉此設,上傳時檔案名稱會自動替換為隨機字串。"
keepOriginalFilenameDescription: "如果關閉此設,上傳時檔案名稱會自動替換為隨機字串。"
noDescription: "沒有說明文字"
alwaysConfirmFollow: "追隨時總是確認"
inquiry: "聯絡我們"
@ -1291,10 +1290,10 @@ performance: "性能"
modified: "已變更"
discard: "取消"
thereAreNChanges: "有 {n} 處的變更"
signinWithPasskey: "使用密碼金鑰登入"
unknownWebAuthnKey: "未註冊的金鑰。"
passkeyVerificationFailed: "驗證金鑰失敗。"
passkeyVerificationSucceededButPasswordlessLoginDisabled: "雖然驗證金鑰成功,但是無密碼登入的方式是停用的。"
signinWithPasskey: "使用通行金鑰登入"
unknownWebAuthnKey: "未註冊的通行金鑰。"
passkeyVerificationFailed: "驗證通行金鑰失敗。"
passkeyVerificationSucceededButPasswordlessLoginDisabled: "雖然驗證通行金鑰成功,但是無密碼登入的方式是停用的。"
messageToFollower: "給追隨者的訊息"
target: "目標 "
testCaptchaWarning: "此功能用於 CAPTCHA 的測試。<strong>請勿在正式環境中使用。</strong>"
@ -1309,6 +1308,130 @@ availableRoles: "可用角色"
acknowledgeNotesAndEnable: "了解注意事項後再開啟。"
federationSpecified: "此伺服器以白名單聯邦的方式運作。除了管理員指定的伺服器外,它無法與其他伺服器互動。"
federationDisabled: "此伺服器未開啟站台聯邦。無法與其他伺服器上的使用者互動。"
confirmOnReact: "反應時確認"
reactAreYouSure: "用「 {emoji} 」反應嗎?"
markAsSensitiveConfirm: "要將這個媒體設定為敏感嗎?"
unmarkAsSensitiveConfirm: "要解除這個媒體的敏感設定嗎?"
preferences: "環境設定"
accessibility: "輔助工具"
preferencesProfile: "設定檔案"
copyPreferenceId: "複製設定 ID"
resetToDefaultValue: "還原成預設值"
overrideByAccount: "覆寫帳號"
untitled: "無標題"
noName: "沒有名稱"
skip: "跳過"
restore: "還原"
syncBetweenDevices: "裝置之間的同步化"
preferenceSyncConflictTitle: "伺服器上存在設定值"
preferenceSyncConflictText: "已啟用同步的設定項目會將設定值儲存至伺服器,並已找到該設定項目在伺服器上儲存的設定值。請選擇要使用哪個設定值進行覆寫。"
preferenceSyncConflictChoiceServer: "伺服器設定值"
preferenceSyncConflictChoiceDevice: "裝置的設定值"
preferenceSyncConflictChoiceCancel: "取消啟用同步"
paste: "貼上"
emojiPalette: "表情符號調色盤"
postForm: "發文視窗"
textCount: "字數"
information: "關於"
chat: "聊天"
migrateOldSettings: "遷移舊設定資訊"
migrateOldSettings_description: "通常情況下,這會自動進行,但若因某些原因未能順利遷移,您可以手動觸發遷移處理。請注意,當前的設定資訊將會被覆寫。"
compress: "壓縮"
right: "右"
bottom: "下"
top: "上"
embed: "嵌入"
_chat:
noMessagesYet: "尚無訊息"
newMessage: "新訊息"
individualChat: "ㄧ對一聊天室"
individualChat_description: "可以與特定使用者進行一對一的聊天。"
roomChat: "多人聊天室"
roomChat_description: "可以進行多人聊天。\n此外即使是未允許個人聊天的使用者只要對方接受也可以進行聊天。"
createRoom: "建立聊天室"
inviteUserToChat: "邀請使用者開始聊天"
yourRooms: "已建立的聊天室"
joiningRooms: "已加入的聊天室"
invitations: "邀請"
noInvitations: "沒有邀請"
history: "歷史紀錄"
noHistory: "沒有歷史紀錄"
noRooms: "沒有可用的聊天室"
inviteUser: "邀請使用者"
sentInvitations: "已傳送的邀請"
join: "加入"
ignore: "忽視"
leave: "退出聊天室"
members: "成員"
searchMessages: "搜尋聊天訊息"
home: "首頁"
send: "發送"
newline: "換行"
muteThisRoom: "此聊天室已靜音"
deleteRoom: "刪除聊天室"
chatNotAvailableForThisAccountOrServer: "這個伺服器或這個帳號的聊天功能尚未啟用。"
chatNotAvailableInOtherAccount: "對方的帳號無法使用聊天功能。"
cannotChatWithTheUser: "無法與此使用者聊天"
cannotChatWithTheUser_description: "聊天功能目前無法使用,或對方尚未開放聊天功能。"
chatWithThisUser: "聊天"
thisUserAllowsChatOnlyFromFollowers: "此使用者僅接受來自追隨者的聊天訊息。"
thisUserAllowsChatOnlyFromFollowing: "此使用者僅接受自己追隨的使用者傳送聊天訊息。"
thisUserAllowsChatOnlyFromMutualFollowing: "此使用者只接受互相追隨的使用者傳送聊天訊息。"
thisUserNotAllowedChatAnyone: "此使用者不接受來自任何人的聊天訊息。"
chatAllowedUsers: "允許聊天的對象"
chatAllowedUsers_note: "無論此設定為何,您仍可與自己曾發送過聊天訊息的對象進行聊天。"
_chatAllowedUsers:
everyone: "任何人"
followers: "追隨自己的使用者"
following: "只有您追隨的使用者"
mutual: "互相追隨"
none: "無"
_emojiPalette:
palettes: "調色盤"
enableSyncBetweenDevicesForPalettes: "啟用裝置與裝置之間的調色盤同步化"
paletteForMain: "主要使用的調色盤"
paletteForReaction: "反應用的調色盤"
_settings:
driveBanner: "您可以管理和設定雲端硬碟、確認使用量,以及調整上傳檔案時的設定。"
pluginBanner: "可使用外掛擴充用戶端的功能。您可以安裝外掛,實施個別的設定與管理。"
notificationsBanner: "您可以設定從伺服器接收通知的類型和範圍,以及推送通知。"
api: "API"
webhook: "Webhook"
serviceConnection: "服務整合"
serviceConnectionBanner: "您可以管理和設定存取權杖與 Webhooks以便與外部應用程式和服務整合。"
accountData: "帳戶資料"
accountDataBanner: "您可以管理帳戶資料的匯出 / 匯入。"
muteAndBlockBanner: "您可以設定和管理要隱藏的內容,並限制特定使用者的行動。"
accessibilityBanner: "可針對客戶端的視覺和行為進行個人化設定,以達到更佳的使用效果。"
privacyBanner: "您可以調整帳戶的隱私設定,例如內容的可見性、尋找內容的容易程度,以及追隨是否需要核准。"
securityBanner: "您可以設定與帳戶安全性相關的設定,例如密碼、登入方式、驗證應用程式和通行金鑰。"
preferencesBanner: "您可以根據喜好設定用戶端的整體行為。"
appearanceBanner: "您可以根據喜好設定與用戶端外觀和顯示方式相關的設定。"
soundsBanner: "您可以調整用戶端播放的聲音設定。"
timelineAndNote: "時間軸及貼文"
makeEveryTextElementsSelectable: "允許選取所有文字"
makeEveryTextElementsSelectable_description: "啟用此功能後,可能會在某些情境下降低可用性。"
useStickyIcons: "使大頭貼跟隨捲動"
showNavbarSubButtons: "在導覽列顯示輔助按鈕"
ifOn: "開啟時"
ifOff: "關閉時"
enableSyncThemesBetweenDevices: "在裝置之間同步已安裝的主題"
_chat:
showSenderName: "顯示發送者的名稱"
sendOnEnter: "按下 Enter 發送訊息"
_preferencesProfile:
profileName: "設定檔案名稱"
profileNameDescription: "設定一個名稱來識別此裝置。"
profileNameDescription2: "例如:「主要個人電腦」、「智慧型手機」等"
_preferencesBackup:
autoBackup: "自動備份"
restoreFromBackup: "從備份還原"
noBackupsFoundTitle: "找不到備份檔"
noBackupsFoundDescription: "沒有找到自動建立的備份,但如果您手動儲存了備份檔案,則可以匯入並還原。"
selectBackupToRestore: "選擇要還原的備份"
youNeedToNameYourProfileToEnableAutoBackup: "要啟用自動備份,必須設定檔案名稱。"
autoPreferencesBackupIsNotEnabledForThisDevice: "此裝置未啟用自動備份設定。"
backupFound: "找到設定的備份"
_accountSettings:
requireSigninToViewContents: "須登入以顯示內容"
requireSigninToViewContentsDescription1: "必須登入才會顯示您建立的貼文等內容。可望有效防止資訊被爬蟲蒐集。"
@ -1319,6 +1442,7 @@ _accountSettings:
makeNotesHiddenBefore: "隱藏過去的貼文"
makeNotesHiddenBeforeDescription: "啟用此功能後,超過設定的日期和時間或超過設定時間的貼文將僅對自己顯示(私密化)。 如果您再次停用它,貼文的公開狀態也會恢復原狀。"
mayNotEffectForFederatedNotes: "聯邦發送至遠端伺服器的貼文可能會不受影響。"
mayNotEffectSomeSituations: "這些限制已經簡化。它們可能不適用於某些情況,例如在遠端伺服器上檢視或管理時。"
notesHavePassedSpecifiedPeriod: "早於指定時間的貼文"
notesOlderThanSpecifiedDateAndTime: "指定時間和日期之前的貼文"
_abuseUserReport:
@ -1433,7 +1557,7 @@ _initialTutorial:
useCases: "伺服器的服務條款可能會規範特定的貼文需要使用隱藏內容,除此之外也會用在隱藏劇情洩漏與敏感內容的貼文。"
_howToMakeAttachmentsSensitive:
title: "如何標記上傳附件為敏感內容?"
description: "如果伺服器服務條款有規範,又或者不希望上傳附件直接被看見,可以設置為「敏感內容」"
description: "如果伺服器的服務條款有規範,又或者不適合直接展示的附件,請記得加上「敏感」標記。"
tryThisFile: "試試看!把附加在發文表單的圖像檔案標記為敏感內容。"
_exampleNote:
note: "打開納豆的包裝失敗了…"
@ -1467,7 +1591,7 @@ _serverSettings:
inquiryUrlDescription: "指定伺服器運營者的聯絡表單網址,或包含運營者聯絡資訊網頁的網址。"
openRegistration: "允許建立帳戶"
openRegistrationWarning: "開放註冊伴隨著風險。 建議只有在伺服器受到持續監控,並準備好在出現問題時能立即處理的情況下才開放註冊。"
thisSettingWillAutomaticallyOffWhenModeratorsInactive: "為了防止 spam如果一段期間內沒有偵測到審查員活動,此設定將自動關閉。"
thisSettingWillAutomaticallyOffWhenModeratorsInactive: "如果一段期間內沒有偵測到任何審查員活動,此設定將自動關閉,以防止垃圾內容。"
_accountMigration:
moveFrom: "從其他帳戶遷移到這個帳戶"
moveFromSub: "為另一個帳戶建立別名"
@ -1481,7 +1605,7 @@ _accountMigration:
startMigration: "遷移"
migrationConfirm: "確定要將這個帳戶遷移至 {account} 嗎?一旦遷移就無法撤銷,也就無法以原來的狀態使用這個帳戶。\n另外請確認在要遷移到的帳戶已經建立了一個別名。"
movedAndCannotBeUndone: "帳戶已遷移。\n遷移無法撤消。"
postMigrationNote: "將在完成遷移的 24 小時取消追隨所有帳號。\n此帳戶的追隨中/追隨者人數將歸零。由於不會解除粉絲對您的追隨,因此他們仍然可以繼續閱覽此帳戶僅對追隨者公開的貼文。"
postMigrationNote: "將在完成遷移的 24 小時取消追隨所有帳號。\n此帳戶的追隨中/追隨者人數將歸零。由於不會解除粉絲對您的追隨,因此他們仍然可以繼續閱覽此帳戶僅對追隨者公開的貼文。"
movedTo: "要遷移到的帳戶:"
_achievements:
earnedAt: "獲得日期"
@ -1764,6 +1888,8 @@ _role:
descriptionOfIsExplorable: "若開啟則公開角色時間軸。若角色不是公開的,則無法公開時間軸。"
displayOrder: "顯示順序"
descriptionOfDisplayOrder: "數字越大顯示在UI上的越上面。"
preserveAssignmentOnMoveAccount: "將指派狀態承接至轉移後的帳戶"
preserveAssignmentOnMoveAccount_description: "開啟此選項後,當具備此角色的帳戶被移轉時,該角色也會承接至轉移後的帳戶。"
canEditMembersByModerator: "允許編輯審查員的成員"
descriptionOfCanEditMembersByModerator: "如果開啟,管理員與審查員都可以為使用者指派/解除指派該角色。如果關閉,則只有管理員可以執行。"
priority: "優先級"
@ -1798,12 +1924,13 @@ _role:
canHideAds: "不顯示廣告"
canSearchNotes: "可否搜尋貼文"
canUseTranslator: "使用翻譯功能"
avatarDecorationLimit: "頭像裝飾的最大設置量"
avatarDecorationLimit: "頭像可掛上的最大裝飾數量"
canImportAntennas: "允許匯入天線"
canImportBlocking: "允許匯入封鎖名單"
canImportFollowing: "允許匯入追隨名單"
canImportMuting: "允許匯入靜音名單"
canImportUserLists: "允許匯入清單"
canChat: "允許聊天"
_condition:
roleAssignedTo: "手動指派角色完成"
isLocal: "本地使用者"
@ -1957,7 +2084,7 @@ _instanceMute:
instanceMuteDescription: "包括對被靜音伺服器上的使用者的回覆,被設定的伺服器上所有貼文及轉發都會被靜音。"
instanceMuteDescription2: "設定時以換行進行分隔"
title: "將隱藏被設定的伺服器貼文。"
heading: "將伺服器靜音"
heading: "要靜音的伺服器"
_theme:
explore: "探索佈景主題"
install: "安裝佈景主題"
@ -1967,6 +2094,7 @@ _theme:
installed: "{name}已安裝"
installedThemes: "已經安裝的佈景主題"
builtinThemes: "標準佈景主題"
instanceTheme: "伺服器的主題"
alreadyInstalled: "已安裝此佈景主題"
invalid: "佈景主題格式錯誤"
make: "製作佈景主題"
@ -1999,7 +2127,6 @@ _theme:
header: "標題"
navBg: "側邊欄的背景 "
navFg: "側邊欄的文字"
navHoverFg: "側邊欄文字(懸浮) "
navActive: "側邊欄文字(活動)"
navIndicator: "側邊欄指示符"
link: "連結"
@ -2022,17 +2149,15 @@ _theme:
buttonHoverBg: "按鈕背景 (漂浮)"
inputBorder: "輸入框邊框"
driveFolderBg: "雲端硬碟文件夾背景"
wallpaperOverlay: "壁紙覆蓋層"
badge: "徽章"
messageBg: "私訊背景"
accentDarken: "強調色(黑暗)"
accentLighten: "強調色(明亮)"
fgHighlighted: "突顯文字"
_sfx:
note: "貼文"
noteMy: "我的貼文"
notification: "通知"
reaction: "選擇反應時"
chatMessage: "聊天訊息"
_soundSettings:
driveFile: "使用雲端硬碟的音效檔案"
driveFileWarn: "請選擇雲端硬碟中的檔案"
@ -2076,11 +2201,11 @@ _2fa:
setupCompleted: "設定完成"
step4: "從現在開始,任何登入操作都將要求您提供權杖。"
securityKeyNotSupported: "您的瀏覽器不支援安全金鑰。"
registerTOTPBeforeKey: "如要註冊安全金鑰或 Passkey,請先設定驗證應用程式。"
securityKeyInfo: "您可以設定使用支援 FIDO2 的硬體安全金鑰以及裝置上的生物辨識、PIN 碼和密碼等來登入。"
registerSecurityKey: "註冊安全金鑰或 Passkey"
registerTOTPBeforeKey: "如要註冊安全金鑰或通行金鑰,請先設定驗證應用程式。"
securityKeyInfo: "註冊 WebAuthn 衍生的金鑰,例如支援 FIDO2 的硬體安全金鑰、裝置生物識別、PIN 鎖和通行金鑰。"
registerSecurityKey: "註冊安全金鑰或通行金鑰"
securityKeyName: "輸入金鑰名稱"
tapSecurityKey: "按照瀏覽器的說明註冊安全金鑰或 Passkey。"
tapSecurityKey: "按照瀏覽器的說明註冊安全金鑰或通行金鑰。"
removeKey: "刪除安全金鑰"
removeKeyConfirm: "要刪除{name}嗎?"
whyTOTPOnlyRenew: "如果註冊了安全金鑰,則無法解除驗證應用程式的設定。"
@ -2179,6 +2304,8 @@ _permissions:
"read:clip-favorite": "查看摘錄的讚"
"read:federation": "查看站台聯邦的相關資訊"
"write:report-abuse": "檢舉違規行為"
"write:chat": "撰寫或刪除訊息"
"read:chat": "查看聊天訊息"
_auth:
shareAccessTitle: "應用程式的存取權限"
shareAccess: "要授權「“{name}”」存取您的帳戶嗎?"
@ -2302,7 +2429,7 @@ _profile:
avatarDecorationMax: "最多可以設置 {max} 個裝飾。"
followedMessage: "被追隨時的訊息"
followedMessageDescription: "可以設定被追隨時顯示給對方的訊息。"
followedMessageDescriptionForLockedAccount: "如果追隨是需要審核的話,在允許追隨請求之後顯示。"
followedMessageDescriptionForLockedAccount: "如果追隨需要核准的話,將在通過追隨請求之後顯示。"
_exportOrImport:
allNotes: "所有貼文"
favoritedNotes: "「我的最愛」貼文"
@ -2408,7 +2535,7 @@ _pages:
note: "嵌式貼文"
_note:
id: "貼文ID"
idDescription: "您也可以粘貼筆記 URL 並進行設置。 "
idDescription: "您也可以貼上貼文 URL 來進行設定。 "
detailed: "顯示詳細內容"
_relayStatus:
requesting: "等待核准"
@ -2422,11 +2549,12 @@ _notification:
youRenoted: "{name} 轉發了你的貼文"
youWereFollowed: "您有新的追隨者"
youReceivedFollowRequest: "您有新的追隨請求"
yourFollowRequestAccepted: "您的追隨請求已通過"
yourFollowRequestAccepted: "您的追隨請求已被核准"
pollEnded: "問卷調查已產生結果"
newNote: "新的貼文"
unreadAntennaNote: "天線 {name}"
roleAssigned: "已授予角色"
chatRoomInvitationReceived: "您被邀請加入聊天室"
emptyPushNotificationMessage: "推送通知已更新"
achievementEarned: "獲得成就"
testNotification: "通知測試"
@ -2440,6 +2568,8 @@ _notification:
flushNotification: "重置通知歷史紀錄"
exportOfXCompleted: "{x} 的匯出已完成。"
login: "已登入"
createToken: "已產生存取權杖"
createTokenDescription: "如果您不知道,請透過「{text}」刪除存取權杖。"
_types:
all: "全部 "
note: "使用者的最新貼文"
@ -2453,9 +2583,11 @@ _notification:
receiveFollowRequest: "已收到追隨請求"
followRequestAccepted: "追隨請求已接受"
roleAssigned: "已授予角色"
chatRoomInvitationReceived: "已被邀請加入聊天室"
achievementEarned: "獲得成就"
exportCompleted: "已完成匯出。"
login: "登入"
createToken: "建立存取權杖"
test: "通知測試"
app: "應用程式通知"
_actions:
@ -2465,6 +2597,9 @@ _notification:
_deck:
alwaysShowMainColumn: "總是顯示主欄"
columnAlign: "對齊欄位"
columnGap: "欄與欄之間的邊距"
deckMenuPosition: "多欄模式的選單位置"
navbarPosition: "導覽列位置"
addColumn: "新增欄位"
newNoteNotificationSettings: "新貼文通知的設定"
configureColumn: "欄位的設定"
@ -2483,6 +2618,7 @@ _deck:
useSimpleUiForNonRootPages: "用簡易介面顯示非根頁面"
usedAsMinWidthWhenFlexible: "如果啟用「自動調整寬度」,此為最小寬度"
flexible: "自動調整寬度"
enableSyncBetweenDevicesForProfiles: "啟用裝置與裝置之間的設定檔資料同步化"
_columns:
main: "主列"
widgets: "小工具"
@ -2590,6 +2726,8 @@ _moderationLogTypes:
deletePage: "刪除頁面"
deleteFlash: "刪除 Play"
deleteGalleryPost: "刪除相簿的貼文"
deleteChatRoom: "刪除聊天室"
updateProxyAccountDescription: "更新代理帳戶的說明"
_fileViewer:
title: "檔案詳細資訊"
type: "檔案類型 "
@ -2603,10 +2741,8 @@ _externalResourceInstaller:
checkVendorBeforeInstall: "安裝前請確認提供者是可信賴的。"
_plugin:
title: "要安裝此外掛嘛?"
metaTitle: "外掛資訊"
_theme:
title: "要安裝此佈景主題嗎?"
metaTitle: "佈景主題資訊"
_meta:
base: "基本配色方案"
_vendorInfo:
@ -2655,7 +2791,7 @@ _dataSaver:
_hemisphere:
N: "北半球"
S: "南半球"
caption: "在某些客戶端的設定中,用於判斷季節。"
caption: "某些客戶端的設定會用此來判斷季節。"
_reversi:
reversi: "黑白棋"
gameSettings: "對弈設定"
@ -2822,8 +2958,6 @@ _remoteLookupErrors:
_responseInvalid:
title: "回應不正確"
description: "雖然能夠與這個伺服器通訊,但是取得的資料不正確。"
_responseInvalidIdHostNotMatch:
description: "輸入的 URI 的網域與最終取得的 URI 的網域不同。 如果您是透過第三方伺服器查詢遠端內容,請使用可在原始伺服器上取得的 URI 再次查詢。"
_noSuchObject:
title: "查無項目"
description: "無法找到所要求的資源,請再次檢查 URI。"
@ -2840,3 +2974,23 @@ _captcha:
_unknown:
title: "CAPTCHA 錯誤"
text: "發生了意外的錯誤。"
_bootErrors:
title: "載入失敗"
serverError: "如果稍等片刻並重新載入後問題仍然存在,請聯絡您的伺服器管理員並提供以下的錯誤 ID。"
solution: "執行以下操作或許可以解決問題。"
solution1: "將瀏覽器和作業系統更新至最新版本"
solution2: "停用廣告攔截器"
solution3: "清除瀏覽器的快取"
solution4: "Tor 瀏覽器)將 dom.webaudio.enabled 設為 true"
otherOption: "其他選項"
otherOption1: "刪除用戶端設定和快取"
otherOption2: "啟動簡易用戶端"
otherOption3: "啟動修復工具"
_search:
searchScopeAll: "全部"
searchScopeLocal: "本地"
searchScopeServer: "指定伺服器"
searchScopeUser: "指定使用者"
pleaseEnterServerHost: "請輸入伺服器的主機名稱"
pleaseSelectUser: "請選擇使用者"
serverHostPlaceholder: "例misskey.example.com"

View file

@ -1,6 +1,6 @@
{
"name": "sharkey",
"version": "2025.3.0-dev",
"version": "2025.4.0-rc.0",
"codename": "shonk",
"repository": {
"type": "git",
@ -24,12 +24,13 @@
"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",
"build-frontend-search-index": "pnpm --filter frontend build-search-index",
"start": "pnpm check:connect && cd packages/backend && MK_WARNED_ABOUT_CONFIG=true node ./built/boot/entry.js",
"start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/entry.js",
"init": "pnpm migrate",
"migrate": "cd packages/backend && pnpm migrate",
"revert": "cd packages/backend && pnpm revert",
"check:connect": "cd packages/backend && pnpm check:connect",
"migrate": "pnpm --filter backend migrate",
"revert": "pnpm --filter backend revert",
"check:connect": "pnpm --filter backend check:connect",
"migrateandstart": "pnpm migrate && pnpm start",
"watch": "pnpm dev",
"dev": "node scripts/dev.mjs",
@ -40,7 +41,7 @@
"cy:open": "pnpm cypress open --browser --e2e --config-file=cypress.config.ts",
"cy:run": "pnpm cypress run",
"e2e": "pnpm start-server-and-test start:test http://localhost:61812 cy:run",
"e2e-dev-container": "cp ./.config/cypress-devcontainer.yml ./.config/test.yml && 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",
"test": "pnpm -r test",
@ -50,34 +51,35 @@
"cleanall": "pnpm clean-all"
},
"resolutions": {
"chokidar": "3.5.3",
"chokidar": "4.0.3",
"lodash": "4.17.21"
},
"dependencies": {
"cssnano": "6.1.2",
"execa": "8.0.1",
"fast-glob": "3.3.2",
"ignore-walk": "6.0.5",
"cssnano": "7.0.6",
"execa": "9.5.2",
"fast-glob": "3.3.3",
"ignore-walk": "7.0.0",
"js-yaml": "4.1.0",
"postcss": "8.4.49",
"tar": "6.2.1",
"terser": "5.36.0",
"typescript": "5.6.3",
"esbuild": "0.24.0",
"glob": "11.0.0"
"postcss": "8.5.3",
"tar": "7.4.3",
"terser": "5.39.0",
"typescript": "5.8.2",
"esbuild": "0.25.0",
"glob": "11.0.1"
},
"optionalDependencies": {
"cypress": "13.15.2"
},
"devDependencies": {
"@misskey-dev/eslint-plugin": "2.0.3",
"@types/node": "22.9.0",
"@typescript-eslint/eslint-plugin": "7.17.0",
"@typescript-eslint/parser": "7.17.0",
"@misskey-dev/eslint-plugin": "2.1.0",
"@types/node": "22.13.10",
"@typescript-eslint/eslint-plugin": "8.27.0",
"@typescript-eslint/parser": "8.27.0",
"cross-env": "7.0.3",
"eslint": "9.14.0",
"globals": "15.12.0",
"eslint": "9.22.0",
"globals": "16.0.0",
"ncp": "2.0.0",
"start-server-and-test": "2.0.8"
"pnpm": "10.6.1",
"start-server-and-test": "2.0.10"
}
}

View file

@ -1,5 +1,5 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"$schema": "https://swc.rs/schema.json",
"jsc": {
"parser": {
"syntax": "typescript",

View file

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

View file

@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class SystemAccounts1740121393164 {
name = 'SystemAccounts1740121393164'
async up(queryRunner) {
await queryRunner.query(`CREATE TABLE "system_account" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "type" character varying(256) NOT NULL, CONSTRAINT "PK_edb56f4aaf9ddd50ee556da97ba" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_41a3c87a37aea616ee459369e1" ON "system_account" ("userId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_c362033aee0ea51011386a5a7e" ON "system_account" ("type") `);
await queryRunner.query(`ALTER TABLE "system_account" ADD CONSTRAINT "FK_41a3c87a37aea616ee459369e12" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
const instanceActor = await queryRunner.query(`SELECT "id" FROM "user" WHERE "username" = 'instance.actor'`);
if (instanceActor.length > 0) {
await queryRunner.query(`INSERT INTO "system_account" ("id", "userId", "type") VALUES ('${instanceActor[0].id}', '${instanceActor[0].id}', 'actor')`);
}
const relayActor = await queryRunner.query(`SELECT "id" FROM "user" WHERE "username" = 'relay.actor'`);
if (relayActor.length > 0) {
await queryRunner.query(`INSERT INTO "system_account" ("id", "userId", "type") VALUES ('${relayActor[0].id}', '${relayActor[0].id}', 'relay')`);
}
const meta = await queryRunner.query(`SELECT "proxyAccountId" FROM "meta" ORDER BY "id" DESC LIMIT 1`);
if (!meta && meta.length >= 1 && meta[0].proxyAccountId) {
await queryRunner.query(`INSERT INTO "system_account" ("id", "userId", "type") VALUES ('${meta[0].proxyAccountId}', '${meta[0].proxyAccountId}', 'proxy')`);
}
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "system_account" DROP CONSTRAINT "FK_41a3c87a37aea616ee459369e12"`);
await queryRunner.query(`DROP INDEX "public"."IDX_c362033aee0ea51011386a5a7e"`);
await queryRunner.query(`DROP INDEX "public"."IDX_41a3c87a37aea616ee459369e1"`);
await queryRunner.query(`DROP TABLE "system_account"`);
}
}

View file

@ -0,0 +1,22 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class SystemAccounts21740129169650 {
name = 'SystemAccounts21740129169650'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP CONSTRAINT "FK_ab1bc0c1e209daa77b8e8d212ad"`);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "proxyAccountId"`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "proxyAccountId" character varying(32)`);
const proxyAccountId = await queryRunner.query(`SELECT "userId" FROM "system_account" WHERE "type" = 'proxy' ORDER BY "id" DESC LIMIT 1`);
if (proxyAccountId && proxyAccountId.length >= 1) {
await queryRunner.query(`UPDATE "meta" SET "proxyAccountId" = '${proxyAccountId[0].userId}'`);
}
await queryRunner.query(`ALTER TABLE "meta" ADD CONSTRAINT "FK_ab1bc0c1e209daa77b8e8d212ad" FOREIGN KEY ("proxyAccountId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
}
}

View file

@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class SystemAccounts31740133121105 {
name = 'SystemAccounts31740133121105'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "rootUserId" character varying(32)`);
await queryRunner.query(`ALTER TABLE "meta" ADD CONSTRAINT "FK_c80e4079d632f95eac06a9d28cc" FOREIGN KEY ("rootUserId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
const users = await queryRunner.query(`SELECT "id" FROM "user" WHERE "isRoot" = true LIMIT 1`);
if (users.length > 0) {
await queryRunner.query(`UPDATE "meta" SET "rootUserId" = $1`, [users[0].id]);
}
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP CONSTRAINT "FK_c80e4079d632f95eac06a9d28cc"`);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "rootUserId"`);
}
}

View file

@ -0,0 +1,35 @@
import { loadConfig } from '../built/config.js';
export class AddUnsignedFetch1740162088574 {
name = 'AddUnsignedFetch1740162088574'
async up(queryRunner) {
// meta.allowUnsignedFetch
await queryRunner.query(`CREATE TYPE "public"."meta_allowunsignedfetch_enum" AS ENUM('never', 'always', 'essential')`);
await queryRunner.query(`ALTER TABLE "meta" ADD "allowUnsignedFetch" "public"."meta_allowunsignedfetch_enum" NOT NULL DEFAULT 'always'`);
// user.allowUnsignedFetch
await queryRunner.query(`CREATE TYPE "public"."user_allowunsignedfetch_enum" AS ENUM('never', 'always', 'essential', 'staff')`);
await queryRunner.query(`ALTER TABLE "user" ADD "allowUnsignedFetch" "public"."user_allowunsignedfetch_enum" NOT NULL DEFAULT 'staff'`);
// Special one-time migration: allow unauthorized fetch for system accounts
await queryRunner.query(`UPDATE "user" SET "allowUnsignedFetch" = 'always' WHERE "username" LIKE '%.%' AND "host" IS null`);
// Special one-time migration: convert legacy config "" to meta setting ""
const config = await loadConfig();
if (config.checkActivityPubGetSignature) {
// noinspection SqlWithoutWhere
await queryRunner.query(`UPDATE "meta" SET "allowUnsignedFetch" = 'never'`);
}
}
async down(queryRunner) {
// user.allowUnsignedFetch
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "allowUnsignedFetch"`);
await queryRunner.query(`DROP TYPE "public"."user_allowunsignedfetch_enum"`);
// meta.allowUnsignedFetch
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "allowUnsignedFetch"`);
await queryRunner.query(`DROP TYPE "public"."meta_allowunsignedfetch_enum"`);
}
}

View file

@ -0,0 +1,17 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class SystemAccounts41740993126937 {
name = 'SystemAccounts41740993126937'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "isRoot"`);
}
async down(queryRunner) {
// down 実行時は isRoot = true のユーザーが存在しなくなるため手動で対応する必要あり
await queryRunner.query(`ALTER TABLE "user" ADD "isRoot" boolean NOT NULL DEFAULT false`);
}
}

View file

@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class SystemAccounts1741279404074 {
name = 'SystemAccounts1741279404074'
async up(queryRunner) {
const instanceActor = await queryRunner.query(`SELECT "id" FROM "user" WHERE "username" = 'instance.actor' AND "host" IS NULL AND "id" NOT IN (SELECT "userId" FROM "system_account" WHERE "type" = 'actor')`);
if (instanceActor.length > 0) {
console.warn('instance.actor was incorrect, updating...');
await queryRunner.query(`UPDATE "system_account" SET "id" = '${instanceActor[0].id}', "userId" = '${instanceActor[0].id}' WHERE "type" = 'actor'`);
}
const relayActor = await queryRunner.query(`SELECT "id" FROM "user" WHERE "username" = 'relay.actor' AND "host" IS NULL AND "id" NOT IN (SELECT "userId" FROM "system_account" WHERE "type" = 'relay')`);
if (relayActor.length > 0) {
console.warn('relay.actor was incorrect, updating...');
await queryRunner.query(`UPDATE "system_account" SET "id" = '${relayActor[0].id}', "userId" = '${relayActor[0].id}' WHERE "type" = 'relay'`);
}
}
async down(queryRunner) {
// fixup migration, no down migration
}
}

View file

@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class UserFeaturedFixup1741424411879 {
name = 'UserFeaturedFixup1741424411879'
async up(queryRunner) {
await queryRunner.query(`CREATE OR REPLACE FUNCTION pg_temp.extract_ap_id(text) RETURNS text AS $$
SELECT
CASE
WHEN $1 ~ '^https?://' THEN $1
WHEN $1 LIKE '{%' THEN COALESCE(jsonb_extract_path_text($1::jsonb, 'id'), null)
ELSE null
END;
$$ LANGUAGE sql IMMUTABLE;`);
// "host" is NOT NULL is not needed but just in case add it to prevent overwriting irreplaceable data
await queryRunner.query(`UPDATE "user" SET "featured" = pg_temp.extract_ap_id("featured") WHERE "host" IS NOT NULL`);
}
async down(queryRunner) {
// fixup migration, no down migration
}
}

View file

@ -0,0 +1,46 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class Chat1742203321812 {
name = 'Chat1742203321812'
async up(queryRunner) {
await queryRunner.query(`CREATE TABLE "chat_room" ("id" character varying(32) NOT NULL, "name" character varying(256) NOT NULL, "ownerId" character varying(32) NOT NULL, CONSTRAINT "PK_8aa3a52cf74c96469f0ef9fbe3e" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_f0d8ad64243fa2ca2800da0dfd" ON "chat_room" ("ownerId") `);
await queryRunner.query(`CREATE TABLE "chat_message" ("id" character varying(32) NOT NULL, "fromUserId" character varying(32) NOT NULL, "toUserId" character varying(32), "toRoomId" character varying(32), "text" character varying(4096), "uri" character varying(512), "reads" character varying(32) array NOT NULL DEFAULT '{}', "fileId" character varying(32), "reactions" character varying(1024) array NOT NULL DEFAULT '{}', CONSTRAINT "PK_3cc0d85193aade457d3077dd06b" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_79a26e7a4d9afa5e4fc05f134e" ON "chat_message" ("fromUserId") `);
await queryRunner.query(`CREATE INDEX "IDX_25e097b51d7622c249452c6f75" ON "chat_message" ("toUserId") `);
await queryRunner.query(`CREATE INDEX "IDX_f006b8a76efd1abf9f221c175c" ON "chat_message" ("toRoomId") `);
await queryRunner.query(`CREATE TABLE "chat_room_membership" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "roomId" character varying(32) NOT NULL, CONSTRAINT "PK_2bd59c741e571b283c048beb69a" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_d99c5279460fb77ef58c596ce5" ON "chat_room_membership" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_c25143ebab714e930aeca1c0e8" ON "chat_room_membership" ("roomId") `);
await queryRunner.query(`ALTER TABLE "chat_room" ADD CONSTRAINT "FK_f0d8ad64243fa2ca2800da0dfd6" FOREIGN KEY ("ownerId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "chat_message" ADD CONSTRAINT "FK_79a26e7a4d9afa5e4fc05f134ed" FOREIGN KEY ("fromUserId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "chat_message" ADD CONSTRAINT "FK_25e097b51d7622c249452c6f757" FOREIGN KEY ("toUserId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "chat_message" ADD CONSTRAINT "FK_f006b8a76efd1abf9f221c175ce" FOREIGN KEY ("toRoomId") REFERENCES "chat_room"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "chat_message" ADD CONSTRAINT "FK_fd0f9a4879430239715ad4f8e2a" FOREIGN KEY ("fileId") REFERENCES "drive_file"("id") ON DELETE SET NULL ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "chat_room_membership" ADD CONSTRAINT "FK_d99c5279460fb77ef58c596ce51" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "chat_room_membership" ADD CONSTRAINT "FK_c25143ebab714e930aeca1c0e8d" FOREIGN KEY ("roomId") REFERENCES "chat_room"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "chat_room_membership" DROP CONSTRAINT "FK_c25143ebab714e930aeca1c0e8d"`);
await queryRunner.query(`ALTER TABLE "chat_room_membership" DROP CONSTRAINT "FK_d99c5279460fb77ef58c596ce51"`);
await queryRunner.query(`ALTER TABLE "chat_message" DROP CONSTRAINT "FK_fd0f9a4879430239715ad4f8e2a"`);
await queryRunner.query(`ALTER TABLE "chat_message" DROP CONSTRAINT "FK_f006b8a76efd1abf9f221c175ce"`);
await queryRunner.query(`ALTER TABLE "chat_message" DROP CONSTRAINT "FK_25e097b51d7622c249452c6f757"`);
await queryRunner.query(`ALTER TABLE "chat_message" DROP CONSTRAINT "FK_79a26e7a4d9afa5e4fc05f134ed"`);
await queryRunner.query(`ALTER TABLE "chat_room" DROP CONSTRAINT "FK_f0d8ad64243fa2ca2800da0dfd6"`);
await queryRunner.query(`DROP INDEX "public"."IDX_c25143ebab714e930aeca1c0e8"`);
await queryRunner.query(`DROP INDEX "public"."IDX_d99c5279460fb77ef58c596ce5"`);
await queryRunner.query(`DROP TABLE "chat_room_membership"`);
await queryRunner.query(`DROP INDEX "public"."IDX_f006b8a76efd1abf9f221c175c"`);
await queryRunner.query(`DROP INDEX "public"."IDX_25e097b51d7622c249452c6f75"`);
await queryRunner.query(`DROP INDEX "public"."IDX_79a26e7a4d9afa5e4fc05f134e"`);
await queryRunner.query(`DROP TABLE "chat_message"`);
await queryRunner.query(`DROP INDEX "public"."IDX_f0d8ad64243fa2ca2800da0dfd"`);
await queryRunner.query(`DROP TABLE "chat_room"`);
}
}

View file

@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class Chat21742608337548 {
name = 'Chat21742608337548'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "user" ADD "chatScope" character varying(128) NOT NULL DEFAULT 'mutual'`);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_185b6b5afa707b5d36d1ce3144" ON "chat_room_membership" ("userId", "roomId") `);
}
async down(queryRunner) {
await queryRunner.query(`DROP INDEX "public"."IDX_185b6b5afa707b5d36d1ce3144"`);
await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "chatScope"`);
}
}

View file

@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class Chat31742617546147 {
name = 'Chat31742617546147'
async up(queryRunner) {
await queryRunner.query(`CREATE TABLE "chat_approval" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "otherId" character varying(32) NOT NULL, CONSTRAINT "PK_fbbb95d60acf5c85388345b5f5d" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_530257863e1381a7f2f1d3282f" ON "chat_approval" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_b1d46037f23d170da5c05fdf75" ON "chat_approval" ("otherId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_12c4768a2f706fc267f2078903" ON "chat_approval" ("userId", "otherId") `);
await queryRunner.query(`ALTER TABLE "chat_approval" ADD CONSTRAINT "FK_530257863e1381a7f2f1d3282fe" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "chat_approval" ADD CONSTRAINT "FK_b1d46037f23d170da5c05fdf755" FOREIGN KEY ("otherId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "chat_approval" DROP CONSTRAINT "FK_b1d46037f23d170da5c05fdf755"`);
await queryRunner.query(`ALTER TABLE "chat_approval" DROP CONSTRAINT "FK_530257863e1381a7f2f1d3282fe"`);
await queryRunner.query(`DROP INDEX "public"."IDX_12c4768a2f706fc267f2078903"`);
await queryRunner.query(`DROP INDEX "public"."IDX_b1d46037f23d170da5c05fdf75"`);
await queryRunner.query(`DROP INDEX "public"."IDX_530257863e1381a7f2f1d3282f"`);
await queryRunner.query(`DROP TABLE "chat_approval"`);
}
}

View file

@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class Chat41742707840715 {
name = 'Chat41742707840715'
async up(queryRunner) {
await queryRunner.query(`CREATE TABLE "chat_room_invitation" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "roomId" character varying(32) NOT NULL, CONSTRAINT "PK_9d489521a312dd28225672de2dc" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_8552bb38e7ed038c5bdd398a38" ON "chat_room_invitation" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_5f265075b215fc390a57523b12" ON "chat_room_invitation" ("roomId") `);
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_044f2a7962b8ee5bbfaa02e8a3" ON "chat_room_invitation" ("userId", "roomId") `);
await queryRunner.query(`ALTER TABLE "chat_room_invitation" ADD CONSTRAINT "FK_8552bb38e7ed038c5bdd398a384" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "chat_room_invitation" ADD CONSTRAINT "FK_5f265075b215fc390a57523b12a" FOREIGN KEY ("roomId") REFERENCES "chat_room"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "chat_room_invitation" DROP CONSTRAINT "FK_5f265075b215fc390a57523b12a"`);
await queryRunner.query(`ALTER TABLE "chat_room_invitation" DROP CONSTRAINT "FK_8552bb38e7ed038c5bdd398a384"`);
await queryRunner.query(`DROP INDEX "public"."IDX_044f2a7962b8ee5bbfaa02e8a3"`);
await queryRunner.query(`DROP INDEX "public"."IDX_5f265075b215fc390a57523b12"`);
await queryRunner.query(`DROP INDEX "public"."IDX_8552bb38e7ed038c5bdd398a38"`);
await queryRunner.query(`DROP TABLE "chat_room_invitation"`);
}
}

View file

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

View file

@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class Chat61742795111958 {
name = 'Chat61742795111958'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "chat_room" ADD "description" character varying(2048) NOT NULL DEFAULT ''`);
await queryRunner.query(`ALTER TABLE "chat_room" ADD "isArchived" boolean NOT NULL DEFAULT false`);
await queryRunner.query(`ALTER TABLE "chat_room_membership" ADD "isMuted" boolean NOT NULL DEFAULT false`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "chat_room_membership" DROP COLUMN "isMuted"`);
await queryRunner.query(`ALTER TABLE "chat_room" DROP COLUMN "isArchived"`);
await queryRunner.query(`ALTER TABLE "chat_room" DROP COLUMN "description"`);
}
}

View file

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

View file

@ -37,18 +37,18 @@
},
"optionalDependencies": {
"@swc/core-android-arm64": "1.3.11",
"@swc/core-darwin-arm64": "1.3.56",
"@swc/core-darwin-x64": "1.3.56",
"@swc/core-darwin-arm64": "1.11.11",
"@swc/core-darwin-x64": "1.11.11",
"@swc/core-freebsd-x64": "1.3.11",
"@swc/core-linux-arm-gnueabihf": "1.3.56",
"@swc/core-linux-arm64-gnu": "1.3.56",
"@swc/core-linux-arm64-musl": "1.3.56",
"@swc/core-linux-x64-gnu": "1.3.56",
"@swc/core-linux-x64-musl": "1.3.56",
"@swc/core-win32-arm64-msvc": "1.3.56",
"@swc/core-win32-ia32-msvc": "1.3.56",
"@swc/core-win32-x64-msvc": "1.3.56",
"bufferutil": "4.0.7",
"@swc/core-linux-arm-gnueabihf": "1.11.11",
"@swc/core-linux-arm64-gnu": "1.11.11",
"@swc/core-linux-arm64-musl": "1.11.11",
"@swc/core-linux-x64-gnu": "1.11.11",
"@swc/core-linux-x64-musl": "1.11.11",
"@swc/core-win32-arm64-msvc": "1.11.11",
"@swc/core-win32-ia32-msvc": "1.11.11",
"@swc/core-win32-x64-msvc": "1.11.11",
"bufferutil": "4.0.9",
"slacc-android-arm-eabi": "0.0.10",
"slacc-android-arm64": "0.0.10",
"slacc-darwin-arm64": "0.0.10",
@ -62,36 +62,33 @@
"slacc-linux-x64-musl": "0.0.10",
"slacc-win32-arm64-msvc": "0.0.10",
"slacc-win32-x64-msvc": "0.0.10",
"utf-8-validate": "6.0.3"
"utf-8-validate": "6.0.5"
},
"dependencies": {
"@aws-sdk/client-s3": "3.620.0",
"@aws-sdk/lib-storage": "3.620.0",
"@bull-board/api": "6.5.0",
"@bull-board/fastify": "6.5.0",
"@bull-board/ui": "6.5.0",
"@aws-sdk/client-s3": "3.772.0",
"@aws-sdk/lib-storage": "3.772.0",
"@discordapp/twemoji": "15.1.0",
"@fastify/accepts": "5.0.1",
"@fastify/cookie": "11.0.1",
"@fastify/cors": "10.0.1",
"@fastify/express": "4.0.1",
"@fastify/http-proxy": "10.0.1",
"@fastify/multipart": "9.0.1",
"@fastify/static": "8.0.2",
"@fastify/view": "10.0.1",
"@fastify/accepts": "5.0.2",
"@fastify/cookie": "11.0.2",
"@fastify/cors": "10.1.0",
"@fastify/express": "4.0.2",
"@fastify/http-proxy": "10.0.2",
"@fastify/multipart": "9.0.3",
"@fastify/static": "8.1.1",
"@fastify/view": "10.0.2",
"@misskey-dev/sharp-read-bmp": "1.2.0",
"@misskey-dev/summaly": "5.1.0",
"@nestjs/common": "10.4.7",
"@nestjs/core": "10.4.7",
"@nestjs/testing": "10.4.7",
"@misskey-dev/summaly": "5.2.0",
"@nestjs/common": "11.0.12",
"@nestjs/core": "11.0.12",
"@nestjs/testing": "11.0.12",
"@peertube/http-signature": "1.7.0",
"@sentry/node": "8.38.0",
"@sentry/profiling-node": "8.38.0",
"@simplewebauthn/server": "10.0.1",
"@sinonjs/fake-timers": "11.2.2",
"@sentry/node": "8.55.0",
"@sentry/profiling-node": "8.55.0",
"@simplewebauthn/server": "12.0.0",
"@sinonjs/fake-timers": "11.3.1",
"@smithy/node-http-handler": "2.5.0",
"@swc/cli": "0.3.12",
"@swc/core": "1.9.2",
"@swc/cli": "0.6.0",
"@swc/core": "1.11.11",
"@transfem-org/sfm-js": "0.24.6",
"@twemoji/parser": "15.1.1",
"@types/psl": "^1.1.3",
@ -103,11 +100,11 @@
"bcryptjs": "2.4.3",
"blurhash": "2.0.5",
"body-parser": "1.20.3",
"bullmq": "5.26.1",
"bullmq": "5.44.1",
"cacheable-lookup": "7.0.0",
"canvas": "^3.1.0",
"cbor": "9.0.2",
"chalk": "5.3.0",
"chalk": "5.4.1",
"chalk-template": "1.1.0",
"chokidar": "3.6.0",
"cli-highlight": "2.1.11",
@ -116,48 +113,48 @@
"date-fns": "2.30.0",
"deep-email-validator": "0.1.21",
"fast-xml-parser": "4.4.1",
"fastify": "5.0.0",
"fastify": "5.2.1",
"fastify-multer": "^2.0.3",
"fastify-raw-body": "5.0.0",
"feed": "4.2.2",
"file-type": "19.6.0",
"fluent-ffmpeg": "2.1.3",
"form-data": "4.0.1",
"form-data": "4.0.2",
"glob": "11.0.0",
"got": "14.4.4",
"happy-dom": "15.11.4",
"got": "14.4.6",
"happy-dom": "16.8.1",
"hpagent": "1.2.0",
"htmlescape": "1.1.1",
"http-link-header": "1.1.3",
"ioredis": "5.4.1",
"ioredis": "5.6.0",
"ip-cidr": "4.0.2",
"ipaddr.js": "2.2.0",
"is-svg": "5.1.0",
"js-yaml": "4.1.0",
"jsdom": "24.1.1",
"jsdom": "26.0.0",
"json5": "2.2.3",
"jsonld": "8.3.2",
"jsonld": "8.3.3",
"jsrsasign": "11.1.0",
"juice": "11.0.0",
"juice": "11.0.1",
"megalodon": "workspace:*",
"meilisearch": "0.45.0",
"meilisearch": "0.49.0",
"microformats-parser": "2.0.2",
"mime-types": "2.1.35",
"misskey-js": "workspace:*",
"misskey-reversi": "workspace:*",
"moment": "^2.30.1",
"ms": "3.0.0-canary.1",
"nanoid": "5.0.8",
"nanoid": "5.1.5",
"nested-property": "4.0.0",
"node-fetch": "3.3.2",
"nodemailer": "6.9.16",
"oauth": "0.10.0",
"nodemailer": "6.10.0",
"oauth": "0.10.2",
"oauth2orize": "1.12.0",
"oauth2orize-pkce": "0.1.2",
"os-utils": "0.0.14",
"otpauth": "9.3.4",
"otpauth": "9.3.6",
"parse5": "7.2.1",
"pg": "8.13.1",
"pg": "8.14.1",
"pkce-challenge": "4.1.0",
"probe-image-size": "7.2.3",
"promise-limit": "2.7.0",
@ -172,31 +169,32 @@
"reflect-metadata": "0.2.2",
"rename": "1.0.4",
"rss-parser": "3.13.0",
"rxjs": "7.8.1",
"sanitize-html": "2.13.1",
"secure-json-parse": "2.7.0",
"rxjs": "7.8.2",
"sanitize-html": "2.15.0",
"secure-json-parse": "3.0.2",
"sharp": "0.33.5",
"slacc": "0.0.10",
"strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0",
"systeminformation": "5.23.5",
"systeminformation": "5.25.11",
"tinycolor2": "1.6.0",
"tmp": "0.2.3",
"tsc-alias": "1.8.10",
"tsc-alias": "1.8.11",
"tsconfig-paths": "4.2.0",
"typeorm": "0.3.20",
"typescript": "5.6.3",
"ulid": "2.3.0",
"typeorm": "0.3.21",
"typescript": "5.8.2",
"ulid": "2.4.0",
"uuid": "^9.0.1",
"vary": "1.1.2",
"web-push": "3.6.7",
"ws": "8.18.0",
"ws": "8.18.1",
"xev": "3.0.2"
},
"devDependencies": {
"@jest/globals": "29.7.0",
"@nestjs/platform-express": "10.4.7",
"@simplewebauthn/types": "10.0.0",
"@nestjs/platform-express": "10.4.15",
"@sentry/vue": "9.8.0",
"@simplewebauthn/types": "12.0.0",
"@swc/jest": "0.2.37",
"@types/accepts": "1.3.7",
"@types/archiver": "6.0.3",
@ -211,15 +209,15 @@
"@types/js-yaml": "4.0.9",
"@types/jsdom": "21.1.7",
"@types/jsonld": "1.5.15",
"@types/jsrsasign": "10.5.14",
"@types/jsrsasign": "10.5.15",
"@types/mime-types": "2.1.4",
"@types/ms": "0.7.34",
"@types/node": "22.9.0",
"@types/nodemailer": "6.4.16",
"@types/node": "22.13.10",
"@types/nodemailer": "6.4.17",
"@types/oauth": "0.9.6",
"@types/oauth2orize": "1.11.5",
"@types/oauth2orize-pkce": "0.1.2",
"@types/pg": "8.11.10",
"@types/pg": "8.11.11",
"@types/proxy-addr": "^2.0.3",
"@types/pug": "2.0.10",
"@types/qrcode": "1.5.5",
@ -235,18 +233,18 @@
"@types/uuid": "^9.0.4",
"@types/vary": "1.1.3",
"@types/web-push": "3.6.4",
"@types/ws": "8.5.13",
"@typescript-eslint/eslint-plugin": "7.17.0",
"@typescript-eslint/parser": "7.17.0",
"aws-sdk-client-mock": "4.0.1",
"@types/ws": "8.18.0",
"@typescript-eslint/eslint-plugin": "8.27.0",
"@typescript-eslint/parser": "8.27.0",
"aws-sdk-client-mock": "4.1.0",
"cross-env": "7.0.3",
"eslint-plugin-import": "2.30.0",
"eslint-plugin-import": "2.31.0",
"execa": "8.0.1",
"fkill": "9.0.0",
"jest": "29.7.0",
"jest-mock": "29.7.0",
"nodemon": "3.1.7",
"pid-port": "1.0.0",
"nodemon": "3.1.9",
"pid-port": "1.0.2",
"simple-oauth2": "5.1.0"
}
}

View file

@ -9,7 +9,7 @@ import { createPostgresDataSource } from '../built/postgres.js';
const config = loadConfig();
// createPostgresDataSource handels primaries and replicas automatically.
// createPostgresDataSource handles primaries and replicas automatically.
// usually, it only opens connections first use, so we force it using
// .initialize()
async function connectToPostgres(){

View file

@ -141,7 +141,7 @@ const $meta: Provider = {
for (const key in body.after) {
(meta as any)[key] = (body.after as any)[key];
}
meta.proxyAccount = null; // joinなカラムは通常取ってこないので
meta.rootUser = null; // joinなカラムは通常取ってこないので
break;
}
default:
@ -178,15 +178,13 @@ export class GlobalModule implements OnApplicationShutdown {
// Wait for all potential DB queries
await allSettled();
// And then disconnect from DB
await Promise.all([
this.db.destroy(),
this.redisClient.disconnect(),
this.redisForPub.disconnect(),
this.redisForSub.disconnect(),
this.redisForTimelines.disconnect(),
this.redisForReactions.disconnect(),
this.redisForRateLimit.disconnect(),
]);
await this.db.destroy();
this.redisClient.disconnect();
this.redisForPub.disconnect();
this.redisForSub.disconnect();
this.redisForTimelines.disconnect();
this.redisForReactions.disconnect();
this.redisForRateLimit.disconnect();
}
async onApplicationShutdown(signal: string): Promise<void> {

View file

@ -8,7 +8,8 @@ import { fileURLToPath } from 'node:url';
import { dirname, resolve } from 'node:path';
import * as yaml from 'js-yaml';
import { globSync } from 'glob';
import * as Sentry from '@sentry/node';
import type * as Sentry from '@sentry/node';
import type * as SentryVue from '@sentry/vue';
import type { RedisOptions } from 'ioredis';
type RedisOptionsSource = Partial<RedisOptions> & {
@ -26,6 +27,7 @@ type RedisOptionsSource = Partial<RedisOptions> & {
*/
type Source = {
url?: string;
altUrls?: string[];
port?: number;
address?: string;
socket?: string;
@ -66,7 +68,12 @@ type Source = {
scope?: 'local' | 'global' | string[];
};
sentryForBackend?: { options: Partial<Sentry.NodeOptions>; enableNodeProfiling: boolean; };
sentryForFrontend?: { options: Partial<Sentry.NodeOptions> };
sentryForFrontend?: {
options: Partial<SentryVue.BrowserOptions> & { dsn: string };
vueIntegration?: SentryVue.VueIntegrationOptions | null;
browserTracingIntegration?: Parameters<typeof SentryVue.browserTracingIntegration>[0] | null;
replayIntegration?: Parameters<typeof SentryVue.replayIntegration>[0] | null;
};
publishTarballInsteadOfProvideRepositoryUrl?: boolean;
@ -77,6 +84,7 @@ type Source = {
proxyBypassHosts?: string[];
allowedPrivateNetworks?: string[];
disallowExternalApRedirect?: boolean;
maxFileSize?: number;
maxNoteLength?: number;
@ -126,8 +134,8 @@ type Source = {
logging?: {
sql?: {
disableQueryTruncation? : boolean,
enableQueryParamLogging? : boolean,
disableQueryTruncation?: boolean,
enableQueryParamLogging?: boolean,
}
}
@ -136,9 +144,11 @@ type Source = {
preSave?: boolean;
maxAge?: number;
};
websocketCompression?: boolean;
};
export type Config = {
export type Config = Tenant & {
url: string;
port: number;
address: string;
@ -177,6 +187,7 @@ export type Config = {
proxySmtp: string | undefined;
proxyBypassHosts: string[] | undefined;
allowedPrivateNetworks: string[] | undefined;
disallowExternalApRedirect: boolean;
maxFileSize: number;
maxNoteLength: number;
maxRemoteNoteLength: number;
@ -200,11 +211,12 @@ export type Config = {
customMOTD: string[] | undefined;
signToActivityPubGet: boolean;
attachLdSignatureForRelays: boolean;
/** @deprecated Use MiMeta.allowUnsignedFetch instead */
checkActivityPubGetSignature: boolean | undefined;
logging?: {
sql?: {
disableQueryTruncation? : boolean,
enableQueryParamLogging? : boolean,
disableQueryTruncation?: boolean,
enableQueryParamLogging?: boolean,
}
}
@ -234,7 +246,12 @@ export type Config = {
redisForReactions: RedisOptions & RedisOptionsSource;
redisForRateLimit: RedisOptions & RedisOptionsSource;
sentryForBackend: { options: Partial<Sentry.NodeOptions>; enableNodeProfiling: boolean; } | undefined;
sentryForFrontend: { options: Partial<Sentry.NodeOptions> } | undefined;
sentryForFrontend: {
options: Partial<SentryVue.BrowserOptions> & { dsn: string };
vueIntegration?: SentryVue.VueIntegrationOptions | null;
browserTracingIntegration?: Parameters<typeof SentryVue.browserTracingIntegration>[0] | null;
replayIntegration?: Parameters<typeof SentryVue.replayIntegration>[0] | null;
} | undefined;
perChannelMaxNoteCacheCount: number;
perUserNotificationsMaxCount: number;
deactivateAntennaThreshold: number;
@ -252,6 +269,22 @@ export type Config = {
preSave: boolean;
maxAge: number;
};
alts: Tenant[];
websocketCompression?: boolean;
};
export type Tenant = {
url: string;
host: string;
hostname: string;
scheme: string;
wsScheme: string;
apiUrl: string;
wsUrl: string;
authUrl: string;
driveUrl: string;
};
export type FulltextSearchProvider = 'sqlLike' | 'sqlPgroonga' | 'meilisearch' | 'sqlTsvector';
@ -319,6 +352,24 @@ export function loadConfig(): Config {
const internalMediaProxy = `${scheme}://${host}/proxy`;
const redis = convertRedisOptions(config.redis, host);
const alts: Tenant[] = config.altUrls?.map(alt => {
const altUrl = tryCreateUrl(alt);
const altHost = altUrl.host;
const altScheme = altUrl.protocol.replace(/:$/, '');
const altWsScheme = altScheme.replace('http', 'ws');
return {
url: alt,
host: altHost,
hostname: altUrl.hostname,
scheme: altScheme,
wsScheme: altWsScheme,
wsUrl: `${altWsScheme}://${altHost}`,
apiUrl: `${altWsScheme}://${altHost}/api`,
authUrl: `${altWsScheme}://${altHost}/auth`,
driveUrl: `${altWsScheme}://${altHost}/files`,
};
}) ?? [];
return {
version,
publishTarballInsteadOfProvideRepositoryUrl: !!config.publishTarballInsteadOfProvideRepositoryUrl,
@ -355,6 +406,7 @@ export function loadConfig(): Config {
proxySmtp: config.proxySmtp,
proxyBypassHosts: config.proxyBypassHosts,
allowedPrivateNetworks: config.allowedPrivateNetworks,
disallowExternalApRedirect: config.disallowExternalApRedirect ?? false,
maxFileSize: config.maxFileSize ?? 262144000,
maxNoteLength: config.maxNoteLength ?? 3000,
maxRemoteNoteLength: config.maxRemoteNoteLength ?? 100000,
@ -400,6 +452,8 @@ export function loadConfig(): Config {
preSave: config.activityLogging?.preSave ?? false,
maxAge: config.activityLogging?.maxAge ?? (1000 * 60 * 60 * 24 * 30),
},
alts,
websocketCompression: config.websocketCompression ?? false,
};
}
@ -478,7 +532,7 @@ function applyEnvOverrides(config: Source) {
}
}
function _step2name(step: string|number): string {
function _step2name(step: string | number): string {
return step.toString().replaceAll(/[^a-z0-9]+/gi, '').toUpperCase();
}
@ -534,7 +588,7 @@ function applyEnvOverrides(config: Source) {
// these are all the settings that can be overridden
_apply_top([['url', 'port', 'address', 'socket', 'chmodSocket', 'disableHsts', 'id', 'dbReplications']]);
_apply_top([['url', 'port', 'address', 'socket', 'chmodSocket', 'disableHsts', 'id', 'dbReplications', 'websocketCompression']]);
_apply_top(['db', ['host', 'port', 'db', 'user', 'pass', 'disableCache']]);
_apply_top(['dbSlaves', Array.from((config.dbSlaves ?? []).keys()), ['host', 'port', 'db', 'user', 'pass']]);
_apply_top([

View file

@ -70,3 +70,9 @@ https://github.com/sindresorhus/file-type/blob/main/supported.js
https://github.com/sindresorhus/file-type/blob/main/core.js
https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers
*/
export const instanceUnsignedFetchOptions = ['never', 'always', 'essential'] as const;
export type InstanceUnsignedFetchOption = (typeof instanceUnsignedFetchOptions)[number];
export const userUnsignedFetchOptions = ['never', 'always', 'essential', 'staff'] as const;
export type UserUnsignedFetchOption = (typeof userUnsignedFetchOptions)[number];

View file

@ -10,9 +10,9 @@ import { bindThis } from '@/decorators.js';
import type { AbuseUserReportsRepository, MiAbuseUserReport, MiUser, UsersRepository } from '@/models/_.js';
import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js';
import { QueueService } from '@/core/QueueService.js';
import { InstanceActorService } from '@/core/InstanceActorService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
import { SystemAccountService } from '@/core/SystemAccountService.js';
import { IdService } from './IdService.js';
@Injectable()
@ -27,7 +27,7 @@ export class AbuseReportService {
private idService: IdService,
private abuseReportNotificationService: AbuseReportNotificationService,
private queueService: QueueService,
private instanceActorService: InstanceActorService,
private systemAccountService: SystemAccountService,
private apRendererService: ApRendererService,
private moderationLogService: ModerationLogService,
) {
@ -136,7 +136,7 @@ export class AbuseReportService {
forwarded: true,
});
const actor = await this.instanceActorService.getInstanceActor();
const actor = await this.systemAccountService.fetch('actor');
const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId });
const flag = this.apRendererService.renderFlag(actor, targetUser.uri!, report.comment);

View file

@ -20,10 +20,11 @@ import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js';
import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { ProxyAccountService } from '@/core/ProxyAccountService.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
import InstanceChart from '@/core/chart/charts/instance.js';
import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js';
import { SystemAccountService } from '@/core/SystemAccountService.js';
import { RoleService } from '@/core/RoleService.js';
@Injectable()
export class AccountMoveService {
@ -58,12 +59,13 @@ export class AccountMoveService {
private apRendererService: ApRendererService,
private apDeliverManagerService: ApDeliverManagerService,
private globalEventService: GlobalEventService,
private proxyAccountService: ProxyAccountService,
private perUserFollowingChart: PerUserFollowingChart,
private federatedInstanceService: FederatedInstanceService,
private instanceChart: InstanceChart,
private relayService: RelayService,
private queueService: QueueService,
private systemAccountService: SystemAccountService,
private roleService: RoleService,
) {
}
@ -123,6 +125,7 @@ export class AccountMoveService {
this.copyBlocking(src, dst),
this.copyMutings(src, dst),
this.deleteScheduledNotes(src),
this.copyRoles(src, dst),
this.updateLists(src, dst),
]);
} catch {
@ -130,11 +133,11 @@ export class AccountMoveService {
}
// follow the new account
const proxy = await this.proxyAccountService.fetch();
const proxy = await this.systemAccountService.fetch('proxy');
const followings = await this.followingsRepository.findBy({
followeeId: src.id,
followerHost: IsNull(), // follower is local
followerId: proxy ? Not(proxy.id) : undefined,
followerId: Not(proxy.id),
});
const followJobs = followings.map(following => ({
from: { id: following.followerId },
@ -220,6 +223,32 @@ export class AccountMoveService {
});
}
@bindThis
public async copyRoles(src: ThinUser, dst: ThinUser): Promise<void> {
// Insert new roles with the same values except userId
// role service may have cache for roles so retrieve roles from service
const [oldRoleAssignments, roles] = await Promise.all([
this.roleService.getUserAssigns(src.id),
this.roleService.getRoles(),
]);
if (oldRoleAssignments.length === 0) return;
// No promise all since the only async operation is writing to the database
for (const oldRoleAssignment of oldRoleAssignments) {
const role = roles.find(x => x.id === oldRoleAssignment.roleId);
if (role == null) continue; // Very unlikely however removing role may cause this case
if (!role.preserveAssignmentOnMoveAccount) continue;
try {
await this.roleService.assign(dst.id, role.id, oldRoleAssignment.expiresAt);
} catch (e) {
if (e instanceof RoleService.AlreadyAssignedError) continue;
throw e;
}
}
}
/**
* Update lists while moving accounts.
* - No removal of the old account from the lists
@ -269,10 +298,8 @@ export class AccountMoveService {
// Have the proxy account follow the new account in the same way as UserListService.push
if (this.userEntityService.isRemoteUser(dst)) {
const proxy = await this.proxyAccountService.fetch();
if (proxy) {
this.queueService.createFollowJob([{ from: { id: proxy.id }, to: { id: dst.id } }]);
}
const proxy = await this.systemAccountService.fetch('proxy');
this.queueService.createFollowJob([{ from: { id: proxy.id }, to: { id: dst.id } }]);
}
}

View file

@ -114,6 +114,8 @@ export class AntennaService implements OnApplicationShutdown {
if (note.visibility === 'specified') return false;
if (note.visibility === 'followers') return false;
if (antenna.hideNotesInSensitiveChannel && note.channel?.isSensitive) return false;
if (antenna.excludeBots && noteUser.isBot) return false;
if (antenna.localOnly && noteUser.host != null) return false;

View file

@ -139,6 +139,24 @@ export class ApLogService {
}
}
/**
* Deletes all logged inbox activities from a user or users
* @param userIds IDs of the users to delete
*/
public async deleteInboxLogs(userIds: string | string[]): Promise<number> {
if (Array.isArray(userIds)) {
const logsDeleted = await this.apInboxLogsRepository.delete({
authUserId: In(userIds),
});
return logsDeleted.affected ?? 0;
} else {
const logsDeleted = await this.apInboxLogsRepository.delete({
authUserId: userIds,
});
return logsDeleted.affected ?? 0;
}
}
/**
* Deletes all expired AP logs and garbage-collects the AP context cache.
* Returns the total number of deleted rows.

View file

@ -5,6 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis';
import { IsNull } from 'typeorm';
import type { BlockingsRepository, FollowingsRepository, MutingsRepository, RenoteMutingsRepository, MiUserProfile, UserProfilesRepository, UsersRepository, MiFollowing } from '@/models/_.js';
import { MemoryKVCache, RedisKVCache } from '@/misc/cache.js';
import type { MiLocalUser, MiUser } from '@/models/User.js';
@ -179,6 +180,13 @@ export class CacheService implements OnApplicationShutdown {
return this.userByIdCache.fetch(userId, () => this.usersRepository.findOneByOrFail({ id: userId }));
}
@bindThis
public async findLocalUserById(userId: MiUser['id']): Promise<MiLocalUser | null> {
return await this.localUserByIdCache.fetchMaybe(userId, async () => {
return await this.usersRepository.findOneBy({ id: userId, host: IsNull() }) as MiLocalUser | null ?? undefined;
}) ?? null;
}
@bindThis
public dispose(): void {
this.redisForSub.off('message', this.onMessage);

View file

@ -47,7 +47,7 @@ export type CaptchaSetting = {
siteKey: string | null;
secretKey: string | null;
}
}
};
export class CaptchaError extends Error {
public readonly code: CaptchaErrorCode;
@ -63,11 +63,11 @@ export class CaptchaError extends Error {
export type CaptchaSaveSuccess = {
success: true;
}
};
export type CaptchaSaveFailure = {
success: false;
error: CaptchaError;
}
};
export type CaptchaSaveResult = CaptchaSaveSuccess | CaptchaSaveFailure;
type CaptchaResponse = {

View file

@ -0,0 +1,891 @@
/*
* 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 { Brackets } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { QueueService } from '@/core/QueueService.js';
import { IdService } from '@/core/IdService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { ChatEntityService } from '@/core/entities/ChatEntityService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { PushNotificationService } from '@/core/PushNotificationService.js';
import { bindThis } from '@/decorators.js';
import type { ChatApprovalsRepository, ChatMessagesRepository, ChatRoomInvitationsRepository, ChatRoomMembershipsRepository, ChatRoomsRepository, MiChatMessage, MiChatRoom, MiChatRoomMembership, MiDriveFile, MiUser, MutingsRepository, UsersRepository } from '@/models/_.js';
import { UserBlockingService } from '@/core/UserBlockingService.js';
import { QueryService } from '@/core/QueryService.js';
import { RoleService } from '@/core/RoleService.js';
import { UserFollowingService } from '@/core/UserFollowingService.js';
import { MiChatRoomInvitation } from '@/models/ChatRoomInvitation.js';
import { Packed } from '@/misc/json-schema.js';
import { sqlLikeEscape } from '@/misc/sql-like-escape.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { emojiRegex } from '@/misc/emoji-regex.js';
import { NotificationService } from '@/core/NotificationService.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
const MAX_ROOM_MEMBERS = 30;
const MAX_REACTIONS_PER_MESSAGE = 100;
const isCustomEmojiRegexp = /^:([\w+-]+)(?:@\.)?:$/;
// TODO: ReactionServiceのやつと共通化
function normalizeEmojiString(x: string) {
const match = emojiRegex.exec(x);
if (match) {
// 合字を含む1つの絵文字
const unicode = match[0];
// 異体字セレクタ除去
return unicode.match('\u200d') ? unicode : unicode.replace(/\ufe0f/g, '');
} else {
throw new Error('invalid emoji');
}
}
@Injectable()
export class ChatService {
constructor(
@Inject(DI.config)
private config: Config,
@Inject(DI.redis)
private redisClient: Redis.Redis,
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
@Inject(DI.chatMessagesRepository)
private chatMessagesRepository: ChatMessagesRepository,
@Inject(DI.chatApprovalsRepository)
private chatApprovalsRepository: ChatApprovalsRepository,
@Inject(DI.chatRoomsRepository)
private chatRoomsRepository: ChatRoomsRepository,
@Inject(DI.chatRoomInvitationsRepository)
private chatRoomInvitationsRepository: ChatRoomInvitationsRepository,
@Inject(DI.chatRoomMembershipsRepository)
private chatRoomMembershipsRepository: ChatRoomMembershipsRepository,
@Inject(DI.mutingsRepository)
private mutingsRepository: MutingsRepository,
private userEntityService: UserEntityService,
private chatEntityService: ChatEntityService,
private idService: IdService,
private globalEventService: GlobalEventService,
private apRendererService: ApRendererService,
private queueService: QueueService,
private pushNotificationService: PushNotificationService,
private notificationService: NotificationService,
private userBlockingService: UserBlockingService,
private queryService: QueryService,
private roleService: RoleService,
private userFollowingService: UserFollowingService,
private customEmojiService: CustomEmojiService,
private moderationLogService: ModerationLogService,
) {
}
@bindThis
public async createMessageToUser(fromUser: { id: MiUser['id']; host: MiUser['host']; }, toUser: MiUser, params: {
text?: string | null;
file?: MiDriveFile | null;
uri?: string | null;
}): Promise<Packed<'ChatMessageLiteFor1on1'>> {
if (fromUser.id === toUser.id) {
throw new Error('yourself');
}
const approvals = await this.chatApprovalsRepository.createQueryBuilder('approval')
.where(new Brackets(qb => { // 自分が相手を許可しているか
qb.where('approval.userId = :fromUserId', { fromUserId: fromUser.id })
.andWhere('approval.otherId = :toUserId', { toUserId: toUser.id });
}))
.orWhere(new Brackets(qb => { // 相手が自分を許可しているか
qb.where('approval.userId = :toUserId', { toUserId: toUser.id })
.andWhere('approval.otherId = :fromUserId', { fromUserId: fromUser.id });
}))
.take(2)
.getMany();
const otherApprovedMe = approvals.some(approval => approval.userId === toUser.id);
const iApprovedOther = approvals.some(approval => approval.userId === fromUser.id);
if (!otherApprovedMe) {
if (toUser.chatScope === 'none') {
throw new Error('recipient is cannot chat (none)');
} else if (toUser.chatScope === 'followers') {
const isFollower = await this.userFollowingService.isFollowing(fromUser.id, toUser.id);
if (!isFollower) {
throw new Error('recipient is cannot chat (followers)');
}
} else if (toUser.chatScope === 'following') {
const isFollowing = await this.userFollowingService.isFollowing(toUser.id, fromUser.id);
if (!isFollowing) {
throw new Error('recipient is cannot chat (following)');
}
} else if (toUser.chatScope === 'mutual') {
const isMutual = await this.userFollowingService.isMutual(fromUser.id, toUser.id);
if (!isMutual) {
throw new Error('recipient is cannot chat (mutual)');
}
}
}
if (!(await this.roleService.getUserPolicies(toUser.id)).canChat) {
throw new Error('recipient is cannot chat (policy)');
}
const blocked = await this.userBlockingService.checkBlocked(toUser.id, fromUser.id);
if (blocked) {
throw new Error('blocked');
}
const message = {
id: this.idService.gen(),
fromUserId: fromUser.id,
toUserId: toUser.id,
text: params.text ? params.text.trim() : null,
fileId: params.file ? params.file.id : null,
reads: [],
uri: params.uri ?? null,
} satisfies Partial<MiChatMessage>;
const inserted = await this.chatMessagesRepository.insertOne(message);
// 相手を許可しておく
if (!iApprovedOther) {
this.chatApprovalsRepository.insertOne({
id: this.idService.gen(),
userId: fromUser.id,
otherId: toUser.id,
});
}
const packedMessage = await this.chatEntityService.packMessageLiteFor1on1(inserted);
if (this.userEntityService.isLocalUser(toUser)) {
const redisPipeline = this.redisClient.pipeline();
redisPipeline.set(`newUserChatMessageExists:${toUser.id}:${fromUser.id}`, message.id);
redisPipeline.sadd(`newChatMessagesExists:${toUser.id}`, `user:${fromUser.id}`);
redisPipeline.exec();
}
if (this.userEntityService.isLocalUser(fromUser)) {
// 自分のストリーム
this.globalEventService.publishChatUserStream(fromUser.id, toUser.id, 'message', packedMessage);
}
if (this.userEntityService.isLocalUser(toUser)) {
// 相手のストリーム
this.globalEventService.publishChatUserStream(toUser.id, fromUser.id, 'message', packedMessage);
}
// 3秒経っても既読にならなかったらイベント発行
if (this.userEntityService.isLocalUser(toUser)) {
setTimeout(async () => {
const marker = await this.redisClient.get(`newUserChatMessageExists:${toUser.id}:${fromUser.id}`);
if (marker == null) return; // 既読
const packedMessageForTo = await this.chatEntityService.packMessageDetailed(inserted, toUser);
this.globalEventService.publishMainStream(toUser.id, 'newChatMessage', packedMessageForTo);
//this.pushNotificationService.pushNotification(toUser.id, 'newChatMessage', packedMessageForTo);
}, 3000);
}
return packedMessage;
}
@bindThis
public async createMessageToRoom(fromUser: { id: MiUser['id']; host: MiUser['host']; }, toRoom: MiChatRoom, params: {
text?: string | null;
file?: MiDriveFile | null;
uri?: string | null;
}): Promise<Packed<'ChatMessageLiteForRoom'>> {
const memberships = (await this.chatRoomMembershipsRepository.findBy({ roomId: toRoom.id })).map(m => ({
userId: m.userId,
isMuted: m.isMuted,
})).concat({ // ownerはmembershipレコードを作らないため
userId: toRoom.ownerId,
isMuted: false,
});
if (!memberships.some(member => member.userId === fromUser.id)) {
throw new Error('you are not a member of the room');
}
const membershipsOtherThanMe = memberships.filter(member => member.userId !== fromUser.id);
const message = {
id: this.idService.gen(),
fromUserId: fromUser.id,
toRoomId: toRoom.id,
text: params.text ? params.text.trim() : null,
fileId: params.file ? params.file.id : null,
reads: [],
uri: params.uri ?? null,
} satisfies Partial<MiChatMessage>;
const inserted = await this.chatMessagesRepository.insertOne(message);
const packedMessage = await this.chatEntityService.packMessageLiteForRoom(inserted);
this.globalEventService.publishChatRoomStream(toRoom.id, 'message', packedMessage);
const redisPipeline = this.redisClient.pipeline();
for (const membership of membershipsOtherThanMe) {
if (membership.isMuted) continue;
redisPipeline.set(`newRoomChatMessageExists:${membership.userId}:${toRoom.id}`, message.id);
redisPipeline.sadd(`newChatMessagesExists:${membership.userId}`, `room:${toRoom.id}`);
}
redisPipeline.exec();
// 3秒経っても既読にならなかったらイベント発行
setTimeout(async () => {
const redisPipeline = this.redisClient.pipeline();
for (const membership of membershipsOtherThanMe) {
redisPipeline.get(`newRoomChatMessageExists:${membership.userId}:${toRoom.id}`);
}
const markers = await redisPipeline.exec();
if (markers == null) throw new Error('redis error');
if (markers.every(marker => marker[1] == null)) return;
const packedMessageForTo = await this.chatEntityService.packMessageDetailed(inserted);
for (let i = 0; i < membershipsOtherThanMe.length; i++) {
const marker = markers[i][1];
if (marker == null) continue;
this.globalEventService.publishMainStream(membershipsOtherThanMe[i].userId, 'newChatMessage', packedMessageForTo);
//this.pushNotificationService.pushNotification(membershipsOtherThanMe[i].userId, 'newChatMessage', packedMessageForTo);
}
}, 3000);
return packedMessage;
}
@bindThis
public async readUserChatMessage(
readerId: MiUser['id'],
senderId: MiUser['id'],
): Promise<void> {
const redisPipeline = this.redisClient.pipeline();
redisPipeline.del(`newUserChatMessageExists:${readerId}:${senderId}`);
redisPipeline.srem(`newChatMessagesExists:${readerId}`, `user:${senderId}`);
await redisPipeline.exec();
}
@bindThis
public async readRoomChatMessage(
readerId: MiUser['id'],
roomId: MiChatRoom['id'],
): Promise<void> {
const redisPipeline = this.redisClient.pipeline();
redisPipeline.del(`newRoomChatMessageExists:${readerId}:${roomId}`);
redisPipeline.srem(`newChatMessagesExists:${readerId}`, `room:${roomId}`);
await redisPipeline.exec();
}
@bindThis
public findMessageById(messageId: MiChatMessage['id']) {
return this.chatMessagesRepository.findOneBy({ id: messageId });
}
@bindThis
public findMyMessageById(userId: MiUser['id'], messageId: MiChatMessage['id']) {
return this.chatMessagesRepository.findOneBy({ id: messageId, fromUserId: userId });
}
@bindThis
public async hasPermissionToViewRoomTimeline(meId: MiUser['id'], room: MiChatRoom) {
if (await this.isRoomMember(room, meId)) {
return true;
} else {
const iAmModerator = await this.roleService.isModerator({ id: meId });
if (iAmModerator) {
return true;
}
return false;
}
}
@bindThis
public async deleteMessage(message: MiChatMessage) {
await this.chatMessagesRepository.delete(message.id);
if (message.toUserId) {
const [fromUser, toUser] = await Promise.all([
this.usersRepository.findOneByOrFail({ id: message.fromUserId }),
this.usersRepository.findOneByOrFail({ id: message.toUserId }),
]);
if (this.userEntityService.isLocalUser(fromUser)) this.globalEventService.publishChatUserStream(message.fromUserId, message.toUserId, 'deleted', message.id);
if (this.userEntityService.isLocalUser(toUser)) this.globalEventService.publishChatUserStream(message.toUserId, message.fromUserId, 'deleted', message.id);
if (this.userEntityService.isLocalUser(fromUser) && this.userEntityService.isRemoteUser(toUser)) {
//const activity = this.apRendererService.addContext(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${message.id}`), fromUser));
//this.queueService.deliver(fromUser, activity, toUser.inbox);
}
} else if (message.toRoomId) {
this.globalEventService.publishChatRoomStream(message.toRoomId, 'deleted', message.id);
}
}
@bindThis
public async userTimeline(meId: MiUser['id'], otherId: MiUser['id'], limit: number, sinceId?: MiChatMessage['id'] | null, untilId?: MiChatMessage['id'] | null) {
const query = this.queryService.makePaginationQuery(this.chatMessagesRepository.createQueryBuilder('message'), sinceId, untilId)
.andWhere(new Brackets(qb => {
qb
.where(new Brackets(qb => {
qb
.where('message.fromUserId = :meId')
.andWhere('message.toUserId = :otherId');
}))
.orWhere(new Brackets(qb => {
qb
.where('message.fromUserId = :otherId')
.andWhere('message.toUserId = :meId');
}));
}))
.setParameter('meId', meId)
.setParameter('otherId', otherId);
const messages = await query.take(limit).getMany();
return messages;
}
@bindThis
public async roomTimeline(roomId: MiChatRoom['id'], limit: number, sinceId?: MiChatMessage['id'] | null, untilId?: MiChatMessage['id'] | null) {
const query = this.queryService.makePaginationQuery(this.chatMessagesRepository.createQueryBuilder('message'), sinceId, untilId)
.andWhere('message.toRoomId = :roomId', { roomId })
.leftJoinAndSelect('message.file', 'file')
.leftJoinAndSelect('message.fromUser', 'fromUser');
const messages = await query.take(limit).getMany();
return messages;
}
@bindThis
public async userHistory(meId: MiUser['id'], limit: number): Promise<MiChatMessage[]> {
const history: MiChatMessage[] = [];
const mutingQuery = this.mutingsRepository.createQueryBuilder('muting')
.select('muting.muteeId')
.where('muting.muterId = :muterId', { muterId: meId });
for (let i = 0; i < limit; i++) {
const found = history.map(m => (m.fromUserId === meId) ? m.toUserId! : m.fromUserId!);
const query = this.chatMessagesRepository.createQueryBuilder('message')
.orderBy('message.id', 'DESC')
.where(new Brackets(qb => {
qb
.where('message.fromUserId = :meId', { meId: meId })
.orWhere('message.toUserId = :meId', { meId: meId });
}))
.andWhere('message.toRoomId IS NULL')
.andWhere(`message.fromUserId NOT IN (${ mutingQuery.getQuery() })`)
.andWhere(`message.toUserId NOT IN (${ mutingQuery.getQuery() })`);
if (found.length > 0) {
query.andWhere('message.fromUserId NOT IN (:...found)', { found: found });
query.andWhere('message.toUserId NOT IN (:...found)', { found: found });
}
query.setParameters(mutingQuery.getParameters());
const message = await query.getOne();
if (message) {
history.push(message);
} else {
break;
}
}
return history;
}
@bindThis
public async roomHistory(meId: MiUser['id'], limit: number): Promise<MiChatMessage[]> {
// TODO: 一回のクエリにまとめられるかも
const [memberRoomIds, ownedRoomIds] = await Promise.all([
this.chatRoomMembershipsRepository.findBy({
userId: meId,
}).then(xs => xs.map(x => x.roomId)),
this.chatRoomsRepository.findBy({
ownerId: meId,
}).then(xs => xs.map(x => x.id)),
]);
const roomIds = memberRoomIds.concat(ownedRoomIds);
if (memberRoomIds.length === 0 && ownedRoomIds.length === 0) {
return [];
}
const history: MiChatMessage[] = [];
for (let i = 0; i < limit; i++) {
const found = history.map(m => m.toRoomId!);
const query = this.chatMessagesRepository.createQueryBuilder('message')
.orderBy('message.id', 'DESC')
.where('message.toRoomId IN (:...roomIds)', { roomIds });
if (found.length > 0) {
query.andWhere('message.toRoomId NOT IN (:...found)', { found: found });
}
const message = await query.getOne();
if (message) {
history.push(message);
} else {
break;
}
}
return history;
}
@bindThis
public async getUserReadStateMap(userId: MiUser['id'], otherIds: MiUser['id'][]) {
const readStateMap: Record<MiUser['id'], boolean> = {};
const redisPipeline = this.redisClient.pipeline();
for (const otherId of otherIds) {
redisPipeline.get(`newUserChatMessageExists:${userId}:${otherId}`);
}
const markers = await redisPipeline.exec();
if (markers == null) throw new Error('redis error');
for (let i = 0; i < otherIds.length; i++) {
const marker = markers[i][1];
readStateMap[otherIds[i]] = marker == null;
}
return readStateMap;
}
@bindThis
public async getRoomReadStateMap(userId: MiUser['id'], roomIds: MiChatRoom['id'][]) {
const readStateMap: Record<MiChatRoom['id'], boolean> = {};
const redisPipeline = this.redisClient.pipeline();
for (const roomId of roomIds) {
redisPipeline.get(`newRoomChatMessageExists:${userId}:${roomId}`);
}
const markers = await redisPipeline.exec();
if (markers == null) throw new Error('redis error');
for (let i = 0; i < roomIds.length; i++) {
const marker = markers[i][1];
readStateMap[roomIds[i]] = marker == null;
}
return readStateMap;
}
@bindThis
public async hasUnreadMessages(userId: MiUser['id']) {
const card = await this.redisClient.scard(`newChatMessagesExists:${userId}`);
return card > 0;
}
@bindThis
public async createRoom(owner: MiUser, params: Partial<{
name: string;
description: string;
}>) {
const room = {
id: this.idService.gen(),
name: params.name,
description: params.description,
ownerId: owner.id,
} satisfies Partial<MiChatRoom>;
const created = await this.chatRoomsRepository.insertOne(room);
return created;
}
@bindThis
public async hasPermissionToDeleteRoom(meId: MiUser['id'], room: MiChatRoom) {
if (room.ownerId === meId) {
return true;
}
const iAmModerator = await this.roleService.isModerator({ id: meId });
if (iAmModerator) {
return true;
}
return false;
}
@bindThis
public async deleteRoom(room: MiChatRoom, deleter?: MiUser) {
await this.chatRoomsRepository.delete(room.id);
if (deleter) {
const deleterIsModerator = await this.roleService.isModerator(deleter);
if (deleterIsModerator) {
this.moderationLogService.log(deleter, 'deleteChatRoom', {
roomId: room.id,
room: room,
});
}
}
}
@bindThis
public async findMyRoomById(ownerId: MiUser['id'], roomId: MiChatRoom['id']) {
return this.chatRoomsRepository.findOneBy({ id: roomId, ownerId: ownerId });
}
@bindThis
public async findRoomById(roomId: MiChatRoom['id']) {
return this.chatRoomsRepository.findOne({ where: { id: roomId }, relations: ['owner'] });
}
@bindThis
public async isRoomMember(room: MiChatRoom, userId: MiUser['id']) {
if (room.ownerId === userId) return true;
const membership = await this.chatRoomMembershipsRepository.findOneBy({ roomId: room.id, userId });
return membership != null;
}
@bindThis
public async createRoomInvitation(inviterId: MiUser['id'], roomId: MiChatRoom['id'], inviteeId: MiUser['id']) {
if (inviterId === inviteeId) {
throw new Error('yourself');
}
const room = await this.chatRoomsRepository.findOneByOrFail({ id: roomId, ownerId: inviterId });
if (await this.isRoomMember(room, inviteeId)) {
throw new Error('already member');
}
const existingInvitation = await this.chatRoomInvitationsRepository.findOneBy({ roomId, userId: inviteeId });
if (existingInvitation) {
throw new Error('already invited');
}
const membershipsCount = await this.chatRoomMembershipsRepository.countBy({ roomId });
if (membershipsCount >= MAX_ROOM_MEMBERS) {
throw new Error('room is full');
}
// TODO: cehck block
const invitation = {
id: this.idService.gen(),
roomId: room.id,
userId: inviteeId,
} satisfies Partial<MiChatRoomInvitation>;
const created = await this.chatRoomInvitationsRepository.insertOne(invitation);
this.notificationService.createNotification(inviteeId, 'chatRoomInvitationReceived', {
invitationId: invitation.id,
}, inviterId);
return created;
}
@bindThis
public async getSentRoomInvitationsWithPagination(roomId: MiChatRoom['id'], limit: number, sinceId?: MiChatRoomInvitation['id'] | null, untilId?: MiChatRoomInvitation['id'] | null) {
const query = this.queryService.makePaginationQuery(this.chatRoomInvitationsRepository.createQueryBuilder('invitation'), sinceId, untilId)
.andWhere('invitation.roomId = :roomId', { roomId });
const invitations = await query.take(limit).getMany();
return invitations;
}
@bindThis
public async getOwnedRoomsWithPagination(ownerId: MiUser['id'], limit: number, sinceId?: MiChatRoom['id'] | null, untilId?: MiChatRoom['id'] | null) {
const query = this.queryService.makePaginationQuery(this.chatRoomsRepository.createQueryBuilder('room'), sinceId, untilId)
.andWhere('room.ownerId = :ownerId', { ownerId });
const rooms = await query.take(limit).getMany();
return rooms;
}
@bindThis
public async getReceivedRoomInvitationsWithPagination(userId: MiUser['id'], limit: number, sinceId?: MiChatRoomInvitation['id'] | null, untilId?: MiChatRoomInvitation['id'] | null) {
const query = this.queryService.makePaginationQuery(this.chatRoomInvitationsRepository.createQueryBuilder('invitation'), sinceId, untilId)
.andWhere('invitation.userId = :userId', { userId })
.andWhere('invitation.ignored = FALSE');
const invitations = await query.take(limit).getMany();
return invitations;
}
@bindThis
public async joinToRoom(userId: MiUser['id'], roomId: MiChatRoom['id']) {
const invitation = await this.chatRoomInvitationsRepository.findOneByOrFail({ roomId, userId });
const membershipsCount = await this.chatRoomMembershipsRepository.countBy({ roomId });
if (membershipsCount >= MAX_ROOM_MEMBERS) {
throw new Error('room is full');
}
const membership = {
id: this.idService.gen(),
roomId: roomId,
userId: userId,
} satisfies Partial<MiChatRoomMembership>;
// TODO: transaction
await this.chatRoomMembershipsRepository.insertOne(membership);
await this.chatRoomInvitationsRepository.delete(invitation.id);
}
@bindThis
public async ignoreRoomInvitation(userId: MiUser['id'], roomId: MiChatRoom['id']) {
const invitation = await this.chatRoomInvitationsRepository.findOneByOrFail({ roomId, userId });
await this.chatRoomInvitationsRepository.update(invitation.id, { ignored: true });
}
@bindThis
public async leaveRoom(userId: MiUser['id'], roomId: MiChatRoom['id']) {
const membership = await this.chatRoomMembershipsRepository.findOneByOrFail({ roomId, userId });
await this.chatRoomMembershipsRepository.delete(membership.id);
}
@bindThis
public async muteRoom(userId: MiUser['id'], roomId: MiChatRoom['id'], mute: boolean) {
const membership = await this.chatRoomMembershipsRepository.findOneByOrFail({ roomId, userId });
await this.chatRoomMembershipsRepository.update(membership.id, { isMuted: mute });
}
@bindThis
public async updateRoom(room: MiChatRoom, params: {
name?: string;
description?: string;
}): Promise<MiChatRoom> {
return this.chatRoomsRepository.createQueryBuilder().update()
.set(params)
.where('id = :id', { id: room.id })
.returning('*')
.execute()
.then((response) => {
return response.raw[0];
});
}
@bindThis
public async getRoomMembershipsWithPagination(roomId: MiChatRoom['id'], limit: number, sinceId?: MiChatRoomMembership['id'] | null, untilId?: MiChatRoomMembership['id'] | null) {
const query = this.queryService.makePaginationQuery(this.chatRoomMembershipsRepository.createQueryBuilder('membership'), sinceId, untilId)
.andWhere('membership.roomId = :roomId', { roomId });
const memberships = await query.take(limit).getMany();
return memberships;
}
@bindThis
public async searchMessages(meId: MiUser['id'], query: string, limit: number, params: {
userId?: MiUser['id'] | null;
roomId?: MiChatRoom['id'] | null;
}) {
const q = this.chatMessagesRepository.createQueryBuilder('message');
if (params.userId) {
q.andWhere(new Brackets(qb => {
qb
.where(new Brackets(qb => {
qb
.where('message.fromUserId = :meId')
.andWhere('message.toUserId = :otherId');
}))
.orWhere(new Brackets(qb => {
qb
.where('message.fromUserId = :otherId')
.andWhere('message.toUserId = :meId');
}));
}))
.setParameter('meId', meId)
.setParameter('otherId', params.userId);
} else if (params.roomId) {
q.where('message.toRoomId = :roomId', { roomId: params.roomId });
} else {
const membershipsQuery = this.chatRoomMembershipsRepository.createQueryBuilder('membership')
.select('membership.roomId')
.where('membership.userId = :meId', { meId: meId });
const ownedRoomsQuery = this.chatRoomsRepository.createQueryBuilder('room')
.select('room.id')
.where('room.ownerId = :meId', { meId });
q.andWhere(new Brackets(qb => {
qb
.where('message.fromUserId = :meId')
.orWhere('message.toUserId = :meId')
.orWhere(`message.toRoomId IN (${membershipsQuery.getQuery()})`)
.orWhere(`message.toRoomId IN (${ownedRoomsQuery.getQuery()})`);
}));
q.setParameters(membershipsQuery.getParameters());
q.setParameters(ownedRoomsQuery.getParameters());
}
q.andWhere('LOWER(message.text) LIKE :q', { q: `%${ sqlLikeEscape(query.toLowerCase()) }%` });
q.leftJoinAndSelect('message.file', 'file');
q.leftJoinAndSelect('message.fromUser', 'fromUser');
q.leftJoinAndSelect('message.toUser', 'toUser');
q.leftJoinAndSelect('message.toRoom', 'toRoom');
q.leftJoinAndSelect('toRoom.owner', 'toRoomOwner');
const messages = await q.orderBy('message.id', 'DESC').take(limit).getMany();
return messages;
}
@bindThis
public async react(messageId: MiChatMessage['id'], userId: MiUser['id'], reaction_: string) {
let reaction;
const custom = reaction_.match(isCustomEmojiRegexp);
if (custom == null) {
reaction = normalizeEmojiString(reaction_);
} else {
const name = custom[1];
const emoji = (await this.customEmojiService.localEmojisCache.fetch()).get(name);
if (emoji == null) {
throw new Error('no such emoji');
} else {
reaction = `:${name}:`;
}
}
const message = await this.chatMessagesRepository.findOneByOrFail({ id: messageId });
if (message.fromUserId === userId) {
throw new Error('cannot react to own message');
}
if (message.toRoomId === null && message.toUserId !== userId) {
throw new Error('cannot react to others message');
}
if (message.reactions.length >= MAX_REACTIONS_PER_MESSAGE) {
throw new Error('too many reactions');
}
const room = message.toRoomId ? await this.chatRoomsRepository.findOneByOrFail({ id: message.toRoomId }) : null;
if (room) {
if (!await this.isRoomMember(room, userId)) {
throw new Error('cannot react to others message');
}
}
await this.chatMessagesRepository.createQueryBuilder().update()
.set({
reactions: () => `array_append("reactions", '${userId}/${reaction}')`,
})
.where('id = :id', { id: message.id })
.execute();
if (room) {
this.globalEventService.publishChatRoomStream(room.id, 'react', {
messageId: message.id,
user: await this.userEntityService.pack(userId),
reaction,
});
} else {
this.globalEventService.publishChatUserStream(message.fromUserId, message.toUserId!, 'react', {
messageId: message.id,
reaction,
});
this.globalEventService.publishChatUserStream(message.toUserId!, message.fromUserId, 'react', {
messageId: message.id,
reaction,
});
}
}
@bindThis
public async unreact(messageId: MiChatMessage['id'], userId: MiUser['id'], reaction_: string) {
let reaction;
const custom = reaction_.match(isCustomEmojiRegexp);
if (custom == null) {
reaction = normalizeEmojiString(reaction_);
} else { // 削除されたカスタム絵文字のリアクションを削除したいかもしれないので絵文字の存在チェックはする必要なし
const name = custom[1];
reaction = `:${name}:`;
}
// NOTE: 自分のリアクションを(あれば)削除するだけなので諸々の権限チェックは必要なし
const message = await this.chatMessagesRepository.findOneByOrFail({ id: messageId });
const room = message.toRoomId ? await this.chatRoomsRepository.findOneByOrFail({ id: message.toRoomId }) : null;
await this.chatMessagesRepository.createQueryBuilder().update()
.set({
reactions: () => `array_remove("reactions", '${userId}/${reaction}')`,
})
.where('id = :id', { id: message.id })
.execute();
// TODO: 実際に削除が行われたときのみイベントを発行する
if (room) {
this.globalEventService.publishChatRoomStream(room.id, 'unreact', {
messageId: message.id,
user: await this.userEntityService.pack(userId),
reaction,
});
} else {
this.globalEventService.publishChatUserStream(message.fromUserId, message.toUserId!, 'unreact', {
messageId: message.id,
reaction,
});
this.globalEventService.publishChatUserStream(message.toUserId!, message.fromUserId, 'unreact', {
messageId: message.id,
reaction,
});
}
}
@bindThis
public async getMyMemberships(userId: MiUser['id'], limit: number, sinceId?: MiChatRoomMembership['id'] | null, untilId?: MiChatRoomMembership['id'] | null) {
const query = this.queryService.makePaginationQuery(this.chatRoomMembershipsRepository.createQueryBuilder('membership'), sinceId, untilId)
.andWhere('membership.userId = :userId', { userId });
const memberships = await query.take(limit).getMany();
return memberships;
}
}

View file

@ -19,6 +19,7 @@ import { TimeService } from '@/core/TimeService.js';
import { EnvService } from '@/core/EnvService.js';
import { ApUtilityService } from '@/core/activitypub/ApUtilityService.js';
import { ApLogService } from '@/core/ApLogService.js';
import { UpdateInstanceQueue } from '@/core/UpdateInstanceQueue.js';
import { AccountMoveService } from './AccountMoveService.js';
import { AccountUpdateService } from './AccountUpdateService.js';
import { AnnouncementService } from './AnnouncementService.js';
@ -27,7 +28,6 @@ import { AppLockService } from './AppLockService.js';
import { AchievementService } from './AchievementService.js';
import { AvatarDecorationService } from './AvatarDecorationService.js';
import { CaptchaService } from './CaptchaService.js';
import { CreateSystemUserService } from './CreateSystemUserService.js';
import { CustomEmojiService } from './CustomEmojiService.js';
import { DeleteAccountService } from './DeleteAccountService.js';
import { DownloadService } from './DownloadService.js';
@ -40,7 +40,7 @@ import { HashtagService } from './HashtagService.js';
import { HttpRequestService } from './HttpRequestService.js';
import { IdService } from './IdService.js';
import { ImageProcessingService } from './ImageProcessingService.js';
import { InstanceActorService } from './InstanceActorService.js';
import { SystemAccountService } from './SystemAccountService.js';
import { InternalStorageService } from './InternalStorageService.js';
import { MetaService } from './MetaService.js';
import { MfmService } from './MfmService.js';
@ -50,7 +50,6 @@ import { NoteEditService } from './NoteEditService.js';
import { NoteDeleteService } from './NoteDeleteService.js';
import { LatestNoteService } from './LatestNoteService.js';
import { NotePiningService } from './NotePiningService.js';
import { NoteReadService } from './NoteReadService.js';
import { NotificationService } from './NotificationService.js';
import { PollService } from './PollService.js';
import { PushNotificationService } from './PushNotificationService.js';
@ -74,7 +73,6 @@ import { UserSuspendService } from './UserSuspendService.js';
import { UserAuthService } from './UserAuthService.js';
import { VideoProcessingService } from './VideoProcessingService.js';
import { UserWebhookService } from './UserWebhookService.js';
import { ProxyAccountService } from './ProxyAccountService.js';
import { UtilityService } from './UtilityService.js';
import { FileInfoService } from './FileInfoService.js';
import { SearchService } from './SearchService.js';
@ -82,6 +80,7 @@ import { ClipService } from './ClipService.js';
import { FeaturedService } from './FeaturedService.js';
import { FanoutTimelineService } from './FanoutTimelineService.js';
import { ChannelFollowingService } from './ChannelFollowingService.js';
import { ChatService } from './ChatService.js';
import { RegistryApiService } from './RegistryApiService.js';
import { ReversiService } from './ReversiService.js';
@ -107,6 +106,7 @@ import { AppEntityService } from './entities/AppEntityService.js';
import { AuthSessionEntityService } from './entities/AuthSessionEntityService.js';
import { BlockingEntityService } from './entities/BlockingEntityService.js';
import { ChannelEntityService } from './entities/ChannelEntityService.js';
import { ChatEntityService } from './entities/ChatEntityService.js';
import { ClipEntityService } from './entities/ClipEntityService.js';
import { DriveFileEntityService } from './entities/DriveFileEntityService.js';
import { DriveFolderEntityService } from './entities/DriveFolderEntityService.js';
@ -173,7 +173,6 @@ const $AppLockService: Provider = { provide: 'AppLockService', useExisting: AppL
const $AchievementService: Provider = { provide: 'AchievementService', useExisting: AchievementService };
const $AvatarDecorationService: Provider = { provide: 'AvatarDecorationService', useExisting: AvatarDecorationService };
const $CaptchaService: Provider = { provide: 'CaptchaService', useExisting: CaptchaService };
const $CreateSystemUserService: Provider = { provide: 'CreateSystemUserService', useExisting: CreateSystemUserService };
const $CustomEmojiService: Provider = { provide: 'CustomEmojiService', useExisting: CustomEmojiService };
const $DeleteAccountService: Provider = { provide: 'DeleteAccountService', useExisting: DeleteAccountService };
const $DownloadService: Provider = { provide: 'DownloadService', useExisting: DownloadService };
@ -186,7 +185,6 @@ const $HashtagService: Provider = { provide: 'HashtagService', useExisting: Hash
const $HttpRequestService: Provider = { provide: 'HttpRequestService', useExisting: HttpRequestService };
const $IdService: Provider = { provide: 'IdService', useExisting: IdService };
const $ImageProcessingService: Provider = { provide: 'ImageProcessingService', useExisting: ImageProcessingService };
const $InstanceActorService: Provider = { provide: 'InstanceActorService', useExisting: InstanceActorService };
const $InternalStorageService: Provider = { provide: 'InternalStorageService', useExisting: InternalStorageService };
const $MetaService: Provider = { provide: 'MetaService', useExisting: MetaService };
const $MfmService: Provider = { provide: 'MfmService', useExisting: MfmService };
@ -196,10 +194,9 @@ const $NoteEditService: Provider = { provide: 'NoteEditService', useExisting: No
const $NoteDeleteService: Provider = { provide: 'NoteDeleteService', useExisting: NoteDeleteService };
const $LatestNoteService: Provider = { provide: 'LatestNoteService', useExisting: LatestNoteService };
const $NotePiningService: Provider = { provide: 'NotePiningService', useExisting: NotePiningService };
const $NoteReadService: Provider = { provide: 'NoteReadService', useExisting: NoteReadService };
const $NotificationService: Provider = { provide: 'NotificationService', useExisting: NotificationService };
const $PollService: Provider = { provide: 'PollService', useExisting: PollService };
const $ProxyAccountService: Provider = { provide: 'ProxyAccountService', useExisting: ProxyAccountService };
const $SystemAccountService: Provider = { provide: 'SystemAccountService', useExisting: SystemAccountService };
const $PushNotificationService: Provider = { provide: 'PushNotificationService', useExisting: PushNotificationService };
const $QueryService: Provider = { provide: 'QueryService', useExisting: QueryService };
const $ReactionService: Provider = { provide: 'ReactionService', useExisting: ReactionService };
@ -220,6 +217,7 @@ const $UserRenoteMutingService: Provider = { provide: 'UserRenoteMutingService',
const $UserSearchService: Provider = { provide: 'UserSearchService', useExisting: UserSearchService };
const $UserSuspendService: Provider = { provide: 'UserSuspendService', useExisting: UserSuspendService };
const $UserAuthService: Provider = { provide: 'UserAuthService', useExisting: UserAuthService };
const $UpdateInstanceQueue: Provider = { provide: 'UpdateInstanceQueue', useExisting: UpdateInstanceQueue };
const $VideoProcessingService: Provider = { provide: 'VideoProcessingService', useExisting: VideoProcessingService };
const $UserWebhookService: Provider = { provide: 'UserWebhookService', useExisting: UserWebhookService };
const $SystemWebhookService: Provider = { provide: 'SystemWebhookService', useExisting: SystemWebhookService };
@ -233,6 +231,7 @@ const $FeaturedService: Provider = { provide: 'FeaturedService', useExisting: Fe
const $FanoutTimelineService: Provider = { provide: 'FanoutTimelineService', useExisting: FanoutTimelineService };
const $FanoutTimelineEndpointService: Provider = { provide: 'FanoutTimelineEndpointService', useExisting: FanoutTimelineEndpointService };
const $ChannelFollowingService: Provider = { provide: 'ChannelFollowingService', useExisting: ChannelFollowingService };
const $ChatService: Provider = { provide: 'ChatService', useExisting: ChatService };
const $RegistryApiService: Provider = { provide: 'RegistryApiService', useExisting: RegistryApiService };
const $ReversiService: Provider = { provide: 'ReversiService', useExisting: ReversiService };
const $TimeService: Provider = { provide: 'TimeService', useExisting: TimeService };
@ -261,6 +260,7 @@ const $AppEntityService: Provider = { provide: 'AppEntityService', useExisting:
const $AuthSessionEntityService: Provider = { provide: 'AuthSessionEntityService', useExisting: AuthSessionEntityService };
const $BlockingEntityService: Provider = { provide: 'BlockingEntityService', useExisting: BlockingEntityService };
const $ChannelEntityService: Provider = { provide: 'ChannelEntityService', useExisting: ChannelEntityService };
const $ChatEntityService: Provider = { provide: 'ChatEntityService', useExisting: ChatEntityService };
const $ClipEntityService: Provider = { provide: 'ClipEntityService', useExisting: ClipEntityService };
const $DriveFileEntityService: Provider = { provide: 'DriveFileEntityService', useExisting: DriveFileEntityService };
const $DriveFolderEntityService: Provider = { provide: 'DriveFolderEntityService', useExisting: DriveFolderEntityService };
@ -331,7 +331,6 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
AchievementService,
AvatarDecorationService,
CaptchaService,
CreateSystemUserService,
CustomEmojiService,
DeleteAccountService,
DownloadService,
@ -344,7 +343,6 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
HttpRequestService,
IdService,
ImageProcessingService,
InstanceActorService,
InternalStorageService,
MetaService,
MfmService,
@ -354,10 +352,9 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
NoteDeleteService,
LatestNoteService,
NotePiningService,
NoteReadService,
NotificationService,
PollService,
ProxyAccountService,
SystemAccountService,
PushNotificationService,
QueryService,
ReactionService,
@ -378,6 +375,7 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
UserSearchService,
UserSuspendService,
UserAuthService,
UpdateInstanceQueue,
VideoProcessingService,
UserWebhookService,
SystemWebhookService,
@ -391,6 +389,7 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
FanoutTimelineService,
FanoutTimelineEndpointService,
ChannelFollowingService,
ChatService,
RegistryApiService,
ReversiService,
TimeService,
@ -419,6 +418,7 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
AuthSessionEntityService,
BlockingEntityService,
ChannelEntityService,
ChatEntityService,
ClipEntityService,
DriveFileEntityService,
DriveFolderEntityService,
@ -485,7 +485,6 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
$AchievementService,
$AvatarDecorationService,
$CaptchaService,
$CreateSystemUserService,
$CustomEmojiService,
$DeleteAccountService,
$DownloadService,
@ -498,7 +497,6 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
$HttpRequestService,
$IdService,
$ImageProcessingService,
$InstanceActorService,
$InternalStorageService,
$MetaService,
$MfmService,
@ -508,10 +506,9 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
$NoteDeleteService,
$LatestNoteService,
$NotePiningService,
$NoteReadService,
$NotificationService,
$PollService,
$ProxyAccountService,
$SystemAccountService,
$PushNotificationService,
$QueryService,
$ReactionService,
@ -532,6 +529,7 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
$UserSearchService,
$UserSuspendService,
$UserAuthService,
$UpdateInstanceQueue,
$VideoProcessingService,
$UserWebhookService,
$SystemWebhookService,
@ -545,6 +543,7 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
$FanoutTimelineService,
$FanoutTimelineEndpointService,
$ChannelFollowingService,
$ChatService,
$RegistryApiService,
$ReversiService,
$TimeService,
@ -573,6 +572,7 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
$AuthSessionEntityService,
$BlockingEntityService,
$ChannelEntityService,
$ChatEntityService,
$ClipEntityService,
$DriveFileEntityService,
$DriveFolderEntityService,
@ -640,7 +640,6 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
AchievementService,
AvatarDecorationService,
CaptchaService,
CreateSystemUserService,
CustomEmojiService,
DeleteAccountService,
DownloadService,
@ -653,7 +652,6 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
HttpRequestService,
IdService,
ImageProcessingService,
InstanceActorService,
InternalStorageService,
MetaService,
MfmService,
@ -663,10 +661,9 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
NoteDeleteService,
LatestNoteService,
NotePiningService,
NoteReadService,
NotificationService,
PollService,
ProxyAccountService,
SystemAccountService,
PushNotificationService,
QueryService,
ReactionService,
@ -687,6 +684,7 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
UserSearchService,
UserSuspendService,
UserAuthService,
UpdateInstanceQueue,
VideoProcessingService,
UserWebhookService,
SystemWebhookService,
@ -700,6 +698,7 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
FanoutTimelineService,
FanoutTimelineEndpointService,
ChannelFollowingService,
ChatService,
RegistryApiService,
ReversiService,
TimeService,
@ -727,6 +726,7 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
AuthSessionEntityService,
BlockingEntityService,
ChannelEntityService,
ChatEntityService,
ClipEntityService,
DriveFileEntityService,
DriveFolderEntityService,
@ -793,7 +793,6 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
$AchievementService,
$AvatarDecorationService,
$CaptchaService,
$CreateSystemUserService,
$CustomEmojiService,
$DeleteAccountService,
$DownloadService,
@ -806,7 +805,6 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
$HttpRequestService,
$IdService,
$ImageProcessingService,
$InstanceActorService,
$InternalStorageService,
$MetaService,
$MfmService,
@ -816,10 +814,9 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
$NoteDeleteService,
$LatestNoteService,
$NotePiningService,
$NoteReadService,
$NotificationService,
$PollService,
$ProxyAccountService,
$SystemAccountService,
$PushNotificationService,
$QueryService,
$ReactionService,
@ -840,6 +837,7 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
$UserSearchService,
$UserSuspendService,
$UserAuthService,
$UpdateInstanceQueue,
$VideoProcessingService,
$UserWebhookService,
$SystemWebhookService,
@ -852,6 +850,7 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
$FanoutTimelineService,
$FanoutTimelineEndpointService,
$ChannelFollowingService,
$ChatService,
$RegistryApiService,
$ReversiService,
$TimeService,
@ -879,6 +878,7 @@ const $SponsorsService: Provider = { provide: 'SponsorsService', useExisting: Sp
$AuthSessionEntityService,
$BlockingEntityService,
$ChannelEntityService,
$ChatEntityService,
$ClipEntityService,
$DriveFileEntityService,
$DriveFolderEntityService,

View file

@ -1,88 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { randomUUID } from 'node:crypto';
import { Inject, Injectable } from '@nestjs/common';
import * as argon2 from 'argon2';
//import bcrypt from 'bcryptjs';
import { IsNull, DataSource } from 'typeorm';
import { genRsaKeyPair } from '@/misc/gen-key-pair.js';
import { MiUser } from '@/models/User.js';
import { MiUserProfile } from '@/models/UserProfile.js';
import { IdService } from '@/core/IdService.js';
import { MiUserKeypair } from '@/models/UserKeypair.js';
import { MiUsedUsername } from '@/models/UsedUsername.js';
import { DI } from '@/di-symbols.js';
import generateNativeUserToken from '@/misc/generate-native-user-token.js';
import { bindThis } from '@/decorators.js';
@Injectable()
export class CreateSystemUserService {
constructor(
@Inject(DI.db)
private db: DataSource,
private idService: IdService,
) {
}
@bindThis
public async createSystemUser(username: string): Promise<MiUser> {
const password = randomUUID();
// Generate hash of password
//const salt = await bcrypt.genSalt(8);
const hash = await argon2.hash(password);
// Generate secret
const secret = generateNativeUserToken();
const keyPair = await genRsaKeyPair();
let account!: MiUser;
// Start transaction
await this.db.transaction(async transactionalEntityManager => {
const exist = await transactionalEntityManager.findOneBy(MiUser, {
usernameLower: username.toLowerCase(),
host: IsNull(),
});
if (exist) throw new Error('the user is already exists');
account = await transactionalEntityManager.insert(MiUser, {
id: this.idService.gen(),
username: username,
usernameLower: username.toLowerCase(),
host: null,
token: secret,
isRoot: false,
isLocked: true,
isExplorable: false,
approved: true,
isBot: true,
}).then(x => transactionalEntityManager.findOneByOrFail(MiUser, x.identifiers[0]));
await transactionalEntityManager.insert(MiUserKeypair, {
publicKey: keyPair.publicKey,
privateKey: keyPair.privateKey,
userId: account.id,
});
await transactionalEntityManager.insert(MiUserProfile, {
userId: account.id,
autoAcceptFollowed: false,
password: hash,
});
await transactionalEntityManager.insert(MiUsedUsername, {
createdAt: new Date(),
username: username.toLowerCase(),
});
});
return account;
}
}

View file

@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { Not, IsNull } from 'typeorm';
import type { FollowingsRepository, MiUser, UsersRepository } from '@/models/_.js';
import type { FollowingsRepository, MiMeta, MiUser, UsersRepository } from '@/models/_.js';
import { QueueService } from '@/core/QueueService.js';
import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
@ -13,11 +13,16 @@ import { GlobalEventService } from '@/core/GlobalEventService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
import { SystemAccountService } from '@/core/SystemAccountService.js';
import { isSystemAccount } from '@/misc/is-system-account.js';
import type { MiPartialUser } from '@/models/User.js';
@Injectable()
export class DeleteAccountService {
constructor(
@Inject(DI.meta)
private meta: MiMeta,
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
@ -29,17 +34,19 @@ export class DeleteAccountService {
private queueService: QueueService,
private globalEventService: GlobalEventService,
private moderationLogService: ModerationLogService,
private systemAccountService: SystemAccountService,
) {
}
@bindThis
public async deleteAccount(user: {
id: string;
host: string | null;
}, moderator?: MiUser): Promise<void> {
public async deleteAccount(user: MiPartialUser, moderator?: MiUser): Promise<void> {
if (this.meta.rootUserId === user.id) throw new Error('cannot delete a root account');
const _user = await this.usersRepository.findOneByOrFail({ id: user.id });
if (_user.isRoot) throw new Error('cannot delete a root account');
if (isSystemAccount(_user)) throw new Error('cannot delete a system account');
if (isSystemAccount(_user)) {
throw new Error('cannot delete a system account');
}
if (moderator != null) {
this.moderationLogService.log(moderator, 'deleteAccount', {

View file

@ -34,7 +34,7 @@ export class DownloadService {
}
@bindThis
public async downloadUrl(url: string, path: string, options: { timeout?: number, operationTimeout?: number, maxSize?: number} = {} ): Promise<{
public async downloadUrl(url: string, path: string, options: { timeout?: number, operationTimeout?: number, maxSize?: number } = {} ): Promise<{
filename: string;
}> {
this.logger.info(`Downloading ${chalk.cyan(url)} to ${chalk.cyanBright(path)} ...`);
@ -60,8 +60,8 @@ export class DownloadService {
request: operationTimeout, // whole operation timeout
},
agent: {
http: this.httpRequestService.httpAgent,
https: this.httpRequestService.httpsAgent,
http: this.httpRequestService.getAgentForHttp(urlObj, true),
https: this.httpRequestService.getAgentForHttps(urlObj, true),
},
http2: false, // default
retry: {

View file

@ -70,7 +70,9 @@ type AddFileArgs = {
ext?: string | null;
requestIp?: string | null;
requestHeaders?: Record<string, string> | null;
requestHeaders?: {
[Name in string]?: string | string[]
} | null;
};
type UploadFromUrlArgs = {
@ -83,7 +85,9 @@ type UploadFromUrlArgs = {
isLink?: boolean;
comment?: string | null;
requestIp?: string | null;
requestHeaders?: Record<string, string> | null;
requestHeaders?: {
[Name in string]?: string | string[]
} | null;
};
@Injectable()
@ -177,7 +181,8 @@ export class DriveService {
?? `${ this.meta.objectStorageUseSSL ? 'https' : 'http' }://${ this.meta.objectStorageEndpoint }${ this.meta.objectStoragePort ? `:${this.meta.objectStoragePort}` : '' }/${ this.meta.objectStorageBucket }`;
// for original
const key = `${this.meta.objectStoragePrefix}/${randomUUID()}${ext}`;
const prefix = this.meta.objectStoragePrefix ? `${this.meta.objectStoragePrefix}/` : '';
const key = `${prefix}${randomUUID()}${ext}`;
const url = `${ baseUrl }/${ key }`;
// for alts
@ -194,7 +199,7 @@ export class DriveService {
];
if (alts.webpublic) {
webpublicKey = `${this.meta.objectStoragePrefix}/webpublic-${randomUUID()}.${alts.webpublic.ext}`;
webpublicKey = `${prefix}webpublic-${randomUUID()}.${alts.webpublic.ext}`;
webpublicUrl = `${ baseUrl }/${ webpublicKey }`;
this.registerLogger.info(`uploading webpublic: ${webpublicKey}`);
@ -202,7 +207,7 @@ export class DriveService {
}
if (alts.thumbnail) {
thumbnailKey = `${this.meta.objectStoragePrefix}/thumbnail-${randomUUID()}.${alts.thumbnail.ext}`;
thumbnailKey = `${prefix}thumbnail-${randomUUID()}.${alts.thumbnail.ext}`;
thumbnailUrl = `${ baseUrl }/${ thumbnailKey }`;
this.registerLogger.info(`uploading thumbnail: ${thumbnailKey}`);
@ -560,6 +565,17 @@ export class DriveService {
const folder = await fetchFolder();
const headers: Record<string, string> = {};
if (requestHeaders) {
for (const [name, value] of Object.entries(requestHeaders)) {
if (Array.isArray(value)) {
headers[name] = value.join();
} else if (value) {
headers[name] = value;
}
}
}
let file = new MiDriveFile();
file.id = this.idService.gen();
file.userId = user ? user.id : null;
@ -570,7 +586,7 @@ export class DriveService {
file.blurhash = info.blurhash ?? null;
file.isLink = isLink;
file.requestIp = requestIp;
file.requestHeaders = requestHeaders;
file.requestHeaders = headers;
file.maybeSensitive = info.sensitive;
file.maybePorn = info.porn;
file.isSensitive = user

View file

@ -164,6 +164,13 @@ export class EmailService {
available: boolean;
reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp' | 'banned' | 'network' | 'blacklist';
}> {
if (!this.utilityService.validateEmailFormat(emailAddress)) {
return {
available: false,
reason: 'format',
};
}
const exist = await this.userProfilesRepository.countBy({
emailVerified: true,
email: emailAddress,

View file

@ -9,7 +9,7 @@ import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js';
export type FanoutTimelineName =
export type FanoutTimelineName = (
// home timeline
| `homeTimeline:${string}`
| `homeTimelineWithFiles:${string}` // only notes with files are included
@ -37,6 +37,7 @@ export type FanoutTimelineName =
// role timelines
| `roleTimeline:${string}` // any notes are included
);
@Injectable()
export class FanoutTimelineService {

View file

@ -20,7 +20,7 @@ import type { MiPage } from '@/models/Page.js';
import type { MiWebhook } from '@/models/Webhook.js';
import type { MiSystemWebhook } from '@/models/SystemWebhook.js';
import type { MiMeta } from '@/models/Meta.js';
import { MiAvatarDecoration, MiReversiGame, MiRole, MiRoleAssignment } from '@/models/_.js';
import { MiAvatarDecoration, MiChatMessage, MiChatRoom, MiReversiGame, MiRole, MiRoleAssignment } from '@/models/_.js';
import type { Packed } from '@/misc/json-schema.js';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
@ -72,12 +72,8 @@ export interface MainEventTypes {
readAllNotifications: undefined;
notificationFlushed: undefined;
unreadNotification: Packed<'Notification'>;
unreadMention: MiNote['id'];
readAllUnreadMentions: undefined;
unreadSpecifiedNote: MiNote['id'];
readAllUnreadSpecifiedNotes: undefined;
readAllAntennas: undefined;
unreadAntenna: MiAntenna;
newChatMessage: Packed<'ChatMessage'>;
readAllAnnouncements: undefined;
myTokenRegenerated: undefined;
signin: {
@ -168,6 +164,21 @@ export interface AdminEventTypes {
};
}
export interface ChatEventTypes {
message: Packed<'ChatMessageLite'>;
deleted: Packed<'ChatMessageLite'>['id'];
react: {
reaction: string;
user?: Packed<'UserLite'>;
messageId: MiChatMessage['id'];
};
unreact: {
reaction: string;
user?: Packed<'UserLite'>;
messageId: MiChatMessage['id'];
};
}
export interface ReversiEventTypes {
matched: {
game: Packed<'ReversiGameDetailed'>;
@ -207,7 +218,7 @@ export interface ReversiGameEventTypes {
type Events<T extends object> = { [K in keyof T]: { type: K; body: T[K]; } };
type EventUnionFromDictionary<
T extends object,
U = Events<T>
U = Events<T>,
> = U[keyof U];
type SerializedAll<T> = {
@ -216,7 +227,7 @@ type SerializedAll<T> = {
type UndefinedAsNullAll<T> = {
[K in keyof T]: T[K] extends undefined ? null : T[K];
}
};
export interface InternalEventTypes {
userChangeSuspendedState: { id: MiUser['id']; isSuspended: MiUser['isSuspended']; };
@ -300,6 +311,14 @@ export type GlobalEvents = {
name: 'notesStream';
payload: Serialized<Packed<'Note'>>;
};
chatUser: {
name: `chatUserStream:${MiUser['id']}-${MiUser['id']}`;
payload: EventTypesToEventPayload<ChatEventTypes>;
};
chatRoom: {
name: `chatRoomStream:${MiChatRoom['id']}`;
payload: EventTypesToEventPayload<ChatEventTypes>;
};
reversi: {
name: `reversiStream:${MiUser['id']}`;
payload: EventTypesToEventPayload<ReversiEventTypes>;
@ -398,6 +417,16 @@ export class GlobalEventService {
this.publish(`adminStream:${userId}`, type, typeof value === 'undefined' ? null : value);
}
@bindThis
public publishChatUserStream<K extends keyof ChatEventTypes>(fromUserId: MiUser['id'], toUserId: MiUser['id'], type: K, value?: ChatEventTypes[K]): void {
this.publish(`chatUserStream:${fromUserId}-${toUserId}`, type, typeof value === 'undefined' ? null : value);
}
@bindThis
public publishChatRoomStream<K extends keyof ChatEventTypes>(toRoomId: MiChatRoom['id'], type: K, value?: ChatEventTypes[K]): void {
this.publish(`chatRoomStream:${toRoomId}`, type, typeof value === 'undefined' ? null : value);
}
@bindThis
public publishReversiStream<K extends keyof ReversiEventTypes>(userId: MiUser['id'], type: K, value?: ReversiEventTypes[K]): void {
this.publish(`reversiStream:${userId}`, type, typeof value === 'undefined' ? null : value);

View file

@ -16,7 +16,7 @@ import type { Config } from '@/config.js';
import { StatusError } from '@/misc/status-error.js';
import { bindThis } from '@/decorators.js';
import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js';
import { IObject } from '@/core/activitypub/type.js';
import type { IObject, IObjectWithId } from '@/core/activitypub/type.js';
import { ApUtilityService } from './activitypub/ApUtilityService.js';
import type { Response } from 'node-fetch';
import type { URL } from 'node:url';
@ -115,32 +115,32 @@ export class HttpRequestService {
/**
* Get http non-proxy agent (without local address filtering)
*/
private httpNative: http.Agent;
private readonly httpNative: http.Agent;
/**
* Get https non-proxy agent (without local address filtering)
*/
private httpsNative: https.Agent;
private readonly httpsNative: https.Agent;
/**
* Get http non-proxy agent
*/
private http: http.Agent;
private readonly http: http.Agent;
/**
* Get https non-proxy agent
*/
private https: https.Agent;
private readonly https: https.Agent;
/**
* Get http proxy or non-proxy agent
*/
public httpAgent: http.Agent;
public readonly httpAgent: http.Agent;
/**
* Get https proxy or non-proxy agent
*/
public httpsAgent: https.Agent;
public readonly httpsAgent: https.Agent;
constructor(
@Inject(DI.config)
@ -198,7 +198,7 @@ export class HttpRequestService {
/**
* Get agent by URL
* @param url URL
* @param bypassProxy Allways bypass proxy
* @param bypassProxy Always bypass proxy
* @param isLocalAddressAllowed
*/
@bindThis
@ -216,8 +216,40 @@ export class HttpRequestService {
}
}
/**
* Get agent for http by URL
* @param url URL
* @param isLocalAddressAllowed
*/
@bindThis
public async getActivityJson(url: string, isLocalAddressAllowed = false): Promise<IObject> {
public getAgentForHttp(url: URL, isLocalAddressAllowed = false): http.Agent {
if ((this.config.proxyBypassHosts ?? []).includes(url.hostname)) {
return isLocalAddressAllowed
? this.httpNative
: this.http;
} else {
return this.httpAgent;
}
}
/**
* Get agent for https by URL
* @param url URL
* @param isLocalAddressAllowed
*/
@bindThis
public getAgentForHttps(url: URL, isLocalAddressAllowed = false): https.Agent {
if ((this.config.proxyBypassHosts ?? []).includes(url.hostname)) {
return isLocalAddressAllowed
? this.httpsNative
: this.https;
} else {
return this.httpsAgent;
}
}
@bindThis
public async getActivityJson(url: string, isLocalAddressAllowed = false): Promise<IObjectWithId> {
const res = await this.send(url, {
method: 'GET',
headers: {
@ -237,7 +269,7 @@ export class HttpRequestService {
// The caller (ApResolverService) will verify the ID against the original / entry URL, which ensures that all three match.
this.apUtilityService.assertIdMatchesUrlAuthority(activity, res.url);
return activity;
return activity as IObjectWithId;
}
@bindThis

View file

@ -7,13 +7,13 @@ import { Inject, Injectable } from '@nestjs/common';
import { ulid } from 'ulid';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { genAid, isSafeAidT, parseAid } from '@/misc/id/aid.js';
import { genAidx, isSafeAidxT, parseAidx } from '@/misc/id/aidx.js';
import { genMeid, isSafeMeidT, parseMeid } from '@/misc/id/meid.js';
import { genMeidg, isSafeMeidgT, parseMeidg } from '@/misc/id/meidg.js';
import { genObjectId, isSafeObjectIdT, parseObjectId } from '@/misc/id/object-id.js';
import { genAid, isSafeAidT, parseAid, parseAidFull } from '@/misc/id/aid.js';
import { genAidx, isSafeAidxT, parseAidx, parseAidxFull } from '@/misc/id/aidx.js';
import { genMeid, isSafeMeidT, parseMeid, parseMeidFull } from '@/misc/id/meid.js';
import { genMeidg, isSafeMeidgT, parseMeidg, parseMeidgFull } from '@/misc/id/meidg.js';
import { genObjectId, isSafeObjectIdT, parseObjectId, parseObjectIdFull } from '@/misc/id/object-id.js';
import { bindThis } from '@/decorators.js';
import { parseUlid } from '@/misc/id/ulid.js';
import { parseUlid, parseUlidFull } from '@/misc/id/ulid.js';
@Injectable()
export class IdService {
@ -70,4 +70,18 @@ export class IdService {
default: throw new Error('unrecognized id generation method');
}
}
// Note: additional is at most 64 bits
@bindThis
public parseFull(id: string): { date: number; additional: bigint; } {
switch (this.method) {
case 'aid': return parseAidFull(id);
case 'aidx': return parseAidxFull(id);
case 'objectid': return parseObjectIdFull(id);
case 'meid': return parseMeidFull(id);
case 'meidg': return parseMeidgFull(id);
case 'ulid': return parseUlidFull(id);
default: throw new Error('unrecognized id generation method');
}
}
}

View file

@ -1,57 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import { IsNull, Not } from 'typeorm';
import type { MiLocalUser } from '@/models/User.js';
import type { UsersRepository } from '@/models/_.js';
import { MemorySingleCache } from '@/misc/cache.js';
import { DI } from '@/di-symbols.js';
import { CreateSystemUserService } from '@/core/CreateSystemUserService.js';
import { bindThis } from '@/decorators.js';
const ACTOR_USERNAME = 'instance.actor' as const;
@Injectable()
export class InstanceActorService {
private cache: MemorySingleCache<MiLocalUser>;
constructor(
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
private createSystemUserService: CreateSystemUserService,
) {
this.cache = new MemorySingleCache<MiLocalUser>(Infinity);
}
@bindThis
public async realLocalUsersPresent(): Promise<boolean> {
return await this.usersRepository.existsBy({
host: IsNull(),
username: Not(ACTOR_USERNAME),
});
}
@bindThis
public async getInstanceActor(): Promise<MiLocalUser> {
const cached = this.cache.get();
if (cached) return cached;
const user = await this.usersRepository.findOneBy({
host: IsNull(),
username: ACTOR_USERNAME,
}) as MiLocalUser | undefined;
if (user) {
this.cache.set(user);
return user;
} else {
const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME) as MiLocalUser;
this.cache.set(created);
return created;
}
}
}

View file

@ -53,7 +53,7 @@ export class MetaService implements OnApplicationShutdown {
case 'metaUpdated': {
this.cache = { // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい
...(body.after),
proxyAccount: null, // joinなカラムは通常取ってこないので
rootUser: null, // joinなカラムは通常取ってこないので
};
break;
}
@ -113,17 +113,20 @@ export class MetaService implements OnApplicationShutdown {
if (before) {
await transactionalEntityManager.update(MiMeta, before.id, data);
const metas = await transactionalEntityManager.find(MiMeta, {
order: {
id: 'DESC',
},
});
return metas[0];
} else {
return await transactionalEntityManager.save(MiMeta, data);
await transactionalEntityManager.save(MiMeta, {
...data,
id: 'x',
});
}
const afters = await transactionalEntityManager.find(MiMeta, {
order: {
id: 'DESC',
},
});
return afters[0];
});
if (data.hiddenTags) {

View file

@ -6,7 +6,7 @@
import { URL } from 'node:url';
import { Inject, Injectable } from '@nestjs/common';
import * as parse5 from 'parse5';
import { Window, XMLSerializer } from 'happy-dom';
import { Window } from 'happy-dom';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { intersperse } from '@/misc/prelude/array.js';
@ -179,7 +179,7 @@ export class MfmService {
break;
}
// this is here only to catch upstream changes!
// this is here only to catch upstream changes!
case 'ruby--': {
let ruby: [string, string][] = [];
for (const child of node.childNodes) {
@ -576,7 +576,8 @@ export class MfmService {
appendChildren(nodes, body);
const serialized = new XMLSerializer().serializeToString(body);
// Remove the unnecessary namespace
const serialized = body.outerHTML;
happyDOM.close().catch(err => {});
@ -584,9 +585,10 @@ export class MfmService {
}
// the toMastoApiHtml function was taken from Iceshrimp and written by zotan and modified by marie to work with the current MK version
// additionally modified by hazelnoot to remove async
@bindThis
public async toMastoApiHtml(nodes: mfm.MfmNode[] | null, mentionedRemoteUsers: IMentionedRemoteUsers = [], inline = false, quoteUri: string | null = null) {
public toMastoApiHtml(nodes: mfm.MfmNode[] | null, mentionedRemoteUsers: IMentionedRemoteUsers = [], inline = false, quoteUri: string | null = null) {
if (nodes == null) {
return null;
}
@ -597,50 +599,50 @@ export class MfmService {
const body = doc.createElement('p');
async function appendChildren(children: mfm.MfmNode[], targetElement: any): Promise<void> {
function appendChildren(children: mfm.MfmNode[], targetElement: any): void {
if (children) {
for (const child of await Promise.all(children.map(async (x) => await (handlers as any)[x.type](x)))) targetElement.appendChild(child);
for (const child of children.map((x) => (handlers as any)[x.type](x))) targetElement.appendChild(child);
}
}
const handlers: {
[K in mfm.MfmNode['type']]: (node: mfm.NodeType<K>) => any;
} = {
async bold(node) {
bold(node) {
const el = doc.createElement('span');
el.textContent = '**';
await appendChildren(node.children, el);
appendChildren(node.children, el);
el.textContent += '**';
return el;
},
async small(node) {
small(node) {
const el = doc.createElement('small');
await appendChildren(node.children, el);
appendChildren(node.children, el);
return el;
},
async strike(node) {
strike(node) {
const el = doc.createElement('span');
el.textContent = '~~';
await appendChildren(node.children, el);
appendChildren(node.children, el);
el.textContent += '~~';
return el;
},
async italic(node) {
italic(node) {
const el = doc.createElement('span');
el.textContent = '*';
await appendChildren(node.children, el);
appendChildren(node.children, el);
el.textContent += '*';
return el;
},
async fn(node) {
fn(node) {
switch (node.props.name) {
case 'group': { // hack for ruby
const el = doc.createElement('span');
await appendChildren(node.children, el);
appendChildren(node.children, el);
return el;
}
case 'ruby': {
@ -666,7 +668,7 @@ export class MfmService {
if (!rt) {
const el = doc.createElement('span');
await appendChildren(node.children, el);
appendChildren(node.children, el);
return el;
}
@ -679,7 +681,7 @@ export class MfmService {
const rpEndEl = doc.createElement('rp');
rpEndEl.appendChild(doc.createTextNode(')'));
await appendChildren(node.children.slice(0, node.children.length - 1), rubyEl);
appendChildren(node.children.slice(0, node.children.length - 1), rubyEl);
rtEl.appendChild(doc.createTextNode(text.trim()));
rubyEl.appendChild(rpStartEl);
rubyEl.appendChild(rtEl);
@ -691,7 +693,7 @@ export class MfmService {
default: {
const el = doc.createElement('span');
el.textContent = '*';
await appendChildren(node.children, el);
appendChildren(node.children, el);
el.textContent += '*';
return el;
}
@ -714,9 +716,9 @@ export class MfmService {
return pre;
},
async center(node) {
center(node) {
const el = doc.createElement('div');
await appendChildren(node.children, el);
appendChildren(node.children, el);
return el;
},
@ -755,16 +757,16 @@ export class MfmService {
return el;
},
async link(node) {
link(node) {
const a = doc.createElement('a');
a.setAttribute('rel', 'nofollow noopener noreferrer');
a.setAttribute('target', '_blank');
a.setAttribute('href', node.props.url);
await appendChildren(node.children, a);
appendChildren(node.children, a);
return a;
},
async mention(node) {
mention(node) {
const { username, host, acct } = node.props;
const resolved = mentionedRemoteUsers.find(remoteUser => remoteUser.username === username && remoteUser.host === host);
@ -787,9 +789,9 @@ export class MfmService {
return el;
},
async quote(node) {
quote(node) {
const el = doc.createElement('blockquote');
await appendChildren(node.children, el);
appendChildren(node.children, el);
return el;
},
@ -822,14 +824,14 @@ export class MfmService {
return a;
},
async plain(node) {
plain(node) {
const el = doc.createElement('span');
await appendChildren(node.children, el);
appendChildren(node.children, el);
return el;
},
};
await appendChildren(nodes, body);
appendChildren(nodes, body);
if (quoteUri !== null) {
const a = doc.createElement('a');
@ -846,13 +848,13 @@ export class MfmService {
body.appendChild(quote);
}
let result = new XMLSerializer().serializeToString(body);
let result = body.outerHTML;
if (inline) {
result = result.replace(/^<p>/, '').replace(/<\/p>$/, '');
}
happyDOM.close().catch(e => {});
happyDOM.close().catch(() => {});
return result;
}

View file

@ -42,7 +42,6 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js';
import { NoteReadService } from '@/core/NoteReadService.js';
import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js';
import { bindThis } from '@/decorators.js';
import { RoleService } from '@/core/RoleService.js';
@ -203,7 +202,6 @@ export class NoteCreateService implements OnApplicationShutdown {
private globalEventService: GlobalEventService,
private queueService: QueueService,
private fanoutTimelineService: FanoutTimelineService,
private noteReadService: NoteReadService,
private notificationService: NotificationService,
private relayService: RelayService,
private federatedInstanceService: FederatedInstanceService,
@ -573,7 +571,7 @@ export class NoteCreateService implements OnApplicationShutdown {
if (this.meta.enableStatsForFederatedInstances) {
if (this.userEntityService.isRemoteUser(user)) {
this.federatedInstanceService.fetchOrRegister(user.host).then(async i => {
if (note.renote && note.text || !note.renote) {
if (!this.isRenote(note) || this.isQuote(note)) {
this.updateNotesCountQueue.enqueue(i.id, 1);
}
if (this.meta.enableChartsForFederatedInstances) {
@ -585,24 +583,22 @@ export class NoteCreateService implements OnApplicationShutdown {
// ハッシュタグ更新
if (data.visibility === 'public' || data.visibility === 'home') {
if (user.isBot && this.meta.enableBotTrending) {
this.hashtagService.updateHashtags(user, tags);
} else if (!user.isBot) {
if (!user.isBot || this.meta.enableBotTrending) {
this.hashtagService.updateHashtags(user, tags);
}
}
if (data.renote && data.text) {
// Increment notes count (user)
this.incNotesCountOfUser(user);
} else if (!data.renote) {
if (!this.isRenote(note) || this.isQuote(note)) {
// Increment notes count (user)
this.incNotesCountOfUser(user);
}
this.pushToTl(note, user);
this.antennaService.addNoteToAntennas(note, user);
this.antennaService.addNoteToAntennas({
...note,
channel: data.channel ?? null,
}, user);
if (data.reply) {
this.saveReply(data.reply, note);
@ -633,7 +629,7 @@ export class NoteCreateService implements OnApplicationShutdown {
});
}
if (data.renote && data.text == null && data.renote.userId !== user.id && !user.isBot) {
if (this.isRenote(data) && !this.isQuote(data) && data.renote.userId !== user.id && !user.isBot) {
this.incRenoteCount(data.renote);
}
@ -651,31 +647,6 @@ export class NoteCreateService implements OnApplicationShutdown {
if (!silent) {
if (this.userEntityService.isLocalUser(user)) this.activeUsersChart.write(user);
// 未読通知を作成
if (data.visibility === 'specified') {
if (data.visibleUsers == null) throw new Error('invalid param');
for (const u of data.visibleUsers) {
// ローカルユーザーのみ
if (!this.userEntityService.isLocalUser(u)) continue;
this.noteReadService.insertNoteUnread(u.id, note, {
isSpecified: true,
isMentioned: false,
});
}
} else {
for (const u of mentionedUsers) {
// ローカルユーザーのみ
if (!this.userEntityService.isLocalUser(u)) continue;
this.noteReadService.insertNoteUnread(u.id, note, {
isSpecified: false,
isMentioned: true,
});
}
}
// Pack the note
const noteObj = await this.noteEntityService.pack(note, null, { skipHide: true, withReactionAndUserPairCache: true });
@ -733,13 +704,7 @@ export class NoteCreateService implements OnApplicationShutdown {
},
});
const [
userIdsWhoMeMuting,
] = data.renote.userId ? await Promise.all([
this.cacheService.userMutingsCache.fetch(data.renote.userId),
]) : [new Set<string>()];
const muted = isUserRelated(note, userIdsWhoMeMuting);
const muted = data.renote.userId && isUserRelated(note, await this.cacheService.userMutingsCache.fetch(data.renote.userId));
if (!isThreadMuted && !muted) {
nm.push(data.renote.userId, type);
@ -866,7 +831,8 @@ export class NoteCreateService implements OnApplicationShutdown {
@bindThis
private async createMentionedEvents(mentionedUsers: MinimumUser[], note: MiNote, nm: NotificationManager) {
for (const u of mentionedUsers.filter(u => this.userEntityService.isLocalUser(u))) {
// Only create mention events for local users, and users for whom the note is visible
for (const u of mentionedUsers.filter(u => (note.visibility !== 'specified' || note.visibleUserIds.some(x => x === u.id)) && this.userEntityService.isLocalUser(u))) {
const isThreadMuted = await this.noteThreadMutingsRepository.exists({
where: {
userId: u.id,
@ -874,13 +840,7 @@ export class NoteCreateService implements OnApplicationShutdown {
},
});
const [
userIdsWhoMeMuting,
] = u.id ? await Promise.all([
this.cacheService.userMutingsCache.fetch(u.id),
]) : [new Set<string>()];
const muted = isUserRelated(note, userIdsWhoMeMuting);
const muted = u.id && isUserRelated(note, await this.cacheService.userMutingsCache.fetch(u.id));
if (isThreadMuted || muted) {
continue;
@ -908,8 +868,8 @@ export class NoteCreateService implements OnApplicationShutdown {
if (data.localOnly) return null;
const content = this.isRenote(data) && !this.isQuote(data)
? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note)
: this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, user, false), note);
? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note, user)
: this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, user, false), note, user);
return this.apRendererService.addContext(content);
}

View file

@ -3,9 +3,9 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Brackets, In } from 'typeorm';
import { Brackets, In, IsNull, Not } from 'typeorm';
import { Injectable, Inject } from '@nestjs/common';
import type { MiUser, MiLocalUser, MiRemoteUser } from '@/models/User.js';
import type { MiUser, MiLocalUser, MiRemoteUser, MiPartialUser } from '@/models/User.js';
import { MiNote, IMentionedRemoteUsers } from '@/models/Note.js';
import type { InstancesRepository, MiMeta, NotesRepository, UsersRepository } from '@/models/_.js';
import { RelayService } from '@/core/RelayService.js';
@ -71,7 +71,7 @@ export class NoteDeleteService {
* @param user 稿
* @param note 稿
*/
async delete(user: { id: MiUser['id']; uri: MiUser['uri']; host: MiUser['host']; isBot: MiUser['isBot']; }, note: MiNote, quiet = false, deleter?: MiUser) {
async delete(user: MiPartialUser & { isBot: MiUser['isBot']; }, note: MiNote, quiet = false, deleter?: MiUser) {
const deletedAt = new Date();
const cascadingNotes = await this.findCascadingNotes(note);
@ -103,7 +103,7 @@ export class NoteDeleteService {
}
const content = this.apRendererService.addContext(renote
? this.apRendererService.renderUndo(this.apRendererService.renderAnnounce(renote.uri ?? `${this.config.url}/notes/${renote.id}`, note), user)
? this.apRendererService.renderUndo(this.apRendererService.renderAnnounce(renote.uri ?? `${this.config.url}/notes/${renote.id}`, note, user), user)
: this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${note.id}`), user));
this.deliverToConcerned(user, note, content);
@ -231,13 +231,27 @@ export class NoteDeleteService {
}) as MiRemoteUser[];
}
@bindThis
private async getRenotedOrRepliedRemoteUsers(note: MiNote) {
const query = this.notesRepository.createQueryBuilder('note')
.leftJoinAndSelect('note.user', 'user')
.where(new Brackets(qb => {
qb.orWhere('note.renoteId = :renoteId', { renoteId: note.id });
qb.orWhere('note.replyId = :replyId', { replyId: note.id });
}))
.andWhere({ userHost: Not(IsNull()) });
const notes = await query.getMany() as (MiNote & { user: MiRemoteUser })[];
const remoteUsers = notes.map(({ user }) => user);
return remoteUsers;
}
@bindThis
private async deliverToConcerned(user: { id: MiLocalUser['id']; host: null; }, note: MiNote, content: any) {
this.apDeliverManagerService.deliverToFollowers(user, content);
this.relayService.deliverToRelays(user, content);
const remoteUsers = await this.getMentionedRemoteUsers(note);
for (const remoteUser of remoteUsers) {
this.apDeliverManagerService.deliverToUser(user, content, remoteUser);
}
this.apDeliverManagerService.deliverToUsers(user, content, [
...await this.getMentionedRemoteUsers(note),
...await this.getRenotedOrRepliedRemoteUsers(note),
]);
}
}

View file

@ -8,6 +8,7 @@ import * as mfm from '@transfem-org/sfm-js';
import { DataSource, In, IsNull, LessThan } from 'typeorm';
import * as Redis from 'ioredis';
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
import { UnrecoverableError } from 'bullmq';
import { extractMentions } from '@/misc/extract-mentions.js';
import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm.js';
import { extractHashtags } from '@/misc/extract-hashtags.js';
@ -36,7 +37,6 @@ import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js';
import { NoteReadService } from '@/core/NoteReadService.js';
import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js';
import { bindThis } from '@/decorators.js';
import { RoleService } from '@/core/RoleService.js';
@ -203,7 +203,6 @@ export class NoteEditService implements OnApplicationShutdown {
private globalEventService: GlobalEventService,
private queueService: QueueService,
private fanoutTimelineService: FanoutTimelineService,
private noteReadService: NoteReadService,
private notificationService: NotificationService,
private relayService: RelayService,
private federatedInstanceService: FederatedInstanceService,
@ -233,7 +232,7 @@ export class NoteEditService implements OnApplicationShutdown {
noindex: MiUser['noindex'];
}, editid: MiNote['id'], data: Option, silent = false): Promise<MiNote> {
if (!editid) {
throw new Error('fail');
throw new UnrecoverableError('edit failed: missing editid');
}
const oldnote = await this.notesRepository.findOneBy({
@ -241,11 +240,11 @@ export class NoteEditService implements OnApplicationShutdown {
});
if (oldnote == null) {
throw new Error('no such note');
throw new UnrecoverableError(`edit failed for ${editid}: missing oldnote`);
}
if (oldnote.userId !== user.id) {
throw new Error('not the author');
throw new UnrecoverableError(`edit failed for ${editid}: user is not the note author`);
}
// we never want to change the replyId, so fetch the original "parent"
@ -276,12 +275,12 @@ export class NoteEditService implements OnApplicationShutdown {
data.channel = await this.channelsRepository.findOneBy({ id: data.reply.channelId });
}
if (data.updatedAt == null) data.updatedAt = new Date();
if (data.visibility == null) data.visibility = 'public';
if (data.localOnly == null) data.localOnly = false;
if (data.channel != null) data.visibility = 'public';
if (data.channel != null) data.visibleUsers = [];
if (data.channel != null) data.localOnly = true;
if (data.updatedAt == null) data.updatedAt = new Date();
if (data.visibility === 'public' && data.channel == null) {
const sensitiveWords = this.meta.sensitiveWords;
@ -310,7 +309,7 @@ export class NoteEditService implements OnApplicationShutdown {
if (this.isRenote(data)) {
if (data.renote.id === oldnote.id) {
throw new Error('A note can\'t renote itself');
throw new UnrecoverableError(`edit failed for ${oldnote.id}: cannot renote itself`);
}
switch (data.renote.visibility) {
@ -406,10 +405,10 @@ export class NoteEditService implements OnApplicationShutdown {
// Parse MFM if needed
if (!tags || !emojis || !mentionedUsers) {
const tokens = data.text ? mfm.parse(data.text)! : [];
const cwTokens = data.cw ? mfm.parse(data.cw)! : [];
const tokens = data.text ? mfm.parse(data.text) : [];
const cwTokens = data.cw ? mfm.parse(data.cw) : [];
const choiceTokens = data.poll && data.poll.choices
? concat(data.poll.choices.map(choice => mfm.parse(choice)!))
? concat(data.poll.choices.map(choice => mfm.parse(choice)))
: [];
const combinedTokens = tokens.concat(cwTokens).concat(choiceTokens);
@ -424,7 +423,7 @@ export class NoteEditService implements OnApplicationShutdown {
// if the host is media-silenced, custom emojis are not allowed
if (this.utilityService.isMediaSilencedHost(this.meta.mediaSilencedHosts, user.host)) emojis = [];
tags = tags.filter(tag => Array.from(tag ?? '').length <= 128).splice(0, 32);
tags = tags.filter(tag => Array.from(tag).length <= 128).splice(0, 32);
if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) {
mentionedUsers.push(await this.usersRepository.findOneByOrFail({ id: data.reply!.userId }));
@ -467,10 +466,8 @@ export class NoteEditService implements OnApplicationShutdown {
update.hasPoll = !!data.poll;
}
// technically we should check if the two sets of files are
// different, or if their descriptions have changed. In practice
// this is good enough.
const filesChanged = oldnote.fileIds?.length || data.files?.length;
// TODO deep-compare files
const filesChanged = oldnote.fileIds.length || data.files?.length;
const poll = await this.pollsRepository.findOneBy({ noteId: oldnote.id });
@ -564,7 +561,7 @@ export class NoteEditService implements OnApplicationShutdown {
noteVisibility: note.visibility,
userId: user.id,
userHost: user.host,
channelId: data.channel ? data.channel.id : null,
channelId: data.channel?.id ?? null,
});
if (!oldnote.hasPoll) {
@ -628,44 +625,12 @@ export class NoteEditService implements OnApplicationShutdown {
if (!silent) {
if (this.userEntityService.isLocalUser(user)) this.activeUsersChart.write(user);
// 未読通知を作成
if (data.visibility === 'specified') {
if (data.visibleUsers == null) throw new Error('invalid param');
for (const u of data.visibleUsers) {
// ローカルユーザーのみ
if (!this.userEntityService.isLocalUser(u)) continue;
this.noteReadService.insertNoteUnread(u.id, note, {
isSpecified: true,
isMentioned: false,
});
}
} else {
for (const u of mentionedUsers) {
// ローカルユーザーのみ
if (!this.userEntityService.isLocalUser(u)) continue;
this.noteReadService.insertNoteUnread(u.id, note, {
isSpecified: false,
isMentioned: true,
});
}
}
// Pack the note
const noteObj = await this.noteEntityService.pack(note, null, { skipHide: true, withReactionAndUserPairCache: true });
if (data.poll != null) {
this.globalEventService.publishNoteStream(note.id, 'updated', {
cw: note.cw,
text: note.text!,
});
} else {
this.globalEventService.publishNoteStream(note.id, 'updated', {
cw: note.cw,
text: note.text!,
});
}
this.globalEventService.publishNoteStream(note.id, 'updated', {
cw: note.cw,
text: note.text ?? '',
});
this.roleService.addNoteToRoleTimeline(noteObj);
@ -673,8 +638,6 @@ export class NoteEditService implements OnApplicationShutdown {
const nm = new NotificationManager(this.mutingsRepository, this.notificationService, user, note);
//await this.createMentionedEvents(mentionedUsers, note, nm);
// If has in reply to note
if (data.reply) {
// 通知
@ -697,7 +660,6 @@ export class NoteEditService implements OnApplicationShutdown {
if (!isThreadMuted && !muted) {
nm.push(data.reply.userId, 'edited');
this.globalEventService.publishMainStream(data.reply.userId, 'edited', noteObj);
this.webhookService.enqueueUserWebhook(data.reply.userId, 'reply', { note: noteObj });
}
}
@ -803,47 +765,12 @@ export class NoteEditService implements OnApplicationShutdown {
(note.files != null && note.files.length > 0);
}
// TODO why is this unused?
@bindThis
private async createMentionedEvents(mentionedUsers: MinimumUser[], note: MiNote, nm: NotificationManager) {
for (const u of mentionedUsers.filter(u => this.userEntityService.isLocalUser(u))) {
const isThreadMuted = await this.noteThreadMutingsRepository.exists({
where: {
userId: u.id,
threadId: note.threadId ?? note.id,
},
});
const [
userIdsWhoMeMuting,
] = u.id ? await Promise.all([
this.cacheService.userMutingsCache.fetch(u.id),
]) : [new Set<string>()];
const muted = isUserRelated(note, userIdsWhoMeMuting);
if (isThreadMuted || muted) {
continue;
}
const detailPackedNote = await this.noteEntityService.pack(note, u, {
detail: true,
});
this.globalEventService.publishMainStream(u.id, 'edited', detailPackedNote);
this.webhookService.enqueueUserWebhook(u.id, 'edited', { note: detailPackedNote });
// Create notification
nm.push(u.id, 'edited');
}
}
@bindThis
private async renderNoteOrRenoteActivity(data: Option, note: MiNote, user: MiUser) {
if (data.localOnly) return null;
const content = this.isRenote(data) && !this.isQuote(data)
? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note)
? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note, user)
: this.apRendererService.renderUpdate(await this.apRendererService.renderUpNote(note, user, false), user);
return this.apRendererService.addContext(content);

View file

@ -1,147 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { setTimeout } from 'node:timers/promises';
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
import { In } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { MiUser } from '@/models/User.js';
import type { Packed } from '@/misc/json-schema.js';
import type { MiNote } from '@/models/Note.js';
import { IdService } from '@/core/IdService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import type { NoteUnreadsRepository, MutingsRepository, NoteThreadMutingsRepository } from '@/models/_.js';
import { bindThis } from '@/decorators.js';
import { trackPromise } from '@/misc/promise-tracker.js';
@Injectable()
export class NoteReadService implements OnApplicationShutdown {
#shutdownController = new AbortController();
constructor(
@Inject(DI.noteUnreadsRepository)
private noteUnreadsRepository: NoteUnreadsRepository,
@Inject(DI.mutingsRepository)
private mutingsRepository: MutingsRepository,
@Inject(DI.noteThreadMutingsRepository)
private noteThreadMutingsRepository: NoteThreadMutingsRepository,
private idService: IdService,
private globalEventService: GlobalEventService,
) {
}
@bindThis
public async insertNoteUnread(userId: MiUser['id'], note: MiNote, params: {
// NOTE: isSpecifiedがtrueならisMentionedは必ずfalse
isSpecified: boolean;
isMentioned: boolean;
}): Promise<void> {
//#region ミュートしているなら無視
const mute = await this.mutingsRepository.findBy({
muterId: userId,
});
if (mute.map(m => m.muteeId).includes(note.userId)) return;
//#endregion
// スレッドミュート
const isThreadMuted = await this.noteThreadMutingsRepository.exists({
where: {
userId: userId,
threadId: note.threadId ?? note.id,
},
});
if (isThreadMuted) return;
const unread = {
id: this.idService.gen(),
noteId: note.id,
userId: userId,
isSpecified: params.isSpecified,
isMentioned: params.isMentioned,
noteUserId: note.userId,
};
/* we may be called from NoteEditService, for a note that's
already present in the `note_unread` table: `upsert` makes sure
we don't throw a "duplicate key" error, while still updating
the other columns if they've changed */
await this.noteUnreadsRepository.upsert(unread, ['userId', 'noteId']);
// 2秒経っても既読にならなかったら「未読の投稿がありますよ」イベントを発行する
setTimeout(2000, 'unread note', { signal: this.#shutdownController.signal }).then(async () => {
const exist = await this.noteUnreadsRepository.exists({ where: { id: unread.id } });
if (!exist) return;
if (params.isMentioned) {
this.globalEventService.publishMainStream(userId, 'unreadMention', note.id);
}
if (params.isSpecified) {
this.globalEventService.publishMainStream(userId, 'unreadSpecifiedNote', note.id);
}
}, () => { /* aborted, ignore it */ });
}
@bindThis
public async read(
userId: MiUser['id'],
notes: (MiNote | Packed<'Note'>)[],
): Promise<void> {
if (notes.length === 0) return;
const noteIds = new Set<MiNote['id']>();
for (const note of notes) {
if (note.mentions && note.mentions.includes(userId)) {
noteIds.add(note.id);
} else if (note.visibleUserIds && note.visibleUserIds.includes(userId)) {
noteIds.add(note.id);
}
}
if (noteIds.size === 0) return;
// Remove the record
await this.noteUnreadsRepository.delete({
userId: userId,
noteId: In(Array.from(noteIds)),
});
// TODO: ↓まとめてクエリしたい
trackPromise(this.noteUnreadsRepository.countBy({
userId: userId,
isMentioned: true,
}).then(mentionsCount => {
if (mentionsCount === 0) {
// 全て既読になったイベントを発行
this.globalEventService.publishMainStream(userId, 'readAllUnreadMentions');
}
}));
trackPromise(this.noteUnreadsRepository.countBy({
userId: userId,
isSpecified: true,
}).then(specifiedCount => {
if (specifiedCount === 0) {
// 全て既読になったイベントを発行
this.globalEventService.publishMainStream(userId, 'readAllUnreadSpecifiedNotes');
}
}));
}
@bindThis
public dispose(): void {
this.#shutdownController.abort();
}
@bindThis
public onApplicationShutdown(signal?: string | undefined): void {
this.dispose();
}
}

View file

@ -7,6 +7,7 @@ import { setTimeout } from 'node:timers/promises';
import * as Redis from 'ioredis';
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
import { In } from 'typeorm';
import { ReplyError } from 'ioredis';
import { DI } from '@/di-symbols.js';
import type { UsersRepository } from '@/models/_.js';
import type { MiUser } from '@/models/User.js';
@ -19,7 +20,7 @@ import { IdService } from '@/core/IdService.js';
import { CacheService } from '@/core/CacheService.js';
import type { Config } from '@/config.js';
import { UserListService } from '@/core/UserListService.js';
import type { FilterUnionByProperty } from '@/types.js';
import { FilterUnionByProperty, groupedNotificationTypes, obsoleteNotificationTypes } from '@/types.js';
import { trackPromise } from '@/misc/promise-tracker.js';
@Injectable()
@ -145,21 +146,36 @@ export class NotificationService implements OnApplicationShutdown {
}
}
const notification = {
id: this.idService.gen(),
createdAt: new Date(),
type: type,
...(notifierId ? {
notifierId,
} : {}),
...data,
} as any as FilterUnionByProperty<MiNotification, 'type', T>;
const createdAt = new Date();
let notification: FilterUnionByProperty<MiNotification, 'type', T>;
let redisId: string;
const redisIdPromise = this.redisClient.xadd(
`notificationTimeline:${notifieeId}`,
'MAXLEN', '~', this.config.perUserNotificationsMaxCount.toString(),
'*',
'data', JSON.stringify(notification));
do {
notification = {
id: this.idService.gen(),
createdAt,
type: type,
...(notifierId ? {
notifierId,
} : {}),
...data,
} as unknown as FilterUnionByProperty<MiNotification, 'type', T>;
try {
redisId = (await this.redisClient.xadd(
`notificationTimeline:${notifieeId}`,
'MAXLEN', '~', this.config.perUserNotificationsMaxCount.toString(),
this.toXListId(notification.id, 0),
'data', JSON.stringify(notification)))!;
} catch (e) {
// The ID specified in XADD is equal or smaller than the target stream top item で失敗することがあるのでリトライ
if (e instanceof ReplyError) continue;
throw e;
}
break;
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
} while (true);
const packed = await this.notificationEntityService.pack(notification, notifieeId, {});
@ -173,7 +189,7 @@ export class NotificationService implements OnApplicationShutdown {
const interval = notification.type === 'test' ? 0 : 2000;
setTimeout(interval, 'unread notification', { signal: this.#shutdownController.signal }).then(async () => {
const latestReadNotificationId = await this.redisClient.get(`latestReadNotification:${notifieeId}`);
if (latestReadNotificationId && (latestReadNotificationId >= (await redisIdPromise)!)) return;
if (latestReadNotificationId && (latestReadNotificationId >= redisId)) return;
this.globalEventService.publishMainStream(notifieeId, 'unreadNotification', packed);
this.pushNotificationService.pushNotification(notifieeId, 'notification', packed);
@ -228,6 +244,79 @@ export class NotificationService implements OnApplicationShutdown {
this.#shutdownController.abort();
}
private toXListId(id: string, offset: number): string {
const { date, additional } = this.idService.parseFull(id);
return (date + offset).toString() + '-' + additional.toString();
}
@bindThis
public async getNotifications(
userId: MiUser['id'],
{
sinceId,
untilId,
limit = 20,
includeTypes,
excludeTypes,
}: {
sinceId?: string,
untilId?: string,
limit?: number,
// any extra types are allowed, those are no-op
includeTypes?: (MiNotification['type'] | string)[],
excludeTypes?: (MiNotification['type'] | string)[],
},
): Promise<MiNotification[]> {
let sinceTime = sinceId ? this.toXListId(sinceId, 1) : null;
let untilTime = untilId ? this.toXListId(untilId, -1) : null;
let notifications: MiNotification[];
for (;;) {
let notificationsRes: [id: string, fields: string[]][];
// sinceidのみの場合は古い順、そうでない場合は新しい順。 QueryService.makePaginationQueryも参照
if (sinceTime && !untilTime) {
notificationsRes = await this.redisClient.xrange(
`notificationTimeline:${userId}`,
'(' + sinceTime,
'+',
'COUNT', limit);
} else {
notificationsRes = await this.redisClient.xrevrange(
`notificationTimeline:${userId}`,
untilTime ? '(' + untilTime : '+',
sinceTime ? '(' + sinceTime : '-',
'COUNT', limit);
}
if (notificationsRes.length === 0) {
return [];
}
notifications = notificationsRes.map(x => JSON.parse(x[1][1])) as MiNotification[];
if (includeTypes && includeTypes.length > 0) {
notifications = notifications.filter(notification => includeTypes.includes(notification.type));
} else if (excludeTypes && excludeTypes.length > 0) {
notifications = notifications.filter(notification => !excludeTypes.includes(notification.type));
}
if (notifications.length !== 0) {
// 通知が1件以上ある場合は返す
break;
}
// フィルタしたことで通知が0件になった場合、次のページを取得する
if (sinceId && !untilId) {
sinceTime = notificationsRes[notificationsRes.length - 1][0];
} else {
untilTime = notificationsRes[notificationsRes.length - 1][0];
}
}
return notifications;
}
@bindThis
public onApplicationShutdown(signal?: string | undefined): void {
this.dispose();

View file

@ -1,28 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import type { MiMeta, UsersRepository } from '@/models/_.js';
import type { MiLocalUser } from '@/models/User.js';
import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
@Injectable()
export class ProxyAccountService {
constructor(
@Inject(DI.meta)
private meta: MiMeta,
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
) {
}
@bindThis
public async fetch(): Promise<MiLocalUser | null> {
if (this.meta.proxyAccountId == null) return null;
return await this.usersRepository.findOneByOrFail({ id: this.meta.proxyAccountId }) as MiLocalUser;
}
}

View file

@ -69,7 +69,7 @@ export class QueryService {
// ここでいうBlockedは被Blockedの意
@bindThis
public generateBlockedUserQuery(q: SelectQueryBuilder<any>, me: { id: MiUser['id'] }): void {
public generateBlockedUserQueryForNotes(q: SelectQueryBuilder<any>, me: { id: MiUser['id'] }): void {
const blockingQuery = this.blockingsRepository.createQueryBuilder('blocking')
.select('blocking.blockerId')
.where('blocking.blockeeId = :blockeeId', { blockeeId: me.id });
@ -127,7 +127,7 @@ export class QueryService {
}
@bindThis
public generateMutedUserQuery(q: SelectQueryBuilder<any>, me: { id: MiUser['id'] }, exclude?: { id: MiUser['id'] }): void {
public generateMutedUserQueryForNotes(q: SelectQueryBuilder<any>, me: { id: MiUser['id'] }, exclude?: { id: MiUser['id'] }): void {
const mutingQuery = this.mutingsRepository.createQueryBuilder('muting')
.select('muting.muteeId')
.where('muting.muterId = :muterId', { muterId: me.id });
@ -213,7 +213,6 @@ export class QueryService {
.orWhere('note.userId = :meId')
// または 自分宛て
.orWhere(':meIdAsList <@ note.visibleUserIds')
.orWhere(':meIdAsList <@ note.mentions')
.orWhere(new Brackets(qb => {
qb
// または フォロワー宛ての投稿であり、
@ -223,7 +222,8 @@ export class QueryService {
// 自分がフォロワーである
.where(`note.userId IN (${ followingQuery.getQuery() })`)
// または 自分の投稿へのリプライ
.orWhere('note.replyUserId = :meId');
.orWhere('note.replyUserId = :meId')
.orWhere(':meIdAsList <@ note.mentions');
}));
}));
}));

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