Compare commits

...

257 Commits

Author SHA1 Message Date
syuilo
5bd68aa3e0 Merge pull request #10177 from misskey-dev/develop
Release: 13.9.0
2023-03-03 15:35:40 +09:00
tamaina
da3fcf178e fix CHANGELOG.md 2023-03-03 06:12:34 +00:00
syuilo
5d46c1c9bb (CSS完全に)理解した 2023-03-03 14:55:56 +09:00
syuilo
1b33653f1b 13.9.0 2023-03-03 12:32:05 +09:00
syuilo
af24011eec clean up 2023-03-03 12:31:41 +09:00
syuilo
87c6d0cbee 🎨 2023-03-03 12:29:34 +09:00
syuilo
3066a133ac fix(client): prevent null reference error 2023-03-03 11:43:53 +09:00
syuilo
436190966c New Crowdin updates (#10114)
* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

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

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (English)

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

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Thai)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Slovak)

* New translations ja-JP.yml (Ukrainian)

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

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

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Vietnamese)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Bengali)

* New translations ja-JP.yml (Thai)

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

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

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

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Slovak)

* New translations ja-JP.yml (Thai)

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

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

* New translations ja-JP.yml (Italian)
2023-03-03 11:37:32 +09:00
syuilo
b4e96181f5 localization: インスタンス -> サーバー
Resolve #7599
2023-03-03 11:36:26 +09:00
Kagami Sascha Rosylight
61215e50ff test(backend): APIテストの復活 (#10163)
* Revert 1c5291f818

* APIテストの復活

* apiテストの移行

* moduleNameMapper修正

* simpleGetでthrowしないように

status確認しているので要らない

* longer timeout

* ローカルでは問題ないのになんで

* case sensitive

* Run Nest instance within the current process

* Skip some setIntervals

* wait for 5 seconds

* kill them all!!

* logHeapUsage: true

* detectOpenHandlesがじゃましているらしい

* maxWorkers=1?

* restore drive api tests

* workerIdleMemoryLimit: 500MB

* 1024MiB

* Wait what
2023-03-03 11:13:12 +09:00
kabo2468
53987fadd7 fix(server): チャンネルでミュートが正しく機能していないのを修正 (#10166)
* fix(server): チャンネルでミュートが正しく機能していないのを修正

* Update CHANGELOG.md
2023-03-03 10:30:21 +09:00
syuilo
8a561bdb78 Update CHANGELOG.md 2023-03-03 10:09:51 +09:00
rinsuki
452a48e7f4 fix(server): DriveFile related N+1 query when call note packMany (#10133)
* fix(server): DriveFile related N+1 query when call note packMany

* Update packages/backend/src/misc/is-not-null.ts

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

* ignore lint

* 途中でやめたやつが混入していた

* fix: 順番通りである必要がある場所で順番通りになっていなかった

---------

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
2023-03-03 10:06:59 +09:00
syuilo
5248395fc5 update sounds 2023-03-03 09:41:33 +09:00
syuilo
cf8a7f93d5 🎨 2023-03-03 08:48:52 +09:00
syuilo
187a698d54 🎨 2023-03-02 20:47:24 +09:00
syuilo
ebd7b27075 clean up 2023-03-02 18:40:55 +09:00
syuilo
dad915e522 enhance(client): provide sticktyFooter 2023-03-02 18:40:43 +09:00
Kagami Sascha Rosylight
896400a6c9 refactor(frontend): add explicit Promise<void> return types in os.ts (#10156) 2023-03-02 15:05:05 +09:00
syuilo
fdf7605074 refactor(client): use css modules 2023-03-02 14:38:45 +09:00
syuilo
ea1cff499a update sounds 2023-03-02 08:36:15 +09:00
syuilo
b392564165 Update about-misskey.vue 2023-03-02 08:36:06 +09:00
syuilo
39e41d7424 🎨 2023-03-01 17:30:23 +09:00
syuilo
afa9c1f6f0 Update CHANGELOG.md 2023-03-01 17:22:32 +09:00
syuilo
47b1b09b21 enhance(client): add new sounds 2023-03-01 17:22:17 +09:00
Kagami Sascha Rosylight
44058f8b85 enhance(e2e): more resilient version of visit('/') (#10128) 2023-03-01 15:32:53 +09:00
Kagami Sascha Rosylight
6d82371449 fix(frontend): read KeyboardEvent.key instead of which/code (#10083) 2023-03-01 15:24:09 +09:00
KokiSakano
830fabef12 refactor: plugin.tsの型を修正する (#10027)
* refactor:plugin内のすべての関数にreturn typeを設定

* fix:pluginContextsから取得できない場合は早期リターンする

* fix:valueがstring以外の時は早期リターンする

* fix:valueが取得できる時以外は早期リターンする

* fix:pluginに型をつける

* fix:絞り込みをassertStringに変更

* fix:修正漏れ

* fix:valToJsからvalueを取得するように変更
2023-03-01 15:19:20 +09:00
Khsmty
c34e7e6e08 enhance(client): Renote した時の表示をリップルエフェクトと toast に (#10116)
* enhance(client): Renote した時の表示を toast に

* fix: lint エラー

* enhance(client): Renote した時の表示をリップルエフェクトに

* toast も追加

* rippleeffect のタイミング変更

* toast の位置を header に被らないように
2023-03-01 14:55:57 +09:00
syuilo
78d66d3806 🎨 2023-03-01 14:54:02 +09:00
syuilo
44f041587c 🎨 2023-03-01 14:46:53 +09:00
syuilo
d0bbeeee52 🎨 2023-03-01 14:22:53 +09:00
syuilo
9e5278d276 fix of #10145 2023-03-01 12:02:37 +09:00
syuilo
064a6bf065 🎨 2023-03-01 10:56:51 +09:00
syuilo
1c5291f818 feat: 時限ロール (#10145)
* feat: 時限ロール

* クライアントから期限を確認できるように

* リファクタとか

* fix test

* fix test

* fix test

* clean up
2023-03-01 10:20:03 +09:00
syuilo
7c3a390763 enhance(client): ノートの操作部をホバー時のみ表示するオプション 2023-02-28 20:53:32 +09:00
syuilo
83a67606a9 enhance(server): make antenna handle cw
Resolve #10140
2023-02-28 20:20:23 +09:00
tamaina
c1e69e7a53 enhance(client): emojisはIndexedDBに保存する (#10121)
* enhance(client): emojisはIndexedDBに保存する

* lastEmojisFetchedAt
2023-02-28 20:10:52 +09:00
syuilo
570f331477 Update CHANGELOG.md 2023-02-28 19:56:04 +09:00
tamaina
ffe3386e5b fix(sw): プッシュ通知でカスタム絵文字リアクションを表示できるように (#10122)
* fix(sw): プッシュ通知でカスタム絵文字リアクションを表示できるように
Fix #10117
/emoji/*.webpにbadgeモードを

* ?

* ✌️

* fix
2023-02-28 19:55:31 +09:00
牛蒡
c63447e194 enhance: Play の「ソースを表示」にシンタックスハイライトを当てる (#10107)
* シンタックスハイライトを当てる

* fix
2023-02-28 17:38:43 +09:00
tamaina
17d0bde50e fix(client): photoswipe(画像の拡大表示)がなんか変 (#10138)
* fix(client): photoswipe(画像の拡大表示)がなんか変
Fix  #10037

* important

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-28 17:26:42 +09:00
syuilo
4ea978000d Update CHANGELOG.md 2023-02-28 17:14:55 +09:00
tamaina
12932d2831 fix: 外部メディアプロキシ使用時にアバタークロップができない問題を修正 (#10142)
* wip

* fix

* Update packages/frontend/src/scripts/media-proxy.ts

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

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-28 17:14:23 +09:00
syuilo
1ba848e5f5 dev: introduce Reviewer lottery 2023-02-28 17:08:20 +09:00
syuilo
a6ea9de4b9 Update 03_release.md 2023-02-28 16:51:04 +09:00
syuilo
746770ac3b fix Serialized type 2023-02-28 16:46:25 +09:00
syuilo
ab7a8a2dae enhance(client): 招待コードが必要なことが分かりやすいように 2023-02-28 16:05:05 +09:00
syuilo
b60c985203 fix(server): メールアドレス更新時にバリデーションが正しく行われていないのを修正 2023-02-28 15:31:48 +09:00
syuilo
785c67ea8d 🎨 2023-02-28 15:27:54 +09:00
Kagami Sascha Rosylight
647a018362 fix(backend): return HTTP 404 for any unknown api endpoint paths (#10130)
* fix(backend): return HTTP 400 for any invalid api endpoint paths

* 404
2023-02-27 18:01:43 +09:00
syuilo
647ce174b3 Merge pull request #10112 from misskey-dev/develop
Release: 13.8.1
2023-02-26 20:57:13 +09:00
syuilo
81e6a21fe0 13.8.1 2023-02-26 20:52:00 +09:00
syuilo
d8dcce807b fix(client): モバイル環境でポップアップが表示されない
Fix #10110
2023-02-26 20:51:06 +09:00
syuilo
103dc32dce Update 03_release.md 2023-02-26 20:30:03 +09:00
syuilo
b7e72cfb7e Update CHANGELOG.md 2023-02-26 20:29:53 +09:00
syuilo
02c8fd9de5 Merge pull request #10108 from misskey-dev/develop
* Add dialog to remove follower (#9718)

* update PULL_REQUEST_TEMPLATE

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

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

* check:connectをstart内に移動

---------

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

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

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

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

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

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

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

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

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

* fix(client): MkTimeを改良

* numberを許容

* falsyな値もとる

* 不明

* ありません

* fix

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

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

* NO_SUCH_FILE

* Update codecov.yml

* Update apple-touch-icon.png

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

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

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

* enhance(client): improve clip menu ux

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

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

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

* 順番関係ある?

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

* Update @swc/core to v1.3.36

* Update CHANGELOG.md

* Update CHANGELOG.md

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

* 🎨

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

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

* fix: エラーの修正

* add: changelog

---------

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

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

Resolve #10019

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

Resolve #10078

* Update CHANGELOG.md

* enhance(client): tweak contextmenu position calculation

* 🎨

* 🎨

* feat: in-channel featured note

Resolve #9938

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

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

* Simplify search.vue

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

* Remove unused imports

* Update about-misskey.vue

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

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

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

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

* ✌️

* wip

* wip

* ✌️

* RequiredProp

* Revert "RequiredProp"

This reverts commit 7469390011.

* add api:notes/create

* fix lint

* text

* ✌️

* improve readability

---------

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

* New Crowdin updates (#10059)

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

* New translations ja-JP.yml (Romanian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Slovak)

* New translations ja-JP.yml (Ukrainian)

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

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

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Vietnamese)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Bengali)

* New translations ja-JP.yml (Thai)

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

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

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

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Ukrainian)

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

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (Ukrainian)

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

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

* New translations ja-JP.yml (Thai)

* New translations ja-JP.yml (Thai)

* New translations ja-JP.yml (Thai)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Spanish)

* enhance(client): improve user menu ux

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

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

* add: changelog

---------

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

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

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

* Update codecov.yml

* Update CHANGELOG.md

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

Fix #10064

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

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

* Applied editorconfig for pnpm-workspace.yaml

---------

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

* update deps

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

* refactor

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

* Update CHANGELOG.md

* 13.8.0

---------

Co-authored-by: atsuchan <83960488+atsu1125@users.noreply.github.com>
Co-authored-by: Masaya Suzuki <15100604+massongit@users.noreply.github.com>
Co-authored-by: tamaina <tamaina@hotmail.co.jp>
Co-authored-by: Kagami Sascha Rosylight <saschanaz@outlook.com>
Co-authored-by: taiy <53635909+taiyme@users.noreply.github.com>
Co-authored-by: xianon <xianon@hotmail.co.jp>
Co-authored-by: kabo2468 <28654659+kabo2468@users.noreply.github.com>
Co-authored-by: YS <47836716+yszkst@users.noreply.github.com>
Co-authored-by: Khsmty <me@khsmty.com>
Co-authored-by: Soni L <EnderMoneyMod@gmail.com>
Co-authored-by: mei23 <m@m544.net>
Co-authored-by: daima3629 <52790780+daima3629@users.noreply.github.com>
Co-authored-by: Windymelt <1113940+windymelt@users.noreply.github.com>
2023-02-26 20:21:54 +09:00
tamaina
cf950224de Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-26 11:10:29 +00:00
tamaina
02d7ffd305 fix(server): 単純にrenoteできないのを修正 2023-02-26 11:10:24 +00:00
syuilo
9f8c9dd881 Update packages/backend/check_connect.js
Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
2023-02-26 20:07:52 +09:00
syuilo
d019c1c440 Update packages/backend/check_connect.js
Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
2023-02-26 20:07:45 +09:00
syuilo
a56898df94 13.8.0 2023-02-26 19:03:22 +09:00
syuilo
f78c519ae5 Update CHANGELOG.md 2023-02-26 19:02:35 +09:00
syuilo
dc9ef87c44 New translations ja-JP.yml (French) (#10103) 2023-02-26 19:02:06 +09:00
syuilo
a78a839841 refactor 2023-02-26 18:57:24 +09:00
xianon
67ca7ee4ec ホームタイムラインの読み込みでクエリタイムアウトになるのを修正する (#10106) 2023-02-26 18:54:52 +09:00
syuilo
76f3bdcdf9 update deps 2023-02-26 18:51:45 +09:00
Windymelt
9234ffc927 [chore]Editorconfig: ymlに加えてyamlファイルに対しても同じ規約を適用する (#10081)
* Added yaml file in addition to yml file, in editorconfig

* Applied editorconfig for pnpm-workspace.yaml

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-26 18:18:23 +09:00
syuilo
cc149e2f46 fix(server): エラーのスタックトレースは返さないように
Fix #10064
2023-02-26 17:12:15 +09:00
syuilo
cedfb85b60 Update CHANGELOG.md 2023-02-26 14:21:54 +09:00
syuilo
302af7099c Update codecov.yml 2023-02-26 14:17:29 +09:00
daima3629
1bdde6bd5c [Fix] fixed an typo in error message (#10102) 2023-02-26 14:14:57 +09:00
syuilo
2acdd933c0 enhance(client): メニューの「もっと」からインスタンス情報を見れるように 2023-02-26 12:50:34 +09:00
Khsmty
72888b4814 enhance(client): photoswipe 表示時に戻る操作をしても前の画面に戻らないように (#10098)
* enhance(client): photoswipe 表示時に戻る操作をしても前の画面に戻らないように

* add: changelog

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-26 12:25:27 +09:00
syuilo
60342ed3fa enhance(client): improve user menu ux 2023-02-26 11:57:37 +09:00
syuilo
504baa9de2 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-26 11:32:31 +09:00
syuilo
16ac03322c New Crowdin updates (#10059)
* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Romanian)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Arabic)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Slovak)

* New translations ja-JP.yml (Ukrainian)

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

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

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Vietnamese)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Bengali)

* New translations ja-JP.yml (Thai)

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

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

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

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Ukrainian)

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

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (Ukrainian)

* New translations ja-JP.yml (Ukrainian)

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

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

* New translations ja-JP.yml (Thai)

* New translations ja-JP.yml (Thai)

* New translations ja-JP.yml (Thai)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Spanish)
2023-02-26 11:32:10 +09:00
syuilo
52d86275b6 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-26 11:32:07 +09:00
tamaina
18dbcfa0b0 test(server): add validation test of api:notes/create (#10090)
* fix(server): notes/createのバリデーションが効いていない
Fix #10079

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

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

* ✌️

* wip

* wip

* ✌️

* RequiredProp

* Revert "RequiredProp"

This reverts commit 7469390011.

* add api:notes/create

* fix lint

* text

* ✌️

* improve readability

---------

Co-authored-by: mei23 <m@m544.net>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-26 11:28:05 +09:00
syuilo
991945ea26 Update about-misskey.vue 2023-02-26 11:24:09 +09:00
Soni L
dbd9d11d67 Simplify search.vue (remove dead code) (#10088)
* Simplify search.vue

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

* Remove unused imports
2023-02-26 11:14:07 +09:00
Kagami Sascha Rosylight
209d8b4f39 refactor(frontend): fix eslint error (#10084) 2023-02-25 18:27:15 +09:00
syuilo
ea04778649 feat: in-channel featured note
Resolve #9938
2023-02-25 18:26:35 +09:00
syuilo
24553eb69a 🎨 2023-02-25 18:03:16 +09:00
syuilo
86eab355c6 🎨 2023-02-25 17:49:54 +09:00
syuilo
e7a1046b87 enhance(client): tweak contextmenu position calculation 2023-02-25 13:44:37 +09:00
syuilo
3c01c0cbf2 Update CHANGELOG.md 2023-02-25 09:46:28 +09:00
syuilo
a683278fb8 enhance(client): renoteした際の表示を改善
Resolve #10078
2023-02-25 09:44:35 +09:00
syuilo
5bea4feac8 enhance(client): ノートメニューからユーザーメニューを開けるように
Resolve #10019
2023-02-25 09:18:36 +09:00
Khsmty
64be363adc feat: 2つの検索画面の統合 (#9949) (#10038)
* feat: 検索画面の UI を統一

* fix: エラーの修正

* add: changelog

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-25 09:01:21 +09:00
syuilo
68e53f1526 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-25 08:58:55 +09:00
syuilo
dd3a65b52b 🎨 2023-02-25 08:58:51 +09:00
YS
cc8d60e53b バックグラウンドで一定時間経過したらページネーションのアイテム更新をしない (#10053) 2023-02-25 08:18:12 +09:00
kabo2468
1c9c9745f5 Windows環境でswcを使うと正常にビルドができない問題の修正 (#10074)
* Update @swc/core to v1.3.36

* Update CHANGELOG.md

* Update CHANGELOG.md
2023-02-25 05:22:36 +09:00
tamaina
8b30c0c0cd fix(client): Android ChromeでPWAとしてインストールできない問題を修正 (#10069)
* fix(client): Android ChromeでPWAとしてインストールできない問題を修正

* 順番関係ある?
2023-02-25 05:22:09 +09:00
xianon
0ec5327474 未知のユーザーが deleteActor されたら処理をスキップする (#10067) 2023-02-25 04:27:37 +09:00
syuilo
0691901345 enhance(client): improve clip menu ux 2023-02-24 20:48:19 +09:00
Masaya Suzuki
a7943dceca デプロイされているプレビュー環境がない場合はプレビュー環境を削除しないようにする (#10062)
* デプロイされているプレビュー環境がない場合はDestroy preview environmentを実行しないようにする

* CIがない場合の処理追加
2023-02-24 18:51:31 +09:00
syuilo
c4429ca65e Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-24 18:18:53 +09:00
syuilo
b7961b00fe Update apple-touch-icon.png 2023-02-24 18:18:50 +09:00
syuilo
759c4a8976 Update codecov.yml 2023-02-24 16:43:08 +09:00
tamaina
e4336f5b76 fix(server): notes/createで、fileIdsと見つかったファイルの数が異なる場合はエラーにする (#9911)
* fix(server): notes/createで、fileIdsと見つかったファイルの数が異なる場合はエラーにする

* NO_SUCH_FILE
2023-02-24 16:32:01 +09:00
tamaina
5c989ed18f fix/refaftor(client): MkTime.vueの変更 (#10061)
* fix(client): MkTime.timeにstringでもDateでない値が入った場合、?を表示

* fix(client): MkTimeを改良

* numberを許容

* falsyな値もとる

* 不明

* ありません

* fix
2023-02-24 16:21:49 +09:00
Kagami Sascha Rosylight
d1d3b48e51 test(backend): restore ap-request tests (#9997)
Co-authored-by: tamaina <tamaina@hotmail.co.jp>
2023-02-24 16:10:48 +09:00
taiy
8856d68571 enhance(client): MkUrlPreviewの閉じるボタンを見やすく (#9913)
Co-authored-by: tamaina <tamaina@hotmail.co.jp>
2023-02-24 14:38:47 +09:00
Kagami Sascha Rosylight
9edd0d25c2 Pass --detectOpenHandles to Jest (#9895)
Co-authored-by: tamaina <tamaina@hotmail.co.jp>
2023-02-24 14:37:22 +09:00
Masaya Suzuki
6b52403d05 起動時にRedisの疎通確認を行う (#9832)
* 起動時にRedisの疎通確認を行う

* check:connectをstart内に移動

---------

Co-authored-by: tamaina <tamaina@hotmail.co.jp>
2023-02-24 14:09:17 +09:00
syuilo
55cc6b8dee update PULL_REQUEST_TEMPLATE 2023-02-24 13:48:17 +09:00
atsuchan
e211d4e0cb Add dialog to remove follower (#9718) 2023-02-24 13:08:06 +09:00
syuilo
1ba49b614d Merge pull request #10058 from misskey-dev/develop
Release: 13.7.5
2023-02-24 13:06:55 +09:00
syuilo
320e5dba83 13.7.5 2023-02-24 11:41:47 +09:00
syuilo
9cc08ab3d8 13.7.4 2023-02-24 10:36:53 +09:00
syuilo
390369498b Update CHANGELOG.md 2023-02-24 10:31:45 +09:00
arrow2nd
9c787a578e feat(frontend): スマホ・タブレットの場合、チャンネルの投稿フォームに自動でフォーカスしないように (#10051)
* feat(frontend): スマホ・タブレットの場合、チャンネルの投稿フォームに自動でフォーカスしない

* Update CHANGELOG.md
2023-02-24 10:31:21 +09:00
syuilo
e516a63272 New Crowdin updates (#10057)
* 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 (Catalan)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Greek)

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Portuguese)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Slovak)

* New translations ja-JP.yml (Swedish)

* New translations ja-JP.yml (Ukrainian)

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

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

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Vietnamese)

* New translations ja-JP.yml (Indonesian)

* New translations ja-JP.yml (Bengali)

* New translations ja-JP.yml (Thai)

* New translations ja-JP.yml (Lao)

* New translations ja-JP.yml (Kabyle)

* New translations ja-JP.yml (Japanese, Kansai)
2023-02-24 10:30:52 +09:00
syuilo
d564202355 Update about-icon.png 2023-02-24 10:30:34 +09:00
syuilo
ff8437c378 enhance(client): ローカルのみ -> 連合なし
Resolve #10055
2023-02-24 10:24:25 +09:00
syuilo
ec092579a6 Update CONTRIBUTING.md 2023-02-24 09:14:58 +09:00
tamaina
40de14415c Release: 13.7.4
Merge pull request #10050 from misskey-dev/develop
2023-02-23 23:11:25 +09:00
tamaina
a1f3bd6865 fix CHANGELOG 2023-02-23 14:03:02 +00:00
tamaina
c925e3d281 fix(server): 全ての通知が削除されてしまうのを修正 2023-02-23 14:01:18 +00:00
tamaina
7c9330a02f Release: 13.7.3
Merge pull request #10048 from misskey-dev/develop
2023-02-23 22:15:56 +09:00
syuilo
ca99468970 Update CONTRIBUTING.md 2023-02-23 20:49:09 +09:00
syuilo
8a5c6240b4 Merge branch 'master' into develop 2023-02-23 20:48:20 +09:00
syuilo
fca820c90c 13.7.3 2023-02-23 20:47:19 +09:00
tamaina
becc4d2e54 fix: i/notificationsで古い通知タイプを許容するなど、古い通知タイプの清算 (#10042)
* wip

* fix

* create migration

* oops

* fix front const

* changelog

* fix type

* fix

* wip

* Revert "wip"

This reverts commit 6cdb3600e2.

* enumのこす

* fix

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-23 20:46:14 +09:00
syuilo
c645f9f99f chore(dev): remove outdated tip 2023-02-23 20:36:03 +09:00
tamaina
a5341cbd7d CONTRIBUTING: enumの削除は気をつける 2023-02-23 11:33:49 +00:00
syuilo
3dd363a6c5 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-23 20:26:36 +09:00
syuilo
e630803922 enumの変更はしない 2023-02-23 20:26:33 +09:00
tamaina
cb3b167d61 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-23 10:56:10 +00:00
tamaina
774b7fed1f update CHANGELOG.md 2023-02-23 10:55:54 +00:00
syuilo
cbf526b043 chore(client): tweak online users widget 2023-02-23 19:51:10 +09:00
syuilo
48331bc851 chore(client): tweak deck experience 2023-02-23 19:49:24 +09:00
tamaina
bda3d69539 fix(client):「キャッシュを削除」した後、ローカルのカスタム絵文字が表示されなくなる問題を修正
Fix #10044
2023-02-23 10:29:20 +00:00
syuilo
71900e0231 Release: 13.7.2 (#10035)
* ci: swcにしたためtypecheckは別途実施

* 🎨

* Update package.json

* マイグレーションが失敗することがあるのを修正

* refactor ci

* use tsc for build

Windowsだとエラーが出るため

* feat: swc build in windows (#10032)

* feat: add optional swc

* fix: windowsで動かない現象を修正

* fix: fix swc path alias

* fix: docker build時に`Host key verification failed`と言われてgitリポジトリからパッケージをインストールできないのでssh -> htpsに変更

* use swc

* chore(client): tweak custom emoji size

* enhance: make pwa icon maskable (#10033)

* 🎨

* feat(server): add @swc/core-android-arm64 to optional (#10034)

* feat: add optional swc

* fix: windowsで動かない現象を修正

* fix: fix swc path alias

* fix: docker build時に`Host key verification failed`と言われてgitリポジトリからパッケージをインストールできないのでssh -> htpsに変更

* feat(server): add @swc/core-android-arm64 to optional

* fix: conflict

* Update package.json

* chore(backend): fix indent

* Update CHANGELOG.md

* compress png

---------

Co-authored-by: CaffeinePower <86540016+cffnpwr@users.noreply.github.com>
Co-authored-by: Shogo Sensui <shogosensui@gmail.com>
Co-authored-by: tamaina <tamaina@hotmail.co.jp>
2023-02-23 17:36:36 +09:00
syuilo
694f08c79b compress png 2023-02-23 17:34:29 +09:00
syuilo
c328584bb6 Update CHANGELOG.md 2023-02-23 17:30:01 +09:00
tamaina
4c01198811 chore(backend): fix indent 2023-02-23 08:15:54 +00:00
syuilo
7781497b42 Update package.json 2023-02-23 16:42:36 +09:00
CaffeinePower
cde0eb621d feat(server): add @swc/core-android-arm64 to optional (#10034)
* feat: add optional swc

* fix: windowsで動かない現象を修正

* fix: fix swc path alias

* fix: docker build時に`Host key verification failed`と言われてgitリポジトリからパッケージをインストールできないのでssh -> htpsに変更

* feat(server): add @swc/core-android-arm64 to optional

* fix: conflict
2023-02-23 16:23:16 +09:00
syuilo
474b8789a7 🎨 2023-02-23 16:03:50 +09:00
Shogo Sensui
2189acdde1 enhance: make pwa icon maskable (#10033) 2023-02-23 15:59:21 +09:00
syuilo
c174f23389 chore(client): tweak custom emoji size 2023-02-23 15:42:57 +09:00
syuilo
4e23500732 use swc 2023-02-23 15:36:47 +09:00
CaffeinePower
b965f5e4a9 feat: swc build in windows (#10032)
* feat: add optional swc

* fix: windowsで動かない現象を修正

* fix: fix swc path alias

* fix: docker build時に`Host key verification failed`と言われてgitリポジトリからパッケージをインストールできないのでssh -> htpsに変更
2023-02-23 15:36:17 +09:00
syuilo
d1a69abf81 use tsc for build
Windowsだとエラーが出るため
2023-02-23 11:06:23 +09:00
syuilo
d2ef0efbff refactor ci 2023-02-23 10:56:01 +09:00
syuilo
ce5c78d0d2 マイグレーションが失敗することがあるのを修正 2023-02-23 10:40:15 +09:00
syuilo
28bea88da0 Update package.json 2023-02-23 10:17:00 +09:00
syuilo
a2e6f459e7 🎨 2023-02-23 08:29:16 +09:00
syuilo
0026c45fe0 ci: swcにしたためtypecheckは別途実施 2023-02-23 08:23:55 +09:00
syuilo
424292f335 Merge branch 'develop' 2023-02-23 08:09:32 +09:00
syuilo
8ca2f24df6 13.7.1 2023-02-23 08:09:22 +09:00
syuilo
fb7e5a3fac enhance(client): tweak renote collapsing logic 2023-02-23 08:08:17 +09:00
nenohi
5dd24e44d1 マイグレーションファイルの変更ミス (#10029) 2023-02-23 07:52:01 +09:00
tamaina
f7c6ea93d7 perf(backend): Use swc on pnpm build (#10026)
* perf(backend): Use swc on pnpm build

* update CHANGELOG

* no jest
2023-02-22 23:09:24 +09:00
syuilo
7658351041 Merge branch 'develop' 2023-02-22 18:06:25 +09:00
syuilo
833e2869e7 13.7.0 2023-02-22 18:06:06 +09:00
syuilo
5b3a07ee9e Revert "Allow configuring the listen host (#9924)"
This reverts commit 3dfe3aa9a4.
2023-02-22 18:00:35 +09:00
ledlamp
3dfe3aa9a4 Allow configuring the listen host (#9924) 2023-02-22 17:51:40 +09:00
syuilo
f68e13d905 New Crowdin updates (#9897)
* New translations ja-JP.yml (Japanese, Kansai)

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

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

* New translations ja-JP.yml (Italian)

* New translations ja-JP.yml (Italian)

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

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Italian)

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

* New translations ja-JP.yml (Ukrainian)
2023-02-22 17:46:23 +09:00
syuilo
3157d81e95 enhance(client): make possible to reload page of window
Resolve #10007
2023-02-22 17:43:10 +09:00
potpro
bd13ea3d2c MFMのDOM ParserをJSDOMからhappy-domに変更する (#10016)
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-22 17:32:45 +09:00
syuilo
f0cb587c89 fix(client): ユーザーのハッシュタグ検索が機能していないのを修正 2023-02-22 17:25:33 +09:00
syuilo
84e2ee220b fix(server): tweak admin/show-user api
Fix #9883
2023-02-22 17:17:36 +09:00
syuilo
a7977c6642 fix #10021 2023-02-22 17:14:23 +09:00
syuilo
1dfcd45704 Update ROADMAP.md 2023-02-22 16:38:00 +09:00
syuilo
8013cd2e79 Create codecov.yml 2023-02-22 15:51:39 +09:00
syuilo
9c69501404 lint 2023-02-22 15:50:08 +09:00
syuilo
0c8d874e3a lint 2023-02-22 15:36:12 +09:00
syuilo
0fb9c372dd lint 2023-02-22 15:28:17 +09:00
syuilo
3bb7afe544 improve performance of some tests 2023-02-22 15:16:29 +09:00
syuilo
29399e1ddc fix test 2023-02-22 15:12:21 +09:00
syuilo
dfc1410bb0 fix e2e 2023-02-22 15:03:30 +09:00
syuilo
9b72e02da3 tweak ci 2023-02-22 15:02:39 +09:00
syuilo
5ec07ede7c fix types 2023-02-22 14:58:41 +09:00
syuilo
72d4ad4c45 fix type 2023-02-22 14:53:36 +09:00
dojineko
a6fb6150a3 chore: add tiny definition for redis-lock (#9971)
* add tiny definition for redis-lock

* Update packages/backend/src/@types/redis-lock.d.ts

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

* fix type name

* add @typescript-eslint/naming-convention

* define taskToPerform type

* chore: use default settings for `@typescript-eslint/naming-convention`

* set `format:none` to typeParameter (default)

* ignore lines to be treated as exceptions

* chore: fix naming

---------

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-22 14:51:34 +09:00
tamaina
b9ee14fe5b fix: MkUserSelectDialog/search-by-username-and-hostでローカルユーザーを絞って検索できない問題を修正 (#9943)
* fix: MkUserSelectDialog/search-by-username-and-hostでローカルユーザーを絞って検索できない問題を修正
Fix #9627

* update CHANGELOG.md

* clean up

* search-by-username-and-host大改造
2023-02-22 14:47:51 +09:00
syuilo
6e68a78d6a Update CHANGELOG.md 2023-02-22 14:44:10 +09:00
syuilo
870f7608be enhance: exploreで公開ロール一覧とそのメンバーを閲覧できるように 2023-02-22 14:43:18 +09:00
syuilo
69869307bf enhance(client): improve entrance page
Resolve #9986
2023-02-22 11:00:34 +09:00
syuilo
b161f38710 fix(server): improve security of admin/drive/show-file 2023-02-21 14:47:11 +09:00
kabo2468
a7f464147d enhance(client): MFMのx3, x4が含まれていたらノートをたたむようにした (#10012) 2023-02-21 10:45:53 +09:00
syuilo
8eb87c8e4d Update CHANGELOG.md 2023-02-21 10:44:17 +09:00
syuilo
7925b130e8 fix syntax error 2023-02-21 10:41:09 +09:00
syuilo
16e3cb01ca Update about-misskey.vue 2023-02-21 10:18:54 +09:00
nenohi
543ba2b3b7 管理画面の広告を10個以上見えるように (#9990)
* 日付のフォーマット指定と変更がうまくいかない

* もっとのボタンで応急処置

* Update packages/frontend/src/pages/admin/ads.vue

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

* Update packages/frontend/src/pages/admin/ads.vue

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

* Update packages/frontend/src/pages/admin/ads.vue

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

* Revert "日付のフォーマット指定と変更がうまくいかない"

This reverts commit c8a81364ef.

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-20 17:57:01 +09:00
syuilo
beb9cd5710 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-20 17:28:13 +09:00
syuilo
b5fa8767da 🎨 2023-02-20 17:28:09 +09:00
Kagami Sascha Rosylight
f846b207b6 test(backend): restore emoji reaction tests (#9996) 2023-02-20 17:24:39 +09:00
Kagami Sascha Rosylight
c6b07acdcc test(backend): restore more unit tests (#9994) 2023-02-20 17:24:09 +09:00
xianon
b055f516c0 削除済みのユーザーが deleteActor される時の動作を修正する (#9980) 2023-02-20 17:08:05 +09:00
syuilo
716ffcace6 update deps 2023-02-20 17:04:57 +09:00
tamaina
980bf1306e 🎨 2FA設定のデザイン向上 / セキュリティキーの名前を変更できるように (#9985)
* wip

* fix

* wip

* wip

* ✌️

* rename key

* 🎨

* update CHANGELOG.md

* パスワードレスログインの判断はサーバーで

* 日本語

* 日本語

* 日本語

* 日本語

* ✌️

* fix

* refactor

* トークン→確認コード

* fix password-less / qr click

* use otpauth

* 日本語

* autocomplete

* パスワードレス設定は外に出す

* 🎨

* 🎨

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-20 16:40:24 +09:00
noonworks
ea92254b73 refactor: 型エラー修正 / Fix type errors backend (#9983)
* refactor: fix type errors in backend

* revert some changes

* なるべくJS挙動を変えない方法に修正

* Update packages/backend/src/server/api/ApiCallService.ts

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

* コンフリクトするファイルを削除

---------

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
2023-02-20 08:13:37 +09:00
tamaina
16ba1b3708 fix typescript version on vscode 2023-02-19 12:29:04 +00:00
syuilo
47b6f466ec enhance(client): snap scroll on deck 2023-02-19 19:54:19 +09:00
syuilo
2e76fcdf6f Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-19 17:50:16 +09:00
syuilo
7ce0f79f7f chore(server): tweak notes/featured api 2023-02-19 17:50:14 +09:00
syuilo
0c59dd3da7 Update about-misskey.vue 2023-02-19 17:49:55 +09:00
Kagami Sascha Rosylight
2aa73fdf6c test(backend): restore AP unit tests (#9987) 2023-02-19 15:27:14 +09:00
tamaina
cd5615d354 fix lint 2023-02-18 14:11:45 +00:00
tamaina
8c883653c9 fix/enhance(sw): プッシュ通知 (バックグラウンドで開いている場合も通知, リアクション通知はノートにつき1つに) (#9977)
* fix(sw): クライアントがあってもpush notificationを無視しない
「プッシュ通知を更新しました」の原因になるため

* enhance(sw): リアクション通知は1つのノートにつき1つしか表示しない
Safari対応で、通知tagは能動的に閉じるように

* revert closeNotificationsByTags
2023-02-18 17:48:20 +09:00
tamaina
36170a11f5 refactor(sw): self => globalThis 2023-02-18 05:16:34 +00:00
syuilo
0f546b47d1 refactor: fix types 2023-02-17 15:39:10 +09:00
syuilo
60df819c60 refactor: fix types 2023-02-17 15:36:36 +09:00
syuilo
0e1b5d6f14 refactor: fix types 2023-02-17 15:15:36 +09:00
syuilo
bde22208fe refactor: fix types 2023-02-17 15:06:52 +09:00
syuilo
d4eb1def61 fix(client): MkHeader及びデッキのカラムでチャンネル一覧を選択したとき、最大5個までしか表示されない
Fix #9904
2023-02-17 14:59:11 +09:00
syuilo
14cff15c89 enhance(client): add quiz preset for play 2023-02-17 14:57:05 +09:00
tamaina
e8c5307f66 perf(client): ウェルカムページを最適化 (#9960)
* perf(client): ウェルカムページの最適化

* remove max
2023-02-17 12:38:30 +09:00
Kagami Sascha Rosylight
dd52be3a01 ci: run typecheck and eslint separately (#9966)
* ci: run typecheck and eslint separately

* fix syntax
2023-02-17 10:57:40 +09:00
Kagami Sascha Rosylight
8f9ce23e52 style(backend): fix all eslint errors (#9967) 2023-02-17 10:56:59 +09:00
Kagami Sascha Rosylight
7c5fc2c423 style(frontend): fix autofixable eslint errors (#9968) 2023-02-17 10:56:23 +09:00
Kagami Sascha Rosylight
63df2c851e refactor: remove all unused imports (#9951)
Co-authored-by: tamaina <tamaina@hotmail.co.jp>
2023-02-16 23:09:41 +09:00
tamaina
4db787c4ee fix(server): マイグレーションad1676438468213が通らないのを修正 (#9963)
* fix(server): マイグレーションad1676438468213が通らないのを修正
Fix #9962

* fix
2023-02-16 22:08:45 +09:00
tamaina
839a626716 fix(server): dropGroupマイグレーションが通るように (#9961) 2023-02-16 22:07:34 +09:00
Kagami Sascha Rosylight
ef7ad05c0b Fix type errors from vite.json5.ts (#9936) 2023-02-15 17:14:47 +09:00
syuilo
e24b0ceb80 startAt -> startsAt 2023-02-15 14:31:59 +09:00
nenohi
71c42bef9b 広告開始時期の設定 (#9944)
* 広告開始時期の設定

* 過去のものも表示するように
2023-02-15 14:29:40 +09:00
syuilo
8caf288ac1 drop group (#9942)
* drop group

* Update operations.ts
2023-02-15 13:37:18 +09:00
syuilo
8f2049bcd2 drop messaging (#9919)
* drop messaging (from backend)

* wip
2023-02-15 13:06:06 +09:00
tamaina
d0aba46ee3 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-14 07:25:29 +00:00
tamaina
57c94a5cf0 fix(client): ユーザーページのファイル付きTLはリプライも含む 2023-02-14 07:25:14 +00:00
Kohei Ota (inductor)
c1f1e0ee7c Revert "attempt matrix build (#9927)" (#9930)
This reverts commit 192ea9738d.
2023-02-14 15:00:50 +09:00
Kohei Ota (inductor)
192ea9738d attempt matrix build (#9927) 2023-02-14 14:38:53 +09:00
Kohei Ota (inductor)
37b849ad1f Add Description on Chart.yaml (#9928) 2023-02-14 14:34:59 +09:00
tamaina
4e68126c06 enhance(server): URLプレビュー(summaly)はプロキシを通すように (#9905)
* enhance(server): URLプレビュー(summaly)はプロキシを通すように

* update summaly

* update summaly

* 型エラーバスター

* basic.html

* Delete basic.html

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-14 14:17:07 +09:00
RyotaK
c7fbf5637f fix: Dev Containerの設定を修正 (#9921)
* Dev Containerの設定を修正

* CONTRIBUTING.mdにDev Container使用時の注意書きを追加

* 注意書きを改行する
2023-02-14 13:17:34 +09:00
taiy
5cf5b66696 fix(client): use tabler icons (#9915) 2023-02-14 13:17:00 +09:00
Neko7sora
7436a58ea1 改行コードをLFに統一 (#9926)
* chore: update gitattribute editorconfig

* Normalize all the line endings
2023-02-14 13:13:34 +09:00
tamaina
b7b8fd4b59 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-14 04:09:03 +00:00
tamaina
55d4d3418e fix(server): HttpRequestService.sendでは常にUser-Agentを含むように
Fix #9817 (maybe)
2023-02-14 04:08:56 +00:00
Kohei Ota (inductor)
1c8419cea0 Update Docker GHA (#9920)
* Update Docker GHA

* add id
2023-02-14 09:59:50 +09:00
syuilo
e8d4f3eac3 refactor: fix types 2023-02-13 16:19:29 +09:00
syuilo
1b21bad202 refactor 2023-02-13 15:50:22 +09:00
syuilo
30f600e03e Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-13 15:28:10 +09:00
syuilo
f34f9f6ea5 refactor: fix types 2023-02-13 15:28:07 +09:00
tamaina
8d4c5deb8d perf(sw): skipWaitingしない 2023-02-12 15:48:56 +00:00
Kagami Sascha Rosylight
2f41f12aea fix(client): Make isTimelineAvailable a reference (#9906)
* Make `isTimelineAvailable` a reference

* Update b.vue
2023-02-13 00:40:36 +09:00
Kagami Sascha Rosylight
9f0e0dc8ce refactor(sw): Fix type errors in packages/sw (#9909)
* Fix type errors in packages/sw

* mouhitotsu

* @typesは越境しない

* Update packages/sw/src/scripts/create-notification.ts

---------

Co-authored-by: tamaina <tamaina@hotmail.co.jp>
2023-02-13 00:31:37 +09:00
syuilo
a71682f6f0 refactor: fix types 2023-02-12 20:06:10 +09:00
syuilo
5d3d5cd59c refactor: fix types 2023-02-12 18:54:38 +09:00
syuilo
451bc0b444 refactor: fix types 2023-02-12 18:47:30 +09:00
tamaina
d7a2d59f41 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-12 08:42:42 +00:00
tamaina
7deb4691fb 🎨 2023-02-12 08:42:34 +00:00
Kagami Sascha Rosylight
9965bc8f94 Fix moduleNameMapper to not resolve .wasm.js to .wasm (#9894)
* Fix moduleNameMapper to not resolve `.wasm.js` to `.js`

Fixes #9767

Undici [tries to import `./llhttp/llhttp.wasm.js`](e155c6db5c/lib/client.js (L342)) which is currently broken by the (hacky) module name mapper.

* longer timeout value

* 30s

* 50s

* 60s to be safe

* Revert "60s to be safe"

This reverts commit f3e0f57962.

* 2cc98226ca revert?

* revert

* remove timeout

* detectOpenHandles

* Really solved?

* Revert "detectOpenHandles"

This reverts commit 29214bdff8.

* Add `coveragePathIgnorePatterns`

* Revert "Add `coveragePathIgnorePatterns`"

This reverts commit fcf8c6806b.

* Import jsonld dynamically

* remove import

* add comment

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2023-02-12 17:18:31 +09:00
taiy
317770fb23 enhance(client): リアクションが無いことを伝える (#9901) 2023-02-12 17:15:12 +09:00
syuilo
19c204ea03 Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop 2023-02-12 16:52:51 +09:00
syuilo
b9feacab85 fix(client): エラー時に再試行ができない問題を修正 2023-02-12 16:52:48 +09:00
syuilo
56c7359a0c refactor 2023-02-12 16:51:45 +09:00
mattn
a7c1afffc6 fix typo (#9900) 2023-02-12 16:40:12 +09:00
syuilo
fdb745b4a8 🎨 2023-02-12 14:31:00 +09:00
syuilo
b3d8134c7a 🎨 2023-02-12 14:25:34 +09:00
syuilo
0879ab50b8 fix(client): call checkMissingMention immediately 2023-02-12 14:00:15 +09:00
735 changed files with 9098 additions and 11335 deletions

View File

@@ -2,10 +2,10 @@
"name": "Misskey", "name": "Misskey",
"dockerComposeFile": "docker-compose.yml", "dockerComposeFile": "docker-compose.yml",
"service": "app", "service": "app",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", "workspaceFolder": "/workspace",
"features": { "features": {
"ghcr.io/devcontainers-contrib/features/pnpm:2": {} "ghcr.io/devcontainers-contrib/features/pnpm:2": {}
}, },
"forwardPorts": [3000], "forwardPorts": [3000],
"postCreateCommand": ".devcontainer/init.sh" "postCreateCommand": "sudo chmod 755 .devcontainer/init.sh && .devcontainer/init.sh"
} }

View File

@@ -7,7 +7,7 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
volumes: volumes:
- ../..:/workspaces:cached - ../:/workspace:cached
command: sleep infinity command: sleep infinity
@@ -21,7 +21,7 @@ services:
networks: networks:
- internal_network - internal_network
volumes: volumes:
- ../redis:/data - redis-data:/data
healthcheck: healthcheck:
test: "redis-cli ping" test: "redis-cli ping"
interval: 5s interval: 5s
@@ -37,7 +37,7 @@ services:
POSTGRES_PASSWORD: postgres POSTGRES_PASSWORD: postgres
POSTGRES_DB: misskey POSTGRES_DB: misskey
volumes: volumes:
- ../db:/var/lib/postgresql/data - postgres-data:/var/lib/postgresql/data
healthcheck: healthcheck:
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB" test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
interval: 5s interval: 5s
@@ -45,6 +45,7 @@ services:
volumes: volumes:
postgres-data: postgres-data:
redis-data:
networks: networks:
internal_network: internal_network:

View File

@@ -2,6 +2,7 @@
set -xe set -xe
sudo chown -R node /workspace
git submodule update --init git submodule update --init
pnpm install --frozen-lockfile pnpm install --frozen-lockfile
cp .devcontainer/devcontainer.yml .config/default.yml cp .devcontainer/devcontainer.yml .config/default.yml

View File

@@ -5,6 +5,7 @@ indent_style = tab
indent_size = 2 indent_size = 2
charset = utf-8 charset = utf-8
insert_final_newline = true insert_final_newline = true
end_of_line = lf
[*.yml] [*.{yml,yaml}]
indent_style = space indent_style = space

1
.gitattributes vendored
View File

@@ -5,3 +5,4 @@
*.glb -diff -text *.glb -diff -text
*.blend -diff -text *.blend -diff -text
*.afdesign -diff -text *.afdesign -diff -text
* text=auto eol=lf

View File

@@ -0,0 +1,17 @@
<!-- お読みください / README
PRありがとうございます PRを作成する前に、コントリビューションガイドをご確認ください:
Thank you for your PR! Before creating a PR, please check the contribution guide:
https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md
-->
# What
<!-- このPRで何をしたのか どう変わるのか? -->
<!-- What did you do with this PR? How will it change things? -->
# Why
<!-- なぜそうするのか? どういう意図なのか? 何が困っているのか? -->
<!-- Why do you do it? What are your intentions? What is the problem? -->
# Additional info (optional)
<!-- テスト観点など -->
<!-- Test perspective, etc -->

View File

@@ -0,0 +1,20 @@
## Summary
This is a release PR.
For more information on the release instructions, please see:
https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md#release
## For reviewers
- CHANGELOGに抜け漏れは無いか
- バージョンの上げ方は適切か
- 他にこのリリースに含めなければならない変更は無いか
- 全体的な変更内容を俯瞰し問題は無いか
- レビューされていないコミットがある場合は、それが問題ないか
- 最終的な動作確認を行い問題は無いか
などを確認し、リリースする準備が整っていると思われる場合は approve してください。
## Checklist
- [ ] package.jsonのバージョンが正しく更新されている
- [ ] CHANGELOGが過不足無く更新されている
- [ ] CIが全て通っている

10
.github/reviewer-lottery.yml vendored Normal file
View File

@@ -0,0 +1,10 @@
groups:
- name: devs
reviewers: 2
internal_reviewers: 1
usernames:
- syuilo
- acid-chicken
- EbiseLutica
- rinsuki
- tamaina

View File

@@ -1,18 +1,18 @@
name: Check copyright year name: Check copyright year
on: on:
push: push:
branches: branches:
- master - master
- develop - develop
jobs: jobs:
check_copyright_year: check_copyright_year:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3.2.0 - uses: actions/checkout@v3.2.0
- run: | - run: |
if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then
echo "Please change copyright year!" echo "Please change copyright year!"
exit 1 exit 1
fi fi

View File

@@ -15,7 +15,10 @@ jobs:
- name: Check out the repo - name: Check out the repo
uses: actions/checkout@v3.3.0 uses: actions/checkout@v3.3.0
- name: Set up Docker Buildx - name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.3.0 uses: docker/setup-buildx-action@v2.3.0
with:
platforms: linux/amd64,linux/arm64
- name: Docker meta - name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v4 uses: docker/metadata-action@v4
@@ -27,10 +30,13 @@ jobs:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push to Docker Hub - name: Build and Push to Docker Hub
uses: docker/build-push-action@v3 uses: docker/build-push-action@v4
with: with:
builder: ${{ steps.buildx.outputs.name }}
context: . context: .
push: true push: true
platforms: ${{ steps.buildx.outputs.platforms }}
provenance: false
tags: misskey/misskey:develop tags: misskey/misskey:develop
labels: develop labels: develop
cache-from: type=gha cache-from: type=gha

View File

@@ -13,6 +13,11 @@ jobs:
steps: steps:
- name: Check out the repo - name: Check out the repo
uses: actions/checkout@v3.3.0 uses: actions/checkout@v3.3.0
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2.3.0
with:
platforms: linux/amd64,linux/arm64
- name: Docker meta - name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v4 uses: docker/metadata-action@v4
@@ -31,9 +36,14 @@ jobs:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push to Docker Hub - name: Build and Push to Docker Hub
uses: docker/build-push-action@v3 uses: docker/build-push-action@v4
with: with:
builder: ${{ steps.buildx.outputs.name }}
context: . context: .
push: true push: true
platforms: ${{ steps.buildx.outputs.platforms }}
provenance: false
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

View File

@@ -1,54 +1,79 @@
name: Lint name: Lint
on: on:
push: push:
branches: branches:
- master - master
- develop - develop
pull_request: pull_request:
jobs: jobs:
pnpm_install: pnpm_install:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3.3.0 - uses: actions/checkout@v3.3.0
with: with:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
with: with:
version: 7 version: 7
run_install: false run_install: false
- uses: actions/setup-node@v3.6.0 - uses: actions/setup-node@v3.6.0
with: with:
node-version: 18.x node-version: 18.x
cache: 'pnpm' cache: 'pnpm'
- run: corepack enable - run: corepack enable
- run: pnpm i --frozen-lockfile - run: pnpm i --frozen-lockfile
lint: lint:
needs: [pnpm_install] needs: [pnpm_install]
runs-on: ubuntu-latest runs-on: ubuntu-latest
continue-on-error: true continue-on-error: true
strategy: strategy:
matrix: matrix:
workspace: workspace:
- backend - backend
- frontend - frontend
- sw - sw
steps: steps:
- uses: actions/checkout@v3.3.0 - uses: actions/checkout@v3.3.0
with: with:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
with: with:
version: 7 version: 7
run_install: false run_install: false
- uses: actions/setup-node@v3.6.0 - uses: actions/setup-node@v3.6.0
with: with:
node-version: 18.x node-version: 18.x
cache: 'pnpm' cache: 'pnpm'
- run: corepack enable - run: corepack enable
- run: pnpm i --frozen-lockfile - run: pnpm i --frozen-lockfile
- run: pnpm --filter ${{ matrix.workspace }} run lint - run: pnpm --filter ${{ matrix.workspace }} run eslint
typecheck:
needs: [pnpm_install]
runs-on: ubuntu-latest
continue-on-error: true
strategy:
matrix:
workspace:
- backend
steps:
- uses: actions/checkout@v3.3.0
with:
fetch-depth: 0
submodules: true
- uses: pnpm/action-setup@v2
with:
version: 7
run_install: false
- uses: actions/setup-node@v3.6.0
with:
node-version: 18.x
cache: 'pnpm'
- run: corepack enable
- run: pnpm i --frozen-lockfile
- run: pnpm --filter ${{ matrix.workspace }} run typecheck

View File

@@ -9,14 +9,46 @@ name: Destroy preview environment
jobs: jobs:
destroy-preview-environment: destroy-preview-environment:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == github.event.pull_request.head.repo.full_name
steps: steps:
- uses: actions/github-script@v6.3.3
id: check-conclusion
env:
number: ${{ github.event.number }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
result-encoding: string
script: |
const { data: pull } = await github.rest.pulls.get({
...context.repo,
pull_number: process.env.number
});
const ref = pull.head.sha;
const { data: checks } = await github.rest.checks.listForRef({
...context.repo,
ref
});
const check = checks.check_runs.filter(c => c.name === 'deploy-preview-environment');
if (check.length === 0) {
return;
}
const { data: result } = await github.rest.checks.get({
...context.repo,
check_run_id: check[0].id,
});
return result.conclusion;
- name: Context - name: Context
if: steps.check-conclusion.outputs.result == 'success'
uses: okteto/context@latest uses: okteto/context@latest
with: with:
token: ${{ secrets.OKTETO_TOKEN }} token: ${{ secrets.OKTETO_TOKEN }}
- name: Destroy preview environment - name: Destroy preview environment
if: steps.check-conclusion.outputs.result == 'success'
uses: okteto/destroy-preview@latest uses: okteto/destroy-preview@latest
with: with:
name: pr-${{ github.event.number }}-syuilo name: pr-${{ github.event.number }}-syuilo

13
.github/workflows/reviewer_lottery.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
name: "Reviewer lottery"
on:
pull_request_target:
types: [opened, ready_for_review, reopened]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: uesteibar/reviewer-lottery@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,5 +1,9 @@
{ {
"search.exclude": { "search.exclude": {
"**/node_modules": true "**/node_modules": true
},
"typescript.tsdk": "node_modules/typescript/lib",
"files.associations": {
"*.test.ts": "typescript"
} }
} }

View File

@@ -2,12 +2,122 @@
## 13.x.x (unreleased) ## 13.x.x (unreleased)
### Improvements ### Improvements
-
### Bugfixes ### Bugfixes
- -
You should also include the user name that made the change. You should also include the user name that made the change.
--> -->
## 13.9.0 (2023/03/03)
### Improvements
- 時限ロール
- アンテナでCWも検索対象にするように
- ノートの操作部をホバー時のみ表示するオプションを追加
- サウンドを追加
- サーバーのパフォーマンスを改善
### Bugfixes
- 外部メディアプロキシ使用時にアバタークロップができない問題を修正
- fix(server): メールアドレス更新時にバリデーションが正しく行われていないのを修正
- fix(server): チャンネルでミュートが正しく機能していないのを修正
- プッシュ通知でカスタム絵文字リアクションを表示できなかった問題を修正
## 13.8.1 (2023/02/26)
### Bugfixes
- モバイルでドロワーメニューが表示されない問題を修正
## 13.8.0 (2023/02/26)
### Improvements
- チャンネル内ハイライト
- ホームタイムラインのパフォーマンスを改善
- renoteした際の表示を改善
- バックグラウンドで一定時間経過したらページネーションのアイテム更新をしない
- enhance(client): MkUrlPreviewの閉じるボタンを見やすく
- Add dialog to remove follower
- enhance(client): improve clip menu ux
- 検索画面の統合
- enhance(client): ノートメニューからユーザーメニューを開けるように
- photoswipe 表示時に戻る操作をしても前の画面に戻らないように
### Bugfixes
- Windows環境でswcを使うと正しくビルドできない問題の修正
- fix(client): Android ChromeでPWAとしてインストールできない問題を修正
- 未知のユーザーが deleteActor されたら処理をスキップする
- fix(server): notes/createで、fileIdsと見つかったファイルの数が異なる場合はエラーにする
- fix(server): notes/createのバリデーションが機能していないのを修正
- fix(server): エラーのスタックトレースは返さないように
## 13.7.5 (2023/02/24)
### Note
13.7.0以前から直接このバージョンにアップデートする場合は全ての通知が削除**されません。**
### Improvements
- 紛らわしいため公開範囲の「ローカルのみ」オプションの名称を「連合なし」に変更
- Frontend: スマホ・タブレットの場合、チャンネルの投稿フォームに自動でフォーカスしないように
### Bugfixes
- 全ての通知が削除されてしまうのを修正
## 13.7.3 (2023/02/23)
### Note
~~13.7.0以前から直接このバージョンにアップデートする場合は全ての通知が削除**されません。**~~
### Improvements
### Bugfixes
- Client: 「キャッシュを削除」した後、ローカルのカスタム絵文字が表示されなくなるされなくなる問題を修正
- Client: 通知設定画面で以前からグループの招待を有効化していた場合、通知の表示に失敗する問題の修正
- Client: 通知設定画面に古いトグルが残っていた問題を修正
## 13.7.2 (2023/02/23)
### Note
13.7.0以前からアップデートする場合は全ての通知が削除されます。
### Improvements
- enhance: make pwa icon maskable
- chore(client): tweak custom emoji size
### Bugfixes
- マイグレーションが失敗することがあるのを修正
## 13.7.1 (2023/02/23)
### Improvements
- pnpm buildではswcを使うように
### Bugfixes
- NODE_ENV=productionでビルドできないのを修正
## 13.7.0 (2023/02/22)
### Changes
- チャット機能が削除されました
### Improvements
- Server: URLプレビューsummalyはプロキシを通すように
- Client: 2FA設定のUIをまともにした
- セキュリティキーの名前を変更できるように
- enhance(client): add quiz preset for play
- 広告開始時期を設定できるように
- みつけるで公開ロール一覧とそのメンバーを閲覧できるように
- enhance(client): MFMのx3, x4が含まれていたらートをたたむように
- enhance(client): make possible to reload page of window
### Bugfixes
- ユーザー検索ダイアログでローカルユーザーを絞って検索できない問題を修正
- fix(client): MkHeader及びデッキのカラムでチャンネル一覧を選択したとき、最大5個までしか表示されない
- 管理画面の広告を10個以上見えるように
- Moderation note が保存できない
- ユーザーのハッシュタグ検索が機能していないのを修正
## 13.6.1 (2023/02/12) ## 13.6.1 (2023/02/12)
### Improvements ### Improvements

View File

@@ -83,11 +83,18 @@ An actual domain will be assigned so you can test the federation.
- The title must be in the format `Release: x.y.z`. - The title must be in the format `Release: x.y.z`.
- `x.y.z` is the new version you are trying to release. - `x.y.z` is the new version you are trying to release.
3. Deploy and perform a simple QA check. Also verify that the tests passed. 3. Deploy and perform a simple QA check. Also verify that the tests passed.
4. Merge it. 4. Merge it. (Do not squash commit)
5. Create a [release of GitHub](https://github.com/misskey-dev/misskey/releases) 5. Create a [release of GitHub](https://github.com/misskey-dev/misskey/releases)
- The target branch must be `master` - The target branch must be `master`
- The tag name must be the version - The tag name must be the version
> **Note**
> Why this instruction is necessary:
> - To perform final QA checks
> - To distribute responsibility
> - To check direct commits to develop
> - To celebrate the release together 🎉
## Localization (l10n) ## Localization (l10n)
Misskey uses [Crowdin](https://crowdin.com/project/misskey) for localization management. Misskey uses [Crowdin](https://crowdin.com/project/misskey) for localization management.
You can improve our translations with your Crowdin account. You can improve our translations with your Crowdin account.
@@ -113,7 +120,8 @@ command.
### Dev Container ### Dev Container
Instead of running `pnpm` locally, you can use Dev Container to set up your development environment. Instead of running `pnpm` locally, you can use Dev Container to set up your development environment.
To use Dev Container, open the project directory on VSCode with Dev Containers installed. To use Dev Container, open the project directory on VSCode with Dev Containers installed.
**Note:** If you are using Windows, please clone the repository with WSL. Using Git for Windows will result in broken files due to the difference in how newlines are handled.
It will run the following command automatically inside the container. It will run the following command automatically inside the container.
``` bash ``` bash
@@ -277,9 +285,10 @@ SQLでは配列のインデックスは**1始まり**。
### null IN ### null IN
nullが含まれる可能性のあるカラムにINするときは、そのままだとおかしくなるのでORなどでnullのハンドリングをしよう。 nullが含まれる可能性のあるカラムにINするときは、そのままだとおかしくなるのでORなどでnullのハンドリングをしよう。
### `undefined`にご用心 ### enumの削除は気をつける
MongoDBの時とは違い、findOneでレコードを取得する時に対象レコードが存在しない場合 **`undefined`** が返ってくるので注意。 enumの列挙の内容の削除は、その値をもつレコードを全て削除しないといけない
MongoDBは`null`で返してきてたので、その感覚で`if (x === null)`とか書くとバグる。代わりに`if (x == null)`と書いてください
削除が重たかったり不可能だったりする場合は、削除しないでおく
### Migration作成方法 ### Migration作成方法
packages/backendで: packages/backendで:
@@ -290,6 +299,27 @@ pnpm dlx typeorm migration:generate -d ormconfig.js -o <migration name>
- 生成後、ファイルをmigration下に移してください - 生成後、ファイルをmigration下に移してください
- 作成されたスクリプトは不必要な変更を含むため除去してください - 作成されたスクリプトは不必要な変更を含むため除去してください
### JSON SchemaのobjectでanyOfを使うとき
JSON Schemaで、objectに対してanyOfを使う場合、anyOfの中でpropertiesを定義しないこと。
バリデーションが効かないため。SchemaTypeもそのように作られており、objectのanyOf内のpropertiesは捨てられます
https://github.com/misskey-dev/misskey/pull/10082
テキストhogeおよびfugaについて、片方を必須としつつ両方の指定もありうる場合:
```
export const paramDef = {
type: 'object',
properties: {
hoge: { type: 'string', minLength: 1 },
fuga: { type: 'string', minLength: 1 },
},
anyOf: [
{ required: ['hoge'] },
{ required: ['fuga'] },
],
} as const;
```
### コネクションには`markRaw`せよ ### コネクションには`markRaw`せよ
**Vueのコンポーネントのdataオプションとして**misskey.jsのコネクションを設定するとき、必ず`markRaw`でラップしてください。インスタンスが不必要にリアクティブ化されることで、misskey.js内の処理で不具合が発生するとともに、パフォーマンス上の問題にも繋がる。なお、Composition APIを使う場合はこの限りではない(リアクティブ化はマニュアルなため)。 **Vueのコンポーネントのdataオプションとして**misskey.jsのコネクションを設定するとき、必ず`markRaw`でラップしてください。インスタンスが不必要にリアクティブ化されることで、misskey.js内の処理で不具合が発生するとともに、パフォーマンス上の問題にも繋がる。なお、Composition APIを使う場合はこの限りではない(リアクティブ化はマニュアルなため)。

View File

@@ -1,3 +1,5 @@
# syntax = docker/dockerfile:1.4
ARG NODE_VERSION=18.13.0-bullseye ARG NODE_VERSION=18.13.0-bullseye
FROM node:${NODE_VERSION} AS builder FROM node:${NODE_VERSION} AS builder
@@ -14,16 +16,16 @@ RUN corepack enable
WORKDIR /misskey WORKDIR /misskey
COPY ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"] COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
COPY ["scripts", "./scripts"] COPY --link ["scripts", "./scripts"]
COPY ["packages/backend/package.json", "./packages/backend/"] COPY --link ["packages/backend/package.json", "./packages/backend/"]
COPY ["packages/frontend/package.json", "./packages/frontend/"] COPY --link ["packages/frontend/package.json", "./packages/frontend/"]
COPY ["packages/sw/package.json", "./packages/sw/"] COPY --link ["packages/sw/package.json", "./packages/sw/"]
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \ RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
pnpm i --frozen-lockfile --aggregate-output pnpm i --frozen-lockfile --aggregate-output
COPY . ./ COPY --link . ./
ARG NODE_ENV=production ARG NODE_ENV=production

View File

@@ -5,9 +5,9 @@ Also, the later tasks are more indefinite and are subject to change as developme
## (1) Improve maintainability \<current phase\> ## (1) Improve maintainability \<current phase\>
This is the phase we are at now. We need to make a high-maintenance environment that can withstand future development. This is the phase we are at now. We need to make a high-maintenance environment that can withstand future development.
- Make the number of type errors zero (backend) - ~~Make the number of type errors zero (backend)~~ → Done ✔️
- Improve CI - Improve CI
- Fix tests - ~~Fix tests~~ → Done ✔️
- Fix random test failures - https://github.com/misskey-dev/misskey/issues/7985 and https://github.com/misskey-dev/misskey/issues/7986 - Fix random test failures - https://github.com/misskey-dev/misskey/issues/7985 and https://github.com/misskey-dev/misskey/issues/7986
- Add more tests - Add more tests
- ~~May need to implement a mechanism that allows for DI~~ → Done ✔️ - ~~May need to implement a mechanism that allows for DI~~ → Done ✔️

View File

@@ -1,3 +1,4 @@
apiVersion: v2 apiVersion: v2
name: misskey name: misskey
version: 0.0.0 version: 0.0.0
description: This chart is created for the purpose of previewing Pull Requests. Do not use this for production use.

4
codecov.yml Normal file
View File

@@ -0,0 +1,4 @@
coverage:
status:
project: false
patch: false

View File

@@ -10,14 +10,14 @@ describe('Before setup instance', () => {
}); });
it('successfully loads', () => { it('successfully loads', () => {
cy.visit('/'); cy.visitHome();
}); });
it('setup instance', () => { it('setup instance', () => {
cy.visit('/'); cy.visitHome();
cy.intercept('POST', '/api/admin/accounts/create').as('signup'); cy.intercept('POST', '/api/admin/accounts/create').as('signup');
cy.get('[data-cy-admin-username] input').type('admin'); cy.get('[data-cy-admin-username] input').type('admin');
cy.get('[data-cy-admin-password] input').type('admin1234'); cy.get('[data-cy-admin-password] input').type('admin1234');
cy.get('[data-cy-admin-ok]').click(); cy.get('[data-cy-admin-ok]').click();
@@ -43,11 +43,11 @@ describe('After setup instance', () => {
}); });
it('successfully loads', () => { it('successfully loads', () => {
cy.visit('/'); cy.visitHome();
}); });
it('signup', () => { it('signup', () => {
cy.visit('/'); cy.visitHome();
cy.intercept('POST', '/api/signup').as('signup'); cy.intercept('POST', '/api/signup').as('signup');
@@ -79,11 +79,11 @@ describe('After user signup', () => {
}); });
it('successfully loads', () => { it('successfully loads', () => {
cy.visit('/'); cy.visitHome();
}); });
it('signin', () => { it('signin', () => {
cy.visit('/'); cy.visitHome();
cy.intercept('POST', '/api/signin').as('signin'); cy.intercept('POST', '/api/signin').as('signin');
@@ -101,7 +101,7 @@ describe('After user signup', () => {
userId: this.alice.id, userId: this.alice.id,
}); });
cy.visit('/'); cy.visitHome();
cy.get('[data-cy-signin]').click(); cy.get('[data-cy-signin]').click();
cy.get('[data-cy-signin-username] input').type('alice'); cy.get('[data-cy-signin-username] input').type('alice');
@@ -112,7 +112,7 @@ describe('After user signup', () => {
}); });
}); });
describe('After user singed in', () => { describe('After user signed in', () => {
beforeEach(() => { beforeEach(() => {
cy.resetState(); cy.resetState();
@@ -141,6 +141,19 @@ describe('After user singed in', () => {
cy.get('[data-cy-open-post-form-submit]').click(); cy.get('[data-cy-open-post-form-submit]').click();
cy.contains('Hello, Misskey!'); cy.contains('Hello, Misskey!');
});
it('open note form with hotkey', () => {
// Wait until the page loads
cy.get('[data-cy-open-post-form]').should('be.visible');
// Use trigger() to give different `code` to test if hotkeys also work on non-QWERTY keyboards.
cy.document().trigger("keydown", { eventConstructor: 'KeyboardEvent', key: "n", code: "KeyL" });
// See if the form is opened
cy.get('[data-cy-post-form-text]').should('be.visible');
// Close it
cy.focused().trigger("keydown", { eventConstructor: 'KeyboardEvent', key: "Escape", code: "Escape" });
// See if the form is closed
cy.get('[data-cy-post-form-text]').should('not.be.visible');
}); });
}); });

View File

@@ -24,6 +24,11 @@
// -- This will overwrite an existing command -- // -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
Cypress.Commands.add('visitHome', () => {
cy.visit('/');
cy.get('button', { timeout: 30000 }).should('be.visible');
})
Cypress.Commands.add('resetState', () => { Cypress.Commands.add('resetState', () => {
cy.window(win => { cy.window(win => {
win.indexedDB.deleteDatabase('keyval-store'); win.indexedDB.deleteDatabase('keyval-store');
@@ -43,7 +48,7 @@ Cypress.Commands.add('registerUser', (username, password, isAdmin = false) => {
}); });
Cypress.Commands.add('login', (username, password) => { Cypress.Commands.add('login', (username, password) => {
cy.visit('/'); cy.visitHome();
cy.intercept('POST', '/api/signin').as('signin'); cy.intercept('POST', '/api/signin').as('signin');

View File

@@ -379,13 +379,10 @@ about: "عن"
aboutMisskey: "عن Misskey" aboutMisskey: "عن Misskey"
administrator: "المدير" administrator: "المدير"
token: "الرمز المميز" token: "الرمز المميز"
twoStepAuthentication: "الإستيثاق بعاملَيْن"
moderator: "مشرِف" moderator: "مشرِف"
moderation: "الإشراف" moderation: "الإشراف"
nUsersMentioned: "{n} مستخدمين أُشير إليهم" nUsersMentioned: "{n} مستخدمين أُشير إليهم"
securityKey: "مفتاح الأمان" securityKey: "مفتاح الأمان"
securityKeyName: "اسم المفتاح"
registerSecurityKey: "سجل مفتاح أمان"
lastUsed: "آخر استخدام" lastUsed: "آخر استخدام"
unregister: "إلغاء التسجيل" unregister: "إلغاء التسجيل"
passwordLessLogin: "لِج مِن دون كلمة سرية" passwordLessLogin: "لِج مِن دون كلمة سرية"
@@ -403,24 +400,15 @@ markAsReadAllTalkMessages: "علّم جميع الرسائل كمقروءة"
help: "المساعدة" help: "المساعدة"
inputMessageHere: "اكتب رسالتك هنا" inputMessageHere: "اكتب رسالتك هنا"
close: "اغلق" close: "اغلق"
group: "الفريق"
groups: "الفِرَق"
createGroup: "انشئ فريقًا"
ownedGroups: "فِرقي"
joinedGroups: "الفِرق المُنضم إليها"
invites: "دعوة" invites: "دعوة"
groupName: "اسم الفريق"
members: "الأعضاء" members: "الأعضاء"
transfer: "نقل" transfer: "نقل"
messagingWithUser: "تحدث مع مستخدم"
messagingWithGroup: "محادثة جماعية"
title: "العنوان" title: "العنوان"
text: "النص" text: "النص"
enable: "تشغيل" enable: "تشغيل"
next: "التالية" next: "التالية"
retype: "أعد الكتابة" retype: "أعد الكتابة"
noteOf: "ملاحظات {user}" noteOf: "ملاحظات {user}"
inviteToGroup: "دعوة إلى فريق"
quoteAttached: "اِقتُبسَ" quoteAttached: "اِقتُبسَ"
quoteQuestion: "أتريد تضمينها كاقتباس" quoteQuestion: "أتريد تضمينها كاقتباس"
noMessagesYet: "ليس هناك رسائل بعد" noMessagesYet: "ليس هناك رسائل بعد"
@@ -442,14 +430,10 @@ passwordMatched: "التطابق صحيح!"
passwordNotMatched: "غير متطابقتان" passwordNotMatched: "غير متطابقتان"
signinWith: "الولوج عبر {x}" signinWith: "الولوج عبر {x}"
signinFailed: "فشل الولوج، خطأ في اسم المستخدم أو كلمة المرور." signinFailed: "فشل الولوج، خطأ في اسم المستخدم أو كلمة المرور."
tapSecurityKey: "أنقر مفتاح الأمان"
or: "أو" or: "أو"
language: "اللغة" language: "اللغة"
uiLanguage: "لغة واجهة المستخدم" uiLanguage: "لغة واجهة المستخدم"
groupInvited: "دُعيت إلى فريقٍ"
aboutX: "عن {x}" aboutX: "عن {x}"
youHaveNoGroups: "لا تمتلك أية فِرَق"
joinOrCreateGroup: "احصل على دعوة لفريق أو أنشئ واحدًا."
noHistory: "السجل فارغ" noHistory: "السجل فارغ"
signinHistory: "تاريخ تسجيل الدخول" signinHistory: "تاريخ تسجيل الدخول"
doing: "انتظر لحظة" doing: "انتظر لحظة"
@@ -790,8 +774,6 @@ deleteAccountConfirm: "سيحذف حسابك نهائيًا، أتريد الم
incorrectPassword: "كلمة السر خاطئة." incorrectPassword: "كلمة السر خاطئة."
voteConfirm: "متيقِّن من تصويتك لـ {choice}؟" voteConfirm: "متيقِّن من تصويتك لـ {choice}؟"
hide: "إخفاء" hide: "إخفاء"
leaveGroup: "مغادرة الفريق"
leaveGroupConfirm: "متيقن من مغادرة \"{name}\"؟"
welcomeBackWithName: "مرحبًا بك مجددًا {name}" welcomeBackWithName: "مرحبًا بك مجددًا {name}"
clickToFinishEmailVerification: "انقر [{ok}] لاستيثاق بريدك الإلكتروني." clickToFinishEmailVerification: "انقر [{ok}] لاستيثاق بريدك الإلكتروني."
overridedDeviceKind: "نوع الجهاز" overridedDeviceKind: "نوع الجهاز"
@@ -803,6 +785,7 @@ size: "الحجم"
numberOfColumn: "عدد الأعمدة" numberOfColumn: "عدد الأعمدة"
searchByGoogle: "غوغل" searchByGoogle: "غوغل"
mutePeriod: "مدة الكتم" mutePeriod: "مدة الكتم"
period: "ينتهي استطلاع الرأي في"
indefinitely: "أبدًا" indefinitely: "أبدًا"
tenMinutes: "10 دقائق" tenMinutes: "10 دقائق"
oneHour: "ساعة" oneHour: "ساعة"
@@ -989,6 +972,7 @@ _ago:
weeksAgo: "منذ {n} أسابيع" weeksAgo: "منذ {n} أسابيع"
monthsAgo: "منذ {n} أشهر" monthsAgo: "منذ {n} أشهر"
yearsAgo: "منذ {n} سنوات" yearsAgo: "منذ {n} سنوات"
invalid: "لا يوجد شيء هنا"
_time: _time:
second: "ثا" second: "ثا"
minute: "د" minute: "د"
@@ -1019,12 +1003,11 @@ _tutorial:
step7_3: "حظًا سعيدًا واستمتع بوقتك مع ميسكي! 🚀" step7_3: "حظًا سعيدًا واستمتع بوقتك مع ميسكي! 🚀"
_2fa: _2fa:
alreadyRegistered: "سجلت سلفًا جهازًا للاستيثاق بعاملين." alreadyRegistered: "سجلت سلفًا جهازًا للاستيثاق بعاملين."
registerDevice: "سجّل جهازًا جديدًا"
registerKey: "تسجيل مفتاح أمان جديد"
step1: "أولًا ثبّت تطبيق استيثاق على جهازك (مثل {a} و{b})." step1: "أولًا ثبّت تطبيق استيثاق على جهازك (مثل {a} و{b})."
step2: "امسح رمز الاستجابة السريعة الموجد على الشاشة." step2: "امسح رمز الاستجابة السريعة الموجد على الشاشة."
step3: "أدخل الرمز الموجود في تطبيقك لإكمال التثبيت." step3: "أدخل الرمز الموجود في تطبيقك لإكمال التثبيت."
step4: "من هذه اللحظة أثناء ولوجك سيُطلب منك الرمز." step4: "من هذه اللحظة أثناء ولوجك سيُطلب منك الرمز."
renewTOTPCancel: "ليس اﻵن"
_permissions: _permissions:
"read:account": "اعرض معلومات حسابك" "read:account": "اعرض معلومات حسابك"
"write:account": "تعديل معلومات حسابك" "write:account": "تعديل معلومات حسابك"
@@ -1133,8 +1116,6 @@ _visibility:
followersDescription: "اجعلها مرئية لمتابِعيك فقط" followersDescription: "اجعلها مرئية لمتابِعيك فقط"
specified: "مباشرة" specified: "مباشرة"
specifiedDescription: "اجعلها مرئية لمستخدمين محددين" specifiedDescription: "اجعلها مرئية لمستخدمين محددين"
localOnly: "المحلي فقط"
localOnlyDescription: "ليس مرئيًا للمستخدمين البِعاد"
_postForm: _postForm:
replyPlaceholder: "رد على هذه الملاحظة…" replyPlaceholder: "رد على هذه الملاحظة…"
quotePlaceholder: "اقتبس هذه الملاحظة…" quotePlaceholder: "اقتبس هذه الملاحظة…"
@@ -1255,12 +1236,9 @@ _notification:
youGotReply: "ردّ عليك {name}" youGotReply: "ردّ عليك {name}"
youGotQuote: "اقتبس منك {name}" youGotQuote: "اقتبس منك {name}"
youRenoted: "إعادت نشر من {name}" youRenoted: "إعادت نشر من {name}"
youGotMessagingMessageFromUser: "لقد تلقيت رسالة مِن {name}"
youGotMessagingMessageFromGroup: "لقد أرسِلَت رسالة إلى الفريق {name}"
youWereFollowed: "يتابعك" youWereFollowed: "يتابعك"
youReceivedFollowRequest: "تلقيتَ طلب متابعة" youReceivedFollowRequest: "تلقيتَ طلب متابعة"
yourFollowRequestAccepted: "قُبل طلب المتابعة" yourFollowRequestAccepted: "قُبل طلب المتابعة"
youWereInvitedToGroup: "دُعيت إلى فريقٍ"
pollEnded: "ظهرت نتائج الاستطلاع" pollEnded: "ظهرت نتائج الاستطلاع"
unreadAntennaNote: "هوائي {name}" unreadAntennaNote: "هوائي {name}"
_types: _types:
@@ -1273,7 +1251,6 @@ _notification:
reaction: "التفاعلات" reaction: "التفاعلات"
receiveFollowRequest: "طلبات المتابعة المتلقاة" receiveFollowRequest: "طلبات المتابعة المتلقاة"
followRequestAccepted: "طلبات المتابعة المقبولة" followRequestAccepted: "طلبات المتابعة المقبولة"
groupInvited: "دعوات الفريق"
app: "إشعارات التطبيقات المرتبطة" app: "إشعارات التطبيقات المرتبطة"
_actions: _actions:
followBack: "تابعك بالمثل" followBack: "تابعك بالمثل"

View File

@@ -382,12 +382,9 @@ about: "আপনার সম্পর্কে"
aboutMisskey: "Misskey সম্পর্কে" aboutMisskey: "Misskey সম্পর্কে"
administrator: "প্রশাসক" administrator: "প্রশাসক"
token: "টোকেন" token: "টোকেন"
twoStepAuthentication: "২-ধাপ প্রমাণীকরণ"
moderator: "মডারেটর" moderator: "মডারেটর"
nUsersMentioned: "{n} জনকে উল্লেখ করা হয়েছে" nUsersMentioned: "{n} জনকে উল্লেখ করা হয়েছে"
securityKey: "সিকিউরিটি কী" securityKey: "সিকিউরিটি কী"
securityKeyName: "কী'র নাম"
registerSecurityKey: "সিকিউরিটি কী নিবন্ধন করুন"
lastUsed: "শেষ ব্যাবহার করা হয়েছে" lastUsed: "শেষ ব্যাবহার করা হয়েছে"
unregister: "নিবন্ধনমুক্ত হন" unregister: "নিবন্ধনমুক্ত হন"
passwordLessLogin: "পাসওয়ার্ড-বিহীন লগইন সেট আপ করুন" passwordLessLogin: "পাসওয়ার্ড-বিহীন লগইন সেট আপ করুন"
@@ -405,24 +402,15 @@ markAsReadAllTalkMessages: "সমস্ত মেসেজ পঠিত হি
help: "সহায়তা" help: "সহায়তা"
inputMessageHere: "এখানে মেসেজ লিখুন" inputMessageHere: "এখানে মেসেজ লিখুন"
close: "বন্ধ" close: "বন্ধ"
group: "গ্রুপ"
groups: "গ্রুপসমূহ"
createGroup: "গ্রুপ তৈরী করুন"
ownedGroups: "আপনার গ্রুপগুলি"
joinedGroups: "যেসব গ্রুপে আপনি আছেন"
invites: "আমন্ত্রণ" invites: "আমন্ত্রণ"
groupName: "গ্রুপের নাম"
members: "সদস্যবৃন্দ" members: "সদস্যবৃন্দ"
transfer: "হস্তান্তর" transfer: "হস্তান্তর"
messagingWithUser: "প্রাইভেট চ্যাট"
messagingWithGroup: "গ্রুপ চ্যাট"
title: "শিরোনাম" title: "শিরোনাম"
text: "পাঠ্য" text: "পাঠ্য"
enable: "সক্রিয়" enable: "সক্রিয়"
next: "পরবর্তী" next: "পরবর্তী"
retype: "পুনঃ প্রবেশ" retype: "পুনঃ প্রবেশ"
noteOf: "{user} এর নোট" noteOf: "{user} এর নোট"
inviteToGroup: "গ্রুপে আমন্ত্রণ জানান"
quoteAttached: "উদ্ধৃত" quoteAttached: "উদ্ধৃত"
quoteQuestion: "উদ্ধৃতি হিসাবে সংযুক্ত করবেন?" quoteQuestion: "উদ্ধৃতি হিসাবে সংযুক্ত করবেন?"
noMessagesYet: "কোন মেসেজ নেই" noMessagesYet: "কোন মেসেজ নেই"
@@ -444,15 +432,11 @@ passwordMatched: "মিলেছে"
passwordNotMatched: "মিলেনি" passwordNotMatched: "মিলেনি"
signinWith: "{x} এর সাহায্যে সাইন ইন করুন" signinWith: "{x} এর সাহায্যে সাইন ইন করুন"
signinFailed: "লগ ইন করা যায়নি। আপনার ব্যবহারকারীর নাম এবং পাসওয়ার্ড চেক করুন." signinFailed: "লগ ইন করা যায়নি। আপনার ব্যবহারকারীর নাম এবং পাসওয়ার্ড চেক করুন."
tapSecurityKey: "সিকিউরিটি কী স্পর্শ করুন"
or: "অথবা" or: "অথবা"
language: "ভাষা" language: "ভাষা"
uiLanguage: "UI এর ভাষা" uiLanguage: "UI এর ভাষা"
groupInvited: "আপনি একটি গ্রুপে আমন্ত্রিত হয়েছেন"
aboutX: "{x} সম্পর্কে" aboutX: "{x} সম্পর্কে"
disableDrawer: "ড্রয়ার মেনু প্রদর্শন করবেন না" disableDrawer: "ড্রয়ার মেনু প্রদর্শন করবেন না"
youHaveNoGroups: "আপনার কোন গ্রুপ নেই "
joinOrCreateGroup: "একটি বিদ্যমান গ্রুপের আমন্ত্রণ পান বা একটি নতুন গ্রুপ তৈরি করুন৷"
noHistory: "কোনো ইতিহাস নেই" noHistory: "কোনো ইতিহাস নেই"
signinHistory: "প্রবেশ করার ইতিহাস" signinHistory: "প্রবেশ করার ইতিহাস"
doing: "প্রক্রিয়া করছে..." doing: "প্রক্রিয়া করছে..."
@@ -820,8 +804,6 @@ deleteAccountConfirm: "আপনার অ্যাকাউন্ট মুছ
incorrectPassword: "আপনার দেওয়া পাসওয়ার্ডটি ভুল।" incorrectPassword: "আপনার দেওয়া পাসওয়ার্ডটি ভুল।"
voteConfirm: "\"{choice}\" এ ভোট দিতে চান?" voteConfirm: "\"{choice}\" এ ভোট দিতে চান?"
hide: "লুকান" hide: "লুকান"
leaveGroup: "গ্রুপ ছেড়ে চলে যান"
leaveGroupConfirm: "\"{name}\" গ্রুপ ছেড়ে চলে যেতে চান?"
useDrawerReactionPickerForMobile: "মোবাইলে রিঅ্যাকশন পিকারকে ড্রয়ারে প্রদর্শন করুন" useDrawerReactionPickerForMobile: "মোবাইলে রিঅ্যাকশন পিকারকে ড্রয়ারে প্রদর্শন করুন"
welcomeBackWithName: "আবার স্বাগতম, {name}" welcomeBackWithName: "আবার স্বাগতম, {name}"
clickToFinishEmailVerification: " [{ok}] ক্লিক করার মাধ্যমে আপনার ইমেল ঠিকানা নিশ্চিত করুন।" clickToFinishEmailVerification: " [{ok}] ক্লিক করার মাধ্যমে আপনার ইমেল ঠিকানা নিশ্চিত করুন।"
@@ -837,6 +819,7 @@ instanceDefaultLightTheme: "ইন্সট্যান্সের ডিফল
instanceDefaultDarkTheme: "ইন্সট্যান্সের ডিফল্ট ডার্ক থিম" instanceDefaultDarkTheme: "ইন্সট্যান্সের ডিফল্ট ডার্ক থিম"
instanceDefaultThemeDescription: "অবজেক্ট ফরম্যাটে থিম কোড লিখুন" instanceDefaultThemeDescription: "অবজেক্ট ফরম্যাটে থিম কোড লিখুন"
mutePeriod: "মিউটের সময়কাল" mutePeriod: "মিউটের সময়কাল"
period: "পোলের সময়সীমা"
indefinitely: "অনির্দিষ্ট" indefinitely: "অনির্দিষ্ট"
tenMinutes: "১০ মিনিট" tenMinutes: "১০ মিনিট"
oneHour: "১ ঘণ্টা" oneHour: "১ ঘণ্টা"
@@ -1051,6 +1034,7 @@ _ago:
weeksAgo: "{n} সপ্তাহ আগে" weeksAgo: "{n} সপ্তাহ আগে"
monthsAgo: "{n} মাস আগে" monthsAgo: "{n} মাস আগে"
yearsAgo: "{n} বছর আগে" yearsAgo: "{n} বছর আগে"
invalid: "এখানে কিছুই নাই"
_time: _time:
second: "সেকেন্ড" second: "সেকেন্ড"
minute: "মিনিট" minute: "মিনিট"
@@ -1081,8 +1065,6 @@ _tutorial:
step7_3: "এখন Misskey উপভোগ করুন 🚀" step7_3: "এখন Misskey উপভোগ করুন 🚀"
_2fa: _2fa:
alreadyRegistered: "আপনি ইতিমধ্যে একটি 2-ফ্যাক্টর অথেনটিকেশন ডিভাইস নিবন্ধন করেছেন৷" alreadyRegistered: "আপনি ইতিমধ্যে একটি 2-ফ্যাক্টর অথেনটিকেশন ডিভাইস নিবন্ধন করেছেন৷"
registerDevice: "নতুন ডিভাইস নিবন্ধন করুন"
registerKey: "সিকিউরিটি কী নিবন্ধন করুন"
step1: "প্রথমে, আপনার ডিভাইসে {a} বা {b} এর মতো একটি অথেনটিকেশন অ্যাপ ইনস্টল করুন৷" step1: "প্রথমে, আপনার ডিভাইসে {a} বা {b} এর মতো একটি অথেনটিকেশন অ্যাপ ইনস্টল করুন৷"
step2: "এরপরে, অ্যাপের সাহায্যে প্রদর্শিত QR কোডটি স্ক্যান করুন।" step2: "এরপরে, অ্যাপের সাহায্যে প্রদর্শিত QR কোডটি স্ক্যান করুন।"
step2Url: "ডেস্কটপ অ্যাপে, নিম্নলিখিত URL লিখুন:" step2Url: "ডেস্কটপ অ্যাপে, নিম্নলিখিত URL লিখুন:"
@@ -1134,7 +1116,6 @@ _antennaSources:
homeTimeline: "আপনি অনুসরণ করছেন, এমন ব্যবহারকারীদের নোট" homeTimeline: "আপনি অনুসরণ করছেন, এমন ব্যবহারকারীদের নোট"
users: "এক বা একাধিক নির্দিষ্ট ব্যবহারকারীর নোট" users: "এক বা একাধিক নির্দিষ্ট ব্যবহারকারীর নোট"
userList: "নির্দিষ্ট তালিকায় নাম থাকা ব্যবহারকারীদের নোট" userList: "নির্দিষ্ট তালিকায় নাম থাকা ব্যবহারকারীদের নোট"
userGroup: "নির্দিষ্ট গ্রুপে থাকা ব্যবহারকারীদের নোট"
_weekday: _weekday:
sunday: "রবিবার" sunday: "রবিবার"
monday: "সোমবার" monday: "সোমবার"
@@ -1203,8 +1184,6 @@ _visibility:
followersDescription: "শুধুমাত্র আপনার অনুসরণকারীদের নিকট পোস্ট করুন" followersDescription: "শুধুমাত্র আপনার অনুসরণকারীদের নিকট পোস্ট করুন"
specified: "ডাইরেক্ট নোট" specified: "ডাইরেক্ট নোট"
specifiedDescription: "শুধুমাত্র নির্দিষ্ট ব্যাবহারকারীর নিকট পাঠান" specifiedDescription: "শুধুমাত্র নির্দিষ্ট ব্যাবহারকারীর নিকট পাঠান"
localOnly: "শুধুমাত্র লোকাল"
localOnlyDescription: "রিমোট ব্যাবহারকারীদের নিকট দৃশ্যমান নয়"
_postForm: _postForm:
replyPlaceholder: "নোটটির জবাব দিন..." replyPlaceholder: "নোটটির জবাব দিন..."
quotePlaceholder: "নোটটিকে উদ্ধৃত করুন..." quotePlaceholder: "নোটটিকে উদ্ধৃত করুন..."
@@ -1332,12 +1311,9 @@ _notification:
youGotReply: "{name} আপনাকে জবাব দিয়েছে" youGotReply: "{name} আপনাকে জবাব দিয়েছে"
youGotQuote: "{name} আপনাকে উদ্ধৃত করেছে" youGotQuote: "{name} আপনাকে উদ্ধৃত করেছে"
youRenoted: "{name} এর Renote" youRenoted: "{name} এর Renote"
youGotMessagingMessageFromUser: "{name} আপনাকে মেসেজ করেছে"
youGotMessagingMessageFromGroup: "{name} গ্রুপে একটি নতুন মেসেজ আছে"
youWereFollowed: "আপনাকে অনুসরণ করছে" youWereFollowed: "আপনাকে অনুসরণ করছে"
youReceivedFollowRequest: "অনুসরণ করার জন্য অনুরোধ পাওয়া গেছে" youReceivedFollowRequest: "অনুসরণ করার জন্য অনুরোধ পাওয়া গেছে"
yourFollowRequestAccepted: "আপনার অনুসরণ করার অনুরোধ গৃহীত হয়েছে" yourFollowRequestAccepted: "আপনার অনুসরণ করার অনুরোধ গৃহীত হয়েছে"
youWereInvitedToGroup: "আপনি একটি গ্রুপে আমন্ত্রিত হয়েছেন"
pollEnded: "পোলের ফলাফল দেখা যাবে" pollEnded: "পোলের ফলাফল দেখা যাবে"
emptyPushNotificationMessage: "আপডেট করা পুশ বিজ্ঞপ্তি" emptyPushNotificationMessage: "আপডেট করা পুশ বিজ্ঞপ্তি"
_types: _types:
@@ -1351,7 +1327,6 @@ _notification:
pollEnded: "পোল শেষ" pollEnded: "পোল শেষ"
receiveFollowRequest: "প্রাপ্ত অনুসরণের অনুরোধসমূহ" receiveFollowRequest: "প্রাপ্ত অনুসরণের অনুরোধসমূহ"
followRequestAccepted: "গৃহীত অনুসরণের অনুরোধসমূহ" followRequestAccepted: "গৃহীত অনুসরণের অনুরোধসমূহ"
groupInvited: "গ্রুপের আমন্ত্রনসমূহ"
app: "লিঙ্ক করা অ্যাপ থেকে বিজ্ঞপ্তি" app: "লিঙ্ক করা অ্যাপ থেকে বিজ্ঞপ্তি"
_actions: _actions:
followBack: "ফলো ব্যাক করেছে" followBack: "ফলো ব্যাক করেছে"

View File

@@ -315,13 +315,10 @@ userList: "Llistes"
about: "Informació" about: "Informació"
aboutMisskey: "Quant a Misskey" aboutMisskey: "Quant a Misskey"
administrator: "Administrador/a" administrator: "Administrador/a"
twoStepAuthentication: "Verificació en dos passos"
moderator: "Moderador/a" moderator: "Moderador/a"
moderation: "Moderació" moderation: "Moderació"
nUsersMentioned: "{n} usuaris mencionats" nUsersMentioned: "{n} usuaris mencionats"
securityKey: "Clau de seguretat" securityKey: "Clau de seguretat"
securityKeyName: "Nom de la clau"
registerSecurityKey: "Registra la clau de seguretat"
unregister: "Cancel·la el registre" unregister: "Cancel·la el registre"
passwordLessLogin: "Inici de sessió sense contrasenya" passwordLessLogin: "Inici de sessió sense contrasenya"
resetPassword: "Restableix la contrasenya" resetPassword: "Restableix la contrasenya"
@@ -334,7 +331,6 @@ help: "Ajuda"
invites: "Convida" invites: "Convida"
next: "Següent" next: "Següent"
noteOf: "Publicació de: {user}" noteOf: "Publicació de: {user}"
inviteToGroup: "Convida'l al grup"
invitations: "Convida" invitations: "Convida"
tags: "Etiquetes" tags: "Etiquetes"
docSource: "Font del document" docSource: "Font del document"
@@ -393,7 +389,6 @@ _antennaSources:
homeTimeline: "Publicacions dels usuaris seguits" homeTimeline: "Publicacions dels usuaris seguits"
users: "Publicacions d'usuaris específics" users: "Publicacions d'usuaris específics"
userList: "Publicacions d'una llista d'usuaris" userList: "Publicacions d'una llista d'usuaris"
userGroup: "Publicacions d'usuaris d'un grup"
_widgets: _widgets:
profile: "Perfil" profile: "Perfil"
instanceInfo: "Informació del fitxer d'instal·lació" instanceInfo: "Informació del fitxer d'instal·lació"

View File

@@ -337,12 +337,9 @@ about: "Informace"
aboutMisskey: "O Misskey" aboutMisskey: "O Misskey"
administrator: "Administrátor" administrator: "Administrátor"
token: "Token" token: "Token"
twoStepAuthentication: "Dvoufaktorová autentikace"
moderator: "Moderátor" moderator: "Moderátor"
nUsersMentioned: "{n} uživatelů zmínilo" nUsersMentioned: "{n} uživatelů zmínilo"
securityKey: "Bezpečnostní klíč" securityKey: "Bezpečnostní klíč"
securityKeyName: "Název klíče"
registerSecurityKey: "Registrovat bezpečnostní klíč"
lastUsed: "Naposledy použito" lastUsed: "Naposledy použito"
unregister: "Odstranit" unregister: "Odstranit"
resetPassword: "Resetovat heslo" resetPassword: "Resetovat heslo"
@@ -359,13 +356,7 @@ markAsReadAllTalkMessages: "Označit všechny zprávy za přečtené"
help: "Nápověda" help: "Nápověda"
inputMessageHere: "Sem zadejte zprávu" inputMessageHere: "Sem zadejte zprávu"
close: "Zavřít" close: "Zavřít"
group: "Skupina"
groups: "Skupiny"
createGroup: "Vytvořit skupinu"
ownedGroups: "Vlastněné skupiny"
joinedGroups: "Členství ve skupinách"
invites: "Pozvat" invites: "Pozvat"
groupName: "Název skupiny"
members: "Členové" members: "Členové"
transfer: "Převod" transfer: "Převod"
title: "Titulek" title: "Titulek"
@@ -374,7 +365,6 @@ enable: "Povolit"
next: "Další" next: "Další"
retype: "Zadejte znovu" retype: "Zadejte znovu"
noteOf: "{user} poznámky" noteOf: "{user} poznámky"
inviteToGroup: "Pozvat do skupiny"
quoteAttached: "Citace" quoteAttached: "Citace"
quoteQuestion: "Přiložit jako citaci?" quoteQuestion: "Přiložit jako citaci?"
noMessagesYet: "Zatím tu nejsou žádné zprávy" noMessagesYet: "Zatím tu nejsou žádné zprávy"
@@ -396,14 +386,10 @@ passwordMatched: "Hesla se schodují"
passwordNotMatched: "Hesla se neschodují" passwordNotMatched: "Hesla se neschodují"
signinWith: "Přihlásit se s {x}" signinWith: "Přihlásit se s {x}"
signinFailed: "Nelze se přihlásit. Zkontrolujte prosím své uživatelské jméno a heslo." signinFailed: "Nelze se přihlásit. Zkontrolujte prosím své uživatelské jméno a heslo."
tapSecurityKey: "Ťukněte na bezpečnostní klíč"
or: "Nebo" or: "Nebo"
language: "Jazyk" language: "Jazyk"
uiLanguage: "Jazyk uživatelského rozhraní" uiLanguage: "Jazyk uživatelského rozhraní"
groupInvited: "Pozvat do skupiny"
aboutX: "O {x}" aboutX: "O {x}"
youHaveNoGroups: "Nemáte žádné skupiny"
joinOrCreateGroup: "Můžete požádat o pozvání do stávající skupiny nebo vytvořit novou."
noHistory: "Žádná historie" noHistory: "Žádná historie"
signinHistory: "Historie přihlášení" signinHistory: "Historie přihlášení"
category: "Kategorie" category: "Kategorie"
@@ -673,13 +659,11 @@ _sfx:
_ago: _ago:
future: "Budoucí" future: "Budoucí"
justNow: "Teď" justNow: "Teď"
invalid: "Nic nebylo nalezeno"
_time: _time:
second: "Sekund" second: "Sekund"
minute: "Minut" minute: "Minut"
hour: "Hodin" hour: "Hodin"
_2fa:
registerDevice: "Přidat zařízení"
registerKey: "Přidat bezpečnostní klíč"
_weekday: _weekday:
sunday: "Neděle" sunday: "Neděle"
monday: "Pondělí" monday: "Pondělí"
@@ -773,7 +757,6 @@ _pages:
button: "Tlačítko" button: "Tlačítko"
_notification: _notification:
youWereFollowed: "Máte nového následovníka" youWereFollowed: "Máte nového následovníka"
youWereInvitedToGroup: "Pozvat do skupiny"
_types: _types:
all: "Vše" all: "Vše"
follow: "Sledovaní" follow: "Sledovaní"

View File

@@ -103,6 +103,8 @@ renoted: "Renote getätigt."
cantRenote: "Renote dieses Beitrags nicht möglich." cantRenote: "Renote dieses Beitrags nicht möglich."
cantReRenote: "Renote einer Renote nicht möglich." cantReRenote: "Renote einer Renote nicht möglich."
quote: "Zitieren" quote: "Zitieren"
inChannelRenote: "Kanal-interner Renote"
inChannelQuote: "Kanal-internes Zitat"
pinnedNote: "Angeheftete Notiz" pinnedNote: "Angeheftete Notiz"
pinned: "Angeheftet" pinned: "Angeheftet"
you: "Du" you: "Du"
@@ -391,16 +393,19 @@ about: "Über"
aboutMisskey: "Über Misskey" aboutMisskey: "Über Misskey"
administrator: "Administrator" administrator: "Administrator"
token: "Token" token: "Token"
twoStepAuthentication: "Zwei-Faktor-Authentifizierung" 2fa: "Zwei-Faktor-Authentifizierung"
totp: "Authentifizierungs-App"
totpDescription: "Logge dich via Authentifizierungs-App mit Einmalpasswort ein"
moderator: "Moderator" moderator: "Moderator"
moderation: "Moderation" moderation: "Moderation"
nUsersMentioned: "Von {n} Benutzern erwähnt" nUsersMentioned: "Von {n} Benutzern erwähnt"
securityKeyAndPasskey: "Security-Tokens und Passkeys"
securityKey: "Sicherheitsschlüssel" securityKey: "Sicherheitsschlüssel"
securityKeyName: "Schlüsselname"
registerSecurityKey: "Sicherheitsschlüssel registrieren"
lastUsed: "Zuletzt benutzt" lastUsed: "Zuletzt benutzt"
lastUsedAt: "Zuletzt verwendet: {t}"
unregister: "Deaktivieren" unregister: "Deaktivieren"
passwordLessLogin: "Passwortloses Anmelden einrichten" passwordLessLogin: "Passwortloses Anmelden einrichten"
passwordLessLoginDescription: "Ermöglicht passwortfreies Einloggen, nur via Security-Token oder Passkey"
resetPassword: "Passwort zurücksetzen" resetPassword: "Passwort zurücksetzen"
newPasswordIs: "Das neue Passwort ist „{password}“" newPasswordIs: "Das neue Passwort ist „{password}“"
reduceUiAnimation: "Animationen der Benutzeroberfläche reduzieren" reduceUiAnimation: "Animationen der Benutzeroberfläche reduzieren"
@@ -415,24 +420,15 @@ markAsReadAllTalkMessages: "Alle Chats als gelesen markieren"
help: "Hilfe" help: "Hilfe"
inputMessageHere: "Hier Nachricht eingeben" inputMessageHere: "Hier Nachricht eingeben"
close: "Schließen" close: "Schließen"
group: "Gruppe"
groups: "Gruppen"
createGroup: "Gruppe erstellen"
ownedGroups: "Meine Gruppen"
joinedGroups: "Beigetretene Gruppen"
invites: "Einladungen" invites: "Einladungen"
groupName: "Gruppenname"
members: "Mitglieder" members: "Mitglieder"
transfer: "Übertragen" transfer: "Übertragen"
messagingWithUser: "Privatchat"
messagingWithGroup: "Gruppenchat"
title: "Titel" title: "Titel"
text: "Text" text: "Text"
enable: "Aktivieren" enable: "Aktivieren"
next: "Weiter" next: "Weiter"
retype: "Erneut eingeben" retype: "Erneut eingeben"
noteOf: "Notiz von {user}" noteOf: "Notiz von {user}"
inviteToGroup: "Zu Gruppe einladen"
quoteAttached: "Zitat" quoteAttached: "Zitat"
quoteQuestion: "Als Zitat anhängen?" quoteQuestion: "Als Zitat anhängen?"
noMessagesYet: "Noch keine Nachrichten vorhanden" noMessagesYet: "Noch keine Nachrichten vorhanden"
@@ -454,19 +450,18 @@ passwordMatched: "Stimmt überein"
passwordNotMatched: "Stimmt nicht überein" passwordNotMatched: "Stimmt nicht überein"
signinWith: "Mit {x} anmelden" signinWith: "Mit {x} anmelden"
signinFailed: "Anmeldung fehlgeschlagen. Überprüfe Benutzername und Passswort." signinFailed: "Anmeldung fehlgeschlagen. Überprüfe Benutzername und Passswort."
tapSecurityKey: "Tippe deinen Sicherheitsschlüssel an"
or: "Oder" or: "Oder"
language: "Sprache" language: "Sprache"
uiLanguage: "Sprache der Benutzeroberfläche" uiLanguage: "Sprache der Benutzeroberfläche"
groupInvited: "Du wurdest in eine Gruppe eingeladen"
aboutX: "Über {x}" aboutX: "Über {x}"
emojiStyle: "Emoji-Stil" emojiStyle: "Emoji-Stil"
native: "Nativ" native: "Nativ"
disableDrawer: "Keine ausfahrbaren Menüs verwenden" disableDrawer: "Keine ausfahrbaren Menüs verwenden"
youHaveNoGroups: "Keine Gruppen vorhanden" showNoteActionsOnlyHover: "Aktionen für Notizen nur bei Mouseover anzeigen"
joinOrCreateGroup: "Lass dich zu einer Gruppe einladen oder erstelle deine eigene."
noHistory: "Kein Verlauf gefunden" noHistory: "Kein Verlauf gefunden"
signinHistory: "Anmeldungsverlauf" signinHistory: "Anmeldungsverlauf"
enableAdvancedMfm: "Erweitertes MFM aktivieren"
enableAnimatedMfm: "Animiertes MFM aktivieren"
doing: "In Bearbeitung …" doing: "In Bearbeitung …"
category: "Kategorie" category: "Kategorie"
tags: "Schlagwörter" tags: "Schlagwörter"
@@ -785,6 +780,7 @@ popularPosts: "Beliebte Beiträge"
shareWithNote: "Mit Notiz teilen" shareWithNote: "Mit Notiz teilen"
ads: "Werbung" ads: "Werbung"
expiration: "Frist" expiration: "Frist"
startingperiod: "Start"
memo: "Merkzettel" memo: "Merkzettel"
priority: "Priorität" priority: "Priorität"
high: "Hoch" high: "Hoch"
@@ -817,6 +813,7 @@ lastCommunication: "Letzte Kommunikation"
resolved: "Gelöst" resolved: "Gelöst"
unresolved: "Ungelöst" unresolved: "Ungelöst"
breakFollow: "Follower entfernen" breakFollow: "Follower entfernen"
breakFollowConfirm: "Diesen Follower wirklich entfernen?"
itsOn: "Eingeschaltet" itsOn: "Eingeschaltet"
itsOff: "Ausgeschaltet" itsOff: "Ausgeschaltet"
emailRequiredForSignup: "Angabe einer Email-Adresse als benötigt markieren" emailRequiredForSignup: "Angabe einer Email-Adresse als benötigt markieren"
@@ -836,8 +833,6 @@ deleteAccountConfirm: "Dein Benutzerkonto wird unwiderruflich gelöscht. Trotzde
incorrectPassword: "Falsches Passwort." incorrectPassword: "Falsches Passwort."
voteConfirm: "Wirklich für „{choice}“ abstimmen?" voteConfirm: "Wirklich für „{choice}“ abstimmen?"
hide: "Inhalt verbergen" hide: "Inhalt verbergen"
leaveGroup: "Gruppe verlassen"
leaveGroupConfirm: "Möchtest du „{name}“ wirklich verlassen?"
useDrawerReactionPickerForMobile: "Auf mobilen Geräten ausfahrbare Reaktionsauswahl anzeigen" useDrawerReactionPickerForMobile: "Auf mobilen Geräten ausfahrbare Reaktionsauswahl anzeigen"
welcomeBackWithName: "Willkommen zurück, {name}" welcomeBackWithName: "Willkommen zurück, {name}"
clickToFinishEmailVerification: "Drücke bitte auf [{ok}], um die Email-Bestätigung abzuschließen." clickToFinishEmailVerification: "Drücke bitte auf [{ok}], um die Email-Bestätigung abzuschließen."
@@ -853,11 +848,13 @@ instanceDefaultLightTheme: "Instanzweites Standardfarbschema (Hell)"
instanceDefaultDarkTheme: "Instanzweites Standardfarbschema (Dunkel)" instanceDefaultDarkTheme: "Instanzweites Standardfarbschema (Dunkel)"
instanceDefaultThemeDescription: "Gib den Farbschemencode im Objektformat ein." instanceDefaultThemeDescription: "Gib den Farbschemencode im Objektformat ein."
mutePeriod: "Stummschaltungsdauer" mutePeriod: "Stummschaltungsdauer"
period: "Zeitlimit"
indefinitely: "Dauerhaft" indefinitely: "Dauerhaft"
tenMinutes: "10 Minuten" tenMinutes: "10 Minuten"
oneHour: "Eine Stunde" oneHour: "Eine Stunde"
oneDay: "Einen Tag" oneDay: "Einen Tag"
oneWeek: "Eine Woche" oneWeek: "Eine Woche"
oneMonth: "1 Monat"
reflectMayTakeTime: "Es kann etwas dauern, bis sich dies widerspiegelt." reflectMayTakeTime: "Es kann etwas dauern, bis sich dies widerspiegelt."
failedToFetchAccountInformation: "Benutzerkontoinformationen konnten nicht abgefragt werden" failedToFetchAccountInformation: "Benutzerkontoinformationen konnten nicht abgefragt werden"
rateLimitExceeded: "Versuchsanzahl überschritten" rateLimitExceeded: "Versuchsanzahl überschritten"
@@ -945,6 +942,19 @@ selectFromPresets: "Aus Vorlagen wählen"
achievements: "Errungenschaften" achievements: "Errungenschaften"
gotInvalidResponseError: "Ungültige Antwort des Servers" gotInvalidResponseError: "Ungültige Antwort des Servers"
gotInvalidResponseErrorDescription: "Eventuell ist der Server momentan nicht erreichbar oder untergeht Wartungsarbeiten. Bitte versuche es später noch einmal." gotInvalidResponseErrorDescription: "Eventuell ist der Server momentan nicht erreichbar oder untergeht Wartungsarbeiten. Bitte versuche es später noch einmal."
thisPostMayBeAnnoying: "Dieser Beitrag stört eventuell andere Benutzer."
thisPostMayBeAnnoyingHome: "Zur Startseite schicken"
thisPostMayBeAnnoyingCancel: "Abbrechen"
thisPostMayBeAnnoyingIgnore: "Trotzdem schicken"
collapseRenotes: "Bereits gesehene Renotes verkürzt anzeigen"
internalServerError: "Serverinterner Fehler"
internalServerErrorDescription: "Im Server ist ein unerwarteter Fehler aufgetreten."
copyErrorInfo: "Fehlerdetails kopieren"
joinThisServer: "Bei dieser Instanz registrieren"
exploreOtherServers: "Eine andere Instanz finden"
letsLookAtTimeline: "Die Chronik durchstöbern"
disableFederationWarn: "Dies deaktiviert Föderation, aber alle Notizen bleiben, sofern nicht umgestellt, öffentlich. In den meisten Fällen wird diese Option nicht benötigt."
invitationRequiredToRegister: "Diese Instanz ist einladungsbasiert. Du musst einen validen Einladungscode eingeben, um dich zu registrieren."
_achievements: _achievements:
earnedAt: "Freigeschaltet am" earnedAt: "Freigeschaltet am"
_types: _types:
@@ -1458,6 +1468,7 @@ _ago:
weeksAgo: "vor {n} Woche(n)" weeksAgo: "vor {n} Woche(n)"
monthsAgo: "vor {n} Monat(en)" monthsAgo: "vor {n} Monat(en)"
yearsAgo: "vor {n} Jahr(en)" yearsAgo: "vor {n} Jahr(en)"
invalid: "Ungültig"
_time: _time:
second: "Sekunde(n)" second: "Sekunde(n)"
minute: "Minute(n)" minute: "Minute(n)"
@@ -1491,14 +1502,29 @@ _tutorial:
step8_3: "Diese Einstellung kannst du jederzeit ändern." step8_3: "Diese Einstellung kannst du jederzeit ändern."
_2fa: _2fa:
alreadyRegistered: "Du hast bereits ein Gerät für Zwei-Faktor-Authentifizierung registriert." alreadyRegistered: "Du hast bereits ein Gerät für Zwei-Faktor-Authentifizierung registriert."
registerDevice: "Neues Gerät registrieren" registerTOTP: "Authentifizierungs-App registrieren"
registerKey: "Neuen Sicherheitsschlüssel registrieren" passwordToTOTP: "Bitte Passwort eingeben"
step1: "Installiere zuerst eine Authentifizierungsapp (z.B. {a} oder {b}) auf deinem Gerät." step1: "Installiere zuerst eine Authentifizierungsapp (z.B. {a} oder {b}) auf deinem Gerät."
step2: "Dann, scanne den angezeigten QR-Code mit deinem Gerät." step2: "Dann, scanne den angezeigten QR-Code mit deinem Gerät."
step2Click: "Durch Klicken dieses QR-Codes kannst du Verifikation mit deinem Security-Token oder einer App registrieren."
step2Url: "Nutzt du ein Desktopprogramm kannst du alternativ diese URL eingeben:" step2Url: "Nutzt du ein Desktopprogramm kannst du alternativ diese URL eingeben:"
step3Title: "Authentifizierungsscode eingeben"
step3: "Gib zum Abschluss den Token ein, der von deiner App angezeigt wird." step3: "Gib zum Abschluss den Token ein, der von deiner App angezeigt wird."
step4: "Alle folgenden Anmeldungsversuche werden ab sofort die Eingabe eines solchen Tokens benötigen." step4: "Alle folgenden Anmeldungsversuche werden ab sofort die Eingabe eines solchen Tokens benötigen."
securityKeyNotSupported: "Dein Browser unterstützt keine Security-Tokens."
registerTOTPBeforeKey: "Um einen Security-Token oder einen Passkey zu registrieren, musst du zuerst eine Authentifizierungs-App registrieren."
securityKeyInfo: "Du kannst neben Fingerabdruck- oder PIN-Authentifizierung auf deinem Gerät auch Anmeldung mit Hilfe eines FIDO2-kompatiblen Hardware-Sicherheitsschlüssels einrichten." securityKeyInfo: "Du kannst neben Fingerabdruck- oder PIN-Authentifizierung auf deinem Gerät auch Anmeldung mit Hilfe eines FIDO2-kompatiblen Hardware-Sicherheitsschlüssels einrichten."
chromePasskeyNotSupported: "Chrome-Passkeys werden zur Zeit nicht unterstützt."
registerSecurityKey: "Security-Token oder Passkey registrieren"
securityKeyName: "Schlüsselname eingeben"
tapSecurityKey: "Bitten folge den Anweisungen deines Browsers zur Registrierung"
removeKey: "Sicherheitsschlüssel entfernen"
removeKeyConfirm: "Den Schlüssel {name} wirklich löschen?"
whyTOTPOnlyRenew: "Solange ein Sicherheitsschlüssel registriert ist, kann die Authentifizierungs-App nicht entfernt werden."
renewTOTP: "Authentifizierungs-App neu einrichten"
renewTOTPConfirm: "Codes der bisherigen App werden hierdurch nutzlos"
renewTOTPOk: "Neu einrichten"
renewTOTPCancel: "Abbrechen"
_permissions: _permissions:
"read:account": "Deine Benutzerkontoinformationen lesen" "read:account": "Deine Benutzerkontoinformationen lesen"
"write:account": "Deine Benutzerkontoinformationen bearbeiten" "write:account": "Deine Benutzerkontoinformationen bearbeiten"
@@ -1547,7 +1573,6 @@ _antennaSources:
homeTimeline: "Notizen von Benutzern, denen gefolgt wird" homeTimeline: "Notizen von Benutzern, denen gefolgt wird"
users: "Notizen von einem oder mehreren angegebenen Benutzern" users: "Notizen von einem oder mehreren angegebenen Benutzern"
userList: "Notizen von allen Benutzern einer Liste" userList: "Notizen von allen Benutzern einer Liste"
userGroup: "Notizen von allen Benutzern einer Gruppe"
_weekday: _weekday:
sunday: "Sonntag" sunday: "Sonntag"
monday: "Montag" monday: "Montag"
@@ -1622,8 +1647,8 @@ _visibility:
followersDescription: "Nur für Follower sichtbar" followersDescription: "Nur für Follower sichtbar"
specified: "Direkt" specified: "Direkt"
specifiedDescription: "Nur für bestimmte Benutzer sichtbar" specifiedDescription: "Nur für bestimmte Benutzer sichtbar"
localOnly: "Nur Lokal" disableFederation: "Deförderiert"
localOnlyDescription: "Unsichtbar für Benutzer anderer Instanzen" disableFederationDescription: "Nicht an andere Instanzen übertragen"
_postForm: _postForm:
replyPlaceholder: "Dieser Notiz antworten …" replyPlaceholder: "Dieser Notiz antworten …"
quotePlaceholder: "Diese Notiz zitieren …" quotePlaceholder: "Diese Notiz zitieren …"
@@ -1761,12 +1786,9 @@ _notification:
youGotReply: "{name} hat dir geantwortet" youGotReply: "{name} hat dir geantwortet"
youGotQuote: "{name} hat dich zitiert" youGotQuote: "{name} hat dich zitiert"
youRenoted: "Renote deiner Notiz von {name}" youRenoted: "Renote deiner Notiz von {name}"
youGotMessagingMessageFromUser: "{name} hat dir eine Chatnachricht gesendet"
youGotMessagingMessageFromGroup: "In die Gruppe {name} wurde eine Chatnachricht gesendet"
youWereFollowed: "ist dir gefolgt" youWereFollowed: "ist dir gefolgt"
youReceivedFollowRequest: "Du hast eine Follow-Anfrage erhalten" youReceivedFollowRequest: "Du hast eine Follow-Anfrage erhalten"
yourFollowRequestAccepted: "Deine Follow-Anfrage wurde akzeptiert" yourFollowRequestAccepted: "Deine Follow-Anfrage wurde akzeptiert"
youWereInvitedToGroup: "{userName} hat dich in eine Gruppe eingeladen"
pollEnded: "Umfrageergebnisse sind verfügbar" pollEnded: "Umfrageergebnisse sind verfügbar"
unreadAntennaNote: "Antenne {name}" unreadAntennaNote: "Antenne {name}"
emptyPushNotificationMessage: "Push-Benachrichtigungen wurden aktualisiert" emptyPushNotificationMessage: "Push-Benachrichtigungen wurden aktualisiert"
@@ -1782,7 +1804,7 @@ _notification:
pollEnded: "Ende von Umfragen" pollEnded: "Ende von Umfragen"
receiveFollowRequest: "Erhaltene Follow-Anfragen" receiveFollowRequest: "Erhaltene Follow-Anfragen"
followRequestAccepted: "Akzeptierte Follow-Anfragen" followRequestAccepted: "Akzeptierte Follow-Anfragen"
groupInvited: "Erhaltene Gruppeneinladungen" achievementEarned: "Errungenschaft freigeschaltet"
app: "Benachrichtigungen von Apps" app: "Benachrichtigungen von Apps"
_actions: _actions:
followBack: "folgt dir nun auch" followBack: "folgt dir nun auch"
@@ -1815,3 +1837,6 @@ _deck:
channel: "Kanal" channel: "Kanal"
mentions: "Erwähnungen" mentions: "Erwähnungen"
direct: "Direktnachrichten" direct: "Direktnachrichten"
_dialog:
charactersExceeded: "Maximallänge überschritten! Momentan {current} von {max}"
charactersBelow: "Minimallänge unterschritten! Momentan {current} von {min}"

View File

@@ -230,21 +230,13 @@ moderator: "Συντονιστής"
moderation: "Συντονισμός" moderation: "Συντονισμός"
cacheClear: "Εκκαθάριση προσωρινής μνήμης" cacheClear: "Εκκαθάριση προσωρινής μνήμης"
markAsReadAllNotifications: "Όλες οι ειδοποιήσεις διαβάστηκαν" markAsReadAllNotifications: "Όλες οι ειδοποιήσεις διαβάστηκαν"
group: "Ομάδα"
groups: "Ομάδες"
createGroup: "Δημιουργία ομάδας"
ownedGroups: "Οι ομάδες σας"
groupName: "Όνομα ομάδας"
members: "Μέλη" members: "Μέλη"
transfer: "Μεταφορά" transfer: "Μεταφορά"
messagingWithUser: "Ιδιωτική συνομιλία"
messagingWithGroup: "Ομαδική συνομιλία"
title: "Τίτλος" title: "Τίτλος"
text: "Κείμενο" text: "Κείμενο"
enable: "Ενεργοποίηση" enable: "Ενεργοποίηση"
next: "Επόμενο" next: "Επόμενο"
noteOf: "Σημείωμα από {user}" noteOf: "Σημείωμα από {user}"
inviteToGroup: "Πρόσκληση στην ομάδα"
quoteAttached: "Παράθεση" quoteAttached: "Παράθεση"
signinRequired: "Παρακαλούμε δημιουργήστε λογαριασμό ή συνδεθείτε πριν συνεχίσετε" signinRequired: "Παρακαλούμε δημιουργήστε λογαριασμό ή συνδεθείτε πριν συνεχίσετε"
category: "Κατηγορία" category: "Κατηγορία"
@@ -337,7 +329,6 @@ _antennaSources:
homeTimeline: "Σημειώματα από μέλη που ακολουθείτε" homeTimeline: "Σημειώματα από μέλη που ακολουθείτε"
users: "Σημειώματα από συγκεκριμένα μέλη" users: "Σημειώματα από συγκεκριμένα μέλη"
userList: "Σημειώματα από καθορισμένη λίστα μελών" userList: "Σημειώματα από καθορισμένη λίστα μελών"
userGroup: "Σημειώματα από μέλη καθορισμένης ομάδας"
_widgets: _widgets:
profile: "Προφίλ" profile: "Προφίλ"
instanceInfo: "Πληροφορίες του instance" instanceInfo: "Πληροφορίες του instance"
@@ -382,7 +373,6 @@ _pages:
blocks: blocks:
image: "Εικόνες" image: "Εικόνες"
_notification: _notification:
youGotMessagingMessageFromUser: "{name} σάς έστειλε ένα μήνυμα συνομιλίας"
youWereFollowed: "σε ακολούθησε" youWereFollowed: "σε ακολούθησε"
_types: _types:
follow: "Νέοι ακόλουθοι" follow: "Νέοι ακόλουθοι"

View File

@@ -103,6 +103,8 @@ renoted: "Renoted."
cantRenote: "This post can't be renoted." cantRenote: "This post can't be renoted."
cantReRenote: "A renote can't be renoted." cantReRenote: "A renote can't be renoted."
quote: "Quote" quote: "Quote"
inChannelRenote: "Channel-only Renote"
inChannelQuote: "Channel-only Quote"
pinnedNote: "Pinned note" pinnedNote: "Pinned note"
pinned: "Pin to profile" pinned: "Pin to profile"
you: "You" you: "You"
@@ -391,16 +393,19 @@ about: "About"
aboutMisskey: "About Misskey" aboutMisskey: "About Misskey"
administrator: "Administrator" administrator: "Administrator"
token: "Token" token: "Token"
twoStepAuthentication: "Two-factor authentication" 2fa: "Two-factor authentication"
totp: "Authenticator App"
totpDescription: "Use an authenticator app to enter one-time passwords"
moderator: "Moderator" moderator: "Moderator"
moderation: "Moderation" moderation: "Moderation"
nUsersMentioned: "Mentioned by {n} users" nUsersMentioned: "Mentioned by {n} users"
securityKeyAndPasskey: "Security- and passkeys"
securityKey: "Security key" securityKey: "Security key"
securityKeyName: "Key name"
registerSecurityKey: "Register a security key"
lastUsed: "Last used" lastUsed: "Last used"
lastUsedAt: "Last used: {t}"
unregister: "Unregister" unregister: "Unregister"
passwordLessLogin: "Password-less login" passwordLessLogin: "Password-less login"
passwordLessLoginDescription: "Allows password-less login using a security- or passkey only"
resetPassword: "Reset password" resetPassword: "Reset password"
newPasswordIs: "The new password is \"{password}\"" newPasswordIs: "The new password is \"{password}\""
reduceUiAnimation: "Reduce UI animations" reduceUiAnimation: "Reduce UI animations"
@@ -415,24 +420,15 @@ markAsReadAllTalkMessages: "Mark all messages as read"
help: "Help" help: "Help"
inputMessageHere: "Enter message here" inputMessageHere: "Enter message here"
close: "Close" close: "Close"
group: "Group"
groups: "Groups"
createGroup: "Create a group"
ownedGroups: "Owned Groups"
joinedGroups: "Joined groups"
invites: "Invites" invites: "Invites"
groupName: "Group name"
members: "Members" members: "Members"
transfer: "Transfer" transfer: "Transfer"
messagingWithUser: "Private chat"
messagingWithGroup: "Group chat"
title: "Title" title: "Title"
text: "Text" text: "Text"
enable: "Enable" enable: "Enable"
next: "Next" next: "Next"
retype: "Enter again" retype: "Enter again"
noteOf: "Note by {user}" noteOf: "Note by {user}"
inviteToGroup: "Invite to group"
quoteAttached: "Quote" quoteAttached: "Quote"
quoteQuestion: "Append as quote?" quoteQuestion: "Append as quote?"
noMessagesYet: "No messages yet" noMessagesYet: "No messages yet"
@@ -454,21 +450,18 @@ passwordMatched: "Matches"
passwordNotMatched: "Does not match" passwordNotMatched: "Does not match"
signinWith: "Sign in with {x}" signinWith: "Sign in with {x}"
signinFailed: "Unable to sign in. The entered username or password is incorrect." signinFailed: "Unable to sign in. The entered username or password is incorrect."
tapSecurityKey: "Tap your security key"
or: "Or" or: "Or"
language: "Language" language: "Language"
uiLanguage: "User interface language" uiLanguage: "User interface language"
groupInvited: "You've been invited to a group"
aboutX: "About {x}" aboutX: "About {x}"
emojiStyle: "Emoji style" emojiStyle: "Emoji style"
native: "Native" native: "Native"
disableDrawer: "Don't use drawer-style menus" disableDrawer: "Don't use drawer-style menus"
youHaveNoGroups: "You have no groups" showNoteActionsOnlyHover: "Only show note actions on hover"
joinOrCreateGroup: "Get invited to a group or create your own."
noHistory: "No history available" noHistory: "No history available"
signinHistory: "Login history" signinHistory: "Login history"
enableAdvancedMfm: "Enable advanced MFM" enableAdvancedMfm: "Enable advanced MFM"
enableAnimatedMfm: "Enable MFM with animation" enableAnimatedMfm: "Enable animated MFM"
doing: "Processing..." doing: "Processing..."
category: "Category" category: "Category"
tags: "Tags" tags: "Tags"
@@ -787,6 +780,7 @@ popularPosts: "Popular posts"
shareWithNote: "Share with note" shareWithNote: "Share with note"
ads: "Advertisements" ads: "Advertisements"
expiration: "Deadline" expiration: "Deadline"
startingperiod: "Start"
memo: "Memo" memo: "Memo"
priority: "Priority" priority: "Priority"
high: "High" high: "High"
@@ -819,6 +813,7 @@ lastCommunication: "Last communication"
resolved: "Resolved" resolved: "Resolved"
unresolved: "Unresolved" unresolved: "Unresolved"
breakFollow: "Remove follower" breakFollow: "Remove follower"
breakFollowConfirm: "Really remove this follower?"
itsOn: "Enabled" itsOn: "Enabled"
itsOff: "Disabled" itsOff: "Disabled"
emailRequiredForSignup: "Require email address for sign-up" emailRequiredForSignup: "Require email address for sign-up"
@@ -838,8 +833,6 @@ deleteAccountConfirm: "This will irreversibly delete your account. Proceed?"
incorrectPassword: "Incorrect password." incorrectPassword: "Incorrect password."
voteConfirm: "Confirm your vote for \"{choice}\"?" voteConfirm: "Confirm your vote for \"{choice}\"?"
hide: "Hide" hide: "Hide"
leaveGroup: "Leave group"
leaveGroupConfirm: "Are you sure you want to leave \"{name}\"?"
useDrawerReactionPickerForMobile: "Display reaction picker as drawer on mobile" useDrawerReactionPickerForMobile: "Display reaction picker as drawer on mobile"
welcomeBackWithName: "Welcome back, {name}" welcomeBackWithName: "Welcome back, {name}"
clickToFinishEmailVerification: "Please click [{ok}] to complete email verification." clickToFinishEmailVerification: "Please click [{ok}] to complete email verification."
@@ -855,11 +848,13 @@ instanceDefaultLightTheme: "Instance-wide default light theme"
instanceDefaultDarkTheme: "Instance-wide default dark theme" instanceDefaultDarkTheme: "Instance-wide default dark theme"
instanceDefaultThemeDescription: "Enter the theme code in object format." instanceDefaultThemeDescription: "Enter the theme code in object format."
mutePeriod: "Mute duration" mutePeriod: "Mute duration"
period: "Time limit"
indefinitely: "Permanently" indefinitely: "Permanently"
tenMinutes: "10 minutes" tenMinutes: "10 minutes"
oneHour: "One hour" oneHour: "One hour"
oneDay: "One day" oneDay: "One day"
oneWeek: "One week" oneWeek: "One week"
oneMonth: "One month"
reflectMayTakeTime: "It may take some time for this to be reflected." reflectMayTakeTime: "It may take some time for this to be reflected."
failedToFetchAccountInformation: "Could not fetch account information" failedToFetchAccountInformation: "Could not fetch account information"
rateLimitExceeded: "Rate limit exceeded" rateLimitExceeded: "Rate limit exceeded"
@@ -951,6 +946,15 @@ thisPostMayBeAnnoying: "This note may annoy others."
thisPostMayBeAnnoyingHome: "Post to home timeline" thisPostMayBeAnnoyingHome: "Post to home timeline"
thisPostMayBeAnnoyingCancel: "Cancel" thisPostMayBeAnnoyingCancel: "Cancel"
thisPostMayBeAnnoyingIgnore: "Post anyway" thisPostMayBeAnnoyingIgnore: "Post anyway"
collapseRenotes: "Collapse renotes you've already seen"
internalServerError: "Internal Server Error"
internalServerErrorDescription: "The server has run into an unexpected error."
copyErrorInfo: "Copy error details"
joinThisServer: "Sign up at this instance"
exploreOtherServers: "Look for another instance"
letsLookAtTimeline: "Have a look at the timeline"
disableFederationWarn: "This will disable federation, but posts will continue to be public unless set otherwise. You usually do not need to use this setting."
invitationRequiredToRegister: "This instance is invite-only. You must enter a valid invite code sign up."
_achievements: _achievements:
earnedAt: "Unlocked at" earnedAt: "Unlocked at"
_types: _types:
@@ -1159,7 +1163,7 @@ _achievements:
description: "You've clicked here" description: "You've clicked here"
_justPlainLucky: _justPlainLucky:
title: "Just Plain Lucky" title: "Just Plain Lucky"
description: "Has a chance to be obtained with a probability of 0.01% every 10 seconds" description: "Has a chance to be obtained with a probability of 0.005% every 10 seconds"
_setNameToSyuilo: _setNameToSyuilo:
title: "God Complex" title: "God Complex"
description: "Set your name to \"syuilo\"" description: "Set your name to \"syuilo\""
@@ -1464,6 +1468,7 @@ _ago:
weeksAgo: "{n}w ago" weeksAgo: "{n}w ago"
monthsAgo: "{n}mo ago" monthsAgo: "{n}mo ago"
yearsAgo: "{n}y ago" yearsAgo: "{n}y ago"
invalid: "None"
_time: _time:
second: "Second(s)" second: "Second(s)"
minute: "Minute(s)" minute: "Minute(s)"
@@ -1497,14 +1502,29 @@ _tutorial:
step8_3: "You can always change this setting later." step8_3: "You can always change this setting later."
_2fa: _2fa:
alreadyRegistered: "You have already registered a 2-factor authentication device." alreadyRegistered: "You have already registered a 2-factor authentication device."
registerDevice: "Register a new device" registerTOTP: "Register authenticator app"
registerKey: "Register a security key" passwordToTOTP: "Enter your password"
step1: "First, install an authentication app (such as {a} or {b}) on your device." step1: "First, install an authentication app (such as {a} or {b}) on your device."
step2: "Then, scan the QR code displayed on this screen." step2: "Then, scan the QR code displayed on this screen."
step2Click: "Clicking on this QR code will allow you to register 2FA to your security key or phone authenticator app."
step2Url: "You can also enter this URL if you're using a desktop program:" step2Url: "You can also enter this URL if you're using a desktop program:"
step3Title: "Enter an authentication code"
step3: "Enter the token provided by your app to finish setup." step3: "Enter the token provided by your app to finish setup."
step4: "From now on, any future login attempts will ask for such a login token." step4: "From now on, any future login attempts will ask for such a login token."
securityKeyNotSupported: "Your browser does not support security keys."
registerTOTPBeforeKey: "Please set up an authenticator app to register a security or pass key."
securityKeyInfo: "Besides fingerprint or PIN authentication, you can also setup authentication via hardware security keys that support FIDO2 to further secure your account." securityKeyInfo: "Besides fingerprint or PIN authentication, you can also setup authentication via hardware security keys that support FIDO2 to further secure your account."
chromePasskeyNotSupported: "Chrome passkeys are currently not supported."
registerSecurityKey: "Register a security or pass key"
securityKeyName: "Enter a key name"
tapSecurityKey: "Please follow your browser to register the security or pass key"
removeKey: "Remove security key"
removeKeyConfirm: "Really delete the {name} key?"
whyTOTPOnlyRenew: "The authenticator app cannot be removed as long as a security key is registered."
renewTOTP: "Reconfigure authenticator app"
renewTOTPConfirm: "This will cause verification codes from your previous app to stop working"
renewTOTPOk: "Reconfigure"
renewTOTPCancel: "Cancel"
_permissions: _permissions:
"read:account": "View your account information" "read:account": "View your account information"
"write:account": "Edit your account information" "write:account": "Edit your account information"
@@ -1553,7 +1573,6 @@ _antennaSources:
homeTimeline: "Notes from followed users" homeTimeline: "Notes from followed users"
users: "Notes from specific users" users: "Notes from specific users"
userList: "Notes from a specified list of users" userList: "Notes from a specified list of users"
userGroup: "Notes from users in a specified group"
_weekday: _weekday:
sunday: "Sunday" sunday: "Sunday"
monday: "Monday" monday: "Monday"
@@ -1628,8 +1647,8 @@ _visibility:
followersDescription: "Make visible to your followers only" followersDescription: "Make visible to your followers only"
specified: "Direct" specified: "Direct"
specifiedDescription: "Make visible for specified users only" specifiedDescription: "Make visible for specified users only"
localOnly: "Local only" disableFederation: "Unfederated"
localOnlyDescription: "Not visible to remote users" disableFederationDescription: "Don't transmit to other instances"
_postForm: _postForm:
replyPlaceholder: "Reply to this note..." replyPlaceholder: "Reply to this note..."
quotePlaceholder: "Quote this note..." quotePlaceholder: "Quote this note..."
@@ -1767,12 +1786,9 @@ _notification:
youGotReply: "{name} replied to you" youGotReply: "{name} replied to you"
youGotQuote: "{name} quoted you" youGotQuote: "{name} quoted you"
youRenoted: "Renote from {name}" youRenoted: "Renote from {name}"
youGotMessagingMessageFromUser: "{name} sent you a chat message"
youGotMessagingMessageFromGroup: "A chat message was sent to the {name} group"
youWereFollowed: "followed you" youWereFollowed: "followed you"
youReceivedFollowRequest: "You've received a follow request" youReceivedFollowRequest: "You've received a follow request"
yourFollowRequestAccepted: "Your follow request was accepted" yourFollowRequestAccepted: "Your follow request was accepted"
youWereInvitedToGroup: "{userName} invited you to a group"
pollEnded: "Poll results have become available" pollEnded: "Poll results have become available"
unreadAntennaNote: "Antenna {name}" unreadAntennaNote: "Antenna {name}"
emptyPushNotificationMessage: "Push notifications have been updated" emptyPushNotificationMessage: "Push notifications have been updated"
@@ -1788,7 +1804,7 @@ _notification:
pollEnded: "Polls ending" pollEnded: "Polls ending"
receiveFollowRequest: "Received follow requests" receiveFollowRequest: "Received follow requests"
followRequestAccepted: "Accepted follow requests" followRequestAccepted: "Accepted follow requests"
groupInvited: "Group invitations" achievementEarned: "Achievement unlocked"
app: "Notifications from linked apps" app: "Notifications from linked apps"
_actions: _actions:
followBack: "followed you back" followBack: "followed you back"
@@ -1821,3 +1837,6 @@ _deck:
channel: "Channel" channel: "Channel"
mentions: "Mentions" mentions: "Mentions"
direct: "Direct notes" direct: "Direct notes"
_dialog:
charactersExceeded: "You've exceeded the maximum character limit! Currently at {current} of {max}."
charactersBelow: "You're below the minimum character limit! Currently at {current} of {min}."

View File

@@ -103,6 +103,8 @@ renoted: "Renotado"
cantRenote: "No se puede renotar este post" cantRenote: "No se puede renotar este post"
cantReRenote: "No se puede renotar una renota" cantReRenote: "No se puede renotar una renota"
quote: "Citar" quote: "Citar"
inChannelRenote: "Renota sólo del canal"
inChannelQuote: "Cita sólo del canal"
pinnedNote: "Nota fijada" pinnedNote: "Nota fijada"
pinned: "Fijar al perfil" pinned: "Fijar al perfil"
you: "Tú" you: "Tú"
@@ -391,16 +393,19 @@ about: "Información"
aboutMisskey: "Sobre Misskey" aboutMisskey: "Sobre Misskey"
administrator: "Administrador" administrator: "Administrador"
token: "Token" token: "Token"
twoStepAuthentication: "Autenticación de dos factores" 2fa: "Autenticación de doble factor"
totp: "Aplicación autentícadora"
totpDescription: "Ingresa una contaseña de un sólo uso usando la aplicación autenticadora"
moderator: "Moderador" moderator: "Moderador"
moderation: "Moderación" moderation: "Moderación"
nUsersMentioned: "{n} usuarios mencionados" nUsersMentioned: "{n} usuarios mencionados"
securityKeyAndPasskey: "Clave de seguridad / clave de paso"
securityKey: "Clave de seguridad" securityKey: "Clave de seguridad"
securityKeyName: "Nombre de la Clave"
registerSecurityKey: "Registrar clave de seguridad"
lastUsed: "Última vez usado" lastUsed: "Última vez usado"
lastUsedAt: "Último uso: {t}"
unregister: "Cancelar registro" unregister: "Cancelar registro"
passwordLessLogin: "Iniciar sesión sin contraseña" passwordLessLogin: "Iniciar sesión sin contraseña"
passwordLessLoginDescription: "Iniciar sesión con sólo una clave se seguridad / de paso sin usar una contraseña"
resetPassword: "Resetear contraseña" resetPassword: "Resetear contraseña"
newPasswordIs: "La nueva contraseña es \"{password}\"" newPasswordIs: "La nueva contraseña es \"{password}\""
reduceUiAnimation: "Reducir la animación de la UI" reduceUiAnimation: "Reducir la animación de la UI"
@@ -415,24 +420,15 @@ markAsReadAllTalkMessages: "Marcar todos los chats como leídos"
help: "Ayuda" help: "Ayuda"
inputMessageHere: "Escribe el mensaje aquí" inputMessageHere: "Escribe el mensaje aquí"
close: "Cerrar" close: "Cerrar"
group: "Grupo"
groups: "Grupos"
createGroup: "Crear grupo"
ownedGroups: "Tus"
joinedGroups: "Grupos a los que me uní"
invites: "Invitar" invites: "Invitar"
groupName: "Nombre del grupo"
members: "Miembros" members: "Miembros"
transfer: "Transferir" transfer: "Transferir"
messagingWithUser: "Chatear con usuario"
messagingWithGroup: "Chatear en grupo"
title: "Título" title: "Título"
text: "Texto" text: "Texto"
enable: "Activar" enable: "Activar"
next: "Siguiente" next: "Siguiente"
retype: "Intentar de nuevo" retype: "Intentar de nuevo"
noteOf: "Notas de {user}" noteOf: "Notas de {user}"
inviteToGroup: "Invitar al grupo"
quoteAttached: "Cita añadida" quoteAttached: "Cita añadida"
quoteQuestion: "¿Quiere añadir una cita?" quoteQuestion: "¿Quiere añadir una cita?"
noMessagesYet: "Aún no hay chat" noMessagesYet: "Aún no hay chat"
@@ -454,19 +450,18 @@ passwordMatched: "Correcto"
passwordNotMatched: "Las contraseñas no son las mismas" passwordNotMatched: "Las contraseñas no son las mismas"
signinWith: "Inicie sesión con {x}" signinWith: "Inicie sesión con {x}"
signinFailed: "Autenticación fallida. Asegúrate de haber usado el nombre de usuario y contraseña correctos." signinFailed: "Autenticación fallida. Asegúrate de haber usado el nombre de usuario y contraseña correctos."
tapSecurityKey: "Toque la clave de seguridad"
or: "O" or: "O"
language: "Idioma" language: "Idioma"
uiLanguage: "Idioma de visualización de la interfaz" uiLanguage: "Idioma de visualización de la interfaz"
groupInvited: "Invitado al grupo"
aboutX: "Acerca de {x}" aboutX: "Acerca de {x}"
emojiStyle: "Estilo de emoji" emojiStyle: "Estilo de emoji"
native: "Nativo" native: "Nativo"
disableDrawer: "No mostrar los menús en cajones" disableDrawer: "No mostrar los menús en cajones"
youHaveNoGroups: "Sin grupos" showNoteActionsOnlyHover: "Mostrar acciones de la nota sólo al pasar el cursor"
joinOrCreateGroup: "Obtenga una invitación para unirse al grupos o puede crear su propio grupo."
noHistory: "No hay datos en el historial" noHistory: "No hay datos en el historial"
signinHistory: "Historial de ingresos" signinHistory: "Historial de ingresos"
enableAdvancedMfm: "Habilitar MFM avanzado"
enableAnimatedMfm: "Habilitar MFM con movimiento"
doing: "Voy en camino" doing: "Voy en camino"
category: "Categoría" category: "Categoría"
tags: "Etiqueta" tags: "Etiqueta"
@@ -785,6 +780,7 @@ popularPosts: "Más vistos"
shareWithNote: "Compartir con una nota" shareWithNote: "Compartir con una nota"
ads: "Anuncios" ads: "Anuncios"
expiration: "Termina el" expiration: "Termina el"
startingperiod: "periodo de inicio"
memo: "Notas" memo: "Notas"
priority: "Prioridad" priority: "Prioridad"
high: "Alta" high: "Alta"
@@ -817,6 +813,7 @@ lastCommunication: "Última comunicación"
resolved: "Resuelto" resolved: "Resuelto"
unresolved: "Sin resolver" unresolved: "Sin resolver"
breakFollow: "Dejar de seguir" breakFollow: "Dejar de seguir"
breakFollowConfirm: "¿Quieres dejar de seguir?"
itsOn: "¡Está encendido!" itsOn: "¡Está encendido!"
itsOff: "¡Está apagado!" itsOff: "¡Está apagado!"
emailRequiredForSignup: "Se requere una dirección de correo electrónico para el registro de la cuenta" emailRequiredForSignup: "Se requere una dirección de correo electrónico para el registro de la cuenta"
@@ -836,8 +833,6 @@ deleteAccountConfirm: "La cuenta será borrada. ¿Está seguro?"
incorrectPassword: "La contraseña es incorrecta" incorrectPassword: "La contraseña es incorrecta"
voteConfirm: "¿Confirma su voto a {choice}?" voteConfirm: "¿Confirma su voto a {choice}?"
hide: "Ocultar" hide: "Ocultar"
leaveGroup: "Dejar el grupo"
leaveGroupConfirm: "¿Desea salir de {name}?"
useDrawerReactionPickerForMobile: "Mostrar panel de reacciones en móviles" useDrawerReactionPickerForMobile: "Mostrar panel de reacciones en móviles"
welcomeBackWithName: "Bienvenido otra vez, {name}" welcomeBackWithName: "Bienvenido otra vez, {name}"
clickToFinishEmailVerification: "Cliquée {ok} y verifique su correo" clickToFinishEmailVerification: "Cliquée {ok} y verifique su correo"
@@ -853,6 +848,7 @@ instanceDefaultLightTheme: "Tema claro por defecto de la instancia"
instanceDefaultDarkTheme: "Tema oscuro por defecto de la instancia" instanceDefaultDarkTheme: "Tema oscuro por defecto de la instancia"
instanceDefaultThemeDescription: "Ingrese el código del tema en formato objeto" instanceDefaultThemeDescription: "Ingrese el código del tema en formato objeto"
mutePeriod: "Período de silenciamiento" mutePeriod: "Período de silenciamiento"
period: "Termina el"
indefinitely: "Sin límite de tiempo" indefinitely: "Sin límite de tiempo"
tenMinutes: "10 minutos" tenMinutes: "10 minutos"
oneHour: "1 hora" oneHour: "1 hora"
@@ -863,6 +859,8 @@ failedToFetchAccountInformation: "No se pudo obtener información de la cuenta"
rateLimitExceeded: "Se excedió el límite de peticiones" rateLimitExceeded: "Se excedió el límite de peticiones"
cropImage: "Recortar imágen" cropImage: "Recortar imágen"
cropImageAsk: "¿Desea recortar la imagen?" cropImageAsk: "¿Desea recortar la imagen?"
cropYes: "Recortar"
cropNo: "Usar como está"
file: "Archivos" file: "Archivos"
recentNHours: "Últimas {n} horas" recentNHours: "Últimas {n} horas"
recentNDays: "Últimos {n} días" recentNDays: "Últimos {n} días"
@@ -943,6 +941,19 @@ selectFromPresets: "Escoger desde predefinidos"
achievements: "Logros" achievements: "Logros"
gotInvalidResponseError: "Respuesta del servidor inválida" gotInvalidResponseError: "Respuesta del servidor inválida"
gotInvalidResponseErrorDescription: "Puede que el servidor esté caído o en mantenimiento. Favor de intentar más tarde" gotInvalidResponseErrorDescription: "Puede que el servidor esté caído o en mantenimiento. Favor de intentar más tarde"
thisPostMayBeAnnoying: "Ésta publicación puede resultar molesta."
thisPostMayBeAnnoyingHome: "Publicar en línea de tiempo 'Inicio'"
thisPostMayBeAnnoyingCancel: "detener"
thisPostMayBeAnnoyingIgnore: "Publicar de todos modos"
collapseRenotes: "Colapsar renotas que ya hayas visto"
internalServerError: "Error interno del servidor"
internalServerErrorDescription: "El servidor tuvo un error inesperado."
copyErrorInfo: "Copiar detalles del error"
joinThisServer: "Registrarse en esta instancia"
exploreOtherServers: "Buscar otra instancia"
letsLookAtTimeline: "Mirar la línea de tiempo local"
disableFederationWarn: "Esto desactivará la federación, pero las publicaciones segurán siendo públicas al menos que se configure diferente. Usualmente no necesitas usar esta configuración."
invitationRequiredToRegister: "Esta instancia está configurada sólo por invitación, tienes que ingresar un código de invitación válido."
_achievements: _achievements:
earnedAt: "Desbloqueado el" earnedAt: "Desbloqueado el"
_types: _types:
@@ -1456,6 +1467,7 @@ _ago:
weeksAgo: "Hace {n} semanas" weeksAgo: "Hace {n} semanas"
monthsAgo: "Hace {n} meses" monthsAgo: "Hace {n} meses"
yearsAgo: "Hace {n} años" yearsAgo: "Hace {n} años"
invalid: "No hay nada que ver aqui"
_time: _time:
second: "Segundos" second: "Segundos"
minute: "Minutos" minute: "Minutos"
@@ -1489,14 +1501,29 @@ _tutorial:
step8_3: "La configuración de las notificaciones puede modificarse posteriormente." step8_3: "La configuración de las notificaciones puede modificarse posteriormente."
_2fa: _2fa:
alreadyRegistered: "Ya has completado la configuración." alreadyRegistered: "Ya has completado la configuración."
registerDevice: "Registrar dispositivo" registerTOTP: "Registrar aplicación autenticadora"
registerKey: "Registrar clave" passwordToTOTP: "Ingresa tu contraseña"
step1: "Primero, instale en su dispositivo la aplicación de autenticación {a} o {b} u otra." step1: "Primero, instale en su dispositivo la aplicación de autenticación {a} o {b} u otra."
step2: "Luego, escanee con la aplicación el código QR mostrado en pantalla." step2: "Luego, escanee con la aplicación el código QR mostrado en pantalla."
step2Click: "Clicking on this QR code will allow you to register 2FA to your security key or phone authenticator app.\nTocar este código QR te permitirá registrar la autenticación 2FA a tu llave de seguridad o aplicación autenticadora."
step2Url: "En una aplicación de escritorio se puede ingresar la siguiente URL:" step2Url: "En una aplicación de escritorio se puede ingresar la siguiente URL:"
step3Title: "Ingresa un código de autenticación"
step3: "Para terminar, ingrese el token mostrado en la aplicación." step3: "Para terminar, ingrese el token mostrado en la aplicación."
step4: "Ahora cuando inicie sesión, ingrese el mismo token" step4: "Ahora cuando inicie sesión, ingrese el mismo token"
securityKeyNotSupported: "Tu navegador no soporta claves de autenticación."
registerTOTPBeforeKey: "Please set up an authenticator app to register a security or pass key.\npor favor. configura una aplicación de autenticación para registrar una llave de seguridad."
securityKeyInfo: "Se puede configurar el inicio de sesión usando una clave de seguridad de hardware que soporte FIDO2 o con un certificado de huella digital o con un PIN" securityKeyInfo: "Se puede configurar el inicio de sesión usando una clave de seguridad de hardware que soporte FIDO2 o con un certificado de huella digital o con un PIN"
chromePasskeyNotSupported: "Las llaves de seguridad de Chrome no son soportadas por el momento."
registerSecurityKey: "Registrar una llave de seguridad"
securityKeyName: "Ingresa un nombre para la clave"
tapSecurityKey: "Por favor, sigue tu navegador para registrar una llave de seguridad"
removeKey: "Quitar la llave de seguridad"
removeKeyConfirm: "¿Borrar el respaldo \"{name}\"?"
whyTOTPOnlyRenew: "The authenticator app cannot be removed as long as a security key is registered.\nLa aplicación autenticadora no puede ser eliminada mientras la llave de seguridad se encuentre registrada."
renewTOTP: "Reconfigurar la aplicación autenticadora"
renewTOTPConfirm: "This will cause verification codes from your previous app to stop working\nEsto hará que los códigos de verificación de la aplicación anterior dejen de funcionar"
renewTOTPOk: "Reconfigurar"
renewTOTPCancel: "No gracias"
_permissions: _permissions:
"read:account": "Ver información de la cuenta" "read:account": "Ver información de la cuenta"
"write:account": "Editar información de la cuenta" "write:account": "Editar información de la cuenta"
@@ -1545,7 +1572,6 @@ _antennaSources:
homeTimeline: "Notas de los usuarios que sigues" homeTimeline: "Notas de los usuarios que sigues"
users: "Notas de un usuario o varios" users: "Notas de un usuario o varios"
userList: "Notas de los usuarios de una lista" userList: "Notas de los usuarios de una lista"
userGroup: "Notas de los usuarios de una grupo"
_weekday: _weekday:
sunday: "Domingo" sunday: "Domingo"
monday: "Lunes" monday: "Lunes"
@@ -1620,8 +1646,8 @@ _visibility:
followersDescription: "Visible sólo para tus seguidores" followersDescription: "Visible sólo para tus seguidores"
specified: "Mensaje directo" specified: "Mensaje directo"
specifiedDescription: "Visible sólo para los usuarios elegidos" specifiedDescription: "Visible sólo para los usuarios elegidos"
localOnly: "Solo local" disableFederation: "No federado"
localOnlyDescription: "Oculto para usuarios remotos" disableFederationDescription: "No enviar a otras instancias"
_postForm: _postForm:
replyPlaceholder: "Responder a esta nota" replyPlaceholder: "Responder a esta nota"
quotePlaceholder: "Citar esta nota" quotePlaceholder: "Citar esta nota"
@@ -1759,12 +1785,9 @@ _notification:
youGotReply: "Respuesta de {name}" youGotReply: "Respuesta de {name}"
youGotQuote: "Citado por {name}" youGotQuote: "Citado por {name}"
youRenoted: "Renotado por {name}" youRenoted: "Renotado por {name}"
youGotMessagingMessageFromUser: "{name} comenzó un chat contigo"
youGotMessagingMessageFromGroup: "Tienes un chat de {name}"
youWereFollowed: "te ha seguido" youWereFollowed: "te ha seguido"
youReceivedFollowRequest: "Has mandado una solicitud de seguimiento" youReceivedFollowRequest: "Has mandado una solicitud de seguimiento"
yourFollowRequestAccepted: "Tu solicitud de seguimiento fue aceptada" yourFollowRequestAccepted: "Tu solicitud de seguimiento fue aceptada"
youWereInvitedToGroup: "Invitado al grupo"
pollEnded: "Estan disponibles los resultados de la encuesta" pollEnded: "Estan disponibles los resultados de la encuesta"
unreadAntennaNote: "Antena {name}" unreadAntennaNote: "Antena {name}"
emptyPushNotificationMessage: "Se han actualizado las notificaciones push" emptyPushNotificationMessage: "Se han actualizado las notificaciones push"
@@ -1780,7 +1803,7 @@ _notification:
pollEnded: "La encuesta terminó" pollEnded: "La encuesta terminó"
receiveFollowRequest: "Recibió una solicitud de seguimiento" receiveFollowRequest: "Recibió una solicitud de seguimiento"
followRequestAccepted: "El seguimiento fue aceptado" followRequestAccepted: "El seguimiento fue aceptado"
groupInvited: "Invitado al grupo" achievementEarned: "Logro desbloqueado"
app: "Notificaciones desde aplicaciones" app: "Notificaciones desde aplicaciones"
_actions: _actions:
followBack: "Te sigue de vuelta" followBack: "Te sigue de vuelta"
@@ -1813,3 +1836,6 @@ _deck:
channel: "Canal" channel: "Canal"
mentions: "Menciones" mentions: "Menciones"
direct: "Mensaje directo" direct: "Mensaje directo"
_dialog:
charactersExceeded: "¡Has excedido el límite de caracteres! Actualmente {current} de {max}."
charactersBelow: "¡Estás por debajo del límite de caracteres! Actualmente {current} de {min}."

View File

@@ -103,6 +103,8 @@ renoted: "Renoté !"
cantRenote: "Ce message ne peut pas être renoté." cantRenote: "Ce message ne peut pas être renoté."
cantReRenote: "Impossible de renoter une Renote." cantReRenote: "Impossible de renoter une Renote."
quote: "Citer" quote: "Citer"
inChannelRenote: "Renoter dans le canal"
inChannelQuote: "Citer dans le canal"
pinnedNote: "Note épinglée" pinnedNote: "Note épinglée"
pinned: "Épingler sur le profil" pinned: "Épingler sur le profil"
you: "Vous" you: "Vous"
@@ -129,6 +131,7 @@ unblockConfirm: "Êtes-vous sûr·e de vouloir débloquer ce compte ?"
suspendConfirm: "Êtes-vous sûr·e de vouloir suspendre ce compte ?" suspendConfirm: "Êtes-vous sûr·e de vouloir suspendre ce compte ?"
unsuspendConfirm: "Êtes-vous sûr·e de vouloir annuler la suspension de ce compte ?" unsuspendConfirm: "Êtes-vous sûr·e de vouloir annuler la suspension de ce compte ?"
selectList: "Sélectionner une liste" selectList: "Sélectionner une liste"
selectChannel: "Sélectionner un canal"
selectAntenna: "Sélectionner une antenne" selectAntenna: "Sélectionner une antenne"
selectWidget: "Sélectionner un widget" selectWidget: "Sélectionner un widget"
editWidgets: "Modifier les widgets" editWidgets: "Modifier les widgets"
@@ -388,13 +391,10 @@ about: "Informations"
aboutMisskey: "À propos de Misskey" aboutMisskey: "À propos de Misskey"
administrator: "Administrateur" administrator: "Administrateur"
token: "Jeton" token: "Jeton"
twoStepAuthentication: "Authentification à deux facteurs"
moderator: "Modérateur·rice·s" moderator: "Modérateur·rice·s"
moderation: "Modérations" moderation: "Modérations"
nUsersMentioned: "{n} utilisateur·rice·s mentionné·e·s" nUsersMentioned: "{n} utilisateur·rice·s mentionné·e·s"
securityKey: "Clé de sécurité" securityKey: "Clé de sécurité"
securityKeyName: "Nom de la clé"
registerSecurityKey: "Enregistrer une clé de sécurité"
lastUsed: "Dernier utilisé" lastUsed: "Dernier utilisé"
unregister: "Se désinscrire" unregister: "Se désinscrire"
passwordLessLogin: "Se connecter sans mot de passe" passwordLessLogin: "Se connecter sans mot de passe"
@@ -412,24 +412,15 @@ markAsReadAllTalkMessages: "Marquer toutes les discussions comme lues"
help: "Aide" help: "Aide"
inputMessageHere: "Écrivez votre message ici" inputMessageHere: "Écrivez votre message ici"
close: "Fermer" close: "Fermer"
group: "Groupe"
groups: "Groupes"
createGroup: "Créer un groupe"
ownedGroups: "Mes groupes"
joinedGroups: "Groupes rejoints"
invites: "Invitations" invites: "Invitations"
groupName: "Nom du groupe"
members: "Membres" members: "Membres"
transfer: "Transférer" transfer: "Transférer"
messagingWithUser: "Discuter avec un·e autre utilisateur·rice"
messagingWithGroup: "Discuter avec un groupe"
title: "Titre" title: "Titre"
text: "Texte" text: "Texte"
enable: "Activer" enable: "Activer"
next: "Suivant" next: "Suivant"
retype: "Confirmation" retype: "Confirmation"
noteOf: "Notes de {user}" noteOf: "Notes de {user}"
inviteToGroup: "Inviter dans un groupe"
quoteAttached: "Avec citation" quoteAttached: "Avec citation"
quoteQuestion: "Souhaitez-vous ajouter une citation ?" quoteQuestion: "Souhaitez-vous ajouter une citation ?"
noMessagesYet: "Pas encore de discussion" noMessagesYet: "Pas encore de discussion"
@@ -451,17 +442,13 @@ passwordMatched: "Les mots de passe correspondent"
passwordNotMatched: "Les mots de passe ne correspondent pas" passwordNotMatched: "Les mots de passe ne correspondent pas"
signinWith: "Se connecter avec {x}" signinWith: "Se connecter avec {x}"
signinFailed: "Échec dauthentification. Veuillez vérifier que votre nom dutilisateur et mot de passe sont corrects." signinFailed: "Échec dauthentification. Veuillez vérifier que votre nom dutilisateur et mot de passe sont corrects."
tapSecurityKey: "Appuyez sur votre clé de sécurité"
or: "OU" or: "OU"
language: "Langue" language: "Langue"
uiLanguage: "Langue daffichage de linterface" uiLanguage: "Langue daffichage de linterface"
groupInvited: "Invité au groupe"
aboutX: "À propos de {x}" aboutX: "À propos de {x}"
emojiStyle: "Style des émojis" emojiStyle: "Style des émojis"
native: "Natif" native: "Natif"
disableDrawer: "Les menus ne s'affichent pas dans le tiroir" disableDrawer: "Les menus ne s'affichent pas dans le tiroir"
youHaveNoGroups: "Vous navez aucun groupe"
joinOrCreateGroup: "Vous pouvez être invité·e à rejoindre des groupes existants ou créer votre propre nouveau groupe."
noHistory: "Pas d'historique" noHistory: "Pas d'historique"
signinHistory: "Historique de connexion" signinHistory: "Historique de connexion"
doing: "En cours..." doing: "En cours..."
@@ -831,8 +818,6 @@ deleteAccountConfirm: "Votre compte sera supprimé. Êtes vous certain ?"
incorrectPassword: "Le mot de passe est incorrect." incorrectPassword: "Le mot de passe est incorrect."
voteConfirm: "Confirmez-vous votre vote pour « {choice} » ?" voteConfirm: "Confirmez-vous votre vote pour « {choice} » ?"
hide: "Masquer" hide: "Masquer"
leaveGroup: "Quitter le groupe"
leaveGroupConfirm: "Êtes vous sûr de vouloir quitter \"{name}\" ?"
useDrawerReactionPickerForMobile: "Afficher le sélecteur de réactions en tant que panneau sur mobile" useDrawerReactionPickerForMobile: "Afficher le sélecteur de réactions en tant que panneau sur mobile"
welcomeBackWithName: "Heureux de vous revoir, {name}" welcomeBackWithName: "Heureux de vous revoir, {name}"
clickToFinishEmailVerification: "Veuillez cliquer sur [{ok}] afin de compléter la vérification par courriel." clickToFinishEmailVerification: "Veuillez cliquer sur [{ok}] afin de compléter la vérification par courriel."
@@ -848,6 +833,7 @@ instanceDefaultLightTheme: "Thème clair par défaut sur toute linstance"
instanceDefaultDarkTheme: "Thème sombre par défaut sur toute linstance" instanceDefaultDarkTheme: "Thème sombre par défaut sur toute linstance"
instanceDefaultThemeDescription: "Saisissez le code du thème en format objet." instanceDefaultThemeDescription: "Saisissez le code du thème en format objet."
mutePeriod: "Durée de mise en sourdine" mutePeriod: "Durée de mise en sourdine"
period: "Fin du sondage"
indefinitely: "Illimité" indefinitely: "Illimité"
tenMinutes: "10 minutes" tenMinutes: "10 minutes"
oneHour: "1 heure" oneHour: "1 heure"
@@ -916,6 +902,17 @@ show: "Affichage"
neverShow: "Ne plus afficher" neverShow: "Ne plus afficher"
remindMeLater: "Peut-être plus tard" remindMeLater: "Peut-être plus tard"
color: "Couleur" color: "Couleur"
_achievements:
_types:
_notes100000:
title: "ALL YOUR NOTE ARE BELONG TO US"
_login1000:
flavor: "Merci d'utiliser Misskey !"
_markedAsCat:
title: "Je suis un chat"
flavor: "Je n'ai pas encore de nom"
_following50:
title: "Beaucoup d'amis"
_role: _role:
priority: "Priorité" priority: "Priorité"
_priority: _priority:
@@ -1139,6 +1136,7 @@ _ago:
weeksAgo: "Il y a {n} semaines" weeksAgo: "Il y a {n} semaines"
monthsAgo: "Il y a {n} mois" monthsAgo: "Il y a {n} mois"
yearsAgo: "Il y a {n} ans" yearsAgo: "Il y a {n} ans"
invalid: "Il n'y a rien à voir ici"
_time: _time:
second: "s" second: "s"
minute: "min" minute: "min"
@@ -1171,14 +1169,14 @@ _tutorial:
step8_2: "En les activant, vous recevrez des notifications pour les mentions, les réactions, les suivis, etc., même lorsque Misskey n'est pas ouvert." step8_2: "En les activant, vous recevrez des notifications pour les mentions, les réactions, les suivis, etc., même lorsque Misskey n'est pas ouvert."
_2fa: _2fa:
alreadyRegistered: "Configuration déjà achevée." alreadyRegistered: "Configuration déjà achevée."
registerDevice: "Ajouter un nouvel appareil"
registerKey: "Enregistrer une clef"
step1: "Tout d'abord, installez une application d'authentification, telle que {a} ou {b}, sur votre appareil." step1: "Tout d'abord, installez une application d'authentification, telle que {a} ou {b}, sur votre appareil."
step2: "Ensuite, scannez le code QR affiché sur lécran." step2: "Ensuite, scannez le code QR affiché sur lécran."
step2Url: "Vous pouvez également saisir cette URL si vous utilisez un programme de bureau :" step2Url: "Vous pouvez également saisir cette URL si vous utilisez un programme de bureau :"
step3: "Entrez le jeton affiché sur votre application pour compléter la configuration." step3: "Entrez le jeton affiché sur votre application pour compléter la configuration."
step4: "À partir de maintenant, ce même jeton vous sera demandé à chacune de vos connexions." step4: "À partir de maintenant, ce même jeton vous sera demandé à chacune de vos connexions."
securityKeyInfo: "Vous pouvez configurer l'authentification WebAuthN pour sécuriser davantage le processus de connexion grâce à une clé de sécurité matérielle qui prend en charge FIDO2, ou bien en configurant l'authentification par empreinte digitale ou par code PIN sur votre appareil." securityKeyInfo: "Vous pouvez configurer l'authentification WebAuthN pour sécuriser davantage le processus de connexion grâce à une clé de sécurité matérielle qui prend en charge FIDO2, ou bien en configurant l'authentification par empreinte digitale ou par code PIN sur votre appareil."
removeKeyConfirm: "Voulez-vous supprimer {name} ?"
renewTOTPCancel: "Pas maintenant"
_permissions: _permissions:
"read:account": "Afficher les informations du compte" "read:account": "Afficher les informations du compte"
"write:account": "Mettre à jour les informations de votre compte" "write:account": "Mettre à jour les informations de votre compte"
@@ -1224,7 +1222,6 @@ _antennaSources:
homeTimeline: "Notes venant des utilisateur·rice·s auxquel·les je suis abonné" homeTimeline: "Notes venant des utilisateur·rice·s auxquel·les je suis abonné"
users: "Notes venant de la part dutilisateur·rice·s précis" users: "Notes venant de la part dutilisateur·rice·s précis"
userList: "Notes venant dune liste spécifique" userList: "Notes venant dune liste spécifique"
userGroup: "Notes venant dutilisateur·rice·s du groupe spécifié"
_weekday: _weekday:
sunday: "Dimanche" sunday: "Dimanche"
monday: "Lundi" monday: "Lundi"
@@ -1296,8 +1293,6 @@ _visibility:
followersDescription: "Publier à vos abonné·e·s uniquement" followersDescription: "Publier à vos abonné·e·s uniquement"
specified: "Direct" specified: "Direct"
specifiedDescription: "Publier uniquement aux utilisateur·rice·s mentionné·e·s" specifiedDescription: "Publier uniquement aux utilisateur·rice·s mentionné·e·s"
localOnly: "Local seulement"
localOnlyDescription: "Caché pour les utilisateurs distant"
_postForm: _postForm:
replyPlaceholder: "Répondre à cette note ..." replyPlaceholder: "Répondre à cette note ..."
quotePlaceholder: "Citez cette note ..." quotePlaceholder: "Citez cette note ..."
@@ -1425,12 +1420,9 @@ _notification:
youGotReply: "Réponse de {name}" youGotReply: "Réponse de {name}"
youGotQuote: "Cité·e par {name}" youGotQuote: "Cité·e par {name}"
youRenoted: "{name} vous a Renoté" youRenoted: "{name} vous a Renoté"
youGotMessagingMessageFromUser: "{name} vous envoyé un message"
youGotMessagingMessageFromGroup: "Un message a été envoyé au groupe {name}"
youWereFollowed: "Vous suit" youWereFollowed: "Vous suit"
youReceivedFollowRequest: "Vous avez reçu une demande dabonnement" youReceivedFollowRequest: "Vous avez reçu une demande dabonnement"
yourFollowRequestAccepted: "Votre demande dabonnement a été accepté" yourFollowRequestAccepted: "Votre demande dabonnement a été accepté"
youWereInvitedToGroup: "Invité·e au groupe"
pollEnded: "Les résultats du sondage sont disponibles" pollEnded: "Les résultats du sondage sont disponibles"
unreadAntennaNote: "Antenne {name}" unreadAntennaNote: "Antenne {name}"
emptyPushNotificationMessage: "Les notifications push ont été mises à jour" emptyPushNotificationMessage: "Les notifications push ont été mises à jour"
@@ -1445,7 +1437,6 @@ _notification:
pollEnded: "Sondages se cloturant" pollEnded: "Sondages se cloturant"
receiveFollowRequest: "Demande d'abonnement reçue" receiveFollowRequest: "Demande d'abonnement reçue"
followRequestAccepted: "Demande d'abonnement acceptée" followRequestAccepted: "Demande d'abonnement acceptée"
groupInvited: "Invitation à un groupe"
app: "Notifications provenant des apps" app: "Notifications provenant des apps"
_actions: _actions:
followBack: "Suivre" followBack: "Suivre"

View File

@@ -84,7 +84,7 @@ error: "Galat"
somethingHappened: "Terjadi kesalahan" somethingHappened: "Terjadi kesalahan"
retry: "Coba lagi" retry: "Coba lagi"
pageLoadError: "Gagal memuat halaman." pageLoadError: "Gagal memuat halaman."
pageLoadErrorDescription: "Umumnya disebabkan jaringan atau tembolok perambah. Cobalah bersihkan tembolok peramban lalu tunggu sesaat sebelum mencoba kembali." pageLoadErrorDescription: "Umumnya disebabkan jaringan atau tembolok peramban. Cobalah bersihkan tembolok peramban lalu tunggu sesaat sebelum mencoba kembali."
serverIsDead: "Tidak ada respon dari peladen. Mohon tunggu dan coba beberapa saat lagi." serverIsDead: "Tidak ada respon dari peladen. Mohon tunggu dan coba beberapa saat lagi."
youShouldUpgradeClient: "Untuk melihat halaman ini, mohon muat ulang untuk memutakhirkan klienmu." youShouldUpgradeClient: "Untuk melihat halaman ini, mohon muat ulang untuk memutakhirkan klienmu."
enterListName: "Masukkan nama daftar" enterListName: "Masukkan nama daftar"
@@ -103,6 +103,8 @@ renoted: "Telah direnote"
cantRenote: "Postingan ini tidak dapat direnote" cantRenote: "Postingan ini tidak dapat direnote"
cantReRenote: "Renote tidak dapat direnote" cantReRenote: "Renote tidak dapat direnote"
quote: "Kutip" quote: "Kutip"
inChannelRenote: "Hanya renote dalam kanal"
inChannelQuote: "Hanya kutip dalam kanal"
pinnedNote: "Catatan yang disematkan" pinnedNote: "Catatan yang disematkan"
pinned: "Sematkan ke profil" pinned: "Sematkan ke profil"
you: "Kamu" you: "Kamu"
@@ -129,6 +131,7 @@ unblockConfirm: "Apakah kamu yakin ingin membuka blokir akun ini?"
suspendConfirm: "Apakah kamu yakin ingin membekukan akun ini?" suspendConfirm: "Apakah kamu yakin ingin membekukan akun ini?"
unsuspendConfirm: "Apakah kamu yakin ingin membuka pembekuan akun ini?" unsuspendConfirm: "Apakah kamu yakin ingin membuka pembekuan akun ini?"
selectList: "Pilih daftar" selectList: "Pilih daftar"
selectChannel: "Pilih kanal"
selectAntenna: "Pilih Antena" selectAntenna: "Pilih Antena"
selectWidget: "Pilih gawit" selectWidget: "Pilih gawit"
editWidgets: "Sunting gawit" editWidgets: "Sunting gawit"
@@ -256,6 +259,8 @@ noMoreHistory: "Tidak ada sejarah lagi"
startMessaging: "Mulai mengirim pesan" startMessaging: "Mulai mengirim pesan"
nUsersRead: "Dibaca oleh {n}" nUsersRead: "Dibaca oleh {n}"
agreeTo: "Saya setuju kepada {0}" agreeTo: "Saya setuju kepada {0}"
agreeBelow: "Saya setuju dengan di bawah ini"
basicNotesBeforeCreateAccount: "Catatan penting"
tos: "Syarat dan ketentuan" tos: "Syarat dan ketentuan"
start: "Mulai" start: "Mulai"
home: "Beranda" home: "Beranda"
@@ -388,13 +393,10 @@ about: "Informasi"
aboutMisskey: "Tentang Misskey" aboutMisskey: "Tentang Misskey"
administrator: "Admin" administrator: "Admin"
token: "Token" token: "Token"
twoStepAuthentication: "Otentikasi dua faktor"
moderator: "Moderator" moderator: "Moderator"
moderation: "Moderasi" moderation: "Moderasi"
nUsersMentioned: "{n} pengguna disebut" nUsersMentioned: "{n} pengguna disebut"
securityKey: "Kunci keamanan" securityKey: "Kunci keamanan"
securityKeyName: "Nama kunci"
registerSecurityKey: "Daftarkan kunci keamanan"
lastUsed: "Terakhir digunakan" lastUsed: "Terakhir digunakan"
unregister: "Batalkan pendaftaran" unregister: "Batalkan pendaftaran"
passwordLessLogin: "Setel login tanpa kata sandi" passwordLessLogin: "Setel login tanpa kata sandi"
@@ -412,24 +414,15 @@ markAsReadAllTalkMessages: "Tandai semua pesan telah dibaca"
help: "Bantuan" help: "Bantuan"
inputMessageHere: "Ketik pesan disini" inputMessageHere: "Ketik pesan disini"
close: "Tutup" close: "Tutup"
group: "Grup"
groups: "Grup"
createGroup: "Buat grup"
ownedGroups: "Grup yang dimiliki"
joinedGroups: "Grup yang diikuti"
invites: "Undang" invites: "Undang"
groupName: "Nama grup"
members: "Anggota" members: "Anggota"
transfer: "Transfer" transfer: "Transfer"
messagingWithUser: "Obrolan dengan pengguna lain"
messagingWithGroup: "Obrolan di dalam grup"
title: "Judul" title: "Judul"
text: "Teks" text: "Teks"
enable: "Aktifkan" enable: "Aktifkan"
next: "Selanjutnya" next: "Selanjutnya"
retype: "Masukkan ulang" retype: "Masukkan ulang"
noteOf: "Catatan milik {user}" noteOf: "Catatan milik {user}"
inviteToGroup: "Undang ke grup"
quoteAttached: "Dikutip" quoteAttached: "Dikutip"
quoteQuestion: "Apakah kamu ingin menambahkan kutipan?" quoteQuestion: "Apakah kamu ingin menambahkan kutipan?"
noMessagesYet: "Tidak ada pesan" noMessagesYet: "Tidak ada pesan"
@@ -451,19 +444,17 @@ passwordMatched: "Kata sandi sama"
passwordNotMatched: "Kata sandi tidak sama" passwordNotMatched: "Kata sandi tidak sama"
signinWith: "Masuk dengan {x}" signinWith: "Masuk dengan {x}"
signinFailed: "Tidak dapat masuk. Nama pengguna atau kata sandi yang kamu masukkan salah." signinFailed: "Tidak dapat masuk. Nama pengguna atau kata sandi yang kamu masukkan salah."
tapSecurityKey: "Ketuk kunci keamanan kamu"
or: "atau" or: "atau"
language: "Bahasa" language: "Bahasa"
uiLanguage: "Bahasa antarmuka pengguna" uiLanguage: "Bahasa antarmuka pengguna"
groupInvited: "Telah diundang ke grup"
aboutX: "Tentang {x}" aboutX: "Tentang {x}"
emojiStyle: "Gaya emoji" emojiStyle: "Gaya emoji"
native: "Native" native: "Native"
disableDrawer: "Jangan gunakan menu bergaya laci" disableDrawer: "Jangan gunakan menu bergaya laci"
youHaveNoGroups: "Kamu tidak memiliki grup"
joinOrCreateGroup: "Bergabunglah dengan grup atau kamu dapat membuat grupmu sendiri."
noHistory: "Tidak ada riwayat" noHistory: "Tidak ada riwayat"
signinHistory: "Riwayat masuk" signinHistory: "Riwayat masuk"
enableAdvancedMfm: "Nyalakan MFM tingkat lanjut"
enableAnimatedMfm: "Nyalakan animasi MFM"
doing: "Sedang berkerja..." doing: "Sedang berkerja..."
category: "Kategori" category: "Kategori"
tags: "Tandai" tags: "Tandai"
@@ -833,8 +824,6 @@ deleteAccountConfirm: "Akun akan dihapus. Apakah kamu yakin?"
incorrectPassword: "Kata sandi salah." incorrectPassword: "Kata sandi salah."
voteConfirm: "Konfirmasi suara kamu untuk ({choice})" voteConfirm: "Konfirmasi suara kamu untuk ({choice})"
hide: "Sembunyikan" hide: "Sembunyikan"
leaveGroup: "Keluar grup"
leaveGroupConfirm: "Apakah kamu yakin untuk keluar dari \"{name}\"?"
useDrawerReactionPickerForMobile: "Tampilkan bilah reaksi sebagai laci di ponsel" useDrawerReactionPickerForMobile: "Tampilkan bilah reaksi sebagai laci di ponsel"
welcomeBackWithName: "Selamat datang kembali, {name}." welcomeBackWithName: "Selamat datang kembali, {name}."
clickToFinishEmailVerification: "Mohon klik [{ok}] untuk menyelesaikan verifikasi email." clickToFinishEmailVerification: "Mohon klik [{ok}] untuk menyelesaikan verifikasi email."
@@ -850,6 +839,7 @@ instanceDefaultLightTheme: "Bawaan instan tema terang"
instanceDefaultDarkTheme: "Bawaan instan tema gelap" instanceDefaultDarkTheme: "Bawaan instan tema gelap"
instanceDefaultThemeDescription: "Masukkan kode tema di format obyek." instanceDefaultThemeDescription: "Masukkan kode tema di format obyek."
mutePeriod: "Batas waktu bisu" mutePeriod: "Batas waktu bisu"
period: "Batas akhir"
indefinitely: "Selamanya" indefinitely: "Selamanya"
tenMinutes: "10 Menit" tenMinutes: "10 Menit"
oneHour: "1 Jam" oneHour: "1 Jam"
@@ -860,6 +850,8 @@ failedToFetchAccountInformation: "Gagal untuk mendapatkan informasi akun"
rateLimitExceeded: "Batas sudah terlampaui" rateLimitExceeded: "Batas sudah terlampaui"
cropImage: "potong gambar" cropImage: "potong gambar"
cropImageAsk: "Ingin memotong gambar?" cropImageAsk: "Ingin memotong gambar?"
cropYes: "Potong"
cropNo: "Gunakan apa adanya"
file: "Berkas" file: "Berkas"
recentNHours: "{n} jam terakhir" recentNHours: "{n} jam terakhir"
recentNDays: "{n} hari terakhir" recentNDays: "{n} hari terakhir"
@@ -926,10 +918,87 @@ didYouLikeMisskey: "Apakah kamu mulai menyukai Misskey?"
pleaseDonate: "{host} menggunakan perangkat lunak bebas yaitu Misskey. Kami sangat mengapresiasi sekali donasi dari kamu agar pengembangan Misskey tetap dapat berlanjut!" pleaseDonate: "{host} menggunakan perangkat lunak bebas yaitu Misskey. Kami sangat mengapresiasi sekali donasi dari kamu agar pengembangan Misskey tetap dapat berlanjut!"
roles: "Peran" roles: "Peran"
role: "Peran" role: "Peran"
normalUser: "Pengguna umum"
undefined: "Tak terdefinisi"
assign: "Tetapkan\n"
unassign: "Batalkan penetapan"
color: "Warna" color: "Warna"
manageCustomEmojis: "Kelola Emoji Kustom"
youCannotCreateAnymore: "Kamu melewati batas pembuatan."
cannotPerformTemporary: "Sementara Tidak Tersedia"
cannotPerformTemporaryDescription: "Aksi ini tidak dapat dilakukan sementara karena melewati batas eksekusi. Mohon tunggu sejenak dan coba lagi."
preset: "Prasetel"
selectFromPresets: "Pilih dari prasetel"
achievements: "Pencapaian"
gotInvalidResponseError: "Respon peladen tidak valid"
gotInvalidResponseErrorDescription: "Peladen tidak dapat dijangkau atau sedang dalam perawatan. Mohon coba lagi nanti."
thisPostMayBeAnnoying: "Catatan ini mungkin dapat mengganggu orang lain."
thisPostMayBeAnnoyingHome: "Catat ke linimasa beranda"
thisPostMayBeAnnoyingCancel: "Batalkan"
thisPostMayBeAnnoyingIgnore: "Tetap catat"
collapseRenotes: "Tutup renote yang sudah kamu lihat"
internalServerError: "Kesalahan internal peladen"
internalServerErrorDescription: "Peladen sedang mengalami galat tak terduga"
copyErrorInfo: "Salin detil galat"
_achievements: _achievements:
earnedAt: "Terbuka pada"
_types: _types:
_notes1:
title: "Cus, baru gabung Misskey nih!"
description: "Catat catatan pertama kamu"
flavor: "Selamat bersenang-senang dengan Misskey!"
_notes10:
title: "Beberapa catatan"
description: "Catat 10 catatan"
_notes100:
title: "Banyak catatan"
description: "Catat 100 catatan"
_notes500:
title: "Tertumpuk catatan"
description: "Catat 500 catatan"
_notes1000:
title: "Gunung catatan"
description: "Catat 1000 catatan"
_notes5000:
title: "Luapan catatan"
description: "Catat 5000 catatan"
_notes10000:
title: "Catatan super"
description: "Catat 10 ribu catatan"
_notes20000:
title: "Butuh... banyak... catatan..."
description: "Catat 20 ribu catatan"
_notes30000:
title: "Catat, catat, catat !"
description: "Catat 30 ribu catatan"
_notes40000:
title: "Pabrik catatan"
description: "Catat 40 ribu catatan"
_notes50000:
title: "Planet catatan"
description: "Catat 50 ribu catatan"
_notes60000:
title: "Kuasar catatan"
description: "Catat 60 ribu catatan"
_notes70000:
title: "Lubang hitam catatan"
description: "Catat 70 ribu catatan"
_notes80000:
title: "Galaksi catatan"
description: "Catat 80 ribu catatan"
_notes90000:
title: "Semesta catatan"
description: "Catat 90 ribu catatan"
_notes100000:
title: "ALL YOUR NOTE ARE BELONG TO US"
description: "Catat 100 ribu catatan"
flavor: "Banyak bacot ya kamu."
_login3:
title: "Pemula I"
description: "Login selama 3 hari"
flavor: "Mulai hari ini, panggil gue Misskist"
_login7: _login7:
title: "Pemula II"
description: "Login selama 7 hari" description: "Login selama 7 hari"
flavor: "Sudah mulai terbiasa?" flavor: "Sudah mulai terbiasa?"
_login15: _login15:
@@ -1002,7 +1071,80 @@ _achievements:
_following100: _following100:
title: "100 Teman" title: "100 Teman"
description: "Ikuti 100 pengguna lain" description: "Ikuti 100 pengguna lain"
_following300:
title: "Kelebihan teman"
description: "Mengikuti 300 pengguna lain"
_followers1:
title: "Pengikut pertama"
description: "Dapatkan 1 pengikut"
_followers10:
title: "Ikuti aku!"
description: "Dapatkan 10 pengikut"
_followers50:
title: "Rame-rame"
description: "Dapatkan 50 pengikut"
_followers100:
title: "Terkenal"
description: "Dapatkan 100 pengikut"
_followers300:
title: "Mohon antri satu baris"
description: "Dapatkan 300 pengikut"
_followers500:
title: "Stasiun Informasi"
description: "Dapatkan 500 pengikut"
_followers1000:
title: "Influencer"
description: "Dapatkan 1000 pengikut"
_collectAchievements30:
title: "Kolektor pencapaian"
description: "Dapatkan 30 pencapaian"
_viewAchievements3min:
title: "Suka Pencapaian"
description: "Lugat daftar pencapaianmu setidaknya 3 menit"
_iLoveMisskey:
title: "I Love Misskey"
description: "Catat \"I ❤ #Misskey\""
flavor: "Tim pengembang misskey sangat mengapresiasi dukungan kamu!"
_foundTreasure:
title: "Berburu Harta Karun"
description: "Kamu telah menemukan harta karun tersembunyi"
_client30min:
title: "Istirahat pendek"
description: "Habiskan waktu 30 menit di Misskey"
_noteDeletedWithin1min:
title: "Eh, salah coy!"
description: "Hapus catatan kurang dari semenit kamu catat"
_postedAtLateNight:
title: "Nokturnal"
description: "Catat catatan di tengah malam hari"
flavor: "Udah waktunya boboq."
_postedAt0min0sec:
title: "Jam ngomong"
description: "Catat catatan di jam 00.00"
flavor: "Tik Tok Tik Toeeeng"
_selfQuote:
title: "Rujukan mandiri"
description: "Kutip catatanmu sendiri"
_htl20npm:
title: "Linimasa mengalir"
description: "Memiliki linimasa beranda dengan kecepatan melebihi 20 cpm (catatan per menit)"
_viewInstanceChart:
title: "Analis"
description: "Lihat bagan instansimu"
_outputHelloWorldOnScratchpad:
title: "Halo, dunia!"
description: "Munculkan \"hello world\" di Scratchpad"
_open3windows:
title: "Jendela ganda"
description: "Memiliki setidaknya 3 jendela yang terbuka secara bersamaan"
_driveFolderCircularReference:
title: "Referensi Siklus"
description: "Mencoba membuat folder bersarang rekursif di Drive"
_reactWithoutRead:
title: "Beneran udah dibaca?"
description: "Mereaksi catatan dengan 100 karakter panjangnya dalam 3 detik setelah dicatat"
_clickedClickHere: _clickedClickHere:
title: "Klik di sini"
description: "Kamu telah mengeklik disini" description: "Kamu telah mengeklik disini"
_justPlainLucky: _justPlainLucky:
title: "Lagi Beruntung" title: "Lagi Beruntung"
@@ -1025,6 +1167,7 @@ _achievements:
_loggedInOnNewYearsDay: _loggedInOnNewYearsDay:
title: "Selamat Tahun Baru!" title: "Selamat Tahun Baru!"
description: "Login di hari pertama tahun baru" description: "Login di hari pertama tahun baru"
flavor: "Untuk tahun baru yang berkah bagi instansi ini"
_cookieClicked: _cookieClicked:
title: "Permainan dimana kamu mengeklik kue" title: "Permainan dimana kamu mengeklik kue"
description: "Mengeklik kue" description: "Mengeklik kue"
@@ -1053,6 +1196,9 @@ _role:
baseRole: "Templat peran" baseRole: "Templat peran"
useBaseValue: "Gunakan nilai templat peran" useBaseValue: "Gunakan nilai templat peran"
chooseRoleToAssign: "Pilih peran yang ditugaskan" chooseRoleToAssign: "Pilih peran yang ditugaskan"
iconUrl: "URL ikon"
asBadge: "Tampilkan sebagai lencana"
descriptionOfAsBadge: "Ikon peran ini akan ditampilkan bersebelahan dengan username pengguna yang memiliki peran ini jika dinyalakan."
canEditMembersByModerator: "Perbolehkan moderator untuk menyunting daftar anggota untuk peran ini" canEditMembersByModerator: "Perbolehkan moderator untuk menyunting daftar anggota untuk peran ini"
descriptionOfCanEditMembersByModerator: "Ketika dinyalakan, moderator beserta administrator dapat menugaskan ataupun mencabut pengguna ke peran ini. Ketika dimatikan, hanya administrator saja yang dapat menugaskan pengguna ke peran ini." descriptionOfCanEditMembersByModerator: "Ketika dinyalakan, moderator beserta administrator dapat menugaskan ataupun mencabut pengguna ke peran ini. Ketika dimatikan, hanya administrator saja yang dapat menugaskan pengguna ke peran ini."
priority: "Prioritas" priority: "Prioritas"
@@ -1068,6 +1214,36 @@ _role:
canManageCustomEmojis: "Dapat mengelola Emoji kustom" canManageCustomEmojis: "Dapat mengelola Emoji kustom"
driveCapacity: "Kapasitas Drive" driveCapacity: "Kapasitas Drive"
pinMax: "Jumlah maksimal catatan yang disematkan" pinMax: "Jumlah maksimal catatan yang disematkan"
antennaMax: "Jumlah maksimum antena"
wordMuteMax: "Jumlah maksimum karakter yang diperbolehkan dalam membisukan kata"
webhookMax: "Jumlah maksimum Webhook"
clipMax: "Jumlah maksimum Klip"
noteEachClipsMax: "Jumlah maksimum catatan di dalam Klip"
userListMax: "Jumlah maksimum daftar pengguna"
userEachUserListsMax: "Jumlah maksimum pengguna dalam dsftar pengguna"
rateLimitFactor: "Batas kecepatan"
descriptionOfRateLimitFactor: "Batas kecepatan yang rendah tidak begitu membatasi, batas kecepatan tinggi lebih membatasi. "
canHideAds: "Dapat menyembunyikan iklan"
_condition:
isLocal: "Pengguna lokal"
isRemote: "Pengguna remote"
createdLessThan: "Telah berlalu kurang dari X sejak pembuatan akun"
createdMoreThan: "Telah berlalu lebih dari X sejak pembuatan akun"
followersLessThanOrEq: "Memiliki pengikut X atau kurang dari tersebut"
followersMoreThanOrEq: "Memiliki pengikut X atau lebih dari tersebut"
followingLessThanOrEq: "Mengikuti X pengguna atau kurang dari itu"
followingMoreThanOrEq: "Mengikuti X pengguna atau lebih dari itu"
and: "Kondisi-AND"
or: "Kondisi-OR"
not: "Kondisi-NOT"
_sensitiveMediaDetection:
description: "Mengurangi usaha moderasi server dengan mengenali media NSFW srcara otomatis menggunakan Machine Learning. Fungsi ini akan sedikit menaikkan beban peladen."
sensitivity: "Sensitivitas deteksi"
sensitivityDescription: "Mengurangi sensitivitas akan mengurangi misdeteksi (false positive) sedangkan meningkatkannya akan menambah misdeteksi (false positive)."
setSensitiveFlagAutomatically: "Tandai sebagai NSFW"
setSensitiveFlagAutomaticallyDescription: "Hasil dari deteksi internal akan dipertahankan meskipun fungsi ini dimatikan."
analyzeVideos: "Nyalakan analisis terhadap video"
analyzeVideosDescription: "Analisa video sebagai tambahan dari gambar. Ini akan sedikit meningkatkan beban ke peladen."
_emailUnavailable: _emailUnavailable:
used: "Alamat surel ini telah digunakan" used: "Alamat surel ini telah digunakan"
format: "Format tidak valid." format: "Format tidak valid."
@@ -1111,6 +1287,24 @@ _plugin:
install: "Memasang plugin" install: "Memasang plugin"
installWarn: "Mohon jangan memasang plugin yang tidak dapat dipercayai." installWarn: "Mohon jangan memasang plugin yang tidak dapat dipercayai."
manage: "Manajemen plugin" manage: "Manajemen plugin"
_preferencesBackups:
list: "Cadangan yang dibuat"
saveNew: "Simpan cadangan baru"
loadFile: "Muat dari berkas"
apply: "Terapkan pada perangkat ini"
save: "Simpan perubahan"
inputName: "Mohon masukkan nama untuk cadangan ini"
cannotSave: "Gagal menyimpan"
nameAlreadyExists: "Cadangan bernama \"{name}\" sudah ada. Mohon gunakan nama lain."
applyConfirm: "Apakah kamu yakin untuk menerapkan cadangan \"{name}\" ke perangkat ini? Pengaturan yang sudah ada di perangkat ini nantinya akan ditimpa."
saveConfirm: "Simpan cadangan sebagai {name}?"
deleteConfirm: "Hapus cadangan {name}?"
renameConfirm: "Ganti cadangan ini dari \"{old}\" ke \"{new}\"?"
noBackups: "Tidak ada cadangan. Kamu dapat mencadangkan pengaturanmu di peladen ini dengan menggunakan \"Buat cadangan baru\"."
createdAt: "Dibuat pada: {date} {time}"
updatedAt: "Diperbarui pada: {date} {time}"
cannotLoad: "Gagal memuat"
invalidFile: "Format berkas tidak valid"
_registry: _registry:
scope: "Lingkup" scope: "Lingkup"
key: "Kunci" key: "Kunci"
@@ -1259,6 +1453,7 @@ _ago:
weeksAgo: "{n} minggu lalu" weeksAgo: "{n} minggu lalu"
monthsAgo: "{n} bulan lalu" monthsAgo: "{n} bulan lalu"
yearsAgo: "{n} tahun lalu" yearsAgo: "{n} tahun lalu"
invalid: "Tidak ada sama sekali disini"
_time: _time:
second: "detik" second: "detik"
minute: "menit" minute: "menit"
@@ -1287,17 +1482,19 @@ _tutorial:
step7_1: "Yay, Selamat! Kamu sudah menyelesaikan tutorial dasar Misskey." step7_1: "Yay, Selamat! Kamu sudah menyelesaikan tutorial dasar Misskey."
step7_2: "Jika kamu ingin mempelajari lebih lanjut tentang Misskey, cobalah berkunjung ke bagian {help}." step7_2: "Jika kamu ingin mempelajari lebih lanjut tentang Misskey, cobalah berkunjung ke bagian {help}."
step7_3: "Semoga berhasil dan bersenang-senanglah! 🚀" step7_3: "Semoga berhasil dan bersenang-senanglah! 🚀"
step8_1: "Yang terakhir, apakah kamu ingin menyalakam pemberitahuan push?"
step8_2: "Menyalakan ini akan memungkinkan kamu menerima pemberitahuan untuk sebutan, reaksi, ikuti, dll. Bahkan ketika Misskey sedang tidak dibuka."
step8_3: "Kamu dapat mengganti pengaturan ini nanti." step8_3: "Kamu dapat mengganti pengaturan ini nanti."
_2fa: _2fa:
alreadyRegistered: "Kamu telah mendaftarkan perangkat otentikasi dua faktor." alreadyRegistered: "Kamu telah mendaftarkan perangkat otentikasi dua faktor."
registerDevice: "Daftarkan perangkat baru"
registerKey: "Daftarkan kunci keamanan baru"
step1: "Pertama, pasang aplikasi otentikasi (seperti {a} atau {b}) di perangkat kamu." step1: "Pertama, pasang aplikasi otentikasi (seperti {a} atau {b}) di perangkat kamu."
step2: "Lalu, pindai kode QR yang ada di layar." step2: "Lalu, pindai kode QR yang ada di layar."
step2Url: "Di aplikasi desktop, masukkan URL berikut:" step2Url: "Di aplikasi desktop, masukkan URL berikut:"
step3: "Masukkan token yang telah disediakan oleh aplikasimu untuk menyelesaikan pemasangan." step3: "Masukkan token yang telah disediakan oleh aplikasimu untuk menyelesaikan pemasangan."
step4: "Mulai sekarang, upaya login apapun akan meminta token login dari aplikasi otentikasi kamu." step4: "Mulai sekarang, upaya login apapun akan meminta token login dari aplikasi otentikasi kamu."
securityKeyInfo: "Kamu dapat memasang otentikasi WebAuthN untuk mengamankan proses login lebih lanjut dengan tidak hanya perangkat keras kunci keamanan yang mendukung FIDO2, namun juga sidik jari atau otentikasi PIN pada perangkatmu." securityKeyInfo: "Kamu dapat memasang otentikasi WebAuthN untuk mengamankan proses login lebih lanjut dengan tidak hanya perangkat keras kunci keamanan yang mendukung FIDO2, namun juga sidik jari atau otentikasi PIN pada perangkatmu."
removeKeyConfirm: "Hapus cadangan {name}?"
renewTOTPCancel: "Tidak sekarang."
_permissions: _permissions:
"read:account": "Lihat informasi akun" "read:account": "Lihat informasi akun"
"write:account": "Sunting informasi akun" "write:account": "Sunting informasi akun"
@@ -1332,18 +1529,20 @@ _permissions:
"read:gallery-likes": "Lihat daftar postingan galeri yang disukai" "read:gallery-likes": "Lihat daftar postingan galeri yang disukai"
"write:gallery-likes": "Sunting daftar postingan galeri yang disukai" "write:gallery-likes": "Sunting daftar postingan galeri yang disukai"
_auth: _auth:
shareAccessTitle: "Mendapatkan ijin akses aplikasi"
shareAccess: "Apakah kamu ingin mengijinkan \"{name}\" untuk mengakses akun ini?" shareAccess: "Apakah kamu ingin mengijinkan \"{name}\" untuk mengakses akun ini?"
shareAccessAsk: "Apakah kamu ingin mengijinkan aplikasi ini untuk mengakses akun kamu?" shareAccessAsk: "Apakah kamu ingin mengijinkan aplikasi ini untuk mengakses akun kamu?"
permission: "{name} meminta ijin berikut"
permissionAsk: "Aplikasi ini membutuhkan beberapa ijin, yaitu:" permissionAsk: "Aplikasi ini membutuhkan beberapa ijin, yaitu:"
pleaseGoBack: "Mohon kembali ke aplikasi kamu" pleaseGoBack: "Mohon kembali ke aplikasi kamu"
callback: "Mengembalikan kamu ke aplikasi" callback: "Mengembalikan kamu ke aplikasi"
denied: "Akses ditolak" denied: "Akses ditolak"
pleaseLogin: "Mohon masuk untuk otorisasi aplikasi."
_antennaSources: _antennaSources:
all: "Semua catatan" all: "Semua catatan"
homeTimeline: "Catatan dari pengguna yang diikuti" homeTimeline: "Catatan dari pengguna yang diikuti"
users: "Catatan dari pengguna tertentu" users: "Catatan dari pengguna tertentu"
userList: "Catatan dari daftar tertentu" userList: "Catatan dari daftar tertentu"
userGroup: "Catatan dari pengguna dalam grup yang ditentukan"
_weekday: _weekday:
sunday: "Minggu" sunday: "Minggu"
monday: "Senin" monday: "Senin"
@@ -1418,8 +1617,6 @@ _visibility:
followersDescription: "Catat ke pengikut saja" followersDescription: "Catat ke pengikut saja"
specified: "Langsung" specified: "Langsung"
specifiedDescription: "Catat ke pengguna yang ditentukan saja" specifiedDescription: "Catat ke pengguna yang ditentukan saja"
localOnly: "Hanya lokal"
localOnlyDescription: "Hanya dapat dilihat di instansi lokal"
_postForm: _postForm:
replyPlaceholder: "Balas ke catatan ini..." replyPlaceholder: "Balas ke catatan ini..."
quotePlaceholder: "Kutip catatan ini..." quotePlaceholder: "Kutip catatan ini..."
@@ -1557,12 +1754,9 @@ _notification:
youGotReply: "{name} membalas kamu" youGotReply: "{name} membalas kamu"
youGotQuote: "{name} mengutip kamu" youGotQuote: "{name} mengutip kamu"
youRenoted: "{name} me-renote kamu" youRenoted: "{name} me-renote kamu"
youGotMessagingMessageFromUser: "{name} mengirimi kamu pesan"
youGotMessagingMessageFromGroup: "Sebuah pesan telah dikirim ke grup {name}"
youWereFollowed: "Mengikuti kamu" youWereFollowed: "Mengikuti kamu"
youReceivedFollowRequest: "Kamu menerima permintaan mengikuti" youReceivedFollowRequest: "Kamu menerima permintaan mengikuti"
yourFollowRequestAccepted: "Permintaan mengikuti kamu telah diterima" yourFollowRequestAccepted: "Permintaan mengikuti kamu telah diterima"
youWereInvitedToGroup: "Telah diundang ke grup"
pollEnded: "Hasil Kuesioner telah keluar" pollEnded: "Hasil Kuesioner telah keluar"
unreadAntennaNote: "Antena {name}" unreadAntennaNote: "Antena {name}"
emptyPushNotificationMessage: "Pembaruan notifikasi dorong" emptyPushNotificationMessage: "Pembaruan notifikasi dorong"
@@ -1578,7 +1772,6 @@ _notification:
pollEnded: "Jajak pendapat berakhir" pollEnded: "Jajak pendapat berakhir"
receiveFollowRequest: "Permintaan mengikuti diterima" receiveFollowRequest: "Permintaan mengikuti diterima"
followRequestAccepted: "Permintaan mengikuti disetujui" followRequestAccepted: "Permintaan mengikuti disetujui"
groupInvited: "Diundang ke grup"
app: "Pemberitahuan dari aplikasi" app: "Pemberitahuan dari aplikasi"
_actions: _actions:
followBack: "Ikuti Kembali" followBack: "Ikuti Kembali"

View File

@@ -11,7 +11,7 @@ password: "Password"
forgotPassword: "Hai dimenticato la password?" forgotPassword: "Hai dimenticato la password?"
fetchingAsApObject: "Recuperando dal Fediverso..." fetchingAsApObject: "Recuperando dal Fediverso..."
ok: "OK" ok: "OK"
gotIt: "Ho capito" gotIt: "ok!"
cancel: "Annulla" cancel: "Annulla"
noThankYou: "No grazie" noThankYou: "No grazie"
enterUsername: "Inserisci un nome utente" enterUsername: "Inserisci un nome utente"
@@ -46,7 +46,7 @@ copyContent: "Copia il contenuto"
copyLink: "Copia il link" copyLink: "Copia il link"
delete: "Elimina" delete: "Elimina"
deleteAndEdit: "Elimina e modifica" deleteAndEdit: "Elimina e modifica"
deleteAndEditConfirm: "Vuoi davvero cancellare questa nota e scriverla di nuovo? Verrano eliminate anche tutte le reazioni, Rinote e risposte collegate." deleteAndEditConfirm: "Vuoi davvero cancellare questa nota e scriverla di nuovo? Verranno eliminate anche tutte le reazioni, rinote e risposte collegate."
addToList: "Aggiungi alla lista" addToList: "Aggiungi alla lista"
sendMessage: "Invia messaggio" sendMessage: "Invia messaggio"
copyRSS: "Copia RSS" copyRSS: "Copia RSS"
@@ -75,7 +75,7 @@ lists: "Liste"
noLists: "Nessuna lista" noLists: "Nessuna lista"
note: "Nota" note: "Nota"
notes: "Note" notes: "Note"
following: "Follows" following: "Follow"
followers: "Followers" followers: "Followers"
followsYou: "Ti segue" followsYou: "Ti segue"
createList: "Aggiungi una nuova lista" createList: "Aggiungi una nuova lista"
@@ -84,17 +84,17 @@ error: "Errore"
somethingHappened: "Si è verificato un problema" somethingHappened: "Si è verificato un problema"
retry: "Riprova" retry: "Riprova"
pageLoadError: "Caricamento pagina non riuscito. " pageLoadError: "Caricamento pagina non riuscito. "
pageLoadErrorDescription: "Questo viene normalmente causato dalla rete o dalla cache del browser. Si prega di pulire la cache, o di attendere e riprovare più tardi." pageLoadErrorDescription: "Questo problema viene normalmente causato da errori di rete o dalla cache del browser. Si prega di pulire la cache, o di attendere e riprovare più tardi."
serverIsDead: "Il server non risponde. Si prega di attendere e riprovare più tardi." serverIsDead: "Il server non risponde. Si prega di attendere e riprovare più tardi."
youShouldUpgradeClient: "Per visualizzare la pagina è necessario aggiornare il client alla nuova versione e ricaricare." youShouldUpgradeClient: "Per visualizzare la pagina è necessario aggiornare il client alla nuova versione e ricaricare."
enterListName: "Nome della lista" enterListName: "Nome della lista"
privacy: "Privacy" privacy: "Privacy"
makeFollowManuallyApprove: "Richiedi di approvare i follower manualmente" makeFollowManuallyApprove: "Approva i follower manualmente"
defaultNoteVisibility: "Privacy predefinita delle note" defaultNoteVisibility: "Privacy predefinita delle note"
follow: "Segui" follow: "Segui"
followRequest: "Richiesta di follow" followRequest: "Richiesta di follow"
followRequests: "Richieste di follow" followRequests: "Richieste di follow"
unfollow: "Smetti di seguire" unfollow: "Non seguire"
followRequestPending: "Richiesta in approvazione" followRequestPending: "Richiesta in approvazione"
enterEmoji: "Inserisci emoji" enterEmoji: "Inserisci emoji"
renote: "Rinota" renote: "Rinota"
@@ -103,6 +103,8 @@ renoted: "Rinotato!"
cantRenote: "È impossibile rinotare questa nota." cantRenote: "È impossibile rinotare questa nota."
cantReRenote: "È impossibile rinotare una Rinota." cantReRenote: "È impossibile rinotare una Rinota."
quote: "Cita" quote: "Cita"
inChannelRenote: "Rinota nel canale"
inChannelQuote: "Cita nel canale"
pinnedNote: "Nota fissata" pinnedNote: "Nota fissata"
pinned: "Fissa sul profilo" pinned: "Fissa sul profilo"
you: "Tu" you: "Tu"
@@ -119,7 +121,7 @@ markAsSensitive: "Segna come sensibile"
unmarkAsSensitive: "Segna come non sensibile" unmarkAsSensitive: "Segna come non sensibile"
enterFileName: "Nome del file" enterFileName: "Nome del file"
mute: "Silenzia" mute: "Silenzia"
unmute: "Riattiva" unmute: "Riattiva l'audio"
block: "Blocca" block: "Blocca"
unblock: "Sblocca" unblock: "Sblocca"
suspend: "Sospendi" suspend: "Sospendi"
@@ -129,6 +131,7 @@ unblockConfirm: "Vuoi davvero sbloccare il profilo?"
suspendConfirm: "Vuoi sospendere questo profilo?" suspendConfirm: "Vuoi sospendere questo profilo?"
unsuspendConfirm: "Vuoi revocare la sospensione si questo profilo?" unsuspendConfirm: "Vuoi revocare la sospensione si questo profilo?"
selectList: "Seleziona una lista" selectList: "Seleziona una lista"
selectChannel: "Seleziona canale"
selectAntenna: "Scegli un'antenna" selectAntenna: "Scegli un'antenna"
selectWidget: "Seleziona il riquadro" selectWidget: "Seleziona il riquadro"
editWidgets: "Modifica i riquadri" editWidgets: "Modifica i riquadri"
@@ -140,7 +143,7 @@ emojiName: "Nome dell'emoji"
emojiUrl: "URL dell'emoji" emojiUrl: "URL dell'emoji"
addEmoji: "Aggiungi un emoji" addEmoji: "Aggiungi un emoji"
settingGuide: "Configurazione suggerita" settingGuide: "Configurazione suggerita"
cacheRemoteFiles: "Memorizzazione nella cache dei file remoti" cacheRemoteFiles: "Memorizza i file remoti nella cache"
cacheRemoteFilesDescription: "Disabilitando questa opzione, i file remoti verranno linkati direttamente senza essere memorizzati nella cache. Sarà possibile risparmiare spazio di archiviazione sul server, ma il traffico aumenterà in quanto non verranno generate anteprime." cacheRemoteFilesDescription: "Disabilitando questa opzione, i file remoti verranno linkati direttamente senza essere memorizzati nella cache. Sarà possibile risparmiare spazio di archiviazione sul server, ma il traffico aumenterà in quanto non verranno generate anteprime."
flagAsBot: "Io sono un robot" flagAsBot: "Io sono un robot"
flagAsBotDescription: "Attiva questo campo se il profilo esegue principalmente operazioni automatiche. L'attivazione segnala agli altri sviluppatori come comportarsi per evitare catene dinterazione infinite con altri bot. I sistemi interni di Misskey si adegueranno al fine di trattare questo profilo come bot." flagAsBotDescription: "Attiva questo campo se il profilo esegue principalmente operazioni automatiche. L'attivazione segnala agli altri sviluppatori come comportarsi per evitare catene dinterazione infinite con altri bot. I sistemi interni di Misskey si adegueranno al fine di trattare questo profilo come bot."
@@ -151,14 +154,14 @@ flagShowTimelineRepliesDescription: "Se è attiva, la timeline mostra le rispost
autoAcceptFollowed: "Accetta automaticamente le richieste di follow da utenti che già segui" autoAcceptFollowed: "Accetta automaticamente le richieste di follow da utenti che già segui"
addAccount: "Aggiungi profilo" addAccount: "Aggiungi profilo"
loginFailed: "Accesso non riuscito" loginFailed: "Accesso non riuscito"
showOnRemote: "Sfoglia sull'istanza remota" showOnRemote: "Leggi sull'istanza remota"
general: "Generali" general: "Generali"
wallpaper: "Sfondo" wallpaper: "Sfondo"
setWallpaper: "Imposta sfondo" setWallpaper: "Imposta sfondo"
removeWallpaper: "Elimina lo sfondo" removeWallpaper: "Elimina lo sfondo"
searchWith: "Cerca: {q}" searchWith: "Cerca: {q}"
youHaveNoLists: "Non hai ancora creato nessuna lista" youHaveNoLists: "Non hai ancora creato nessuna lista"
followConfirm: "Sei sicur@ di voler seguire {name}?" followConfirm: "Vuoi seguire {name}?"
proxyAccount: "Profilo proxy" proxyAccount: "Profilo proxy"
proxyAccountDescription: "Un profilo proxy funziona come follower per i profili remoti, sotto certe condizioni. Ad esempio, quando un profilo locale ne inserisce uno remoto in una lista (senza seguirlo), se nessun altro segue quel profilo remoto, le attività non possono essere distribuite. Dunque, il profilo proxy le seguirà per tutti." proxyAccountDescription: "Un profilo proxy funziona come follower per i profili remoti, sotto certe condizioni. Ad esempio, quando un profilo locale ne inserisce uno remoto in una lista (senza seguirlo), se nessun altro segue quel profilo remoto, le attività non possono essere distribuite. Dunque, il profilo proxy le seguirà per tutti."
host: "Server remoto" host: "Server remoto"
@@ -206,19 +209,19 @@ intro: "L'installazione di Misskey è terminata! Si prega di creare il profilo a
done: "Fine" done: "Fine"
processing: "In elaborazione" processing: "In elaborazione"
preview: "Anteprima" preview: "Anteprima"
default: "Predefinito" default: "Medio"
defaultValueIs: "Predefinito: {value}" defaultValueIs: "Predefinito: {value}"
noCustomEmojis: "Nessun emoji" noCustomEmojis: "Nessun emoji"
noJobs: "Nessun lavoro" noJobs: "Nessun lavoro"
federating: "Federazione" federating: "Federazione"
blocked: "Bloccato" blocked: "Bloccato"
suspended: "Sospensione" suspended: "Sospensione"
all: "Tutti" all: "Tutte"
subscribing: "Iscrizione" subscribing: "Iscrizione"
publishing: "Pubblicazione" publishing: "Pubblicazione"
notResponding: "Nessuna risposta" notResponding: "Nessuna risposta"
instanceFollowing: "Seguiti dall'istanza" instanceFollowing: "Seguiti dall'istanza"
instanceFollowers: "Followers dell'istanza" instanceFollowers: "Follower dell'istanza"
instanceUsers: "Utenti dell'istanza" instanceUsers: "Utenti dell'istanza"
changePassword: "Aggiorna Password" changePassword: "Aggiorna Password"
security: "Sicurezza" security: "Sicurezza"
@@ -231,7 +234,7 @@ more: "Di più!"
featured: "Tendenze" featured: "Tendenze"
usernameOrUserId: "Nome utente o ID utente" usernameOrUserId: "Nome utente o ID utente"
noSuchUser: "Nessun utente trovato" noSuchUser: "Nessun utente trovato"
lookup: "Cercare" lookup: "Cerca"
announcements: "Annunci" announcements: "Annunci"
imageUrl: "URL dell'immagine" imageUrl: "URL dell'immagine"
remove: "Elimina" remove: "Elimina"
@@ -256,6 +259,8 @@ noMoreHistory: "Non c'è più cronologia da visualizzare"
startMessaging: "Nuovo messaggio" startMessaging: "Nuovo messaggio"
nUsersRead: "Letto da {n} persone" nUsersRead: "Letto da {n} persone"
agreeTo: "Sono d'accordo con {0}" agreeTo: "Sono d'accordo con {0}"
agreeBelow: "Accetto quanto riportato sotto"
basicNotesBeforeCreateAccount: "Note importanti"
tos: "Termini di servizio" tos: "Termini di servizio"
start: "Inizia!" start: "Inizia!"
home: "Home" home: "Home"
@@ -283,7 +288,7 @@ selectFolders: "Seleziona cartella"
renameFile: "Rinomina file" renameFile: "Rinomina file"
folderName: "Nome della cartella" folderName: "Nome della cartella"
createFolder: "Nuova cartella" createFolder: "Nuova cartella"
renameFolder: "Rinominare cartella" renameFolder: "Rinomina cartella"
deleteFolder: "Elimina cartella" deleteFolder: "Elimina cartella"
addFile: "Allega" addFile: "Allega"
emptyDrive: "Il Drive è vuoto" emptyDrive: "Il Drive è vuoto"
@@ -300,7 +305,7 @@ avatar: "Foto del profilo"
banner: "Intestazione" banner: "Intestazione"
nsfw: "Contenuti sensibili" nsfw: "Contenuti sensibili"
whenServerDisconnected: "Quando la connessione col server è persa" whenServerDisconnected: "Quando la connessione col server è persa"
disconnectedFromServer: "Disconness@ dal server" disconnectedFromServer: "Il server si è disconnesso"
reload: "Ricarica" reload: "Ricarica"
doNothing: "Nessun'azione" doNothing: "Nessun'azione"
reloadConfirm: "Vuoi ricaricare?" reloadConfirm: "Vuoi ricaricare?"
@@ -311,9 +316,9 @@ reject: "Rifiuta"
normal: "Normale" normal: "Normale"
instanceName: "Nome dell'istanza" instanceName: "Nome dell'istanza"
instanceDescription: "Descrizione dell'istanza" instanceDescription: "Descrizione dell'istanza"
maintainerName: "Nome dell'Amministratore" maintainerName: "Nome dell'amministratore"
maintainerEmail: "Indirizzo e-mail dell'Amministratore" maintainerEmail: "Indirizzo e-mail dell'amministratore"
tosUrl: "Termini di servizio URL" tosUrl: "URL dei termini del servizio e della privacy"
thisYear: "Anno" thisYear: "Anno"
thisMonth: "Mese" thisMonth: "Mese"
today: "Oggi" today: "Oggi"
@@ -322,13 +327,13 @@ monthX: "{month}"
yearX: "{year}" yearX: "{year}"
pages: "Pagine" pages: "Pagine"
integration: "App collegate" integration: "App collegate"
connectService: "Connessione" connectService: "Connetti"
disconnectService: "Disconnessione " disconnectService: "Disconnetti"
enableLocalTimeline: "Abilita Timeline locale" enableLocalTimeline: "Abilita la timeline locale"
enableGlobalTimeline: "Abilita Timeline federata" enableGlobalTimeline: "Abilita la timeline federata"
disablingTimelinesInfo: "Anche disabilitandole, gli Amministratori e i Moderatori potranno comunque accedervi." disablingTimelinesInfo: "Anche disabilitandole, gli Amministratori e i Moderatori potranno comunque accedervi."
registration: "Iscriviti" registration: "Iscriviti"
enableRegistration: "Permettere nuove registrazioni" enableRegistration: "Consenti a chiunque di registrarsi"
invite: "Invita" invite: "Invita"
driveCapacityPerLocalAccount: "Capienza del Drive per profilo locale" driveCapacityPerLocalAccount: "Capienza del Drive per profilo locale"
driveCapacityPerRemoteAccount: "Capienza del Drive per profilo remoto" driveCapacityPerRemoteAccount: "Capienza del Drive per profilo remoto"
@@ -388,16 +393,19 @@ about: "Informazioni"
aboutMisskey: "Informazioni di Misskey" aboutMisskey: "Informazioni di Misskey"
administrator: "Amministratore" administrator: "Amministratore"
token: "Token" token: "Token"
twoStepAuthentication: "Autenticazione a due fattori" 2fa: "Autenticazione a due fattori"
totp: "App di autenticazione"
totpDescription: "Inserisci un codice OTP tramite un'app di autenticazione"
moderator: "Moderatore" moderator: "Moderatore"
moderation: "moderazione" moderation: "moderazione"
nUsersMentioned: "{n} profili menzionati" nUsersMentioned: "{n} profili menzionati"
securityKeyAndPasskey: "Chiave di sicurezza e accesso"
securityKey: "Chiave di sicurezza" securityKey: "Chiave di sicurezza"
securityKeyName: "Nome della chiave"
registerSecurityKey: "Registra una chiave di sicurezza"
lastUsed: "Ultima attività" lastUsed: "Ultima attività"
lastUsedAt: "Uso più recente: {t}"
unregister: "Annulla l'iscrizione" unregister: "Annulla l'iscrizione"
passwordLessLogin: "Accedi senza password" passwordLessLogin: "Accedi senza password"
passwordLessLoginDescription: "Accedi senza password, usando la chiave di sicurezza"
resetPassword: "Reimposta password" resetPassword: "Reimposta password"
newPasswordIs: "La tua nuova password è「{password}」" newPasswordIs: "La tua nuova password è「{password}」"
reduceUiAnimation: "Ridurre le animazioni dell'interfaccia" reduceUiAnimation: "Ridurre le animazioni dell'interfaccia"
@@ -412,24 +420,15 @@ markAsReadAllTalkMessages: "Segna tutte le chat come lette"
help: "Guida" help: "Guida"
inputMessageHere: "Scrivi messaggio qui" inputMessageHere: "Scrivi messaggio qui"
close: "Chiudi" close: "Chiudi"
group: "Gruppo"
groups: "Gruppi"
createGroup: "Nuovo gruppo"
ownedGroups: "I miei gruppi"
joinedGroups: "Gruppi a cui mi sono unit@"
invites: "Inviti" invites: "Inviti"
groupName: "Nome del gruppo"
members: "Membri" members: "Membri"
transfer: "Trasferisci" transfer: "Trasferisci"
messagingWithUser: "Iniziare una chat con un altr@ utente"
messagingWithGroup: "Chattare in gruppo"
title: "Titolo" title: "Titolo"
text: "Testo" text: "Testo"
enable: "Abilita" enable: "Abilita"
next: "Avanti" next: "Avanti"
retype: "Conferma" retype: "Conferma"
noteOf: "Note di {user}" noteOf: "Note di {user}"
inviteToGroup: "Invitare al gruppo"
quoteAttached: "Citazione allegata" quoteAttached: "Citazione allegata"
quoteQuestion: "Vuoi aggiungere una citazione?" quoteQuestion: "Vuoi aggiungere una citazione?"
noMessagesYet: "Ancora nessuna chat" noMessagesYet: "Ancora nessuna chat"
@@ -451,19 +450,18 @@ passwordMatched: "Corretta"
passwordNotMatched: "Le password non corrispondono." passwordNotMatched: "Le password non corrispondono."
signinWith: "Accedi con {x}" signinWith: "Accedi con {x}"
signinFailed: "Autenticazione non riuscita. Controlla la tua password e nome utente." signinFailed: "Autenticazione non riuscita. Controlla la tua password e nome utente."
tapSecurityKey: "Premi la chiave di sicurezza"
or: "oppure" or: "oppure"
language: "Lingua" language: "Lingua"
uiLanguage: "Lingua di visualizzazione dell'interfaccia" uiLanguage: "Lingua di visualizzazione dell'interfaccia"
groupInvited: "Invitat@ al gruppo"
aboutX: "Informazioni su {x}" aboutX: "Informazioni su {x}"
emojiStyle: "Stile emoji" emojiStyle: "Stile emoji"
native: "Nativo" native: "Nativo"
disableDrawer: "Non mostrare il menù sul drawer" disableDrawer: "Non mostrare il menù sul drawer"
youHaveNoGroups: "Nessun gruppo" showNoteActionsOnlyHover: "Mostra le azioni delle Note solo al passaggio del mouse"
joinOrCreateGroup: "Puoi creare il tuo gruppo o essere invitat@ a gruppi che già esistono."
noHistory: "Nessuna cronologia" noHistory: "Nessuna cronologia"
signinHistory: "Storico degli accessi al profilo" signinHistory: "Storico degli accessi al profilo"
enableAdvancedMfm: "Attiva MFM avanzati"
enableAnimatedMfm: "Attiva MFM animati"
doing: "In corso..." doing: "In corso..."
category: "Categoria" category: "Categoria"
tags: "Tag" tags: "Tag"
@@ -473,7 +471,7 @@ existingAccount: "Profilo esistente"
regenerate: "Generare di nuovo" regenerate: "Generare di nuovo"
fontSize: "Dimensione carattere" fontSize: "Dimensione carattere"
noFollowRequests: "Non hai alcuna richiesta di follow" noFollowRequests: "Non hai alcuna richiesta di follow"
openImageInNewTab: "Aprire immagini in una nuova scheda" openImageInNewTab: "Apri le immagini in un nuovo tab"
dashboard: "Pannello di controllo" dashboard: "Pannello di controllo"
local: "Locale" local: "Locale"
remote: "Remoto" remote: "Remoto"
@@ -602,7 +600,7 @@ smtpPass: "Password"
emptyToDisableSmtpAuth: "Lasciare il nome utente e la password vuoti per disabilitare la verifica SMTP" emptyToDisableSmtpAuth: "Lasciare il nome utente e la password vuoti per disabilitare la verifica SMTP"
smtpSecure: "Usare la porta SSL/TLS implicito per le connessioni SMTP" smtpSecure: "Usare la porta SSL/TLS implicito per le connessioni SMTP"
smtpSecureInfo: "Disabilitare quando è attivo STARTTLS." smtpSecureInfo: "Disabilitare quando è attivo STARTTLS."
testEmail: "Testare la consegna di posta elettronica" testEmail: "Testa la consegna di posta elettronica"
wordMute: "Filtri parole" wordMute: "Filtri parole"
regexpError: "errore regex" regexpError: "errore regex"
regexpErrorDescription: "Si è verificato un errore nell'espressione regolare alla riga {line} della parola muta {tab}:" regexpErrorDescription: "Si è verificato un errore nell'espressione regolare alla riga {line} della parola muta {tab}:"
@@ -615,7 +613,7 @@ metrics: "Statistiche"
overview: "Anteprima" overview: "Anteprima"
logs: "Log" logs: "Log"
delayed: "Ritardo" delayed: "Ritardo"
database: "Base di dati" database: "Base dati"
channel: "Canale" channel: "Canale"
create: "Crea" create: "Crea"
notificationSetting: "Impostazioni notifiche" notificationSetting: "Impostazioni notifiche"
@@ -704,7 +702,7 @@ narrow: "Stretto"
reloadToApplySetting: "Le tue preferenze verranno impostate dopo il ricaricamento della pagina. Vuoi ricaricare adesso?" reloadToApplySetting: "Le tue preferenze verranno impostate dopo il ricaricamento della pagina. Vuoi ricaricare adesso?"
needReloadToApply: "È necessario riavviare per rendere effettive le modifiche." needReloadToApply: "È necessario riavviare per rendere effettive le modifiche."
showTitlebar: "Visualizza la barra del titolo" showTitlebar: "Visualizza la barra del titolo"
clearCache: "Svuota cache" clearCache: "Svuota la cache"
onlineUsersCount: "{n} utenti online" onlineUsersCount: "{n} utenti online"
nUsers: "{n} utenti" nUsers: "{n} utenti"
nNotes: "{n}Note" nNotes: "{n}Note"
@@ -729,9 +727,9 @@ currentVersion: "Versione attuale"
latestVersion: "Ultima versione" latestVersion: "Ultima versione"
youAreRunningUpToDateClient: "Stai usando la versione più recente del client." youAreRunningUpToDateClient: "Stai usando la versione più recente del client."
newVersionOfClientAvailable: "Una nuova versione del tuo client è disponibile." newVersionOfClientAvailable: "Una nuova versione del tuo client è disponibile."
usageAmount: "In utilizzo" usageAmount: "In uso"
capacity: "Capacità" capacity: "Capacità"
inUse: "In utilizzo" inUse: "In uso"
editCode: "Modifica codice" editCode: "Modifica codice"
apply: "Applica" apply: "Applica"
receiveAnnouncementFromInstance: "Ricevi i messaggi informativi dall'istanza" receiveAnnouncementFromInstance: "Ricevi i messaggi informativi dall'istanza"
@@ -782,6 +780,7 @@ popularPosts: "Le più visualizzate"
shareWithNote: "Condividere in nota" shareWithNote: "Condividere in nota"
ads: "Pubblicità" ads: "Pubblicità"
expiration: "Scadenza" expiration: "Scadenza"
startingperiod: "Periodo di inizio"
memo: "Promemoria" memo: "Promemoria"
priority: "Priorità" priority: "Priorità"
high: "Alta" high: "Alta"
@@ -813,11 +812,12 @@ pubSub: "Publish/Subscribe del profilo"
lastCommunication: "La comunicazione più recente" lastCommunication: "La comunicazione più recente"
resolved: "Risolto" resolved: "Risolto"
unresolved: "Non risolto" unresolved: "Non risolto"
breakFollow: "Smetti di seguire" breakFollow: "Non seguire"
breakFollowConfirm: "Vuoi davvero togliere follower?"
itsOn: "Abilitato" itsOn: "Abilitato"
itsOff: "Disabilitato" itsOff: "Disabilitato"
emailRequiredForSignup: "L'ndirizzo e-mail è obbligatorio per registrarsi" emailRequiredForSignup: "L'ndirizzo e-mail è obbligatorio per registrarsi"
unread: "Non letto" unread: "Non lette"
filter: "Filtri" filter: "Filtri"
controlPanel: "Pannello di controllo" controlPanel: "Pannello di controllo"
manageAccounts: "Gestisci i profili" manageAccounts: "Gestisci i profili"
@@ -833,8 +833,6 @@ deleteAccountConfirm: "Così verrà eliminato il profilo. Vuoi procedere?"
incorrectPassword: "La password è errata." incorrectPassword: "La password è errata."
voteConfirm: "Votare per「{choice}」?" voteConfirm: "Votare per「{choice}」?"
hide: "Nascondere" hide: "Nascondere"
leaveGroup: "Esci dal gruppo"
leaveGroupConfirm: "Uscire da「{name}」?"
useDrawerReactionPickerForMobile: "Mostra sul drawer da dispositivo mobile" useDrawerReactionPickerForMobile: "Mostra sul drawer da dispositivo mobile"
welcomeBackWithName: "Ciao, {name}! Eccoti di nuovo!" welcomeBackWithName: "Ciao, {name}! Eccoti di nuovo!"
clickToFinishEmailVerification: "Fai click su [{ok}] per completare la verifica dell'indirizzo email." clickToFinishEmailVerification: "Fai click su [{ok}] per completare la verifica dell'indirizzo email."
@@ -850,16 +848,20 @@ instanceDefaultLightTheme: "Istanza, tema luminoso predefinito."
instanceDefaultDarkTheme: "Istanza, tema scuro predefinito." instanceDefaultDarkTheme: "Istanza, tema scuro predefinito."
instanceDefaultThemeDescription: "Compilare il codice del tema nel modulo dell'oggetto." instanceDefaultThemeDescription: "Compilare il codice del tema nel modulo dell'oggetto."
mutePeriod: "Durata del mute" mutePeriod: "Durata del mute"
period: "Scadenza"
indefinitely: "Non scade" indefinitely: "Non scade"
tenMinutes: "10 minuti" tenMinutes: "10 minuti"
oneHour: "1 ora" oneHour: "1 ora"
oneDay: "1 giorno" oneDay: "1 giorno"
oneWeek: "1 settimana" oneWeek: "1 settimana"
oneMonth: "Un mese"
reflectMayTakeTime: "Potrebbe essere necessario un po' di tempo perché ciò abbia effetto." reflectMayTakeTime: "Potrebbe essere necessario un po' di tempo perché ciò abbia effetto."
failedToFetchAccountInformation: "Impossibile recuperare le informazioni sul profilo" failedToFetchAccountInformation: "Impossibile recuperare le informazioni sul profilo"
rateLimitExceeded: "Superato il limite di velocità." rateLimitExceeded: "Superato il limite di richieste."
cropImage: "Ritaglio dell'immagine" cropImage: "Ritaglia l'immagine"
cropImageAsk: "Si desidera ritagliare l'immagine?" cropImageAsk: "Vuoi ritagliare l'immagine?"
cropYes: "Ritaglia"
cropNo: "Non ritagliare"
file: "Allegati" file: "Allegati"
recentNHours: "Ultime {n} ore" recentNHours: "Ultime {n} ore"
recentNDays: "Ultimi {n} giorni" recentNDays: "Ultimi {n} giorni"
@@ -938,6 +940,21 @@ cannotPerformTemporaryDescription: "L'attività non può essere svolta, poiché
preset: "Preimpostato" preset: "Preimpostato"
selectFromPresets: "Seleziona preimpostato" selectFromPresets: "Seleziona preimpostato"
achievements: "Obiettivi raggiunti" achievements: "Obiettivi raggiunti"
gotInvalidResponseError: "Risposta del server non valida"
gotInvalidResponseErrorDescription: "Il server potrebbe essere irraggiungibile o in manutenzione. Riprova più tardi."
thisPostMayBeAnnoying: "Questa nota potrebbe essere offensiva"
thisPostMayBeAnnoyingHome: "Pubblica sulla timeline principale"
thisPostMayBeAnnoyingCancel: "Annulla"
thisPostMayBeAnnoyingIgnore: "Pubblica lo stesso"
collapseRenotes: "Comprimi i Rinota già letti"
internalServerError: "Errore interno del server"
internalServerErrorDescription: "Si è verificato un errore imprevisto all'interno del server"
copyErrorInfo: "Copia le informazioni sull'errore"
joinThisServer: "Registrati su questa istanza"
exploreOtherServers: "Trova altre istanze"
letsLookAtTimeline: "Sbircia la timeline"
disableFederationWarn: "Disabilita la federazione. Questo cambiamento non rende le pubblicazioni private. Di solito non è necessario abilitare questa opzione."
invitationRequiredToRegister: "L'accesso a questo nodo è solo ad invito. Devi inserire un codice d'invito valido. Puoi richiedere un codice all'amministratore."
_achievements: _achievements:
earnedAt: "Data di conseguimento" earnedAt: "Data di conseguimento"
_types: _types:
@@ -993,53 +1010,53 @@ _achievements:
flavor: "Hai molto da scrivere?" flavor: "Hai molto da scrivere?"
_login3: _login3:
title: "Principiante I" title: "Principiante I"
description: "Accedi per un totale di 3 giorni" description: "Hai totalizzato 3 accessi!"
flavor: "Da oggi, chiamatemi Misskist" flavor: "Da oggi, chiamatemi Misskist"
_login7: _login7:
title: "Principiante II" title: "Principiante II"
description: "Accedi per un totale di 7 giorni" description: "Hai totalizzato 7 accessi!"
flavor: "Ti sembra di avere la situazione sotto controllo?" flavor: "Ti sembra di avere la situazione sotto controllo?"
_login15: _login15:
title: "Principiante III" title: "Principiante III"
description: "Accedi per un totale di 15 giorni" description: "Hai totalizzato 15 accessi!"
_login30: _login30:
title: "Misskist I" title: "Misskist I"
description: "Accedi per un totale di 30 giorni" description: "Hai totalizzato 30 accessi!"
_login60: _login60:
title: "Misskeist II" title: "Misskeist II"
description: "Accedi per un totale di 60 giorni" description: "Hai totalizzato 60 accessi!"
_login100: _login100:
title: "Misskeist III" title: "Misskeist III"
description: "Accedi per un totale di 100 giorni" description: "Hai totalizzato 100 accessi!"
flavor: "Violent Misskeist" flavor: "Violent Misskeist"
_login200: _login200:
title: "Regolare I" title: "Regolare I livello"
description: "Accedi per un totale di 200 giorni" description: "Hai totalizzato 200 accessi!"
_login300: _login300:
title: "Regolare II" title: "Regolare II livello"
description: "Accedi per un totale di 300 giorni" description: "Hai totalizzato 300 accessi!"
_login400: _login400:
title: "Regolare III" title: "Regolare III livello"
description: "Accedi per un totale di 400 giorni" description: "Hai totalizzato 400 accessi!"
_login500: _login500:
title: "Professionista I" title: "Professionista I livello"
description: "Accedi per un totale di 500 giorni" description: "Hai totalizzato 500 accessi!"
flavor: "Amici cari, mi piacciono le Note" flavor: "Amici cari, mi piacciono le Note"
_login600: _login600:
title: "Professionista II" title: "Professionista II livello"
description: "Accedi per un totale di 600 giorni" description: "Hai totalizzato 600 accessi!"
_login700: _login700:
title: "Professionista III" title: "Professionista III livello"
description: "Accedi per un totale di 700 giorni" description: "Hai totalizzato 700 accessi!"
_login800: _login800:
title: "Maestro di Note I" title: "Maestro di Note I livello"
description: "Accedi per un totale di 800 giorni" description: "Hai totalizzato 800 accessi!"
_login900: _login900:
title: "Maestro di Note II" title: "Maestro di Note II livello"
description: "Accedi per un totale di 900 giorni" description: "Hai totalizzato 900 accessi!"
_login1000: _login1000:
title: "Maestro di Note III" title: "Maestro di Note III livello"
description: "Accedi per un totale di 1.000 giorni" description: "Hai totalizzato 1000 accessi!"
flavor: "Grazie per aver usato Misskey!" flavor: "Grazie per aver usato Misskey!"
_noteClipped1: _noteClipped1:
title: "Devo clippare!" title: "Devo clippare!"
@@ -1051,7 +1068,7 @@ _achievements:
title: "Fornitura stelline" title: "Fornitura stelline"
description: "Qualcuno ha preferito una delle tue Note" description: "Qualcuno ha preferito una delle tue Note"
_profileFilled: _profileFilled:
title: "Perfettamente" title: "Preparazione perfetta!"
description: "Imposta il tuo profilo" description: "Imposta il tuo profilo"
_markedAsCat: _markedAsCat:
title: "Io sono un gatto" title: "Io sono un gatto"
@@ -1074,7 +1091,7 @@ _achievements:
description: "Hai seguito 300 profili" description: "Hai seguito 300 profili"
_followers1: _followers1:
title: "Il primo profilo tuo Follower" title: "Il primo profilo tuo Follower"
description: "Hai ottenuto il tuo primo Follower" description: "Hai ottenuto il tuo primo profilo Follower"
_followers10: _followers10:
title: "Follow me!" title: "Follow me!"
description: "Hai ottenuto 10 profili Follower" description: "Hai ottenuto 10 profili Follower"
@@ -1451,6 +1468,7 @@ _ago:
weeksAgo: "{n} sett. fa" weeksAgo: "{n} sett. fa"
monthsAgo: "{n} mesi fa" monthsAgo: "{n} mesi fa"
yearsAgo: "{n} anni fa" yearsAgo: "{n} anni fa"
invalid: "Niente da visualizzare"
_time: _time:
second: "s" second: "s"
minute: "min" minute: "min"
@@ -1459,10 +1477,10 @@ _time:
_tutorial: _tutorial:
title: "Come usare Misskey" title: "Come usare Misskey"
step1_1: "Eccoci!" step1_1: "Eccoci!"
step1_2: "Questa pagina si chiama una \" Timeline \". Mostra in ordine cronologico le \" note \" delle persone che segui." step1_2: "Questa pagina si chiama \"Timeline \" e mostra in ordine cronologico le \"note\" delle persone che segui."
step1_3: "Attualmente la tua Timeline è vuota perché non segui alcun profilo e non hai pubblicato alcuna nota ancora." step1_3: "Attualmente la tua Timeline è vuota perché non segui alcun profilo e non hai ancora pubblicato alcuna nota."
step2_1: "Prima di scrivere una «Nota» o di seguire altri profili, prepara il tuo profilo!" step2_1: "Prima di scrivere una «Nota» o di seguire altri profili, prepara il tuo profilo!"
step2_2: "Aggiungere qualche informazione su di te aumenterà le tue possibilità di essere seguit@ da altre persone. " step2_2: "Se aggiungi informazioni personali aumenterai le tue possibilità di essere seguit@ da altre persone. "
step3_1: "Hai finito di impostare il tuo profilo?" step3_1: "Hai finito di impostare il tuo profilo?"
step3_2: "Ora puoi pubblicare una «Nota». Proviamo subito! Premi il bottone con l'icona «penna» per iniziare a scrivere in una finestra di dialogo. " step3_2: "Ora puoi pubblicare una «Nota». Proviamo subito! Premi il bottone con l'icona «penna» per iniziare a scrivere in una finestra di dialogo. "
step3_3: "Scritto il testo della nota, puoi pubblicarla premendo il pulsante nella parte superiore destra della finestra di dialogo." step3_3: "Scritto il testo della nota, puoi pubblicarla premendo il pulsante nella parte superiore destra della finestra di dialogo."
@@ -1481,28 +1499,43 @@ _tutorial:
step7_3: "Da ultimo, buon divertimento su Misskey! 🚀" step7_3: "Da ultimo, buon divertimento su Misskey! 🚀"
step8_1: "Per concludere, vuoi attivare le notifiche push?" step8_1: "Per concludere, vuoi attivare le notifiche push?"
step8_2: "Attivandole, otterrai notifiche di follow, reazioni e menzioni anche quando Misskey è chiuso." step8_2: "Attivandole, otterrai notifiche di follow, reazioni e menzioni anche quando Misskey è chiuso."
step8_3: "Puoi anche modificare questa impostazione successivamente." step8_3: "Potrai modificare questa impostazione."
_2fa: _2fa:
alreadyRegistered: "La configurazione è stata già completata." alreadyRegistered: "La configurazione è stata già completata."
registerDevice: "Aggiungi dispositivo" registerTOTP: "Registra un'app di autenticazione"
registerKey: "Chiave di registro." passwordToTOTP: "Inserire la password"
step1: "Innanzitutto, installare sul dispositivo un'applicazione di autenticazione come {a} o {b}." step1: "Innanzitutto, installare sul dispositivo un'applicazione di autenticazione come {a} o {b}."
step2: "Quindi, scansionare il codice QR visualizzato con l'app." step2: "Quindi, scansionare il codice QR visualizzato con l'app."
step2Click: "Cliccando sul codice QR, puoi registrarlo con l'app di autenticazione o il portachiavi installato sul tuo dispositivo."
step2Url: "Nell'applicazione desktop inserire il seguente URL: " step2Url: "Nell'applicazione desktop inserire il seguente URL: "
step3Title: "Inserisci il codice di verifica"
step3: "Inserite il token visualizzato nell'app e il gioco è fatto." step3: "Inserite il token visualizzato nell'app e il gioco è fatto."
step4: "D'ora in poi, quando si accede, si inserisce il token nello stesso modo." step4: "D'ora in poi, quando si accede, si inserisce il token nello stesso modo."
securityKeyNotSupported: "Il tuo browser non supporta le chiavi di sicurezza."
registerTOTPBeforeKey: "Ti occorre un'app di autenticazione con OTP, prima di registrare la chiave di sicurezza."
securityKeyInfo: "È possibile impostare il dispositivo per accedere utilizzando una chiave di sicurezza hardware che supporta FIDO2 o un'impronta digitale o un PIN sul dispositivo." securityKeyInfo: "È possibile impostare il dispositivo per accedere utilizzando una chiave di sicurezza hardware che supporta FIDO2 o un'impronta digitale o un PIN sul dispositivo."
chromePasskeyNotSupported: "Le passkey di Chrome non sono attualmente supportate."
registerSecurityKey: "Registra la chiave di sicurezza"
securityKeyName: "Inserisci il nome della chiave"
tapSecurityKey: "Segui le istruzioni del browser e registra la chiave di sicurezza."
removeKey: "Elimina la chiave di sicurezza"
removeKeyConfirm: "Vuoi davvero eliminare \"{name}\"?"
whyTOTPOnlyRenew: "Se c'è una chiave di sicurezza attiva, non è possibile rimuovere l'app di autenticazione."
renewTOTP: "Riconfigura l'app di autenticazione"
renewTOTPConfirm: "I codici di verifica nelle app di autenticazione esistenti smetteranno di funzionare"
renewTOTPOk: "Ripristina"
renewTOTPCancel: "No grazie"
_permissions: _permissions:
"read:account": "Visualizzare le informazioni sul profilo" "read:account": "Visualizza le informazioni sul profilo"
"write:account": "Modificare le informazioni sul profilo" "write:account": "Modifica le informazioni sul profilo"
"read:blocks": "Visualizza i profili bloccati" "read:blocks": "Visualizza i profili bloccati"
"write:blocks": "Gestisci i profili bloccati" "write:blocks": "Gestisci i profili bloccati"
"read:drive": "Aprire il Drive" "read:drive": "Apri il Drive"
"write:drive": "Gestire il Drive" "write:drive": "Gestisci il Drive"
"read:favorites": "Visualizza i tuoi preferiti" "read:favorites": "Visualizza i tuoi preferiti"
"write:favorites": "Gestisci i tuoi preferiti" "write:favorites": "Gestisci i tuoi preferiti"
"read:following": "Vedi le informazioni di follow" "read:following": "Vedi le informazioni di follow"
"write:following": "Seguiti/ Smetti di seguire" "write:following": "Seguire / Non seguire altri profili"
"read:messaging": "Visualizzare la chat" "read:messaging": "Visualizzare la chat"
"write:messaging": "Gestire la chat" "write:messaging": "Gestire la chat"
"read:mutes": "Vedi i profili silenziati" "read:mutes": "Vedi i profili silenziati"
@@ -1526,18 +1559,20 @@ _permissions:
"read:gallery-likes": "Visualizza i contenuti della galleria." "read:gallery-likes": "Visualizza i contenuti della galleria."
"write:gallery-likes": "Manipolazione dei \"Mi piace\" della galleria." "write:gallery-likes": "Manipolazione dei \"Mi piace\" della galleria."
_auth: _auth:
shareAccessTitle: "Permessi dell'applicazione"
shareAccess: "Vuoi autorizzare {name} ad accedere al tuo profilo?" shareAccess: "Vuoi autorizzare {name} ad accedere al tuo profilo?"
shareAccessAsk: "Vuoi autorizzare questa App ad accedere al tuo profilo?" shareAccessAsk: "Vuoi autorizzare questa App ad accedere al tuo profilo?"
permission: "{name} richiede i permessi seguenti"
permissionAsk: "Questa app richiede le seguenti autorizzazioni:" permissionAsk: "Questa app richiede le seguenti autorizzazioni:"
pleaseGoBack: "Si prega di ritornare sulla app" pleaseGoBack: "Si prega di ritornare sulla app"
callback: "Ritornando sulla app" callback: "Ritornando sulla app"
denied: "Accesso negato" denied: "Accesso negato"
pleaseLogin: "Per favore accedi al tuo account per cambiare i permessi dell'applicazione"
_antennaSources: _antennaSources:
all: "Tutte le note" all: "Tutte le note"
homeTimeline: "Note dagli utenti che segui" homeTimeline: "Note dagli utenti che segui"
users: "Note dagli utenti selezionati" users: "Note dagli utenti selezionati"
userList: "Note dagli utenti della lista selezionata" userList: "Note dagli utenti della lista selezionata"
userGroup: "Note dagli utenti del gruppo selezionato"
_weekday: _weekday:
sunday: "Domenica" sunday: "Domenica"
monday: "Lunedì" monday: "Lunedì"
@@ -1608,23 +1643,23 @@ _visibility:
publicDescription: "Visibile per tutti sul Fediverso" publicDescription: "Visibile per tutti sul Fediverso"
home: "Home" home: "Home"
homeDescription: "Visibile solo sulla timeline \"Home\"" homeDescription: "Visibile solo sulla timeline \"Home\""
followers: "Followers" followers: "Follower"
followersDescription: "Visibile solo per i tuoi followers" followersDescription: "Visibile solo per i tuoi follower"
specified: "Diretta" specified: "Nota diretta"
specifiedDescription: "Visibile solo ai profili menzionati" specifiedDescription: "Visibile solo ai profili menzionati"
localOnly: "Soltanto locale" disableFederation: "Interrompi la federazione"
localOnlyDescription: "Non visibile ai profili remoti" disableFederationDescription: "Non spedire attività alle altre istanze remote"
_postForm: _postForm:
replyPlaceholder: "Nota la tua risposta.." replyPlaceholder: "Rispondi a questa nota..."
quotePlaceholder: "Cita Nota..." quotePlaceholder: "Cita questa nota..."
channelPlaceholder: "Pubblica in canale" channelPlaceholder: "Pubblica sul canale..."
_placeholders: _placeholders:
a: "Che succede?" a: "Come va?"
b: "È successo qualcosa?" b: "Hai qualcosa da raccontare? Inizia pure..."
c: "Che cos'hai in mente?" c: "Stai pensando a qualcosa?"
d: "Vuoi dire qualcosa?" d: "Vuoi dire qualcosa?"
e: "Scrivi qualcosa qui" e: "Puoi scrivere qui..."
f: "Aspettando che scriva..." f: "Inizia pure a scrivere..."
_profile: _profile:
name: "Nome" name: "Nome"
username: "Nome utente" username: "Nome utente"
@@ -1640,7 +1675,7 @@ _profile:
_exportOrImport: _exportOrImport:
allNotes: "Tutte le note" allNotes: "Tutte le note"
favoritedNotes: "Note preferite" favoritedNotes: "Note preferite"
followingList: "Follows" followingList: "Follow"
muteList: "Elenco profili silenziati" muteList: "Elenco profili silenziati"
blockingList: "Elenco profili bloccati" blockingList: "Elenco profili bloccati"
userLists: "Liste" userLists: "Liste"
@@ -1655,9 +1690,9 @@ _charts:
notesIncDec: "Variazione del numero di note" notesIncDec: "Variazione del numero di note"
localNotesIncDec: "Variazione del numero di note locali" localNotesIncDec: "Variazione del numero di note locali"
remoteNotesIncDec: "Variazione del numero di note distanti" remoteNotesIncDec: "Variazione del numero di note distanti"
notesTotal: "Conteggio totale di note" notesTotal: "Numero di note in totale"
filesIncDec: "Variazione del numero dei file" filesIncDec: "Variazione del numero dei file"
filesTotal: "Numero totale di file" filesTotal: "Numero di file in totale"
storageUsageIncDec: "Variazione dell'utilizzo dell'immagazzinamento" storageUsageIncDec: "Variazione dell'utilizzo dell'immagazzinamento"
storageUsageTotal: "Utilizzo totale dell'immagazzinamento" storageUsageTotal: "Utilizzo totale dell'immagazzinamento"
_instanceCharts: _instanceCharts:
@@ -1749,14 +1784,11 @@ _notification:
fileUploaded: "File caricato correttamente" fileUploaded: "File caricato correttamente"
youGotMention: "{name} ti ha menzionato" youGotMention: "{name} ti ha menzionato"
youGotReply: "{name} ti ha risposto" youGotReply: "{name} ti ha risposto"
youGotQuote: "{name} ha citato il tuo Nota e ha detto" youGotQuote: "{name} ha citato la tua Nota e ha detto"
youRenoted: "{name} ha rinotato" youRenoted: "{name} ha rinotato"
youGotMessagingMessageFromUser: "{name} ti ha mandato un messaggio"
youGotMessagingMessageFromGroup: "{name} ti ha mandato un messaggio nella chat"
youWereFollowed: "Ha iniziato a seguirti" youWereFollowed: "Ha iniziato a seguirti"
youReceivedFollowRequest: "Hai ricevuto una richiesta di follow" youReceivedFollowRequest: "Hai ricevuto una richiesta di follow"
yourFollowRequestAccepted: "La tua richiesta di follow è stata accettata" yourFollowRequestAccepted: "La tua richiesta di follow è stata accettata"
youWereInvitedToGroup: "Invitat@ al gruppo"
pollEnded: "Risultati del sondaggio." pollEnded: "Risultati del sondaggio."
unreadAntennaNote: "Antenna {name}" unreadAntennaNote: "Antenna {name}"
emptyPushNotificationMessage: "Le notifiche push sono state aggiornate." emptyPushNotificationMessage: "Le notifiche push sono state aggiornate."
@@ -1772,7 +1804,7 @@ _notification:
pollEnded: "Sondaggio chiuso." pollEnded: "Sondaggio chiuso."
receiveFollowRequest: "Richiesta di follow ricevuta" receiveFollowRequest: "Richiesta di follow ricevuta"
followRequestAccepted: "Richiesta di follow accettata" followRequestAccepted: "Richiesta di follow accettata"
groupInvited: "Invito a un gruppo" achievementEarned: "Risultato raggiunto"
app: "Notifiche da applicazioni" app: "Notifiche da applicazioni"
_actions: _actions:
followBack: "Segui" followBack: "Segui"
@@ -1805,3 +1837,6 @@ _deck:
channel: "Canale" channel: "Canale"
mentions: "Menzioni" mentions: "Menzioni"
direct: "Diretta" direct: "Diretta"
_dialog:
charactersExceeded: "Hai superato il limite di {max} caratteri! ({corrente})"
charactersBelow: "Sei al di sotto del minimo di {min} caratteri! ({corrente})"

View File

@@ -2,7 +2,7 @@ _lang_: "日本語"
headlineMisskey: "ノートでつながるネットワーク" headlineMisskey: "ノートでつながるネットワーク"
introMisskey: "ようこそMisskeyは、オープンソースの分散型マイクロブログサービスです。\n「ート」を作成して、いま起こっていることを共有したり、あなたについて皆に発信しよう📡\n「リアクション」機能で、皆のートに素早く反応を追加することもできます👍\n新しい世界を探検しよう🚀" introMisskey: "ようこそMisskeyは、オープンソースの分散型マイクロブログサービスです。\n「ート」を作成して、いま起こっていることを共有したり、あなたについて皆に発信しよう📡\n「リアクション」機能で、皆のートに素早く反応を追加することもできます👍\n新しい世界を探検しよう🚀"
poweredByMisskeyDescription: "{name}は、オープンソースのプラットフォーム<b>Misskey</b>を使ったサービス(Misskeyインスタンスと呼ばれます)のひとつです。" poweredByMisskeyDescription: "{name}は、オープンソースのプラットフォーム<b>Misskey</b>のサーバーのひとつです。"
monthAndDay: "{month}月 {day}日" monthAndDay: "{month}月 {day}日"
search: "検索" search: "検索"
notifications: "通知" notifications: "通知"
@@ -18,7 +18,7 @@ enterUsername: "ユーザー名を入力"
renotedBy: "{user}がRenote" renotedBy: "{user}がRenote"
noNotes: "ノートはありません" noNotes: "ノートはありません"
noNotifications: "通知はありません" noNotifications: "通知はありません"
instance: "インスタンス" instance: "サーバー"
settings: "設定" settings: "設定"
basicSettings: "基本設定" basicSettings: "基本設定"
otherSettings: "その他の設定" otherSettings: "その他の設定"
@@ -163,13 +163,13 @@ searchWith: "検索: {q}"
youHaveNoLists: "リストがありません" youHaveNoLists: "リストがありません"
followConfirm: "{name}をフォローしますか?" followConfirm: "{name}をフォローしますか?"
proxyAccount: "プロキシアカウント" proxyAccount: "プロキシアカウント"
proxyAccountDescription: "プロキシアカウントは、特定の条件下でユーザーのリモートフォローを代行するアカウントです。例えば、ユーザーがリモートユーザーをリストに入れたとき、リストに入れられたユーザーを誰もフォローしていないとアクティビティがインスタンスに配達されないため、代わりにプロキシアカウントがフォローするようにします。" proxyAccountDescription: "プロキシアカウントは、特定の条件下でユーザーのリモートフォローを代行するアカウントです。例えば、ユーザーがリモートユーザーをリストに入れたとき、リストに入れられたユーザーを誰もフォローしていないとアクティビティがサーバーに配達されないため、代わりにプロキシアカウントがフォローするようにします。"
host: "ホスト" host: "ホスト"
selectUser: "ユーザーを選択" selectUser: "ユーザーを選択"
recipient: "宛先" recipient: "宛先"
annotation: "注釈" annotation: "注釈"
federation: "連合" federation: "連合"
instances: "インスタンス" instances: "サーバー"
registeredAt: "初観測" registeredAt: "初観測"
latestRequestReceivedAt: "直近のリクエスト受信" latestRequestReceivedAt: "直近のリクエスト受信"
latestStatus: "直近のステータス" latestStatus: "直近のステータス"
@@ -178,7 +178,7 @@ charts: "チャート"
perHour: "1時間ごと" perHour: "1時間ごと"
perDay: "1日ごと" perDay: "1日ごと"
stopActivityDelivery: "アクティビティの配送を停止" stopActivityDelivery: "アクティビティの配送を停止"
blockThisInstance: "このインスタンスをブロック" blockThisInstance: "このサーバーをブロック"
operations: "操作" operations: "操作"
software: "ソフトウェア" software: "ソフトウェア"
version: "バージョン" version: "バージョン"
@@ -189,15 +189,15 @@ jobQueue: "ジョブキュー"
cpuAndMemory: "CPUとメモリ" cpuAndMemory: "CPUとメモリ"
network: "ネットワーク" network: "ネットワーク"
disk: "ディスク" disk: "ディスク"
instanceInfo: "インスタンス情報" instanceInfo: "サーバー情報"
statistics: "統計" statistics: "統計"
clearQueue: "キューをクリア" clearQueue: "キューをクリア"
clearQueueConfirmTitle: "キューをクリアしますか?" clearQueueConfirmTitle: "キューをクリアしますか?"
clearQueueConfirmText: "未配達の投稿は配送されなくなります。通常この操作を行う必要はありません。" clearQueueConfirmText: "未配達の投稿は配送されなくなります。通常この操作を行う必要はありません。"
clearCachedFiles: "キャッシュをクリア" clearCachedFiles: "キャッシュをクリア"
clearCachedFilesConfirm: "キャッシュされたリモートファイルをすべて削除しますか?" clearCachedFilesConfirm: "キャッシュされたリモートファイルをすべて削除しますか?"
blockedInstances: "ブロックしたインスタンス" blockedInstances: "ブロックしたサーバー"
blockedInstancesDescription: "ブロックしたいインスタンスのホストを改行で区切って設定します。ブロックされたインスタンスは、このインスタンスとやり取りできなくなります。サブドメインもブロックされます。" blockedInstancesDescription: "ブロックしたいサーバーのホストを改行で区切って設定します。ブロックされたサーバーは、このサーバーとやり取りできなくなります。サブドメインもブロックされます。"
muteAndBlock: "ミュートとブロック" muteAndBlock: "ミュートとブロック"
mutedUsers: "ミュートしたユーザー" mutedUsers: "ミュートしたユーザー"
blockedUsers: "ブロックしたユーザー" blockedUsers: "ブロックしたユーザー"
@@ -220,9 +220,9 @@ all: "全て"
subscribing: "購読中" subscribing: "購読中"
publishing: "配信中" publishing: "配信中"
notResponding: "応答なし" notResponding: "応答なし"
instanceFollowing: "インスタンスのフォロー" instanceFollowing: "サーバーのフォロー"
instanceFollowers: "インスタンスのフォロワー" instanceFollowers: "サーバーのフォロワー"
instanceUsers: "インスタンスのユーザー" instanceUsers: "サーバーのユーザー"
changePassword: "パスワードを変更" changePassword: "パスワードを変更"
security: "セキュリティ" security: "セキュリティ"
retypedNotMatch: "入力が一致しません。" retypedNotMatch: "入力が一致しません。"
@@ -314,8 +314,8 @@ unwatch: "ウォッチ解除"
accept: "許可" accept: "許可"
reject: "拒否" reject: "拒否"
normal: "正常" normal: "正常"
instanceName: "インスタンス名" instanceName: "サーバー名"
instanceDescription: "インスタンスの紹介" instanceDescription: "サーバーの紹介"
maintainerName: "管理者の名前" maintainerName: "管理者の名前"
maintainerEmail: "管理者のメールアドレス" maintainerEmail: "管理者のメールアドレス"
tosUrl: "利用規約URL" tosUrl: "利用規約URL"
@@ -345,7 +345,7 @@ basicInfo: "基本情報"
pinnedUsers: "ピン留めユーザー" pinnedUsers: "ピン留めユーザー"
pinnedUsersDescription: "「みつける」ページなどにピン留めしたいユーザーを改行で区切って記述します。" pinnedUsersDescription: "「みつける」ページなどにピン留めしたいユーザーを改行で区切って記述します。"
pinnedPages: "ピン留めページ" pinnedPages: "ピン留めページ"
pinnedPagesDescription: "インスタンスのトップページにピン留めしたいページのパスを改行で区切って記述します。" pinnedPagesDescription: "サーバーのトップページにピン留めしたいページのパスを改行で区切って記述します。"
pinnedClipId: "ピン留めするクリップのID" pinnedClipId: "ピン留めするクリップのID"
pinnedNotes: "ピン留めされたノート" pinnedNotes: "ピン留めされたノート"
hcaptcha: "hCaptcha" hcaptcha: "hCaptcha"
@@ -392,17 +392,20 @@ userList: "リスト"
about: "情報" about: "情報"
aboutMisskey: "Misskeyについて" aboutMisskey: "Misskeyについて"
administrator: "管理者" administrator: "管理者"
token: "トークン" token: "確認コード"
twoStepAuthentication: "二段階認証" 2fa: "二要素認証"
totp: "認証アプリ"
totpDescription: "認証アプリを使ってワンタイムパスワードを入力"
moderator: "モデレーター" moderator: "モデレーター"
moderation: "モデレーション" moderation: "モデレーション"
nUsersMentioned: "{n}人が投稿" nUsersMentioned: "{n}人が投稿"
securityKeyAndPasskey: "セキュリティキー・パスキー"
securityKey: "セキュリティキー" securityKey: "セキュリティキー"
securityKeyName: "キーの名前"
registerSecurityKey: "セキュリティキーを登録する"
lastUsed: "最後の使用" lastUsed: "最後の使用"
lastUsedAt: "最後の使用: {t}"
unregister: "登録を解除" unregister: "登録を解除"
passwordLessLogin: "パスワード無しログイン" passwordLessLogin: "パスワードレスログイン"
passwordLessLoginDescription: "パスワードを使用せず、セキュリティキーやパスキーなどのみでログインします"
resetPassword: "パスワードをリセット" resetPassword: "パスワードをリセット"
newPasswordIs: "新しいパスワードは「{password}」です" newPasswordIs: "新しいパスワードは「{password}」です"
reduceUiAnimation: "UIのアニメーションを減らす" reduceUiAnimation: "UIのアニメーションを減らす"
@@ -417,24 +420,15 @@ markAsReadAllTalkMessages: "すべてのチャットを既読にする"
help: "ヘルプ" help: "ヘルプ"
inputMessageHere: "ここにメッセージを入力" inputMessageHere: "ここにメッセージを入力"
close: "閉じる" close: "閉じる"
group: "グループ"
groups: "グループ"
createGroup: "グループを作成"
ownedGroups: "所有グループ"
joinedGroups: "参加しているグループ"
invites: "招待" invites: "招待"
groupName: "グループ名"
members: "メンバー" members: "メンバー"
transfer: "譲渡" transfer: "譲渡"
messagingWithUser: "ユーザーとチャット"
messagingWithGroup: "グループでチャット"
title: "タイトル" title: "タイトル"
text: "テキスト" text: "テキスト"
enable: "有効にする" enable: "有効にする"
next: "次" next: "次"
retype: "再入力" retype: "再入力"
noteOf: "{user}のノート" noteOf: "{user}のノート"
inviteToGroup: "グループに招待"
quoteAttached: "引用付き" quoteAttached: "引用付き"
quoteQuestion: "引用として添付しますか?" quoteQuestion: "引用として添付しますか?"
noMessagesYet: "まだチャットはありません" noMessagesYet: "まだチャットはありません"
@@ -456,17 +450,14 @@ passwordMatched: "一致しました"
passwordNotMatched: "一致していません" passwordNotMatched: "一致していません"
signinWith: "{x}でログイン" signinWith: "{x}でログイン"
signinFailed: "ログインできませんでした。ユーザー名とパスワードを確認してください。" signinFailed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
tapSecurityKey: "セキュリティキーにタッチ"
or: "もしくは" or: "もしくは"
language: "言語" language: "言語"
uiLanguage: "UIの表示言語" uiLanguage: "UIの表示言語"
groupInvited: "グループに招待されました"
aboutX: "{x}について" aboutX: "{x}について"
emojiStyle: "絵文字のスタイル" emojiStyle: "絵文字のスタイル"
native: "ネイティブ" native: "ネイティブ"
disableDrawer: "メニューをドロワーで表示しない" disableDrawer: "メニューをドロワーで表示しない"
youHaveNoGroups: "グループがありません" showNoteActionsOnlyHover: "ノートの操作部をホバー時のみ表示する"
joinOrCreateGroup: "既存のグループに招待してもらうか、新しくグループを作成してください。"
noHistory: "履歴はありません" noHistory: "履歴はありません"
signinHistory: "ログイン履歴" signinHistory: "ログイン履歴"
enableAdvancedMfm: "高度なMFMを有効にする" enableAdvancedMfm: "高度なMFMを有効にする"
@@ -547,7 +538,7 @@ updateRemoteUser: "リモートユーザー情報の更新"
deleteAllFiles: "すべてのファイルを削除" deleteAllFiles: "すべてのファイルを削除"
deleteAllFilesConfirm: "すべてのファイルを削除しますか?" deleteAllFilesConfirm: "すべてのファイルを削除しますか?"
removeAllFollowing: "フォローを全解除" removeAllFollowing: "フォローを全解除"
removeAllFollowingDescription: "{host}からのフォローをすべて解除します。そのインスタンスがもう存在しなくなった場合などに実行してください。" removeAllFollowingDescription: "{host}からのフォローをすべて解除します。そのサーバーがもう存在しなくなった場合などに実行してください。"
userSuspended: "このユーザーは凍結されています。" userSuspended: "このユーザーは凍結されています。"
userSilenced: "このユーザーはサイレンスされています。" userSilenced: "このユーザーはサイレンスされています。"
yourAccountSuspendedTitle: "アカウントが凍結されています" yourAccountSuspendedTitle: "アカウントが凍結されています"
@@ -613,7 +604,7 @@ testEmail: "配信テスト"
wordMute: "ワードミュート" wordMute: "ワードミュート"
regexpError: "正規表現エラー" regexpError: "正規表現エラー"
regexpErrorDescription: "{tab}ワードミュートの{line}行目の正規表現にエラーが発生しました:" regexpErrorDescription: "{tab}ワードミュートの{line}行目の正規表現にエラーが発生しました:"
instanceMute: "インスタンスミュート" instanceMute: "サーバーミュート"
userSaysSomething: "{name}が何かを言いました" userSaysSomething: "{name}が何かを言いました"
makeActive: "アクティブにする" makeActive: "アクティブにする"
display: "表示" display: "表示"
@@ -644,15 +635,15 @@ abuseReported: "内容が送信されました。ご報告ありがとうござ
reporter: "通報者" reporter: "通報者"
reporteeOrigin: "通報先" reporteeOrigin: "通報先"
reporterOrigin: "通報元" reporterOrigin: "通報元"
forwardReport: "リモートインスタンスに通報を転送する" forwardReport: "リモートサーバーに通報を転送する"
forwardReportIsAnonymous: "リモートインスタンスからはあなたの情報は見れず、匿名のシステムアカウントとして表示されます。" forwardReportIsAnonymous: "リモートサーバーからはあなたの情報は見れず、匿名のシステムアカウントとして表示されます。"
send: "送信" send: "送信"
abuseMarkAsResolved: "対応済みにする" abuseMarkAsResolved: "対応済みにする"
openInNewTab: "新しいタブで開く" openInNewTab: "新しいタブで開く"
openInSideView: "サイドビューで開く" openInSideView: "サイドビューで開く"
defaultNavigationBehaviour: "デフォルトのナビゲーション" defaultNavigationBehaviour: "デフォルトのナビゲーション"
editTheseSettingsMayBreakAccount: "これらの設定を編集するとアカウントが破損する可能性があります。" editTheseSettingsMayBreakAccount: "これらの設定を編集するとアカウントが破損する可能性があります。"
instanceTicker: "ノートのインスタンス情報" instanceTicker: "ノートのサーバー情報"
waitingFor: "{x}を待っています" waitingFor: "{x}を待っています"
random: "ランダム" random: "ランダム"
system: "システム" system: "システム"
@@ -741,7 +732,7 @@ capacity: "容量"
inUse: "使用中" inUse: "使用中"
editCode: "コードを編集" editCode: "コードを編集"
apply: "適用" apply: "適用"
receiveAnnouncementFromInstance: "インスタンスからのお知らせを受け取る" receiveAnnouncementFromInstance: "サーバーからのお知らせを受け取る"
emailNotification: "メール通知" emailNotification: "メール通知"
publish: "公開" publish: "公開"
inChannelSearch: "チャンネル内検索" inChannelSearch: "チャンネル内検索"
@@ -769,7 +760,7 @@ active: "アクティブ"
offline: "オフライン" offline: "オフライン"
notRecommended: "非推奨" notRecommended: "非推奨"
botProtection: "Botプロテクション" botProtection: "Botプロテクション"
instanceBlocking: "インスタンスブロック" instanceBlocking: "サーバーブロック"
selectAccount: "アカウントを選択" selectAccount: "アカウントを選択"
switchAccount: "アカウントを切り替え" switchAccount: "アカウントを切り替え"
enabled: "有効" enabled: "有効"
@@ -789,6 +780,7 @@ popularPosts: "人気の投稿"
shareWithNote: "ノートで共有" shareWithNote: "ノートで共有"
ads: "広告" ads: "広告"
expiration: "期限" expiration: "期限"
startingperiod: "開始期間"
memo: "メモ" memo: "メモ"
priority: "優先度" priority: "優先度"
high: "高" high: "高"
@@ -821,6 +813,7 @@ lastCommunication: "直近の通信"
resolved: "解決済み" resolved: "解決済み"
unresolved: "未解決" unresolved: "未解決"
breakFollow: "フォロワーを解除" breakFollow: "フォロワーを解除"
breakFollowConfirm: "フォロワー解除しますか?"
itsOn: "オンになっています" itsOn: "オンになっています"
itsOff: "オフになっています" itsOff: "オフになっています"
emailRequiredForSignup: "アカウント登録にメールアドレスを必須にする" emailRequiredForSignup: "アカウント登録にメールアドレスを必須にする"
@@ -840,8 +833,6 @@ deleteAccountConfirm: "アカウントが削除されます。よろしいです
incorrectPassword: "パスワードが間違っています。" incorrectPassword: "パスワードが間違っています。"
voteConfirm: "「{choice}」に投票しますか?" voteConfirm: "「{choice}」に投票しますか?"
hide: "隠す" hide: "隠す"
leaveGroup: "グループから抜ける"
leaveGroupConfirm: "「{name}」から抜けますか?"
useDrawerReactionPickerForMobile: "モバイルデバイスのときドロワーで表示" useDrawerReactionPickerForMobile: "モバイルデバイスのときドロワーで表示"
welcomeBackWithName: "おかえりなさい、{name}さん" welcomeBackWithName: "おかえりなさい、{name}さん"
clickToFinishEmailVerification: "[{ok}]を押して、メールアドレスの確認を完了してください。" clickToFinishEmailVerification: "[{ok}]を押して、メールアドレスの確認を完了してください。"
@@ -853,15 +844,17 @@ themeColor: "テーマカラー"
size: "サイズ" size: "サイズ"
numberOfColumn: "列の数" numberOfColumn: "列の数"
searchByGoogle: "検索" searchByGoogle: "検索"
instanceDefaultLightTheme: "インスタンスデフォルトのライトテーマ" instanceDefaultLightTheme: "サーバーデフォルトのライトテーマ"
instanceDefaultDarkTheme: "インスタンスデフォルトのダークテーマ" instanceDefaultDarkTheme: "サーバーデフォルトのダークテーマ"
instanceDefaultThemeDescription: "オブジェクト形式のテーマコードを記入します。" instanceDefaultThemeDescription: "オブジェクト形式のテーマコードを記入します。"
mutePeriod: "ミュートする期限" mutePeriod: "ミュートする期限"
period: "期限"
indefinitely: "無期限" indefinitely: "無期限"
tenMinutes: "10分" tenMinutes: "10分"
oneHour: "1時間" oneHour: "1時間"
oneDay: "1日" oneDay: "1日"
oneWeek: "1週間" oneWeek: "1週間"
oneMonth: "1ヶ月"
reflectMayTakeTime: "反映されるまで時間がかかる場合があります。" reflectMayTakeTime: "反映されるまで時間がかかる場合があります。"
failedToFetchAccountInformation: "アカウント情報の取得に失敗しました" failedToFetchAccountInformation: "アカウント情報の取得に失敗しました"
rateLimitExceeded: "レート制限を超えました" rateLimitExceeded: "レート制限を超えました"
@@ -905,7 +898,7 @@ cannotUploadBecauseInappropriate: "不適切な内容を含む可能性がある
cannotUploadBecauseNoFreeSpace: "ドライブの空き容量が無いためアップロードできません。" cannotUploadBecauseNoFreeSpace: "ドライブの空き容量が無いためアップロードできません。"
beta: "ベータ" beta: "ベータ"
enableAutoSensitive: "自動NSFW判定" enableAutoSensitive: "自動NSFW判定"
enableAutoSensitiveDescription: "利用可能な場合は、機械学習を利用して自動でメディアにNSFWフラグを設定します。この機能をオフにしても、インスタンスによっては自動で設定されることがあります。" enableAutoSensitiveDescription: "利用可能な場合は、機械学習を利用して自動でメディアにNSFWフラグを設定します。この機能をオフにしても、サーバーによっては自動で設定されることがあります。"
activeEmailValidationDescription: "ユーザーのメールアドレスのバリデーションを、捨てアドかどうかや実際に通信可能かどうかなどを判定しより積極的に行います。オフにすると単に文字列として正しいかどうかのみチェックされます。" activeEmailValidationDescription: "ユーザーのメールアドレスのバリデーションを、捨てアドかどうかや実際に通信可能かどうかなどを判定しより積極的に行います。オフにすると単に文字列として正しいかどうかのみチェックされます。"
navbar: "ナビゲーションバー" navbar: "ナビゲーションバー"
shuffle: "シャッフル" shuffle: "シャッフル"
@@ -915,7 +908,7 @@ pushNotification: "プッシュ通知"
subscribePushNotification: "プッシュ通知を有効化" subscribePushNotification: "プッシュ通知を有効化"
unsubscribePushNotification: "プッシュ通知を停止する" unsubscribePushNotification: "プッシュ通知を停止する"
pushNotificationAlreadySubscribed: "プッシュ通知は有効です" pushNotificationAlreadySubscribed: "プッシュ通知は有効です"
pushNotificationNotSupported: "ブラウザかインスタンスがプッシュ通知に非対応" pushNotificationNotSupported: "ブラウザかサーバーがプッシュ通知に非対応"
sendPushNotificationReadMessage: "通知やメッセージが既読になったらプッシュ通知を削除する" sendPushNotificationReadMessage: "通知やメッセージが既読になったらプッシュ通知を削除する"
sendPushNotificationReadMessageCaption: "「{emptyPushNotificationMessage}」という通知が一瞬表示されるようになります。端末の電池消費量が増加する可能性があります。" sendPushNotificationReadMessageCaption: "「{emptyPushNotificationMessage}」という通知が一瞬表示されるようになります。端末の電池消費量が増加する可能性があります。"
windowMaximize: "最大化" windowMaximize: "最大化"
@@ -957,6 +950,11 @@ collapseRenotes: "見たことのあるRenoteを省略して表示"
internalServerError: "サーバー内部エラー" internalServerError: "サーバー内部エラー"
internalServerErrorDescription: "サーバー内部で予期しないエラーが発生しました。" internalServerErrorDescription: "サーバー内部で予期しないエラーが発生しました。"
copyErrorInfo: "エラー情報をコピー" copyErrorInfo: "エラー情報をコピー"
joinThisServer: "このサーバーに登録する"
exploreOtherServers: "他のサーバーを探す"
letsLookAtTimeline: "タイムラインを見てみる"
disableFederationWarn: "連合が無効になっています。無効にしても投稿が非公開にはなりません。ほとんどの場合、このオプションを有効にする必要はありません。"
invitationRequiredToRegister: "現在このサーバーは招待制です。招待コードをお持ちの方のみ登録できます。"
_achievements: _achievements:
earnedAt: "獲得日時" earnedAt: "獲得日時"
@@ -1148,7 +1146,7 @@ _achievements:
description: "ホームタイムラインの流速が20npmを越す" description: "ホームタイムラインの流速が20npmを越す"
_viewInstanceChart: _viewInstanceChart:
title: "アナリスト" title: "アナリスト"
description: "インスタンスのチャートを表示した" description: "サーバーのチャートを表示した"
_outputHelloWorldOnScratchpad: _outputHelloWorldOnScratchpad:
title: "Hello, world!" title: "Hello, world!"
description: "スクラッチパッドで hello world を出力した" description: "スクラッチパッドで hello world を出力した"
@@ -1185,7 +1183,7 @@ _achievements:
_loggedInOnNewYearsDay: _loggedInOnNewYearsDay:
title: "あけましておめでとうございます" title: "あけましておめでとうございます"
description: "元日にログインした" description: "元日にログインした"
flavor: "今年も弊インスタンスをよろしくお願いします" flavor: "今年も弊サーバーをよろしくお願いします"
_cookieClicked: _cookieClicked:
title: "クッキーをクリックするゲーム" title: "クッキーをクリックするゲーム"
description: "クッキーをクリックした" description: "クッキーをクリックした"
@@ -1201,7 +1199,7 @@ _role:
name: "ロール名" name: "ロール名"
description: "ロールの説明" description: "ロールの説明"
permission: "ロールの権限" permission: "ロールの権限"
descriptionOfPermission: "<b>モデレーター</b>は基本的なモデレーションに関する操作を行えます。\n<b>管理者</b>はインスタンスの全ての設定を変更できます。" descriptionOfPermission: "<b>モデレーター</b>は基本的なモデレーションに関する操作を行えます。\n<b>管理者</b>はサーバーの全ての設定を変更できます。"
assignTarget: "アサイン" assignTarget: "アサイン"
descriptionOfAssignTarget: "<b>マニュアル</b>は誰がこのロールに含まれるかを手動で管理します。\n<b>コンディショナル</b>は条件を設定し、それに合致するユーザーが自動で含まれるようになります。" descriptionOfAssignTarget: "<b>マニュアル</b>は誰がこのロールに含まれるかを手動で管理します。\n<b>コンディショナル</b>は条件を設定し、それに合致するユーザーが自動で含まれるようになります。"
manual: "マニュアル" manual: "マニュアル"
@@ -1229,7 +1227,7 @@ _role:
gtlAvailable: "グローバルタイムラインの閲覧" gtlAvailable: "グローバルタイムラインの閲覧"
ltlAvailable: "ローカルタイムラインの閲覧" ltlAvailable: "ローカルタイムラインの閲覧"
canPublicNote: "パブリック投稿の許可" canPublicNote: "パブリック投稿の許可"
canInvite: "インスタンス招待コードの発行" canInvite: "サーバー招待コードの発行"
canManageCustomEmojis: "カスタム絵文字の管理" canManageCustomEmojis: "カスタム絵文字の管理"
driveCapacity: "ドライブ容量" driveCapacity: "ドライブ容量"
pinMax: "ノートのピン留めの最大数" pinMax: "ノートのピン留めの最大数"
@@ -1298,7 +1296,7 @@ _ad:
_forgotPassword: _forgotPassword:
enterEmail: "アカウントに登録したメールアドレスを入力してください。そのアドレス宛てに、パスワードリセット用のリンクが送信されます。" enterEmail: "アカウントに登録したメールアドレスを入力してください。そのアドレス宛てに、パスワードリセット用のリンクが送信されます。"
ifNoEmail: "メールアドレスを登録していない場合は、管理者までお問い合わせください。" ifNoEmail: "メールアドレスを登録していない場合は、管理者までお問い合わせください。"
contactAdmin: "このインスタンスではメールがサポートされていないため、パスワードリセットを行う場合は管理者までお問い合わせください。" contactAdmin: "このサーバーではメールがサポートされていないため、パスワードリセットを行う場合は管理者までお問い合わせください。"
_gallery: _gallery:
my: "自分の投稿" my: "自分の投稿"
@@ -1396,10 +1394,10 @@ _wordMute:
mutedNotes: "ミュートされたノート" mutedNotes: "ミュートされたノート"
_instanceMute: _instanceMute:
instanceMuteDescription: "ミュートしたインスタンスのユーザーへの返信を含めて、設定したインスタンスの全てのートとRenoteをミュートします。" instanceMuteDescription: "ミュートしたサーバーのユーザーへの返信を含めて、設定したサーバーの全てのートとRenoteをミュートします。"
instanceMuteDescription2: "改行で区切って設定します" instanceMuteDescription2: "改行で区切って設定します"
title: "設定したインスタンスのノートを隠します。" title: "設定したサーバーのノートを隠します。"
heading: "ミュートするインスタンス" heading: "ミュートするサーバー"
_theme: _theme:
explore: "テーマを探す" explore: "テーマを探す"
@@ -1496,6 +1494,7 @@ _ago:
weeksAgo: "{n}週間前" weeksAgo: "{n}週間前"
monthsAgo: "{n}ヶ月前" monthsAgo: "{n}ヶ月前"
yearsAgo: "{n}年前" yearsAgo: "{n}年前"
invalid: "ありません"
_time: _time:
second: "秒" second: "秒"
@@ -1532,14 +1531,29 @@ _tutorial:
_2fa: _2fa:
alreadyRegistered: "既に設定は完了しています。" alreadyRegistered: "既に設定は完了しています。"
registerDevice: "デバイスを登録" registerTOTP: "認証アプリの設定を開始"
registerKey: "キーを登録" passwordToTOTP: "パスワードを入力してください"
step1: "まず、{a}や{b}などの認証アプリをお使いのデバイスにインストールします。" step1: "まず、{a}や{b}などの認証アプリをお使いのデバイスにインストールします。"
step2: "次に、表示されているQRコードをアプリでスキャンします。" step2: "次に、表示されているQRコードをアプリでスキャンします。"
step2Url: "デスクトップアプリでは次のURLを入力します:" step2Click: "QRコードをクリックすると、お使いの端末にインストールされている認証アプリやキーリングに登録できます"
step3: "アプリに表示されているトークンを入力して完了です。" step2Url: "デスクトップアプリでは次のURIを入力します:"
step4: "これからログインするときも、同じようにトークンを入力します。" step3Title: "確認コードを入力"
securityKeyInfo: "FIDO2をサポートするハードウェアセキュリティキーもしくは端末の指紋認証やPINを使用してログインするように設定できます。" step3: "アプリに表示されている確認コード(トークン)を入力して完了です。"
step4: "これからログインするときも、同じように確認コードを入力します。"
securityKeyNotSupported: "お使いのブラウザはセキュリティキーに対応していません。"
registerTOTPBeforeKey: "セキュリティキー・パスキーを登録するには、まず認証アプリの設定を行なってください。"
securityKeyInfo: "FIDO2をサポートするハードウェアセキュリティキー、端末の生体認証やPINロック、パスキーといった、WebAuthn由来の鍵を登録します。"
chromePasskeyNotSupported: "Chromeのパスキーは現在サポートしていません。"
registerSecurityKey: "セキュリティキー・パスキーを登録する"
securityKeyName: "キーの名前を入力"
tapSecurityKey: "ブラウザの指示に従い、セキュリティキーやパスキーを登録してください"
removeKey: "セキュリティキーを削除"
removeKeyConfirm: "{name}を削除しますか?"
whyTOTPOnlyRenew: "セキュリティキーが登録されている場合、認証アプリの設定は解除できません。"
renewTOTP: "認証アプリを再設定"
renewTOTPConfirm: "今までの認証アプリの確認コードは使用できなくなります"
renewTOTPOk: "再設定する"
renewTOTPCancel: "やめておく"
_permissions: _permissions:
"read:account": "アカウントの情報を見る" "read:account": "アカウントの情報を見る"
@@ -1591,7 +1605,6 @@ _antennaSources:
homeTimeline: "フォローしているユーザーのノート" homeTimeline: "フォローしているユーザーのノート"
users: "指定した一人または複数のユーザーのノート" users: "指定した一人または複数のユーザーのノート"
userList: "指定したリストのユーザーのノート" userList: "指定したリストのユーザーのノート"
userGroup: "指定したグループのユーザーのノート"
_weekday: _weekday:
sunday: "日曜日" sunday: "日曜日"
@@ -1604,7 +1617,7 @@ _weekday:
_widgets: _widgets:
profile: "プロフィール" profile: "プロフィール"
instanceInfo: "インスタンス情報" instanceInfo: "サーバー情報"
memo: "付箋" memo: "付箋"
notifications: "通知" notifications: "通知"
timeline: "タイムライン" timeline: "タイムライン"
@@ -1618,7 +1631,7 @@ _widgets:
digitalClock: "デジタル時計" digitalClock: "デジタル時計"
unixClock: "UNIX時計" unixClock: "UNIX時計"
federation: "連合" federation: "連合"
instanceCloud: "インスタンスクラウド" instanceCloud: "サーバークラウド"
postForm: "投稿フォーム" postForm: "投稿フォーム"
slideshow: "スライドショー" slideshow: "スライドショー"
button: "ボタン" button: "ボタン"
@@ -1671,8 +1684,8 @@ _visibility:
followersDescription: "自分のフォロワーのみに公開" followersDescription: "自分のフォロワーのみに公開"
specified: "ダイレクト" specified: "ダイレクト"
specifiedDescription: "指定したユーザーのみに公開" specifiedDescription: "指定したユーザーのみに公開"
localOnly: "ローカルのみ" disableFederation: "連合なし"
localOnlyDescription: "リモートユーザーには非公開" disableFederationDescription: "他サーバーへの配信を行いません"
_postForm: _postForm:
replyPlaceholder: "このノートに返信..." replyPlaceholder: "このノートに返信..."
@@ -1821,12 +1834,9 @@ _notification:
youGotReply: "{name}からのリプライ" youGotReply: "{name}からのリプライ"
youGotQuote: "{name}による引用" youGotQuote: "{name}による引用"
youRenoted: "{name}がRenoteしました" youRenoted: "{name}がRenoteしました"
youGotMessagingMessageFromUser: "{name}からのチャットがあります"
youGotMessagingMessageFromGroup: "{name}のチャットがあります"
youWereFollowed: "フォローされました" youWereFollowed: "フォローされました"
youReceivedFollowRequest: "フォローリクエストが来ました" youReceivedFollowRequest: "フォローリクエストが来ました"
yourFollowRequestAccepted: "フォローリクエストが承認されました" yourFollowRequestAccepted: "フォローリクエストが承認されました"
youWereInvitedToGroup: "{userName}があなたをグループに招待しました"
pollEnded: "アンケートの結果が出ました" pollEnded: "アンケートの結果が出ました"
unreadAntennaNote: "アンテナ {name}" unreadAntennaNote: "アンテナ {name}"
emptyPushNotificationMessage: "プッシュ通知の更新をしました" emptyPushNotificationMessage: "プッシュ通知の更新をしました"
@@ -1843,7 +1853,7 @@ _notification:
pollEnded: "アンケートが終了" pollEnded: "アンケートが終了"
receiveFollowRequest: "フォロー申請を受け取った" receiveFollowRequest: "フォロー申請を受け取った"
followRequestAccepted: "フォローが受理された" followRequestAccepted: "フォローが受理された"
groupInvited: "グループに招待された" achievementEarned: "実績の獲得"
app: "連携アプリからの通知" app: "連携アプリからの通知"
_actions: _actions:
@@ -1879,3 +1889,7 @@ _deck:
channel: "チャンネル" channel: "チャンネル"
mentions: "あなた宛て" mentions: "あなた宛て"
direct: "ダイレクト" direct: "ダイレクト"
_dialog:
charactersExceeded: "最大文字数を超えています! 現在 {current} / 制限 {max}"
charactersBelow: "最小文字数を下回っています! 現在 {current} / 制限 {min}"

View File

@@ -67,7 +67,7 @@ import: "インポート"
export: "エクスポート" export: "エクスポート"
files: "ファイル" files: "ファイル"
download: "ダウンロード" download: "ダウンロード"
driveFileDeleteConfirm: "ファイル「{name}」を消してしもうてええか?このファイルを添付したノートも消えてまうで。" driveFileDeleteConfirm: "ファイル「{name}」をほかしてええか?このファイルを添付したノートも消えてまうで。"
unfollowConfirm: "{name}のフォローを解除してもええんか?" unfollowConfirm: "{name}のフォローを解除してもええんか?"
exportRequested: "エクスポートしてな、ってリクエストしたけど、これ多分めっちゃ時間かかるで。エクスポート終わったら「ドライブ」に突っ込んどくで。" exportRequested: "エクスポートしてな、ってリクエストしたけど、これ多分めっちゃ時間かかるで。エクスポート終わったら「ドライブ」に突っ込んどくで。"
importRequested: "インポートしてな、ってリクエストしたけど、これ多分めっちゃ時間かかるで。" importRequested: "インポートしてな、ってリクエストしたけど、これ多分めっちゃ時間かかるで。"
@@ -83,7 +83,7 @@ manageLists: "リストの管理"
error: "エラー" error: "エラー"
somethingHappened: "なんかアカンことが起こったで" somethingHappened: "なんかアカンことが起こったで"
retry: "もっぺんやる?" retry: "もっぺんやる?"
pageLoadError: "ページの読み込みに失敗してもうた…" pageLoadError: "ページの読み込みに失敗してもうた…"
pageLoadErrorDescription: "これは普通、ネットワークかブラウザキャッシュが原因やからね。キャッシュをクリアするか、もうちっとだけ待ってくれへんか?" pageLoadErrorDescription: "これは普通、ネットワークかブラウザキャッシュが原因やからね。キャッシュをクリアするか、もうちっとだけ待ってくれへんか?"
serverIsDead: "サーバーからの応答がないで。もうちょい待ってから試してみてな。" serverIsDead: "サーバーからの応答がないで。もうちょい待ってから試してみてな。"
youShouldUpgradeClient: "このページを表示するには、リロードして新しいバージョンのクライアントを使ってなー。" youShouldUpgradeClient: "このページを表示するには、リロードして新しいバージョンのクライアントを使ってなー。"
@@ -103,6 +103,8 @@ renoted: "Renoteしたで。"
cantRenote: "この投稿はRenoteできへんらしい。" cantRenote: "この投稿はRenoteできへんらしい。"
cantReRenote: "Renote自体はRenoteできへんで。" cantReRenote: "Renote自体はRenoteできへんで。"
quote: "引用" quote: "引用"
inChannelRenote: "チャンネル内Renote"
inChannelQuote: "チャンネル内引用"
pinnedNote: "ピン留めされとるノート" pinnedNote: "ピン留めされとるノート"
pinned: "ピン留めしとく" pinned: "ピン留めしとく"
you: "あんた" you: "あんた"
@@ -151,7 +153,7 @@ flagShowTimelineReplies: "タイムラインにノートへの返信を表示す
flagShowTimelineRepliesDescription: "オンにしたら、タイムラインにユーザーのノートの他にもそのユーザーの他のノートへの返信を表示するで。" flagShowTimelineRepliesDescription: "オンにしたら、タイムラインにユーザーのノートの他にもそのユーザーの他のノートへの返信を表示するで。"
autoAcceptFollowed: "フォローしとるユーザーからのフォローリクエストを勝手に許可しとく" autoAcceptFollowed: "フォローしとるユーザーからのフォローリクエストを勝手に許可しとく"
addAccount: "アカウントを追加" addAccount: "アカウントを追加"
loginFailed: "ログインに失敗してもうた…" loginFailed: "ログインに失敗してもうた…"
showOnRemote: "リモートで見る" showOnRemote: "リモートで見る"
general: "全般" general: "全般"
wallpaper: "壁紙" wallpaper: "壁紙"
@@ -243,7 +245,7 @@ resetAreYouSure: "リセットしてええん?"
saved: "保存したで!" saved: "保存したで!"
messaging: "チャット" messaging: "チャット"
upload: "アップロード" upload: "アップロード"
keepOriginalUploading: "オリジナル画像を保持する" keepOriginalUploading: "オリジナル画像を保持する"
keepOriginalUploadingDescription: "画像を上げるときにオリジナル版を保持するで。オフにしたら上げたときにブラウザでWeb公開用の画像を生成するで。 " keepOriginalUploadingDescription: "画像を上げるときにオリジナル版を保持するで。オフにしたら上げたときにブラウザでWeb公開用の画像を生成するで。 "
fromDrive: "ドライブから" fromDrive: "ドライブから"
fromUrl: "URLから" fromUrl: "URLから"
@@ -391,16 +393,19 @@ about: "情報"
aboutMisskey: "Misskeyってなんや" aboutMisskey: "Misskeyってなんや"
administrator: "管理者" administrator: "管理者"
token: "トークン" token: "トークン"
twoStepAuthentication: "二段階認証" 2fa: "二要素認証"
totp: "認証アプリ"
totpDescription: "認証アプリ使てワンタイムパスワードを入れる"
moderator: "モデレーター" moderator: "モデレーター"
moderation: "モデレーション" moderation: "モデレーション"
nUsersMentioned: "{n}人が投稿" nUsersMentioned: "{n}人が投稿"
securityKeyAndPasskey: "セキュリティキー・パスキー"
securityKey: "セキュリティキー" securityKey: "セキュリティキー"
securityKeyName: "キーの名前"
registerSecurityKey: "セキュリティキーを登録するで"
lastUsed: "最後につこうた日" lastUsed: "最後につこうた日"
lastUsedAt: "最後に使たん: {t}"
unregister: "登録やめる" unregister: "登録やめる"
passwordLessLogin: "パスワード無くてもログインできるようにする" passwordLessLogin: "パスワード無くてもログインできるようにする"
passwordLessLoginDescription: "パスワードやなくて、セキュリティキーとかパスキーだけでログインするわ"
resetPassword: "パスワードをリセット" resetPassword: "パスワードをリセット"
newPasswordIs: "今度のパスワードは「{password}」や" newPasswordIs: "今度のパスワードは「{password}」や"
reduceUiAnimation: "UIの動きやアニメーションを減らす" reduceUiAnimation: "UIの動きやアニメーションを減らす"
@@ -415,24 +420,15 @@ markAsReadAllTalkMessages: "チャットはもうぜんぶ読んだわっ"
help: "ヘルプ" help: "ヘルプ"
inputMessageHere: "ここにメッセージ書いてや" inputMessageHere: "ここにメッセージ書いてや"
close: "閉じる" close: "閉じる"
group: "グループ"
groups: "グループ"
createGroup: "グループを作るで"
ownedGroups: "所有しとるグループ"
joinedGroups: "参加しとるグループ"
invites: "来てや" invites: "来てや"
groupName: "グループ名"
members: "メンバー" members: "メンバー"
transfer: "譲渡" transfer: "譲渡"
messagingWithUser: "ユーザーとチャット"
messagingWithGroup: "グループでチャット"
title: "タイトル" title: "タイトル"
text: "テキスト" text: "テキスト"
enable: "有効にするで" enable: "有効にするで"
next: "次" next: "次"
retype: "もっかい入力" retype: "もっかい入力"
noteOf: "{user}のノート" noteOf: "{user}のノート"
inviteToGroup: "グループに招く"
quoteAttached: "引用付いとるで" quoteAttached: "引用付いとるで"
quoteQuestion: "引用として添付してもええか?" quoteQuestion: "引用として添付してもええか?"
noMessagesYet: "まだチャットはあらへんで" noMessagesYet: "まだチャットはあらへんで"
@@ -454,17 +450,14 @@ passwordMatched: "よし!一致や!"
passwordNotMatched: "一致しとらんで?" passwordNotMatched: "一致しとらんで?"
signinWith: "{x}でログイン" signinWith: "{x}でログイン"
signinFailed: "ログインできんかったで。もっかいユーザー名とパスワードを確認してみてな。" signinFailed: "ログインできんかったで。もっかいユーザー名とパスワードを確認してみてな。"
tapSecurityKey: "セキュリティキーにタッチしてな"
or: "それか" or: "それか"
language: "言語" language: "言語"
uiLanguage: "UIの表示言語" uiLanguage: "UIの表示言語"
groupInvited: "グループに招待されとるで"
aboutX: "{x}について" aboutX: "{x}について"
emojiStyle: "絵文字のスタイル" emojiStyle: "絵文字のスタイル"
native: "ネイティブ" native: "ネイティブ"
disableDrawer: "メニューをドロワーで表示せぇへん" disableDrawer: "メニューをドロワーで表示せぇへん"
youHaveNoGroups: "グループがあらへんねぇ。" showNoteActionsOnlyHover: "ノートの操作部をホバー時のみ表示するで"
joinOrCreateGroup: "既存のグループに招待してもらうか、新しくグループ作ってからやってな"
noHistory: "履歴はあらへんねぇ。" noHistory: "履歴はあらへんねぇ。"
signinHistory: "ログイン履歴" signinHistory: "ログイン履歴"
enableAdvancedMfm: "ややこしいMFMもありにする" enableAdvancedMfm: "ややこしいMFMもありにする"
@@ -589,7 +582,7 @@ generateAccessToken: "アクセストークンの発行"
permission: "権限" permission: "権限"
enableAll: "全部使えるようにする" enableAll: "全部使えるようにする"
disableAll: "全部使えへんようにする" disableAll: "全部使えへんようにする"
tokenRequested: "アカウントへのアクセス許" tokenRequested: "アカウントへのアクセス許してやったらどうや"
pluginTokenRequestedDescription: "このプラグインはここで設定した権限を使えるようになるで。" pluginTokenRequestedDescription: "このプラグインはここで設定した権限を使えるようになるで。"
notificationType: "通知の種類" notificationType: "通知の種類"
edit: "編集" edit: "編集"
@@ -787,6 +780,7 @@ popularPosts: "人気の投稿"
shareWithNote: "ノートで共有" shareWithNote: "ノートで共有"
ads: "広告" ads: "広告"
expiration: "期限" expiration: "期限"
startingperiod: "始めた期間"
memo: "メモ" memo: "メモ"
priority: "優先度" priority: "優先度"
high: "高い" high: "高い"
@@ -819,6 +813,7 @@ lastCommunication: "直近の通信"
resolved: "解決したで" resolved: "解決したで"
unresolved: "まだ解決してないで" unresolved: "まだ解決してないで"
breakFollow: "フォロワーを解除するで" breakFollow: "フォロワーを解除するで"
breakFollowConfirm: "フォロワー解除してもええか?"
itsOn: "オンになっとるよ" itsOn: "オンになっとるよ"
itsOff: "オフになってるで" itsOff: "オフになってるで"
emailRequiredForSignup: "アカウント登録にメールアドレスを必須にするで" emailRequiredForSignup: "アカウント登録にメールアドレスを必須にするで"
@@ -838,10 +833,8 @@ deleteAccountConfirm: "アカウントを消すで?ええんか?"
incorrectPassword: "パスワードがちゃうで。" incorrectPassword: "パスワードがちゃうで。"
voteConfirm: "「{choice}」に投票するんか?" voteConfirm: "「{choice}」に投票するんか?"
hide: "隠す" hide: "隠す"
leaveGroup: "グループから抜けるで"
leaveGroupConfirm: "「{name}」から抜けるん?"
useDrawerReactionPickerForMobile: "ケータイとかのときドロワーで表示するで" useDrawerReactionPickerForMobile: "ケータイとかのときドロワーで表示するで"
welcomeBackWithName: "まいど、{name}ん" welcomeBackWithName: "まいど、{name}ん"
clickToFinishEmailVerification: "[{ok}]を押してメアドの確認を終わらせてなー" clickToFinishEmailVerification: "[{ok}]を押してメアドの確認を終わらせてなー"
overridedDeviceKind: "デバイスタイプ" overridedDeviceKind: "デバイスタイプ"
smartphone: "スマホ" smartphone: "スマホ"
@@ -855,11 +848,13 @@ instanceDefaultLightTheme: "インスタンスの最初の明るいテーマ"
instanceDefaultDarkTheme: "インスタンスの最初の暗いテーマ" instanceDefaultDarkTheme: "インスタンスの最初の暗いテーマ"
instanceDefaultThemeDescription: "オブジェクト形式のテーマコードを記入するで。" instanceDefaultThemeDescription: "オブジェクト形式のテーマコードを記入するで。"
mutePeriod: "ミュートする期間" mutePeriod: "ミュートする期間"
period: "期限"
indefinitely: "無期限" indefinitely: "無期限"
tenMinutes: "10分" tenMinutes: "10分"
oneHour: "1時間" oneHour: "1時間"
oneDay: "1日" oneDay: "1日"
oneWeek: "1週間" oneWeek: "1週間"
oneMonth: "1ヶ月"
reflectMayTakeTime: "反映されるまで時間がかかることがあるで" reflectMayTakeTime: "反映されるまで時間がかかることがあるで"
failedToFetchAccountInformation: "アカウントの取得に失敗したみたいや…" failedToFetchAccountInformation: "アカウントの取得に失敗したみたいや…"
rateLimitExceeded: "レート制限が超えたみたいやで" rateLimitExceeded: "レート制限が超えたみたいやで"
@@ -898,7 +893,7 @@ fast: "速い"
sensitiveMediaDetection: "センシティブなメディアの検出" sensitiveMediaDetection: "センシティブなメディアの検出"
localOnly: "ローカルのみ" localOnly: "ローカルのみ"
remoteOnly: "リモートのみ" remoteOnly: "リモートのみ"
failedToUpload: "アップロードに失敗したで" failedToUpload: "アップロードに失敗してもうたわ…"
cannotUploadBecauseInappropriate: "不適切な内容を含むかもしれへんって判定されたでアップロードできまへん。" cannotUploadBecauseInappropriate: "不適切な内容を含むかもしれへんって判定されたでアップロードできまへん。"
cannotUploadBecauseNoFreeSpace: "ドライブの空き容量が無いでアップロードできまへん。" cannotUploadBecauseNoFreeSpace: "ドライブの空き容量が無いでアップロードできまへん。"
beta: "ベータ" beta: "ベータ"
@@ -948,35 +943,254 @@ achievements: "実績"
gotInvalidResponseError: "サーバー黙っとるわ、知らんけど" gotInvalidResponseError: "サーバー黙っとるわ、知らんけど"
gotInvalidResponseErrorDescription: "サーバーいま日曜日。またきて月曜日。" gotInvalidResponseErrorDescription: "サーバーいま日曜日。またきて月曜日。"
thisPostMayBeAnnoying: "この投稿は迷惑かもしらんで。" thisPostMayBeAnnoying: "この投稿は迷惑かもしらんで。"
thisPostMayBeAnnoyingHome: "ホームに投稿"
thisPostMayBeAnnoyingCancel: "やめとく"
thisPostMayBeAnnoyingIgnore: "このまま投稿"
collapseRenotes: "見たことあるRenoteは省略やで" collapseRenotes: "見たことあるRenoteは省略やで"
internalServerError: "サーバー内部エラー"
internalServerErrorDescription: "サーバー内部でよう分からんエラーやわ"
copyErrorInfo: "エラー情報をコピー"
joinThisServer: "このサーバーに登録するわ"
exploreOtherServers: "他のサーバー見てみる"
letsLookAtTimeline: "タイムライン見てみーや"
disableFederationWarn: "連合が無効になっとるで。無効にしても投稿は非公開ってわけちゃうねん。大体の場合はこのオプションを有効にする必要は別にないで。"
invitationRequiredToRegister: "今このサーバー招待制になってもうてんねん。招待コードを持っとるんやったら登録できるで。"
_achievements: _achievements:
earnedAt: "貰った日ぃ" earnedAt: "貰った日ぃ"
_types: _types:
_notes1: _notes1:
title: "まいど!" title: "まいど!"
description: "初めてノート投稿したった" description: "初めてノート投稿したった"
flavor: "Misskeyを楽しんでな"
_notes10: _notes10:
title: "ノートの天保山" title: "ノートの天保山"
description: "ートを10回投稿した"
_notes100: _notes100:
title: "ノートの真田山" title: "ノートの真田山"
description: "ートを100回投稿した"
_notes500: _notes500:
title: "ノートの生駒山" title: "ノートの生駒山"
description: "ートを500回投稿した"
_notes1000:
title: "ノートの山"
description: "ートを1,000回投稿した"
_notes5000: _notes5000:
title: "箕面の滝からノート" title: "箕面の滝からノート"
description: "ートを5,000回投稿した"
_notes10000:
title: "スーパーノート"
description: "ートを10,000回投稿した"
_notes20000:
title: "ニードモアノート"
description: "ートを20,000回投稿した"
_notes30000:
title: "ノートノートノート"
description: "ートを30,000回投稿した"
_notes40000:
title: "ノート工場"
description: "ートを40,000回投稿した"
_notes50000:
title: "ノートの惑星"
description: "ートを50,000回投稿した"
_notes60000:
title: "ノートクエーサー"
description: "ートを60,000回投稿した"
_notes70000:
title: "ブラックノートホール"
description: "ートを70,000回投稿した"
_notes80000:
title: "ノートギャラクシー"
description: "ートを80,000回投稿した"
_notes90000:
title: "ノートバース"
description: "ートを90,000回投稿した"
_notes100000:
title: "ALL YOUR NOTE ARE BELONG TO US"
description: "ートを100,000回投稿した"
flavor: "そんなに書くことあるんか?"
_login3: _login3:
title: "ビギナーⅠ"
description: "通算3日ログインした"
flavor: "今日からワシはミスキストやで" flavor: "今日からワシはミスキストやで"
_login7:
title: "ビギナーⅡ"
description: "通算7日ログインした"
flavor: "慣れてきたんちゃう?"
_login15:
title: "ビギナーⅢ"
description: "通算15日ログインした"
_login30:
title: "ミスキストⅠ"
description: "通算30日ログインした"
_login60:
title: "ミスキストⅡ"
description: "通算60日ログインした"
_login100:
title: "ミスキストⅢ"
description: "通算100日ログインした"
flavor: "そのユーザー、ミスキストにつき"
_login200:
title: "常連さんⅠ"
description: "通算200日ログインした"
_login300:
title: "常連さんⅡ"
description: "通算300日ログインした"
_login400:
title: "常連さんⅢ"
description: "通算400日ログインした"
_login500:
title: "ベテランさんⅠ"
description: "通算500日ログインした"
flavor: "あんたら、うちはノートが好きや"
_login600:
title: "ベテランさんⅡ"
description: "通算600日ログインした"
_login700:
title: "ベテランさんⅢ"
description: "通算700日ログインした"
_login800:
title: "ノートマイスターⅠ"
description: "通算800日ログインした"
_login900:
title: "ノートマイスターⅡ"
description: "通算900日ログインした"
_login1000:
title: "ノートマイスターⅢ"
description: "通算1,000日ログインした"
flavor: "Misskeyようさん使てもろておおきにな"
_noteClipped1:
title: "アカンどれもクリップしたいわ"
description: "初めてノートをクリップした"
_noteFavorited1:
title: "星ぃみるひと"
description: "初めてノートをお気に入りに登録した"
_myNoteFavorited1:
title: "星ぃ欲しい"
description: "ワレのノートが他のひとにお気に入り登録されたで"
_profileFilled:
title: "準備万端や"
description: "プロフィールを設定した"
_markedAsCat:
title: "吾輩は猫やねん"
description: "アカウントがCatになってもうた"
flavor: "名前はまだないねん。"
_following1:
title: "はじめてのフォロー"
description: "初めてフォローした"
_following10:
title: "ついてく、ついてく"
description: "フォローが10人超えた"
_following50:
title: "友達ぎょうさん"
description: "フォローが50人超えた"
_following100:
title: "友達100人"
description: "フォローが100人超えた"
_following300:
title: "いや友達多すぎやろ"
description: "フォローが300人超えた"
_followers1:
title: "はじめてのフォロワー"
description: "初めてフォローされた"
_followers10:
title: "フォローみぃ!"
description: "フォロワーが10人超えた"
_followers50:
title: "ぞろぞろ"
description: "フォロワーが50人超えた"
_followers100:
title: "人気もん"
description: "フォロワーが100人超えた"
_followers300:
title: "ほらそこ一列に並んで!"
description: "フォロワーが300人超えた"
_followers500:
title: "基地局"
description: "フォロワーが500人超えた"
_followers1000:
title: "インフルエンサー"
description: "フォロワーが1,000人超えた"
_collectAchievements30:
title: "実績コレクター"
description: "実績を30個以上獲得した"
_viewAchievements3min:
title: "実績好き"
description: "実績一覧を3分以上眺め続けた"
_iLoveMisskey: _iLoveMisskey:
title: "Misskey好きやねん" title: "Misskey好きやねん"
description: "\"I ❤ #Misskey\"を投稿した"
flavor: "Misskeyを使ってくれてありがとうな by 開発チーム"
_foundTreasure: _foundTreasure:
title: "なんでも鑑定団" title: "なんでも鑑定団"
description: "隠されたお宝を発見した"
_client30min: _client30min:
title: "ねんね" title: "ねんね"
description: "クライアントを起動してから30分以上経過した"
_noteDeletedWithin1min: _noteDeletedWithin1min:
title: "*おおっと*" title: "*おおっと*"
description: "投稿してから1分以内にその投稿を消した"
_postedAtLateNight:
title: "夜行性"
description: "深夜にノートを投稿した"
flavor: "そろそろ寝よか"
_postedAt0min0sec:
title: "時報"
description: "0分0秒にートを投稿した"
flavor: "ポッ ポッ ポッ ピーン"
_selfQuote:
title: "自己言及"
description: "自分のノートを引用した"
_htl20npm:
title: "流れるTL"
description: "ホームタイムラインの流速が20npmを超す"
_viewInstanceChart:
title: "アナリスト"
description: "インスタンスのチャートを表示した"
_outputHelloWorldOnScratchpad:
title: "Hello, world!"
description: "スクラッチパッドで hello worldを出力した"
_open3windows: _open3windows:
title: "マド開けすぎ" title: "マド開けすぎ"
description: "ウィンドウを3つ以上開いた状態にした"
_driveFolderCircularReference: _driveFolderCircularReference:
title: "環状線" title: "環状線"
description: "ドライブのフォルダを再帰的な入れ子にしようとした"
_reactWithoutRead:
title: "ちゃんと読んだんか?"
description: "100文字以上のテキストを含むートに投稿されてから3秒以内にリアクションした"
_clickedClickHere:
title: "ここをクリック"
description: "ここをクリックした"
_justPlainLucky:
title: "単なるラッキー"
description: "10秒ごとに0.005%の確率で獲得"
_setNameToSyuilo:
title: "神様コンプレックス"
description: "名前を syuilo に設定した"
_passedSinceAccountCreated1:
title: "一周年"
description: "アカウント作成から1年経過した"
_passedSinceAccountCreated2:
title: "二周年"
description: "アカウント作成から2年経過した"
_passedSinceAccountCreated3:
title: "三周年"
description: "アカウント作成から3年経過した"
_loggedInOnBirthday:
title: "ハッピーバースデー!"
description: "誕生日にログインした"
_loggedInOnNewYearsDay:
title: "あけましておめでとうございます!"
description: "元旦にログインした"
flavor: "今年も弊インスタンスをよろしくお願いします"
_cookieClicked:
title: "クッキー叩くやつ"
description: "クッキー叩いてもうた"
flavor: "兄ちゃんソフト間違っとんで"
_brainDiver:
title: "Brain Diver"
description: "Brain Diverへのリンクを投稿したった"
flavor: "Misskey-Misskey La-Tu-Ma"
_role: _role:
new: "ロールの作成" new: "ロールの作成"
edit: "ロールの編集" edit: "ロールの編集"
@@ -997,6 +1211,9 @@ _role:
baseRole: "ベースロール" baseRole: "ベースロール"
useBaseValue: "ベースロールの値を使用" useBaseValue: "ベースロールの値を使用"
chooseRoleToAssign: "アサインするロールを選択" chooseRoleToAssign: "アサインするロールを選択"
iconUrl: "アイコン画像のURL"
asBadge: "バッジとして見せる"
descriptionOfAsBadge: "オンにすると、ユーザー名の横んとこにロールのアイコンが表示されるで。"
canEditMembersByModerator: "モデレーターのメンバー編集を許可" canEditMembersByModerator: "モデレーターのメンバー編集を許可"
descriptionOfCanEditMembersByModerator: "オンにすると、管理者に加えてモデレーターもこのロールへユーザーをアサイン/アサイン解除できるようになるで。オフにすると管理者のみが行えるで。" descriptionOfCanEditMembersByModerator: "オンにすると、管理者に加えてモデレーターもこのロールへユーザーをアサイン/アサイン解除できるようになるで。オフにすると管理者のみが行えるで。"
priority: "優先度" priority: "優先度"
@@ -1251,6 +1468,7 @@ _ago:
weeksAgo: "{n}週間前" weeksAgo: "{n}週間前"
monthsAgo: "{n}ヶ月前" monthsAgo: "{n}ヶ月前"
yearsAgo: "{n}年前" yearsAgo: "{n}年前"
invalid: "あらへん"
_time: _time:
second: "秒" second: "秒"
minute: "分" minute: "分"
@@ -1284,14 +1502,29 @@ _tutorial:
step8_3: "通知の設定はあとから変更できるで" step8_3: "通知の設定はあとから変更できるで"
_2fa: _2fa:
alreadyRegistered: "もう設定終わっとるわ。" alreadyRegistered: "もう設定終わっとるわ。"
registerDevice: "デバイスを登録するで" registerTOTP: "認証アプリの設定はじめる"
registerKey: "キーを登録するで" passwordToTOTP: "パスワードを入れてーや"
step1: "ほんなら、{a}や{b}とかの認証アプリを使っとるデバイスにインストールしてな。" step1: "ほんなら、{a}や{b}とかの認証アプリを使っとるデバイスにインストールしてな。"
step2: "次に、ここにあるQRコードをアプリでスキャンしてな。" step2: "次に、ここにあるQRコードをアプリでスキャンしてな。"
step2Click: "QRコードをクリックすると、今使とる端末に入っとる認証アプリとかキーリングに登録できるで。"
step2Url: "デスクトップアプリやったら次のURLを入力してや:" step2Url: "デスクトップアプリやったら次のURLを入力してや:"
step3Title: "確認コードを入れてーや"
step3: "アプリに表示されているトークンを入力して終わりや。" step3: "アプリに表示されているトークンを入力して終わりや。"
step4: "これからログインするときも、同じようにトークンを入力するんやで" step4: "これからログインするときも、同じようにトークンを入力するんやで"
securityKeyNotSupported: "今使とるブラウザはセキュリティキーに対応してへんのやってさ。"
registerTOTPBeforeKey: "セキュリティキー・パスキーを登録するんやったら、まず認証アプリを設定してーな。"
securityKeyInfo: "FIDO2をサポートするハードウェアセキュリティキーか端末の指紋認証やPINを使ってログインするように設定できるで。" securityKeyInfo: "FIDO2をサポートするハードウェアセキュリティキーか端末の指紋認証やPINを使ってログインするように設定できるで。"
chromePasskeyNotSupported: "Chromeのパスキーは今んとこ対応してないねん。"
registerSecurityKey: "セキュリティキー・パスキーを登録するわ"
securityKeyName: "キーの名前を入れてーや"
tapSecurityKey: "ブラウザが言うこと聞いて、セキュリティキーとかパスキー登録しといでや"
removeKey: "セキュリティキーをほかす"
removeKeyConfirm: "{name}を消すん?"
whyTOTPOnlyRenew: "セキュリティキーが登録されとったら、認証アプリの設定は解除できへんで。"
renewTOTP: "認証アプリをもっかい設定"
renewTOTPConfirm: "今までの人称アプリの確認コードは使えんくなるけどええか?"
renewTOTPOk: "もっかい設定する"
renewTOTPCancel: "やめとく"
_permissions: _permissions:
"read:account": "アカウントの情報を見るで" "read:account": "アカウントの情報を見るで"
"write:account": "アカウントの情報を変更するで" "write:account": "アカウントの情報を変更するで"
@@ -1326,6 +1559,7 @@ _permissions:
"read:gallery-likes": "ギャラリーのいいねを見るで" "read:gallery-likes": "ギャラリーのいいねを見るで"
"write:gallery-likes": "ギャラリーのいいねを操作するで" "write:gallery-likes": "ギャラリーのいいねを操作するで"
_auth: _auth:
shareAccessTitle: "アプリへのアクセス許してやったらどうや"
shareAccess: "「{name}」がアカウントにアクセスすることを許可してええか?" shareAccess: "「{name}」がアカウントにアクセスすることを許可してええか?"
shareAccessAsk: "アカウントのアクセスを許可してもええか?" shareAccessAsk: "アカウントのアクセスを許可してもええか?"
permission: "{name}に次の権限つけたってやって" permission: "{name}に次の権限つけたってやって"
@@ -1339,7 +1573,6 @@ _antennaSources:
homeTimeline: "フォローしとるユーザーのノート" homeTimeline: "フォローしとるユーザーのノート"
users: "選らんだ一人か複数のユーザーのノート" users: "選らんだ一人か複数のユーザーのノート"
userList: "選んだリストのユーザーのノート" userList: "選んだリストのユーザーのノート"
userGroup: "選んだグループのユーザーのノート"
_weekday: _weekday:
sunday: "日曜日" sunday: "日曜日"
monday: "月曜日" monday: "月曜日"
@@ -1414,16 +1647,16 @@ _visibility:
followersDescription: "自分のフォロワーのみに公開するで" followersDescription: "自分のフォロワーのみに公開するで"
specified: "ダイレクト" specified: "ダイレクト"
specifiedDescription: "選んだユーザーのみに公開するで" specifiedDescription: "選んだユーザーのみに公開するで"
localOnly: "ローカルのみ" disableFederation: "連合なし"
localOnlyDescription: "リモートユーザーには非公開にするで" disableFederationDescription: "他インスタンスへは送らんとくわ"
_postForm: _postForm:
replyPlaceholder: "このノートに返信..." replyPlaceholder: "このノートに返信..."
quotePlaceholder: "このノートを引用..." quotePlaceholder: "このノートを引用..."
channelPlaceholder: "チャンネルに投稿..." channelPlaceholder: "チャンネルに投稿..."
_placeholders: _placeholders:
a: "いまどしとるん?" a: "いまどないしとるん?"
b: "何かあったん?" b: "何かあったん?"
c: "何考えとるん?" c: "何考えとるん?"
d: "何か言いたいことあるん?" d: "何か言いたいことあるん?"
e: "ここに書いてーなー" e: "ここに書いてーなー"
f: "あんたが書くの待っとるで" f: "あんたが書くの待っとるで"
@@ -1510,7 +1743,7 @@ _pages:
viewPage: "ページを見る" viewPage: "ページを見る"
like: "ええやん" like: "ええやん"
unlike: "良くないわ" unlike: "良くないわ"
my: "人気のページ" my: "自分のページ"
liked: "ええと思ったページ" liked: "ええと思ったページ"
featured: "人気" featured: "人気"
inspector: "インスペクター" inspector: "インスペクター"
@@ -1553,12 +1786,9 @@ _notification:
youGotReply: "{name}からのリプライ" youGotReply: "{name}からのリプライ"
youGotQuote: "{name}による引用" youGotQuote: "{name}による引用"
youRenoted: "{name}がRenoteしたみたいやで" youRenoted: "{name}がRenoteしたみたいやで"
youGotMessagingMessageFromUser: "{name}からのチャットがあるで"
youGotMessagingMessageFromGroup: "{name}のチャットがあるで"
youWereFollowed: "フォローされたで" youWereFollowed: "フォローされたで"
youReceivedFollowRequest: "フォロー許可してほしいみたいやな" youReceivedFollowRequest: "フォロー許可してほしいみたいやな"
yourFollowRequestAccepted: "フォローさせてもろたで" yourFollowRequestAccepted: "フォローさせてもろたで"
youWereInvitedToGroup: "グループに招待されとるで"
pollEnded: "アンケートの結果が出たみたいや" pollEnded: "アンケートの結果が出たみたいや"
unreadAntennaNote: "アンテナ {name}" unreadAntennaNote: "アンテナ {name}"
emptyPushNotificationMessage: "プッシュ通知の更新をしといたで" emptyPushNotificationMessage: "プッシュ通知の更新をしといたで"
@@ -1574,7 +1804,7 @@ _notification:
pollEnded: "アンケートが終了したで" pollEnded: "アンケートが終了したで"
receiveFollowRequest: "フォロー許可してほしいみたいやで" receiveFollowRequest: "フォロー許可してほしいみたいやで"
followRequestAccepted: "フォローが受理されたで" followRequestAccepted: "フォローが受理されたで"
groupInvited: "グループに招待されたで" achievementEarned: "実績の獲得"
app: "連携アプリからの通知や" app: "連携アプリからの通知や"
_actions: _actions:
followBack: "フォローバック" followBack: "フォローバック"
@@ -1607,3 +1837,6 @@ _deck:
channel: "チャンネル" channel: "チャンネル"
mentions: "あんた宛て" mentions: "あんた宛て"
direct: "ダイレクト" direct: "ダイレクト"
_dialog:
charactersExceeded: "最大の文字数を上回っとるで!今は {current} / 最大でも {max}"
charactersBelow: "最小の文字数を下回っとるで!今は {current} / 最低でも {min}"

View File

@@ -39,10 +39,8 @@ remove: "Kkes"
connectService: "Qqen" connectService: "Qqen"
userList: "Tibdarin" userList: "Tibdarin"
securityKey: "Tasarutt n tɣellist" securityKey: "Tasarutt n tɣellist"
securityKeyName: "Isem n tsarutt"
signinRequired: "Ttxil jerred" signinRequired: "Ttxil jerred"
signinWith: "Tuqqna s {x}" signinWith: "Tuqqna s {x}"
tapSecurityKey: "Sekcem tasarutt-ik·im n tɣellist"
uiLanguage: "Tutlayt n wegrudem" uiLanguage: "Tutlayt n wegrudem"
accountSettings: "Iɣewwaṛen n umiḍan" accountSettings: "Iɣewwaṛen n umiḍan"
plugins: "Izegrar" plugins: "Izegrar"

View File

@@ -15,7 +15,7 @@ gotIt: "알겠어요"
cancel: "취소" cancel: "취소"
noThankYou: "나중에" noThankYou: "나중에"
enterUsername: "유저명 입력" enterUsername: "유저명 입력"
renotedBy: "{user}님 리노트" renotedBy: "{user}님 리노트"
noNotes: "노트가 없습니다" noNotes: "노트가 없습니다"
noNotifications: "표시할 알림이 없습니다" noNotifications: "표시할 알림이 없습니다"
instance: "인스턴스" instance: "인스턴스"
@@ -103,6 +103,8 @@ renoted: "리노트했습니다"
cantRenote: "이 게시물은 리노트 할 수 없습니다." cantRenote: "이 게시물은 리노트 할 수 없습니다."
cantReRenote: "리노트를 리노트 할 수 없습니다." cantReRenote: "리노트를 리노트 할 수 없습니다."
quote: "인용" quote: "인용"
inChannelRenote: "채널 내 리노트"
inChannelQuote: "채널 내 인용"
pinnedNote: "고정해놓은 노트" pinnedNote: "고정해놓은 노트"
pinned: "프로필에 고정" pinned: "프로필에 고정"
you: "당신" you: "당신"
@@ -391,16 +393,19 @@ about: "정보"
aboutMisskey: "Misskey에 대하여" aboutMisskey: "Misskey에 대하여"
administrator: "관리자" administrator: "관리자"
token: "토큰" token: "토큰"
twoStepAuthentication: "2단계 인증" 2fa: "2단계 인증"
totp: "인증 앱"
totpDescription: "인증 앱을 사용하여 일회성 비밀번호 입력"
moderator: "모더레이터" moderator: "모더레이터"
moderation: "모더레이션" moderation: "모더레이션"
nUsersMentioned: "{n}명이 언급함" nUsersMentioned: "{n}명이 언급함"
securityKeyAndPasskey: "보안 키 또는 패스 키"
securityKey: "보안 키" securityKey: "보안 키"
securityKeyName: "키 이름"
registerSecurityKey: "보안 키를 등록"
lastUsed: "마지막 사용" lastUsed: "마지막 사용"
lastUsedAt: "마지막 사용: {t}"
unregister: "등록 해제" unregister: "등록 해제"
passwordLessLogin: "비밀번호 없이 로그인" passwordLessLogin: "비밀번호 없이 로그인"
passwordLessLoginDescription: "비밀번호를 사용하지 않고 보안 키 또는 패스 키 등으로만 로그인합니다."
resetPassword: "비밀번호 재설정" resetPassword: "비밀번호 재설정"
newPasswordIs: "새로운 비밀번호는 \"{password}\" 입니다" newPasswordIs: "새로운 비밀번호는 \"{password}\" 입니다"
reduceUiAnimation: "UI의 애니메이션을 줄이기" reduceUiAnimation: "UI의 애니메이션을 줄이기"
@@ -415,24 +420,15 @@ markAsReadAllTalkMessages: "모든 대화를 읽은 상태로 표시"
help: "도움말" help: "도움말"
inputMessageHere: "여기에 메시지를 입력하세요" inputMessageHere: "여기에 메시지를 입력하세요"
close: "닫기" close: "닫기"
group: "그룹"
groups: "그룹"
createGroup: "그룹 만들기"
ownedGroups: "소유 그룹"
joinedGroups: "참여중인 그룹"
invites: "초대" invites: "초대"
groupName: "그룹명"
members: "멤버" members: "멤버"
transfer: "양도" transfer: "양도"
messagingWithUser: "유저와 대화하기"
messagingWithGroup: "그룹끼리 대화하기"
title: "제목" title: "제목"
text: "텍스트" text: "텍스트"
enable: "사용" enable: "사용"
next: "다음" next: "다음"
retype: "다시 입력" retype: "다시 입력"
noteOf: "{user}의 노트" noteOf: "{user}의 노트"
inviteToGroup: "그룹에 초대하기"
quoteAttached: "인용함" quoteAttached: "인용함"
quoteQuestion: "인용해서 작성하시겠습니까?" quoteQuestion: "인용해서 작성하시겠습니까?"
noMessagesYet: "아직 대화가 없습니다" noMessagesYet: "아직 대화가 없습니다"
@@ -454,17 +450,13 @@ passwordMatched: "일치합니다"
passwordNotMatched: "일치하지 않습니다" passwordNotMatched: "일치하지 않습니다"
signinWith: "{x}로 로그인" signinWith: "{x}로 로그인"
signinFailed: "로그인할 수 없습니다. 사용자명과 비밀번호를 확인하여 주십시오." signinFailed: "로그인할 수 없습니다. 사용자명과 비밀번호를 확인하여 주십시오."
tapSecurityKey: "보안 키를 터치"
or: "혹은" or: "혹은"
language: "언어" language: "언어"
uiLanguage: "UI 표시 언어" uiLanguage: "UI 표시 언어"
groupInvited: "그룹에 초대되었습니다"
aboutX: "{x}에 대하여" aboutX: "{x}에 대하여"
emojiStyle: "이모지 스타일" emojiStyle: "이모지 스타일"
native: "네이티브" native: "네이티브"
disableDrawer: "드로어 메뉴를 사용하지 않기" disableDrawer: "드로어 메뉴를 사용하지 않기"
youHaveNoGroups: "그룹이 없습니다"
joinOrCreateGroup: "다른 그룹의 초대를 받거나, 직접 새 그룹을 만들어 보세요."
noHistory: "기록이 없습니다" noHistory: "기록이 없습니다"
signinHistory: "로그인 기록" signinHistory: "로그인 기록"
enableAdvancedMfm: "고급 MFM을 활성화" enableAdvancedMfm: "고급 MFM을 활성화"
@@ -787,6 +779,7 @@ popularPosts: "인기 포스트"
shareWithNote: "노트로 공유" shareWithNote: "노트로 공유"
ads: "광고" ads: "광고"
expiration: "기한" expiration: "기한"
startingperiod: "시작 기간"
memo: "메모" memo: "메모"
priority: "우선순위" priority: "우선순위"
high: "높음" high: "높음"
@@ -819,6 +812,7 @@ lastCommunication: "마지막 통신"
resolved: "해결됨" resolved: "해결됨"
unresolved: "해결되지 않음" unresolved: "해결되지 않음"
breakFollow: "팔로워 해제" breakFollow: "팔로워 해제"
breakFollowConfirm: "팔로우를 해제하시겠습니까?"
itsOn: "켜짐" itsOn: "켜짐"
itsOff: "꺼짐" itsOff: "꺼짐"
emailRequiredForSignup: "가입할 때 이메일 주소 입력을 필수로 하기" emailRequiredForSignup: "가입할 때 이메일 주소 입력을 필수로 하기"
@@ -838,8 +832,6 @@ deleteAccountConfirm: "계정이 삭제되고 되돌릴 수 없게 됩니다.
incorrectPassword: "비밀번호가 올바르지 않습니다." incorrectPassword: "비밀번호가 올바르지 않습니다."
voteConfirm: "\"{choice}\"에 투표하시겠습니까?" voteConfirm: "\"{choice}\"에 투표하시겠습니까?"
hide: "숨기기" hide: "숨기기"
leaveGroup: "그룹 나가기"
leaveGroupConfirm: "\"{name}\"에서 나갈까요?"
useDrawerReactionPickerForMobile: "모바일에서 드로어 메뉴로 표시" useDrawerReactionPickerForMobile: "모바일에서 드로어 메뉴로 표시"
welcomeBackWithName: "환영합니다, {name}님" welcomeBackWithName: "환영합니다, {name}님"
clickToFinishEmailVerification: "[{ok}]를 눌러 이메일 인증을 완료하세요." clickToFinishEmailVerification: "[{ok}]를 눌러 이메일 인증을 완료하세요."
@@ -855,11 +847,13 @@ instanceDefaultLightTheme: "인스턴스 기본 라이트 테마"
instanceDefaultDarkTheme: "인스턴스 기본 다크 테마" instanceDefaultDarkTheme: "인스턴스 기본 다크 테마"
instanceDefaultThemeDescription: "객체 형식의 테마 코드를 입력해 주세요." instanceDefaultThemeDescription: "객체 형식의 테마 코드를 입력해 주세요."
mutePeriod: "뮤트할 기간" mutePeriod: "뮤트할 기간"
period: "투표 기한"
indefinitely: "무기한" indefinitely: "무기한"
tenMinutes: "10분" tenMinutes: "10분"
oneHour: "1시간" oneHour: "1시간"
oneDay: "1일" oneDay: "1일"
oneWeek: "일주일" oneWeek: "일주일"
oneMonth: "1개월"
reflectMayTakeTime: "반영되기까지 시간이 걸릴 수 있습니다." reflectMayTakeTime: "반영되기까지 시간이 걸릴 수 있습니다."
failedToFetchAccountInformation: "계정 정보를 가져오지 못했습니다" failedToFetchAccountInformation: "계정 정보를 가져오지 못했습니다"
rateLimitExceeded: "요청 제한 횟수를 초과하였습니다" rateLimitExceeded: "요청 제한 횟수를 초과하였습니다"
@@ -951,6 +945,15 @@ thisPostMayBeAnnoying: "이 게시물은 다른 유저에게 피해를 줄 가
thisPostMayBeAnnoyingHome: "홈에 게시" thisPostMayBeAnnoyingHome: "홈에 게시"
thisPostMayBeAnnoyingCancel: "그만두기" thisPostMayBeAnnoyingCancel: "그만두기"
thisPostMayBeAnnoyingIgnore: "이대로 게시" thisPostMayBeAnnoyingIgnore: "이대로 게시"
collapseRenotes: "이미 본 리노트를 간략화하기"
internalServerError: "내부 서버 오류"
internalServerErrorDescription: "내부 서버에서 예기치 않은 오류가 발생했습니다."
copyErrorInfo: "오류 정보 복사"
joinThisServer: "이 서버에 가입"
exploreOtherServers: "다른 서버 둘러보기"
letsLookAtTimeline: "타임라인 구경하기"
disableFederationWarn: "연합이 비활성화됩니다. 비활성화해도 게시물이 비공개가 되지는 않습니다. 대부분의 경우 이 옵션을 활성화할 필요가 없습니다."
invitationRequiredToRegister: "현재 이 서버는 비공개입니다. 회원가입을 하시려면 초대번호가 필요합니다."
_achievements: _achievements:
earnedAt: "달성 일시" earnedAt: "달성 일시"
_types: _types:
@@ -1232,7 +1235,7 @@ _role:
noteEachClipsMax: "각 클립에 추가할 수 있는 노트 수" noteEachClipsMax: "각 클립에 추가할 수 있는 노트 수"
userListMax: "생성할 수 있는 유저 리스트 수" userListMax: "생성할 수 있는 유저 리스트 수"
userEachUserListsMax: "유저 리스트당 최대 사용자 수" userEachUserListsMax: "유저 리스트당 최대 사용자 수"
rateLimitFactor: "도 제한" rateLimitFactor: "요청 빈도 제한"
descriptionOfRateLimitFactor: "작을수록 제한이 완화되고, 클수록 제한이 강화됩니다." descriptionOfRateLimitFactor: "작을수록 제한이 완화되고, 클수록 제한이 강화됩니다."
canHideAds: "광고 숨기기" canHideAds: "광고 숨기기"
_condition: _condition:
@@ -1464,6 +1467,7 @@ _ago:
weeksAgo: "{n}주 전" weeksAgo: "{n}주 전"
monthsAgo: "{n}개월 전" monthsAgo: "{n}개월 전"
yearsAgo: "{n}년 전" yearsAgo: "{n}년 전"
invalid: "없음"
_time: _time:
second: "초" second: "초"
minute: "분" minute: "분"
@@ -1497,14 +1501,29 @@ _tutorial:
step8_3: "알림 설정은 나중에도 변경할 수 있습니다." step8_3: "알림 설정은 나중에도 변경할 수 있습니다."
_2fa: _2fa:
alreadyRegistered: "이미 설정이 완료되었습니다." alreadyRegistered: "이미 설정이 완료되었습니다."
registerDevice: "디바이스 등록" registerTOTP: "인증 앱 설정 시작"
registerKey: "키를 등록" passwordToTOTP: "비밀번호를 입력하세요."
step1: "먼저, {a}나 {b}등의 인증 앱을 사용 중인 디바이스에 설치합니다." step1: "먼저, {a}나 {b}등의 인증 앱을 사용 중인 디바이스에 설치합니다."
step2: "그 후, 표시되어 있는 QR코드를 앱으로 스캔합니다." step2: "그 후, 표시되어 있는 QR코드를 앱으로 스캔합니다."
step2Click: "QR 코드를 클릭하면 기기에 설치된 인증 앱에 등록할 수 있습니다."
step2Url: "데스크톱 앱에서는 다음 URL을 입력하세요:" step2Url: "데스크톱 앱에서는 다음 URL을 입력하세요:"
step3Title: "인증 코드 입력"
step3: "앱에 표시된 토큰을 입력하시면 완료됩니다." step3: "앱에 표시된 토큰을 입력하시면 완료됩니다."
step4: "다음 로그인부터는 토큰을 입력해야 합니다." step4: "다음 로그인부터는 토큰을 입력해야 합니다."
securityKeyNotSupported: "이 브라우저는 보안 키를 지원하지 않습니다."
registerTOTPBeforeKey: "보안 키 또는 패스키를 등록하려면 인증 앱을 등록하십시오."
securityKeyInfo: "FIDO2를 지원하는 하드웨어 보안 키 혹은 디바이스의 지문인식이나 화면잠금 PIN을 이용해서 로그인하도록 설정할 수 있습니다." securityKeyInfo: "FIDO2를 지원하는 하드웨어 보안 키 혹은 디바이스의 지문인식이나 화면잠금 PIN을 이용해서 로그인하도록 설정할 수 있습니다."
chromePasskeyNotSupported: "현재 Chrome의 패스키는 지원되지 않습니다."
registerSecurityKey: "보안 키 또는 패스키 등록"
securityKeyName: "키 이름 입력"
tapSecurityKey: "브라우저의 지시에 따라 보안 키 또는 패스키를 등록하여 주십시오"
removeKey: "보안 키를 삭제"
removeKeyConfirm: "{name} 을(를) 삭제하시겠습니까?"
whyTOTPOnlyRenew: "보안 키가 등록되어 있는 경우 인증 앱을 해제할 수 없습니다."
renewTOTP: "인증 앱 재설정"
renewTOTPConfirm: "기존에 등록되어 있던 인증 키는 사용하지 못하게 됩니다."
renewTOTPOk: "재설정"
renewTOTPCancel: "취소"
_permissions: _permissions:
"read:account": "계정의 정보를 봅니다" "read:account": "계정의 정보를 봅니다"
"write:account": "계정의 정보를 변경합니다" "write:account": "계정의 정보를 변경합니다"
@@ -1553,7 +1572,6 @@ _antennaSources:
homeTimeline: "팔로우중인 유저의 노트" homeTimeline: "팔로우중인 유저의 노트"
users: "지정한 한 명 혹은 여러 명의 유저의 노트" users: "지정한 한 명 혹은 여러 명의 유저의 노트"
userList: "지정한 리스트에 속한 유저의 노트" userList: "지정한 리스트에 속한 유저의 노트"
userGroup: "지정한 그룹에 속한 유저의 노트"
_weekday: _weekday:
sunday: "일요일" sunday: "일요일"
monday: "월요일" monday: "월요일"
@@ -1628,8 +1646,8 @@ _visibility:
followersDescription: "팔로워에게만 공개" followersDescription: "팔로워에게만 공개"
specified: "다이렉트" specified: "다이렉트"
specifiedDescription: "지정한 유저에게만 공개" specifiedDescription: "지정한 유저에게만 공개"
localOnly: "로컬에만" disableFederation: "연합에 보내지 않기"
localOnlyDescription: "리모트 유저에게지 않" disableFederationDescription: "다른 인스턴스로지 않습니다"
_postForm: _postForm:
replyPlaceholder: "이 노트에 답글..." replyPlaceholder: "이 노트에 답글..."
quotePlaceholder: "이 노트를 인용..." quotePlaceholder: "이 노트를 인용..."
@@ -1767,12 +1785,9 @@ _notification:
youGotReply: "{name}님이 답글함" youGotReply: "{name}님이 답글함"
youGotQuote: "{name}님이 인용함" youGotQuote: "{name}님이 인용함"
youRenoted: "{name}님이 Renote" youRenoted: "{name}님이 Renote"
youGotMessagingMessageFromUser: "{name} 님이 보낸 채팅이 있어요"
youGotMessagingMessageFromGroup: "{name}에서 보낸 채팅이 있어요"
youWereFollowed: "새로운 팔로워가 있습니다" youWereFollowed: "새로운 팔로워가 있습니다"
youReceivedFollowRequest: "새로운 팔로우 요청이 있습니다" youReceivedFollowRequest: "새로운 팔로우 요청이 있습니다"
yourFollowRequestAccepted: "팔로우 요청이 수락되었습니다" yourFollowRequestAccepted: "팔로우 요청이 수락되었습니다"
youWereInvitedToGroup: "그룹에 초대되었습니다"
pollEnded: "투표 결과가 발표되었습니다" pollEnded: "투표 결과가 발표되었습니다"
unreadAntennaNote: "안테나 {name}" unreadAntennaNote: "안테나 {name}"
emptyPushNotificationMessage: "푸시 알림이 갱신되었습니다" emptyPushNotificationMessage: "푸시 알림이 갱신되었습니다"
@@ -1788,7 +1803,7 @@ _notification:
pollEnded: "투표가 종료됨" pollEnded: "투표가 종료됨"
receiveFollowRequest: "팔로우 요청을 받았을 때" receiveFollowRequest: "팔로우 요청을 받았을 때"
followRequestAccepted: "팔로우 요청이 승인되었을 때" followRequestAccepted: "팔로우 요청이 승인되었을 때"
groupInvited: "그룹에 초대되었을 때" achievementEarned: "도전 과제 획득"
app: "연동된 앱을 통한 알림" app: "연동된 앱을 통한 알림"
_actions: _actions:
followBack: "팔로우" followBack: "팔로우"
@@ -1821,3 +1836,6 @@ _deck:
channel: "채널" channel: "채널"
mentions: "받은 멘션" mentions: "받은 멘션"
direct: "다이렉트" direct: "다이렉트"
_dialog:
charactersExceeded: "최대 글자수를 초과하였습니다! 현재 {current} / 최대 {min}"
charactersBelow: "최소 글자수 미만입니다! 현재 {current} / 최소 {min}"

View File

@@ -136,7 +136,29 @@ loginFailed: "ການເຂົ້າສູ່ລະບົບບໍ່ສຳເ
general: "ທົ່ວໄປ" general: "ທົ່ວໄປ"
wallpaper: "ພາບພື້ນຫລັງ" wallpaper: "ພາບພື້ນຫລັງ"
setWallpaper: "ຕັ້ງເປັນພາບພື້ນຫຼັງ" setWallpaper: "ຕັ້ງເປັນພາບພື້ນຫຼັງ"
searchWith: "ຊອກຫາ: {q}"
proxyAccount: "ບັນຊີພຣັອກຊີ"
host: "ໂຮດສ"
selectUser: "ເລືອກຜູ້ໃຊ້"
recipient: "ເຖິງ"
annotation: "ຄຳເຫັນ"
federation: "ສະຫະພັນ"
instances: "ອີນສະແຕນ" instances: "ອີນສະແຕນ"
registeredAt: "ລົງທະບຽນຢູ່"
storageUsage: "ບ່ອນ​ຈັດ​ເກັບ​ຂໍ້​ມູນທີ່ໃຊ້"
charts: "ອັນດັບເພງ"
perHour: "ຕໍ່ຊົ່ວໂມງ"
perDay: "ຕໍ່​ມື້"
stopActivityDelivery: "ຢຸດເຊົາການສົ່ງກິດຈະກໍາ"
blockThisInstance: "ຂັດຂວາງຕົວຢ່າງນີ້"
operations: "ການດຳເນີນງານ"
software: "ຊອບແວ"
version: "ສະບັບ"
metadata: "Metadata"
monitor: "ຈໍພາບ"
cpuAndMemory: "CPU ແລະ ຫນ່ວຍຄວາມຈໍາ"
network: "ເຄືອຂ່າຍ"
disk: "ດິສກ໌"
instanceInfo: "ອີນສະແຕນ" instanceInfo: "ອີນສະແຕນ"
statistics: "ສະຖິຕິ" statistics: "ສະຖິຕິ"
clearQueue: "ລ້າງຄິວ" clearQueue: "ລ້າງຄິວ"
@@ -178,6 +200,7 @@ nsfw: "NSFW"
accept: "ອະນຸຍາດ" accept: "ອະນຸຍາດ"
pinnedNotes: "ບັນທຶກທີ່ປັກໝຸດໄວ້" pinnedNotes: "ບັນທຶກທີ່ປັກໝຸດໄວ້"
userList: "ລາຍການ" userList: "ລາຍການ"
smtpHost: "ໂຮດສ"
smtpUser: "ຊື່ຜູ້ໃຊ້" smtpUser: "ຊື່ຜູ້ໃຊ້"
smtpPass: "ລະຫັດຜ່ານ" smtpPass: "ລະຫັດຜ່ານ"
clearCache: "ລຶບລ້າງແຄສ" clearCache: "ລຶບລ້າງແຄສ"
@@ -195,11 +218,14 @@ _sfx:
note: "ບັນທຶກ" note: "ບັນທຶກ"
notification: "ການແຈ້ງເຕືອນ" notification: "ການແຈ້ງເຕືອນ"
chat: "ແຊ໋ດ" chat: "ແຊ໋ດ"
_2fa:
renewTOTPCancel: "ບໍ່​ແມ່ນ​ຕອນ​ນີ້"
_widgets: _widgets:
profile: "ໂພຼຟາຍ" profile: "ໂພຼຟາຍ"
instanceInfo: "ອີນສະແຕນ" instanceInfo: "ອີນສະແຕນ"
notifications: "ການແຈ້ງເຕືອນ" notifications: "ການແຈ້ງເຕືອນ"
timeline: "​ເສັ້ນກຳ​ນົດ​ເວ​ລາ​" timeline: "​ເສັ້ນກຳ​ນົດ​ເວ​ລາ​"
federation: "ສະຫະພັນ"
_userList: _userList:
chooseList: "ເລືອກບັນຊີລາຍການ" chooseList: "ເລືອກບັນຊີລາຍການ"
_cw: _cw:
@@ -214,6 +240,8 @@ _exportOrImport:
muteList: "ປີດສຽງ" muteList: "ປີດສຽງ"
blockingList: "ບ໋ອກ" blockingList: "ບ໋ອກ"
userLists: "ລາຍການ" userLists: "ລາຍການ"
_charts:
federation: "ສະຫະພັນ"
_timelines: _timelines:
home: "ໜ້າຫຼັກ" home: "ໜ້າຫຼັກ"
_pages: _pages:

View File

@@ -376,13 +376,10 @@ about: "Over"
aboutMisskey: "Over Misskey" aboutMisskey: "Over Misskey"
administrator: "Beheerder" administrator: "Beheerder"
token: "Token" token: "Token"
twoStepAuthentication: "Tweestapsverificatie"
moderator: "Moderator" moderator: "Moderator"
moderation: "Moderatie" moderation: "Moderatie"
nUsersMentioned: "Vermeld door {n} gebruikers" nUsersMentioned: "Vermeld door {n} gebruikers"
securityKey: "Beveiligingssleutel" securityKey: "Beveiligingssleutel"
securityKeyName: "Sleutelnaam"
registerSecurityKey: "Zekerheids-Sleutel registreren"
lastUsed: "Laatst gebruikt" lastUsed: "Laatst gebruikt"
unregister: "Uitschrijven" unregister: "Uitschrijven"
passwordLessLogin: "Inloggen zonder wachtwoord" passwordLessLogin: "Inloggen zonder wachtwoord"
@@ -399,8 +396,6 @@ markAsReadAllTalkMessages: "Markeer alle berichten als gelezen"
help: "Help" help: "Help"
inputMessageHere: "Voer hier je bericht in" inputMessageHere: "Voer hier je bericht in"
close: "Sluiten" close: "Sluiten"
group: "Groep"
groups: "Groepen"
invites: "Uitnodigen" invites: "Uitnodigen"
invitations: "Uitnodigen" invitations: "Uitnodigen"
sound: "Geluid" sound: "Geluid"
@@ -435,6 +430,8 @@ _sfx:
note: "Notities" note: "Notities"
notification: "Meldingen" notification: "Meldingen"
chat: "Chat" chat: "Chat"
_2fa:
renewTOTPCancel: "Nee, bedankt"
_widgets: _widgets:
profile: "Profiel" profile: "Profiel"
instanceInfo: "Serverinformatie" instanceInfo: "Serverinformatie"

View File

@@ -385,13 +385,10 @@ about: "Informacje"
aboutMisskey: "O Misskey" aboutMisskey: "O Misskey"
administrator: "Admin" administrator: "Admin"
token: "Token" token: "Token"
twoStepAuthentication: "Uwierzytelnianie dwuskładnikowe"
moderator: "Moderator" moderator: "Moderator"
moderation: "Moderacja" moderation: "Moderacja"
nUsersMentioned: "{n} wspomnianych użytkowników" nUsersMentioned: "{n} wspomnianych użytkowników"
securityKey: "Klucz bezpieczeństwa" securityKey: "Klucz bezpieczeństwa"
securityKeyName: "Nazwa klucza"
registerSecurityKey: "Zarejestruj klucz bezpieczeństwa"
lastUsed: "Ostatnio używane" lastUsed: "Ostatnio używane"
unregister: "Cofnij rejestrację" unregister: "Cofnij rejestrację"
passwordLessLogin: "Skonfiguruj logowanie bez użycia hasła" passwordLessLogin: "Skonfiguruj logowanie bez użycia hasła"
@@ -409,24 +406,15 @@ markAsReadAllTalkMessages: "Oznacz wszystkie wiadomości jako przeczytane"
help: "Pomoc" help: "Pomoc"
inputMessageHere: "Wprowadź wiadomość tutaj" inputMessageHere: "Wprowadź wiadomość tutaj"
close: "Zamknij" close: "Zamknij"
group: "Grupy"
groups: "Grupy"
createGroup: "Utwórz grupę"
ownedGroups: "Posiadane grupy"
joinedGroups: "Członkostwa w grupach"
invites: "Zaproś" invites: "Zaproś"
groupName: "Nazwa grupy"
members: "Członkowie" members: "Członkowie"
transfer: "Transfer" transfer: "Transfer"
messagingWithUser: "Rozmowy z innym użytkownikiem"
messagingWithGroup: "Rozmowy wewnątrz grupy"
title: "Tytuł" title: "Tytuł"
text: "Tekst" text: "Tekst"
enable: "Włącz" enable: "Włącz"
next: "Dalej" next: "Dalej"
retype: "Wprowadź ponownie" retype: "Wprowadź ponownie"
noteOf: "Wpisy {user}" noteOf: "Wpisy {user}"
inviteToGroup: "Zaproś do grupy"
quoteAttached: "Zacytowano" quoteAttached: "Zacytowano"
quoteQuestion: "Czy na pewno chcesz umieścić cytat?" quoteQuestion: "Czy na pewno chcesz umieścić cytat?"
noMessagesYet: "Nie napisano jeszcze wiadomości" noMessagesYet: "Nie napisano jeszcze wiadomości"
@@ -448,17 +436,13 @@ passwordMatched: "Pasuje"
passwordNotMatched: "Hasła nie pasują do siebie" passwordNotMatched: "Hasła nie pasują do siebie"
signinWith: "Zaloguj się z {x}" signinWith: "Zaloguj się z {x}"
signinFailed: "Nie udało się zalogować. Wprowadzona nazwa użytkownika lub hasło są nieprawidłowe." signinFailed: "Nie udało się zalogować. Wprowadzona nazwa użytkownika lub hasło są nieprawidłowe."
tapSecurityKey: "Wybierz swój klucz bezpieczeństwa"
or: "Lub" or: "Lub"
language: "Język" language: "Język"
uiLanguage: "Język wyświetlania UI" uiLanguage: "Język wyświetlania UI"
groupInvited: "Zaproszony(-a) do grupy"
aboutX: "O {x}" aboutX: "O {x}"
emojiStyle: "Styl emoji" emojiStyle: "Styl emoji"
native: "Natywny" native: "Natywny"
disableDrawer: "Nie używaj menu w stylu szuflady" disableDrawer: "Nie używaj menu w stylu szuflady"
youHaveNoGroups: "Nie masz żadnych grup"
joinOrCreateGroup: "Uzyskaj zaproszenie do dołączenia do grupy lub utwórz własną grupę."
noHistory: "Brak historii" noHistory: "Brak historii"
signinHistory: "Historia logowania" signinHistory: "Historia logowania"
doing: "Przetwarzanie..." doing: "Przetwarzanie..."
@@ -816,8 +800,6 @@ deleteAccountConfirm: "Spowoduje to nieodwracalne usunięcie Twojego konta. Kont
incorrectPassword: "Nieprawidłowe hasło." incorrectPassword: "Nieprawidłowe hasło."
voteConfirm: "Potwierdzić swój głos na \"{choice}\"?" voteConfirm: "Potwierdzić swój głos na \"{choice}\"?"
hide: "Ukryj" hide: "Ukryj"
leaveGroup: "Opuść grupę"
leaveGroupConfirm: "Czy na pewno chcesz opuścić \"{name}\"?"
useDrawerReactionPickerForMobile: "Wyświetlaj wybornik reakcji jako szufladę na urządzeniach mobilnych" useDrawerReactionPickerForMobile: "Wyświetlaj wybornik reakcji jako szufladę na urządzeniach mobilnych"
welcomeBackWithName: "Witaj z powrotem, {name}" welcomeBackWithName: "Witaj z powrotem, {name}"
clickToFinishEmailVerification: "Kliknij [{ok}], aby zakończyć weryfikację e-mail." clickToFinishEmailVerification: "Kliknij [{ok}], aby zakończyć weryfikację e-mail."
@@ -828,6 +810,7 @@ auto: "Automatycznie"
size: "Rozmiar" size: "Rozmiar"
numberOfColumn: "Liczba kolumn" numberOfColumn: "Liczba kolumn"
searchByGoogle: "Szukaj" searchByGoogle: "Szukaj"
period: "Ankieta kończy się"
indefinitely: "Nigdy" indefinitely: "Nigdy"
tenMinutes: "10 minut" tenMinutes: "10 minut"
oneHour: "1 godzina" oneHour: "1 godzina"
@@ -1079,6 +1062,7 @@ _ago:
weeksAgo: "{n} tyg. temu" weeksAgo: "{n} tyg. temu"
monthsAgo: "{n} mies. temu" monthsAgo: "{n} mies. temu"
yearsAgo: "{n} lat temu" yearsAgo: "{n} lat temu"
invalid: "Nie ma tu niczego"
_time: _time:
second: "sekunda" second: "sekunda"
minute: "minuta" minute: "minuta"
@@ -1112,12 +1096,12 @@ _tutorial:
step8_3: "Ustawienia powiadomień można zmienić później." step8_3: "Ustawienia powiadomień można zmienić później."
_2fa: _2fa:
alreadyRegistered: "Zarejestrowałeś już urządzenie do uwierzytelniania dwuskładnikowego." alreadyRegistered: "Zarejestrowałeś już urządzenie do uwierzytelniania dwuskładnikowego."
registerDevice: "Zarejestruj nowe urządzenie"
registerKey: "Zarejestruj klucz bezpieczeństwa"
step1: "Najpierw, zainstaluj aplikację uwierzytelniającą (taką jak {a} lub {b}) na swoim urządzeniu." step1: "Najpierw, zainstaluj aplikację uwierzytelniającą (taką jak {a} lub {b}) na swoim urządzeniu."
step2: "Następnie, zeskanuje kod QR z ekranu." step2: "Następnie, zeskanuje kod QR z ekranu."
step3: "Wprowadź token podany w aplikacji, aby ukończyć konfigurację." step3: "Wprowadź token podany w aplikacji, aby ukończyć konfigurację."
step4: "Od teraz, przy każdej próbie logowania otrzymasz prośbę o token logowania." step4: "Od teraz, przy każdej próbie logowania otrzymasz prośbę o token logowania."
removeKeyConfirm: "Usunąć kopię zapasową {name}?"
renewTOTPCancel: "Nie teraz"
_permissions: _permissions:
"read:account": "Wyświetl informacje o swoim koncie" "read:account": "Wyświetl informacje o swoim koncie"
"write:account": "Edytuj swoje informacje o koncie" "write:account": "Edytuj swoje informacje o koncie"
@@ -1328,12 +1312,9 @@ _notification:
youGotReply: "{name} odpowiedział(a) Tobie" youGotReply: "{name} odpowiedział(a) Tobie"
youGotQuote: "{name} zacytował(a) Ciebie" youGotQuote: "{name} zacytował(a) Ciebie"
youRenoted: "{name} udostępnił(a) Twój wpis" youRenoted: "{name} udostępnił(a) Twój wpis"
youGotMessagingMessageFromUser: "{name} wysłał(a) Ci wiadomość"
youGotMessagingMessageFromGroup: "Została wysłana wiadomość do grupy {name}"
youWereFollowed: "Zaobserwował(a) Cię" youWereFollowed: "Zaobserwował(a) Cię"
youReceivedFollowRequest: "Otrzymałeś(-aś) prośbę o możliwość obserwacji" youReceivedFollowRequest: "Otrzymałeś(-aś) prośbę o możliwość obserwacji"
yourFollowRequestAccepted: "Twoja prośba o możliwość obserwacji została przyjęta" yourFollowRequestAccepted: "Twoja prośba o możliwość obserwacji została przyjęta"
youWereInvitedToGroup: "Zaproszony(-a) do grupy"
pollEnded: "Wyniki ankiety stały się dostępne" pollEnded: "Wyniki ankiety stały się dostępne"
unreadAntennaNote: "Antena {name}" unreadAntennaNote: "Antena {name}"
emptyPushNotificationMessage: "Powiadomienia push zostały zaktualizowane" emptyPushNotificationMessage: "Powiadomienia push zostały zaktualizowane"
@@ -1347,7 +1328,6 @@ _notification:
reaction: "Reakcja" reaction: "Reakcja"
receiveFollowRequest: "Otrzymano prośbę o możliwość obserwacji" receiveFollowRequest: "Otrzymano prośbę o możliwość obserwacji"
followRequestAccepted: "Przyjęto prośbę o możliwość obserwacji" followRequestAccepted: "Przyjęto prośbę o możliwość obserwacji"
groupInvited: "Zaproszono do grup"
app: "Powiadomienia z aplikacji" app: "Powiadomienia z aplikacji"
_actions: _actions:
followBack: "zaobserwował cię z powrotem" followBack: "zaobserwował cię z powrotem"

View File

@@ -382,12 +382,9 @@ about: "Informações"
aboutMisskey: "Sobre Misskey" aboutMisskey: "Sobre Misskey"
administrator: "Administrador" administrator: "Administrador"
token: "Símbolo" token: "Símbolo"
twoStepAuthentication: "Verificação em duas etapas"
moderator: "Moderador" moderator: "Moderador"
nUsersMentioned: "Postado por {n} pessoas" nUsersMentioned: "Postado por {n} pessoas"
securityKey: "Chave de segurança" securityKey: "Chave de segurança"
securityKeyName: "Nome chave"
registerSecurityKey: "Registre a chave de segurança"
lastUsed: "Último uso" lastUsed: "Último uso"
unregister: "Cancelar registro" unregister: "Cancelar registro"
passwordLessLogin: "Entrar sem senha" passwordLessLogin: "Entrar sem senha"
@@ -405,10 +402,6 @@ markAsReadAllTalkMessages: "Marcar todas as conversas como lidas"
help: "Ajuda" help: "Ajuda"
inputMessageHere: "Escrever mensagem aqui" inputMessageHere: "Escrever mensagem aqui"
close: "Fechar" close: "Fechar"
group: "Grupos"
groups: "Grupos"
createGroup: "Criar grupo"
ownedGroups: "Grupo próprio"
invites: "Convidar" invites: "Convidar"
invitations: "Convidar" invitations: "Convidar"
tags: "Etiquetas" tags: "Etiquetas"
@@ -522,12 +515,9 @@ _notification:
youGotMention: "{name} te mencionou" youGotMention: "{name} te mencionou"
youGotReply: "{name} te respondeu" youGotReply: "{name} te respondeu"
youGotQuote: "{name} te citou" youGotQuote: "{name} te citou"
youGotMessagingMessageFromUser: "{name} te mandou uma mensagem de bate-papo"
youGotMessagingMessageFromGroup: "Uma mensagem foi mandada para o grupo {name}"
youWereFollowed: "Você tem um novo seguidor" youWereFollowed: "Você tem um novo seguidor"
youReceivedFollowRequest: "Você recebeu um pedido de seguimento" youReceivedFollowRequest: "Você recebeu um pedido de seguimento"
yourFollowRequestAccepted: "Seu pedido de seguimento foi aceito" yourFollowRequestAccepted: "Seu pedido de seguimento foi aceito"
youWereInvitedToGroup: "{userName} te convidou para um grupo"
pollEnded: "Os resultados da enquete agora estão disponíveis" pollEnded: "Os resultados da enquete agora estão disponíveis"
emptyPushNotificationMessage: "As notificações de alerta foram atualizadas" emptyPushNotificationMessage: "As notificações de alerta foram atualizadas"
_types: _types:
@@ -541,7 +531,6 @@ _notification:
pollEnded: "Enquetes terminando" pollEnded: "Enquetes terminando"
receiveFollowRequest: "Recebeu pedidos de seguimento" receiveFollowRequest: "Recebeu pedidos de seguimento"
followRequestAccepted: "Aceitou pedidos de seguimento" followRequestAccepted: "Aceitou pedidos de seguimento"
groupInvited: "Convites de grupo"
app: "Notificações de aplicativos conectados" app: "Notificações de aplicativos conectados"
_actions: _actions:
followBack: "te seguiu de volta" followBack: "te seguiu de volta"

View File

@@ -382,12 +382,9 @@ about: "Despre"
aboutMisskey: "Despre Misskey" aboutMisskey: "Despre Misskey"
administrator: "Administrator" administrator: "Administrator"
token: "Token" token: "Token"
twoStepAuthentication: "Autentificare în doi pași"
moderator: "Moderator" moderator: "Moderator"
nUsersMentioned: "Menționat de {n} utilizatori" nUsersMentioned: "Menționat de {n} utilizatori"
securityKey: "Cheie de securitate" securityKey: "Cheie de securitate"
securityKeyName: "Numele cheii"
registerSecurityKey: "Înregistrează o cheie de securitate"
lastUsed: "Ultima utilizată" lastUsed: "Ultima utilizată"
unregister: "Dezînregistrează" unregister: "Dezînregistrează"
passwordLessLogin: "Autentificare fără parolă" passwordLessLogin: "Autentificare fără parolă"
@@ -405,24 +402,15 @@ markAsReadAllTalkMessages: "Marchează toate mesajele drept citit"
help: "Ajutor" help: "Ajutor"
inputMessageHere: "Introdu un mesaj aici" inputMessageHere: "Introdu un mesaj aici"
close: "Închide" close: "Închide"
group: "Grup"
groups: "Grupuri"
createGroup: "Crează un grup"
ownedGroups: "Grupuri deținute"
joinedGroups: "Grupuri alăturate"
invites: "Invită" invites: "Invită"
groupName: "Numele grupului"
members: "Membri" members: "Membri"
transfer: "Transferă" transfer: "Transferă"
messagingWithUser: "Chat privat"
messagingWithGroup: "Chat de grup"
title: "Titlu" title: "Titlu"
text: "Text" text: "Text"
enable: "Activează" enable: "Activează"
next: "Următorul" next: "Următorul"
retype: "Introdu din nou" retype: "Introdu din nou"
noteOf: "Notă de {user}" noteOf: "Notă de {user}"
inviteToGroup: "Invită în grup"
quoteAttached: "Citat" quoteAttached: "Citat"
quoteQuestion: "Vrei să adaugi ca citat?" quoteQuestion: "Vrei să adaugi ca citat?"
noMessagesYet: "Niciun mesaj încă" noMessagesYet: "Niciun mesaj încă"
@@ -444,15 +432,11 @@ passwordMatched: "Se potrivește!"
passwordNotMatched: "Nu se potrivește" passwordNotMatched: "Nu se potrivește"
signinWith: "Autentifică-te cu {x}" signinWith: "Autentifică-te cu {x}"
signinFailed: "Nu se poate autentifica. Numele de utilizator sau parola introduse sunt incorecte." signinFailed: "Nu se poate autentifica. Numele de utilizator sau parola introduse sunt incorecte."
tapSecurityKey: "Apasă pe cheia ta de securitate."
or: "Sau" or: "Sau"
language: "Limbă" language: "Limbă"
uiLanguage: "Limba interfeței" uiLanguage: "Limba interfeței"
groupInvited: "Ai fost invitat într-un grup"
aboutX: "Despre {x}" aboutX: "Despre {x}"
disableDrawer: "Nu folosi meniuri în stil sertar" disableDrawer: "Nu folosi meniuri în stil sertar"
youHaveNoGroups: "Nu ai niciun grup"
joinOrCreateGroup: "Primește o invitație într-un grup sau creează unul nou."
noHistory: "Nu există istoric" noHistory: "Nu există istoric"
signinHistory: "Istoric autentificări" signinHistory: "Istoric autentificări"
doing: "Se procesează..." doing: "Se procesează..."
@@ -664,6 +648,8 @@ _sfx:
note: "Note" note: "Note"
notification: "Notificări" notification: "Notificări"
chat: "Chat" chat: "Chat"
_ago:
invalid: "Nu e nimic de văzut aici"
_widgets: _widgets:
profile: "Profil" profile: "Profil"
instanceInfo: "Informații despre instanță" instanceInfo: "Informații despre instanță"
@@ -699,7 +685,6 @@ _pages:
image: "Imagini" image: "Imagini"
_notification: _notification:
youWereFollowed: "te-a urmărit" youWereFollowed: "te-a urmărit"
youWereInvitedToGroup: "Ai fost invitat într-un grup"
_types: _types:
follow: "Urmărești" follow: "Urmărești"
mention: "Mențiune" mention: "Mențiune"

View File

@@ -8,7 +8,7 @@ search: "Поиск"
notifications: "Уведомления" notifications: "Уведомления"
username: "Имя пользователя" username: "Имя пользователя"
password: "Пароль" password: "Пароль"
forgotPassword: "Пароль забыт" forgotPassword: "Забыли пароль?"
fetchingAsApObject: "Приём с других сайтов" fetchingAsApObject: "Приём с других сайтов"
ok: "Окей" ok: "Окей"
gotIt: "Ясно!" gotIt: "Ясно!"
@@ -103,6 +103,8 @@ renoted: "Репост совершён."
cantRenote: "Это нельзя репостить." cantRenote: "Это нельзя репостить."
cantReRenote: "Невозможно репостить репост." cantReRenote: "Невозможно репостить репост."
quote: "Цитата" quote: "Цитата"
inChannelRenote: "В канале"
inChannelQuote: "Заметки в канале"
pinnedNote: "Закреплённая заметка" pinnedNote: "Закреплённая заметка"
pinned: "Закрепить в профиле" pinned: "Закрепить в профиле"
you: "Вы" you: "Вы"
@@ -129,6 +131,7 @@ unblockConfirm: "Разблокировать этот аккаунт?"
suspendConfirm: "Заморозить этот аккаунт?" suspendConfirm: "Заморозить этот аккаунт?"
unsuspendConfirm: "Разморозить этот аккаунт?" unsuspendConfirm: "Разморозить этот аккаунт?"
selectList: "Выберите список" selectList: "Выберите список"
selectChannel: "Выберите канал"
selectAntenna: "Выберите антенну" selectAntenna: "Выберите антенну"
selectWidget: "Выберите виджет" selectWidget: "Выберите виджет"
editWidgets: "Редактировать виджеты" editWidgets: "Редактировать виджеты"
@@ -256,6 +259,8 @@ noMoreHistory: "История закончилась"
startMessaging: "Начать общение" startMessaging: "Начать общение"
nUsersRead: "Прочитали {n}" nUsersRead: "Прочитали {n}"
agreeTo: "Я соглашаюсь с {0}" agreeTo: "Я соглашаюсь с {0}"
agreeBelow: "Согласен со следующими"
basicNotesBeforeCreateAccount: "Записи, перед созданием аккаунта"
tos: "Пользовательское соглашение" tos: "Пользовательское соглашение"
start: "Начать" start: "Начать"
home: "Главная" home: "Главная"
@@ -351,6 +356,8 @@ recaptcha: "reCAPTCHA"
enableRecaptcha: "Включить reCAPTCHA" enableRecaptcha: "Включить reCAPTCHA"
recaptchaSiteKey: "Ключ сайта" recaptchaSiteKey: "Ключ сайта"
recaptchaSecretKey: "Секретный ключ" recaptchaSecretKey: "Секретный ключ"
turnstile: "Сервис Turnstile"
enableTurnstile: "Включить Turnstile"
turnstileSiteKey: "Ключ сайта" turnstileSiteKey: "Ключ сайта"
turnstileSecretKey: "Секретный ключ" turnstileSecretKey: "Секретный ключ"
avoidMultiCaptchaConfirm: "Несколько способов проверки могут мешать друг другу. Подтвердите, если хотите отключить другие способы. Или нажмите «Отмена», чтобы оставить их включёнными." avoidMultiCaptchaConfirm: "Несколько способов проверки могут мешать друг другу. Подтвердите, если хотите отключить другие способы. Или нажмите «Отмена», чтобы оставить их включёнными."
@@ -386,16 +393,19 @@ about: "Описание"
aboutMisskey: "О Misskey" aboutMisskey: "О Misskey"
administrator: "Администратор" administrator: "Администратор"
token: "Токен" token: "Токен"
twoStepAuthentication: "Двухфакторная аутентификация" 2fa: "2-х факторная аутентификация"
totp: "Приложение-аутентификатор"
totpDescription: "Описание приложения-аутентификатора"
moderator: "Модератор" moderator: "Модератор"
moderation: "Модерация" moderation: "Модерация"
nUsersMentioned: "Упомянуло пользователей: {n}" nUsersMentioned: "Упомянуло пользователей: {n}"
securityKeyAndPasskey: "Ключ безопасности и парольная фраза"
securityKey: "Ключ безопасности" securityKey: "Ключ безопасности"
securityKeyName: "Имя ключа"
registerSecurityKey: "Зарегистрировать защитный ключ"
lastUsed: "Последнее использование" lastUsed: "Последнее использование"
lastUsedAt: "Последнее использование: {t}"
unregister: "Отписаться" unregister: "Отписаться"
passwordLessLogin: "Настроить вход без пароля" passwordLessLogin: "Настроить вход без пароля"
passwordLessLoginDescription: "Вход без пароля"
resetPassword: "Сброс пароля:" resetPassword: "Сброс пароля:"
newPasswordIs: "Новый пароль — «{password}»." newPasswordIs: "Новый пароль — «{password}»."
reduceUiAnimation: "Уменьшить анимацию в пользовательском интерфейсе" reduceUiAnimation: "Уменьшить анимацию в пользовательском интерфейсе"
@@ -410,24 +420,15 @@ markAsReadAllTalkMessages: "Отметить все реплики как про
help: "Помощь" help: "Помощь"
inputMessageHere: "Введите сообщение здесь" inputMessageHere: "Введите сообщение здесь"
close: "Закрыть" close: "Закрыть"
group: "Группа"
groups: "Группы"
createGroup: "Создать группу"
ownedGroups: "Собственные группы"
joinedGroups: "Участие в группах"
invites: "Приглашения" invites: "Приглашения"
groupName: "Название группы"
members: "Участники" members: "Участники"
transfer: "Отдать" transfer: "Отдать"
messagingWithUser: "Общение с другим пользователем"
messagingWithGroup: "Общение в группе"
title: "Заголовок" title: "Заголовок"
text: "Текст" text: "Текст"
enable: "Включить" enable: "Включить"
next: "Дальше" next: "Дальше"
retype: "Введите ещё раз" retype: "Введите ещё раз"
noteOf: "Что пишет {user}" noteOf: "Что пишет {user}"
inviteToGroup: "Пригласить в группу"
quoteAttached: "Цитата" quoteAttached: "Цитата"
quoteQuestion: "Хотите добавить цитату?" quoteQuestion: "Хотите добавить цитату?"
noMessagesYet: "Пока ни одного сообщения" noMessagesYet: "Пока ни одного сообщения"
@@ -449,19 +450,17 @@ passwordMatched: "Совпали"
passwordNotMatched: "Не совпадают" passwordNotMatched: "Не совпадают"
signinWith: "Использовать {x} для входа" signinWith: "Использовать {x} для входа"
signinFailed: "Невозможно войти в систему. Введенное вами имя пользователя или пароль неверны." signinFailed: "Невозможно войти в систему. Введенное вами имя пользователя или пароль неверны."
tapSecurityKey: "Нажмите на свой электронный ключ"
or: "или" or: "или"
language: "Язык" language: "Язык"
uiLanguage: "Язык интерфейса" uiLanguage: "Язык интерфейса"
groupInvited: "Приглашение в группу"
aboutX: "Описание {x}" aboutX: "Описание {x}"
emojiStyle: "Стиль эмодзи" emojiStyle: "Стиль эмодзи"
native: "Системные" native: "Системные"
disableDrawer: "Не использовать выдвижные меню" disableDrawer: "Не использовать выдвижные меню"
youHaveNoGroups: "У вас нет ни одной группы"
joinOrCreateGroup: "Получайте приглашения в группы или создавайте свои собственные"
noHistory: "История пока пуста" noHistory: "История пока пуста"
signinHistory: "Журнал посещений" signinHistory: "Журнал посещений"
enableAdvancedMfm: "Включить расширенный MFM"
enableAnimatedMfm: "Включить анимированную разметку MFM"
doing: "В процессе" doing: "В процессе"
category: "Категория" category: "Категория"
tags: "Метки" tags: "Метки"
@@ -780,6 +779,7 @@ popularPosts: "Популярные публикации"
shareWithNote: "Поделиться заметкой" shareWithNote: "Поделиться заметкой"
ads: "Реклама" ads: "Реклама"
expiration: "Опрос длится" expiration: "Опрос длится"
startingperiod: "Начальный период"
memo: "Памятка" memo: "Памятка"
priority: "Приоритет" priority: "Приоритет"
high: "Высокий" high: "Высокий"
@@ -812,6 +812,7 @@ lastCommunication: "Последнее сообщение"
resolved: "Решено" resolved: "Решено"
unresolved: "Без решения" unresolved: "Без решения"
breakFollow: "Отписка" breakFollow: "Отписка"
breakFollowConfirm: "Удалить из подписок пользователя ?"
itsOn: "Включено" itsOn: "Включено"
itsOff: "Выключено" itsOff: "Выключено"
emailRequiredForSignup: "Для регистрации учётной записи нужен адрес электронной почты" emailRequiredForSignup: "Для регистрации учётной записи нужен адрес электронной почты"
@@ -831,8 +832,6 @@ deleteAccountConfirm: "Учётная запись будет безвозвра
incorrectPassword: "Пароль неверен." incorrectPassword: "Пароль неверен."
voteConfirm: "Отдать голос за «{choice}»?" voteConfirm: "Отдать голос за «{choice}»?"
hide: "Спрятать" hide: "Спрятать"
leaveGroup: "Покинуть группу"
leaveGroupConfirm: "Покинуть группу «{name}»?"
useDrawerReactionPickerForMobile: "Выдвижная палитра на мобильном устройстве" useDrawerReactionPickerForMobile: "Выдвижная палитра на мобильном устройстве"
welcomeBackWithName: "С возвращением, {name}!" welcomeBackWithName: "С возвращением, {name}!"
clickToFinishEmailVerification: "Пожалуйста, нажмите [{ok}], чтобы завершить подтверждение адреса электронной почты." clickToFinishEmailVerification: "Пожалуйста, нажмите [{ok}], чтобы завершить подтверждение адреса электронной почты."
@@ -848,6 +847,7 @@ instanceDefaultLightTheme: "Светлая тема по умолчанию"
instanceDefaultDarkTheme: "Темная тема по умолчанию" instanceDefaultDarkTheme: "Темная тема по умолчанию"
instanceDefaultThemeDescription: "Описание темы по умолчанию для инстанса" instanceDefaultThemeDescription: "Описание темы по умолчанию для инстанса"
mutePeriod: "Продолжительность скрытия" mutePeriod: "Продолжительность скрытия"
period: "Опрос длится"
indefinitely: "вечно" indefinitely: "вечно"
tenMinutes: "10 минут" tenMinutes: "10 минут"
oneHour: "1 час" oneHour: "1 час"
@@ -855,8 +855,11 @@ oneDay: "1 день"
oneWeek: "1 неделя" oneWeek: "1 неделя"
reflectMayTakeTime: "Изменения могут занять время для отображения" reflectMayTakeTime: "Изменения могут занять время для отображения"
failedToFetchAccountInformation: "Не удалось получить информацию об аккаунте" failedToFetchAccountInformation: "Не удалось получить информацию об аккаунте"
rateLimitExceeded: "Ограничение скорости превышено"
cropImage: "Кадрирование" cropImage: "Кадрирование"
cropImageAsk: "Нужно ли кадрировать изображение?" cropImageAsk: "Нужно ли кадрировать изображение?"
cropYes: "Обрезать"
cropNo: "Не обрезать"
file: "Файлы" file: "Файлы"
recentNHours: "Последние {n} ч" recentNHours: "Последние {n} ч"
recentNDays: "Последние {n} сут" recentNDays: "Последние {n} сут"
@@ -883,6 +886,8 @@ refreshInterval: "Интервал перезагрузки"
label: "Метка" label: "Метка"
type: "Тип" type: "Тип"
speed: "Скорость" speed: "Скорость"
slow: "Медленная"
fast: "Быстрая"
sensitiveMediaDetection: "Определение содержимого деликатного характера" sensitiveMediaDetection: "Определение содержимого деликатного характера"
localOnly: "Локально" localOnly: "Локально"
remoteOnly: "Только удалённо" remoteOnly: "Только удалённо"
@@ -933,6 +938,20 @@ cannotPerformTemporaryDescription: "Это действие временно н
preset: "Шаблоны" preset: "Шаблоны"
selectFromPresets: "Выбрать из шаблонов" selectFromPresets: "Выбрать из шаблонов"
achievements: "Достижения" achievements: "Достижения"
gotInvalidResponseError: "Сервер ответил ошибкой"
gotInvalidResponseErrorDescription: "Сервер временно не доступен. Возможно проводятся технические работы, или сервер отключен."
thisPostMayBeAnnoying: "Это сообщение может быть неприятным."
thisPostMayBeAnnoyingHome: "Этот пост может быть отправлен на главную"
thisPostMayBeAnnoyingCancel: "Этот пост не может быть отменен."
thisPostMayBeAnnoyingIgnore: "Этот пост может быть проигнорирован "
collapseRenotes: "Свернуть репосты"
internalServerError: "Внутренняя ошибка сервера"
internalServerErrorDescription: "Внутри сервера произошла непредвиденная ошибка."
copyErrorInfo: "Скопировать код ошибки"
joinThisServer: "Присоединяйтесь к этому серверу"
exploreOtherServers: "Искать другие сервера"
letsLookAtTimeline: "Давайте посмотрим на ленту"
disableFederationWarn: "Объединение отключено. Если вы отключите это, сообщение не будет приватным. В большинстве случаев вам не нужно включать эту опцию."
_achievements: _achievements:
earnedAt: "Разблокировано в" earnedAt: "Разблокировано в"
_types: _types:
@@ -1189,6 +1208,9 @@ _role:
baseRole: "Шаблон роли" baseRole: "Шаблон роли"
useBaseValue: "Использовать значение из шаблона" useBaseValue: "Использовать значение из шаблона"
chooseRoleToAssign: "Выберите роль, которую хотите выдать" chooseRoleToAssign: "Выберите роль, которую хотите выдать"
iconUrl: "Адрес на иконку роли"
asBadge: "Показывать как значок"
descriptionOfAsBadge: "Описание значка"
canEditMembersByModerator: "Могут назначать модераторы" canEditMembersByModerator: "Могут назначать модераторы"
descriptionOfCanEditMembersByModerator: "Если включено, на эту роль могут назначать пользователей как администраторы, так и модераторы. Если выключено, назначать могут только администраторы." descriptionOfCanEditMembersByModerator: "Если включено, на эту роль могут назначать пользователей как администраторы, так и модераторы. Если выключено, назначать могут только администраторы."
priority: "Приоритет" priority: "Приоритет"
@@ -1206,6 +1228,7 @@ _role:
pinMax: "Доступное количество закреплённых заметок" pinMax: "Доступное количество закреплённых заметок"
antennaMax: "Доступное количество антенн" antennaMax: "Доступное количество антенн"
wordMuteMax: "Доступное количество знаков в списке скрытия слов" wordMuteMax: "Доступное количество знаков в списке скрытия слов"
webhookMax: "Максимум web-хуков"
clipMax: "Максимальное количество подборок" clipMax: "Максимальное количество подборок"
noteEachClipsMax: "Максимальное количество заметок в подборке" noteEachClipsMax: "Максимальное количество заметок в подборке"
userListMax: "Максимальное количество списков аккаунтов" userListMax: "Максимальное количество списков аккаунтов"
@@ -1227,7 +1250,12 @@ _role:
not: "Кроме тех, у кого…" not: "Кроме тех, у кого…"
_sensitiveMediaDetection: _sensitiveMediaDetection:
description: "Машинное обучение может быть использовано для автоматического обнаружения чувствительных медиа для модерации. Нагрузка на сервер увеличивается незначительно." description: "Машинное обучение может быть использовано для автоматического обнаружения чувствительных медиа для модерации. Нагрузка на сервер увеличивается незначительно."
sensitivity: "Чувствительность обнаружения"
sensitivityDescription: "Более низкая чувствительность уменьшает количество ложных срабатываний (false positives). Повышение чувствительности уменьшает утечку при обнаружении (ложноотрицательные результаты)."
setSensitiveFlagAutomatically: "Установить флаг NSFW" setSensitiveFlagAutomatically: "Установить флаг NSFW"
setSensitiveFlagAutomaticallyDescription: "Даже если этот параметр отключен, результат оценки сохраняется внутри системы."
analyzeVideos: "Анализировать видео?"
analyzeVideosDescription: "Анализируйте видео в дополнение к неподвижным изображениям. Нагрузка на сервер немного увеличивается."
_emailUnavailable: _emailUnavailable:
used: "Уже используется" used: "Уже используется"
format: "Неверный формат" format: "Неверный формат"
@@ -1437,6 +1465,7 @@ _ago:
weeksAgo: "{n} нед. назад" weeksAgo: "{n} нед. назад"
monthsAgo: "{n} мес. назад" monthsAgo: "{n} мес. назад"
yearsAgo: "{n} г. назад" yearsAgo: "{n} г. назад"
invalid: "Ничего нет"
_time: _time:
second: "с" second: "с"
minute: "мин" minute: "мин"
@@ -1470,14 +1499,29 @@ _tutorial:
step8_3: "Эту настройку вы всегда сможете поменять" step8_3: "Эту настройку вы всегда сможете поменять"
_2fa: _2fa:
alreadyRegistered: "Двухфакторная аутентификация уже настроена." alreadyRegistered: "Двухфакторная аутентификация уже настроена."
registerDevice: "Зарегистрируйте ваше устройство" registerTOTP: "Начните настраивать приложение-аутентификатор"
registerKey: "Зарегистрировать ключ" passwordToTOTP: "Пожалуйста, введите свой пароль"
step1: "Прежде всего, установите на устройство приложение для аутентификации, например, {a} или {b}." step1: "Прежде всего, установите на устройство приложение для аутентификации, например, {a} или {b}."
step2: "Далее отсканируйте отображаемый QR-код при помощи приложения." step2: "Далее отсканируйте отображаемый QR-код при помощи приложения."
step2Click: "Нажав на QR-код, вы можете зарегистрироваться с помощью приложения для аутентификации или брелка для ключей, установленного на вашем устройстве."
step2Url: "Если пользуетесь приложением на компьютере, можете ввести в него эту строку (URL):" step2Url: "Если пользуетесь приложением на компьютере, можете ввести в него эту строку (URL):"
step3Title: "Введите проверочный код"
step3: "И наконец, введите код, который покажет приложение." step3: "И наконец, введите код, который покажет приложение."
step4: "Теперь при каждом входе на сайт вам нужно будет вводить код из приложения аналогичным образом." step4: "Теперь при каждом входе на сайт вам нужно будет вводить код из приложения аналогичным образом."
securityKeyNotSupported: "Ваш браузер не поддерживает ключи безопасности."
registerTOTPBeforeKey: "Чтобы зарегистрировать ключ безопасности и пароль, сначала настройте приложение аутентификации."
securityKeyInfo: "Вы можете настроить вход с помощью аппаратного ключа безопасности, поддерживающего FIDO2, или отпечатка пальца или PIN-кода на устройстве." securityKeyInfo: "Вы можете настроить вход с помощью аппаратного ключа безопасности, поддерживающего FIDO2, или отпечатка пальца или PIN-кода на устройстве."
chromePasskeyNotSupported: "В настоящее время Chrome не поддерживает пароль-ключи."
registerSecurityKey: "Зарегистрируйте ключ безопасности ・Passkey"
securityKeyName: "Введите имя для ключа"
tapSecurityKey: "Пожалуйста, следуйте инструкциям в вашем браузере, чтобы зарегистрировать свой ключ безопасности или пароль"
removeKey: "Удалить ключ безопасности"
removeKeyConfirm: "Удалить резервную копию «{name}»?"
whyTOTPOnlyRenew: "Если ключ безопасности зарегистрирован, вы не сможете отключить приложение аутентификации."
renewTOTP: "Перенастроите приложение аутентификации"
renewTOTPConfirm: "Проверочный код предыдущего приложения для аутентификации больше не будет доступен"
renewTOTPOk: "Настроить"
renewTOTPCancel: "Нет, спасибо"
_permissions: _permissions:
"read:account": "Просматривать данные учётной записи" "read:account": "Просматривать данные учётной записи"
"write:account": "Изменять данные учётной записи" "write:account": "Изменять данные учётной записи"
@@ -1512,18 +1556,20 @@ _permissions:
"read:gallery-likes": "Просмотр списка понравившегося в галерее" "read:gallery-likes": "Просмотр списка понравившегося в галерее"
"write:gallery-likes": "Изменение списка понравившегося в галерее" "write:gallery-likes": "Изменение списка понравившегося в галерее"
_auth: _auth:
shareAccessTitle: "Разрешения для приложений"
shareAccess: "Дать доступ для «{name}» к вашей учётной записи?" shareAccess: "Дать доступ для «{name}» к вашей учётной записи?"
shareAccessAsk: "Уверены, что хотите дать приложению доступ к своей учётной записи?" shareAccessAsk: "Уверены, что хотите дать приложению доступ к своей учётной записи?"
permission: "{name} Запрашивает следующие разрешения:"
permissionAsk: "Приложение запрашивает следующие разрешения:" permissionAsk: "Приложение запрашивает следующие разрешения:"
pleaseGoBack: "Вернитесь, пожалуйста, в приложение" pleaseGoBack: "Вернитесь, пожалуйста, в приложение"
callback: "Возврат в приложение" callback: "Возврат в приложение"
denied: "Доступ закрыт" denied: "Доступ закрыт"
pleaseLogin: "Вы должны войти в систему, чтобы дать разрешение приложению."
_antennaSources: _antennaSources:
all: "Все заметки" all: "Все заметки"
homeTimeline: "Заметки тех на которых вы подписаны" homeTimeline: "Заметки тех на которых вы подписаны"
users: "Заметки выбранных пользователей" users: "Заметки выбранных пользователей"
userList: "Заметки пользователей из выбранных списков" userList: "Заметки пользователей из выбранных списков"
userGroup: "Заметки от пользователей из заданной группы"
_weekday: _weekday:
sunday: "Воскресенье" sunday: "Воскресенье"
monday: "Понедельник" monday: "Понедельник"
@@ -1598,8 +1644,8 @@ _visibility:
followersDescription: "Только вашим подписчикам" followersDescription: "Только вашим подписчикам"
specified: "Личное" specified: "Личное"
specifiedDescription: "Тем, кого укажете" specifiedDescription: "Тем, кого укажете"
localOnly: "Локально" disableFederation: "Отключить федерацию"
localOnlyDescription: "Только для этого сайта" disableFederationDescription: "Не доставляет в другие экземпляры"
_postForm: _postForm:
replyPlaceholder: "Ответ на заметку..." replyPlaceholder: "Ответ на заметку..."
quotePlaceholder: "Пояснение к цитате..." quotePlaceholder: "Пояснение к цитате..."
@@ -1664,7 +1710,16 @@ _timelines:
social: "Социальная" social: "Социальная"
global: "Всеобщая" global: "Всеобщая"
_play: _play:
new: "Создать приложение "
edit: "Редактировать приложение"
created: "Приложение создано"
updated: "Приложение обновлено"
deleted: "Приложение удалено"
pageSetting: "Настройки приложения"
editThisPage: "Отредактировать страницу"
viewSource: "Просмотр исходника" viewSource: "Просмотр исходника"
my: "Мои приложения "
liked: "Понравилось"
featured: "Популярные" featured: "Популярные"
title: "Заголовок" title: "Заголовок"
script: "Скрипт" script: "Скрипт"
@@ -1728,13 +1783,11 @@ _notification:
youGotReply: "{name} отвечает вам." youGotReply: "{name} отвечает вам."
youGotQuote: "{name} цитирует вас." youGotQuote: "{name} цитирует вас."
youRenoted: "{name} передаёт вашу заметку." youRenoted: "{name} передаёт вашу заметку."
youGotMessagingMessageFromUser: "{name} пишет вам."
youGotMessagingMessageFromGroup: "Новое сообщение в группе «{name}»."
youWereFollowed: "У вас новый подписчик." youWereFollowed: "У вас новый подписчик."
youReceivedFollowRequest: "У вас новый запрос на подписку." youReceivedFollowRequest: "У вас новый запрос на подписку."
yourFollowRequestAccepted: "Ваш запрос на подписку одобрен." yourFollowRequestAccepted: "Ваш запрос на подписку одобрен."
youWereInvitedToGroup: "Вы приглашены в группу."
pollEnded: "Подведены окончательные итоги опроса" pollEnded: "Подведены окончательные итоги опроса"
unreadAntennaNote: "Антенна {name}"
emptyPushNotificationMessage: "Обновлены push-уведомления" emptyPushNotificationMessage: "Обновлены push-уведомления"
achievementEarned: "Получено достижение" achievementEarned: "Получено достижение"
_types: _types:
@@ -1748,7 +1801,7 @@ _notification:
pollEnded: "Окончания опросов" pollEnded: "Окончания опросов"
receiveFollowRequest: "Получен запрос на подписку" receiveFollowRequest: "Получен запрос на подписку"
followRequestAccepted: "Запрос на подписку одобрен" followRequestAccepted: "Запрос на подписку одобрен"
groupInvited: "Приглашение в группы" achievementEarned: "Получение достижений"
app: "Уведомления из приложений" app: "Уведомления из приложений"
_actions: _actions:
followBack: "отвечает взаимной подпиской" followBack: "отвечает взаимной подпиской"
@@ -1781,3 +1834,6 @@ _deck:
channel: "Каналы" channel: "Каналы"
mentions: "Упоминания" mentions: "Упоминания"
direct: "Личное" direct: "Личное"
_dialog:
charactersExceeded: "Превышено максимальное количество символов! У вас {current} / из {max}"
charactersBelow: "Это ниже минимального количества символов! У вас {current} / из {min}"

View File

@@ -103,6 +103,8 @@ renoted: "Preposlané."
cantRenote: "Tento príspevok sa nedá preposlať." cantRenote: "Tento príspevok sa nedá preposlať."
cantReRenote: "Odpoveď nemôže byť odstránená." cantReRenote: "Odpoveď nemôže byť odstránená."
quote: "Citovať" quote: "Citovať"
inChannelRenote: "Preposlania v kanáli"
inChannelQuote: "Citácie v kanáli"
pinnedNote: "Pripnuté poznámky" pinnedNote: "Pripnuté poznámky"
pinned: "Pripnúť" pinned: "Pripnúť"
you: "Vy" you: "Vy"
@@ -129,6 +131,7 @@ unblockConfirm: "Naozaj chcete odblokovať tento účet?"
suspendConfirm: "Naozaj chcete zmraziť tento účet?" suspendConfirm: "Naozaj chcete zmraziť tento účet?"
unsuspendConfirm: "Naozaj chcete odmraziť tento účet?" unsuspendConfirm: "Naozaj chcete odmraziť tento účet?"
selectList: "Vyberte zoznam" selectList: "Vyberte zoznam"
selectChannel: "Zvoľte kanál"
selectAntenna: "Vyberte anténu" selectAntenna: "Vyberte anténu"
selectWidget: "Vyberte widget" selectWidget: "Vyberte widget"
editWidgets: "Upraviť widget" editWidgets: "Upraviť widget"
@@ -256,6 +259,8 @@ noMoreHistory: "To je všetko"
startMessaging: "Začať chat" startMessaging: "Začať chat"
nUsersRead: "prečítané {n} používateľmi" nUsersRead: "prečítané {n} používateľmi"
agreeTo: "Súhlasím s {0}" agreeTo: "Súhlasím s {0}"
agreeBelow: "Súhlasím s nasledovným"
basicNotesBeforeCreateAccount: "Základné bezpečnostné opatrenia"
tos: "Podmienky používania" tos: "Podmienky používania"
start: "Začať" start: "Začať"
home: "Domov" home: "Domov"
@@ -388,16 +393,19 @@ about: "Informácie"
aboutMisskey: "O Misskey" aboutMisskey: "O Misskey"
administrator: "Administrátor" administrator: "Administrátor"
token: "Token" token: "Token"
twoStepAuthentication: "Dvojfaktorová autentifikácia" 2fa: "Dvojfaktorové overenie (2FA)"
totp: "Overovacia aplikácia"
totpDescription: "Zadajte jednorazové heslo z overovacej aplikácie"
moderator: "Moderátor" moderator: "Moderátor"
moderation: "Moderovanie" moderation: "Moderovanie"
nUsersMentioned: "{n} používateľov spomenulo" nUsersMentioned: "{n} používateľov spomenulo"
securityKeyAndPasskey: "Bezpečnostný kľúč/heslo"
securityKey: "Bezpečnostný kľúč" securityKey: "Bezpečnostný kľúč"
securityKeyName: "Názov kľúča"
registerSecurityKey: "Registrovať bezpečnostný kľúč"
lastUsed: "Naposledy použité" lastUsed: "Naposledy použité"
lastUsedAt: "Naposledy použité: {t}"
unregister: "Odregistrovať" unregister: "Odregistrovať"
passwordLessLogin: "Nastaviť bezheslové prihlásenie" passwordLessLogin: "Nastaviť bezheslové prihlásenie"
passwordLessLoginDescription: "Prihlásenie bez hesla, len bezpečnostným kľúčom alebo prístupovým kľúčom"
resetPassword: "Resetovať heslo" resetPassword: "Resetovať heslo"
newPasswordIs: "Nové heslo je \"{password}\"" newPasswordIs: "Nové heslo je \"{password}\""
reduceUiAnimation: "Menej UI animácií" reduceUiAnimation: "Menej UI animácií"
@@ -412,24 +420,15 @@ markAsReadAllTalkMessages: "Označiť všetky správy ako prečítané"
help: "Pomoc" help: "Pomoc"
inputMessageHere: "Sem napíšte správu" inputMessageHere: "Sem napíšte správu"
close: "Zavrieť" close: "Zavrieť"
group: "Skupina"
groups: "Skupiny"
createGroup: "Vytvoriť skupinu"
ownedGroups: "Vlastnené skupiny"
joinedGroups: "Členstvo v skupinách"
invites: "Pozvať" invites: "Pozvať"
groupName: "Názov skupiny"
members: "Členovia" members: "Členovia"
transfer: "Presun" transfer: "Presun"
messagingWithUser: "Súkromný chat"
messagingWithGroup: "Skupinový chat"
title: "Nadpis" title: "Nadpis"
text: "Text" text: "Text"
enable: "Povoliť" enable: "Povoliť"
next: "Ďalší" next: "Ďalší"
retype: "Zadajte znovu" retype: "Zadajte znovu"
noteOf: "Poznámky používateľa {user}" noteOf: "Poznámky používateľa {user}"
inviteToGroup: "Pozvať do skupiny"
quoteAttached: "Citované" quoteAttached: "Citované"
quoteQuestion: "Pripojiť ako citát?" quoteQuestion: "Pripojiť ako citát?"
noMessagesYet: "Zatiaľ žiadne správy" noMessagesYet: "Zatiaľ žiadne správy"
@@ -451,19 +450,18 @@ passwordMatched: "Heslá sú rovnaké"
passwordNotMatched: "Heslá nie sú rovnaké" passwordNotMatched: "Heslá nie sú rovnaké"
signinWith: "Prihlásiť sa použitím {x}" signinWith: "Prihlásiť sa použitím {x}"
signinFailed: "Nedá sa prihlásiť. Skontrolujte prosím meno používateľa a heslo." signinFailed: "Nedá sa prihlásiť. Skontrolujte prosím meno používateľa a heslo."
tapSecurityKey: "Ťuknite na bezpečnostný kľúč"
or: "Alebo" or: "Alebo"
language: "Jazyk" language: "Jazyk"
uiLanguage: "Jazyk používateľského prostredia" uiLanguage: "Jazyk používateľského prostredia"
groupInvited: "Pozvať do skupiny"
aboutX: "O {x}" aboutX: "O {x}"
emojiStyle: "Štýl emoji" emojiStyle: "Štýl emoji"
native: "Natívne" native: "Natívne"
disableDrawer: "Nepoužívať šuflíkové menu" disableDrawer: "Nepoužívať šuflíkové menu"
youHaveNoGroups: "Nemáte žiadne skupiny" showNoteActionsOnlyHover: "Ovládacie prvky poznámky sa zobrazujú len po nabehnutí myši"
joinOrCreateGroup: "Požiadajte o pozvanie do existujúcej skupiny alebo vytvorte novú."
noHistory: "Žiadna história" noHistory: "Žiadna história"
signinHistory: "História prihlásení" signinHistory: "História prihlásení"
enableAdvancedMfm: "Povolenie pokročilého MFM"
enableAnimatedMfm: "Povoliť animované MFM"
doing: "Pracujem..." doing: "Pracujem..."
category: "Kategórie" category: "Kategórie"
tags: "Značky" tags: "Značky"
@@ -572,6 +570,7 @@ manage: "Administrácia"
plugins: "Pluginy" plugins: "Pluginy"
preferencesBackups: "Zálohy nastavení" preferencesBackups: "Zálohy nastavení"
deck: "Deck" deck: "Deck"
undeck: "Oddokovať"
useBlurEffectForModal: "Použiť efekt rozmazania na okná" useBlurEffectForModal: "Použiť efekt rozmazania na okná"
useFullReactionPicker: "Použiť plnú veľkosť výberu reakcií" useFullReactionPicker: "Použiť plnú veľkosť výberu reakcií"
width: "Šírka" width: "Šírka"
@@ -781,6 +780,7 @@ popularPosts: "Populárne príspevky"
shareWithNote: "Zdieľať s poznámkou" shareWithNote: "Zdieľať s poznámkou"
ads: "Reklamy" ads: "Reklamy"
expiration: "Ukončiť hlasovanie" expiration: "Ukončiť hlasovanie"
startingperiod: "Začiatok"
memo: "Memo" memo: "Memo"
priority: "Priorita" priority: "Priorita"
high: "Vysoká" high: "Vysoká"
@@ -832,8 +832,6 @@ deleteAccountConfirm: "Toto nezvrátiteľne vymaže váš účet. Pokračovať?"
incorrectPassword: "Nesprávne heslo." incorrectPassword: "Nesprávne heslo."
voteConfirm: "Potvrdzujete svoj hlas za \"{choice}\"?" voteConfirm: "Potvrdzujete svoj hlas za \"{choice}\"?"
hide: "Skryť" hide: "Skryť"
leaveGroup: "Opustiť skupiny"
leaveGroupConfirm: "Naozaj chcete opustiť \"{name}\"?"
useDrawerReactionPickerForMobile: "Zobraziť výber reakcií ako šuflík na mobile" useDrawerReactionPickerForMobile: "Zobraziť výber reakcií ako šuflík na mobile"
welcomeBackWithName: "Vitajte späť, {name}" welcomeBackWithName: "Vitajte späť, {name}"
clickToFinishEmailVerification: "Kliknutím na [{ok}] dokončíte overeniu emailu." clickToFinishEmailVerification: "Kliknutím na [{ok}] dokončíte overeniu emailu."
@@ -849,11 +847,13 @@ instanceDefaultLightTheme: "Predvolená svetlá téma"
instanceDefaultDarkTheme: "Predvolená tmavá téma" instanceDefaultDarkTheme: "Predvolená tmavá téma"
instanceDefaultThemeDescription: "Vložte kód témy v objektovom formáte" instanceDefaultThemeDescription: "Vložte kód témy v objektovom formáte"
mutePeriod: "Trvanie stíšenia" mutePeriod: "Trvanie stíšenia"
period: "Ukončiť hlasovanie"
indefinitely: "Navždy" indefinitely: "Navždy"
tenMinutes: "10 minút" tenMinutes: "10 minút"
oneHour: "1 hodina" oneHour: "1 hodina"
oneDay: "1 deň" oneDay: "1 deň"
oneWeek: "1 týždeň" oneWeek: "1 týždeň"
oneMonth: "1 mesiac"
reflectMayTakeTime: "Zmeny môžu chvíľu trvať kým sa prejavia." reflectMayTakeTime: "Zmeny môžu chvíľu trvať kým sa prejavia."
failedToFetchAccountInformation: "Nepodarilo sa načítať informácie o účte." failedToFetchAccountInformation: "Nepodarilo sa načítať informácie o účte."
rateLimitExceeded: "Prekročený limit rýchlosti" rateLimitExceeded: "Prekročený limit rýchlosti"
@@ -1141,6 +1141,7 @@ _ago:
weeksAgo: "pred {n} týždňami" weeksAgo: "pred {n} týždňami"
monthsAgo: "pred {n} mesiacmi" monthsAgo: "pred {n} mesiacmi"
yearsAgo: "pred {n} rokmi" yearsAgo: "pred {n} rokmi"
invalid: "Nič tu nie je"
_time: _time:
second: "s" second: "s"
minute: "min" minute: "min"
@@ -1174,14 +1175,14 @@ _tutorial:
step8_3: "Nastavenia notifikácií môžete neskôr zmeniť." step8_3: "Nastavenia notifikácií môžete neskôr zmeniť."
_2fa: _2fa:
alreadyRegistered: "Už ste zaregistrovali 2-faktorové autentifikačné zariadenie." alreadyRegistered: "Už ste zaregistrovali 2-faktorové autentifikačné zariadenie."
registerDevice: "Registrovať nové zariadenie"
registerKey: "Registrovať bezpečnostný kľúč"
step1: "Najprv si nainštalujte autentifikačnú aplikáciu (napríklad {a} alebo {b}) na svoje zariadenie." step1: "Najprv si nainštalujte autentifikačnú aplikáciu (napríklad {a} alebo {b}) na svoje zariadenie."
step2: "Potom, naskenujte QR kód zobrazený na obrazovke." step2: "Potom, naskenujte QR kód zobrazený na obrazovke."
step2Url: "Do aplikácie zadajte nasledujúcu URL adresu:" step2Url: "Do aplikácie zadajte nasledujúcu URL adresu:"
step3: "Nastavenie dokončíte zadaním tokenu z vašej aplikácie." step3: "Nastavenie dokončíte zadaním tokenu z vašej aplikácie."
step4: "Od teraz, všetky ďalšie prihlásenia budú vyžadovať prihlasovací token." step4: "Od teraz, všetky ďalšie prihlásenia budú vyžadovať prihlasovací token."
securityKeyInfo: "Okrem odtlačku prsta alebo PIN autentifikácie si môžete nastaviť autentifikáciu cez hardvérový bezpečnostný kľúč podporujúci FIDO2 a tak ešte viac zabezpečiť svoj účet." securityKeyInfo: "Okrem odtlačku prsta alebo PIN autentifikácie si môžete nastaviť autentifikáciu cez hardvérový bezpečnostný kľúč podporujúci FIDO2 a tak ešte viac zabezpečiť svoj účet."
removeKeyConfirm: "Naozaj chcete odstrániť \"{name}\"?"
renewTOTPCancel: "Nie, ďakujem"
_permissions: _permissions:
"read:account": "Vidieť informácie o vašom účte" "read:account": "Vidieť informácie o vašom účte"
"write:account": "Upraviť informácie o vašom účte" "write:account": "Upraviť informácie o vašom účte"
@@ -1227,7 +1228,6 @@ _antennaSources:
homeTimeline: "Poznámky od sledovaného používateľa" homeTimeline: "Poznámky od sledovaného používateľa"
users: "Poznámky od konkrétneho používateľa" users: "Poznámky od konkrétneho používateľa"
userList: "Poznámky od používateľov v zozname" userList: "Poznámky od používateľov v zozname"
userGroup: "Poznámky od používateľov z konkrétnej skupiny."
_weekday: _weekday:
sunday: "Nedeľa" sunday: "Nedeľa"
monday: "Pondelok" monday: "Pondelok"
@@ -1299,8 +1299,6 @@ _visibility:
followersDescription: "Viditeľné iba tým, ktorí vás sledujú" followersDescription: "Viditeľné iba tým, ktorí vás sledujú"
specified: "Priame" specified: "Priame"
specifiedDescription: "Viditeľné iba pre konkrétnych používateľov" specifiedDescription: "Viditeľné iba pre konkrétnych používateľov"
localOnly: "Iba lokálne"
localOnlyDescription: "Vzdialený používatelia nebudú vidieť"
_postForm: _postForm:
replyPlaceholder: "Odpoveď na túto poznámku..." replyPlaceholder: "Odpoveď na túto poznámku..."
quotePlaceholder: "Citovanie tejto poznámky..." quotePlaceholder: "Citovanie tejto poznámky..."
@@ -1428,12 +1426,9 @@ _notification:
youGotReply: "{name} vám odpovedal/a" youGotReply: "{name} vám odpovedal/a"
youGotQuote: "{name} vás citoval/a" youGotQuote: "{name} vás citoval/a"
youRenoted: "{name} preposlal/a vašu poznámku" youRenoted: "{name} preposlal/a vašu poznámku"
youGotMessagingMessageFromUser: "{name} vám poslal/a správu"
youGotMessagingMessageFromGroup: "Prišla správa do skupiny {name}"
youWereFollowed: "Máte nového sledujúceho" youWereFollowed: "Máte nového sledujúceho"
youReceivedFollowRequest: "Dostali ste žiadosť o sledovanie" youReceivedFollowRequest: "Dostali ste žiadosť o sledovanie"
yourFollowRequestAccepted: "Vaša žiadosť o sledovanie bola prijatá" yourFollowRequestAccepted: "Vaša žiadosť o sledovanie bola prijatá"
youWereInvitedToGroup: "Pozvať do skupiny"
pollEnded: "Výsledky hlasovania sú k dispozícii." pollEnded: "Výsledky hlasovania sú k dispozícii."
unreadAntennaNote: "Anténa {name}" unreadAntennaNote: "Anténa {name}"
emptyPushNotificationMessage: "Push notifikácie aktualizované" emptyPushNotificationMessage: "Push notifikácie aktualizované"
@@ -1448,7 +1443,6 @@ _notification:
pollEnded: "Hlasovanie skončilo" pollEnded: "Hlasovanie skončilo"
receiveFollowRequest: "Doručené žiadosti o sledovanie" receiveFollowRequest: "Doručené žiadosti o sledovanie"
followRequestAccepted: "Schválené žiadosti o sledovanie" followRequestAccepted: "Schválené žiadosti o sledovanie"
groupInvited: "Pozvánky do skupín"
app: "Oznámenia z prepojených aplikácií" app: "Oznámenia z prepojených aplikácií"
_actions: _actions:
followBack: "Sledovať späť\n" followBack: "Sledovať späť\n"

View File

@@ -383,12 +383,13 @@ _sfx:
notification: "Notifikationer" notification: "Notifikationer"
chat: "Chatt" chat: "Chatt"
antenna: "Antenner" antenna: "Antenner"
_2fa:
renewTOTPCancel: "Nej tack"
_antennaSources: _antennaSources:
all: "Alla noter" all: "Alla noter"
homeTimeline: "Noter från följda användare" homeTimeline: "Noter från följda användare"
users: "Noter från specifika användare" users: "Noter från specifika användare"
userList: "Noter från en specificerad lista av användare" userList: "Noter från en specificerad lista av användare"
userGroup: "Noter från användare i en specificerad grupp"
_widgets: _widgets:
profile: "Profil" profile: "Profil"
instanceInfo: "Instansinformation" instanceInfo: "Instansinformation"

View File

@@ -103,6 +103,8 @@ renoted: "รีโน้ตเอาไว้"
cantRenote: "โพสต์นี้ไม่สามารถรีโน้ตไว้ใหม่ได้นะ" cantRenote: "โพสต์นี้ไม่สามารถรีโน้ตไว้ใหม่ได้นะ"
cantReRenote: "ไม่สามารถรีโน้ตเอาไว้ใหม่ได้นะ" cantReRenote: "ไม่สามารถรีโน้ตเอาไว้ใหม่ได้นะ"
quote: "อ้างคำพูด" quote: "อ้างคำพูด"
inChannelRenote: "รีโน้ตช่องแชลแนลเท่านั้น"
inChannelQuote: "อ้างช่องเท่านั้น"
pinnedNote: "โน้ตที่ปักหมุดเอาไว้" pinnedNote: "โน้ตที่ปักหมุดเอาไว้"
pinned: "ปักหมุดไปยังโปรไฟล์" pinned: "ปักหมุดไปยังโปรไฟล์"
you: "ตัวเอง" you: "ตัวเอง"
@@ -257,6 +259,8 @@ noMoreHistory: "ในนั้นไม่มีประวัติอีก
startMessaging: "เริ่มการสนทนา" startMessaging: "เริ่มการสนทนา"
nUsersRead: "อ่านโดย {n}" nUsersRead: "อ่านโดย {n}"
agreeTo: "ฉันยอมรับที่จะ {0}" agreeTo: "ฉันยอมรับที่จะ {0}"
agreeBelow: "ฉันยอมรับถึงด้านล่าง"
basicNotesBeforeCreateAccount: "หมายเหตุสำคัญ"
tos: "ข้อกำหนดและเงื่อนไข" tos: "ข้อกำหนดและเงื่อนไข"
start: "เริ่มต้น​ใช้งาน​" start: "เริ่มต้น​ใช้งาน​"
home: "หน้าแรก" home: "หน้าแรก"
@@ -389,16 +393,19 @@ about: "เกี่ยวกับ"
aboutMisskey: "เกี่ยวกับ Misskey" aboutMisskey: "เกี่ยวกับ Misskey"
administrator: "ผู้ดูแลระบบ" administrator: "ผู้ดูแลระบบ"
token: "โทเค็น" token: "โทเค็น"
twoStepAuthentication: "ยืนยันตัวตน 2 ชั้น" 2fa: "การยืนยันตัวตนแบบสองชั้น"
totp: "แอป Authenticator"
totpDescription: "ใช้แอปยืนยันตัวตนเพื่อป้อนรหัสผ่านแบบใช้ครั้งเดียว"
moderator: "ผู้ควบคุม" moderator: "ผู้ควบคุม"
moderation: "การกลั่นกรอง" moderation: "การกลั่นกรอง"
nUsersMentioned: "กล่าวถึงโดยผู้ใช้ {n} รายนี้" nUsersMentioned: "กล่าวถึงโดยผู้ใช้ {n} รายนี้"
securityKeyAndPasskey: "ความปลอดภัยและรหัสผ่าน"
securityKey: "กุญแจความปลอดภัย" securityKey: "กุญแจความปลอดภัย"
securityKeyName: "ชื่อคีย์"
registerSecurityKey: "ลงทะเบียนรหัสความปลอดภัยคีย์"
lastUsed: "ใช้ล่าสุด" lastUsed: "ใช้ล่าสุด"
lastUsedAt: "ใช้งานครั้งล่าสุด: {t}"
unregister: "เลิกติดตาม" unregister: "เลิกติดตาม"
passwordLessLogin: "เข้าสู่ระบบแบบไม่ใช้รหัสผ่าน" passwordLessLogin: "เข้าสู่ระบบแบบไม่ใช้รหัสผ่าน"
passwordLessLoginDescription: "อนุญาตให้เข้าสู่ระบบโดยไม่ต้องใช้รหัสผ่านโดยใช้รหัสรักษาความปลอดภัยหรือรหัสผ่านเท่านั้น"
resetPassword: "รีเซ็ตรหัสผ่าน" resetPassword: "รีเซ็ตรหัสผ่าน"
newPasswordIs: "รหัสผ่านใหม่คือ \"{password}\"" newPasswordIs: "รหัสผ่านใหม่คือ \"{password}\""
reduceUiAnimation: "ลดภาพเคลื่อนไหว UI" reduceUiAnimation: "ลดภาพเคลื่อนไหว UI"
@@ -413,24 +420,15 @@ markAsReadAllTalkMessages: "ทำเครื่องหมายข้อค
help: "ช่วยเหลือ" help: "ช่วยเหลือ"
inputMessageHere: "พิมพ์ข้อความที่นี่" inputMessageHere: "พิมพ์ข้อความที่นี่"
close: "ปิด" close: "ปิด"
group: "กลุ่ม"
groups: "กลุ่ม"
createGroup: "สร้างกลุ่ม"
ownedGroups: "กลุ่มที่เป็นเจ้าของ"
joinedGroups: "เข้าร่วมกลุ่ม"
invites: "เชิญชวน" invites: "เชิญชวน"
groupName: "ชื่อกลุ่ม"
members: "สมาชิก" members: "สมาชิก"
transfer: "ถ่ายโอน" transfer: "ถ่ายโอน"
messagingWithUser: "แชทส่วนตัว"
messagingWithGroup: "แชทกลุ่ม"
title: "หัวข้อ" title: "หัวข้อ"
text: "ข้อความ" text: "ข้อความ"
enable: "เปิดใช้งาน" enable: "เปิดใช้งาน"
next: "ถัด​ไป" next: "ถัด​ไป"
retype: "พิมพ์รหัสอีกครั้ง" retype: "พิมพ์รหัสอีกครั้ง"
noteOf: "โน้ต โดย {ผู้ใช้งาน}" noteOf: "โน้ต โดย {ผู้ใช้งาน}"
inviteToGroup: "ชวนเข้ากลุ่ม"
quoteAttached: "อ้างอิง" quoteAttached: "อ้างอิง"
quoteQuestion: "นายต้องการที่จะอ้างอิงหรอ?" quoteQuestion: "นายต้องการที่จะอ้างอิงหรอ?"
noMessagesYet: "ยังไม่มีข้อความนะ" noMessagesYet: "ยังไม่มีข้อความนะ"
@@ -452,19 +450,18 @@ passwordMatched: "ถูกต้อง!"
passwordNotMatched: "ไม่ถูกต้อง" passwordNotMatched: "ไม่ถูกต้อง"
signinWith: "ลงชื่อเข้าใช้ด้วย {x}" signinWith: "ลงชื่อเข้าใช้ด้วย {x}"
signinFailed: "ไม่สามารถลงชื่อผู้เข้าใช้ได้ เนื่องจาก ชื่อผู้ใช้หรือรหัสผ่านที่คุณป้อนนั้นไม่ถูกต้องนะ" signinFailed: "ไม่สามารถลงชื่อผู้เข้าใช้ได้ เนื่องจาก ชื่อผู้ใช้หรือรหัสผ่านที่คุณป้อนนั้นไม่ถูกต้องนะ"
tapSecurityKey: "แตะคีย์ความปลอดภัย"
or: "หรือ" or: "หรือ"
language: "ภาษา" language: "ภาษา"
uiLanguage: "ภาษาอินเทอร์เฟซผู้ใช้งาน" uiLanguage: "ภาษาอินเทอร์เฟซผู้ใช้งาน"
groupInvited: "คุณได้รับเชิญให้เข้าร่วมกลุ่ม"
aboutX: "เกี่ยวกับ {x}" aboutX: "เกี่ยวกับ {x}"
emojiStyle: "สไตล์อิโมจิ" emojiStyle: "สไตล์อิโมจิ"
native: "ภาษาแม่" native: "ภาษาแม่"
disableDrawer: "อย่าใช้ลิ้นชักสไตล์เมนู" disableDrawer: "อย่าใช้ลิ้นชักสไตล์เมนู"
youHaveNoGroups: "คุณยังไม่มีกลุ่ม" showNoteActionsOnlyHover: "แสดงการดำเนินการเฉพาะโน้ตเมื่อโฮเวอร์"
joinOrCreateGroup: "รับเชิญเข้าร่วมกลุ่มหรือสร้างกลุ่มของคุณเองเลยนะ"
noHistory: "ไม่มีรายการ" noHistory: "ไม่มีรายการ"
signinHistory: "ประวัติการเข้าสู่ระบบ" signinHistory: "ประวัติการเข้าสู่ระบบ"
enableAdvancedMfm: "เปิดใช้งาน MFM ขั้นสูง"
enableAnimatedMfm: "เปิดการใช้งาน MFM ด้วยแอนิเมชั่น"
doing: "กำลังประมวลผล......" doing: "กำลังประมวลผล......"
category: "หมวดหมู่" category: "หมวดหมู่"
tags: "แท็ก" tags: "แท็ก"
@@ -783,6 +780,7 @@ popularPosts: "โพสต์ติดอันดับ"
shareWithNote: "แบ่งปันด้วยโน้ต" shareWithNote: "แบ่งปันด้วยโน้ต"
ads: "โฆษณา" ads: "โฆษณา"
expiration: "กำหนดเวลา" expiration: "กำหนดเวลา"
startingperiod: "เริ่ม"
memo: "ข้อควรจำ" memo: "ข้อควรจำ"
priority: "ลำดับความสำคัญ" priority: "ลำดับความสำคัญ"
high: "สูง" high: "สูง"
@@ -815,6 +813,7 @@ lastCommunication: "การสื่อสารครั้งสุดท้
resolved: "คลี่คลายแล้ว" resolved: "คลี่คลายแล้ว"
unresolved: "รอการเฉลย" unresolved: "รอการเฉลย"
breakFollow: "ลบผู้ติดตาม" breakFollow: "ลบผู้ติดตาม"
breakFollowConfirm: "ลบผู้ติดตามนี้ออกจริงหรอ?"
itsOn: "เปิดใช้งาน" itsOn: "เปิดใช้งาน"
itsOff: "ปิดใช้งาน" itsOff: "ปิดใช้งาน"
emailRequiredForSignup: "จำเป็นต้องการใช้ที่อยู่อีเมลสำหรับการสมัคร" emailRequiredForSignup: "จำเป็นต้องการใช้ที่อยู่อีเมลสำหรับการสมัคร"
@@ -834,8 +833,6 @@ deleteAccountConfirm: "การดำเนินการนี้จะลบ
incorrectPassword: "รหัสผ่านไม่ถูกต้อง" incorrectPassword: "รหัสผ่านไม่ถูกต้อง"
voteConfirm: "ยืนยันการโหวต \"{choice}\" มั้ย?" voteConfirm: "ยืนยันการโหวต \"{choice}\" มั้ย?"
hide: "ซ่อน" hide: "ซ่อน"
leaveGroup: "ออกจากกลุ่ม"
leaveGroupConfirm: "คุณแน่ใจหรอว่าต้องการออกจาก \"{name}\""
useDrawerReactionPickerForMobile: "แสดงผล ตัวเลือกปฏิกิริยาเป็นลิ้นชักบนมือถือ" useDrawerReactionPickerForMobile: "แสดงผล ตัวเลือกปฏิกิริยาเป็นลิ้นชักบนมือถือ"
welcomeBackWithName: "ยินดีต้อนรับการกลับมานะค่ะ, {name}" welcomeBackWithName: "ยินดีต้อนรับการกลับมานะค่ะ, {name}"
clickToFinishEmailVerification: "กรุณาคลิก [{ok}] เพื่อดำเนินการยืนยันอีเมลให้เสร็จสมบูรณ์นะ" clickToFinishEmailVerification: "กรุณาคลิก [{ok}] เพื่อดำเนินการยืนยันอีเมลให้เสร็จสมบูรณ์นะ"
@@ -851,16 +848,20 @@ instanceDefaultLightTheme: "ธีมสว่างค่าเริ่มต
instanceDefaultDarkTheme: "ธีมมืดค่าเริ่มต้นอินสแตนซ์" instanceDefaultDarkTheme: "ธีมมืดค่าเริ่มต้นอินสแตนซ์"
instanceDefaultThemeDescription: "ป้อนรหัสธีมในรูปแบบออบเจ็กต์" instanceDefaultThemeDescription: "ป้อนรหัสธีมในรูปแบบออบเจ็กต์"
mutePeriod: "ระยะเวลาปิดเสียง" mutePeriod: "ระยะเวลาปิดเสียง"
period: "สิ้นสุดการสำรวจความคิดเห็น"
indefinitely: "ตลอดไป" indefinitely: "ตลอดไป"
tenMinutes: "10 นาที" tenMinutes: "10 นาที"
oneHour: "1 ชั่วโมง" oneHour: "1 ชั่วโมง"
oneDay: "1 วัน" oneDay: "1 วัน"
oneWeek: "1 สัปดาห์" oneWeek: "1 สัปดาห์"
oneMonth: "หนึ่งเดือน"
reflectMayTakeTime: "อาจจำเป็นต้องใช้เวลาสักระยะหนึ่งจึงจะเห็นแสดงผลได้นะ" reflectMayTakeTime: "อาจจำเป็นต้องใช้เวลาสักระยะหนึ่งจึงจะเห็นแสดงผลได้นะ"
failedToFetchAccountInformation: "ไม่สามารถเรียกดึงข้อมูลบัญชีได้" failedToFetchAccountInformation: "ไม่สามารถเรียกดึงข้อมูลบัญชีได้"
rateLimitExceeded: "เกินขีดจำกัดอัตรา" rateLimitExceeded: "เกินขีดจำกัดอัตรา"
cropImage: "ครอบตัดรูปภาพ" cropImage: "ครอบตัดรูปภาพ"
cropImageAsk: "คุณต้องการครอบตัดรูปภาพนี้อย่างงั้นหรือ?" cropImageAsk: "คุณต้องการครอบตัดรูปภาพนี้อย่างงั้นหรือ?"
cropYes: "ครอบตัด"
cropNo: "ใช้ตามที่เป็นอยู่"
file: "ไฟล์" file: "ไฟล์"
recentNHours: "ล่าสุด {n} ชั่วโมงที่แล้ว" recentNHours: "ล่าสุด {n} ชั่วโมงที่แล้ว"
recentNDays: "ล่าสุด {n} วันที่แล้ว" recentNDays: "ล่าสุด {n} วันที่แล้ว"
@@ -941,6 +942,19 @@ selectFromPresets: "เลือกจากการพรีเซ็ต"
achievements: "ความสำเร็จ" achievements: "ความสำเร็จ"
gotInvalidResponseError: "การตอบสนองเซิร์ฟเวอร์ไม่ถูกต้อง" gotInvalidResponseError: "การตอบสนองเซิร์ฟเวอร์ไม่ถูกต้อง"
gotInvalidResponseErrorDescription: "เซิร์ฟเวอร์อาจไม่สามารถเข้าถึงได้หรืออาจจะกำลังอยู่ในระหว่างปรับปรุง กรุณาลองใหม่อีกครั้งในภายหลังนะคะ" gotInvalidResponseErrorDescription: "เซิร์ฟเวอร์อาจไม่สามารถเข้าถึงได้หรืออาจจะกำลังอยู่ในระหว่างปรับปรุง กรุณาลองใหม่อีกครั้งในภายหลังนะคะ"
thisPostMayBeAnnoying: "โน้ตนี้อาจจะเป็นการรบกวนผู้อื่นนะคะ"
thisPostMayBeAnnoyingHome: "โพสต์ไปยังบ้านไทม์ไลน์"
thisPostMayBeAnnoyingCancel: "เลิก"
thisPostMayBeAnnoyingIgnore: "โพสต์ยังไงก็แล้วแต่"
collapseRenotes: "ยุบ renotes ที่คุณได้เห็นแล้ว"
internalServerError: "เซิร์ฟเวอร์ภายในเกิดข้อผิดพลาด"
internalServerErrorDescription: "เซิร์ฟเวอร์รันค้นพบข้อผิดพลาดที่ไม่คาดคิด"
copyErrorInfo: "คัดลอกรายละเอียดข้อผิดพลาด"
joinThisServer: "ลงชื่อสมัครใช้ในอินสแตนซ์นี้"
exploreOtherServers: "มองหาอินสแตนซ์อื่น"
letsLookAtTimeline: "ลองดูที่ไทม์ไลน์"
disableFederationWarn: "การดำเนินการนี้ถ้าหากจะปิดใช้งานการรวมศูนย์ แต่โพสต์ดังกล่าวนั้นจะยังคงเป็นสาธารณะต่อไป ยกเว้นแต่ว่าจะตั้งค่าเป็นอย่างอื่น โดยปกติคุณไม่จำเป็นต้องใช้การตั้งค่านี้นะ"
invitationRequiredToRegister: "อินสแตนซ์นี้เป็นแบบรับเชิญเท่านั้น คุณต้องป้อนรหัสเชิญที่ถูกต้องถึงจะลงทะเบียนได้นะค่ะ"
_achievements: _achievements:
earnedAt: "ได้รับเมื่อ" earnedAt: "ได้รับเมื่อ"
_types: _types:
@@ -1454,6 +1468,7 @@ _ago:
weeksAgo: "{n} สัปดาห์ที่แล้ว" weeksAgo: "{n} สัปดาห์ที่แล้ว"
monthsAgo: "{n} เดือนที่แล้ว" monthsAgo: "{n} เดือนที่แล้ว"
yearsAgo: "{n} ปีที่ผ่านมา" yearsAgo: "{n} ปีที่ผ่านมา"
invalid: "ไม่พบผลลัพธ์"
_time: _time:
second: "วินาที" second: "วินาที"
minute: "นาที" minute: "นาที"
@@ -1487,14 +1502,29 @@ _tutorial:
step8_3: "คุณสามารถเปลี่ยนการตั้งค่านี้ในภายหลังได้ตลอดเวลานะ" step8_3: "คุณสามารถเปลี่ยนการตั้งค่านี้ในภายหลังได้ตลอดเวลานะ"
_2fa: _2fa:
alreadyRegistered: "คุณได้ลงทะเบียนอุปกรณ์ยืนยันตัวตนแบบ 2 ชั้นแล้ว" alreadyRegistered: "คุณได้ลงทะเบียนอุปกรณ์ยืนยันตัวตนแบบ 2 ชั้นแล้ว"
registerDevice: "ลงทะเบียนอุปกรณ์ใหม่" registerTOTP: "ลงทะเบียนแอพตัวตรวจสอบสิทธิ์"
registerKey: "ลงทะเบียนรหัสความปลอดภัย" passwordToTOTP: "กรอกรหัสผ่าน"
step1: "ขั้นตอนแรก ติดตั้งแอปยืนยันตัวตน (เช่น {a} หรือ {b}) บนอุปกรณ์ของคุณ" step1: "ขั้นตอนแรก ติดตั้งแอปยืนยันตัวตน (เช่น {a} หรือ {b}) บนอุปกรณ์ของคุณ"
step2: "จากนั้นสแกนรหัส QR ที่แสดงบนหน้าจอนี้" step2: "จากนั้นสแกนรหัส QR ที่แสดงบนหน้าจอนี้"
step2Click: "การคลิกที่รหัส QR นี้จะช่วยให้คุณนั้นสามารถลงทะเบียน 2FA กับคีย์ความปลอดภัยหรือแอปตรวจสอบความถูกต้องของโทรศัพท์ได้"
step2Url: "คุณยังสามารถป้อนบน URL นี้หากคุณใช้โปรแกรมเดสก์ท็อป:" step2Url: "คุณยังสามารถป้อนบน URL นี้หากคุณใช้โปรแกรมเดสก์ท็อป:"
step3Title: "ป้อนรหัสยืนยัน"
step3: "ป้อนโทเค็นที่แอปของคุณให้มาเพื่อเสร็จสิ้นการตั้งค่า" step3: "ป้อนโทเค็นที่แอปของคุณให้มาเพื่อเสร็จสิ้นการตั้งค่า"
step4: "นับจากนี้เป็นต้นไปการพยายามเข้าสู่ระบบในอนาคตนั้น อาจจะต้องขอโทเค็นในการเข้าสู่ระบบดังกล่าว" step4: "นับจากนี้เป็นต้นไปการพยายามเข้าสู่ระบบในอนาคตนั้น อาจจะต้องขอโทเค็นในการเข้าสู่ระบบดังกล่าว"
securityKeyNotSupported: "เบราว์เซอร์ของคุณไม่รองรับคีย์ความปลอดภัยนะ"
registerTOTPBeforeKey: "กรุณาตั้งค่าแอปยืนยันตัวตนเพื่อลงทะเบียนรหัสความปลอดภัยหรือรหัสผ่าน"
securityKeyInfo: "นอกจากนี้การตรวจสอบความถูกต้องด้วยลายนิ้วมือหรือ PIN แล้ว คุณยังสามารถตั้งค่าการตรวจสอบสิทธิ์ผ่านคีย์ความปลอดภัยของฮาร์ดแวร์ที่รองรับ FIDO2 เพื่อเพิ่มความปลอดภัยให้กับบัญชีของคุณ" securityKeyInfo: "นอกจากนี้การตรวจสอบความถูกต้องด้วยลายนิ้วมือหรือ PIN แล้ว คุณยังสามารถตั้งค่าการตรวจสอบสิทธิ์ผ่านคีย์ความปลอดภัยของฮาร์ดแวร์ที่รองรับ FIDO2 เพื่อเพิ่มความปลอดภัยให้กับบัญชีของคุณ"
chromePasskeyNotSupported: "ขณะนี้ยังไม่รองรับรหัสผ่านของ Chrome"
registerSecurityKey: "ลงทะเบียนรหัสความปลอดภัยหรือรหัสผ่าน"
securityKeyName: "ป้อนชื่อคีย์"
tapSecurityKey: "กรุณาทำตามเบราว์เซอร์ของคุณเพื่อลงทะเบียนรหัสความปลอดภัยหรือรหัสผ่าน"
removeKey: "ลบคีย์ความปลอดภัยออก"
removeKeyConfirm: "ลบข้อมูลสำรอง {name} มั้ย?"
whyTOTPOnlyRenew: "ไม่สามารถลบแอปตัวรับรองความถูกต้องได้ตราบใดที่มีการลงทะเบียนคีย์ความปลอดภัยไว้แล้ว"
renewTOTP: "กำหนดค่าแอพตัวตรวจสอบสิทธิ์ใหม่"
renewTOTPConfirm: "วิธีการแบบนี้จะทําให้รหัสยืนยันจากแอพก่อนหน้าของคุณหยุดทํางานเลยนะ"
renewTOTPOk: "ตั้งค่าคอนฟิกใหม่"
renewTOTPCancel: "ไม่เป็นไร"
_permissions: _permissions:
"read:account": "ดูข้อมูลบัญชีของคุณ" "read:account": "ดูข้อมูลบัญชีของคุณ"
"write:account": "แก้ไขข้อมูลบัญชีของคุณ" "write:account": "แก้ไขข้อมูลบัญชีของคุณ"
@@ -1543,7 +1573,6 @@ _antennaSources:
homeTimeline: "โน้ตจากผู้ใช้ที่ติดตาม" homeTimeline: "โน้ตจากผู้ใช้ที่ติดตาม"
users: "โน้ตจากผู้ใช้ที่เฉพาะเจาะจง" users: "โน้ตจากผู้ใช้ที่เฉพาะเจาะจง"
userList: "โน้ตจากรายชื่อผู้ใช้ที่ระบุ" userList: "โน้ตจากรายชื่อผู้ใช้ที่ระบุ"
userGroup: "โน้ตจากผู้ใช้ในกลุ่มที่ระบุ"
_weekday: _weekday:
sunday: "วันอาทิตย์" sunday: "วันอาทิตย์"
monday: "วันจันทร์" monday: "วันจันทร์"
@@ -1618,8 +1647,8 @@ _visibility:
followersDescription: "ทำให้ผู้ติดตามนั้นมองเห็นแค่คุณเท่านั้น" followersDescription: "ทำให้ผู้ติดตามนั้นมองเห็นแค่คุณเท่านั้น"
specified: "ไดเร็ค" specified: "ไดเร็ค"
specifiedDescription: "ทำให้มองเห็นได้เฉพาะผู้ใช้ที่ระบุเท่านั้น" specifiedDescription: "ทำให้มองเห็นได้เฉพาะผู้ใช้ที่ระบุเท่านั้น"
localOnly: "เฉพาะท้องถิ่น" disableFederation: "ไม่มีสหภาพ"
localOnlyDescription: "ผู้ใช้ระยะไกลนั้นไม่สามารถมองเห็นได้" disableFederationDescription: "อย่าส่งไปยังอินสแตนซ์อื่น"
_postForm: _postForm:
replyPlaceholder: "ตอบกลับโน้ตนี้..." replyPlaceholder: "ตอบกลับโน้ตนี้..."
quotePlaceholder: "อ้างโน้ตนี้..." quotePlaceholder: "อ้างโน้ตนี้..."
@@ -1757,12 +1786,9 @@ _notification:
youGotReply: "{name} ตอบกลับถึงคุณ" youGotReply: "{name} ตอบกลับถึงคุณ"
youGotQuote: "{name} อ้างถึงคุณ" youGotQuote: "{name} อ้างถึงคุณ"
youRenoted: "รีโน้ตจาก {name}" youRenoted: "รีโน้ตจาก {name}"
youGotMessagingMessageFromUser: "{name} ได้ส่งข้อความแชทถึงคุณ"
youGotMessagingMessageFromGroup: "ข้อความแชทถูกส่งไปยัง {name} กลุ่ม"
youWereFollowed: "ได้ติดตามคุณ" youWereFollowed: "ได้ติดตามคุณ"
youReceivedFollowRequest: "คุณมีคำขอติดตามใหม่น่ะ" youReceivedFollowRequest: "คุณมีคำขอติดตามใหม่น่ะ"
yourFollowRequestAccepted: "คำขอติดตามของคุณได้รับการยอมรับแล้วน่ะ" yourFollowRequestAccepted: "คำขอติดตามของคุณได้รับการยอมรับแล้วน่ะ"
youWereInvitedToGroup: "{userName} ได้เชิญคุณเข้ากลุ่ม"
pollEnded: "โพลสำรวจความคิดเห็นผลลัพธ์มีพร้อมใช้งาน" pollEnded: "โพลสำรวจความคิดเห็นผลลัพธ์มีพร้อมใช้งาน"
unreadAntennaNote: "เสาอากาศ {name}" unreadAntennaNote: "เสาอากาศ {name}"
emptyPushNotificationMessage: "การแจ้งเตือนแบบพุชได้รับการอัพเดทแล้ว" emptyPushNotificationMessage: "การแจ้งเตือนแบบพุชได้รับการอัพเดทแล้ว"
@@ -1778,7 +1804,7 @@ _notification:
pollEnded: "โพลนี้สิ้นสุดลงแล้ว" pollEnded: "โพลนี้สิ้นสุดลงแล้ว"
receiveFollowRequest: "ได้รับคำขอติดตาม\n" receiveFollowRequest: "ได้รับคำขอติดตาม\n"
followRequestAccepted: "ยอมรับคำขอติดตาม" followRequestAccepted: "ยอมรับคำขอติดตาม"
groupInvited: "ได้รับคำเชิญเข้ากลุ่ม" achievementEarned: "ปลดล็อกความสำเร็จแล้ว"
app: "การแจ้งเตือนจากแอปที่มีลิงก์" app: "การแจ้งเตือนจากแอปที่มีลิงก์"
_actions: _actions:
followBack: "ติดตามกลับด้วย" followBack: "ติดตามกลับด้วย"
@@ -1811,3 +1837,6 @@ _deck:
channel: "แชนแนล" channel: "แชนแนล"
mentions: "พูดถึง" mentions: "พูดถึง"
direct: "ไดเร็ค" direct: "ไดเร็ค"
_dialog:
charactersExceeded: "คุณกำลังมีตัวอักขระเกินขีดจำกัดสูงสุดแล้วนะ! ปัจจุบันอยู่ที่ {current} จาก {max}"
charactersBelow: "คุณกำลังใช้อักขระต่ำกว่าขีดจำกัดขั้นต่ำเลยนะ! ปัจจุบันอยู่ที่ {current} จาก {min}"

View File

@@ -49,6 +49,7 @@ deleteAndEdit: "Видалити й редагувати"
deleteAndEditConfirm: "Ви впевнені, що хочете видалити цю нотатку та відредагувати її? Ви втратите всі реакції, поширення та відповіді на неї." deleteAndEditConfirm: "Ви впевнені, що хочете видалити цю нотатку та відредагувати її? Ви втратите всі реакції, поширення та відповіді на неї."
addToList: "Додати до списку" addToList: "Додати до списку"
sendMessage: "Надіслати повідомлення" sendMessage: "Надіслати повідомлення"
copyRSS: "Скопіювати RSS"
copyUsername: "Скопіювати ім’я користувача" copyUsername: "Скопіювати ім’я користувача"
searchUser: "Пошук користувачів" searchUser: "Пошук користувачів"
reply: "Відповісти" reply: "Відповісти"
@@ -128,6 +129,7 @@ unblockConfirm: "Ви впевнені, що хочете розблокуват
suspendConfirm: "Ви впевнені, що хочете призупинити цей акаунт?" suspendConfirm: "Ви впевнені, що хочете призупинити цей акаунт?"
unsuspendConfirm: "Ви впевнені, що хочете відновити цей акаунт?" unsuspendConfirm: "Ви впевнені, що хочете відновити цей акаунт?"
selectList: "Виберіть список" selectList: "Виберіть список"
selectChannel: "Виберіть канал"
selectAntenna: "Виберіть антену" selectAntenna: "Виберіть антену"
selectWidget: "Виберіть віджет" selectWidget: "Виберіть віджет"
editWidgets: "Редагувати віджети" editWidgets: "Редагувати віджети"
@@ -255,6 +257,7 @@ noMoreHistory: "Подальшої історії немає"
startMessaging: "Розпочати діалог" startMessaging: "Розпочати діалог"
nUsersRead: "Прочитали {n}" nUsersRead: "Прочитали {n}"
agreeTo: "Я погоджуюсь з {0}" agreeTo: "Я погоджуюсь з {0}"
agreeBelow: "Я погоджуюся з наведеним нижче"
tos: "Умови використання" tos: "Умови використання"
start: "Розпочати" start: "Розпочати"
home: "Домівка" home: "Домівка"
@@ -387,13 +390,12 @@ about: "Інформація"
aboutMisskey: "Про Misskey" aboutMisskey: "Про Misskey"
administrator: "Адмін" administrator: "Адмін"
token: "Токен" token: "Токен"
twoStepAuthentication: "Двохфакторна аутентифікація" 2fa: "Двофакторна аутентифікація"
totp: "Програма аутентифікації"
moderator: "Модератор" moderator: "Модератор"
moderation: "Модерація" moderation: "Модерація"
nUsersMentioned: "Згадали: {n}" nUsersMentioned: "Згадали: {n}"
securityKey: "Ключ захисту" securityKey: "Ключ захисту"
securityKeyName: "Назва ключа"
registerSecurityKey: "Зареєструвати ключ захисту"
lastUsed: "Востаннє використано" lastUsed: "Востаннє використано"
unregister: "Скасувати реєстрацію" unregister: "Скасувати реєстрацію"
passwordLessLogin: "Налаштувати вхід без пароля" passwordLessLogin: "Налаштувати вхід без пароля"
@@ -411,24 +413,15 @@ markAsReadAllTalkMessages: "Позначити всі повідомлення
help: "Допомога" help: "Допомога"
inputMessageHere: "Введіть повідомлення тут" inputMessageHere: "Введіть повідомлення тут"
close: "Закрити" close: "Закрити"
group: "Група"
groups: "Групи"
createGroup: "Створити групу"
ownedGroups: "Власні групи"
joinedGroups: "Членство в групах"
invites: "Запросити" invites: "Запросити"
groupName: "Назва групи"
members: "Учасники" members: "Учасники"
transfer: "Передача" transfer: "Передача"
messagingWithUser: "Чат з користувачами"
messagingWithGroup: "Чат з групою"
title: "Тема" title: "Тема"
text: "Текст" text: "Текст"
enable: "Увімкнути" enable: "Увімкнути"
next: "Далі" next: "Далі"
retype: "Введіть ще раз" retype: "Введіть ще раз"
noteOf: "Нотатка {user}" noteOf: "Нотатка {user}"
inviteToGroup: "Запрошення до групи"
quoteAttached: "Цитата" quoteAttached: "Цитата"
quoteQuestion: "Ви хочете додати цитату?" quoteQuestion: "Ви хочете додати цитату?"
noMessagesYet: "Ще немає повідомлень" noMessagesYet: "Ще немає повідомлень"
@@ -450,17 +443,15 @@ passwordMatched: "Все вірно"
passwordNotMatched: "Паролі не співпадають" passwordNotMatched: "Паролі не співпадають"
signinWith: "Увійти за допомогою {x}" signinWith: "Увійти за допомогою {x}"
signinFailed: "Не вдалося увійти. Введені ім’я користувача або пароль неправильнi." signinFailed: "Не вдалося увійти. Введені ім’я користувача або пароль неправильнi."
tapSecurityKey: "Торкніться ключа безпеки"
or: "або" or: "або"
language: "Мова" language: "Мова"
uiLanguage: "Мова інтерфейсу" uiLanguage: "Мова інтерфейсу"
groupInvited: "Запрошення до групи"
aboutX: "Про {x}" aboutX: "Про {x}"
disableDrawer: "Не використовувати висувні меню" disableDrawer: "Не використовувати висувні меню"
youHaveNoGroups: "Немає груп"
joinOrCreateGroup: "Отримуйте запрошення до груп або створюйте свої власні групи."
noHistory: "Історія порожня" noHistory: "Історія порожня"
signinHistory: "Історія входів" signinHistory: "Історія входів"
enableAdvancedMfm: "Увімкнути розширений MFM"
enableAnimatedMfm: "Увімкнути анімований MFM"
doing: "Виконується" doing: "Виконується"
category: "Категорія" category: "Категорія"
tags: "Теги" tags: "Теги"
@@ -713,6 +704,7 @@ accentColor: "Акцент"
textColor: "Текст" textColor: "Текст"
saveAs: "Зберегти як…" saveAs: "Зберегти як…"
advanced: "Розширені" advanced: "Розширені"
advancedSettings: "Розширені налаштування"
value: "Значення" value: "Значення"
createdAt: "Створено" createdAt: "Створено"
updatedAt: "Останнє оновлення" updatedAt: "Останнє оновлення"
@@ -777,6 +769,7 @@ popularPosts: "Популярні дописи"
shareWithNote: "Поділитися нотаткою" shareWithNote: "Поділитися нотаткою"
ads: "Реклама" ads: "Реклама"
expiration: "Опитування закінчується" expiration: "Опитування закінчується"
startingperiod: "Початковий період"
memo: "Примітка" memo: "Примітка"
priority: "Пріоритет" priority: "Пріоритет"
high: "Високий" high: "Високий"
@@ -825,8 +818,6 @@ deleteAccountConfirm: "Це незворотно видалить ваш ака
incorrectPassword: "Неправильний пароль." incorrectPassword: "Неправильний пароль."
voteConfirm: "Підтверджуєте свій голос за \"{choice}\"?" voteConfirm: "Підтверджуєте свій голос за \"{choice}\"?"
hide: "Сховати" hide: "Сховати"
leaveGroup: "Залишити групу"
leaveGroupConfirm: "Залишити \"{name}\"?"
welcomeBackWithName: "З поверненням, {name}!" welcomeBackWithName: "З поверненням, {name}!"
clickToFinishEmailVerification: "Натисніть [{ok}], щоб завершити перевірку email." clickToFinishEmailVerification: "Натисніть [{ok}], щоб завершити перевірку email."
overridedDeviceKind: "Тип пристрою" overridedDeviceKind: "Тип пристрою"
@@ -840,6 +831,7 @@ searchByGoogle: "Пошук"
instanceDefaultLightTheme: "Світла тема за промовчанням" instanceDefaultLightTheme: "Світла тема за промовчанням"
instanceDefaultDarkTheme: "Темна тема за промовчанням" instanceDefaultDarkTheme: "Темна тема за промовчанням"
mutePeriod: "Тривалість приховування" mutePeriod: "Тривалість приховування"
period: "Опитування закінчується"
indefinitely: "Ніколи" indefinitely: "Ніколи"
tenMinutes: "10 хвилин" tenMinutes: "10 хвилин"
oneHour: "1 година" oneHour: "1 година"
@@ -897,8 +889,17 @@ like: "Вподобати"
unlike: "Не вподобати" unlike: "Не вподобати"
numberOfLikes: "Вподобання" numberOfLikes: "Вподобання"
show: "Відображення" show: "Відображення"
roles: "Ролі"
role: "Роль"
normalUser: "Звичайний користувач"
undefined: "Не визначено"
assign: "Призначити"
unassign: "Скасувати призначення"
color: "Колір" color: "Колір"
achievements: "Досягнення" achievements: "Досягнення"
joinThisServer: "Зареєструватися на цьому сервері"
exploreOtherServers: "Знайти інший сервер"
letsLookAtTimeline: "Перегляд історії"
_achievements: _achievements:
earnedAt: "Відкрито" earnedAt: "Відкрито"
_types: _types:
@@ -1113,11 +1114,20 @@ _achievements:
_loggedInOnNewYearsDay: _loggedInOnNewYearsDay:
title: "З Новим роком!" title: "З Новим роком!"
description: "Увійшли в перший день року" description: "Увійшли в перший день року"
_cookieClicked:
flavor: "Чекайте, це вірний сайт?"
_brainDiver: _brainDiver:
title: "Brain Diver" title: "Brain Diver"
description: "Відправити посилання на \"Brain Diver\"" description: "Відправити посилання на \"Brain Diver\""
flavor: "Misskey-Misskey La-Tu-Ma" flavor: "Misskey-Misskey La-Tu-Ma"
_role: _role:
new: "Нова роль"
edit: "Змінити роль"
name: "Назва ролі"
description: "Опис ролі"
permission: "Права ролі"
assignTarget: "Призначити"
manual: "Вручну"
priority: "Пріоритет" priority: "Пріоритет"
_priority: _priority:
low: "Низький" low: "Низький"
@@ -1315,6 +1325,7 @@ _ago:
weeksAgo: "{n} тиж. тому" weeksAgo: "{n} тиж. тому"
monthsAgo: "{n} міс. тому" monthsAgo: "{n} міс. тому"
yearsAgo: "{n} р. тому" yearsAgo: "{n} р. тому"
invalid: "Тут нічого немає"
_time: _time:
second: "с" second: "с"
minute: "х" minute: "х"
@@ -1347,13 +1358,12 @@ _tutorial:
step8_3: "Ви завжди можете змінити цей параметр пізніше." step8_3: "Ви завжди можете змінити цей параметр пізніше."
_2fa: _2fa:
alreadyRegistered: "Двофакторна автентифікація вже налаштована." alreadyRegistered: "Двофакторна автентифікація вже налаштована."
registerDevice: "Зареєструвати новий пристрій"
registerKey: "Зареєструвати новий ключ безпеки"
step1: "Спершу встановіть на свій пристрій програму автентифікації (наприклад {a} або {b})." step1: "Спершу встановіть на свій пристрій програму автентифікації (наприклад {a} або {b})."
step2: "Потім відскануйте QR-код, який відображається на цьому екрані." step2: "Потім відскануйте QR-код, який відображається на цьому екрані."
step2Url: "Ви також можете ввести цю URL-адресу, якщо використовуєте програму для ПК:" step2Url: "Ви також можете ввести цю URL-адресу, якщо використовуєте програму для ПК:"
step3: "Щоб завершити налаштування, введіть токен, наданий вашою програмою." step3: "Щоб завершити налаштування, введіть токен, наданий вашою програмою."
step4: "Відтепер будь-які майбутні спроби входу вимагатимуть такого токена." step4: "Відтепер будь-які майбутні спроби входу вимагатимуть такого токена."
renewTOTPCancel: "Не зараз"
_permissions: _permissions:
"read:account": "Переглядати дані профілю" "read:account": "Переглядати дані профілю"
"write:account": "Змінити дані акаунту" "write:account": "Змінити дані акаунту"
@@ -1462,8 +1472,6 @@ _visibility:
followersDescription: "Тільки для підписників" followersDescription: "Тільки для підписників"
specified: "Особисто" specified: "Особисто"
specifiedDescription: "Лише для певних користувачів" specifiedDescription: "Лише для певних користувачів"
localOnly: "Локально"
localOnlyDescription: "Приховано для віддалених користувачів"
_postForm: _postForm:
replyPlaceholder: "Відповідь на цю нотатку..." replyPlaceholder: "Відповідь на цю нотатку..."
quotePlaceholder: "Прокоментуйте цю нотатку..." quotePlaceholder: "Прокоментуйте цю нотатку..."
@@ -1588,12 +1596,9 @@ _notification:
youGotReply: "{name} відповідає" youGotReply: "{name} відповідає"
youGotQuote: "{name} цитує вас" youGotQuote: "{name} цитує вас"
youRenoted: "{name} поширює" youRenoted: "{name} поширює"
youGotMessagingMessageFromUser: "Повідомлення від {name}"
youGotMessagingMessageFromGroup: "Нове повідомлення в групі {name}"
youWereFollowed: "Новий підписник" youWereFollowed: "Новий підписник"
youReceivedFollowRequest: "Ви отримали запит на підписку" youReceivedFollowRequest: "Ви отримали запит на підписку"
yourFollowRequestAccepted: "Запит на підписку прийнято" yourFollowRequestAccepted: "Запит на підписку прийнято"
youWereInvitedToGroup: "Запрошення до групи"
achievementEarned: "Досягнення відкрито" achievementEarned: "Досягнення відкрито"
_types: _types:
all: "Все" all: "Все"
@@ -1605,7 +1610,6 @@ _notification:
reaction: "Реакції" reaction: "Реакції"
receiveFollowRequest: "Запити на підписку" receiveFollowRequest: "Запити на підписку"
followRequestAccepted: "Прийняті підписки" followRequestAccepted: "Прийняті підписки"
groupInvited: "Запрошення до груп"
app: "Сповіщення від додатків" app: "Сповіщення від додатків"
_actions: _actions:
reply: "Відповісти" reply: "Відповісти"

View File

@@ -383,13 +383,10 @@ about: "Giới thiệu"
aboutMisskey: "Về Misskey" aboutMisskey: "Về Misskey"
administrator: "Quản trị viên" administrator: "Quản trị viên"
token: "Token" token: "Token"
twoStepAuthentication: "Xác minh 2 bước"
moderator: "Kiểm duyệt viên" moderator: "Kiểm duyệt viên"
moderation: "Kiểm duyệt" moderation: "Kiểm duyệt"
nUsersMentioned: "Dùng bởi {n} người" nUsersMentioned: "Dùng bởi {n} người"
securityKey: "Khóa bảo mật" securityKey: "Khóa bảo mật"
securityKeyName: "Tên khoá"
registerSecurityKey: "Đăng ký khóa bảo mật"
lastUsed: "Dùng lần cuối" lastUsed: "Dùng lần cuối"
unregister: "Hủy đăng ký" unregister: "Hủy đăng ký"
passwordLessLogin: "Đăng nhập không mật khẩu" passwordLessLogin: "Đăng nhập không mật khẩu"
@@ -407,24 +404,15 @@ markAsReadAllTalkMessages: "Đánh dấu tất cả các tin nhắn là đã đ
help: "Trợ giúp" help: "Trợ giúp"
inputMessageHere: "Nhập nội dung tin nhắn" inputMessageHere: "Nhập nội dung tin nhắn"
close: "Đóng" close: "Đóng"
group: "Nhóm"
groups: "Các nhóm"
createGroup: "Tạo nhóm"
ownedGroups: "Nhóm tôi quản lý"
joinedGroups: "Nhóm tôi tham gia"
invites: "Mời" invites: "Mời"
groupName: "Tên nhóm"
members: "Thành viên" members: "Thành viên"
transfer: "Chuyển giao" transfer: "Chuyển giao"
messagingWithUser: "Nhắn riêng"
messagingWithGroup: "Chat nhóm"
title: "Tựa đề" title: "Tựa đề"
text: "Nội dung" text: "Nội dung"
enable: "Bật" enable: "Bật"
next: "Kế tiếp" next: "Kế tiếp"
retype: "Nhập lại" retype: "Nhập lại"
noteOf: "Tút của {user}" noteOf: "Tút của {user}"
inviteToGroup: "Mời vào nhóm"
quoteAttached: "Trích dẫn" quoteAttached: "Trích dẫn"
quoteQuestion: "Trích dẫn lại?" quoteQuestion: "Trích dẫn lại?"
noMessagesYet: "Chưa có tin nhắn" noMessagesYet: "Chưa có tin nhắn"
@@ -446,15 +434,11 @@ passwordMatched: "Trùng khớp"
passwordNotMatched: "Không trùng khớp" passwordNotMatched: "Không trùng khớp"
signinWith: "Đăng nhập bằng {x}" signinWith: "Đăng nhập bằng {x}"
signinFailed: "Không thể đăng nhập. Vui lòng kiểm tra tên người dùng và mật khẩu của bạn." signinFailed: "Không thể đăng nhập. Vui lòng kiểm tra tên người dùng và mật khẩu của bạn."
tapSecurityKey: "Nhấn mã bảo mật của bạn"
or: "Hoặc" or: "Hoặc"
language: "Ngôn ngữ" language: "Ngôn ngữ"
uiLanguage: "Ngôn ngữ giao diện" uiLanguage: "Ngôn ngữ giao diện"
groupInvited: "Bạn đã được mời tham gia nhóm"
aboutX: "Giới thiệu {x}" aboutX: "Giới thiệu {x}"
disableDrawer: "Không dùng menu thanh bên" disableDrawer: "Không dùng menu thanh bên"
youHaveNoGroups: "Không có nhóm nào"
joinOrCreateGroup: "Tham gia hoặc tạo một nhóm mới."
noHistory: "Không có dữ liệu" noHistory: "Không có dữ liệu"
signinHistory: "Lịch sử đăng nhập" signinHistory: "Lịch sử đăng nhập"
doing: "Đang xử lý..." doing: "Đang xử lý..."
@@ -825,8 +809,6 @@ deleteAccountConfirm: "Điều này sẽ khiến tài khoản bị xóa vĩnh vi
incorrectPassword: "Sai mật khẩu." incorrectPassword: "Sai mật khẩu."
voteConfirm: "Xác nhận bình chọn \"{choice}\"?" voteConfirm: "Xác nhận bình chọn \"{choice}\"?"
hide: "Ẩn" hide: "Ẩn"
leaveGroup: "Rời khỏi nhóm"
leaveGroupConfirm: "Bạn có chắc muốn rời khỏi nhóm \"{name}\"?"
useDrawerReactionPickerForMobile: "Hiện bộ chọn biểu cảm dạng xổ ra trên điện thoại" useDrawerReactionPickerForMobile: "Hiện bộ chọn biểu cảm dạng xổ ra trên điện thoại"
welcomeBackWithName: "Chào mừng trở lại, {name}" welcomeBackWithName: "Chào mừng trở lại, {name}"
clickToFinishEmailVerification: "Vui lòng nhấn [{ok}] để hoàn tất việc đăng ký." clickToFinishEmailVerification: "Vui lòng nhấn [{ok}] để hoàn tất việc đăng ký."
@@ -842,6 +824,7 @@ instanceDefaultLightTheme: "Theme máy chủ Sáng-Rộng"
instanceDefaultDarkTheme: "Theme máy chủ Tối-Rộng" instanceDefaultDarkTheme: "Theme máy chủ Tối-Rộng"
instanceDefaultThemeDescription: "Nhập mã theme trong định dạng đối tượng." instanceDefaultThemeDescription: "Nhập mã theme trong định dạng đối tượng."
mutePeriod: "Thời hạn ẩn" mutePeriod: "Thời hạn ẩn"
period: "Thời hạn"
indefinitely: "Vĩnh viễn" indefinitely: "Vĩnh viễn"
tenMinutes: "10 phút" tenMinutes: "10 phút"
oneHour: "1 giờ" oneHour: "1 giờ"
@@ -1120,6 +1103,7 @@ _ago:
weeksAgo: "{n} tuần trước" weeksAgo: "{n} tuần trước"
monthsAgo: "{n} tháng trước" monthsAgo: "{n} tháng trước"
yearsAgo: "{n} năm trước" yearsAgo: "{n} năm trước"
invalid: "Không có gì ở đây"
_time: _time:
second: "s" second: "s"
minute: "phút" minute: "phút"
@@ -1150,14 +1134,13 @@ _tutorial:
step7_3: "Bây giờ, chúc may mắn và vui vẻ với Misskey! 🚀" step7_3: "Bây giờ, chúc may mắn và vui vẻ với Misskey! 🚀"
_2fa: _2fa:
alreadyRegistered: "Bạn đã đăng ký thiết bị xác minh 2 bước." alreadyRegistered: "Bạn đã đăng ký thiết bị xác minh 2 bước."
registerDevice: "Đăng ký một thiết bị"
registerKey: "Đăng ký một mã bảo vệ"
step1: "Trước tiên, hãy cài đặt một ứng dụng xác minh (chẳng hạn như {a} hoặc {b}) trên thiết bị của bạn." step1: "Trước tiên, hãy cài đặt một ứng dụng xác minh (chẳng hạn như {a} hoặc {b}) trên thiết bị của bạn."
step2: "Sau đó, quét mã QR hiển thị trên màn hình này." step2: "Sau đó, quét mã QR hiển thị trên màn hình này."
step2Url: "Bạn cũng có thể nhập URL này nếu sử dụng một chương trình máy tính:" step2Url: "Bạn cũng có thể nhập URL này nếu sử dụng một chương trình máy tính:"
step3: "Nhập mã token do ứng dụng của bạn cung cấp để hoàn tất thiết lập." step3: "Nhập mã token do ứng dụng của bạn cung cấp để hoàn tất thiết lập."
step4: "Kể từ bây giờ, những lần đăng nhập trong tương lai sẽ yêu cầu mã token đăng nhập đó." step4: "Kể từ bây giờ, những lần đăng nhập trong tương lai sẽ yêu cầu mã token đăng nhập đó."
securityKeyInfo: "Bên cạnh xác minh bằng vân tay hoặc mã PIN, bạn cũng có thể thiết lập xác minh thông qua khóa bảo mật phần cứng hỗ trợ FIDO2 để bảo mật hơn nữa cho tài khoản của mình." securityKeyInfo: "Bên cạnh xác minh bằng vân tay hoặc mã PIN, bạn cũng có thể thiết lập xác minh thông qua khóa bảo mật phần cứng hỗ trợ FIDO2 để bảo mật hơn nữa cho tài khoản của mình."
removeKeyConfirm: "Xóa bản sao lưu {name}?"
_permissions: _permissions:
"read:account": "Xem thông tin tài khoản của bạn" "read:account": "Xem thông tin tài khoản của bạn"
"write:account": "Sửa thông tin tài khoản của bạn" "write:account": "Sửa thông tin tài khoản của bạn"
@@ -1203,7 +1186,6 @@ _antennaSources:
homeTimeline: "Tút từ những người đã theo dõi" homeTimeline: "Tút từ những người đã theo dõi"
users: "Tút từ những người cụ thể" users: "Tút từ những người cụ thể"
userList: "Tút từ danh sách người dùng cụ thể" userList: "Tút từ danh sách người dùng cụ thể"
userGroup: "Tút từ người dùng trong một nhóm cụ thể"
_weekday: _weekday:
sunday: "Chủ Nhật" sunday: "Chủ Nhật"
monday: "Thứ Hai" monday: "Thứ Hai"
@@ -1275,8 +1257,6 @@ _visibility:
followersDescription: "Dành riêng cho người theo dõi" followersDescription: "Dành riêng cho người theo dõi"
specified: "Nhắn riêng" specified: "Nhắn riêng"
specifiedDescription: "Chỉ người được nhắc đến mới thấy" specifiedDescription: "Chỉ người được nhắc đến mới thấy"
localOnly: "Chỉ trên máy chủ"
localOnlyDescription: "Không hiển thị với người ở máy chủ khác"
_postForm: _postForm:
replyPlaceholder: "Trả lời tút này" replyPlaceholder: "Trả lời tút này"
quotePlaceholder: "Trích dẫn tút này" quotePlaceholder: "Trích dẫn tút này"
@@ -1404,12 +1384,9 @@ _notification:
youGotReply: "{name} trả lời bạn" youGotReply: "{name} trả lời bạn"
youGotQuote: "{name} trích dẫn tút của bạn" youGotQuote: "{name} trích dẫn tút của bạn"
youRenoted: "{name} đăng lại tút của bạn" youRenoted: "{name} đăng lại tút của bạn"
youGotMessagingMessageFromUser: "{name} nhắn tin cho bạn"
youGotMessagingMessageFromGroup: "Một tin nhắn trong nhóm {name}"
youWereFollowed: "đã theo dõi bạn" youWereFollowed: "đã theo dõi bạn"
youReceivedFollowRequest: "Bạn vừa có một yêu cầu theo dõi" youReceivedFollowRequest: "Bạn vừa có một yêu cầu theo dõi"
yourFollowRequestAccepted: "Yêu cầu theo dõi của bạn đã được chấp nhận" yourFollowRequestAccepted: "Yêu cầu theo dõi của bạn đã được chấp nhận"
youWereInvitedToGroup: "Bạn đã được mời tham gia nhóm"
pollEnded: "Cuộc bình chọn đã kết thúc" pollEnded: "Cuộc bình chọn đã kết thúc"
emptyPushNotificationMessage: "Đã cập nhật thông báo đẩy" emptyPushNotificationMessage: "Đã cập nhật thông báo đẩy"
_types: _types:
@@ -1423,7 +1400,6 @@ _notification:
pollEnded: "Bình chọn kết thúc" pollEnded: "Bình chọn kết thúc"
receiveFollowRequest: "Yêu cầu theo dõi" receiveFollowRequest: "Yêu cầu theo dõi"
followRequestAccepted: "Yêu cầu theo dõi được chấp nhận" followRequestAccepted: "Yêu cầu theo dõi được chấp nhận"
groupInvited: "Mời vào nhóm"
app: "Từ app liên kết" app: "Từ app liên kết"
_actions: _actions:
followBack: "đã theo dõi lại bạn" followBack: "đã theo dõi lại bạn"

View File

@@ -103,6 +103,8 @@ renoted: "已转发。"
cantRenote: "该帖无法转发。" cantRenote: "该帖无法转发。"
cantReRenote: "转发无法被再次转发。" cantReRenote: "转发无法被再次转发。"
quote: "引用" quote: "引用"
inChannelRenote: "在频道内转发"
inChannelQuote: "在频道内引用"
pinnedNote: "已置顶的帖子" pinnedNote: "已置顶的帖子"
pinned: "置顶" pinned: "置顶"
you: "您" you: "您"
@@ -391,16 +393,19 @@ about: "关于"
aboutMisskey: "关于 Misskey" aboutMisskey: "关于 Misskey"
administrator: "管理员" administrator: "管理员"
token: "Token (令牌)" token: "Token (令牌)"
twoStepAuthentication: "两步验证" 2fa: "双因素认证"
totp: "身份验证应用"
totpDescription: "使用认证应用输入一次性密码。"
moderator: "监察员" moderator: "监察员"
moderation: "管理" moderation: "管理"
nUsersMentioned: "{n} 被提到" nUsersMentioned: "{n} 被提到"
securityKeyAndPasskey: "安全密钥/密码"
securityKey: "安全密钥" securityKey: "安全密钥"
securityKeyName: "密钥名称"
registerSecurityKey: "注册硬件安全密钥"
lastUsed: "最后使用:" lastUsed: "最后使用:"
lastUsedAt: "最后使用: {t}"
unregister: "删除账户" unregister: "删除账户"
passwordLessLogin: "无密码登录" passwordLessLogin: "无密码登录"
passwordLessLoginDescription: "不使用密码仅使用安全密钥或Passkey登录"
resetPassword: "重置密码" resetPassword: "重置密码"
newPasswordIs: "新的密码是「{password}」" newPasswordIs: "新的密码是「{password}」"
reduceUiAnimation: "减少UI动画" reduceUiAnimation: "减少UI动画"
@@ -415,24 +420,15 @@ markAsReadAllTalkMessages: "将所有聊天标记为已读"
help: "帮助" help: "帮助"
inputMessageHere: "在此键入信息" inputMessageHere: "在此键入信息"
close: "关闭" close: "关闭"
group: "群组"
groups: "群组"
createGroup: "创建群组"
ownedGroups: "拥有的群组"
joinedGroups: "已加入的群组"
invites: "邀请" invites: "邀请"
groupName: "群组名"
members: "成员" members: "成员"
transfer: "转让" transfer: "转让"
messagingWithUser: "与用户聊天"
messagingWithGroup: "与群组聊天"
title: "标题" title: "标题"
text: "文本" text: "文本"
enable: "启用" enable: "启用"
next: "下一个" next: "下一个"
retype: "重新输入" retype: "重新输入"
noteOf: "{user}的帖子" noteOf: "{user}的帖子"
inviteToGroup: "群组邀请"
quoteAttached: "已引用" quoteAttached: "已引用"
quoteQuestion: "是否引用此链接内容?" quoteQuestion: "是否引用此链接内容?"
noMessagesYet: "现在没有新的聊天" noMessagesYet: "现在没有新的聊天"
@@ -454,17 +450,14 @@ passwordMatched: "密码一致"
passwordNotMatched: "密码不一致" passwordNotMatched: "密码不一致"
signinWith: "以{x}登录" signinWith: "以{x}登录"
signinFailed: "无法登录,请检查您的用户名和密码是否正确。" signinFailed: "无法登录,请检查您的用户名和密码是否正确。"
tapSecurityKey: "轻触硬件安全密钥"
or: "或者" or: "或者"
language: "语言" language: "语言"
uiLanguage: "显示语言" uiLanguage: "显示语言"
groupInvited: "您有新的群组邀请"
aboutX: "关于 {x}" aboutX: "关于 {x}"
emojiStyle: "emoji 的样式" emojiStyle: "emoji 的样式"
native: "原生" native: "原生"
disableDrawer: "不显示抽屉菜单" disableDrawer: "不显示抽屉菜单"
youHaveNoGroups: "没有群组" showNoteActionsOnlyHover: "仅在悬停时显示帖子操作"
joinOrCreateGroup: "请加入一个现有的群组,或者创建新群组。"
noHistory: "没有历史记录" noHistory: "没有历史记录"
signinHistory: "登录历史" signinHistory: "登录历史"
enableAdvancedMfm: "启用扩展MFM" enableAdvancedMfm: "启用扩展MFM"
@@ -683,7 +676,7 @@ driveFilesCount: "网盘的文件数"
driveUsage: "网盘的空间用量" driveUsage: "网盘的空间用量"
noCrawle: "要求搜索引擎不索引该用户" noCrawle: "要求搜索引擎不索引该用户"
noCrawleDescription: "要求搜索引擎不要收录(索引)您的用户页面,帖子,页面等。" noCrawleDescription: "要求搜索引擎不要收录(索引)您的用户页面,帖子,页面等。"
lockedAccountInfo: "即使通过了关注请求,只要您不将帖子可见范围设置成“关注者”,任何人都可以看到您的帖子。" lockedAccountInfo: "即使启用该功能,只要您不将帖子可见范围设置为“仅关注者”,任何人都还是可以看到您的帖子。"
alwaysMarkSensitive: "默认将媒体文件标记为敏感内容" alwaysMarkSensitive: "默认将媒体文件标记为敏感内容"
loadRawImages: "添加附件图像的缩略图时使用原始图像质量" loadRawImages: "添加附件图像的缩略图时使用原始图像质量"
disableShowingAnimatedImages: "不播放动画" disableShowingAnimatedImages: "不播放动画"
@@ -787,6 +780,7 @@ popularPosts: "热门投稿"
shareWithNote: "在帖子中分享" shareWithNote: "在帖子中分享"
ads: "广告" ads: "广告"
expiration: "截止时间" expiration: "截止时间"
startingperiod: "开始时间"
memo: "便笺" memo: "便笺"
priority: "优先级" priority: "优先级"
high: "高" high: "高"
@@ -813,12 +807,13 @@ translatedFrom: "从 {x} 翻译"
accountDeletionInProgress: "正在删除账户" accountDeletionInProgress: "正在删除账户"
usernameInfo: "在服务器上唯一标识您的帐户的名称。您可以使用字母 (a ~ z, A ~ Z)、数字 (0 ~ 9) 和下划线 (_)。用户名以后不能更改。" usernameInfo: "在服务器上唯一标识您的帐户的名称。您可以使用字母 (a ~ z, A ~ Z)、数字 (0 ~ 9) 和下划线 (_)。用户名以后不能更改。"
aiChanMode: "小蓝模式" aiChanMode: "小蓝模式"
keepCw: "保留CW" keepCw: "回复时维持隐藏内容"
pubSub: "Pub/Sub账户" pubSub: "Pub/Sub账户"
lastCommunication: "最近通信" lastCommunication: "最近通信"
resolved: "已解决" resolved: "已解决"
unresolved: "未解决" unresolved: "未解决"
breakFollow: "移除关注者" breakFollow: "移除关注者"
breakFollowConfirm: "你想取消关注吗?"
itsOn: "已开启" itsOn: "已开启"
itsOff: "已关闭" itsOff: "已关闭"
emailRequiredForSignup: "注册账户需要电子邮件地址" emailRequiredForSignup: "注册账户需要电子邮件地址"
@@ -838,8 +833,6 @@ deleteAccountConfirm: "将要删除账户。是否确认?"
incorrectPassword: "密码错误" incorrectPassword: "密码错误"
voteConfirm: "确定投给“{choice}” " voteConfirm: "确定投给“{choice}” "
hide: "隐藏" hide: "隐藏"
leaveGroup: "离开群组"
leaveGroupConfirm: "确定离开「{name}」?"
useDrawerReactionPickerForMobile: "在移动设备上使用抽屉显示" useDrawerReactionPickerForMobile: "在移动设备上使用抽屉显示"
welcomeBackWithName: "欢迎回来,{name}" welcomeBackWithName: "欢迎回来,{name}"
clickToFinishEmailVerification: "点击 [{ok}] 完成电子邮件地址认证。" clickToFinishEmailVerification: "点击 [{ok}] 完成电子邮件地址认证。"
@@ -855,17 +848,19 @@ instanceDefaultLightTheme: "实例默认浅色主题"
instanceDefaultDarkTheme: "实例默认深色主题" instanceDefaultDarkTheme: "实例默认深色主题"
instanceDefaultThemeDescription: "以对象格式键入主题代码" instanceDefaultThemeDescription: "以对象格式键入主题代码"
mutePeriod: "屏蔽期限" mutePeriod: "屏蔽期限"
period: "截止时间"
indefinitely: "永久" indefinitely: "永久"
tenMinutes: "10分钟" tenMinutes: "10分钟"
oneHour: "1小时" oneHour: "1小时"
oneDay: "1天" oneDay: "1天"
oneWeek: "1周" oneWeek: "1周"
oneMonth: "1 个月"
reflectMayTakeTime: "可能需要一些时间才能体现出效果。" reflectMayTakeTime: "可能需要一些时间才能体现出效果。"
failedToFetchAccountInformation: "获取账户信息失败" failedToFetchAccountInformation: "获取账户信息失败"
rateLimitExceeded: "已超過速率限制" rateLimitExceeded: "已超過速率限制"
cropImage: "剪裁图像" cropImage: "剪裁图像"
cropImageAsk: "是否要裁剪图像?" cropImageAsk: "是否要裁剪图像?"
cropYes: "裁剪" cropYes: "裁剪"
cropNo: "就这样吧!" cropNo: "就这样吧!"
file: "文件" file: "文件"
recentNHours: "最近{n}小时" recentNHours: "最近{n}小时"
@@ -951,6 +946,15 @@ thisPostMayBeAnnoying: "这个帖子可能会让其他人感到困扰。"
thisPostMayBeAnnoyingHome: "发到首页" thisPostMayBeAnnoyingHome: "发到首页"
thisPostMayBeAnnoyingCancel: "取消" thisPostMayBeAnnoyingCancel: "取消"
thisPostMayBeAnnoyingIgnore: "就这样发布" thisPostMayBeAnnoyingIgnore: "就这样发布"
collapseRenotes: "省略显示已经看过的转发内容"
internalServerError: "内部服务器错误"
internalServerErrorDescription: "内部服务器发生了预期外的错误"
copyErrorInfo: "复制错误信息"
joinThisServer: "在本实例上注册"
exploreOtherServers: "探索其他实例"
letsLookAtTimeline: "时间线"
disableFederationWarn: "联合被禁用。 禁用它并不能使帖子变成私人的。 在大多数情况下,这个选项不需要被启用。"
invitationRequiredToRegister: "此实例目前只允许拥有邀请码的人注册。"
_achievements: _achievements:
earnedAt: "达成时间" earnedAt: "达成时间"
_types: _types:
@@ -1123,7 +1127,7 @@ _achievements:
title: "休息一下!" title: "休息一下!"
description: "启动客户端超过30分钟" description: "启动客户端超过30分钟"
_noteDeletedWithin1min: _noteDeletedWithin1min:
title: "无话可说" title: "欲言又止"
description: "发帖后一分钟内就将其删除" description: "发帖后一分钟内就将其删除"
_postedAtLateNight: _postedAtLateNight:
title: "夜猫子" title: "夜猫子"
@@ -1430,9 +1434,9 @@ _theme:
infoFg: "信息文本" infoFg: "信息文本"
infoWarnBg: "警告背景" infoWarnBg: "警告背景"
infoWarnFg: "警告文本" infoWarnFg: "警告文本"
cwBg: "CW 按钮背景" cwBg: "隐藏内容按钮背景"
cwFg: "CW 按钮文本" cwFg: "隐藏内容按钮文本"
cwHoverBg: "CW 按钮背景(悬停)" cwHoverBg: "隐藏内容按钮背景(悬停)"
toastBg: "Toast通知背景" toastBg: "Toast通知背景"
toastFg: "Toast通知文本" toastFg: "Toast通知文本"
buttonBg: "按钮背景" buttonBg: "按钮背景"
@@ -1464,6 +1468,7 @@ _ago:
weeksAgo: "{n}周前" weeksAgo: "{n}周前"
monthsAgo: "{n}月前" monthsAgo: "{n}月前"
yearsAgo: "{n}年前" yearsAgo: "{n}年前"
invalid: "没有"
_time: _time:
second: "秒" second: "秒"
minute: "分" minute: "分"
@@ -1497,14 +1502,29 @@ _tutorial:
step8_3: "您也可以稍后再更改通知设置。" step8_3: "您也可以稍后再更改通知设置。"
_2fa: _2fa:
alreadyRegistered: "此设备已被注册" alreadyRegistered: "此设备已被注册"
registerDevice: "注册设备" registerTOTP: "开始设置认证应用"
registerKey: "注册密钥" passwordToTOTP: "请输入您的密码"
step1: "首先,在您的设备上安装验证应用,例如{a}或{b}。" step1: "首先,在您的设备上安装验证应用,例如{a}或{b}。"
step2: "然后,扫描屏幕上显示的二维码。" step2: "然后,扫描屏幕上显示的二维码。"
step2Click: "通过点击QR码您可以使用设备上安装的身份验证器应用程序或密钥环进行注册"
step2Url: "在桌面应用程序中输入以下URL" step2Url: "在桌面应用程序中输入以下URL"
step3Title: "输入验证码"
step3: "输入您的应用提供的动态口令以完成设置。" step3: "输入您的应用提供的动态口令以完成设置。"
step4: "从现在开始,任何登录操作都将要求您提供动态口令。" step4: "从现在开始,任何登录操作都将要求您提供动态口令。"
securityKeyNotSupported: "您的浏览器不支持安全密钥。"
registerTOTPBeforeKey: "要注册安全密钥或Passkey请先设置验证器应用程序。"
securityKeyInfo: "您可以设置使用支持FIDO2的硬件安全密钥、设备上的指纹或PIN来保护您的登录过程。" securityKeyInfo: "您可以设置使用支持FIDO2的硬件安全密钥、设备上的指纹或PIN来保护您的登录过程。"
chromePasskeyNotSupported: "目前不支持 Chrome 的Passkey。"
registerSecurityKey: "注册安全密钥或Passkey"
securityKeyName: "输入密钥名称"
tapSecurityKey: "请按照浏览器说明操作来注册安全密钥或Passkey。"
removeKey: "删除安全密钥"
removeKeyConfirm: "您确定要删除 {name} 吗?"
whyTOTPOnlyRenew: "如果注册了安全密钥,则无法取消验证器应用程序上的设置。"
renewTOTP: "重置验证器应用程序"
renewTOTPConfirm: "当前验证器应用程序的验证码将不再有效"
renewTOTPOk: "重新配置"
renewTOTPCancel: "不用,谢谢"
_permissions: _permissions:
"read:account": "查看账户信息" "read:account": "查看账户信息"
"write:account": "更改帐户信息" "write:account": "更改帐户信息"
@@ -1553,7 +1573,6 @@ _antennaSources:
homeTimeline: "已关注用户的帖子" homeTimeline: "已关注用户的帖子"
users: "来自指定用户的帖子" users: "来自指定用户的帖子"
userList: "来自指定列表中的帖子" userList: "来自指定列表中的帖子"
userGroup: "来自指定群组中用户的帖子"
_weekday: _weekday:
sunday: "星期日" sunday: "星期日"
monday: "星期一" monday: "星期一"
@@ -1628,8 +1647,8 @@ _visibility:
followersDescription: "仅发送至关注者" followersDescription: "仅发送至关注者"
specified: "指定用户" specified: "指定用户"
specifiedDescription: "仅发送至指定用户" specifiedDescription: "仅发送至指定用户"
localOnly: "仅限本地" disableFederation: "不参与联合"
localOnlyDescription: "对远程用户不可见" disableFederationDescription: "不发送到其他实例"
_postForm: _postForm:
replyPlaceholder: "回复这个帖子..." replyPlaceholder: "回复这个帖子..."
quotePlaceholder: "引用这个帖子..." quotePlaceholder: "引用这个帖子..."
@@ -1645,7 +1664,7 @@ _profile:
name: "昵称" name: "昵称"
username: "用户名" username: "用户名"
description: "个人简介" description: "个人简介"
youCanIncludeHashtags: "你可以在个人简介中包含一#标签。" youCanIncludeHashtags: "你可以在个人简介中包含一#标签。"
metadata: "附加信息" metadata: "附加信息"
metadataEdit: "附加信息编辑" metadataEdit: "附加信息编辑"
metadataDescription: "最多可以在个人资料中以表格形式显示四条其他信息。" metadataDescription: "最多可以在个人资料中以表格形式显示四条其他信息。"
@@ -1767,12 +1786,9 @@ _notification:
youGotReply: "来自{name}的回复" youGotReply: "来自{name}的回复"
youGotQuote: "来自{name}的引用" youGotQuote: "来自{name}的引用"
youRenoted: "来自{name}的转发" youRenoted: "来自{name}的转发"
youGotMessagingMessageFromUser: "来自{name}的聊天"
youGotMessagingMessageFromGroup: "来自{name}的群聊"
youWereFollowed: "关注了你。" youWereFollowed: "关注了你。"
youReceivedFollowRequest: "您有新的关注请求" youReceivedFollowRequest: "您有新的关注请求"
yourFollowRequestAccepted: "您的关注请求已通过" yourFollowRequestAccepted: "您的关注请求已通过"
youWereInvitedToGroup: "您有新的群组邀请"
pollEnded: "问卷调查结果已生成。" pollEnded: "问卷调查结果已生成。"
unreadAntennaNote: "天线 {name}" unreadAntennaNote: "天线 {name}"
emptyPushNotificationMessage: "推送通知已更新" emptyPushNotificationMessage: "推送通知已更新"
@@ -1788,7 +1804,7 @@ _notification:
pollEnded: "问卷调查结束" pollEnded: "问卷调查结束"
receiveFollowRequest: "收到关注请求" receiveFollowRequest: "收到关注请求"
followRequestAccepted: "关注请求已通过" followRequestAccepted: "关注请求已通过"
groupInvited: "加入群组邀请" achievementEarned: "取得的成就"
app: "关联应用的通知" app: "关联应用的通知"
_actions: _actions:
followBack: "回关" followBack: "回关"
@@ -1821,3 +1837,6 @@ _deck:
channel: "频道" channel: "频道"
mentions: "提及" mentions: "提及"
direct: "指定用户" direct: "指定用户"
_dialog:
charactersExceeded: "已经超过了最大字符数! 当前字符数 {current} / 限制字符数 {max}"
charactersBelow: "低于最小字符数!当前字符数 {current} / 限制字符数 {min}"

View File

@@ -46,7 +46,7 @@ copyContent: "複製內容"
copyLink: "複製連結" copyLink: "複製連結"
delete: "刪除" delete: "刪除"
deleteAndEdit: "刪除並編輯" deleteAndEdit: "刪除並編輯"
deleteAndEditConfirm: "要刪除並再次編輯嗎?此貼文的所有情感、轉發和回覆也將會消失。" deleteAndEditConfirm: "要刪除並再次編輯嗎?此貼文的所有反應、轉發和回覆也將會消失。"
addToList: "加入至清單" addToList: "加入至清單"
sendMessage: "發送訊息" sendMessage: "發送訊息"
copyRSS: "複製RSS" copyRSS: "複製RSS"
@@ -103,14 +103,16 @@ renoted: "轉傳成功"
cantRenote: "無法轉發此貼文。" cantRenote: "無法轉發此貼文。"
cantReRenote: "無法轉傳之前已經轉傳過的內容。" cantReRenote: "無法轉傳之前已經轉傳過的內容。"
quote: "引用" quote: "引用"
inChannelRenote: "在頻道內轉發"
inChannelQuote: "在頻道內引用"
pinnedNote: "已置頂的貼文" pinnedNote: "已置頂的貼文"
pinned: "置頂" pinned: "置頂"
you: "您" you: "您"
clickToShow: "按一下以顯示" clickToShow: "按一下以顯示"
sensitive: "敏感內容" sensitive: "敏感內容"
add: "新增" add: "新增"
reaction: "情感" reaction: "反應"
reactions: "情感" reactions: "反應"
reactionSetting: "在選擇器中顯示反應" reactionSetting: "在選擇器中顯示反應"
reactionSettingDescription2: "拖動以重新列序,點擊以刪除,按下 + 添加。" reactionSettingDescription2: "拖動以重新列序,點擊以刪除,按下 + 添加。"
rememberNoteVisibility: "記住貼文可見性" rememberNoteVisibility: "記住貼文可見性"
@@ -211,7 +213,7 @@ default: "預設"
defaultValueIs: "預設值:{value}" defaultValueIs: "預設值:{value}"
noCustomEmojis: "沒有自訂的表情符號" noCustomEmojis: "沒有自訂的表情符號"
noJobs: "沒有任務" noJobs: "沒有任務"
federating: "整合搜索中" federating: "聯邦運作中"
blocked: "已封鎖" blocked: "已封鎖"
suspended: "已凍結" suspended: "已凍結"
all: "全部" all: "全部"
@@ -391,16 +393,19 @@ about: "關於"
aboutMisskey: "關於 Misskey" aboutMisskey: "關於 Misskey"
administrator: "管理員" administrator: "管理員"
token: "權杖" token: "權杖"
twoStepAuthentication: "兩階段驗證" 2fa: "雙因素驗證"
totp: "驗證應用程式"
totpDescription: "以驗證應用程式輸入一次性密碼"
moderator: "審查員" moderator: "審查員"
moderation: "審查" moderation: "審查"
nUsersMentioned: "提到了{n}" nUsersMentioned: "提到了{n}"
securityKeyAndPasskey: "安全金鑰・Passkey"
securityKey: "安全金鑰" securityKey: "安全金鑰"
securityKeyName: "金鑰名稱"
registerSecurityKey: "註冊安全金鑰"
lastUsed: "上次使用" lastUsed: "上次使用"
lastUsedAt: "最後使用:{t}"
unregister: "註銷帳號" unregister: "註銷帳號"
passwordLessLogin: "設置無密碼登入" passwordLessLogin: "設置無密碼登入"
passwordLessLoginDescription: "不使用密碼,以安全金鑰或 Passkey 登入"
resetPassword: "重置密碼" resetPassword: "重置密碼"
newPasswordIs: "新密碼為「{password}」" newPasswordIs: "新密碼為「{password}」"
reduceUiAnimation: "減少介面的動態視覺" reduceUiAnimation: "減少介面的動態視覺"
@@ -415,24 +420,15 @@ markAsReadAllTalkMessages: "標記所有訊息為已讀"
help: "幫助" help: "幫助"
inputMessageHere: "在此輸入訊息" inputMessageHere: "在此輸入訊息"
close: "關閉" close: "關閉"
group: "群組"
groups: "群組"
createGroup: "創建群組"
ownedGroups: "擁有的群組"
joinedGroups: "群組成員"
invites: "邀請" invites: "邀請"
groupName: "群組名稱"
members: "成員" members: "成員"
transfer: "轉讓" transfer: "轉讓"
messagingWithUser: "與其他使用者聊天"
messagingWithGroup: "發送訊息至群組"
title: "標題" title: "標題"
text: "文字" text: "文字"
enable: "啟用" enable: "啟用"
next: "下一步" next: "下一步"
retype: "重新輸入" retype: "再次輸入"
noteOf: "{user}的貼文" noteOf: "{user}的貼文"
inviteToGroup: "邀請至群組"
quoteAttached: "引用" quoteAttached: "引用"
quoteQuestion: "是否要引用?" quoteQuestion: "是否要引用?"
noMessagesYet: "沒有訊息" noMessagesYet: "沒有訊息"
@@ -454,17 +450,13 @@ passwordMatched: "密碼一致"
passwordNotMatched: "密碼不一致" passwordNotMatched: "密碼不一致"
signinWith: "以{x}登錄" signinWith: "以{x}登錄"
signinFailed: "登入失敗。 請檢查使用者名稱和密碼。" signinFailed: "登入失敗。 請檢查使用者名稱和密碼。"
tapSecurityKey: "點擊安全密鑰"
or: "或者" or: "或者"
language: "語言" language: "語言"
uiLanguage: "介面語言" uiLanguage: "介面語言"
groupInvited: "您有新的群組邀請"
aboutX: "關於{x}" aboutX: "關於{x}"
emojiStyle: "表情符號的風格" emojiStyle: "表情符號的風格"
native: "原生" native: "原生"
disableDrawer: "不顯示下拉式選單" disableDrawer: "不顯示下拉式選單"
youHaveNoGroups: "找不到群組"
joinOrCreateGroup: "請加入現有群組,或創建新群組。"
noHistory: "沒有歷史紀錄" noHistory: "沒有歷史紀錄"
signinHistory: "登入歷史" signinHistory: "登入歷史"
enableAdvancedMfm: "啟用高級MFM" enableAdvancedMfm: "啟用高級MFM"
@@ -673,8 +665,8 @@ repliedCount: "回覆數量"
renotedCount: "轉發次數" renotedCount: "轉發次數"
followingCount: "正在跟隨的用戶數量" followingCount: "正在跟隨的用戶數量"
followersCount: "跟隨者數量" followersCount: "跟隨者數量"
sentReactionsCount: "情感發送次數" sentReactionsCount: "反應發送次數"
receivedReactionsCount: "情感收到次數" receivedReactionsCount: "收到反應次數"
pollVotesCount: "已統計的投票數" pollVotesCount: "已統計的投票數"
pollVotedCount: "已投票數" pollVotedCount: "已投票數"
yes: "確定" yes: "確定"
@@ -787,6 +779,7 @@ popularPosts: "熱門的貼文"
shareWithNote: "在貼文中分享" shareWithNote: "在貼文中分享"
ads: "廣告" ads: "廣告"
expiration: "期限" expiration: "期限"
startingperiod: "開始期間"
memo: "備忘錄" memo: "備忘錄"
priority: "優先級" priority: "優先級"
high: "高" high: "高"
@@ -819,6 +812,7 @@ lastCommunication: "最近的通信"
resolved: "已解決" resolved: "已解決"
unresolved: "未解決" unresolved: "未解決"
breakFollow: "移除追蹤者" breakFollow: "移除追蹤者"
breakFollowConfirm: "確定要取消被追隨嗎?"
itsOn: "已開啟" itsOn: "已開啟"
itsOff: "已關閉" itsOff: "已關閉"
emailRequiredForSignup: "註冊帳戶需要電子郵件地址" emailRequiredForSignup: "註冊帳戶需要電子郵件地址"
@@ -838,8 +832,6 @@ deleteAccountConfirm: "將要刪除帳戶。是否確定?"
incorrectPassword: "密碼錯誤。" incorrectPassword: "密碼錯誤。"
voteConfirm: "確定投給「{choice}」?" voteConfirm: "確定投給「{choice}」?"
hide: "隱藏" hide: "隱藏"
leaveGroup: "離開群組"
leaveGroupConfirm: "確定離開「{name}」?"
useDrawerReactionPickerForMobile: "在移動設備上使用抽屜顯示" useDrawerReactionPickerForMobile: "在移動設備上使用抽屜顯示"
welcomeBackWithName: "歡迎回來,{name}" welcomeBackWithName: "歡迎回來,{name}"
clickToFinishEmailVerification: "點擊 [{ok}] 完成電子郵件地址認證。" clickToFinishEmailVerification: "點擊 [{ok}] 完成電子郵件地址認證。"
@@ -855,6 +847,7 @@ instanceDefaultLightTheme: "實例預設的淺色主題"
instanceDefaultDarkTheme: "實例預設的深色主題" instanceDefaultDarkTheme: "實例預設的深色主題"
instanceDefaultThemeDescription: "輸入物件形式的主题代碼" instanceDefaultThemeDescription: "輸入物件形式的主题代碼"
mutePeriod: "靜音的期限" mutePeriod: "靜音的期限"
period: "期限"
indefinitely: "無期限" indefinitely: "無期限"
tenMinutes: "10分鐘" tenMinutes: "10分鐘"
oneHour: "1小時" oneHour: "1小時"
@@ -952,6 +945,13 @@ thisPostMayBeAnnoyingHome: "發布到首頁"
thisPostMayBeAnnoyingCancel: "退出" thisPostMayBeAnnoyingCancel: "退出"
thisPostMayBeAnnoyingIgnore: "直接發布貼文" thisPostMayBeAnnoyingIgnore: "直接發布貼文"
collapseRenotes: "省略顯示已看過的轉發貼文" collapseRenotes: "省略顯示已看過的轉發貼文"
internalServerError: "內部伺服器錯誤"
internalServerErrorDescription: "內部伺服器發生了非預期的錯誤。"
copyErrorInfo: "複製錯誤資訊"
joinThisServer: "在此伺服器上註冊"
exploreOtherServers: "探索其他伺服器"
letsLookAtTimeline: "看看時間軸"
disableFederationWarn: "聯邦被停用了。即使停用也不會讓您的貼文不公開,在大多數情況下,不需要啟用這個選項。"
_achievements: _achievements:
earnedAt: "獲得日期" earnedAt: "獲得日期"
_types: _types:
@@ -1096,7 +1096,7 @@ _achievements:
title: "成群結隊" title: "成群結隊"
description: "跟隨者超過50人了" description: "跟隨者超過50人了"
_followers100: _followers100:
title: "紅人" title: "熱門人物"
description: "跟隨者超過100人了" description: "跟隨者超過100人了"
_followers300: _followers300:
title: "請排成一排" title: "請排成一排"
@@ -1154,7 +1154,7 @@ _achievements:
description: "試圖遞迴套入雲端硬碟資料夾" description: "試圖遞迴套入雲端硬碟資料夾"
_reactWithoutRead: _reactWithoutRead:
title: "有好好讀過嗎?" title: "有好好讀過嗎?"
description: "對包含100字以上內容的貼文做出情感反應" description: "對包含100字以上內容的貼文在3秒以內做出反應"
_clickedClickHere: _clickedClickHere:
title: "點擊這裡" title: "點擊這裡"
description: "已點擊這裡了" description: "已點擊這裡了"
@@ -1465,6 +1465,7 @@ _ago:
weeksAgo: "{n}周前" weeksAgo: "{n}周前"
monthsAgo: "{n}個月前" monthsAgo: "{n}個月前"
yearsAgo: "{n}年前" yearsAgo: "{n}年前"
invalid: "未發現"
_time: _time:
second: "秒" second: "秒"
minute: "分鐘" minute: "分鐘"
@@ -1488,7 +1489,7 @@ _tutorial:
step5_3: "想要追隨其他人,只要點擊他們的大頭貼並按「追隨」即可。" step5_3: "想要追隨其他人,只要點擊他們的大頭貼並按「追隨」即可。"
step5_4: "如果使用者的名字旁有鎖頭的圖示,代表他們需要手動核准你的追隨請求。" step5_4: "如果使用者的名字旁有鎖頭的圖示,代表他們需要手動核准你的追隨請求。"
step6_1: "現在你可以在時間軸上看到其他用戶的貼文。" step6_1: "現在你可以在時間軸上看到其他用戶的貼文。"
step6_2: "你也可以對別人的貼文作出「情感」,作出簡單的回覆。" step6_2: "你也可以對別人的貼文作出「反應」,作出簡單的回覆。"
step6_3: "在他人的貼文按下\"+\"圖標,即可選擇喜好的表情符號進行回應。" step6_3: "在他人的貼文按下\"+\"圖標,即可選擇喜好的表情符號進行回應。"
step7_1: "以上為Misskey的基本操作說明教學在此告一段落。辛苦了。" step7_1: "以上為Misskey的基本操作說明教學在此告一段落。辛苦了。"
step7_2: "歡迎到{help}來瞭解更多Misskey相關介紹。" step7_2: "歡迎到{help}來瞭解更多Misskey相關介紹。"
@@ -1498,14 +1499,29 @@ _tutorial:
step8_3: "通知的設定可以在之後變更。" step8_3: "通知的設定可以在之後變更。"
_2fa: _2fa:
alreadyRegistered: "此設備已經被註冊過了" alreadyRegistered: "此設備已經被註冊過了"
registerDevice: "註冊裝置" registerTOTP: "開始設定驗證應用程式"
registerKey: "註冊鍵" passwordToTOTP: "請輸入密碼"
step1: "首先,在您的設備上安裝二步驗證程式,例如{a}或{b}。" step1: "首先,在您的設備上安裝二步驗證程式,例如{a}或{b}。"
step2: "然後掃描螢幕上的QR code。" step2: "然後掃描螢幕上的QR code。"
step2Click: "點擊QR code可以使用設備上安裝的驗證應用程式或金鑰環進行註冊。"
step2Url: "在桌面版應用中請輸入以下的URL" step2Url: "在桌面版應用中請輸入以下的URL"
step3Title: "輸入驗證碼"
step3: "輸入您的App提供的權杖以完成設定。" step3: "輸入您的App提供的權杖以完成設定。"
step4: "從現在開始,任何登入操作都將要求您提供權杖。" step4: "從現在開始,任何登入操作都將要求您提供權杖。"
securityKeyNotSupported: "您的瀏覽器不支援安全金鑰。"
registerTOTPBeforeKey: "要註冊安全金鑰・Passkey請先設定驗證應用程式。"
securityKeyInfo: "您可以設定使用支援FIDO2的硬體安全鎖、終端設備的指纹認證或者PIN碼來登入。" securityKeyInfo: "您可以設定使用支援FIDO2的硬體安全鎖、終端設備的指纹認證或者PIN碼來登入。"
chromePasskeyNotSupported: "目前不支援Chrome的Passkey。"
registerSecurityKey: "註冊安全金鑰・Passkey"
securityKeyName: "輸入金鑰名稱"
tapSecurityKey: "按照瀏覽器的說明操作註冊安全金鑰和Passkey。"
removeKey: "刪除安全金鑰"
removeKeyConfirm: "要刪除{name}嗎?"
whyTOTPOnlyRenew: "如果註冊了安全金鑰,則無法解除驗證應用程式的設定。"
renewTOTP: "重設驗證應用程式"
renewTOTPConfirm: "目前驗證應用程式的驗證碼將無法使用。"
renewTOTPOk: "重設"
renewTOTPCancel: "現在不要"
_permissions: _permissions:
"read:account": "查看我的帳戶資訊" "read:account": "查看我的帳戶資訊"
"write:account": "更改我的帳戶資訊" "write:account": "更改我的帳戶資訊"
@@ -1524,8 +1540,8 @@ _permissions:
"write:notes": "撰寫或刪除貼文" "write:notes": "撰寫或刪除貼文"
"read:notifications": "查看通知" "read:notifications": "查看通知"
"write:notifications": "編輯通知" "write:notifications": "編輯通知"
"read:reactions": "查看情感" "read:reactions": "查看反應"
"write:reactions": "編輯情感" "write:reactions": "編輯反應"
"write:votes": "投票" "write:votes": "投票"
"read:pages": "顯示頁面" "read:pages": "顯示頁面"
"write:pages": "編輯頁面" "write:pages": "編輯頁面"
@@ -1554,7 +1570,6 @@ _antennaSources:
homeTimeline: "來自已追隨使用者的貼文" homeTimeline: "來自已追隨使用者的貼文"
users: "來自特定使用者的貼文" users: "來自特定使用者的貼文"
userList: "來自特定清單中的貼文" userList: "來自特定清單中的貼文"
userGroup: "來自特定群組的貼文"
_weekday: _weekday:
sunday: "週日" sunday: "週日"
monday: "週一" monday: "週一"
@@ -1578,7 +1593,7 @@ _widgets:
photos: "照片" photos: "照片"
digitalClock: "電子時鐘" digitalClock: "電子時鐘"
unixClock: "UNIX時間" unixClock: "UNIX時間"
federation: "聯邦宇宙" federation: "站台聯邦"
instanceCloud: "實例雲" instanceCloud: "實例雲"
postForm: "發佈窗口" postForm: "發佈窗口"
slideshow: "幻燈片" slideshow: "幻燈片"
@@ -1629,8 +1644,8 @@ _visibility:
followersDescription: "僅發送至關注者" followersDescription: "僅發送至關注者"
specified: "指定使用者" specified: "指定使用者"
specifiedDescription: "僅發送至指定使用者" specifiedDescription: "僅發送至指定使用者"
localOnly: "僅限本地" disableFederation: "停用聯邦"
localOnlyDescription: "對遠端使用者隱藏" disableFederationDescription: "不要傳遞給其他實例"
_postForm: _postForm:
replyPlaceholder: "回覆此貼文..." replyPlaceholder: "回覆此貼文..."
quotePlaceholder: "引用此貼文..." quotePlaceholder: "引用此貼文..."
@@ -1768,12 +1783,9 @@ _notification:
youGotReply: "{name}回覆了您" youGotReply: "{name}回覆了您"
youGotQuote: "{name}引用了您" youGotQuote: "{name}引用了您"
youRenoted: "{name} 轉發了你的貼文" youRenoted: "{name} 轉發了你的貼文"
youGotMessagingMessageFromUser: "{name}發送給您的訊息"
youGotMessagingMessageFromGroup: "{name}發送給您的訊息"
youWereFollowed: "您有新的追隨者" youWereFollowed: "您有新的追隨者"
youReceivedFollowRequest: "您有新的追隨請求" youReceivedFollowRequest: "您有新的追隨請求"
yourFollowRequestAccepted: "您的追隨請求已通過" yourFollowRequestAccepted: "您的追隨請求已通過"
youWereInvitedToGroup: "您有新的群組邀請"
pollEnded: "問卷調查已產生結果" pollEnded: "問卷調查已產生結果"
unreadAntennaNote: "天線 {name}" unreadAntennaNote: "天線 {name}"
emptyPushNotificationMessage: "推送通知已更新" emptyPushNotificationMessage: "推送通知已更新"
@@ -1789,7 +1801,7 @@ _notification:
pollEnded: "問卷調查結束" pollEnded: "問卷調查結束"
receiveFollowRequest: "已收到追隨請求" receiveFollowRequest: "已收到追隨請求"
followRequestAccepted: "追隨請求已接受" followRequestAccepted: "追隨請求已接受"
groupInvited: "加入社群邀請" achievementEarned: "獲得成就"
app: "應用程式通知" app: "應用程式通知"
_actions: _actions:
followBack: "回關" followBack: "回關"
@@ -1822,3 +1834,6 @@ _deck:
channel: "頻道" channel: "頻道"
mentions: "提及" mentions: "提及"
direct: "指定使用者" direct: "指定使用者"
_dialog:
charactersExceeded: "已超過最大字數!現在 {current} / 限制 {max}"
charactersBelow: "低於最少字數!現在 {current} / 限制 {max}"

View File

@@ -1,6 +1,6 @@
{ {
"name": "misskey", "name": "misskey",
"version": "13.6.1", "version": "13.9.0",
"codename": "nasubi", "codename": "nasubi",
"repository": { "repository": {
"type": "git", "type": "git",
@@ -16,10 +16,11 @@
"scripts": { "scripts": {
"build-pre": "node ./scripts/build-pre.js", "build-pre": "node ./scripts/build-pre.js",
"build": "pnpm build-pre && pnpm -r build && pnpm gulp", "build": "pnpm build-pre && pnpm -r build && pnpm gulp",
"start": "cd packages/backend && node ./built/boot/index.js", "start": "pnpm check:connect && cd packages/backend && node ./built/boot/index.js",
"start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/index.js", "start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/index.js",
"init": "pnpm migrate", "init": "pnpm migrate",
"migrate": "cd packages/backend && pnpm migrate", "migrate": "cd packages/backend && pnpm migrate",
"check:connect": "cd packages/backend && pnpm check:connect",
"migrateandstart": "pnpm migrate && pnpm start", "migrateandstart": "pnpm migrate && pnpm start",
"gulp": "pnpm exec gulp build", "gulp": "pnpm exec gulp build",
"watch": "pnpm dev", "watch": "pnpm dev",
@@ -54,12 +55,12 @@
"devDependencies": { "devDependencies": {
"@types/gulp": "4.0.10", "@types/gulp": "4.0.10",
"@types/gulp-rename": "2.0.1", "@types/gulp-rename": "2.0.1",
"@typescript-eslint/eslint-plugin": "5.51.0", "@typescript-eslint/eslint-plugin": "5.53.0",
"@typescript-eslint/parser": "5.51.0", "@typescript-eslint/parser": "5.53.0",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"cypress": "12.5.1", "cypress": "12.7.0",
"eslint": "8.33.0", "eslint": "8.35.0",
"start-server-and-test": "1.15.3" "start-server-and-test": "1.15.4"
}, },
"optionalDependencies": { "optionalDependencies": {
"@tensorflow/tfjs-core": "4.2.0" "@tensorflow/tfjs-core": "4.2.0"

View File

@@ -1,7 +1,7 @@
module.exports = { module.exports = {
parserOptions: { parserOptions: {
tsconfigRootDir: __dirname, tsconfigRootDir: __dirname,
project: ['./tsconfig.json'], project: ['./tsconfig.json', './test/tsconfig.json'],
}, },
extends: [ extends: [
'../shared/.eslintrc.js', '../shared/.eslintrc.js',

View File

@@ -1,25 +1,23 @@
{ {
"$schema": "https://json.schemastore.org/swcrc", "$schema": "https://json.schemastore.org/swcrc",
"jsc": { "jsc": {
"parser": { "parser": {
"syntax": "typescript", "syntax": "typescript",
"dynamicImport": true, "dynamicImport": true,
"decorators": true "decorators": true
}, },
"transform": { "transform": {
"legacyDecorator": true, "legacyDecorator": true,
"decoratorMetadata": true "decoratorMetadata": true
}, },
"experimental": { "experimental": {
"keepImportAssertions": true "keepImportAssertions": true
}, },
"baseUrl": ".", "baseUrl": "src",
"paths": { "paths": {
"@/*": [ "@/*": ["*"]
"./src/*"
]
}, },
"target": "es2021" "target": "es2021"
}, },
"minify": false "minify": false
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 162 KiB

View File

@@ -0,0 +1,10 @@
import { loadConfig } from './built/config.js';
import { createRedisConnection } from './built/redis.js';
const config = loadConfig();
const redis = createRedisConnection(config);
redis.on('connect', () => redis.disconnect());
redis.on('error', (e) => {
throw e;
});

View File

@@ -1,14 +0,0 @@
// https://github.com/facebook/jest/issues/12270#issuecomment-1194746382
const nativeModule = require('node:module');
function resolver(module, options) {
const { basedir, defaultResolver } = options;
try {
return defaultResolver(module, options);
} catch (error) {
return nativeModule.createRequire(basedir).resolve(module);
}
}
module.exports = resolver;

View File

@@ -20,7 +20,7 @@ module.exports = {
// collectCoverage: false, // collectCoverage: false,
// An array of glob patterns indicating a set of files for which coverage information should be collected // An array of glob patterns indicating a set of files for which coverage information should be collected
collectCoverageFrom: ['src/**/*.ts'], collectCoverageFrom: ['src/**/*.ts', '!src/**/*.test.ts'],
// The directory where Jest should output its coverage files // The directory where Jest should output its coverage files
coverageDirectory: "coverage", coverageDirectory: "coverage",
@@ -83,8 +83,15 @@ module.exports = {
// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
moduleNameMapper: { moduleNameMapper: {
"^@/(.*?).js": "<rootDir>/src/$1.ts", // Do not resolve .wasm.js to .wasm by the rule below
'^(\\.{1,2}/.*)\\.js$': '$1', '^(.+)\\.wasm\\.js$': '$1.wasm.js',
// SWC converts @/foo/bar.js to `../../src/foo/bar.js`, and then this rule
// converts it again to `../../src/foo/bar` which then can be resolved to
// `.ts` files.
// See https://github.com/swc-project/jest/issues/64#issuecomment-1029753225
// TODO: Use `--allowImportingTsExtensions` on TypeScript 5.0 so that we can
// directly import `.ts` files without this hack.
'^((?:\\.{1,2}|[A-Z:])*/.*)\\.js$': '$1',
}, },
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
@@ -112,7 +119,7 @@ module.exports = {
// resetModules: false, // resetModules: false,
// A path to a custom resolver // A path to a custom resolver
resolver: './jest-resolver.cjs', // resolver: './jest-resolver.cjs',
// Automatically restore mock state between every test // Automatically restore mock state between every test
restoreMocks: true, restoreMocks: true,
@@ -152,7 +159,8 @@ module.exports = {
// The glob patterns Jest uses to detect test files // The glob patterns Jest uses to detect test files
testMatch: [ testMatch: [
"<rootDir>/test/unit/**/*.ts", "<rootDir>/test/unit/**/*.ts",
//"<rootDir>/test/e2e/**/*.ts" "<rootDir>/src/**/*.test.ts",
"<rootDir>/test/e2e/**/*.ts",
], ],
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
@@ -199,4 +207,13 @@ module.exports = {
// watchman: true, // watchman: true,
extensionsToTreatAsEsm: ['.ts'], extensionsToTreatAsEsm: ['.ts'],
testTimeout: 60000,
// Let Jest kill the test worker whenever it grows too much
// (It seems there's a known memory leak issue in Node.js' vm.Script used by Jest)
// https://github.com/facebook/jest/issues/11956
maxWorkers: 1, // Make it use worker (that can be killed and restarted)
logHeapUsage: true, // To debug when out-of-memory happens on CI
workerIdleMemoryLimit: '1GiB', // Limit the worker to 1GB (GitHub Workflows dies at 2GB)
}; };

View File

@@ -0,0 +1,27 @@
export class dropGroup1676434944993 {
name = 'dropGroup1676434944993'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "antenna" DROP CONSTRAINT "FK_ccbf5a8c0be4511133dcc50ddeb"`);
await queryRunner.query(`ALTER TABLE "notification" DROP CONSTRAINT "FK_8fe87814e978053a53b1beb7e98"`);
await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "userGroupJoiningId"`);
await queryRunner.query(`ALTER TABLE "notification" DROP COLUMN "userGroupInvitationId"`);
await queryRunner.query(`ALTER TYPE "public"."antenna_src_enum" RENAME TO "antenna_src_enum_old"`);
await queryRunner.query(`CREATE TYPE "public"."antenna_src_enum" AS ENUM('home', 'all', 'users', 'list')`);
await queryRunner.query(`ALTER TABLE "antenna" ALTER COLUMN "src" TYPE "public"."antenna_src_enum" USING "src"::"text"::"public"."antenna_src_enum"`);
await queryRunner.query(`DROP TYPE "public"."antenna_src_enum_old"`);
await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "emailNotificationTypes" SET DEFAULT '["follow","receiveFollowRequest"]'`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "emailNotificationTypes" SET DEFAULT '["follow", "receiveFollowRequest", "groupInvited"]'`);
await queryRunner.query(`CREATE TYPE "public"."antenna_src_enum_old" AS ENUM('home', 'all', 'users', 'list', 'group')`);
await queryRunner.query(`ALTER TABLE "antenna" ALTER COLUMN "src" TYPE "public"."antenna_src_enum_old" USING "src"::"text"::"public"."antenna_src_enum_old"`);
await queryRunner.query(`DROP TYPE "public"."antenna_src_enum"`);
await queryRunner.query(`ALTER TYPE "public"."antenna_src_enum_old" RENAME TO "antenna_src_enum"`);
await queryRunner.query(`ALTER TABLE "notification" ADD "userGroupInvitationId" character varying(32)`);
await queryRunner.query(`ALTER TABLE "antenna" ADD "userGroupJoiningId" character varying(32)`);
await queryRunner.query(`ALTER TABLE "notification" ADD CONSTRAINT "FK_8fe87814e978053a53b1beb7e98" FOREIGN KEY ("userGroupInvitationId") REFERENCES "user_group_invitation"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
await queryRunner.query(`ALTER TABLE "antenna" ADD CONSTRAINT "FK_ccbf5a8c0be4511133dcc50ddeb" FOREIGN KEY ("userGroupJoiningId") REFERENCES "user_group_joining"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
}

View File

@@ -0,0 +1,9 @@
export class ad1676438468213 {
name = 'ad1676438468213';
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "ad" ADD "startsAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "ad" DROP COLUMN "startsAt"`);
}
}

View File

@@ -0,0 +1,13 @@
export class roleAssignmentExpiresAt1677570181236 {
name = 'roleAssignmentExpiresAt1677570181236'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "role_assignment" ADD "expiresAt" TIMESTAMP WITH TIME ZONE`);
await queryRunner.query(`CREATE INDEX "IDX_539b6c08c05067599743bb6389" ON "role_assignment" ("expiresAt") `);
}
async down(queryRunner) {
await queryRunner.query(`DROP INDEX "public"."IDX_539b6c08c05067599743bb6389"`);
await queryRunner.query(`ALTER TABLE "role_assignment" DROP COLUMN "expiresAt"`);
}
}

View File

@@ -7,46 +7,62 @@
"start": "node ./built/index.js", "start": "node ./built/index.js",
"start:test": "NODE_ENV=test node ./built/index.js", "start:test": "NODE_ENV=test node ./built/index.js",
"migrate": "pnpm typeorm migration:run -d ormconfig.js", "migrate": "pnpm typeorm migration:run -d ormconfig.js",
"build:swc": "swc src -d built -D", "check:connect": "node ./check_connect.js",
"build": "swc src -d built -D",
"watch:swc": "swc src -d built -D -w", "watch:swc": "swc src -d built -D -w",
"build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json", "build:tsc": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
"watch": "node watch.mjs", "watch": "node watch.mjs",
"lint": "tsc --noEmit && eslint --quiet \"src/**/*.ts\"", "typecheck": "tsc --noEmit",
"jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --runInBand", "eslint": "eslint --quiet \"src/**/*.ts\"",
"jest-and-coverage": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit --runInBand", "lint": "pnpm typecheck && pnpm eslint",
"jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit",
"jest-and-coverage": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit",
"jest-clear": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --clearCache", "jest-clear": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --clearCache",
"test": "pnpm jest", "test": "pnpm jest",
"test-and-coverage": "pnpm jest-and-coverage" "test-and-coverage": "pnpm jest-and-coverage"
}, },
"optionalDependencies": { "optionalDependencies": {
"@swc/core-android-arm64": "^1.3.11",
"@swc/core-darwin-arm64": "^1.3.36",
"@swc/core-darwin-x64": "^1.3.36",
"@swc/core-linux-arm-gnueabihf": "^1.3.36",
"@swc/core-linux-arm64-gnu": "^1.3.36",
"@swc/core-linux-arm64-musl": "^1.3.36",
"@swc/core-linux-x64-gnu": "^1.3.36",
"@swc/core-linux-x64-musl": "^1.3.36",
"@swc/core-win32-arm64-msvc": "^1.3.36",
"@swc/core-win32-ia32-msvc": "^1.3.36",
"@swc/core-win32-x64-msvc": "^1.3.36",
"@tensorflow/tfjs": "4.2.0", "@tensorflow/tfjs": "4.2.0",
"@tensorflow/tfjs-node": "4.2.0" "@tensorflow/tfjs-node": "4.2.0"
}, },
"dependencies": { "dependencies": {
"@bull-board/api": "4.11.1", "@bull-board/api": "4.12.1",
"@bull-board/fastify": "4.11.1", "@bull-board/fastify": "4.12.1",
"@bull-board/ui": "4.11.1", "@bull-board/ui": "4.12.1",
"@discordapp/twemoji": "14.0.2", "@discordapp/twemoji": "14.0.2",
"@fastify/accepts": "4.1.0", "@fastify/accepts": "4.1.0",
"@fastify/cookie": "8.3.0", "@fastify/cookie": "8.3.0",
"@fastify/cors": "8.2.0", "@fastify/cors": "8.2.0",
"@fastify/http-proxy": "8.4.0", "@fastify/http-proxy": "8.4.0",
"@fastify/multipart": "7.4.0", "@fastify/multipart": "7.4.1",
"@fastify/static": "6.8.0", "@fastify/static": "6.9.0",
"@fastify/view": "7.4.1", "@fastify/view": "7.4.1",
"@nestjs/common": "9.3.7", "@nestjs/common": "9.3.9",
"@nestjs/core": "9.3.7", "@nestjs/core": "9.3.9",
"@nestjs/testing": "9.3.7", "@nestjs/testing": "9.3.9",
"@peertube/http-signature": "1.7.0", "@peertube/http-signature": "1.7.0",
"@sinonjs/fake-timers": "10.0.2", "@sinonjs/fake-timers": "10.0.2",
"@swc/cli": "0.1.62",
"@swc/core": "1.3.36",
"accepts": "1.3.8", "accepts": "1.3.8",
"ajv": "8.12.0", "ajv": "8.12.0",
"archiver": "5.3.1", "archiver": "5.3.1",
"autwh": "0.1.0", "autwh": "0.1.0",
"aws-sdk": "2.1295.0", "aws-sdk": "2.1318.0",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"blurhash": "2.0.4", "blurhash": "2.0.5",
"bull": "4.10.3", "bull": "4.10.4",
"cacheable-lookup": "6.1.0", "cacheable-lookup": "6.1.0",
"cbor": "8.1.0", "cbor": "8.1.0",
"chalk": "5.2.0", "chalk": "5.2.0",
@@ -58,12 +74,13 @@
"date-fns": "2.29.3", "date-fns": "2.29.3",
"deep-email-validator": "0.1.21", "deep-email-validator": "0.1.21",
"escape-regexp": "0.0.1", "escape-regexp": "0.0.1",
"fastify": "4.12.0", "fastify": "4.13.0",
"feed": "4.2.2", "feed": "4.2.2",
"file-type": "18.2.0", "file-type": "18.2.1",
"fluent-ffmpeg": "2.1.2", "fluent-ffmpeg": "2.1.2",
"form-data": "4.0.0", "form-data": "4.0.0",
"got": "12.5.3", "got": "12.5.3",
"happy-dom": "8.9.0",
"hpagent": "1.2.0", "hpagent": "1.2.0",
"ioredis": "4.28.5", "ioredis": "4.28.5",
"ip-cidr": "3.1.0", "ip-cidr": "3.1.0",
@@ -71,7 +88,7 @@
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
"jsdom": "21.1.0", "jsdom": "21.1.0",
"json5": "2.2.3", "json5": "2.2.3",
"jsonld": "8.1.0", "jsonld": "8.1.1",
"jsrsasign": "10.6.1", "jsrsasign": "10.6.1",
"mfm-js": "0.23.3", "mfm-js": "0.23.3",
"mime-types": "2.1.35", "mime-types": "2.1.35",
@@ -83,6 +100,7 @@
"nsfwjs": "2.4.2", "nsfwjs": "2.4.2",
"oauth": "0.10.0", "oauth": "0.10.0",
"os-utils": "0.0.14", "os-utils": "0.0.14",
"otpauth": "^9.0.2",
"parse5": "7.1.2", "parse5": "7.1.2",
"pg": "8.9.0", "pg": "8.9.0",
"private-ip": "3.0.0", "private-ip": "3.0.0",
@@ -102,15 +120,14 @@
"rss-parser": "3.12.0", "rss-parser": "3.12.0",
"rxjs": "7.8.0", "rxjs": "7.8.0",
"s-age": "1.1.2", "s-age": "1.1.2",
"sanitize-html": "2.9.0", "sanitize-html": "2.10.0",
"seedrandom": "3.0.5", "seedrandom": "3.0.5",
"semver": "7.3.8", "semver": "7.3.8",
"sharp": "0.31.3", "sharp": "0.31.3",
"speakeasy": "2.0.0",
"strict-event-emitter-types": "2.0.0", "strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0", "stringz": "2.1.0",
"summaly": "2.7.0", "summaly": "github:misskey-dev/summaly",
"systeminformation": "5.17.8", "systeminformation": "5.17.10",
"tinycolor2": "1.6.0", "tinycolor2": "1.6.0",
"tmp": "0.2.1", "tmp": "0.2.1",
"tsc-alias": "1.8.2", "tsc-alias": "1.8.2",
@@ -124,14 +141,11 @@
"vary": "1.1.2", "vary": "1.1.2",
"web-push": "3.5.0", "web-push": "3.5.0",
"websocket": "1.0.34", "websocket": "1.0.34",
"ws": "8.12.0", "ws": "8.12.1",
"xev": "3.0.2" "xev": "3.0.2"
}, },
"devDependencies": { "devDependencies": {
"@jest/globals": "29.4.2", "@jest/globals": "29.4.3",
"@redocly/openapi-core": "1.0.0-beta.123",
"@swc/cli": "0.1.61",
"@swc/core": "1.3.34",
"@swc/jest": "0.2.24", "@swc/jest": "0.2.24",
"@types/accepts": "1.3.5", "@types/accepts": "1.3.5",
"@types/archiver": "5.3.1", "@types/archiver": "5.3.1",
@@ -141,7 +155,7 @@
"@types/color-convert": "2.0.0", "@types/color-convert": "2.0.0",
"@types/content-disposition": "0.5.5", "@types/content-disposition": "0.5.5",
"@types/escape-regexp": "0.0.1", "@types/escape-regexp": "0.0.1",
"@types/fluent-ffmpeg": "2.1.20", "@types/fluent-ffmpeg": "2.1.21",
"@types/ioredis": "4.28.10", "@types/ioredis": "4.28.10",
"@types/jest": "29.4.0", "@types/jest": "29.4.0",
"@types/js-yaml": "4.0.5", "@types/js-yaml": "4.0.5",
@@ -149,7 +163,7 @@
"@types/jsonld": "1.5.8", "@types/jsonld": "1.5.8",
"@types/jsrsasign": "10.5.5", "@types/jsrsasign": "10.5.5",
"@types/mime-types": "2.1.1", "@types/mime-types": "2.1.1",
"@types/node": "18.13.0", "@types/node": "18.14.1",
"@types/node-fetch": "3.0.3", "@types/node-fetch": "3.0.3",
"@types/nodemailer": "6.4.7", "@types/nodemailer": "6.4.7",
"@types/oauth": "0.9.1", "@types/oauth": "0.9.1",
@@ -165,22 +179,21 @@
"@types/semver": "7.3.13", "@types/semver": "7.3.13",
"@types/sharp": "0.31.1", "@types/sharp": "0.31.1",
"@types/sinonjs__fake-timers": "8.1.2", "@types/sinonjs__fake-timers": "8.1.2",
"@types/speakeasy": "2.0.7",
"@types/tinycolor2": "1.4.3", "@types/tinycolor2": "1.4.3",
"@types/tmp": "0.2.3", "@types/tmp": "0.2.3",
"@types/unzipper": "0.10.5", "@types/unzipper": "0.10.5",
"@types/uuid": "9.0.0", "@types/uuid": "9.0.1",
"@types/vary": "1.1.0", "@types/vary": "1.1.0",
"@types/web-push": "3.3.2", "@types/web-push": "3.3.2",
"@types/websocket": "1.0.5", "@types/websocket": "1.0.5",
"@types/ws": "8.5.4", "@types/ws": "8.5.4",
"@typescript-eslint/eslint-plugin": "5.51.0", "@typescript-eslint/eslint-plugin": "5.52.0",
"@typescript-eslint/parser": "5.51.0", "@typescript-eslint/parser": "5.53.0",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"eslint": "8.33.0", "eslint": "8.35.0",
"eslint-plugin-import": "2.27.5", "eslint-plugin-import": "2.27.5",
"execa": "6.1.0", "execa": "6.1.0",
"jest": "29.4.2", "jest": "29.4.3",
"jest-mock": "29.4.2" "jest-mock": "29.4.3"
} }
} }

View File

@@ -0,0 +1,8 @@
declare module 'redis-lock' {
import type Redis from 'ioredis';
type Lock = (lockName: string, timeout?: number, taskToPerform?: () => Promise<void>) => void;
function redisLock(client: Redis.Redis, retryDelay: number): Lock;
export = redisLock;
}

View File

@@ -1,3 +1,4 @@
import { setTimeout } from 'node:timers/promises';
import { Global, Inject, Module } from '@nestjs/common'; import { Global, Inject, Module } from '@nestjs/common';
import Redis from 'ioredis'; import Redis from 'ioredis';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
@@ -57,6 +58,14 @@ export class GlobalModule implements OnApplicationShutdown {
) {} ) {}
async onApplicationShutdown(signal: string): Promise<void> { async onApplicationShutdown(signal: string): Promise<void> {
if (process.env.NODE_ENV === 'test') {
// XXX:
// Shutting down the existing connections causes errors on Jest as
// Misskey has asynchronous postgres/redis connections that are not
// awaited.
// Let's wait for some random time for them to finish.
await setTimeout(5000);
}
await Promise.all([ await Promise.all([
this.db.destroy(), this.db.destroy(),
this.redisClient.disconnect(), this.redisClient.disconnect(),

View File

@@ -16,12 +16,14 @@ export async function server() {
app.enableShutdownHooks(); app.enableShutdownHooks();
const serverService = app.get(ServerService); const serverService = app.get(ServerService);
serverService.launch(); await serverService.launch();
app.get(ChartManagementService).start(); app.get(ChartManagementService).start();
app.get(JanitorService).start(); app.get(JanitorService).start();
app.get(QueueStatsService).start(); app.get(QueueStatsService).start();
app.get(ServerStatsService).start(); app.get(ServerStatsService).start();
return app;
} }
export async function jobQueue() { export async function jobQueue() {

View File

@@ -32,7 +32,7 @@ export class AccountUpdateService {
// フォロワーがリモートユーザーかつ投稿者がローカルユーザーならUpdateを配信 // フォロワーがリモートユーザーかつ投稿者がローカルユーザーならUpdateを配信
if (this.userEntityService.isLocalUser(user)) { if (this.userEntityService.isLocalUser(user)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUpdate(await this.apRendererService.renderPerson(user), user)); const content = this.apRendererService.addContext(this.apRendererService.renderUpdate(await this.apRendererService.renderPerson(user), user));
this.apDeliverManagerService.deliverToFollowers(user, content); this.apDeliverManagerService.deliverToFollowers(user, content);
this.relayService.deliverToRelays(user, content); this.relayService.deliverToRelays(user, content);
} }

View File

@@ -12,7 +12,7 @@ import { PushNotificationService } from '@/core/PushNotificationService.js';
import * as Acct from '@/misc/acct.js'; import * as Acct from '@/misc/acct.js';
import type { Packed } from '@/misc/schema.js'; import type { Packed } from '@/misc/schema.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { MutingsRepository, NotesRepository, AntennaNotesRepository, AntennasRepository, UserGroupJoiningsRepository, UserListJoiningsRepository } from '@/models/index.js'; import type { MutingsRepository, NotesRepository, AntennaNotesRepository, AntennasRepository, UserListJoiningsRepository } from '@/models/index.js';
import { UtilityService } from '@/core/UtilityService.js'; import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { StreamMessages } from '@/server/api/stream/types.js'; import { StreamMessages } from '@/server/api/stream/types.js';
@@ -39,9 +39,6 @@ export class AntennaService implements OnApplicationShutdown {
@Inject(DI.antennasRepository) @Inject(DI.antennasRepository)
private antennasRepository: AntennasRepository, private antennasRepository: AntennasRepository,
@Inject(DI.userGroupJoiningsRepository)
private userGroupJoiningsRepository: UserGroupJoiningsRepository,
@Inject(DI.userListJoiningsRepository) @Inject(DI.userListJoiningsRepository)
private userListJoiningsRepository: UserListJoiningsRepository, private userListJoiningsRepository: UserListJoiningsRepository,
@@ -160,14 +157,6 @@ export class AntennaService implements OnApplicationShutdown {
})).map(x => x.userId); })).map(x => x.userId);
if (!listUsers.includes(note.userId)) return false; if (!listUsers.includes(note.userId)) return false;
} else if (antenna.src === 'group') {
const joining = await this.userGroupJoiningsRepository.findOneByOrFail({ id: antenna.userGroupJoiningId! });
const groupUsers = (await this.userGroupJoiningsRepository.findBy({
userGroupId: joining.userGroupId,
})).map(x => x.userId);
if (!groupUsers.includes(note.userId)) return false;
} else if (antenna.src === 'users') { } else if (antenna.src === 'users') {
const accts = antenna.users.map(x => { const accts = antenna.users.map(x => {
const { username, host } = Acct.parse(x); const { username, host } = Acct.parse(x);
@@ -182,13 +171,15 @@ export class AntennaService implements OnApplicationShutdown {
.filter(xs => xs.length > 0); .filter(xs => xs.length > 0);
if (keywords.length > 0) { if (keywords.length > 0) {
if (note.text == null) return false; if (note.text == null && note.cw == null) return false;
const _text = (note.text ?? '') + '\n' + (note.cw ?? '');
const matched = keywords.some(and => const matched = keywords.some(and =>
and.every(keyword => and.every(keyword =>
antenna.caseSensitive antenna.caseSensitive
? note.text!.includes(keyword) ? _text.includes(keyword)
: note.text!.toLowerCase().includes(keyword.toLowerCase()), : _text.toLowerCase().includes(keyword.toLowerCase()),
)); ));
if (!matched) return false; if (!matched) return false;
@@ -200,13 +191,15 @@ export class AntennaService implements OnApplicationShutdown {
.filter(xs => xs.length > 0); .filter(xs => xs.length > 0);
if (excludeKeywords.length > 0) { if (excludeKeywords.length > 0) {
if (note.text == null) return false; if (note.text == null && note.cw == null) return false;
const _text = (note.text ?? '') + '\n' + (note.cw ?? '');
const matched = excludeKeywords.some(and => const matched = excludeKeywords.some(and =>
and.every(keyword => and.every(keyword =>
antenna.caseSensitive antenna.caseSensitive
? note.text!.includes(keyword) ? _text.includes(keyword)
: note.text!.toLowerCase().includes(keyword.toLowerCase()), : _text.toLowerCase().includes(keyword.toLowerCase()),
)); ));
if (matched) return false; if (matched) return false;

View File

@@ -12,7 +12,7 @@ const retryDelay = 100;
@Injectable() @Injectable()
export class AppLockService { export class AppLockService {
private lock: (key: string, timeout?: number) => Promise<() => void>; private lock: (key: string, timeout?: number, _?: (() => Promise<void>) | undefined) => Promise<() => void>;
constructor( constructor(
@Inject(DI.redis) @Inject(DI.redis)

View File

@@ -1,5 +1,4 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { DI } from '../di-symbols.js';
import { AccountUpdateService } from './AccountUpdateService.js'; import { AccountUpdateService } from './AccountUpdateService.js';
import { AiService } from './AiService.js'; import { AiService } from './AiService.js';
import { AntennaService } from './AntennaService.js'; import { AntennaService } from './AntennaService.js';
@@ -22,7 +21,6 @@ import { IdService } from './IdService.js';
import { ImageProcessingService } from './ImageProcessingService.js'; import { ImageProcessingService } from './ImageProcessingService.js';
import { InstanceActorService } from './InstanceActorService.js'; import { InstanceActorService } from './InstanceActorService.js';
import { InternalStorageService } from './InternalStorageService.js'; import { InternalStorageService } from './InternalStorageService.js';
import { MessagingService } from './MessagingService.js';
import { MetaService } from './MetaService.js'; import { MetaService } from './MetaService.js';
import { MfmService } from './MfmService.js'; import { MfmService } from './MfmService.js';
import { ModerationLogService } from './ModerationLogService.js'; import { ModerationLogService } from './ModerationLogService.js';
@@ -82,7 +80,6 @@ import { GalleryLikeEntityService } from './entities/GalleryLikeEntityService.js
import { GalleryPostEntityService } from './entities/GalleryPostEntityService.js'; import { GalleryPostEntityService } from './entities/GalleryPostEntityService.js';
import { HashtagEntityService } from './entities/HashtagEntityService.js'; import { HashtagEntityService } from './entities/HashtagEntityService.js';
import { InstanceEntityService } from './entities/InstanceEntityService.js'; import { InstanceEntityService } from './entities/InstanceEntityService.js';
import { MessagingMessageEntityService } from './entities/MessagingMessageEntityService.js';
import { ModerationLogEntityService } from './entities/ModerationLogEntityService.js'; import { ModerationLogEntityService } from './entities/ModerationLogEntityService.js';
import { MutingEntityService } from './entities/MutingEntityService.js'; import { MutingEntityService } from './entities/MutingEntityService.js';
import { NoteEntityService } from './entities/NoteEntityService.js'; import { NoteEntityService } from './entities/NoteEntityService.js';
@@ -93,8 +90,6 @@ import { PageEntityService } from './entities/PageEntityService.js';
import { PageLikeEntityService } from './entities/PageLikeEntityService.js'; import { PageLikeEntityService } from './entities/PageLikeEntityService.js';
import { SigninEntityService } from './entities/SigninEntityService.js'; import { SigninEntityService } from './entities/SigninEntityService.js';
import { UserEntityService } from './entities/UserEntityService.js'; import { UserEntityService } from './entities/UserEntityService.js';
import { UserGroupEntityService } from './entities/UserGroupEntityService.js';
import { UserGroupInvitationEntityService } from './entities/UserGroupInvitationEntityService.js';
import { UserListEntityService } from './entities/UserListEntityService.js'; import { UserListEntityService } from './entities/UserListEntityService.js';
import { FlashEntityService } from './entities/FlashEntityService.js'; import { FlashEntityService } from './entities/FlashEntityService.js';
import { FlashLikeEntityService } from './entities/FlashLikeEntityService.js'; import { FlashLikeEntityService } from './entities/FlashLikeEntityService.js';
@@ -146,7 +141,6 @@ const $IdService: Provider = { provide: 'IdService', useExisting: IdService };
const $ImageProcessingService: Provider = { provide: 'ImageProcessingService', useExisting: ImageProcessingService }; const $ImageProcessingService: Provider = { provide: 'ImageProcessingService', useExisting: ImageProcessingService };
const $InstanceActorService: Provider = { provide: 'InstanceActorService', useExisting: InstanceActorService }; const $InstanceActorService: Provider = { provide: 'InstanceActorService', useExisting: InstanceActorService };
const $InternalStorageService: Provider = { provide: 'InternalStorageService', useExisting: InternalStorageService }; const $InternalStorageService: Provider = { provide: 'InternalStorageService', useExisting: InternalStorageService };
const $MessagingService: Provider = { provide: 'MessagingService', useExisting: MessagingService };
const $MetaService: Provider = { provide: 'MetaService', useExisting: MetaService }; const $MetaService: Provider = { provide: 'MetaService', useExisting: MetaService };
const $MfmService: Provider = { provide: 'MfmService', useExisting: MfmService }; const $MfmService: Provider = { provide: 'MfmService', useExisting: MfmService };
const $ModerationLogService: Provider = { provide: 'ModerationLogService', useExisting: ModerationLogService }; const $ModerationLogService: Provider = { provide: 'ModerationLogService', useExisting: ModerationLogService };
@@ -207,7 +201,6 @@ const $GalleryLikeEntityService: Provider = { provide: 'GalleryLikeEntityService
const $GalleryPostEntityService: Provider = { provide: 'GalleryPostEntityService', useExisting: GalleryPostEntityService }; const $GalleryPostEntityService: Provider = { provide: 'GalleryPostEntityService', useExisting: GalleryPostEntityService };
const $HashtagEntityService: Provider = { provide: 'HashtagEntityService', useExisting: HashtagEntityService }; const $HashtagEntityService: Provider = { provide: 'HashtagEntityService', useExisting: HashtagEntityService };
const $InstanceEntityService: Provider = { provide: 'InstanceEntityService', useExisting: InstanceEntityService }; const $InstanceEntityService: Provider = { provide: 'InstanceEntityService', useExisting: InstanceEntityService };
const $MessagingMessageEntityService: Provider = { provide: 'MessagingMessageEntityService', useExisting: MessagingMessageEntityService };
const $ModerationLogEntityService: Provider = { provide: 'ModerationLogEntityService', useExisting: ModerationLogEntityService }; const $ModerationLogEntityService: Provider = { provide: 'ModerationLogEntityService', useExisting: ModerationLogEntityService };
const $MutingEntityService: Provider = { provide: 'MutingEntityService', useExisting: MutingEntityService }; const $MutingEntityService: Provider = { provide: 'MutingEntityService', useExisting: MutingEntityService };
const $NoteEntityService: Provider = { provide: 'NoteEntityService', useExisting: NoteEntityService }; const $NoteEntityService: Provider = { provide: 'NoteEntityService', useExisting: NoteEntityService };
@@ -218,8 +211,6 @@ const $PageEntityService: Provider = { provide: 'PageEntityService', useExisting
const $PageLikeEntityService: Provider = { provide: 'PageLikeEntityService', useExisting: PageLikeEntityService }; const $PageLikeEntityService: Provider = { provide: 'PageLikeEntityService', useExisting: PageLikeEntityService };
const $SigninEntityService: Provider = { provide: 'SigninEntityService', useExisting: SigninEntityService }; const $SigninEntityService: Provider = { provide: 'SigninEntityService', useExisting: SigninEntityService };
const $UserEntityService: Provider = { provide: 'UserEntityService', useExisting: UserEntityService }; const $UserEntityService: Provider = { provide: 'UserEntityService', useExisting: UserEntityService };
const $UserGroupEntityService: Provider = { provide: 'UserGroupEntityService', useExisting: UserGroupEntityService };
const $UserGroupInvitationEntityService: Provider = { provide: 'UserGroupInvitationEntityService', useExisting: UserGroupInvitationEntityService };
const $UserListEntityService: Provider = { provide: 'UserListEntityService', useExisting: UserListEntityService }; const $UserListEntityService: Provider = { provide: 'UserListEntityService', useExisting: UserListEntityService };
const $FlashEntityService: Provider = { provide: 'FlashEntityService', useExisting: FlashEntityService }; const $FlashEntityService: Provider = { provide: 'FlashEntityService', useExisting: FlashEntityService };
const $FlashLikeEntityService: Provider = { provide: 'FlashLikeEntityService', useExisting: FlashLikeEntityService }; const $FlashLikeEntityService: Provider = { provide: 'FlashLikeEntityService', useExisting: FlashLikeEntityService };
@@ -273,7 +264,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ImageProcessingService, ImageProcessingService,
InstanceActorService, InstanceActorService,
InternalStorageService, InternalStorageService,
MessagingService,
MetaService, MetaService,
MfmService, MfmService,
ModerationLogService, ModerationLogService,
@@ -333,7 +323,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
GalleryPostEntityService, GalleryPostEntityService,
HashtagEntityService, HashtagEntityService,
InstanceEntityService, InstanceEntityService,
MessagingMessageEntityService,
ModerationLogEntityService, ModerationLogEntityService,
MutingEntityService, MutingEntityService,
NoteEntityService, NoteEntityService,
@@ -344,8 +333,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
PageLikeEntityService, PageLikeEntityService,
SigninEntityService, SigninEntityService,
UserEntityService, UserEntityService,
UserGroupEntityService,
UserGroupInvitationEntityService,
UserListEntityService, UserListEntityService,
FlashEntityService, FlashEntityService,
FlashLikeEntityService, FlashLikeEntityService,
@@ -394,7 +381,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$ImageProcessingService, $ImageProcessingService,
$InstanceActorService, $InstanceActorService,
$InternalStorageService, $InternalStorageService,
$MessagingService,
$MetaService, $MetaService,
$MfmService, $MfmService,
$ModerationLogService, $ModerationLogService,
@@ -454,7 +440,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$GalleryPostEntityService, $GalleryPostEntityService,
$HashtagEntityService, $HashtagEntityService,
$InstanceEntityService, $InstanceEntityService,
$MessagingMessageEntityService,
$ModerationLogEntityService, $ModerationLogEntityService,
$MutingEntityService, $MutingEntityService,
$NoteEntityService, $NoteEntityService,
@@ -465,8 +450,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$PageLikeEntityService, $PageLikeEntityService,
$SigninEntityService, $SigninEntityService,
$UserEntityService, $UserEntityService,
$UserGroupEntityService,
$UserGroupInvitationEntityService,
$UserListEntityService, $UserListEntityService,
$FlashEntityService, $FlashEntityService,
$FlashLikeEntityService, $FlashLikeEntityService,
@@ -516,7 +499,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ImageProcessingService, ImageProcessingService,
InstanceActorService, InstanceActorService,
InternalStorageService, InternalStorageService,
MessagingService,
MetaService, MetaService,
MfmService, MfmService,
ModerationLogService, ModerationLogService,
@@ -575,7 +557,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
GalleryPostEntityService, GalleryPostEntityService,
HashtagEntityService, HashtagEntityService,
InstanceEntityService, InstanceEntityService,
MessagingMessageEntityService,
ModerationLogEntityService, ModerationLogEntityService,
MutingEntityService, MutingEntityService,
NoteEntityService, NoteEntityService,
@@ -586,8 +567,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
PageLikeEntityService, PageLikeEntityService,
SigninEntityService, SigninEntityService,
UserEntityService, UserEntityService,
UserGroupEntityService,
UserGroupInvitationEntityService,
UserListEntityService, UserListEntityService,
FlashEntityService, FlashEntityService,
FlashLikeEntityService, FlashLikeEntityService,
@@ -636,7 +615,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$ImageProcessingService, $ImageProcessingService,
$InstanceActorService, $InstanceActorService,
$InternalStorageService, $InternalStorageService,
$MessagingService,
$MetaService, $MetaService,
$MfmService, $MfmService,
$ModerationLogService, $ModerationLogService,
@@ -695,7 +673,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$GalleryPostEntityService, $GalleryPostEntityService,
$HashtagEntityService, $HashtagEntityService,
$InstanceEntityService, $InstanceEntityService,
$MessagingMessageEntityService,
$ModerationLogEntityService, $ModerationLogEntityService,
$MutingEntityService, $MutingEntityService,
$NoteEntityService, $NoteEntityService,
@@ -706,8 +683,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$PageLikeEntityService, $PageLikeEntityService,
$SigninEntityService, $SigninEntityService,
$UserEntityService, $UserEntityService,
$UserGroupEntityService,
$UserGroupInvitationEntityService,
$UserListEntityService, $UserListEntityService,
$FlashEntityService, $FlashEntityService,
$FlashLikeEntityService, $FlashLikeEntityService,

View File

@@ -1,4 +1,5 @@
import { Inject, Injectable } from '@nestjs/common'; import { setTimeout } from 'node:timers/promises';
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
import type { MutingsRepository, NotificationsRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; import type { MutingsRepository, NotificationsRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js';
import type { User } from '@/models/entities/User.js'; import type { User } from '@/models/entities/User.js';
import type { Notification } from '@/models/entities/Notification.js'; import type { Notification } from '@/models/entities/Notification.js';
@@ -10,7 +11,9 @@ import { PushNotificationService } from '@/core/PushNotificationService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
@Injectable() @Injectable()
export class CreateNotificationService { export class CreateNotificationService implements OnApplicationShutdown {
#shutdownController = new AbortController();
constructor( constructor(
@Inject(DI.usersRepository) @Inject(DI.usersRepository)
private usersRepository: UsersRepository, private usersRepository: UsersRepository,
@@ -40,11 +43,11 @@ export class CreateNotificationService {
if (data.notifierId && (notifieeId === data.notifierId)) { if (data.notifierId && (notifieeId === data.notifierId)) {
return null; return null;
} }
const profile = await this.userProfilesRepository.findOneBy({ userId: notifieeId }); const profile = await this.userProfilesRepository.findOneBy({ userId: notifieeId });
const isMuted = profile?.mutingNotificationTypes.includes(type); const isMuted = profile?.mutingNotificationTypes.includes(type);
// Create notification // Create notification
const notification = await this.notificationsRepository.insert({ const notification = await this.notificationsRepository.insert({
id: this.idService.genId(), id: this.idService.genId(),
@@ -56,18 +59,18 @@ export class CreateNotificationService {
...data, ...data,
} as Partial<Notification>) } as Partial<Notification>)
.then(x => this.notificationsRepository.findOneByOrFail(x.identifiers[0])); .then(x => this.notificationsRepository.findOneByOrFail(x.identifiers[0]));
const packed = await this.notificationEntityService.pack(notification, {}); const packed = await this.notificationEntityService.pack(notification, {});
// Publish notification event // Publish notification event
this.globalEventService.publishMainStream(notifieeId, 'notification', packed); this.globalEventService.publishMainStream(notifieeId, 'notification', packed);
// 2秒経っても(今回作成した)通知が既読にならなかったら「未読の通知がありますよ」イベントを発行する // 2秒経っても(今回作成した)通知が既読にならなかったら「未読の通知がありますよ」イベントを発行する
setTimeout(async () => { setTimeout(2000, 'unread note', { signal: this.#shutdownController.signal }).then(async () => {
const fresh = await this.notificationsRepository.findOneBy({ id: notification.id }); const fresh = await this.notificationsRepository.findOneBy({ id: notification.id });
if (fresh == null) return; // 既に削除されているかもしれない if (fresh == null) return; // 既に削除されているかもしれない
if (fresh.isRead) return; if (fresh.isRead) return;
//#region ただしミュートしているユーザーからの通知なら無視 //#region ただしミュートしているユーザーからの通知なら無視
const mutings = await this.mutingsRepository.findBy({ const mutings = await this.mutingsRepository.findBy({
muterId: notifieeId, muterId: notifieeId,
@@ -76,14 +79,14 @@ export class CreateNotificationService {
return; return;
} }
//#endregion //#endregion
this.globalEventService.publishMainStream(notifieeId, 'unreadNotification', packed); this.globalEventService.publishMainStream(notifieeId, 'unreadNotification', packed);
this.pushNotificationService.pushNotification(notifieeId, 'notification', packed); this.pushNotificationService.pushNotification(notifieeId, 'notification', packed);
if (type === 'follow') this.emailNotificationFollow(notifieeId, await this.usersRepository.findOneByOrFail({ id: data.notifierId! })); if (type === 'follow') this.emailNotificationFollow(notifieeId, await this.usersRepository.findOneByOrFail({ id: data.notifierId! }));
if (type === 'receiveFollowRequest') this.emailNotificationReceiveFollowRequest(notifieeId, await this.usersRepository.findOneByOrFail({ id: data.notifierId! })); if (type === 'receiveFollowRequest') this.emailNotificationReceiveFollowRequest(notifieeId, await this.usersRepository.findOneByOrFail({ id: data.notifierId! }));
}, 2000); }, () => { /* aborted, ignore it */ });
return notification; return notification;
} }
@@ -103,7 +106,7 @@ export class CreateNotificationService {
sendEmail(userProfile.email, i18n.t('_email._follow.title'), `${follower.name} (@${Acct.toString(follower)})`, `${follower.name} (@${Acct.toString(follower)})`); sendEmail(userProfile.email, i18n.t('_email._follow.title'), `${follower.name} (@${Acct.toString(follower)})`, `${follower.name} (@${Acct.toString(follower)})`);
*/ */
} }
@bindThis @bindThis
private async emailNotificationReceiveFollowRequest(userId: User['id'], follower: User) { private async emailNotificationReceiveFollowRequest(userId: User['id'], follower: User) {
/* /*
@@ -115,4 +118,8 @@ export class CreateNotificationService {
sendEmail(userProfile.email, i18n.t('_email._receiveFollowRequest.title'), `${follower.name} (@${Acct.toString(follower)})`, `${follower.name} (@${Acct.toString(follower)})`); sendEmail(userProfile.email, i18n.t('_email._receiveFollowRequest.title'), `${follower.name} (@${Acct.toString(follower)})`, `${follower.name} (@${Acct.toString(follower)})`);
*/ */
} }
onApplicationShutdown(signal?: string | undefined): void {
this.#shutdownController.abort();
}
} }

View File

@@ -61,7 +61,7 @@ export class CustomEmojiService {
await this.db.queryResultCache!.remove(['meta_emojis']); await this.db.queryResultCache!.remove(['meta_emojis']);
this.globalEventService.publishBroadcastStream('emojiAdded', { this.globalEventService.publishBroadcastStream('emojiAdded', {
emoji: await this.emojiEntityService.pack(emoji.id), emoji: await this.emojiEntityService.packDetailed(emoji.id),
}); });
} }

View File

@@ -7,7 +7,7 @@ import { DI } from '@/di-symbols.js';
import type { DriveFilesRepository, UsersRepository, DriveFoldersRepository, UserProfilesRepository } from '@/models/index.js'; import type { DriveFilesRepository, UsersRepository, DriveFoldersRepository, UserProfilesRepository } from '@/models/index.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import Logger from '@/logger.js'; import Logger from '@/logger.js';
import type { IRemoteUser, User } from '@/models/entities/User.js'; import type { RemoteUser, User } from '@/models/entities/User.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { DriveFile } from '@/models/entities/DriveFile.js'; import { DriveFile } from '@/models/entities/DriveFile.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
@@ -255,7 +255,7 @@ export class DriveService {
return { return {
webpublic: null, webpublic: null,
thumbnail: null, thumbnail: null,
} };
} }
try { try {
@@ -399,7 +399,7 @@ export class DriveService {
} }
@bindThis @bindThis
private async deleteOldFile(user: IRemoteUser) { private async deleteOldFile(user: RemoteUser) {
const q = this.driveFilesRepository.createQueryBuilder('file') const q = this.driveFilesRepository.createQueryBuilder('file')
.where('file.userId = :userId', { userId: user.id }) .where('file.userId = :userId', { userId: user.id })
.andWhere('file.isLink = FALSE'); .andWhere('file.isLink = FALSE');
@@ -500,7 +500,7 @@ export class DriveService {
throw new IdentifiableError('c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6', 'No free space.'); throw new IdentifiableError('c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6', 'No free space.');
} else { } else {
// (アバターまたはバナーを含まず)最も古いファイルを削除する // (アバターまたはバナーを含まず)最も古いファイルを削除する
this.deleteOldFile(await this.usersRepository.findOneByOrFail({ id: user.id }) as IRemoteUser); this.deleteOldFile(await this.usersRepository.findOneByOrFail({ id: user.id }) as RemoteUser);
} }
} }
} }

View File

@@ -2,7 +2,6 @@ import { URL } from 'node:url';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { JSDOM } from 'jsdom'; import { JSDOM } from 'jsdom';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import fetch from 'node-fetch';
import type { Instance } from '@/models/entities/Instance.js'; import type { Instance } from '@/models/entities/Instance.js';
import type { InstancesRepository } from '@/models/index.js'; import type { InstancesRepository } from '@/models/index.js';
import { AppLockService } from '@/core/AppLockService.js'; import { AppLockService } from '@/core/AppLockService.js';

View File

@@ -3,7 +3,7 @@ import * as crypto from 'node:crypto';
import { join } from 'node:path'; import { join } from 'node:path';
import * as stream from 'node:stream'; import * as stream from 'node:stream';
import * as util from 'node:util'; import * as util from 'node:util';
import { Inject, Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { FSWatcher } from 'chokidar'; import { FSWatcher } from 'chokidar';
import { fileTypeFromFile } from 'file-type'; import { fileTypeFromFile } from 'file-type';
import FFmpeg from 'fluent-ffmpeg'; import FFmpeg from 'fluent-ffmpeg';

View File

@@ -3,21 +3,15 @@ import Redis from 'ioredis';
import type { User } from '@/models/entities/User.js'; import type { User } from '@/models/entities/User.js';
import type { Note } from '@/models/entities/Note.js'; import type { Note } from '@/models/entities/Note.js';
import type { UserList } from '@/models/entities/UserList.js'; import type { UserList } from '@/models/entities/UserList.js';
import type { UserGroup } from '@/models/entities/UserGroup.js';
import type { Antenna } from '@/models/entities/Antenna.js'; import type { Antenna } from '@/models/entities/Antenna.js';
import type { Channel } from '@/models/entities/Channel.js';
import type { import type {
StreamChannels, StreamChannels,
AdminStreamTypes, AdminStreamTypes,
AntennaStreamTypes, AntennaStreamTypes,
BroadcastTypes, BroadcastTypes,
ChannelStreamTypes,
DriveStreamTypes, DriveStreamTypes,
GroupMessagingStreamTypes,
InternalStreamTypes, InternalStreamTypes,
MainStreamTypes, MainStreamTypes,
MessagingIndexStreamTypes,
MessagingStreamTypes,
NoteStreamTypes, NoteStreamTypes,
UserListStreamTypes, UserListStreamTypes,
UserStreamTypes, UserStreamTypes,
@@ -83,11 +77,6 @@ export class GlobalEventService {
}); });
} }
@bindThis
public publishChannelStream<K extends keyof ChannelStreamTypes>(channelId: Channel['id'], type: K, value?: ChannelStreamTypes[K]): void {
this.publish(`channelStream:${channelId}`, type, typeof value === 'undefined' ? null : value);
}
@bindThis @bindThis
public publishUserListStream<K extends keyof UserListStreamTypes>(listId: UserList['id'], type: K, value?: UserListStreamTypes[K]): void { public publishUserListStream<K extends keyof UserListStreamTypes>(listId: UserList['id'], type: K, value?: UserListStreamTypes[K]): void {
this.publish(`userListStream:${listId}`, type, typeof value === 'undefined' ? null : value); this.publish(`userListStream:${listId}`, type, typeof value === 'undefined' ? null : value);
@@ -98,21 +87,6 @@ export class GlobalEventService {
this.publish(`antennaStream:${antennaId}`, type, typeof value === 'undefined' ? null : value); this.publish(`antennaStream:${antennaId}`, type, typeof value === 'undefined' ? null : value);
} }
@bindThis
public publishMessagingStream<K extends keyof MessagingStreamTypes>(userId: User['id'], otherpartyId: User['id'], type: K, value?: MessagingStreamTypes[K]): void {
this.publish(`messagingStream:${userId}-${otherpartyId}`, type, typeof value === 'undefined' ? null : value);
}
@bindThis
public publishGroupMessagingStream<K extends keyof GroupMessagingStreamTypes>(groupId: UserGroup['id'], type: K, value?: GroupMessagingStreamTypes[K]): void {
this.publish(`messagingStream:${groupId}`, type, typeof value === 'undefined' ? null : value);
}
@bindThis
public publishMessagingIndexStream<K extends keyof MessagingIndexStreamTypes>(userId: User['id'], type: K, value?: MessagingIndexStreamTypes[K]): void {
this.publish(`messagingIndexStream:${userId}`, type, typeof value === 'undefined' ? null : value);
}
@bindThis @bindThis
public publishNotesStream(note: Packed<'Note'>): void { public publishNotesStream(note: Packed<'Note'>): void {
this.publish('notesStream', null, note); this.publish('notesStream', null, note);

View File

@@ -99,7 +99,6 @@ export class HttpRequestService {
const res = await this.send(url, { const res = await this.send(url, {
method: 'GET', method: 'GET',
headers: Object.assign({ headers: Object.assign({
'User-Agent': this.config.userAgent,
Accept: accept, Accept: accept,
}, headers ?? {}), }, headers ?? {}),
timeout: 5000, timeout: 5000,
@@ -114,7 +113,6 @@ export class HttpRequestService {
const res = await this.send(url, { const res = await this.send(url, {
method: 'GET', method: 'GET',
headers: Object.assign({ headers: Object.assign({
'User-Agent': this.config.userAgent,
Accept: accept, Accept: accept,
}, headers ?? {}), }, headers ?? {}),
timeout: 5000, timeout: 5000,
@@ -144,7 +142,10 @@ export class HttpRequestService {
const res = await fetch(url, { const res = await fetch(url, {
method: args.method ?? 'GET', method: args.method ?? 'GET',
headers: args.headers, headers: {
'User-Agent': this.config.userAgent,
...(args.headers ?? {})
},
body: args.body, body: args.body,
size: args.size ?? 10 * 1024 * 1024, size: args.size ?? 10 * 1024 * 1024,
agent: (url) => this.getAgentByUrl(url), agent: (url) => this.getAgentByUrl(url),

View File

@@ -107,7 +107,7 @@ export class ImageProcessingService {
withoutEnlargement: true, withoutEnlargement: true,
}) })
.rotate() .rotate()
.webp(options) .webp(options);
return { return {
data, data,

View File

@@ -1,6 +1,6 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { IsNull } from 'typeorm'; import { IsNull } from 'typeorm';
import type { ILocalUser } from '@/models/entities/User.js'; import type { LocalUser } from '@/models/entities/User.js';
import type { UsersRepository } from '@/models/index.js'; import type { UsersRepository } from '@/models/index.js';
import { Cache } from '@/misc/cache.js'; import { Cache } from '@/misc/cache.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
@@ -11,7 +11,7 @@ const ACTOR_USERNAME = 'instance.actor' as const;
@Injectable() @Injectable()
export class InstanceActorService { export class InstanceActorService {
private cache: Cache<ILocalUser>; private cache: Cache<LocalUser>;
constructor( constructor(
@Inject(DI.usersRepository) @Inject(DI.usersRepository)
@@ -19,24 +19,24 @@ export class InstanceActorService {
private createSystemUserService: CreateSystemUserService, private createSystemUserService: CreateSystemUserService,
) { ) {
this.cache = new Cache<ILocalUser>(Infinity); this.cache = new Cache<LocalUser>(Infinity);
} }
@bindThis @bindThis
public async getInstanceActor(): Promise<ILocalUser> { public async getInstanceActor(): Promise<LocalUser> {
const cached = this.cache.get(null); const cached = this.cache.get(null);
if (cached) return cached; if (cached) return cached;
const user = await this.usersRepository.findOneBy({ const user = await this.usersRepository.findOneBy({
host: IsNull(), host: IsNull(),
username: ACTOR_USERNAME, username: ACTOR_USERNAME,
}) as ILocalUser | undefined; }) as LocalUser | undefined;
if (user) { if (user) {
this.cache.set(null, user); this.cache.set(null, user);
return user; return user;
} else { } else {
const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME) as ILocalUser; const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME) as LocalUser;
this.cache.set(null, created); this.cache.set(null, created);
return created; return created;
} }

View File

@@ -1,307 +0,0 @@
import { Inject, Injectable } from '@nestjs/common';
import { In, Not } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import type { DriveFile } from '@/models/entities/DriveFile.js';
import type { MessagingMessage } from '@/models/entities/MessagingMessage.js';
import type { Note } from '@/models/entities/Note.js';
import type { User, CacheableUser, IRemoteUser } from '@/models/entities/User.js';
import type { UserGroup } from '@/models/entities/UserGroup.js';
import { QueueService } from '@/core/QueueService.js';
import { toArray } from '@/misc/prelude/array.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';
import type { MessagingMessagesRepository, MutingsRepository, UserGroupJoiningsRepository, UsersRepository } from '@/models/index.js';
import { IdService } from '@/core/IdService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { MessagingMessageEntityService } from '@/core/entities/MessagingMessageEntityService.js';
import { PushNotificationService } from '@/core/PushNotificationService.js';
import { bindThis } from '@/decorators.js';
@Injectable()
export class MessagingService {
constructor(
@Inject(DI.config)
private config: Config,
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
@Inject(DI.messagingMessagesRepository)
private messagingMessagesRepository: MessagingMessagesRepository,
@Inject(DI.userGroupJoiningsRepository)
private userGroupJoiningsRepository: UserGroupJoiningsRepository,
@Inject(DI.mutingsRepository)
private mutingsRepository: MutingsRepository,
private userEntityService: UserEntityService,
private messagingMessageEntityService: MessagingMessageEntityService,
private idService: IdService,
private globalEventService: GlobalEventService,
private apRendererService: ApRendererService,
private queueService: QueueService,
private pushNotificationService: PushNotificationService,
) {
}
@bindThis
public async createMessage(user: { id: User['id']; host: User['host']; }, recipientUser: CacheableUser | undefined, recipientGroup: UserGroup | undefined, text: string | null | undefined, file: DriveFile | null, uri?: string) {
const message = {
id: this.idService.genId(),
createdAt: new Date(),
fileId: file ? file.id : null,
recipientId: recipientUser ? recipientUser.id : null,
groupId: recipientGroup ? recipientGroup.id : null,
text: text ? text.trim() : null,
userId: user.id,
isRead: false,
reads: [] as any[],
uri,
} as MessagingMessage;
await this.messagingMessagesRepository.insert(message);
const messageObj = await this.messagingMessageEntityService.pack(message);
if (recipientUser) {
if (this.userEntityService.isLocalUser(user)) {
// 自分のストリーム
this.globalEventService.publishMessagingStream(message.userId, recipientUser.id, 'message', messageObj);
this.globalEventService.publishMessagingIndexStream(message.userId, 'message', messageObj);
this.globalEventService.publishMainStream(message.userId, 'messagingMessage', messageObj);
}
if (this.userEntityService.isLocalUser(recipientUser)) {
// 相手のストリーム
this.globalEventService.publishMessagingStream(recipientUser.id, message.userId, 'message', messageObj);
this.globalEventService.publishMessagingIndexStream(recipientUser.id, 'message', messageObj);
this.globalEventService.publishMainStream(recipientUser.id, 'messagingMessage', messageObj);
}
} else if (recipientGroup) {
// グループのストリーム
this.globalEventService.publishGroupMessagingStream(recipientGroup.id, 'message', messageObj);
// メンバーのストリーム
const joinings = await this.userGroupJoiningsRepository.findBy({ userGroupId: recipientGroup.id });
for (const joining of joinings) {
this.globalEventService.publishMessagingIndexStream(joining.userId, 'message', messageObj);
this.globalEventService.publishMainStream(joining.userId, 'messagingMessage', messageObj);
}
}
// 2秒経っても(今回作成した)メッセージが既読にならなかったら「未読のメッセージがありますよ」イベントを発行する
setTimeout(async () => {
const freshMessage = await this.messagingMessagesRepository.findOneBy({ id: message.id });
if (freshMessage == null) return; // メッセージが削除されている場合もある
if (recipientUser && this.userEntityService.isLocalUser(recipientUser)) {
if (freshMessage.isRead) return; // 既読
//#region ただしミュートされているなら発行しない
const mute = await this.mutingsRepository.findBy({
muterId: recipientUser.id,
});
if (mute.map(m => m.muteeId).includes(user.id)) return;
//#endregion
this.globalEventService.publishMainStream(recipientUser.id, 'unreadMessagingMessage', messageObj);
this.pushNotificationService.pushNotification(recipientUser.id, 'unreadMessagingMessage', messageObj);
} else if (recipientGroup) {
const joinings = await this.userGroupJoiningsRepository.findBy({ userGroupId: recipientGroup.id, userId: Not(user.id) });
for (const joining of joinings) {
if (freshMessage.reads.includes(joining.userId)) return; // 既読
this.globalEventService.publishMainStream(joining.userId, 'unreadMessagingMessage', messageObj);
this.pushNotificationService.pushNotification(joining.userId, 'unreadMessagingMessage', messageObj);
}
}
}, 2000);
if (recipientUser && this.userEntityService.isLocalUser(user) && this.userEntityService.isRemoteUser(recipientUser)) {
const note = {
id: message.id,
createdAt: message.createdAt,
fileIds: message.fileId ? [message.fileId] : [],
text: message.text,
userId: message.userId,
visibility: 'specified',
mentions: [recipientUser].map(u => u.id),
mentionedRemoteUsers: JSON.stringify([recipientUser].map(u => ({
uri: u.uri,
username: u.username,
host: u.host,
}))),
} as Note;
const activity = this.apRendererService.renderActivity(this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false, true), note));
this.queueService.deliver(user, activity, recipientUser.inbox);
}
return messageObj;
}
@bindThis
public async deleteMessage(message: MessagingMessage) {
await this.messagingMessagesRepository.delete(message.id);
this.postDeleteMessage(message);
}
@bindThis
private async postDeleteMessage(message: MessagingMessage) {
if (message.recipientId) {
const user = await this.usersRepository.findOneByOrFail({ id: message.userId });
const recipient = await this.usersRepository.findOneByOrFail({ id: message.recipientId });
if (this.userEntityService.isLocalUser(user)) this.globalEventService.publishMessagingStream(message.userId, message.recipientId, 'deleted', message.id);
if (this.userEntityService.isLocalUser(recipient)) this.globalEventService.publishMessagingStream(message.recipientId, message.userId, 'deleted', message.id);
if (this.userEntityService.isLocalUser(user) && this.userEntityService.isRemoteUser(recipient)) {
const activity = this.apRendererService.renderActivity(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${message.id}`), user));
this.queueService.deliver(user, activity, recipient.inbox);
}
} else if (message.groupId) {
this.globalEventService.publishGroupMessagingStream(message.groupId, 'deleted', message.id);
}
}
/**
* Mark messages as read
*/
@bindThis
public async readUserMessagingMessage(
userId: User['id'],
otherpartyId: User['id'],
messageIds: MessagingMessage['id'][],
) {
if (messageIds.length === 0) return;
const messages = await this.messagingMessagesRepository.findBy({
id: In(messageIds),
});
for (const message of messages) {
if (message.recipientId !== userId) {
throw new IdentifiableError('e140a4bf-49ce-4fb6-b67c-b78dadf6b52f', 'Access denied (user).');
}
}
// Update documents
await this.messagingMessagesRepository.update({
id: In(messageIds),
userId: otherpartyId,
recipientId: userId,
isRead: false,
}, {
isRead: true,
});
// Publish event
this.globalEventService.publishMessagingStream(otherpartyId, userId, 'read', messageIds);
this.globalEventService.publishMessagingIndexStream(userId, 'read', messageIds);
if (!await this.userEntityService.getHasUnreadMessagingMessage(userId)) {
// 全ての(いままで未読だった)自分宛てのメッセージを(これで)読みましたよというイベントを発行
this.globalEventService.publishMainStream(userId, 'readAllMessagingMessages');
this.pushNotificationService.pushNotification(userId, 'readAllMessagingMessages', undefined);
} else {
// そのユーザーとのメッセージで未読がなければイベント発行
const count = await this.messagingMessagesRepository.count({
where: {
userId: otherpartyId,
recipientId: userId,
isRead: false,
},
take: 1,
});
if (!count) {
this.pushNotificationService.pushNotification(userId, 'readAllMessagingMessagesOfARoom', { userId: otherpartyId });
}
}
}
/**
* Mark messages as read
*/
@bindThis
public async readGroupMessagingMessage(
userId: User['id'],
groupId: UserGroup['id'],
messageIds: MessagingMessage['id'][],
) {
if (messageIds.length === 0) return;
// check joined
const joining = await this.userGroupJoiningsRepository.findOneBy({
userId: userId,
userGroupId: groupId,
});
if (joining == null) {
throw new IdentifiableError('930a270c-714a-46b2-b776-ad27276dc569', 'Access denied (group).');
}
const messages = await this.messagingMessagesRepository.findBy({
id: In(messageIds),
});
const reads: MessagingMessage['id'][] = [];
for (const message of messages) {
if (message.userId === userId) continue;
if (message.reads.includes(userId)) continue;
// Update document
await this.messagingMessagesRepository.createQueryBuilder().update()
.set({
reads: (() => `array_append("reads", '${joining.userId}')`) as any,
})
.where('id = :id', { id: message.id })
.execute();
reads.push(message.id);
}
// Publish event
this.globalEventService.publishGroupMessagingStream(groupId, 'read', {
ids: reads,
userId: userId,
});
this.globalEventService.publishMessagingIndexStream(userId, 'read', reads);
if (!await this.userEntityService.getHasUnreadMessagingMessage(userId)) {
// 全ての(いままで未読だった)自分宛てのメッセージを(これで)読みましたよというイベントを発行
this.globalEventService.publishMainStream(userId, 'readAllMessagingMessages');
this.pushNotificationService.pushNotification(userId, 'readAllMessagingMessages', undefined);
} else {
// そのグループにおいて未読がなければイベント発行
const unreadExist = await this.messagingMessagesRepository.createQueryBuilder('message')
.where('message.groupId = :groupId', { groupId: groupId })
.andWhere('message.userId != :userId', { userId: userId })
.andWhere('NOT (:userId = ANY(message.reads))', { userId: userId })
.andWhere('message.createdAt > :joinedAt', { joinedAt: joining.createdAt }) // 自分が加入する前の会話については、未読扱いしない
.getOne().then(x => x != null);
if (!unreadExist) {
this.pushNotificationService.pushNotification(userId, 'readAllMessagingMessagesOfARoom', { groupId });
}
}
}
@bindThis
public async deliverReadActivity(user: { id: User['id']; host: null; }, recipient: IRemoteUser, messages: MessagingMessage | MessagingMessage[]) {
messages = toArray(messages).filter(x => x.uri);
const contents = messages.map(x => this.apRendererService.renderRead(user, x));
if (contents.length > 1) {
const collection = this.apRendererService.renderOrderedCollection(null, contents.length, undefined, undefined, contents);
this.queueService.deliver(user, this.apRendererService.renderActivity(collection), recipient.inbox);
} else {
for (const content of contents) {
this.queueService.deliver(user, this.apRendererService.renderActivity(content), recipient.inbox);
}
}
}
}

View File

@@ -1,9 +1,8 @@
import { URL } from 'node:url'; import { URL } from 'node:url';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import * as parse5 from 'parse5'; import * as parse5 from 'parse5';
import { JSDOM } from 'jsdom'; import { Window } from 'happy-dom';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { UsersRepository } from '@/models/index.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import { intersperse } from '@/misc/prelude/array.js'; import { intersperse } from '@/misc/prelude/array.js';
import type { IMentionedRemoteUsers } from '@/models/entities/Note.js'; import type { IMentionedRemoteUsers } from '@/models/entities/Note.js';
@@ -236,7 +235,7 @@ export class MfmService {
return null; return null;
} }
const { window } = new JSDOM(''); const { window } = new Window();
const doc = window.document; const doc = window.document;
@@ -301,7 +300,7 @@ export class MfmService {
hashtag: (node) => { hashtag: (node) => {
const a = doc.createElement('a'); const a = doc.createElement('a');
a.href = `${this.config.url}/tags/${node.props.hashtag}`; a.setAttribute('href', `${this.config.url}/tags/${node.props.hashtag}`);
a.textContent = `#${node.props.hashtag}`; a.textContent = `#${node.props.hashtag}`;
a.setAttribute('rel', 'tag'); a.setAttribute('rel', 'tag');
return a; return a;
@@ -327,7 +326,7 @@ export class MfmService {
link: (node) => { link: (node) => {
const a = doc.createElement('a'); const a = doc.createElement('a');
a.href = node.props.url; a.setAttribute('href', node.props.url);
appendChildren(node.children, a); appendChildren(node.children, a);
return a; return a;
}, },
@@ -336,7 +335,7 @@ export class MfmService {
const a = doc.createElement('a'); const a = doc.createElement('a');
const { username, host, acct } = node.props; const { username, host, acct } = node.props;
const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username === username && remoteUser.host === host); const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username === username && remoteUser.host === host);
a.href = remoteUserInfo ? (remoteUserInfo.url ? remoteUserInfo.url : remoteUserInfo.uri) : `${this.config.url}/${acct}`; a.setAttribute('href', remoteUserInfo ? (remoteUserInfo.url ? remoteUserInfo.url : remoteUserInfo.uri) : `${this.config.url}/${acct}`);
a.className = 'u-url mention'; a.className = 'u-url mention';
a.textContent = acct; a.textContent = acct;
return a; return a;
@@ -361,14 +360,14 @@ export class MfmService {
url: (node) => { url: (node) => {
const a = doc.createElement('a'); const a = doc.createElement('a');
a.href = node.props.url; a.setAttribute('href', node.props.url);
a.textContent = node.props.url; a.textContent = node.props.url;
return a; return a;
}, },
search: (node) => { search: (node) => {
const a = doc.createElement('a'); const a = doc.createElement('a');
a.href = `https://www.google.com/search?q=${node.props.query}`; a.setAttribute('href', `https://www.google.com/search?q=${node.props.query}`);
a.textContent = node.props.content; a.textContent = node.props.content;
return a; return a;
}, },

View File

@@ -1,6 +1,7 @@
import { setImmediate } from 'node:timers/promises';
import * as mfm from 'mfm-js'; import * as mfm from 'mfm-js';
import { Not, In, DataSource } from 'typeorm'; import { In, DataSource } from 'typeorm';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
import { extractMentions } from '@/misc/extract-mentions.js'; import { extractMentions } from '@/misc/extract-mentions.js';
import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm.js'; import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm.js';
import { extractHashtags } from '@/misc/extract-hashtags.js'; import { extractHashtags } from '@/misc/extract-hashtags.js';
@@ -11,7 +12,7 @@ import type { DriveFile } from '@/models/entities/DriveFile.js';
import type { App } from '@/models/entities/App.js'; import type { App } from '@/models/entities/App.js';
import { concat } from '@/misc/prelude/array.js'; import { concat } from '@/misc/prelude/array.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import type { User, ILocalUser, IRemoteUser } from '@/models/entities/User.js'; import type { User, LocalUser, RemoteUser } from '@/models/entities/User.js';
import type { IPoll } from '@/models/entities/Poll.js'; import type { IPoll } from '@/models/entities/Poll.js';
import { Poll } from '@/models/entities/Poll.js'; import { Poll } from '@/models/entities/Poll.js';
import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js';
@@ -52,7 +53,7 @@ class NotificationManager {
private notifier: { id: User['id']; }; private notifier: { id: User['id']; };
private note: Note; private note: Note;
private queue: { private queue: {
target: ILocalUser['id']; target: LocalUser['id'];
reason: NotificationType; reason: NotificationType;
}[]; }[];
@@ -68,7 +69,7 @@ class NotificationManager {
} }
@bindThis @bindThis
public push(notifiee: ILocalUser['id'], reason: NotificationType) { public push(notifiee: LocalUser['id'], reason: NotificationType) {
// 自分自身へは通知しない // 自分自身へは通知しない
if (this.notifier.id === notifiee) return; if (this.notifier.id === notifiee) return;
@@ -137,7 +138,9 @@ type Option = {
}; };
@Injectable() @Injectable()
export class NoteCreateService { export class NoteCreateService implements OnApplicationShutdown {
#shutdownController = new AbortController();
constructor( constructor(
@Inject(DI.config) @Inject(DI.config)
private config: Config, private config: Config,
@@ -313,7 +316,10 @@ export class NoteCreateService {
const note = await this.insertNote(user, data, tags, emojis, mentionedUsers); const note = await this.insertNote(user, data, tags, emojis, mentionedUsers);
setImmediate(() => this.postNoteCreated(note, user, data, silent, tags!, mentionedUsers!)); setImmediate('post created', { signal: this.#shutdownController.signal }).then(
() => this.postNoteCreated(note, user, data, silent, tags!, mentionedUsers!),
() => { /* aborted, ignore this */ },
);
return note; return note;
} }
@@ -605,7 +611,7 @@ export class NoteCreateService {
// メンションされたリモートユーザーに配送 // メンションされたリモートユーザーに配送
for (const u of mentionedUsers.filter(u => this.userEntityService.isRemoteUser(u))) { for (const u of mentionedUsers.filter(u => this.userEntityService.isRemoteUser(u))) {
dm.addDirectRecipe(u as IRemoteUser); dm.addDirectRecipe(u as RemoteUser);
} }
// 投稿がリプライかつ投稿者がローカルユーザーかつリプライ先の投稿の投稿者がリモートユーザーなら配送 // 投稿がリプライかつ投稿者がローカルユーザーかつリプライ先の投稿の投稿者がリモートユーザーなら配送
@@ -711,7 +717,7 @@ export class NoteCreateService {
? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note) ? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note)
: this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false), note); : this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false), note);
return this.apRendererService.renderActivity(content); return this.apRendererService.addContext(content);
} }
@bindThis @bindThis
@@ -756,4 +762,8 @@ export class NoteCreateService {
return mentionedUsers; return mentionedUsers;
} }
onApplicationShutdown(signal?: string | undefined) {
this.#shutdownController.abort();
}
} }

View File

@@ -1,6 +1,6 @@
import { Brackets, In } from 'typeorm'; import { Brackets, In } from 'typeorm';
import { Injectable, Inject } from '@nestjs/common'; import { Injectable, Inject } from '@nestjs/common';
import type { User, ILocalUser, IRemoteUser } from '@/models/entities/User.js'; import type { User, LocalUser, RemoteUser } from '@/models/entities/User.js';
import type { Note, IMentionedRemoteUsers } from '@/models/entities/Note.js'; import type { Note, IMentionedRemoteUsers } from '@/models/entities/Note.js';
import type { InstancesRepository, NotesRepository, UsersRepository } from '@/models/index.js'; import type { InstancesRepository, NotesRepository, UsersRepository } from '@/models/index.js';
import { RelayService } from '@/core/RelayService.js'; import { RelayService } from '@/core/RelayService.js';
@@ -78,7 +78,7 @@ export class NoteDeleteService {
}); });
} }
const content = this.apRendererService.renderActivity(renote 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)
: this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${note.id}`), user)); : this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${note.id}`), user));
@@ -90,7 +90,7 @@ export class NoteDeleteService {
for (const cascadingNote of cascadingNotes) { for (const cascadingNote of cascadingNotes) {
if (!cascadingNote.user) continue; if (!cascadingNote.user) continue;
if (!this.userEntityService.isLocalUser(cascadingNote.user)) continue; if (!this.userEntityService.isLocalUser(cascadingNote.user)) continue;
const content = this.apRendererService.renderActivity(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${cascadingNote.id}`), cascadingNote.user)); const content = this.apRendererService.addContext(this.apRendererService.renderDelete(this.apRendererService.renderTombstone(`${this.config.url}/notes/${cascadingNote.id}`), cascadingNote.user));
this.deliverToConcerned(cascadingNote.user, cascadingNote, content); this.deliverToConcerned(cascadingNote.user, cascadingNote, content);
} }
//#endregion //#endregion
@@ -159,11 +159,11 @@ export class NoteDeleteService {
return await this.usersRepository.find({ return await this.usersRepository.find({
where, where,
}) as IRemoteUser[]; }) as RemoteUser[];
} }
@bindThis @bindThis
private async deliverToConcerned(user: { id: ILocalUser['id']; host: null; }, note: Note, content: any) { private async deliverToConcerned(user: { id: LocalUser['id']; host: null; }, note: Note, content: any) {
this.apDeliverManagerService.deliverToFollowers(user, content); this.apDeliverManagerService.deliverToFollowers(user, content);
this.relayService.deliverToRelays(user, content); this.relayService.deliverToRelays(user, content);
const remoteUsers = await this.getMentionedRemoteUsers(note); const remoteUsers = await this.getMentionedRemoteUsers(note);

View File

@@ -115,7 +115,7 @@ export class NotePiningService {
const target = `${this.config.url}/users/${user.id}/collections/featured`; const target = `${this.config.url}/users/${user.id}/collections/featured`;
const item = `${this.config.url}/notes/${noteId}`; const item = `${this.config.url}/notes/${noteId}`;
const content = this.apRendererService.renderActivity(isAddition ? this.apRendererService.renderAdd(user, target, item) : this.apRendererService.renderRemove(user, target, item)); const content = this.apRendererService.addContext(isAddition ? this.apRendererService.renderAdd(user, target, item) : this.apRendererService.renderRemove(user, target, item));
this.apDeliverManagerService.deliverToFollowers(user, content); this.apDeliverManagerService.deliverToFollowers(user, content);
this.relayService.deliverToRelays(user, content); this.relayService.deliverToRelays(user, content);

View File

@@ -1,4 +1,5 @@
import { Inject, Injectable } from '@nestjs/common'; import { setTimeout } from 'node:timers/promises';
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
import { In, IsNull, Not } from 'typeorm'; import { In, IsNull, Not } from 'typeorm';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { User } from '@/models/entities/User.js'; import type { User } from '@/models/entities/User.js';
@@ -15,7 +16,9 @@ import { AntennaService } from './AntennaService.js';
import { PushNotificationService } from './PushNotificationService.js'; import { PushNotificationService } from './PushNotificationService.js';
@Injectable() @Injectable()
export class NoteReadService { export class NoteReadService implements OnApplicationShutdown {
#shutdownController = new AbortController();
constructor( constructor(
@Inject(DI.usersRepository) @Inject(DI.usersRepository)
private usersRepository: UsersRepository, private usersRepository: UsersRepository,
@@ -60,14 +63,14 @@ export class NoteReadService {
}); });
if (mute.map(m => m.muteeId).includes(note.userId)) return; if (mute.map(m => m.muteeId).includes(note.userId)) return;
//#endregion //#endregion
// スレッドミュート // スレッドミュート
const threadMute = await this.noteThreadMutingsRepository.findOneBy({ const threadMute = await this.noteThreadMutingsRepository.findOneBy({
userId: userId, userId: userId,
threadId: note.threadId ?? note.id, threadId: note.threadId ?? note.id,
}); });
if (threadMute) return; if (threadMute) return;
const unread = { const unread = {
id: this.idService.genId(), id: this.idService.genId(),
noteId: note.id, noteId: note.id,
@@ -77,15 +80,15 @@ export class NoteReadService {
noteChannelId: note.channelId, noteChannelId: note.channelId,
noteUserId: note.userId, noteUserId: note.userId,
}; };
await this.noteUnreadsRepository.insert(unread); await this.noteUnreadsRepository.insert(unread);
// 2秒経っても既読にならなかったら「未読の投稿がありますよ」イベントを発行する // 2秒経っても既読にならなかったら「未読の投稿がありますよ」イベントを発行する
setTimeout(async () => { setTimeout(2000, 'unread note', { signal: this.#shutdownController.signal }).then(async () => {
const exist = await this.noteUnreadsRepository.findOneBy({ id: unread.id }); const exist = await this.noteUnreadsRepository.findOneBy({ id: unread.id });
if (exist == null) return; if (exist == null) return;
if (params.isMentioned) { if (params.isMentioned) {
this.globalEventService.publishMainStream(userId, 'unreadMention', note.id); this.globalEventService.publishMainStream(userId, 'unreadMention', note.id);
} }
@@ -95,8 +98,8 @@ export class NoteReadService {
if (note.channelId) { if (note.channelId) {
this.globalEventService.publishMainStream(userId, 'unreadChannel', note.id); this.globalEventService.publishMainStream(userId, 'unreadChannel', note.id);
} }
}, 2000); }, () => { /* aborted, ignore it */ });
} }
@bindThis @bindThis
public async read( public async read(
@@ -113,24 +116,24 @@ export class NoteReadService {
}, },
select: ['followeeId'], select: ['followeeId'],
})).map(x => x.followeeId)); })).map(x => x.followeeId));
const myAntennas = (await this.antennaService.getAntennas()).filter(a => a.userId === userId); const myAntennas = (await this.antennaService.getAntennas()).filter(a => a.userId === userId);
const readMentions: (Note | Packed<'Note'>)[] = []; const readMentions: (Note | Packed<'Note'>)[] = [];
const readSpecifiedNotes: (Note | Packed<'Note'>)[] = []; const readSpecifiedNotes: (Note | Packed<'Note'>)[] = [];
const readChannelNotes: (Note | Packed<'Note'>)[] = []; const readChannelNotes: (Note | Packed<'Note'>)[] = [];
const readAntennaNotes: (Note | Packed<'Note'>)[] = []; const readAntennaNotes: (Note | Packed<'Note'>)[] = [];
for (const note of notes) { for (const note of notes) {
if (note.mentions && note.mentions.includes(userId)) { if (note.mentions && note.mentions.includes(userId)) {
readMentions.push(note); readMentions.push(note);
} else if (note.visibleUserIds && note.visibleUserIds.includes(userId)) { } else if (note.visibleUserIds && note.visibleUserIds.includes(userId)) {
readSpecifiedNotes.push(note); readSpecifiedNotes.push(note);
} }
if (note.channelId && followingChannels.has(note.channelId)) { if (note.channelId && followingChannels.has(note.channelId)) {
readChannelNotes.push(note); readChannelNotes.push(note);
} }
if (note.user != null) { // たぶんnullになることは無いはずだけど一応 if (note.user != null) { // たぶんnullになることは無いはずだけど一応
for (const antenna of myAntennas) { for (const antenna of myAntennas) {
if (await this.antennaService.checkHitAntenna(antenna, note, note.user)) { if (await this.antennaService.checkHitAntenna(antenna, note, note.user)) {
@@ -139,14 +142,14 @@ export class NoteReadService {
} }
} }
} }
if ((readMentions.length > 0) || (readSpecifiedNotes.length > 0) || (readChannelNotes.length > 0)) { if ((readMentions.length > 0) || (readSpecifiedNotes.length > 0) || (readChannelNotes.length > 0)) {
// Remove the record // Remove the record
await this.noteUnreadsRepository.delete({ await this.noteUnreadsRepository.delete({
userId: userId, userId: userId,
noteId: In([...readMentions.map(n => n.id), ...readSpecifiedNotes.map(n => n.id), ...readChannelNotes.map(n => n.id)]), noteId: In([...readMentions.map(n => n.id), ...readSpecifiedNotes.map(n => n.id), ...readChannelNotes.map(n => n.id)]),
}); });
// TODO: ↓まとめてクエリしたい // TODO: ↓まとめてクエリしたい
this.noteUnreadsRepository.countBy({ this.noteUnreadsRepository.countBy({
@@ -183,7 +186,7 @@ export class NoteReadService {
noteId: In([...readMentions.map(n => n.id), ...readSpecifiedNotes.map(n => n.id)]), noteId: In([...readMentions.map(n => n.id), ...readSpecifiedNotes.map(n => n.id)]),
}); });
} }
if (readAntennaNotes.length > 0) { if (readAntennaNotes.length > 0) {
await this.antennaNotesRepository.update({ await this.antennaNotesRepository.update({
antennaId: In(myAntennas.map(a => a.id)), antennaId: In(myAntennas.map(a => a.id)),
@@ -191,14 +194,14 @@ export class NoteReadService {
}, { }, {
read: true, read: true,
}); });
// TODO: まとめてクエリしたい // TODO: まとめてクエリしたい
for (const antenna of myAntennas) { for (const antenna of myAntennas) {
const count = await this.antennaNotesRepository.countBy({ const count = await this.antennaNotesRepository.countBy({
antennaId: antenna.id, antennaId: antenna.id,
read: false, read: false,
}); });
if (count === 0) { if (count === 0) {
this.globalEventService.publishMainStream(userId, 'readAntenna', antenna); this.globalEventService.publishMainStream(userId, 'readAntenna', antenna);
this.pushNotificationService.pushNotification(userId, 'readAntenna', { antennaId: antenna.id }); this.pushNotificationService.pushNotification(userId, 'readAntenna', { antennaId: antenna.id });
@@ -213,4 +216,8 @@ export class NoteReadService {
}); });
} }
} }
onApplicationShutdown(signal?: string | undefined): void {
this.#shutdownController.abort();
}
} }

View File

@@ -2,13 +2,12 @@ import { Inject, Injectable } from '@nestjs/common';
import { In } from 'typeorm'; import { In } from 'typeorm';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { NotificationsRepository } from '@/models/index.js'; import type { NotificationsRepository } from '@/models/index.js';
import type { UsersRepository } from '@/models/index.js';
import type { User } from '@/models/entities/User.js'; import type { User } from '@/models/entities/User.js';
import type { Notification } from '@/models/entities/Notification.js'; import type { Notification } from '@/models/entities/Notification.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { bindThis } from '@/decorators.js';
import { GlobalEventService } from './GlobalEventService.js'; import { GlobalEventService } from './GlobalEventService.js';
import { PushNotificationService } from './PushNotificationService.js'; import { PushNotificationService } from './PushNotificationService.js';
import { bindThis } from '@/decorators.js';
@Injectable() @Injectable()
export class NotificationService { export class NotificationService {
@@ -66,7 +65,6 @@ export class NotificationService {
@bindThis @bindThis
private postReadNotifications(userId: User['id'], notificationIds: Notification['id'][]) { private postReadNotifications(userId: User['id'], notificationIds: Notification['id'][]) {
this.globalEventService.publishMainStream(userId, 'readNotifications', notificationIds);
return this.pushNotificationService.pushNotification(userId, 'readNotifications', { notificationIds }); return this.pushNotificationService.pushNotification(userId, 'readNotifications', { notificationIds });
} }
} }

View File

@@ -1,10 +1,8 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { Not } from 'typeorm';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { NotesRepository, UsersRepository, PollsRepository, PollVotesRepository } from '@/models/index.js'; import type { NotesRepository, UsersRepository, PollsRepository, PollVotesRepository, User } from '@/models/index.js';
import type { Note } from '@/models/entities/Note.js'; import type { Note } from '@/models/entities/Note.js';
import { RelayService } from '@/core/RelayService.js'; import { RelayService } from '@/core/RelayService.js';
import type { CacheableUser } from '@/models/entities/User.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
@@ -39,7 +37,7 @@ export class PollService {
} }
@bindThis @bindThis
public async vote(user: CacheableUser, note: Note, choice: number) { public async vote(user: User, note: Note, choice: number) {
const poll = await this.pollsRepository.findOneBy({ noteId: note.id }); const poll = await this.pollsRepository.findOneBy({ noteId: note.id });
if (poll == null) throw new Error('poll not found'); if (poll == null) throw new Error('poll not found');
@@ -97,7 +95,7 @@ export class PollService {
if (user == null) throw new Error('note not found'); if (user == null) throw new Error('note not found');
if (this.userEntityService.isLocalUser(user)) { if (this.userEntityService.isLocalUser(user)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUpdate(await this.apRendererService.renderNote(note, false), user)); const content = this.apRendererService.addContext(this.apRendererService.renderUpdate(await this.apRendererService.renderNote(note, false), user));
this.apDeliverManagerService.deliverToFollowers(user, content); this.apDeliverManagerService.deliverToFollowers(user, content);
this.relayService.deliverToRelays(user, content); this.relayService.deliverToRelays(user, content);
} }

View File

@@ -1,6 +1,6 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import type { UsersRepository } from '@/models/index.js'; import type { UsersRepository } from '@/models/index.js';
import type { ILocalUser, User } from '@/models/entities/User.js'; import type { LocalUser } from '@/models/entities/User.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
@@ -16,9 +16,9 @@ export class ProxyAccountService {
} }
@bindThis @bindThis
public async fetch(): Promise<ILocalUser | null> { public async fetch(): Promise<LocalUser | null> {
const meta = await this.metaService.fetch(); const meta = await this.metaService.fetch();
if (meta.proxyAccountId == null) return null; if (meta.proxyAccountId == null) return null;
return await this.usersRepository.findOneByOrFail({ id: meta.proxyAccountId }) as ILocalUser; return await this.usersRepository.findOneByOrFail({ id: meta.proxyAccountId }) as LocalUser;
} }
} }

View File

@@ -9,24 +9,21 @@ import { MetaService } from '@/core/MetaService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
// Defined also packages/sw/types.ts#L13 // Defined also packages/sw/types.ts#L13
type pushNotificationsTypes = { type PushNotificationsTypes = {
'notification': Packed<'Notification'>; 'notification': Packed<'Notification'>;
'unreadMessagingMessage': Packed<'MessagingMessage'>;
'unreadAntennaNote': { 'unreadAntennaNote': {
antenna: { id: string, name: string }; antenna: { id: string, name: string };
note: Packed<'Note'>; note: Packed<'Note'>;
}; };
'readNotifications': { notificationIds: string[] }; 'readNotifications': { notificationIds: string[] };
'readAllNotifications': undefined; 'readAllNotifications': undefined;
'readAllMessagingMessages': undefined;
'readAllMessagingMessagesOfARoom': { userId: string } | { groupId: string };
'readAntenna': { antennaId: string }; 'readAntenna': { antennaId: string };
'readAllAntennas': undefined; 'readAllAntennas': undefined;
}; };
// Reduce length because push message servers have character limits // Reduce length because push message servers have character limits
function truncateBody<T extends keyof pushNotificationsTypes>(type: T, body: pushNotificationsTypes[T]): pushNotificationsTypes[T] { function truncateBody<T extends keyof PushNotificationsTypes>(type: T, body: PushNotificationsTypes[T]): PushNotificationsTypes[T] {
if (body === undefined) return body; if (typeof body !== 'object') return body;
return { return {
...body, ...body,
@@ -40,11 +37,9 @@ function truncateBody<T extends keyof pushNotificationsTypes>(type: T, body: pus
reply: undefined, reply: undefined,
renote: undefined, renote: undefined,
user: type === 'notification' ? undefined as any : body.note.user, user: type === 'notification' ? undefined as any : body.note.user,
} },
} : {}), } : {}),
}; };
return body;
} }
@Injectable() @Injectable()
@@ -61,7 +56,7 @@ export class PushNotificationService {
} }
@bindThis @bindThis
public async pushNotification<T extends keyof pushNotificationsTypes>(userId: string, type: T, body: pushNotificationsTypes[T]) { public async pushNotification<T extends keyof PushNotificationsTypes>(userId: string, type: T, body: PushNotificationsTypes[T]) {
const meta = await this.metaService.fetch(); const meta = await this.metaService.fetch();
if (!meta.enableServiceWorker || meta.swPublicKey == null || meta.swPrivateKey == null) return; if (!meta.enableServiceWorker || meta.swPublicKey == null || meta.swPrivateKey == null) return;
@@ -81,8 +76,6 @@ export class PushNotificationService {
if ([ if ([
'readNotifications', 'readNotifications',
'readAllNotifications', 'readAllNotifications',
'readAllMessagingMessages',
'readAllMessagingMessagesOfARoom',
'readAntenna', 'readAntenna',
'readAllAntennas', 'readAllAntennas',
].includes(type) && !subscription.sendReadMessage) continue; ].includes(type) && !subscription.sendReadMessage) continue;

View File

@@ -3,7 +3,7 @@ import { IsNull } from 'typeorm';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { EmojisRepository, BlockingsRepository, NoteReactionsRepository, UsersRepository, NotesRepository } from '@/models/index.js'; import type { EmojisRepository, BlockingsRepository, NoteReactionsRepository, UsersRepository, NotesRepository } from '@/models/index.js';
import { IdentifiableError } from '@/misc/identifiable-error.js'; import { IdentifiableError } from '@/misc/identifiable-error.js';
import type { IRemoteUser, User } from '@/models/entities/User.js'; import type { RemoteUser, User } from '@/models/entities/User.js';
import type { Note } from '@/models/entities/Note.js'; import type { Note } from '@/models/entities/Note.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import type { NoteReaction } from '@/models/entities/NoteReaction.js'; import type { NoteReaction } from '@/models/entities/NoteReaction.js';
@@ -85,7 +85,7 @@ export class ReactionService {
} }
@bindThis @bindThis
public async create(user: { id: User['id']; host: User['host']; isBot: User['isBot'] }, note: Note, reaction?: string) { public async create(user: { id: User['id']; host: User['host']; isBot: User['isBot'] }, note: Note, reaction?: string | null) {
// Check blocking // Check blocking
if (note.userId !== user.id) { if (note.userId !== user.id) {
const blocked = await this.userBlockingService.checkBlocked(note.userId, user.id); const blocked = await this.userBlockingService.checkBlocked(note.userId, user.id);
@@ -177,11 +177,11 @@ export class ReactionService {
//#region 配信 //#region 配信
if (this.userEntityService.isLocalUser(user) && !note.localOnly) { if (this.userEntityService.isLocalUser(user) && !note.localOnly) {
const content = this.apRendererService.renderActivity(await this.apRendererService.renderLike(record, note)); const content = this.apRendererService.addContext(await this.apRendererService.renderLike(record, note));
const dm = this.apDeliverManagerService.createDeliverManager(user, content); const dm = this.apDeliverManagerService.createDeliverManager(user, content);
if (note.userHost !== null) { if (note.userHost !== null) {
const reactee = await this.usersRepository.findOneBy({ id: note.userId }); const reactee = await this.usersRepository.findOneBy({ id: note.userId });
dm.addDirectRecipe(reactee as IRemoteUser); dm.addDirectRecipe(reactee as RemoteUser);
} }
if (['public', 'home', 'followers'].includes(note.visibility)) { if (['public', 'home', 'followers'].includes(note.visibility)) {
@@ -189,7 +189,7 @@ export class ReactionService {
} else if (note.visibility === 'specified') { } else if (note.visibility === 'specified') {
const visibleUsers = await Promise.all(note.visibleUserIds.map(id => this.usersRepository.findOneBy({ id }))); const visibleUsers = await Promise.all(note.visibleUserIds.map(id => this.usersRepository.findOneBy({ id })));
for (const u of visibleUsers.filter(u => u && this.userEntityService.isRemoteUser(u))) { for (const u of visibleUsers.filter(u => u && this.userEntityService.isRemoteUser(u))) {
dm.addDirectRecipe(u as IRemoteUser); dm.addDirectRecipe(u as RemoteUser);
} }
} }
@@ -235,11 +235,11 @@ export class ReactionService {
//#region 配信 //#region 配信
if (this.userEntityService.isLocalUser(user) && !note.localOnly) { if (this.userEntityService.isLocalUser(user) && !note.localOnly) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(await this.apRendererService.renderLike(exist, note), user)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(await this.apRendererService.renderLike(exist, note), user));
const dm = this.apDeliverManagerService.createDeliverManager(user, content); const dm = this.apDeliverManagerService.createDeliverManager(user, content);
if (note.userHost !== null) { if (note.userHost !== null) {
const reactee = await this.usersRepository.findOneBy({ id: note.userId }); const reactee = await this.usersRepository.findOneBy({ id: note.userId });
dm.addDirectRecipe(reactee as IRemoteUser); dm.addDirectRecipe(reactee as RemoteUser);
} }
dm.addFollowersRecipe(); dm.addFollowersRecipe();
dm.execute(); dm.execute();

View File

@@ -1,6 +1,6 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { IsNull } from 'typeorm'; import { IsNull } from 'typeorm';
import type { ILocalUser, User } from '@/models/entities/User.js'; import type { LocalUser, User } from '@/models/entities/User.js';
import type { RelaysRepository, UsersRepository } from '@/models/index.js'; import type { RelaysRepository, UsersRepository } from '@/models/index.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { Cache } from '@/misc/cache.js'; import { Cache } from '@/misc/cache.js';
@@ -34,16 +34,16 @@ export class RelayService {
} }
@bindThis @bindThis
private async getRelayActor(): Promise<ILocalUser> { private async getRelayActor(): Promise<LocalUser> {
const user = await this.usersRepository.findOneBy({ const user = await this.usersRepository.findOneBy({
host: IsNull(), host: IsNull(),
username: ACTOR_USERNAME, username: ACTOR_USERNAME,
}); });
if (user) return user as ILocalUser; if (user) return user as LocalUser;
const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME); const created = await this.createSystemUserService.createSystemUser(ACTOR_USERNAME);
return created as ILocalUser; return created as LocalUser;
} }
@bindThis @bindThis
@@ -56,7 +56,7 @@ export class RelayService {
const relayActor = await this.getRelayActor(); const relayActor = await this.getRelayActor();
const follow = await this.apRendererService.renderFollowRelay(relay, relayActor); const follow = await this.apRendererService.renderFollowRelay(relay, relayActor);
const activity = this.apRendererService.renderActivity(follow); const activity = this.apRendererService.addContext(follow);
this.queueService.deliver(relayActor, activity, relay.inbox); this.queueService.deliver(relayActor, activity, relay.inbox);
return relay; return relay;
@@ -75,7 +75,7 @@ export class RelayService {
const relayActor = await this.getRelayActor(); const relayActor = await this.getRelayActor();
const follow = this.apRendererService.renderFollowRelay(relay, relayActor); const follow = this.apRendererService.renderFollowRelay(relay, relayActor);
const undo = this.apRendererService.renderUndo(follow, relayActor); const undo = this.apRendererService.renderUndo(follow, relayActor);
const activity = this.apRendererService.renderActivity(undo); const activity = this.apRendererService.addContext(undo);
this.queueService.deliver(relayActor, activity, relay.inbox); this.queueService.deliver(relayActor, activity, relay.inbox);
await this.relaysRepository.delete(relay.id); await this.relaysRepository.delete(relay.id);

View File

@@ -1,7 +1,6 @@
import { Inject, Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
import { LoggerService } from '@/core/LoggerService.js'; import { LoggerService } from '@/core/LoggerService.js';
import { bindThis } from '@/decorators.js';
@Injectable() @Injectable()
export class RemoteLoggerService { export class RemoteLoggerService {

View File

@@ -4,7 +4,7 @@ import chalk from 'chalk';
import { IsNull } from 'typeorm'; import { IsNull } from 'typeorm';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { UsersRepository } from '@/models/index.js'; import type { UsersRepository } from '@/models/index.js';
import type { IRemoteUser, User } from '@/models/entities/User.js'; import type { RemoteUser, User } from '@/models/entities/User.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
import { UtilityService } from '@/core/UtilityService.js'; import { UtilityService } from '@/core/UtilityService.js';
@@ -60,7 +60,7 @@ export class RemoteUserResolveService {
}); });
} }
const user = await this.usersRepository.findOneBy({ usernameLower, host }) as IRemoteUser | null; const user = await this.usersRepository.findOneBy({ usernameLower, host }) as RemoteUser | null;
const acctLower = `${usernameLower}@${host}`; const acctLower = `${usernameLower}@${host}`;
@@ -82,7 +82,7 @@ export class RemoteUserResolveService {
const self = await this.resolveSelf(acctLower); const self = await this.resolveSelf(acctLower);
if (user.uri !== self.href) { if (user.uri !== self.href) {
// if uri mismatch, Fix (user@host <=> AP's Person id(IRemoteUser.uri)) mapping. // if uri mismatch, Fix (user@host <=> AP's Person id(RemoteUser.uri)) mapping.
this.logger.info(`uri missmatch: ${acctLower}`); this.logger.info(`uri missmatch: ${acctLower}`);
this.logger.info(`recovery missmatch uri for (username=${username}, host=${host}) from ${user.uri} to ${self.href}`); this.logger.info(`recovery missmatch uri for (username=${username}, host=${host}) from ${user.uri} to ${self.href}`);

View File

@@ -3,7 +3,7 @@ import Redis from 'ioredis';
import { In } from 'typeorm'; import { In } from 'typeorm';
import type { Role, RoleAssignment, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/index.js'; import type { Role, RoleAssignment, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/index.js';
import { Cache } from '@/misc/cache.js'; import { Cache } from '@/misc/cache.js';
import type { CacheableLocalUser, CacheableUser, ILocalUser, User } from '@/models/entities/User.js'; import type { User } from '@/models/entities/User.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
@@ -11,6 +11,8 @@ import { UserCacheService } from '@/core/UserCacheService.js';
import type { RoleCondFormulaValue } from '@/models/entities/Role.js'; import type { RoleCondFormulaValue } from '@/models/entities/Role.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { StreamMessages } from '@/server/api/stream/types.js'; import { StreamMessages } from '@/server/api/stream/types.js';
import { IdService } from '@/core/IdService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import type { OnApplicationShutdown } from '@nestjs/common'; import type { OnApplicationShutdown } from '@nestjs/common';
export type RolePolicies = { export type RolePolicies = {
@@ -56,6 +58,9 @@ export class RoleService implements OnApplicationShutdown {
private rolesCache: Cache<Role[]>; private rolesCache: Cache<Role[]>;
private roleAssignmentByUserIdCache: Cache<RoleAssignment[]>; private roleAssignmentByUserIdCache: Cache<RoleAssignment[]>;
public static AlreadyAssignedError = class extends Error {};
public static NotAssignedError = class extends Error {};
constructor( constructor(
@Inject(DI.redisSubscriber) @Inject(DI.redisSubscriber)
private redisSubscriber: Redis.Redis, private redisSubscriber: Redis.Redis,
@@ -72,6 +77,8 @@ export class RoleService implements OnApplicationShutdown {
private metaService: MetaService, private metaService: MetaService,
private userCacheService: UserCacheService, private userCacheService: UserCacheService,
private userEntityService: UserEntityService, private userEntityService: UserEntityService,
private globalEventService: GlobalEventService,
private idService: IdService,
) { ) {
//this.onMessage = this.onMessage.bind(this); //this.onMessage = this.onMessage.bind(this);
@@ -128,6 +135,7 @@ export class RoleService implements OnApplicationShutdown {
cached.push({ cached.push({
...body, ...body,
createdAt: new Date(body.createdAt), createdAt: new Date(body.createdAt),
expiresAt: body.expiresAt ? new Date(body.expiresAt) : null,
}); });
} }
break; break;
@@ -193,7 +201,10 @@ export class RoleService implements OnApplicationShutdown {
@bindThis @bindThis
public async getUserRoles(userId: User['id']) { public async getUserRoles(userId: User['id']) {
const assigns = await this.roleAssignmentByUserIdCache.fetch(userId, () => this.roleAssignmentsRepository.findBy({ userId })); const now = Date.now();
let assigns = await this.roleAssignmentByUserIdCache.fetch(userId, () => this.roleAssignmentsRepository.findBy({ userId }));
// 期限切れのロールを除外
assigns = assigns.filter(a => a.expiresAt == null || (a.expiresAt.getTime() > now));
const assignedRoleIds = assigns.map(x => x.roleId); const assignedRoleIds = assigns.map(x => x.roleId);
const roles = await this.rolesCache.fetch(null, () => this.rolesRepository.findBy({})); const roles = await this.rolesCache.fetch(null, () => this.rolesRepository.findBy({}));
const assignedRoles = roles.filter(r => assignedRoleIds.includes(r.id)); const assignedRoles = roles.filter(r => assignedRoleIds.includes(r.id));
@@ -207,7 +218,10 @@ export class RoleService implements OnApplicationShutdown {
*/ */
@bindThis @bindThis
public async getUserBadgeRoles(userId: User['id']) { public async getUserBadgeRoles(userId: User['id']) {
const assigns = await this.roleAssignmentByUserIdCache.fetch(userId, () => this.roleAssignmentsRepository.findBy({ userId })); const now = Date.now();
let assigns = await this.roleAssignmentByUserIdCache.fetch(userId, () => this.roleAssignmentsRepository.findBy({ userId }));
// 期限切れのロールを除外
assigns = assigns.filter(a => a.expiresAt == null || (a.expiresAt.getTime() > now));
const assignedRoleIds = assigns.map(x => x.roleId); const assignedRoleIds = assigns.map(x => x.roleId);
const roles = await this.rolesCache.fetch(null, () => this.rolesRepository.findBy({})); const roles = await this.rolesCache.fetch(null, () => this.rolesRepository.findBy({}));
const assignedBadgeRoles = roles.filter(r => r.asBadge && assignedRoleIds.includes(r.id)); const assignedBadgeRoles = roles.filter(r => r.asBadge && assignedRoleIds.includes(r.id));
@@ -316,6 +330,65 @@ export class RoleService implements OnApplicationShutdown {
return users; return users;
} }
@bindThis
public async assign(userId: User['id'], roleId: Role['id'], expiresAt: Date | null = null): Promise<void> {
const now = new Date();
const existing = await this.roleAssignmentsRepository.findOneBy({
roleId: roleId,
userId: userId,
});
if (existing) {
if (existing.expiresAt && (existing.expiresAt.getTime() < now.getTime())) {
await this.roleAssignmentsRepository.delete({
roleId: roleId,
userId: userId,
});
} else {
throw new RoleService.AlreadyAssignedError();
}
}
const created = await this.roleAssignmentsRepository.insert({
id: this.idService.genId(),
createdAt: now,
expiresAt: expiresAt,
roleId: roleId,
userId: userId,
}).then(x => this.roleAssignmentsRepository.findOneByOrFail(x.identifiers[0]));
this.rolesRepository.update(roleId, {
lastUsedAt: new Date(),
});
this.globalEventService.publishInternalEvent('userRoleAssigned', created);
}
@bindThis
public async unassign(userId: User['id'], roleId: Role['id']): Promise<void> {
const now = new Date();
const existing = await this.roleAssignmentsRepository.findOneBy({ roleId, userId });
if (existing == null) {
throw new RoleService.NotAssignedError();
} else if (existing.expiresAt && (existing.expiresAt.getTime() < now.getTime())) {
await this.roleAssignmentsRepository.delete({
roleId: roleId,
userId: userId,
});
throw new RoleService.NotAssignedError();
}
await this.roleAssignmentsRepository.delete(existing.id);
this.rolesRepository.update(roleId, {
lastUsedAt: now,
});
this.globalEventService.publishInternalEvent('userRoleUnassigned', existing);
}
@bindThis @bindThis
public onApplicationShutdown(signal?: string | undefined) { public onApplicationShutdown(signal?: string | undefined) {
this.redisSubscriber.off('message', this.onMessage); this.redisSubscriber.off('message', this.onMessage);

View File

@@ -2,7 +2,7 @@
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
import Redis from 'ioredis'; import Redis from 'ioredis';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import type { CacheableUser, User } from '@/models/entities/User.js'; import type { User } from '@/models/entities/User.js';
import type { Blocking } from '@/models/entities/Blocking.js'; import type { Blocking } from '@/models/entities/Blocking.js';
import { QueueService } from '@/core/QueueService.js'; import { QueueService } from '@/core/QueueService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js';
@@ -117,7 +117,7 @@ export class UserBlockingService implements OnApplicationShutdown {
}); });
if (this.userEntityService.isLocalUser(blocker) && this.userEntityService.isRemoteUser(blockee)) { if (this.userEntityService.isLocalUser(blocker) && this.userEntityService.isRemoteUser(blockee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderBlock(blocking)); const content = this.apRendererService.addContext(this.apRendererService.renderBlock(blocking));
this.queueService.deliver(blocker, content, blockee.inbox); this.queueService.deliver(blocker, content, blockee.inbox);
} }
} }
@@ -162,13 +162,13 @@ export class UserBlockingService implements OnApplicationShutdown {
// リモートにフォローリクエストをしていたらUndoFollow送信 // リモートにフォローリクエストをしていたらUndoFollow送信
if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower));
this.queueService.deliver(follower, content, followee.inbox); this.queueService.deliver(follower, content, followee.inbox);
} }
// リモートからフォローリクエストを受けていたらReject送信 // リモートからフォローリクエストを受けていたらReject送信
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
} }
} }
@@ -210,13 +210,13 @@ export class UserBlockingService implements OnApplicationShutdown {
// リモートにフォローをしていたらUndoFollow送信 // リモートにフォローをしていたらUndoFollow送信
if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower));
this.queueService.deliver(follower, content, followee.inbox); this.queueService.deliver(follower, content, followee.inbox);
} }
// リモートからフォローをされていたらRejectFollow送信 // リモートからフォローをされていたらRejectFollow送信
if (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower)) { if (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
} }
} }
@@ -236,7 +236,7 @@ export class UserBlockingService implements OnApplicationShutdown {
} }
@bindThis @bindThis
public async unblock(blocker: CacheableUser, blockee: CacheableUser) { public async unblock(blocker: User, blockee: User) {
const blocking = await this.blockingsRepository.findOneBy({ const blocking = await this.blockingsRepository.findOneBy({
blockerId: blocker.id, blockerId: blocker.id,
blockeeId: blockee.id, blockeeId: blockee.id,
@@ -261,7 +261,7 @@ export class UserBlockingService implements OnApplicationShutdown {
// deliver if remote bloking // deliver if remote bloking
if (this.userEntityService.isLocalUser(blocker) && this.userEntityService.isRemoteUser(blockee)) { if (this.userEntityService.isLocalUser(blocker) && this.userEntityService.isRemoteUser(blockee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderBlock(blocking), blocker)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderBlock(blocking), blocker));
this.queueService.deliver(blocker, content, blockee.inbox); this.queueService.deliver(blocker, content, blockee.inbox);
} }
} }

View File

@@ -2,7 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
import Redis from 'ioredis'; import Redis from 'ioredis';
import type { UsersRepository } from '@/models/index.js'; import type { UsersRepository } from '@/models/index.js';
import { Cache } from '@/misc/cache.js'; import { Cache } from '@/misc/cache.js';
import type { CacheableLocalUser, CacheableUser, ILocalUser, User } from '@/models/entities/User.js'; import type { LocalUser, User } from '@/models/entities/User.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
@@ -11,10 +11,10 @@ import type { OnApplicationShutdown } from '@nestjs/common';
@Injectable() @Injectable()
export class UserCacheService implements OnApplicationShutdown { export class UserCacheService implements OnApplicationShutdown {
public userByIdCache: Cache<CacheableUser>; public userByIdCache: Cache<User>;
public localUserByNativeTokenCache: Cache<CacheableLocalUser | null>; public localUserByNativeTokenCache: Cache<LocalUser | null>;
public localUserByIdCache: Cache<CacheableLocalUser>; public localUserByIdCache: Cache<LocalUser>;
public uriPersonCache: Cache<CacheableUser | null>; public uriPersonCache: Cache<User | null>;
constructor( constructor(
@Inject(DI.redisSubscriber) @Inject(DI.redisSubscriber)
@@ -27,10 +27,10 @@ export class UserCacheService implements OnApplicationShutdown {
) { ) {
//this.onMessage = this.onMessage.bind(this); //this.onMessage = this.onMessage.bind(this);
this.userByIdCache = new Cache<CacheableUser>(Infinity); this.userByIdCache = new Cache<User>(Infinity);
this.localUserByNativeTokenCache = new Cache<CacheableLocalUser | null>(Infinity); this.localUserByNativeTokenCache = new Cache<LocalUser | null>(Infinity);
this.localUserByIdCache = new Cache<CacheableLocalUser>(Infinity); this.localUserByIdCache = new Cache<LocalUser>(Infinity);
this.uriPersonCache = new Cache<CacheableUser | null>(Infinity); this.uriPersonCache = new Cache<User | null>(Infinity);
this.redisSubscriber.on('message', this.onMessage); this.redisSubscriber.on('message', this.onMessage);
} }
@@ -58,7 +58,7 @@ export class UserCacheService implements OnApplicationShutdown {
break; break;
} }
case 'userTokenRegenerated': { case 'userTokenRegenerated': {
const user = await this.usersRepository.findOneByOrFail({ id: body.id }) as ILocalUser; const user = await this.usersRepository.findOneByOrFail({ id: body.id }) as LocalUser;
this.localUserByNativeTokenCache.delete(body.oldToken); this.localUserByNativeTokenCache.delete(body.oldToken);
this.localUserByNativeTokenCache.set(body.newToken, user); this.localUserByNativeTokenCache.set(body.newToken, user);
break; break;

View File

@@ -1,5 +1,5 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import type { CacheableUser, ILocalUser, IRemoteUser, User } from '@/models/entities/User.js'; import type { LocalUser, RemoteUser, User } from '@/models/entities/User.js';
import { IdentifiableError } from '@/misc/identifiable-error.js'; import { IdentifiableError } from '@/misc/identifiable-error.js';
import { QueueService } from '@/core/QueueService.js'; import { QueueService } from '@/core/QueueService.js';
import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js'; import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js';
@@ -21,16 +21,16 @@ import Logger from '../logger.js';
const logger = new Logger('following/create'); const logger = new Logger('following/create');
type Local = ILocalUser | { type Local = LocalUser | {
id: ILocalUser['id']; id: LocalUser['id'];
host: ILocalUser['host']; host: LocalUser['host'];
uri: ILocalUser['uri'] uri: LocalUser['uri']
}; };
type Remote = IRemoteUser | { type Remote = RemoteUser | {
id: IRemoteUser['id']; id: RemoteUser['id'];
host: IRemoteUser['host']; host: RemoteUser['host'];
uri: IRemoteUser['uri']; uri: RemoteUser['uri'];
inbox: IRemoteUser['inbox']; inbox: RemoteUser['inbox'];
}; };
type Both = Local | Remote; type Both = Local | Remote;
@@ -81,7 +81,7 @@ export class UserFollowingService {
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee) && blocked) { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee) && blocked) {
// リモートフォローを受けてブロックしていた場合は、エラーにするのではなくRejectを送り返しておしまい。 // リモートフォローを受けてブロックしていた場合は、エラーにするのではなくRejectを送り返しておしまい。
const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, requestId), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, requestId), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
return; return;
} else if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee) && blocking) { } else if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee) && blocking) {
@@ -130,7 +130,7 @@ export class UserFollowingService {
await this.insertFollowingDoc(followee, follower); await this.insertFollowingDoc(followee, follower);
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
} }
} }
@@ -293,13 +293,13 @@ export class UserFollowingService {
} }
if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower));
this.queueService.deliver(follower, content, followee.inbox); this.queueService.deliver(follower, content, followee.inbox);
} }
if (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower)) { if (this.userEntityService.isLocalUser(followee) && this.userEntityService.isRemoteUser(follower)) {
// local user has null host // local user has null host
const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
} }
} }
@@ -388,7 +388,7 @@ export class UserFollowingService {
} }
if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) { if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderFollow(follower, followee)); const content = this.apRendererService.addContext(this.apRendererService.renderFollow(follower, followee));
this.queueService.deliver(follower, content, followee.inbox); this.queueService.deliver(follower, content, followee.inbox);
} }
} }
@@ -403,7 +403,7 @@ export class UserFollowingService {
}, },
): Promise<void> { ): Promise<void> {
if (this.userEntityService.isRemoteUser(followee)) { if (this.userEntityService.isRemoteUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderFollow(follower, followee), follower));
if (this.userEntityService.isLocalUser(follower)) { // 本来このチェックは不要だけどTSに怒られるので if (this.userEntityService.isLocalUser(follower)) { // 本来このチェックは不要だけどTSに怒られるので
this.queueService.deliver(follower, content, followee.inbox); this.queueService.deliver(follower, content, followee.inbox);
@@ -434,7 +434,7 @@ export class UserFollowingService {
followee: { followee: {
id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox']; id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox'];
}, },
follower: CacheableUser, follower: User,
): Promise<void> { ): Promise<void> {
const request = await this.followRequestsRepository.findOneBy({ const request = await this.followRequestsRepository.findOneBy({
followeeId: followee.id, followeeId: followee.id,
@@ -448,7 +448,7 @@ export class UserFollowingService {
await this.insertFollowingDoc(followee, follower); await this.insertFollowingDoc(followee, follower);
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) { if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
const content = this.apRendererService.renderActivity(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, request.requestId!), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
} }
@@ -556,7 +556,7 @@ export class UserFollowingService {
followerId: follower.id, followerId: follower.id,
}); });
const content = this.apRendererService.renderActivity(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request?.requestId ?? undefined), followee)); const content = this.apRendererService.addContext(this.apRendererService.renderReject(this.apRendererService.renderFollow(follower, followee, request?.requestId ?? undefined), followee));
this.queueService.deliver(followee, content, follower.inbox); this.queueService.deliver(followee, content, follower.inbox);
} }

View File

@@ -35,7 +35,7 @@ export class UserSuspendService {
if (this.userEntityService.isLocalUser(user)) { if (this.userEntityService.isLocalUser(user)) {
// 知り得る全SharedInboxにDelete配信 // 知り得る全SharedInboxにDelete配信
const content = this.apRendererService.renderActivity(this.apRendererService.renderDelete(`${this.config.url}/users/${user.id}`, user)); const content = this.apRendererService.addContext(this.apRendererService.renderDelete(`${this.config.url}/users/${user.id}`, user));
const queue: string[] = []; const queue: string[] = [];
@@ -65,7 +65,7 @@ export class UserSuspendService {
if (this.userEntityService.isLocalUser(user)) { if (this.userEntityService.isLocalUser(user)) {
// 知り得る全SharedInboxにUndo Delete配信 // 知り得る全SharedInboxにUndo Delete配信
const content = this.apRendererService.renderActivity(this.apRendererService.renderUndo(this.apRendererService.renderDelete(`${this.config.url}/users/${user.id}`, user), user)); const content = this.apRendererService.addContext(this.apRendererService.renderUndo(this.apRendererService.renderDelete(`${this.config.url}/users/${user.id}`, user), user));
const queue: string[] = []; const queue: string[] = [];

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