Merge branch 'develop' into enh-i-update-0
This commit is contained in:
commit
cd26043c82
|
@ -5,7 +5,7 @@
|
||||||
"workspaceFolder": "/workspace",
|
"workspaceFolder": "/workspace",
|
||||||
"features": {
|
"features": {
|
||||||
"ghcr.io/devcontainers/features/node:1": {
|
"ghcr.io/devcontainers/features/node:1": {
|
||||||
"version": "20.12.2"
|
"version": "20.16.0"
|
||||||
},
|
},
|
||||||
"ghcr.io/devcontainers-contrib/features/corepack:1": {}
|
"ghcr.io/devcontainers-contrib/features/corepack:1": {}
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,7 +18,7 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [20.12.2]
|
node-version: [20.16.0]
|
||||||
api-json-name: [api-base.json, api-head.json]
|
api-json-name: [api-base.json, api-head.json]
|
||||||
include:
|
include:
|
||||||
- api-json-name: api-base.json
|
- api-json-name: api-base.json
|
||||||
|
|
|
@ -17,7 +17,7 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [20.12.2]
|
node-version: [20.16.0]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.1
|
- uses: actions/checkout@v4.1.1
|
||||||
|
|
|
@ -22,7 +22,7 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [20.12.2]
|
node-version: [20.16.0]
|
||||||
|
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
|
@ -71,7 +71,7 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [20.12.2]
|
node-version: [20.16.0]
|
||||||
|
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
|
|
|
@ -26,7 +26,7 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [20.12.2]
|
node-version: [20.16.0]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.1
|
- uses: actions/checkout@v4.1.1
|
||||||
|
@ -61,7 +61,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [20.12.2]
|
node-version: [20.16.0]
|
||||||
browser: [chrome]
|
browser: [chrome]
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
|
@ -21,7 +21,7 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [20.12.2]
|
node-version: [20.16.0]
|
||||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
|
@ -16,7 +16,7 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [20.12.2]
|
node-version: [20.16.0]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.1
|
- uses: actions/checkout@v4.1.1
|
||||||
|
|
|
@ -18,7 +18,7 @@ jobs:
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [20.12.2]
|
node-version: [20.16.0]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.1
|
- uses: actions/checkout@v4.1.1
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
20.12.2
|
20.16.0
|
||||||
|
|
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -8,6 +8,7 @@
|
||||||
- Feat: 通報を受けた際、または解決した際に、予め登録した宛先に通知を飛ばせるように(mail or webhook) #13705
|
- Feat: 通報を受けた際、または解決した際に、予め登録した宛先に通知を飛ばせるように(mail or webhook) #13705
|
||||||
- Feat: ユーザーのアイコン/バナーの変更可否をロールで設定可能に
|
- Feat: ユーザーのアイコン/バナーの変更可否をロールで設定可能に
|
||||||
- 変更不可となっていても、設定済みのものを解除してデフォルト画像に戻すことは出来ます
|
- 変更不可となっていても、設定済みのものを解除してデフォルト画像に戻すことは出来ます
|
||||||
|
- Feat: ユーザ作成時にSystemWebhookを送信可能に #14281
|
||||||
- Fix: 配信停止したインスタンス一覧が見れなくなる問題を修正
|
- Fix: 配信停止したインスタンス一覧が見れなくなる問題を修正
|
||||||
- Fix: Dockerコンテナの立ち上げ時に`pnpm`のインストールで固まることがある問題
|
- Fix: Dockerコンテナの立ち上げ時に`pnpm`のインストールで固まることがある問題
|
||||||
- Fix: デフォルトテーマに無効なテーマコードを入力するとUIが使用できなくなる問題を修正
|
- Fix: デフォルトテーマに無効なテーマコードを入力するとUIが使用できなくなる問題を修正
|
||||||
|
@ -38,6 +39,13 @@
|
||||||
- Fix: 子メニューの高さがウィンドウからはみ出ることがある問題を修正
|
- Fix: 子メニューの高さがウィンドウからはみ出ることがある問題を修正
|
||||||
- Fix: 個人宛てのダイアログ形式のお知らせが即時表示されない問題を修正
|
- Fix: 個人宛てのダイアログ形式のお知らせが即時表示されない問題を修正
|
||||||
- Fix: 一部の画像がセンシティブ指定されているときに画面に何も表示されないことがあるのを修正
|
- Fix: 一部の画像がセンシティブ指定されているときに画面に何も表示されないことがあるのを修正
|
||||||
|
- Fix: リアクションしたユーザー一覧のユーザー名がはみ出る問題を修正
|
||||||
|
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/672)
|
||||||
|
- Fix: `/share`ページにおいて絵文字ピッカーを開くことができない問題を修正
|
||||||
|
- Fix: deck uiの通知音が重なる問題 (#14029)
|
||||||
|
- Fix: ダイレクト投稿の"削除して編集"において、宛先が保持されていなかった問題を修正
|
||||||
|
- Fix: 投稿フォームへのURL貼り付けによる引用が下書きに保存されていなかった問題を修正
|
||||||
|
- Fix: "削除して編集"や下書きにおいて、リアクションの受け入れ設定が保持/保存されていなかった問題を修正
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
- Feat: レートリミット制限に引っかかったときに`Retry-After`ヘッダーを返すように (#13949)
|
- Feat: レートリミット制限に引っかかったときに`Retry-After`ヘッダーを返すように (#13949)
|
||||||
|
@ -69,6 +77,8 @@
|
||||||
- Fix: 一般ユーザーから見たユーザーのバッジの一覧に公開されていないものが含まれることがある問題を修正
|
- Fix: 一般ユーザーから見たユーザーのバッジの一覧に公開されていないものが含まれることがある問題を修正
|
||||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/652)
|
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/652)
|
||||||
- Fix: ユーザーのリアクション一覧でミュート/ブロックが機能していなかった問題を修正
|
- Fix: ユーザーのリアクション一覧でミュート/ブロックが機能していなかった問題を修正
|
||||||
|
- Fix: FTT有効時にリモートユーザーのノートがHTLにキャッシュされる問題を修正
|
||||||
|
- Fix: 一部の通知がローカル上のリモートユーザーに対して行われていた問題を修正
|
||||||
- Fix: エラーメッセージの誤字を修正 (#14213)
|
- Fix: エラーメッセージの誤字を修正 (#14213)
|
||||||
- Fix: ソーシャルタイムラインにローカルタイムラインに表示される自分へのリプライが表示されない問題を修正
|
- Fix: ソーシャルタイムラインにローカルタイムラインに表示される自分へのリプライが表示されない問題を修正
|
||||||
- Fix: リノートのミュートが適用されるまでに時間がかかることがある問題を修正
|
- Fix: リノートのミュートが適用されるまでに時間がかかることがある問題を修正
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Contribution guide
|
# Contribution guide
|
||||||
We're glad you're interested in contributing Misskey! In this document you will find the information you need to contribute to the project.
|
We're glad you're interested in contributing Misskey! In this document you will find the information you need to contribute to the project.
|
||||||
|
|
||||||
> **Note**
|
> [!NOTE]
|
||||||
> This project uses Japanese as its major language, **but you do not need to translate and write the Issues/PRs in Japanese.**
|
> This project uses Japanese as its major language, **but you do not need to translate and write the Issues/PRs in Japanese.**
|
||||||
> Also, you might receive comments on your Issue/PR in Japanese, but you do not need to reply to them in Japanese as well.\
|
> Also, you might receive comments on your Issue/PR in Japanese, but you do not need to reply to them in Japanese as well.\
|
||||||
> The accuracy of machine translation into Japanese is not high, so it will be easier for us to understand if you write it in the original language.
|
> The accuracy of machine translation into Japanese is not high, so it will be easier for us to understand if you write it in the original language.
|
||||||
|
@ -17,16 +17,31 @@ Before creating an issue, please check the following:
|
||||||
- Issues should only be used to feature requests, suggestions, and bug tracking.
|
- Issues should only be used to feature requests, suggestions, and bug tracking.
|
||||||
- Please ask questions or troubleshooting in [GitHub Discussions](https://github.com/misskey-dev/misskey/discussions) or [Discord](https://discord.gg/Wp8gVStHW3).
|
- Please ask questions or troubleshooting in [GitHub Discussions](https://github.com/misskey-dev/misskey/discussions) or [Discord](https://discord.gg/Wp8gVStHW3).
|
||||||
|
|
||||||
> **Warning**
|
> [!WARNING]
|
||||||
> Do not close issues that are about to be resolved. It should remain open until a commit that actually resolves it is merged.
|
> Do not close issues that are about to be resolved. It should remain open until a commit that actually resolves it is merged.
|
||||||
|
|
||||||
## Before implementation
|
### Recommended discussing before implementation
|
||||||
|
We welcome your proposal.
|
||||||
|
|
||||||
When you want to add a feature or fix a bug, **first have the design and policy reviewed in an Issue** (if it is not there, please make one). Without this step, there is a high possibility that the PR will not be merged even if it is implemented.
|
When you want to add a feature or fix a bug, **first have the design and policy reviewed in an Issue** (if it is not there, please make one). Without this step, there is a high possibility that the PR will not be merged even if it is implemented.
|
||||||
|
|
||||||
At this point, you also need to clarify the goals of the PR you will create, and make sure that the other members of the team are aware of them.
|
At this point, you also need to clarify the goals of the PR you will create, and make sure that the other members of the team are aware of them.
|
||||||
PRs that do not have a clear set of do's and don'ts tend to be bloated and difficult to review.
|
PRs that do not have a clear set of do's and don'ts tend to be bloated and difficult to review.
|
||||||
|
|
||||||
Also, when you start implementation, assign yourself to the Issue (if you cannot do it yourself, ask another member to assign you). By expressing your intention to work the Issue, you can prevent conflicts in the work.
|
Also, when you start implementation, assign yourself to the Issue (if you cannot do it yourself, ask Committer to assign you).
|
||||||
|
By expressing your intention to work on the Issue, you can prevent conflicts in the work.
|
||||||
|
|
||||||
|
To the Committers: you should not assign someone on it before the Final Decision.
|
||||||
|
|
||||||
|
### How issues are triaged
|
||||||
|
|
||||||
|
The Committers may:
|
||||||
|
* close an issue that is not reproducible on latest stable release,
|
||||||
|
* merge an issue into another issue,
|
||||||
|
* split an issue into multiple issues,
|
||||||
|
* or re-open that has been closed for some reason which is not applicable anymore.
|
||||||
|
|
||||||
|
@syuilo reserves the Final Decision rights including whether the project will implement feature and how to implement, these rights are not always exercised.
|
||||||
|
|
||||||
## Well-known branches
|
## Well-known branches
|
||||||
- **`master`** branch is tracking the latest release and used for production purposes.
|
- **`master`** branch is tracking the latest release and used for production purposes.
|
||||||
|
@ -37,14 +52,14 @@ Also, when you start implementation, assign yourself to the Issue (if you cannot
|
||||||
## Creating a PR
|
## Creating a PR
|
||||||
Thank you for your PR! Before creating a PR, please check the following:
|
Thank you for your PR! Before creating a PR, please check the following:
|
||||||
- If possible, prefix the title with a keyword that identifies the type of this PR, as shown below.
|
- If possible, prefix the title with a keyword that identifies the type of this PR, as shown below.
|
||||||
- `fix` / `refactor` / `feat` / `enhance` / `perf` / `chore` etc
|
- `fix` / `refactor` / `feat` / `enhance` / `perf` / `chore` etc
|
||||||
- Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR.
|
- Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR.
|
||||||
- If there is an Issue which will be resolved by this PR, please include a reference to the Issue in the text.
|
- If there is an Issue which will be resolved by this PR, please include a reference to the Issue in the text.
|
||||||
- Please add the summary of the changes to [`CHANGELOG.md`](/CHANGELOG.md). However, this is not necessary for changes that do not affect the users, such as refactoring.
|
- Please add the summary of the changes to [`CHANGELOG.md`](/CHANGELOG.md). However, this is not necessary for changes that do not affect the users, such as refactoring.
|
||||||
- Check if there are any documents that need to be created or updated due to this change.
|
- Check if there are any documents that need to be created or updated due to this change.
|
||||||
- If you have added a feature or fixed a bug, please add a test case if possible.
|
- If you have added a feature or fixed a bug, please add a test case if possible.
|
||||||
- Please make sure that tests and Lint are passed in advance.
|
- Please make sure that tests and Lint are passed in advance.
|
||||||
- You can run it with `pnpm test` and `pnpm lint`. [See more info](#testing)
|
- You can run it with `pnpm test` and `pnpm lint`. [See more info](#testing)
|
||||||
- If this PR includes UI changes, please attach a screenshot in the text.
|
- If this PR includes UI changes, please attach a screenshot in the text.
|
||||||
|
|
||||||
Thanks for your cooperation 🤗
|
Thanks for your cooperation 🤗
|
||||||
|
@ -54,8 +69,8 @@ Be willing to comment on the good points and not just the things you want fixed
|
||||||
|
|
||||||
### Review perspective
|
### Review perspective
|
||||||
- Scope
|
- Scope
|
||||||
- Are the goals of the PR clear?
|
- Are the goals of the PR clear?
|
||||||
- Is the granularity of the PR appropriate?
|
- Is the granularity of the PR appropriate?
|
||||||
- Security
|
- Security
|
||||||
- Does merging this PR create a vulnerability?
|
- Does merging this PR create a vulnerability?
|
||||||
- Performance
|
- Performance
|
||||||
|
@ -77,7 +92,7 @@ An actual domain will be assigned so you can test the federation.
|
||||||
|
|
||||||
## Release
|
## Release
|
||||||
### Release Instructions
|
### Release Instructions
|
||||||
1. Commit version changes in the `develop` branch ([package.json](https://github.com/misskey-dev/misskey/blob/develop/package.json))
|
1. Commit version changes in the `develop` branch ([package.json](package.json))
|
||||||
2. Create a release PR.
|
2. Create a release PR.
|
||||||
- Into `master` from `develop` branch.
|
- Into `master` from `develop` branch.
|
||||||
- The title must be in the format `Release: x.y.z`.
|
- The title must be in the format `Release: x.y.z`.
|
||||||
|
@ -88,7 +103,7 @@ An actual domain will be assigned so you can test the federation.
|
||||||
- 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**
|
> [!NOTE]
|
||||||
> Why this instruction is necessary:
|
> Why this instruction is necessary:
|
||||||
> - To perform final QA checks
|
> - To perform final QA checks
|
||||||
> - To distribute responsibility
|
> - To distribute responsibility
|
||||||
|
@ -123,7 +138,7 @@ You could obtain middleware container by typing `docker compose -f $PROJECT_ROOT
|
||||||
Devcontainer also has necessary setting. This method can be done by connecting from VSCode.
|
Devcontainer also has necessary setting. This method can be done by connecting from VSCode.
|
||||||
|
|
||||||
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.
|
**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.
|
||||||
|
@ -139,11 +154,9 @@ After finishing the migration, you can proceed.
|
||||||
|
|
||||||
### Start developing
|
### Start developing
|
||||||
During development, it is useful to use the
|
During development, it is useful to use the
|
||||||
|
|
||||||
```
|
```
|
||||||
pnpm dev
|
pnpm dev
|
||||||
```
|
```
|
||||||
|
|
||||||
command.
|
command.
|
||||||
|
|
||||||
- Server-side source files and automatically builds them if they are modified. Automatically start the server process(es).
|
- Server-side source files and automatically builds them if they are modified. Automatically start the server process(es).
|
||||||
|
@ -216,7 +229,7 @@ niraxは、Misskeyで使用しているオリジナルのフロントエンド
|
||||||
### ルート定義
|
### ルート定義
|
||||||
ルート定義は、以下の形式のオブジェクトの配列です。
|
ルート定義は、以下の形式のオブジェクトの配列です。
|
||||||
|
|
||||||
``` ts
|
```ts
|
||||||
{
|
{
|
||||||
name?: string;
|
name?: string;
|
||||||
path: string;
|
path: string;
|
||||||
|
@ -229,7 +242,7 @@ niraxは、Misskeyで使用しているオリジナルのフロントエンド
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Warning**
|
> [!WARNING]
|
||||||
> 現状、ルートは定義された順に評価されます。
|
> 現状、ルートは定義された順に評価されます。
|
||||||
> たとえば、`/foo/:id`ルート定義の次に`/foo/bar`ルート定義がされていた場合、後者がマッチすることはありません。
|
> たとえば、`/foo/:id`ルート定義の次に`/foo/bar`ルート定義がされていた場合、後者がマッチすることはありません。
|
||||||
|
|
||||||
|
@ -291,7 +304,7 @@ export const Default = {
|
||||||
parameters: {
|
parameters: {
|
||||||
layout: 'centered',
|
layout: 'centered',
|
||||||
},
|
},
|
||||||
} satisfies StoryObj<typeof MkAvatar>;
|
} satisfies StoryObj<typeof MyComponent>;
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to opt-out from the automatic generation, create a `MyComponent.stories.impl.ts` file and add the following line to the file.
|
If you want to opt-out from the automatic generation, create a `MyComponent.stories.impl.ts` file and add the following line to the file.
|
||||||
|
@ -402,7 +415,7 @@ describe('test', () => {
|
||||||
})
|
})
|
||||||
.useMocker(...
|
.useMocker(...
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
fooService = app.get<FooService>(FooService);
|
fooService = app.get<FooService>(FooService);
|
||||||
barService = app.get<BarService>(BarService) as jest.Mocked<BarService>;
|
barService = app.get<BarService>(BarService) as jest.Mocked<BarService>;
|
||||||
|
|
||||||
|
@ -523,13 +536,13 @@ pnpm dlx typeorm migration:generate -d ormconfig.js -o <migration name>
|
||||||
- 作成されたスクリプトは不必要な変更を含むため除去してください
|
- 作成されたスクリプトは不必要な変更を含むため除去してください
|
||||||
|
|
||||||
### JSON SchemaのobjectでanyOfを使うとき
|
### JSON SchemaのobjectでanyOfを使うとき
|
||||||
JSON Schemaで、objectに対してanyOfを使う場合、anyOfの中でpropertiesを定義しないこと。
|
JSON Schemaで、objectに対してanyOfを使う場合、anyOfの中でpropertiesを定義しないこと。
|
||||||
バリデーションが効かないため。(SchemaTypeもそのように作られており、objectのanyOf内のpropertiesは捨てられます)
|
バリデーションが効かないため。(SchemaTypeもそのように作られており、objectのanyOf内のpropertiesは捨てられます)
|
||||||
https://github.com/misskey-dev/misskey/pull/10082
|
https://github.com/misskey-dev/misskey/pull/10082
|
||||||
|
|
||||||
テキストhogeおよびfugaについて、片方を必須としつつ両方の指定もありうる場合:
|
テキストhogeおよびfugaについて、片方を必須としつつ両方の指定もありうる場合:
|
||||||
|
|
||||||
```
|
```ts
|
||||||
export const paramDef = {
|
export const paramDef = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# syntax = docker/dockerfile:1.4
|
# syntax = docker/dockerfile:1.4
|
||||||
|
|
||||||
ARG NODE_VERSION=20.12.2-bullseye
|
ARG NODE_VERSION=20.16.0-bullseye
|
||||||
|
|
||||||
# build assets & compile TypeScript
|
# build assets & compile TypeScript
|
||||||
|
|
||||||
|
|
|
@ -1262,8 +1262,6 @@ _sfx:
|
||||||
note: "الملاحظات"
|
note: "الملاحظات"
|
||||||
noteMy: "ملاحظتي"
|
noteMy: "ملاحظتي"
|
||||||
notification: "الإشعارات"
|
notification: "الإشعارات"
|
||||||
antenna: "الهوائيات"
|
|
||||||
channel: "إشعارات القنات"
|
|
||||||
_ago:
|
_ago:
|
||||||
future: "المستقبَل"
|
future: "المستقبَل"
|
||||||
justNow: "اللحظة"
|
justNow: "اللحظة"
|
||||||
|
@ -1566,6 +1564,10 @@ _webhookSettings:
|
||||||
active: "مُفعّل"
|
active: "مُفعّل"
|
||||||
_events:
|
_events:
|
||||||
reaction: "عند التفاعل"
|
reaction: "عند التفاعل"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "البريد الإلكتروني "
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "علِق"
|
suspend: "علِق"
|
||||||
deleteDriveFile: "حُذف الملف"
|
deleteDriveFile: "حُذف الملف"
|
||||||
|
|
|
@ -1033,8 +1033,6 @@ _sfx:
|
||||||
note: "নোটগুলি"
|
note: "নোটগুলি"
|
||||||
noteMy: "নোট (আপনার)"
|
noteMy: "নোট (আপনার)"
|
||||||
notification: "বিজ্ঞপ্তি"
|
notification: "বিজ্ঞপ্তি"
|
||||||
antenna: "অ্যান্টেনাগুলি"
|
|
||||||
channel: "চ্যানেলের বিজ্ঞপ্তি"
|
|
||||||
_ago:
|
_ago:
|
||||||
future: "ভবিষ্যৎ"
|
future: "ভবিষ্যৎ"
|
||||||
justNow: "এইমাত্র"
|
justNow: "এইমাত্র"
|
||||||
|
@ -1346,6 +1344,10 @@ _deck:
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
name: "নাম"
|
name: "নাম"
|
||||||
active: "চালু"
|
active: "চালু"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "ইমেইল"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "স্থগিত করা"
|
suspend: "স্থগিত করা"
|
||||||
resetPassword: "পাসওয়ার্ড রিসেট করুন"
|
resetPassword: "পাসওয়ার্ড রিসেট করুন"
|
||||||
|
|
|
@ -1893,8 +1893,6 @@ _sfx:
|
||||||
note: "Notes"
|
note: "Notes"
|
||||||
noteMy: "Nota (per mi)"
|
noteMy: "Nota (per mi)"
|
||||||
notification: "Notificacions"
|
notification: "Notificacions"
|
||||||
antenna: "Antenes"
|
|
||||||
channel: "Notificacions dels canals"
|
|
||||||
reaction: "Quan se selecciona una reacció "
|
reaction: "Quan se selecciona una reacció "
|
||||||
_soundSettings:
|
_soundSettings:
|
||||||
driveFile: "Fer servir un fitxer d'àudio del disc"
|
driveFile: "Fer servir un fitxer d'àudio del disc"
|
||||||
|
@ -2225,6 +2223,10 @@ _deck:
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
name: "Nom"
|
name: "Nom"
|
||||||
active: "Activat"
|
active: "Activat"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "Correu electrònic"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "Suspèn"
|
suspend: "Suspèn"
|
||||||
resetPassword: "Restableix la contrasenya"
|
resetPassword: "Restableix la contrasenya"
|
||||||
|
|
|
@ -1645,8 +1645,6 @@ _sfx:
|
||||||
note: "Poznámky"
|
note: "Poznámky"
|
||||||
noteMy: "Moje poznámka"
|
noteMy: "Moje poznámka"
|
||||||
notification: "Oznámení"
|
notification: "Oznámení"
|
||||||
antenna: "Antény"
|
|
||||||
channel: "Oznámení kanálu"
|
|
||||||
_ago:
|
_ago:
|
||||||
future: "Budoucí"
|
future: "Budoucí"
|
||||||
justNow: "Teď"
|
justNow: "Teď"
|
||||||
|
@ -2022,6 +2020,10 @@ _webhookSettings:
|
||||||
renote: "Při renotaci poznámky"
|
renote: "Při renotaci poznámky"
|
||||||
reaction: "Při obdržení reakce"
|
reaction: "Při obdržení reakce"
|
||||||
mention: "Při zmínce"
|
mention: "Při zmínce"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "Email"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "Zmrazit"
|
suspend: "Zmrazit"
|
||||||
resetPassword: "Resetovat heslo"
|
resetPassword: "Resetovat heslo"
|
||||||
|
|
|
@ -1800,8 +1800,6 @@ _sfx:
|
||||||
note: "Notizen"
|
note: "Notizen"
|
||||||
noteMy: "Meine Notizen"
|
noteMy: "Meine Notizen"
|
||||||
notification: "Benachrichtigungen"
|
notification: "Benachrichtigungen"
|
||||||
antenna: "Antennen"
|
|
||||||
channel: "Kanalbenachrichtigung"
|
|
||||||
_ago:
|
_ago:
|
||||||
future: "Zukunft"
|
future: "Zukunft"
|
||||||
justNow: "Gerade eben"
|
justNow: "Gerade eben"
|
||||||
|
@ -2203,6 +2201,10 @@ _webhookSettings:
|
||||||
renote: "Wenn du ein Renote erhältst"
|
renote: "Wenn du ein Renote erhältst"
|
||||||
reaction: "Wenn du eine Reaktion erhältst"
|
reaction: "Wenn du eine Reaktion erhältst"
|
||||||
mention: "Wenn du erwähnt wirst"
|
mention: "Wenn du erwähnt wirst"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "Email"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
createRole: "Rolle erstellt"
|
createRole: "Rolle erstellt"
|
||||||
deleteRole: "Rolle gelöscht"
|
deleteRole: "Rolle gelöscht"
|
||||||
|
|
|
@ -301,8 +301,6 @@ _theme:
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "Σημειώματα"
|
note: "Σημειώματα"
|
||||||
notification: "Ειδοποιήσεις"
|
notification: "Ειδοποιήσεις"
|
||||||
antenna: "Αντένες"
|
|
||||||
channel: "Ειδοποιήσεις καναλιών"
|
|
||||||
_ago:
|
_ago:
|
||||||
future: "Μελλοντικό"
|
future: "Μελλοντικό"
|
||||||
justNow: "Μόλις τώρα"
|
justNow: "Μόλις τώρα"
|
||||||
|
|
|
@ -108,7 +108,7 @@ enterEmoji: "Enter an emoji"
|
||||||
renote: "Renote"
|
renote: "Renote"
|
||||||
unrenote: "Remove renote"
|
unrenote: "Remove renote"
|
||||||
renoted: "Renoted."
|
renoted: "Renoted."
|
||||||
renotedToX: "Renote from {name} users。"
|
renotedToX: "Renote to {name}."
|
||||||
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"
|
||||||
|
@ -125,8 +125,8 @@ add: "Add"
|
||||||
reaction: "Reactions"
|
reaction: "Reactions"
|
||||||
reactions: "Reactions"
|
reactions: "Reactions"
|
||||||
emojiPicker: "Emoji picker"
|
emojiPicker: "Emoji picker"
|
||||||
pinnedEmojisForReactionSettingDescription: "Set the emojis which should be pinned and displayed immediately when reacting."
|
pinnedEmojisForReactionSettingDescription: "Set the emojis to be pinned and displayed when reacting."
|
||||||
pinnedEmojisSettingDescription: "Set the emojis to be pinned and displayed when viewing emoji picker"
|
pinnedEmojisSettingDescription: "Set the emojis to be pinned and displayed when viewing emoji picker."
|
||||||
emojiPickerDisplay: "Emoji picker display"
|
emojiPickerDisplay: "Emoji picker display"
|
||||||
overwriteFromPinnedEmojisForReaction: "Override from reaction settings"
|
overwriteFromPinnedEmojisForReaction: "Override from reaction settings"
|
||||||
overwriteFromPinnedEmojis: "Override from general settings"
|
overwriteFromPinnedEmojis: "Override from general settings"
|
||||||
|
@ -180,6 +180,10 @@ addAccount: "Add account"
|
||||||
reloadAccountsList: "Reload account list"
|
reloadAccountsList: "Reload account list"
|
||||||
loginFailed: "Failed to sign in"
|
loginFailed: "Failed to sign in"
|
||||||
showOnRemote: "View on remote instance"
|
showOnRemote: "View on remote instance"
|
||||||
|
continueOnRemote: "リモートで続行"
|
||||||
|
chooseServerOnMisskeyHub: "Choose a server from the Misskey Hub"
|
||||||
|
specifyServerHost: "Specify a server host directly"
|
||||||
|
inputHostName: "Enter the domain"
|
||||||
general: "General"
|
general: "General"
|
||||||
wallpaper: "Wallpaper"
|
wallpaper: "Wallpaper"
|
||||||
setWallpaper: "Set wallpaper"
|
setWallpaper: "Set wallpaper"
|
||||||
|
@ -316,6 +320,7 @@ selectFile: "Select a file"
|
||||||
selectFiles: "Select files"
|
selectFiles: "Select files"
|
||||||
selectFolder: "Select a folder"
|
selectFolder: "Select a folder"
|
||||||
selectFolders: "Select folders"
|
selectFolders: "Select folders"
|
||||||
|
fileNotSelected: ""
|
||||||
renameFile: "Rename file"
|
renameFile: "Rename file"
|
||||||
folderName: "Folder name"
|
folderName: "Folder name"
|
||||||
createFolder: "Create a folder"
|
createFolder: "Create a folder"
|
||||||
|
@ -476,6 +481,7 @@ noMessagesYet: "No messages yet"
|
||||||
newMessageExists: "There are new messages"
|
newMessageExists: "There are new messages"
|
||||||
onlyOneFileCanBeAttached: "You can only attach one file to a message"
|
onlyOneFileCanBeAttached: "You can only attach one file to a message"
|
||||||
signinRequired: "Please register or sign in before continuing"
|
signinRequired: "Please register or sign in before continuing"
|
||||||
|
signinOrContinueOnRemote: "To continue, you need to move your server or sign up / log in to this server."
|
||||||
invitations: "Invites"
|
invitations: "Invites"
|
||||||
invitationCode: "Invitation code"
|
invitationCode: "Invitation code"
|
||||||
checking: "Checking..."
|
checking: "Checking..."
|
||||||
|
@ -836,6 +842,7 @@ administration: "Management"
|
||||||
accounts: "Accounts"
|
accounts: "Accounts"
|
||||||
switch: "Switch"
|
switch: "Switch"
|
||||||
noMaintainerInformationWarning: "Maintainer information is not configured."
|
noMaintainerInformationWarning: "Maintainer information is not configured."
|
||||||
|
noInquiryUrlWarning: "Inquiry URL isn’t set"
|
||||||
noBotProtectionWarning: "Bot protection is not configured."
|
noBotProtectionWarning: "Bot protection is not configured."
|
||||||
configure: "Configure"
|
configure: "Configure"
|
||||||
postToGallery: "Create new gallery post"
|
postToGallery: "Create new gallery post"
|
||||||
|
@ -1025,6 +1032,7 @@ thisPostMayBeAnnoyingHome: "Post to home timeline"
|
||||||
thisPostMayBeAnnoyingCancel: "Cancel"
|
thisPostMayBeAnnoyingCancel: "Cancel"
|
||||||
thisPostMayBeAnnoyingIgnore: "Post anyway"
|
thisPostMayBeAnnoyingIgnore: "Post anyway"
|
||||||
collapseRenotes: "Collapse renotes you've already seen"
|
collapseRenotes: "Collapse renotes you've already seen"
|
||||||
|
collapseRenotesDescription: "Collapse notes that you've reacted to or renoted before."
|
||||||
internalServerError: "Internal Server Error"
|
internalServerError: "Internal Server Error"
|
||||||
internalServerErrorDescription: "The server has run into an unexpected error."
|
internalServerErrorDescription: "The server has run into an unexpected error."
|
||||||
copyErrorInfo: "Copy error details"
|
copyErrorInfo: "Copy error details"
|
||||||
|
@ -1239,6 +1247,9 @@ keepOriginalFilenameDescription: "If you turn off this setting, files names will
|
||||||
noDescription: "There is not the explanation"
|
noDescription: "There is not the explanation"
|
||||||
alwaysConfirmFollow: "Always confirm when following"
|
alwaysConfirmFollow: "Always confirm when following"
|
||||||
inquiry: "Contact"
|
inquiry: "Contact"
|
||||||
|
tryAgain: "Please try again later"
|
||||||
|
confirmWhenRevealingSensitiveMedia: "Confirm when revealing sensitive media"
|
||||||
|
sensitiveMediaRevealConfirm: "This might be a sensitive media. Are you sure to reveal?"
|
||||||
_delivery:
|
_delivery:
|
||||||
status: "Delivery status"
|
status: "Delivery status"
|
||||||
stop: "Suspended"
|
stop: "Suspended"
|
||||||
|
@ -1373,6 +1384,8 @@ _serverSettings:
|
||||||
fanoutTimelineDescription: "Greatly increases performance of timeline retrieval and reduces load on the database when enabled. In exchange, memory usage of Redis will increase. Consider disabling this in case of low server memory or server instability."
|
fanoutTimelineDescription: "Greatly increases performance of timeline retrieval and reduces load on the database when enabled. In exchange, memory usage of Redis will increase. Consider disabling this in case of low server memory or server instability."
|
||||||
fanoutTimelineDbFallback: "Fallback to database"
|
fanoutTimelineDbFallback: "Fallback to database"
|
||||||
fanoutTimelineDbFallbackDescription: "When enabled, the timeline will fall back to the database for additional queries if the timeline is not cached. Disabling it further reduces the server load by eliminating the fallback process, but limits the range of timelines that can be retrieved."
|
fanoutTimelineDbFallbackDescription: "When enabled, the timeline will fall back to the database for additional queries if the timeline is not cached. Disabling it further reduces the server load by eliminating the fallback process, but limits the range of timelines that can be retrieved."
|
||||||
|
inquiryUrl: "Query URL"
|
||||||
|
inquiryUrlDescription: "Specify a URL for the inquiry form to the server maintainer or a web page for the contact information."
|
||||||
_accountMigration:
|
_accountMigration:
|
||||||
moveFrom: "Migrate another account to this one"
|
moveFrom: "Migrate another account to this one"
|
||||||
moveFromSub: "Create alias to another account"
|
moveFromSub: "Create alias to another account"
|
||||||
|
@ -1689,6 +1702,7 @@ _role:
|
||||||
canManageAvatarDecorations: "Manage avatar decorations"
|
canManageAvatarDecorations: "Manage avatar decorations"
|
||||||
driveCapacity: "Drive capacity"
|
driveCapacity: "Drive capacity"
|
||||||
alwaysMarkNsfw: "Always mark files as NSFW"
|
alwaysMarkNsfw: "Always mark files as NSFW"
|
||||||
|
canUpdateBioMedia: "Allow to edit an icon or a banner image"
|
||||||
pinMax: "Maximum number of pinned notes"
|
pinMax: "Maximum number of pinned notes"
|
||||||
antennaMax: "Maximum number of antennas"
|
antennaMax: "Maximum number of antennas"
|
||||||
wordMuteMax: "Maximum number of characters allowed in word mutes"
|
wordMuteMax: "Maximum number of characters allowed in word mutes"
|
||||||
|
@ -1932,8 +1946,6 @@ _sfx:
|
||||||
note: "New note"
|
note: "New note"
|
||||||
noteMy: "Own note"
|
noteMy: "Own note"
|
||||||
notification: "Notifications"
|
notification: "Notifications"
|
||||||
antenna: "Antennas"
|
|
||||||
channel: "Channel notifications"
|
|
||||||
reaction: "On choosing a reaction"
|
reaction: "On choosing a reaction"
|
||||||
_soundSettings:
|
_soundSettings:
|
||||||
driveFile: "Use an audio file in Drive."
|
driveFile: "Use an audio file in Drive."
|
||||||
|
@ -2059,7 +2071,7 @@ _permissions:
|
||||||
"read:admin:invite-codes": "View invite codes"
|
"read:admin:invite-codes": "View invite codes"
|
||||||
"write:admin:announcements": "Manage announcements"
|
"write:admin:announcements": "Manage announcements"
|
||||||
"read:admin:announcements": "View announcements"
|
"read:admin:announcements": "View announcements"
|
||||||
"write:admin:avatar-decorations": "Manage avatar decorations"
|
"write:admin:avatar-decorations": "Can manage avatar decorations"
|
||||||
"read:admin:avatar-decorations": "View avatar decorations"
|
"read:admin:avatar-decorations": "View avatar decorations"
|
||||||
"write:admin:federation": "Manage federation data"
|
"write:admin:federation": "Manage federation data"
|
||||||
"write:admin:account": "Manage user account"
|
"write:admin:account": "Manage user account"
|
||||||
|
@ -2358,6 +2370,7 @@ _deck:
|
||||||
alwaysShowMainColumn: "Always show main column"
|
alwaysShowMainColumn: "Always show main column"
|
||||||
columnAlign: "Align columns"
|
columnAlign: "Align columns"
|
||||||
addColumn: "Add column"
|
addColumn: "Add column"
|
||||||
|
newNoteNotificationSettings: "Notification setting for new notes"
|
||||||
configureColumn: "Column settings"
|
configureColumn: "Column settings"
|
||||||
swapLeft: "Swap with the left column"
|
swapLeft: "Swap with the left column"
|
||||||
swapRight: "Swap with the right column"
|
swapRight: "Swap with the right column"
|
||||||
|
@ -2396,6 +2409,7 @@ _drivecleaner:
|
||||||
orderByCreatedAtAsc: "Ascending Dates"
|
orderByCreatedAtAsc: "Ascending Dates"
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
createWebhook: "Create Webhook"
|
createWebhook: "Create Webhook"
|
||||||
|
modifyWebhook: "Modify Webhook"
|
||||||
name: "Name"
|
name: "Name"
|
||||||
secret: "Secret"
|
secret: "Secret"
|
||||||
events: "Webhook Events"
|
events: "Webhook Events"
|
||||||
|
@ -2408,6 +2422,25 @@ _webhookSettings:
|
||||||
renote: "When renoted"
|
renote: "When renoted"
|
||||||
reaction: "When receiving a reaction"
|
reaction: "When receiving a reaction"
|
||||||
mention: "When being mentioned"
|
mention: "When being mentioned"
|
||||||
|
_systemEvents:
|
||||||
|
abuseReport: "When received a new abuse report"
|
||||||
|
abuseReportResolved: "When resolved abuse reports"
|
||||||
|
deleteConfirm: "Are you sure you want to delete the Webhook?"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
createRecipient: "Add a recipient for abuse reports"
|
||||||
|
modifyRecipient: "Edit a recipient for abuse reports"
|
||||||
|
recipientType: "Notification type"
|
||||||
|
_recipientType:
|
||||||
|
mail: "Email"
|
||||||
|
webhook: "Webhook"
|
||||||
|
_captions:
|
||||||
|
mail: "Send the email to moderators' email addresses when you receive abuse."
|
||||||
|
webhook: "Send a notification to SystemWebhook when you receive or resolve abuse."
|
||||||
|
keywords: "Keywords"
|
||||||
|
notifiedUser: "Users to notify"
|
||||||
|
notifiedWebhook: "Webhook to use"
|
||||||
|
deleteConfirm: "Are you sure that you want to delete the notification recipient?"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
createRole: "Role created"
|
createRole: "Role created"
|
||||||
deleteRole: "Role deleted"
|
deleteRole: "Role deleted"
|
||||||
|
@ -2445,6 +2478,12 @@ _moderationLogTypes:
|
||||||
deleteAvatarDecoration: "Avatar decoration deleted"
|
deleteAvatarDecoration: "Avatar decoration deleted"
|
||||||
unsetUserAvatar: "Unset this user's avatar"
|
unsetUserAvatar: "Unset this user's avatar"
|
||||||
unsetUserBanner: "Unset this user's banner"
|
unsetUserBanner: "Unset this user's banner"
|
||||||
|
createSystemWebhook: "Create SystemWebhook"
|
||||||
|
updateSystemWebhook: "Update SystemWebHook"
|
||||||
|
deleteSystemWebhook: "Delete SystemWebhook"
|
||||||
|
createAbuseReportNotificationRecipient: "Create a recipient for abuse reports"
|
||||||
|
updateAbuseReportNotificationRecipient: "Update recipients for abuse reports"
|
||||||
|
deleteAbuseReportNotificationRecipient: "Delete a recipient for abuse reports"
|
||||||
_fileViewer:
|
_fileViewer:
|
||||||
title: "File details"
|
title: "File details"
|
||||||
type: "File type"
|
type: "File type"
|
||||||
|
|
|
@ -302,7 +302,7 @@ location: "Lugar"
|
||||||
theme: "Tema"
|
theme: "Tema"
|
||||||
themeForLightMode: "Tema para usar en Modo Linterna"
|
themeForLightMode: "Tema para usar en Modo Linterna"
|
||||||
themeForDarkMode: "Tema para usar en Modo Oscuro"
|
themeForDarkMode: "Tema para usar en Modo Oscuro"
|
||||||
light: "Linterna"
|
light: "Claro"
|
||||||
dark: "Oscuro"
|
dark: "Oscuro"
|
||||||
lightThemes: "Tema claro"
|
lightThemes: "Tema claro"
|
||||||
darkThemes: "Tema oscuro"
|
darkThemes: "Tema oscuro"
|
||||||
|
@ -1920,8 +1920,6 @@ _sfx:
|
||||||
note: "Notas"
|
note: "Notas"
|
||||||
noteMy: "Nota (a mí mismo)"
|
noteMy: "Nota (a mí mismo)"
|
||||||
notification: "Notificaciones"
|
notification: "Notificaciones"
|
||||||
antenna: "Antena receptora"
|
|
||||||
channel: "Notificaciones del canal"
|
|
||||||
reaction: "Al seleccionar una reacción"
|
reaction: "Al seleccionar una reacción"
|
||||||
_soundSettings:
|
_soundSettings:
|
||||||
driveFile: "Usar un archivo de audio en Drive"
|
driveFile: "Usar un archivo de audio en Drive"
|
||||||
|
@ -2394,6 +2392,10 @@ _webhookSettings:
|
||||||
renote: "Cuando reciba un \"re-note\""
|
renote: "Cuando reciba un \"re-note\""
|
||||||
reaction: "Cuando se recibe una reacción"
|
reaction: "Cuando se recibe una reacción"
|
||||||
mention: "Cuando hay una mención"
|
mention: "Cuando hay una mención"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "Correo"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
createRole: "Rol creado"
|
createRole: "Rol creado"
|
||||||
deleteRole: "Rol eliminado"
|
deleteRole: "Rol eliminado"
|
||||||
|
|
|
@ -1712,8 +1712,6 @@ _sfx:
|
||||||
note: "Nouvelle note"
|
note: "Nouvelle note"
|
||||||
noteMy: "Ma note"
|
noteMy: "Ma note"
|
||||||
notification: "Notifications"
|
notification: "Notifications"
|
||||||
antenna: "Réception de l’antenne"
|
|
||||||
channel: "Notifications de canal"
|
|
||||||
reaction: "Lors de la sélection de la réaction"
|
reaction: "Lors de la sélection de la réaction"
|
||||||
_soundSettings:
|
_soundSettings:
|
||||||
driveFile: "Utiliser un effet sonore sur le Disque"
|
driveFile: "Utiliser un effet sonore sur le Disque"
|
||||||
|
@ -2073,6 +2071,10 @@ _drivecleaner:
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
name: "Nom"
|
name: "Nom"
|
||||||
active: "Activé"
|
active: "Activé"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "E-mail "
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
createRole: "Rôle créé"
|
createRole: "Rôle créé"
|
||||||
deleteRole: "Rôle supprimé"
|
deleteRole: "Rôle supprimé"
|
||||||
|
|
|
@ -180,6 +180,10 @@ addAccount: "Tambahkan akun"
|
||||||
reloadAccountsList: "Muat ulang daftar akun"
|
reloadAccountsList: "Muat ulang daftar akun"
|
||||||
loginFailed: "Gagal untuk masuk"
|
loginFailed: "Gagal untuk masuk"
|
||||||
showOnRemote: "Lihat profil asli"
|
showOnRemote: "Lihat profil asli"
|
||||||
|
continueOnRemote: "Lihat di peladen asal"
|
||||||
|
chooseServerOnMisskeyHub: "Pilih peladen dari Misskey Hub"
|
||||||
|
specifyServerHost: "Tentukan domain peladen"
|
||||||
|
inputHostName: "Masukkan nama domain"
|
||||||
general: "Umum"
|
general: "Umum"
|
||||||
wallpaper: "Wallpaper"
|
wallpaper: "Wallpaper"
|
||||||
setWallpaper: "Atur wallpaper"
|
setWallpaper: "Atur wallpaper"
|
||||||
|
@ -316,6 +320,7 @@ selectFile: "Pilih berkas"
|
||||||
selectFiles: "Pilih berkas"
|
selectFiles: "Pilih berkas"
|
||||||
selectFolder: "Pilih folder"
|
selectFolder: "Pilih folder"
|
||||||
selectFolders: "Pilih folder"
|
selectFolders: "Pilih folder"
|
||||||
|
fileNotSelected: "Tidak ada file yang dipilih"
|
||||||
renameFile: "Ubah nama berkas"
|
renameFile: "Ubah nama berkas"
|
||||||
folderName: "Nama folder"
|
folderName: "Nama folder"
|
||||||
createFolder: "Buat folder"
|
createFolder: "Buat folder"
|
||||||
|
@ -1239,6 +1244,7 @@ keepOriginalFilenameDescription: "Apabila pengaturan ini dimatikan, nama berkas
|
||||||
noDescription: "Tidak ada deskripsi"
|
noDescription: "Tidak ada deskripsi"
|
||||||
alwaysConfirmFollow: "Selalu konfirmasi ketika mengikuti"
|
alwaysConfirmFollow: "Selalu konfirmasi ketika mengikuti"
|
||||||
inquiry: "Hubungi kami"
|
inquiry: "Hubungi kami"
|
||||||
|
tryAgain: "Silahkan coba lagi."
|
||||||
_delivery:
|
_delivery:
|
||||||
status: "Status pengiriman"
|
status: "Status pengiriman"
|
||||||
stop: "Ditangguhkan"
|
stop: "Ditangguhkan"
|
||||||
|
@ -1739,7 +1745,7 @@ _emailUnavailable:
|
||||||
smtp: "Peladen alamat surel ini tidak merespon"
|
smtp: "Peladen alamat surel ini tidak merespon"
|
||||||
banned: "Kamu tidak dapat mendaftar dengan alamat surel ini"
|
banned: "Kamu tidak dapat mendaftar dengan alamat surel ini"
|
||||||
_ffVisibility:
|
_ffVisibility:
|
||||||
public: "Terbitkan"
|
public: "Publik"
|
||||||
followers: "Tampil untuk pengikut saja"
|
followers: "Tampil untuk pengikut saja"
|
||||||
private: "Tersembunyi"
|
private: "Tersembunyi"
|
||||||
_signup:
|
_signup:
|
||||||
|
@ -1932,8 +1938,6 @@ _sfx:
|
||||||
note: "Catatan"
|
note: "Catatan"
|
||||||
noteMy: "Catatan (Saya)"
|
noteMy: "Catatan (Saya)"
|
||||||
notification: "Notifikasi"
|
notification: "Notifikasi"
|
||||||
antenna: "Penerimaan Antenna"
|
|
||||||
channel: "Notifikasi Kanal"
|
|
||||||
reaction: "Ketika memilih reaksi"
|
reaction: "Ketika memilih reaksi"
|
||||||
_soundSettings:
|
_soundSettings:
|
||||||
driveFile: "Menggunakan berkas audio dalam Drive"
|
driveFile: "Menggunakan berkas audio dalam Drive"
|
||||||
|
@ -2396,6 +2400,7 @@ _drivecleaner:
|
||||||
orderByCreatedAtAsc: "Tanggal (Naik)"
|
orderByCreatedAtAsc: "Tanggal (Naik)"
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
createWebhook: "Buat Webhook"
|
createWebhook: "Buat Webhook"
|
||||||
|
modifyWebhook: "Sunting Webhook"
|
||||||
name: "Nama"
|
name: "Nama"
|
||||||
secret: "Secret"
|
secret: "Secret"
|
||||||
events: "Webhook Events"
|
events: "Webhook Events"
|
||||||
|
@ -2408,6 +2413,11 @@ _webhookSettings:
|
||||||
renote: "Ketika direnote"
|
renote: "Ketika direnote"
|
||||||
reaction: "Ketika menerima reaksi"
|
reaction: "Ketika menerima reaksi"
|
||||||
mention: "Ketika sedang disebut"
|
mention: "Ketika sedang disebut"
|
||||||
|
deleteConfirm: "Apakah kamu yakin ingin menghapus Webhook?"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "Surel"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
createRole: "Peran telah dibuat"
|
createRole: "Peran telah dibuat"
|
||||||
deleteRole: "Peran telah dihapus"
|
deleteRole: "Peran telah dihapus"
|
||||||
|
|
|
@ -9392,6 +9392,10 @@ export interface Locale extends ILocale {
|
||||||
* ユーザーからの通報を処理したとき
|
* ユーザーからの通報を処理したとき
|
||||||
*/
|
*/
|
||||||
"abuseReportResolved": string;
|
"abuseReportResolved": string;
|
||||||
|
/**
|
||||||
|
* ユーザーが作成されたとき
|
||||||
|
*/
|
||||||
|
"userCreated": string;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Webhookを削除しますか?
|
* Webhookを削除しますか?
|
||||||
|
|
|
@ -108,11 +108,14 @@ enterEmoji: "Inserisci emoji"
|
||||||
renote: "Rinota"
|
renote: "Rinota"
|
||||||
unrenote: "Elimina la Rinota"
|
unrenote: "Elimina la Rinota"
|
||||||
renoted: "Rinotata!"
|
renoted: "Rinotata!"
|
||||||
|
renotedToX: "Rinota da {name}."
|
||||||
cantRenote: "È impossibile rinotare questa nota."
|
cantRenote: "È impossibile rinotare questa nota."
|
||||||
cantReRenote: "È impossibile rinotare una Rinota."
|
cantReRenote: "È impossibile rinotare una Rinota."
|
||||||
quote: "Citazione"
|
quote: "Citazione"
|
||||||
inChannelRenote: "Rinota nel canale"
|
inChannelRenote: "Rinota nel canale"
|
||||||
inChannelQuote: "Cita nel canale"
|
inChannelQuote: "Cita nel canale"
|
||||||
|
renoteToChannel: "Rinota al canale"
|
||||||
|
renoteToOtherChannel: "Rinota a un altro canale"
|
||||||
pinnedNote: "Nota in primo piano"
|
pinnedNote: "Nota in primo piano"
|
||||||
pinned: "Fissa sul profilo"
|
pinned: "Fissa sul profilo"
|
||||||
you: "Tu"
|
you: "Tu"
|
||||||
|
@ -177,6 +180,10 @@ addAccount: "Aggiungi profilo"
|
||||||
reloadAccountsList: "Ricarica l'elenco dei profili"
|
reloadAccountsList: "Ricarica l'elenco dei profili"
|
||||||
loginFailed: "Accesso non riuscito"
|
loginFailed: "Accesso non riuscito"
|
||||||
showOnRemote: "Leggi sull'istanza remota"
|
showOnRemote: "Leggi sull'istanza remota"
|
||||||
|
continueOnRemote: "Continua da remoto"
|
||||||
|
chooseServerOnMisskeyHub: "Scegli l'istanza sul sito Misskey Hub"
|
||||||
|
specifyServerHost: "Indica l'indirizzo dell'istanza"
|
||||||
|
inputHostName: "Digita il nome del dominio "
|
||||||
general: "Generali"
|
general: "Generali"
|
||||||
wallpaper: "Sfondo"
|
wallpaper: "Sfondo"
|
||||||
setWallpaper: "Imposta sfondo"
|
setWallpaper: "Imposta sfondo"
|
||||||
|
@ -313,6 +320,7 @@ selectFile: "Scelta allegato"
|
||||||
selectFiles: "Scelta allegato"
|
selectFiles: "Scelta allegato"
|
||||||
selectFolder: "Seleziona cartella"
|
selectFolder: "Seleziona cartella"
|
||||||
selectFolders: "Seleziona cartella"
|
selectFolders: "Seleziona cartella"
|
||||||
|
fileNotSelected: "Nessun file selezionato"
|
||||||
renameFile: "Rinomina file"
|
renameFile: "Rinomina file"
|
||||||
folderName: "Nome della cartella"
|
folderName: "Nome della cartella"
|
||||||
createFolder: "Nuova cartella"
|
createFolder: "Nuova cartella"
|
||||||
|
@ -468,10 +476,12 @@ retype: "Conferma"
|
||||||
noteOf: "Note di {user}"
|
noteOf: "Note di {user}"
|
||||||
quoteAttached: "Citazione allegata"
|
quoteAttached: "Citazione allegata"
|
||||||
quoteQuestion: "Vuoi aggiungere una citazione?"
|
quoteQuestion: "Vuoi aggiungere una citazione?"
|
||||||
|
attachAsFileQuestion: "Il testo copiato eccede le dimensioni, vuoi allegarlo?"
|
||||||
noMessagesYet: "Ancora nessuna chat"
|
noMessagesYet: "Ancora nessuna chat"
|
||||||
newMessageExists: "Hai ricevuto un nuovo messaggio"
|
newMessageExists: "Hai ricevuto un nuovo messaggio"
|
||||||
onlyOneFileCanBeAttached: "È possibile allegare al messaggio soltanto uno file"
|
onlyOneFileCanBeAttached: "È possibile allegare al messaggio soltanto uno file"
|
||||||
signinRequired: "Occorre avere un profilo registrato su questa istanza"
|
signinRequired: "Occorre avere un profilo registrato su questa istanza"
|
||||||
|
signinOrContinueOnRemote: "Per continuare, devi accedere alla tua istanza o registrarti su questa e poi accedere"
|
||||||
invitations: "Invita"
|
invitations: "Invita"
|
||||||
invitationCode: "Codice di invito"
|
invitationCode: "Codice di invito"
|
||||||
checking: "Confermando"
|
checking: "Confermando"
|
||||||
|
@ -695,7 +705,7 @@ reporterOrigin: "Segnalazione da"
|
||||||
forwardReport: "Inoltro di un report a un'istanza remota."
|
forwardReport: "Inoltro di un report a un'istanza remota."
|
||||||
forwardReportIsAnonymous: "L'istanza remota non vedrà le tue informazioni, apparirai come profilo di sistema, anonimo."
|
forwardReportIsAnonymous: "L'istanza remota non vedrà le tue informazioni, apparirai come profilo di sistema, anonimo."
|
||||||
send: "Inviare"
|
send: "Inviare"
|
||||||
abuseMarkAsResolved: "Contrassegna la segnalazione come risolta"
|
abuseMarkAsResolved: "Risolvi segnalazione"
|
||||||
openInNewTab: "Apri in una nuova scheda"
|
openInNewTab: "Apri in una nuova scheda"
|
||||||
openInSideView: "Apri in vista laterale"
|
openInSideView: "Apri in vista laterale"
|
||||||
defaultNavigationBehaviour: "Navigazione preimpostata"
|
defaultNavigationBehaviour: "Navigazione preimpostata"
|
||||||
|
@ -832,6 +842,7 @@ administration: "Gestione"
|
||||||
accounts: "Profilo"
|
accounts: "Profilo"
|
||||||
switch: "Cambia"
|
switch: "Cambia"
|
||||||
noMaintainerInformationWarning: "Mancano le informazioni sull'amministratore."
|
noMaintainerInformationWarning: "Mancano le informazioni sull'amministratore."
|
||||||
|
noInquiryUrlWarning: "Non è stata impostata la URL di contatto"
|
||||||
noBotProtectionWarning: "Non è stata impostata alcuna protezione dai Bot"
|
noBotProtectionWarning: "Non è stata impostata alcuna protezione dai Bot"
|
||||||
configure: "Imposta"
|
configure: "Imposta"
|
||||||
postToGallery: "Pubblicare nella galleria"
|
postToGallery: "Pubblicare nella galleria"
|
||||||
|
@ -1021,6 +1032,7 @@ thisPostMayBeAnnoyingHome: "Pubblica sulla timeline principale"
|
||||||
thisPostMayBeAnnoyingCancel: "Annulla"
|
thisPostMayBeAnnoyingCancel: "Annulla"
|
||||||
thisPostMayBeAnnoyingIgnore: "Pubblica lo stesso"
|
thisPostMayBeAnnoyingIgnore: "Pubblica lo stesso"
|
||||||
collapseRenotes: "Comprimi le Rinota già viste"
|
collapseRenotes: "Comprimi le Rinota già viste"
|
||||||
|
collapseRenotesDescription: "Comprimi le Note con cui hai già interagito."
|
||||||
internalServerError: "Errore interno del server"
|
internalServerError: "Errore interno del server"
|
||||||
internalServerErrorDescription: "Si è verificato un errore imprevisto all'interno del server"
|
internalServerErrorDescription: "Si è verificato un errore imprevisto all'interno del server"
|
||||||
copyErrorInfo: "Copia le informazioni sull'errore"
|
copyErrorInfo: "Copia le informazioni sull'errore"
|
||||||
|
@ -1233,10 +1245,20 @@ useNativeUIForVideoAudioPlayer: "Riprodurre audio/video usando le funzionalità
|
||||||
keepOriginalFilename: "Mantieni il nome file originale"
|
keepOriginalFilename: "Mantieni il nome file originale"
|
||||||
keepOriginalFilenameDescription: "Disattivandola, i file verranno caricati usando nomi casuali."
|
keepOriginalFilenameDescription: "Disattivandola, i file verranno caricati usando nomi casuali."
|
||||||
noDescription: "Manca la descrizione"
|
noDescription: "Manca la descrizione"
|
||||||
|
alwaysConfirmFollow: "Richiedi conferma per i Follow"
|
||||||
|
inquiry: "Contattaci"
|
||||||
|
tryAgain: "Per favore riprova"
|
||||||
|
confirmWhenRevealingSensitiveMedia: "Richiedi conferma prima di mostrare gli allegati espliciti"
|
||||||
|
sensitiveMediaRevealConfirm: "Questo allegato è esplicito, vuoi vederlo?"
|
||||||
_delivery:
|
_delivery:
|
||||||
|
status: "Stato della consegna"
|
||||||
stop: "Sospensione"
|
stop: "Sospensione"
|
||||||
|
resume: "Riprendi la consegna"
|
||||||
_type:
|
_type:
|
||||||
none: "Pubblicazione"
|
none: "Pubblicazione"
|
||||||
|
manuallySuspended: "Sospesa manualmente"
|
||||||
|
goneSuspended: "Sospensione server a causa dell'eliminazione"
|
||||||
|
autoSuspendedForNotResponding: "Sospensione del server a causa di mancata risposta"
|
||||||
_bubbleGame:
|
_bubbleGame:
|
||||||
howToPlay: "Come giocare"
|
howToPlay: "Come giocare"
|
||||||
hold: "Tieni"
|
hold: "Tieni"
|
||||||
|
@ -1362,6 +1384,8 @@ _serverSettings:
|
||||||
fanoutTimelineDescription: "Attivando questa funzionalità migliori notevolmente la capacità delle Timeline di collezionare Note, riducendo il carico sul database. Tuttavia, aumenterà l'impiego di memoria RAM per Redis. Disattiva se il tuo server ha poca RAM o la funzionalità è irregolare."
|
fanoutTimelineDescription: "Attivando questa funzionalità migliori notevolmente la capacità delle Timeline di collezionare Note, riducendo il carico sul database. Tuttavia, aumenterà l'impiego di memoria RAM per Redis. Disattiva se il tuo server ha poca RAM o la funzionalità è irregolare."
|
||||||
fanoutTimelineDbFallback: "Elaborazione dati alternativa"
|
fanoutTimelineDbFallback: "Elaborazione dati alternativa"
|
||||||
fanoutTimelineDbFallbackDescription: "Attivando l'elaborazione alternativa, verrà interrogato ulteriormente il database se la timeline non è nella cache. \nDisattivando, si può ridurre ulteriormente il carico del server, evitando l'elaborazione alternativa, ma limitando l'intervallo recuperabile delle timeline."
|
fanoutTimelineDbFallbackDescription: "Attivando l'elaborazione alternativa, verrà interrogato ulteriormente il database se la timeline non è nella cache. \nDisattivando, si può ridurre ulteriormente il carico del server, evitando l'elaborazione alternativa, ma limitando l'intervallo recuperabile delle timeline."
|
||||||
|
inquiryUrl: "URL di contatto"
|
||||||
|
inquiryUrlDescription: "Specificare l'URL al modulo di contatto, oppure le informazioni con i dati di contatto dell'amministrazione."
|
||||||
_accountMigration:
|
_accountMigration:
|
||||||
moveFrom: "Migra un altro profilo dentro a questo"
|
moveFrom: "Migra un altro profilo dentro a questo"
|
||||||
moveFromSub: "Crea un alias verso un altro profilo remoto"
|
moveFromSub: "Crea un alias verso un altro profilo remoto"
|
||||||
|
@ -1678,6 +1702,7 @@ _role:
|
||||||
canManageAvatarDecorations: "Gestisce le decorazioni di immagini del profilo"
|
canManageAvatarDecorations: "Gestisce le decorazioni di immagini del profilo"
|
||||||
driveCapacity: "Capienza del Drive"
|
driveCapacity: "Capienza del Drive"
|
||||||
alwaysMarkNsfw: "Impostare sempre come esplicito (NSFW)"
|
alwaysMarkNsfw: "Impostare sempre come esplicito (NSFW)"
|
||||||
|
canUpdateBioMedia: "Può aggiornare foto profilo e di testata"
|
||||||
pinMax: "Quantità massima di Note in primo piano"
|
pinMax: "Quantità massima di Note in primo piano"
|
||||||
antennaMax: "Quantità massima di Antenne"
|
antennaMax: "Quantità massima di Antenne"
|
||||||
wordMuteMax: "Lunghezza massima del filtro parole"
|
wordMuteMax: "Lunghezza massima del filtro parole"
|
||||||
|
@ -1696,6 +1721,11 @@ _role:
|
||||||
roleAssignedTo: "Assegnato a ruoli manualmente"
|
roleAssignedTo: "Assegnato a ruoli manualmente"
|
||||||
isLocal: "Profilo locale"
|
isLocal: "Profilo locale"
|
||||||
isRemote: "Profilo remoto"
|
isRemote: "Profilo remoto"
|
||||||
|
isCat: "È un gattino"
|
||||||
|
isBot: "È un bot"
|
||||||
|
isSuspended: "È sospeso"
|
||||||
|
isLocked: "È in stato privato"
|
||||||
|
isExplorable: "Autorizza la pubblicazione nei cataloghi"
|
||||||
createdLessThan: "Profilo creato da meno di N"
|
createdLessThan: "Profilo creato da meno di N"
|
||||||
createdMoreThan: "Profilo creato da più di N"
|
createdMoreThan: "Profilo creato da più di N"
|
||||||
followersLessThanOrEq: "Profilo con N follower o meno"
|
followersLessThanOrEq: "Profilo con N follower o meno"
|
||||||
|
@ -1916,8 +1946,6 @@ _sfx:
|
||||||
note: "Nota"
|
note: "Nota"
|
||||||
noteMy: "Mia nota"
|
noteMy: "Mia nota"
|
||||||
notification: "Notifiche"
|
notification: "Notifiche"
|
||||||
antenna: "Ricezione dell'antenna"
|
|
||||||
channel: "Notifiche di canale"
|
|
||||||
reaction: "Quando seleziono una reazione"
|
reaction: "Quando seleziono una reazione"
|
||||||
_soundSettings:
|
_soundSettings:
|
||||||
driveFile: "Suoni del Drive"
|
driveFile: "Suoni del Drive"
|
||||||
|
@ -2342,6 +2370,7 @@ _deck:
|
||||||
alwaysShowMainColumn: "Mostra sempre la colonna principale"
|
alwaysShowMainColumn: "Mostra sempre la colonna principale"
|
||||||
columnAlign: "Allineare colonne"
|
columnAlign: "Allineare colonne"
|
||||||
addColumn: "Aggiungi colonna"
|
addColumn: "Aggiungi colonna"
|
||||||
|
newNoteNotificationSettings: "Preferenze per le notifiche di nuove Note"
|
||||||
configureColumn: "Impostazioni colonna"
|
configureColumn: "Impostazioni colonna"
|
||||||
swapLeft: "Sposta a sinistra"
|
swapLeft: "Sposta a sinistra"
|
||||||
swapRight: "Sposta a destra"
|
swapRight: "Sposta a destra"
|
||||||
|
@ -2380,6 +2409,7 @@ _drivecleaner:
|
||||||
orderByCreatedAtAsc: "Dal più vecchio al più recente"
|
orderByCreatedAtAsc: "Dal più vecchio al più recente"
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
createWebhook: "Creazione Webhook"
|
createWebhook: "Creazione Webhook"
|
||||||
|
modifyWebhook: "Modifica Webhook"
|
||||||
name: "Nome"
|
name: "Nome"
|
||||||
secret: "Segreto"
|
secret: "Segreto"
|
||||||
events: "Quando eseguire il Webhook"
|
events: "Quando eseguire il Webhook"
|
||||||
|
@ -2392,6 +2422,25 @@ _webhookSettings:
|
||||||
renote: "Quando la Nota è Rinotata"
|
renote: "Quando la Nota è Rinotata"
|
||||||
reaction: "Quando ricevo una reazione"
|
reaction: "Quando ricevo una reazione"
|
||||||
mention: "Quando mi menzionano"
|
mention: "Quando mi menzionano"
|
||||||
|
_systemEvents:
|
||||||
|
abuseReport: "Quando arriva una segnalazione"
|
||||||
|
abuseReportResolved: "Quando una segnalazione è risolta"
|
||||||
|
deleteConfirm: "Vuoi davvero eliminare il Webhook?"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
createRecipient: "Aggiungi destinatario della segnalazione"
|
||||||
|
modifyRecipient: "Modifica destinatario della segnalazione"
|
||||||
|
recipientType: "Tipo di notifica"
|
||||||
|
_recipientType:
|
||||||
|
mail: "Email"
|
||||||
|
webhook: "Webhook"
|
||||||
|
_captions:
|
||||||
|
mail: "Quando ricevi un abuso, notifica l'amministrazione via email"
|
||||||
|
webhook: "Spedire una notifica al SystemWebhook specificato (sia quando si riceve una segnalazione, che quando viene risolta)"
|
||||||
|
keywords: "Parole chiave"
|
||||||
|
notifiedUser: "Profili da notificare"
|
||||||
|
notifiedWebhook: "Webhook da usare"
|
||||||
|
deleteConfirm: "Vuoi davvero rimuovere il destinatario della notifica?"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
createRole: "Ruolo creato"
|
createRole: "Ruolo creato"
|
||||||
deleteRole: "Ruolo eliminato"
|
deleteRole: "Ruolo eliminato"
|
||||||
|
@ -2429,6 +2478,12 @@ _moderationLogTypes:
|
||||||
deleteAvatarDecoration: "Eliminazione decorazione della foto profilo"
|
deleteAvatarDecoration: "Eliminazione decorazione della foto profilo"
|
||||||
unsetUserAvatar: "Rimossa foto profilo"
|
unsetUserAvatar: "Rimossa foto profilo"
|
||||||
unsetUserBanner: "Rimossa intestazione profilo"
|
unsetUserBanner: "Rimossa intestazione profilo"
|
||||||
|
createSystemWebhook: "Crea un SystemWebhook"
|
||||||
|
updateSystemWebhook: "Modifica SystemWebhook"
|
||||||
|
deleteSystemWebhook: "Elimina SystemWebhook"
|
||||||
|
createAbuseReportNotificationRecipient: "Crea destinatario per le notifiche di segnalazioni"
|
||||||
|
updateAbuseReportNotificationRecipient: "Aggiorna destinatario notifiche di segnalazioni"
|
||||||
|
deleteAbuseReportNotificationRecipient: "Elimina destinatario notifiche di segnalazioni"
|
||||||
_fileViewer:
|
_fileViewer:
|
||||||
title: "Dettagli del file"
|
title: "Dettagli del file"
|
||||||
type: "Tipo di file"
|
type: "Tipo di file"
|
||||||
|
@ -2554,6 +2609,8 @@ _urlPreviewSetting:
|
||||||
userAgent: "User-Agent"
|
userAgent: "User-Agent"
|
||||||
userAgentDescription: "Definire con quale User-Agent si intende identificarsi durante l'acquisizione di un'anteprima. Se è vuoto, useremo il valore predefinito."
|
userAgentDescription: "Definire con quale User-Agent si intende identificarsi durante l'acquisizione di un'anteprima. Se è vuoto, useremo il valore predefinito."
|
||||||
summaryProxy: "Endpoint proxy che genera l'anteprima"
|
summaryProxy: "Endpoint proxy che genera l'anteprima"
|
||||||
|
summaryProxyDescription: "Genera anteprime utilizzando un proxy Summaly anziché Misskey."
|
||||||
|
summaryProxyDescription2: "I parametri sono collegano al proxy come stringa query. Se il proxy non li supporta, verranno ignorati."
|
||||||
_mediaControls:
|
_mediaControls:
|
||||||
pip: "Sovraimpressione"
|
pip: "Sovraimpressione"
|
||||||
playbackRate: "Velocità di riproduzione"
|
playbackRate: "Velocità di riproduzione"
|
||||||
|
|
|
@ -2491,6 +2491,7 @@ _webhookSettings:
|
||||||
_systemEvents:
|
_systemEvents:
|
||||||
abuseReport: "ユーザーから通報があったとき"
|
abuseReport: "ユーザーから通報があったとき"
|
||||||
abuseReportResolved: "ユーザーからの通報を処理したとき"
|
abuseReportResolved: "ユーザーからの通報を処理したとき"
|
||||||
|
userCreated: "ユーザーが作成されたとき"
|
||||||
deleteConfirm: "Webhookを削除しますか?"
|
deleteConfirm: "Webhookを削除しますか?"
|
||||||
|
|
||||||
_abuseReport:
|
_abuseReport:
|
||||||
|
|
|
@ -108,6 +108,7 @@ enterEmoji: "絵文字を入れてや"
|
||||||
renote: "リノート"
|
renote: "リノート"
|
||||||
unrenote: "リノートやめる"
|
unrenote: "リノートやめる"
|
||||||
renoted: "リノートしたで。"
|
renoted: "リノートしたで。"
|
||||||
|
renotedToX: "{name}にリノートしたで"
|
||||||
cantRenote: "この投稿はリノートできへんっぽい。"
|
cantRenote: "この投稿はリノートできへんっぽい。"
|
||||||
cantReRenote: "リノート自体はリノートできへんで。"
|
cantReRenote: "リノート自体はリノートできへんで。"
|
||||||
quote: "引用"
|
quote: "引用"
|
||||||
|
@ -313,6 +314,7 @@ selectFile: "ファイル選んでや"
|
||||||
selectFiles: "ファイル選んでや"
|
selectFiles: "ファイル選んでや"
|
||||||
selectFolder: "フォルダ選んでや"
|
selectFolder: "フォルダ選んでや"
|
||||||
selectFolders: "フォルダ選んでや"
|
selectFolders: "フォルダ選んでや"
|
||||||
|
fileNotSelected: "ファイルが選択されてへんで"
|
||||||
renameFile: "ファイル名をいらう"
|
renameFile: "ファイル名をいらう"
|
||||||
folderName: "フォルダー名"
|
folderName: "フォルダー名"
|
||||||
createFolder: "フォルダー作る"
|
createFolder: "フォルダー作る"
|
||||||
|
@ -468,6 +470,7 @@ retype: "もっかい入力"
|
||||||
noteOf: "{user}はんのノート"
|
noteOf: "{user}はんのノート"
|
||||||
quoteAttached: "引用付いとるで"
|
quoteAttached: "引用付いとるで"
|
||||||
quoteQuestion: "引用として添付してもええか?"
|
quoteQuestion: "引用として添付してもええか?"
|
||||||
|
attachAsFileQuestion: "クリップボードのテキストが長すぎるからテキストファイルとして添付してもええか?"
|
||||||
noMessagesYet: "まだチャットはあらへんで"
|
noMessagesYet: "まだチャットはあらへんで"
|
||||||
newMessageExists: "新しいメッセージがきたで"
|
newMessageExists: "新しいメッセージがきたで"
|
||||||
onlyOneFileCanBeAttached: "ごめんな、メッセージに添付できるファイルはひとつだけなんよ。"
|
onlyOneFileCanBeAttached: "ごめんな、メッセージに添付できるファイルはひとつだけなんよ。"
|
||||||
|
@ -832,6 +835,7 @@ administration: "管理"
|
||||||
accounts: "アカウント"
|
accounts: "アカウント"
|
||||||
switch: "切り替え"
|
switch: "切り替え"
|
||||||
noMaintainerInformationWarning: "管理者情報が設定されてへんで"
|
noMaintainerInformationWarning: "管理者情報が設定されてへんで"
|
||||||
|
noInquiryUrlWarning: "問い合わせ先URLが設定されてへんで。"
|
||||||
noBotProtectionWarning: "Botプロテクションが設定されてへんで。"
|
noBotProtectionWarning: "Botプロテクションが設定されてへんで。"
|
||||||
configure: "設定する"
|
configure: "設定する"
|
||||||
postToGallery: "ギャラリーへ投稿"
|
postToGallery: "ギャラリーへ投稿"
|
||||||
|
@ -1923,8 +1927,6 @@ _sfx:
|
||||||
note: "ノート"
|
note: "ノート"
|
||||||
noteMy: "ノート(自分)"
|
noteMy: "ノート(自分)"
|
||||||
notification: "通知"
|
notification: "通知"
|
||||||
antenna: "アンテナ受信"
|
|
||||||
channel: "チャンネル通知"
|
|
||||||
reaction: "ツッコミ選んどるとき"
|
reaction: "ツッコミ選んどるとき"
|
||||||
_soundSettings:
|
_soundSettings:
|
||||||
driveFile: "ドライブん中の音使う"
|
driveFile: "ドライブん中の音使う"
|
||||||
|
@ -2399,6 +2401,12 @@ _webhookSettings:
|
||||||
renote: "リノートされるとき~!"
|
renote: "リノートされるとき~!"
|
||||||
reaction: "ツッコまれたとき~!"
|
reaction: "ツッコまれたとき~!"
|
||||||
mention: "メンションがあるとき~!"
|
mention: "メンションがあるとき~!"
|
||||||
|
deleteConfirm: "ほんまにWebhookをほかしてもええんか?"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "メール"
|
||||||
|
deleteConfirm: "通知先を削除してもええか?"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
createRole: "ロールを追加すんで"
|
createRole: "ロールを追加すんで"
|
||||||
deleteRole: "ロールほかす"
|
deleteRole: "ロールほかす"
|
||||||
|
|
|
@ -104,3 +104,7 @@ _deck:
|
||||||
_columns:
|
_columns:
|
||||||
notifications: "Ilɣuyen"
|
notifications: "Ilɣuyen"
|
||||||
list: "Tibdarin"
|
list: "Tibdarin"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "Imayl"
|
||||||
|
|
|
@ -805,6 +805,10 @@ _deck:
|
||||||
mentions: "받언 멘션"
|
mentions: "받언 멘션"
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
name: "이럼"
|
name: "이럼"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "전자우펜"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "얼우기"
|
suspend: "얼우기"
|
||||||
deleteNote: "노트 뭉캐기"
|
deleteNote: "노트 뭉캐기"
|
||||||
|
|
|
@ -52,14 +52,14 @@ deleteAndEditConfirm: "이 노트를 삭제한 뒤 다시 편집하시겠습니
|
||||||
addToList: "리스트에 추가"
|
addToList: "리스트에 추가"
|
||||||
addToAntenna: "안테나에 추가"
|
addToAntenna: "안테나에 추가"
|
||||||
sendMessage: "메시지 보내기"
|
sendMessage: "메시지 보내기"
|
||||||
copyRSS: "RSS 복사"
|
copyRSS: "RSS 주소 복사"
|
||||||
copyUsername: "사용자 이름 복사"
|
copyUsername: "유저명 복사"
|
||||||
copyUserId: "사용자 ID 복사"
|
copyUserId: "유저 ID 복사"
|
||||||
copyNoteId: "노트 ID 복사"
|
copyNoteId: "노트 ID 복사"
|
||||||
copyFileId: "파일 ID 복사"
|
copyFileId: "파일 ID 복사"
|
||||||
copyFolderId: "폴더 ID 복사"
|
copyFolderId: "폴더 ID 복사"
|
||||||
copyProfileUrl: "프로필 URL 복사"
|
copyProfileUrl: "프로필 URL 복사"
|
||||||
searchUser: "사용자 검색"
|
searchUser: "유저 검색"
|
||||||
reply: "답글"
|
reply: "답글"
|
||||||
loadMore: "더 보기"
|
loadMore: "더 보기"
|
||||||
showMore: "더 보기"
|
showMore: "더 보기"
|
||||||
|
@ -108,22 +108,25 @@ enterEmoji: "이모지 입력"
|
||||||
renote: "리노트"
|
renote: "리노트"
|
||||||
unrenote: "리노트 취소"
|
unrenote: "리노트 취소"
|
||||||
renoted: "리노트했습니다"
|
renoted: "리노트했습니다"
|
||||||
|
renotedToX: "{name}명이 리노트했습니다."
|
||||||
cantRenote: "이 게시물은 리노트 할 수 없습니다."
|
cantRenote: "이 게시물은 리노트 할 수 없습니다."
|
||||||
cantReRenote: "리노트를 리노트할 수 없습니다."
|
cantReRenote: "리노트를 리노트 할 수 없습니다."
|
||||||
quote: "인용"
|
quote: "인용"
|
||||||
inChannelRenote: "채널 내 리노트"
|
inChannelRenote: "채널 내 리노트"
|
||||||
inChannelQuote: "채널 내 인용"
|
inChannelQuote: "채널 내 인용"
|
||||||
|
renoteToChannel: "채널에 리노트"
|
||||||
|
renoteToOtherChannel: "다른 채널에 리노트"
|
||||||
pinnedNote: "고정된 노트"
|
pinnedNote: "고정된 노트"
|
||||||
pinned: "고정하기"
|
pinned: "고정하기"
|
||||||
you: "나"
|
you: "나"
|
||||||
clickToShow: "클릭하여 보기"
|
clickToShow: "클릭하여 보기"
|
||||||
sensitive: "열람 주의"
|
sensitive: "열람 주의"
|
||||||
add: "추가"
|
add: "추가"
|
||||||
reaction: "반응"
|
reaction: "리액션"
|
||||||
reactions: "반응"
|
reactions: "리액션"
|
||||||
emojiPicker: "이모지 선택기"
|
emojiPicker: "이모지 선택기"
|
||||||
pinnedEmojisForReactionSettingDescription: "리액션을 할 때 프로필에 고정하여 표시할 이모지를 설정할 수 있습니다"
|
pinnedEmojisForReactionSettingDescription: "리액션을 할 때 이모지 선택기 상단에 표시할 이모지를 설정할 수 있습니다."
|
||||||
pinnedEmojisSettingDescription: "이모지를 입력할 때 프로필에 고정하여 표시할 이모지를 설정할 수 있습니다"
|
pinnedEmojisSettingDescription: "이모지를 입력할 때 이모지 선택기 상단에 표시할 이모지를 설정할 수 있습니다."
|
||||||
emojiPickerDisplay: "선택기 표시"
|
emojiPickerDisplay: "선택기 표시"
|
||||||
overwriteFromPinnedEmojisForReaction: "리액션 설정을 덮어쓰기"
|
overwriteFromPinnedEmojisForReaction: "리액션 설정을 덮어쓰기"
|
||||||
overwriteFromPinnedEmojis: "일반 설정을 덮어쓰기"
|
overwriteFromPinnedEmojis: "일반 설정을 덮어쓰기"
|
||||||
|
@ -136,7 +139,7 @@ unmarkAsSensitive: "열람주의 해제"
|
||||||
enterFileName: "파일명을 입력"
|
enterFileName: "파일명을 입력"
|
||||||
mute: "뮤트"
|
mute: "뮤트"
|
||||||
unmute: "뮤트 해제"
|
unmute: "뮤트 해제"
|
||||||
renoteMute: "리노트 뮤트하기"
|
renoteMute: "리노트 뮤트"
|
||||||
renoteUnmute: "리노트 뮤트 해제"
|
renoteUnmute: "리노트 뮤트 해제"
|
||||||
block: "차단"
|
block: "차단"
|
||||||
unblock: "차단 해제"
|
unblock: "차단 해제"
|
||||||
|
@ -174,12 +177,12 @@ flagShowTimelineReplies: "타임라인에 노트의 답글을 표시하기"
|
||||||
flagShowTimelineRepliesDescription: "이 설정을 활성화하면 타임라인에 다른 유저 간의 답글을 표시합니다."
|
flagShowTimelineRepliesDescription: "이 설정을 활성화하면 타임라인에 다른 유저 간의 답글을 표시합니다."
|
||||||
autoAcceptFollowed: "팔로우 중인 유저로부터의 팔로우 요청을 자동 수락"
|
autoAcceptFollowed: "팔로우 중인 유저로부터의 팔로우 요청을 자동 수락"
|
||||||
addAccount: "계정 추가"
|
addAccount: "계정 추가"
|
||||||
reloadAccountsList: "계정 리스트 정보 갱신"
|
reloadAccountsList: "계정 목록 새로고침"
|
||||||
loginFailed: "로그인에 실패했습니다"
|
loginFailed: "로그인에 실패했습니다"
|
||||||
showOnRemote: "리모트에서 보기"
|
showOnRemote: "리모트에서 보기"
|
||||||
general: "일반"
|
general: "일반"
|
||||||
wallpaper: "배경"
|
wallpaper: "배경"
|
||||||
setWallpaper: "배경화면 설정"
|
setWallpaper: "배경 설정"
|
||||||
removeWallpaper: "배경 제거"
|
removeWallpaper: "배경 제거"
|
||||||
searchWith: "검색: {q}"
|
searchWith: "검색: {q}"
|
||||||
youHaveNoLists: "리스트가 없습니다"
|
youHaveNoLists: "리스트가 없습니다"
|
||||||
|
@ -187,7 +190,7 @@ followConfirm: "{name}님을 팔로우 하시겠습니까?"
|
||||||
proxyAccount: "프록시 계정"
|
proxyAccount: "프록시 계정"
|
||||||
proxyAccountDescription: "프록시 계정은 특정 조건 하에서 유저의 리모트 팔로우를 대행하는 계정입니다. 예를 들면, 유저가 리모트 유저를 리스트에 넣었을 때, 리스트에 들어간 유저를 아무도 팔로우한 적이 없다면 액티비티가 서버로 배달되지 않기 때문에, 대신 프록시 계정이 해당 유저를 팔로우하도록 합니다."
|
proxyAccountDescription: "프록시 계정은 특정 조건 하에서 유저의 리모트 팔로우를 대행하는 계정입니다. 예를 들면, 유저가 리모트 유저를 리스트에 넣었을 때, 리스트에 들어간 유저를 아무도 팔로우한 적이 없다면 액티비티가 서버로 배달되지 않기 때문에, 대신 프록시 계정이 해당 유저를 팔로우하도록 합니다."
|
||||||
host: "호스트"
|
host: "호스트"
|
||||||
selectUser: "사용자 선택"
|
selectUser: "유저 선택"
|
||||||
recipient: "수신인"
|
recipient: "수신인"
|
||||||
annotation: "내용에 대한 주석"
|
annotation: "내용에 대한 주석"
|
||||||
federation: "연합"
|
federation: "연합"
|
||||||
|
@ -230,7 +233,7 @@ noUsers: "아무도 없습니다"
|
||||||
editProfile: "프로필 수정"
|
editProfile: "프로필 수정"
|
||||||
noteDeleteConfirm: "이 노트를 삭제하시겠습니까?"
|
noteDeleteConfirm: "이 노트를 삭제하시겠습니까?"
|
||||||
pinLimitExceeded: "더 이상 고정할 수 없습니다."
|
pinLimitExceeded: "더 이상 고정할 수 없습니다."
|
||||||
intro: "Misskey의 설치를 완료했습니다! 관리자 계정을 만들어 주세요."
|
intro: "Misskey의 설치가 완료되었습니다! 관리자 계정을 생성해주세요."
|
||||||
done: "완료"
|
done: "완료"
|
||||||
processing: "처리중"
|
processing: "처리중"
|
||||||
preview: "미리보기"
|
preview: "미리보기"
|
||||||
|
@ -247,7 +250,7 @@ publishing: "배포 중"
|
||||||
notResponding: "응답 없음"
|
notResponding: "응답 없음"
|
||||||
instanceFollowing: "서버의 팔로잉"
|
instanceFollowing: "서버의 팔로잉"
|
||||||
instanceFollowers: "서버의 팔로워"
|
instanceFollowers: "서버의 팔로워"
|
||||||
instanceUsers: "서버의 유저"
|
instanceUsers: "서버의 사용자"
|
||||||
changePassword: "비밀번호 변경"
|
changePassword: "비밀번호 변경"
|
||||||
security: "보안"
|
security: "보안"
|
||||||
retypedNotMatch: "입력이 일치하지 않습니다."
|
retypedNotMatch: "입력이 일치하지 않습니다."
|
||||||
|
@ -263,12 +266,12 @@ lookup: "찾아보기"
|
||||||
announcements: "공지사항"
|
announcements: "공지사항"
|
||||||
imageUrl: "이미지 URL"
|
imageUrl: "이미지 URL"
|
||||||
remove: "삭제"
|
remove: "삭제"
|
||||||
removed: "삭제하였습니다"
|
removed: "삭제했습니다"
|
||||||
removeAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
|
removeAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
|
||||||
deleteAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
|
deleteAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
|
||||||
resetAreYouSure: "초기화 하시겠습니까?"
|
resetAreYouSure: "초기화 하시겠습니까?"
|
||||||
areYouSure: "계속 진행하시겠습니까?"
|
areYouSure: "계속 진행하시겠습니까?"
|
||||||
saved: "저장하였습니다"
|
saved: "저장했습니다"
|
||||||
messaging: "대화"
|
messaging: "대화"
|
||||||
upload: "업로드"
|
upload: "업로드"
|
||||||
keepOriginalUploading: "원본 이미지를 유지"
|
keepOriginalUploading: "원본 이미지를 유지"
|
||||||
|
@ -296,7 +299,7 @@ activity: "활동"
|
||||||
images: "이미지"
|
images: "이미지"
|
||||||
image: "이미지"
|
image: "이미지"
|
||||||
birthday: "생일"
|
birthday: "생일"
|
||||||
yearsOld: "만 {age} 세"
|
yearsOld: "{age}세"
|
||||||
registeredDate: "등록일"
|
registeredDate: "등록일"
|
||||||
location: "장소"
|
location: "장소"
|
||||||
theme: "테마"
|
theme: "테마"
|
||||||
|
@ -313,6 +316,7 @@ selectFile: "파일 선택"
|
||||||
selectFiles: "파일 선택"
|
selectFiles: "파일 선택"
|
||||||
selectFolder: "폴더 선택"
|
selectFolder: "폴더 선택"
|
||||||
selectFolders: "폴더 선택"
|
selectFolders: "폴더 선택"
|
||||||
|
fileNotSelected: "파일을 선택하지 않았습니다"
|
||||||
renameFile: "파일 이름 변경"
|
renameFile: "파일 이름 변경"
|
||||||
folderName: "폴더 이름"
|
folderName: "폴더 이름"
|
||||||
createFolder: "폴더 만들기"
|
createFolder: "폴더 만들기"
|
||||||
|
@ -370,7 +374,7 @@ inMb: "메가바이트 단위"
|
||||||
bannerUrl: "배너 이미지 URL"
|
bannerUrl: "배너 이미지 URL"
|
||||||
backgroundImageUrl: "배경 이미지 URL"
|
backgroundImageUrl: "배경 이미지 URL"
|
||||||
basicInfo: "기본 정보"
|
basicInfo: "기본 정보"
|
||||||
pinnedUsers: "고정된 유저"
|
pinnedUsers: "고정한 사용자"
|
||||||
pinnedUsersDescription: "\"발견하기\" 페이지 등에 고정하고 싶은 유저를 한 줄에 한 명씩 적습니다."
|
pinnedUsersDescription: "\"발견하기\" 페이지 등에 고정하고 싶은 유저를 한 줄에 한 명씩 적습니다."
|
||||||
pinnedPages: "고정한 페이지"
|
pinnedPages: "고정한 페이지"
|
||||||
pinnedPagesDescription: "서버의 대문에 고정하고 싶은 페이지의 경로를 한 줄에 하나씩 적습니다."
|
pinnedPagesDescription: "서버의 대문에 고정하고 싶은 페이지의 경로를 한 줄에 하나씩 적습니다."
|
||||||
|
@ -437,13 +441,13 @@ moderationNote: "조정 기록"
|
||||||
addModerationNote: "조정 기록 추가하기"
|
addModerationNote: "조정 기록 추가하기"
|
||||||
moderationLogs: "모더레이션 로그"
|
moderationLogs: "모더레이션 로그"
|
||||||
nUsersMentioned: "{n}명이 언급함"
|
nUsersMentioned: "{n}명이 언급함"
|
||||||
securityKeyAndPasskey: "보안 키 또는 패스 키"
|
securityKeyAndPasskey: "보안 키 또는 패스키"
|
||||||
securityKey: "보안 키"
|
securityKey: "보안 키"
|
||||||
lastUsed: "마지막 사용"
|
lastUsed: "마지막 사용"
|
||||||
lastUsedAt: "마지막 사용: {t}"
|
lastUsedAt: "마지막 사용: {t}"
|
||||||
unregister: "등록 해제"
|
unregister: "등록 해제"
|
||||||
passwordLessLogin: "비밀번호 없이 로그인"
|
passwordLessLogin: "비밀번호 없이 로그인"
|
||||||
passwordLessLoginDescription: "비밀번호를 사용하지 않고 보안 키 또는 패스 키 등으로만 로그인합니다."
|
passwordLessLoginDescription: "비밀번호 없이 보안 키 또는 패스키만 사용해서 로그인합니다."
|
||||||
resetPassword: "비밀번호 재설정"
|
resetPassword: "비밀번호 재설정"
|
||||||
newPasswordIs: "새로운 비밀번호는 \"{password}\" 입니다"
|
newPasswordIs: "새로운 비밀번호는 \"{password}\" 입니다"
|
||||||
reduceUiAnimation: "UI의 애니메이션을 줄이기"
|
reduceUiAnimation: "UI의 애니메이션을 줄이기"
|
||||||
|
@ -468,6 +472,7 @@ retype: "다시 입력"
|
||||||
noteOf: "{user}의 노트"
|
noteOf: "{user}의 노트"
|
||||||
quoteAttached: "인용함"
|
quoteAttached: "인용함"
|
||||||
quoteQuestion: "인용해서 작성하시겠습니까?"
|
quoteQuestion: "인용해서 작성하시겠습니까?"
|
||||||
|
attachAsFileQuestion: "붙여넣으려는 글이 너무 깁니다. 텍스트 파일로 첨부하시겠습니까?"
|
||||||
noMessagesYet: "아직 대화가 없습니다"
|
noMessagesYet: "아직 대화가 없습니다"
|
||||||
newMessageExists: "새 메시지가 있습니다"
|
newMessageExists: "새 메시지가 있습니다"
|
||||||
onlyOneFileCanBeAttached: "메시지에 첨부할 수 있는 파일은 하나까지입니다"
|
onlyOneFileCanBeAttached: "메시지에 첨부할 수 있는 파일은 하나까지입니다"
|
||||||
|
@ -486,7 +491,7 @@ strongPassword: "강한 비밀번호"
|
||||||
passwordMatched: "일치합니다"
|
passwordMatched: "일치합니다"
|
||||||
passwordNotMatched: "일치하지 않습니다"
|
passwordNotMatched: "일치하지 않습니다"
|
||||||
signinWith: "{x}로 로그인"
|
signinWith: "{x}로 로그인"
|
||||||
signinFailed: "로그인할 수 없습니다. 사용자명과 비밀번호를 확인하여 주십시오."
|
signinFailed: "로그인할 수 없습니다. 사용자 이름과 비밀번호를 확인해 주십시오."
|
||||||
or: "혹은"
|
or: "혹은"
|
||||||
language: "언어"
|
language: "언어"
|
||||||
uiLanguage: "UI 표시 언어"
|
uiLanguage: "UI 표시 언어"
|
||||||
|
@ -494,7 +499,7 @@ aboutX: "{x}에 대하여"
|
||||||
emojiStyle: "이모지 스타일"
|
emojiStyle: "이모지 스타일"
|
||||||
native: "기본"
|
native: "기본"
|
||||||
disableDrawer: "드로어 메뉴를 사용하지 않기"
|
disableDrawer: "드로어 메뉴를 사용하지 않기"
|
||||||
showNoteActionsOnlyHover: "노트 액션 버튼을 마우스를 올렸을 때에만 표시"
|
showNoteActionsOnlyHover: "마우스가 올라간 때에만 노트 동작 버튼을 표시하기"
|
||||||
showReactionsCount: "노트의 반응 수를 표시하기"
|
showReactionsCount: "노트의 반응 수를 표시하기"
|
||||||
noHistory: "기록이 없습니다"
|
noHistory: "기록이 없습니다"
|
||||||
signinHistory: "로그인 기록"
|
signinHistory: "로그인 기록"
|
||||||
|
@ -559,7 +564,7 @@ popout: "새 창으로 열기"
|
||||||
volume: "음량"
|
volume: "음량"
|
||||||
masterVolume: "마스터 볼륨"
|
masterVolume: "마스터 볼륨"
|
||||||
notUseSound: "음소거 하기"
|
notUseSound: "음소거 하기"
|
||||||
useSoundOnlyWhenActive: "Misskey가 활성화 되어져 있을 때만 소리 출력하기"
|
useSoundOnlyWhenActive: "Misskey를 활성화한 때에만 소리를 출력하기"
|
||||||
details: "자세히"
|
details: "자세히"
|
||||||
chooseEmoji: "이모지 선택"
|
chooseEmoji: "이모지 선택"
|
||||||
unableToProcess: "작업을 완료할 수 없습니다"
|
unableToProcess: "작업을 완료할 수 없습니다"
|
||||||
|
@ -588,7 +593,7 @@ deleteAllFiles: "모든 파일 삭제"
|
||||||
deleteAllFilesConfirm: "모든 파일을 삭제하시겠습니까?"
|
deleteAllFilesConfirm: "모든 파일을 삭제하시겠습니까?"
|
||||||
removeAllFollowing: "모든 팔로잉 해제"
|
removeAllFollowing: "모든 팔로잉 해제"
|
||||||
removeAllFollowingDescription: "{host} 서버의 모든 팔로잉을 해제합니다. 해당 서버가 더 이상 존재하지 않는 경우 등에 실행해 주세요."
|
removeAllFollowingDescription: "{host} 서버의 모든 팔로잉을 해제합니다. 해당 서버가 더 이상 존재하지 않는 경우 등에 실행해 주세요."
|
||||||
userSuspended: "이 계정은 정지된 상태입니다."
|
userSuspended: "이 사용자는 정지되었습니다."
|
||||||
userSilenced: "이 계정은 사일런스된 상태입니다."
|
userSilenced: "이 계정은 사일런스된 상태입니다."
|
||||||
yourAccountSuspendedTitle: "계정이 정지되었습니다"
|
yourAccountSuspendedTitle: "계정이 정지되었습니다"
|
||||||
yourAccountSuspendedDescription: "이 계정은 서버의 이용 약관을 위반하거나, 기타 다른 이유로 인해 정지되었습니다. 자세한 사항은 관리자에게 문의해 주십시오. 계정을 새로 생성하지 마십시오."
|
yourAccountSuspendedDescription: "이 계정은 서버의 이용 약관을 위반하거나, 기타 다른 이유로 인해 정지되었습니다. 자세한 사항은 관리자에게 문의해 주십시오. 계정을 새로 생성하지 마십시오."
|
||||||
|
@ -752,7 +757,7 @@ experimentalFeatures: "실험실"
|
||||||
experimental: "실험실"
|
experimental: "실험실"
|
||||||
thisIsExperimentalFeature: "이 기능은 실험적인 기능입니다. 사양이 변경되거나 정상적으로 동작하지 않을 가능성이 있습니다."
|
thisIsExperimentalFeature: "이 기능은 실험적인 기능입니다. 사양이 변경되거나 정상적으로 동작하지 않을 가능성이 있습니다."
|
||||||
developer: "개발자"
|
developer: "개발자"
|
||||||
makeExplorable: "\"발견하기\"에 내 계정 보이기"
|
makeExplorable: "계정을 쉽게 발견하도록 하기"
|
||||||
makeExplorableDescription: "비활성화하면 \"발견하기\"에 나의 계정을 표시하지 않습니다."
|
makeExplorableDescription: "비활성화하면 \"발견하기\"에 나의 계정을 표시하지 않습니다."
|
||||||
showGapBetweenNotesInTimeline: "타임라인의 노트 사이를 띄워서 표시"
|
showGapBetweenNotesInTimeline: "타임라인의 노트 사이를 띄워서 표시"
|
||||||
duplicate: "복제"
|
duplicate: "복제"
|
||||||
|
@ -798,7 +803,7 @@ emailNotification: "메일 알림"
|
||||||
publish: "게시"
|
publish: "게시"
|
||||||
inChannelSearch: "채널에서 검색"
|
inChannelSearch: "채널에서 검색"
|
||||||
useReactionPickerForContextMenu: "우클릭하여 리액션 선택기 열기"
|
useReactionPickerForContextMenu: "우클릭하여 리액션 선택기 열기"
|
||||||
typingUsers: "{users} 님이 입력하고 있어요.."
|
typingUsers: "{users}님이 입력 중"
|
||||||
jumpToSpecifiedDate: "특정 날짜로 이동"
|
jumpToSpecifiedDate: "특정 날짜로 이동"
|
||||||
showingPastTimeline: "과거의 타임라인을 표시하고 있어요"
|
showingPastTimeline: "과거의 타임라인을 표시하고 있어요"
|
||||||
clear: "지우기"
|
clear: "지우기"
|
||||||
|
@ -832,6 +837,7 @@ administration: "관리"
|
||||||
accounts: "계정"
|
accounts: "계정"
|
||||||
switch: "전환"
|
switch: "전환"
|
||||||
noMaintainerInformationWarning: "관리자 정보가 설정되어 있지 않습니다."
|
noMaintainerInformationWarning: "관리자 정보가 설정되어 있지 않습니다."
|
||||||
|
noInquiryUrlWarning: "문의처 주소를 설정하지 않았습니다."
|
||||||
noBotProtectionWarning: "Bot 방어가 설정되어 있지 않습니다."
|
noBotProtectionWarning: "Bot 방어가 설정되어 있지 않습니다."
|
||||||
configure: "설정하기"
|
configure: "설정하기"
|
||||||
postToGallery: "갤러리에 업로드"
|
postToGallery: "갤러리에 업로드"
|
||||||
|
@ -1021,6 +1027,7 @@ thisPostMayBeAnnoyingHome: "홈에 게시"
|
||||||
thisPostMayBeAnnoyingCancel: "그만두기"
|
thisPostMayBeAnnoyingCancel: "그만두기"
|
||||||
thisPostMayBeAnnoyingIgnore: "이대로 게시"
|
thisPostMayBeAnnoyingIgnore: "이대로 게시"
|
||||||
collapseRenotes: "이미 본 리노트를 간략화하기"
|
collapseRenotes: "이미 본 리노트를 간략화하기"
|
||||||
|
collapseRenotesDescription: "반응이나 리노트를 한 노트를 접어서 표시합니다."
|
||||||
internalServerError: "내부 서버 오류"
|
internalServerError: "내부 서버 오류"
|
||||||
internalServerErrorDescription: "내부 서버에서 예기치 않은 오류가 발생했습니다."
|
internalServerErrorDescription: "내부 서버에서 예기치 않은 오류가 발생했습니다."
|
||||||
copyErrorInfo: "오류 정보 복사"
|
copyErrorInfo: "오류 정보 복사"
|
||||||
|
@ -1090,7 +1097,7 @@ serverRules: "서버 규칙"
|
||||||
pleaseConfirmBelowBeforeSignup: "이 서버에 가입하기 전에 아래 사항을 확인하여 주십시오."
|
pleaseConfirmBelowBeforeSignup: "이 서버에 가입하기 전에 아래 사항을 확인하여 주십시오."
|
||||||
pleaseAgreeAllToContinue: "계속하시려면 모든 항목에 동의하십시오."
|
pleaseAgreeAllToContinue: "계속하시려면 모든 항목에 동의하십시오."
|
||||||
continue: "계속"
|
continue: "계속"
|
||||||
preservedUsernames: "예약된 사용자명"
|
preservedUsernames: "예약한 사용자 이름"
|
||||||
preservedUsernamesDescription: "예약할 사용자명을 한 줄에 하나씩 입력합니다. 여기에서 지정한 사용자명으로는 계정을 생성할 수 없게 됩니다. 단, 관리자 권한으로 계정을 생성할 때에는 해당되지 않으며, 이미 존재하는 계정도 영향을 받지 않습니다."
|
preservedUsernamesDescription: "예약할 사용자명을 한 줄에 하나씩 입력합니다. 여기에서 지정한 사용자명으로는 계정을 생성할 수 없게 됩니다. 단, 관리자 권한으로 계정을 생성할 때에는 해당되지 않으며, 이미 존재하는 계정도 영향을 받지 않습니다."
|
||||||
createNoteFromTheFile: "이 파일로 노트를 작성"
|
createNoteFromTheFile: "이 파일로 노트를 작성"
|
||||||
archive: "아카이브"
|
archive: "아카이브"
|
||||||
|
@ -1230,10 +1237,20 @@ useTotp: "일회용 비밀번호 사용"
|
||||||
useBackupCode: "백업 코드 사용"
|
useBackupCode: "백업 코드 사용"
|
||||||
launchApp: "앱 실행"
|
launchApp: "앱 실행"
|
||||||
useNativeUIForVideoAudioPlayer: "브라우저 UI에서 미디어 재생"
|
useNativeUIForVideoAudioPlayer: "브라우저 UI에서 미디어 재생"
|
||||||
|
keepOriginalFilename: "원본 파일 이름을 유지"
|
||||||
|
keepOriginalFilenameDescription: "이 설정을 끄면 업로드를 할 때 파일 이름이 자동으로 무작위 문자열로 바뀝니다."
|
||||||
|
noDescription: "설명문이 없습니다"
|
||||||
|
alwaysConfirmFollow: "팔로우일 때 항상 확인하기"
|
||||||
|
inquiry: "문의하기"
|
||||||
_delivery:
|
_delivery:
|
||||||
|
status: "전송 상태"
|
||||||
stop: "정지됨"
|
stop: "정지됨"
|
||||||
|
resume: "전송 다시 시작"
|
||||||
_type:
|
_type:
|
||||||
none: "배포 중"
|
none: "배포 중"
|
||||||
|
manuallySuspended: "수동 정지 중"
|
||||||
|
goneSuspended: "서버 삭제를 이유로 정지 중"
|
||||||
|
autoSuspendedForNotResponding: "서버 응답 없음을 이유로 정지 중"
|
||||||
_bubbleGame:
|
_bubbleGame:
|
||||||
howToPlay: "설명"
|
howToPlay: "설명"
|
||||||
hold: "홀드"
|
hold: "홀드"
|
||||||
|
@ -1359,6 +1376,8 @@ _serverSettings:
|
||||||
fanoutTimelineDescription: "활성화하면 각종 타임라인을 가져올 때의 성능을 대폭 향상하며, 데이터베이스의 부하를 줄일 수 있습니다. 단, Redis의 메모리 사용량이 증가합니다. 서버의 메모리 용량이 작거나, 서비스가 불안정해지는 경우 비활성화할 수 있습니다."
|
fanoutTimelineDescription: "활성화하면 각종 타임라인을 가져올 때의 성능을 대폭 향상하며, 데이터베이스의 부하를 줄일 수 있습니다. 단, Redis의 메모리 사용량이 증가합니다. 서버의 메모리 용량이 작거나, 서비스가 불안정해지는 경우 비활성화할 수 있습니다."
|
||||||
fanoutTimelineDbFallback: "데이터베이스를 예비로 사용하기"
|
fanoutTimelineDbFallback: "데이터베이스를 예비로 사용하기"
|
||||||
fanoutTimelineDbFallbackDescription: "활성화하면 타임라인의 캐시되어 있지 않은 부분에 대해 DB에 질의하여 정보를 가져옵니다. 비활성화하면 이를 실행하지 않음으로써 서버의 부하를 줄일 수 있지만, 타임라인에서 가져올 수 있는 게시물 범위가 한정됩니다."
|
fanoutTimelineDbFallbackDescription: "활성화하면 타임라인의 캐시되어 있지 않은 부분에 대해 DB에 질의하여 정보를 가져옵니다. 비활성화하면 이를 실행하지 않음으로써 서버의 부하를 줄일 수 있지만, 타임라인에서 가져올 수 있는 게시물 범위가 한정됩니다."
|
||||||
|
inquiryUrl: "문의처 URL"
|
||||||
|
inquiryUrlDescription: "서버 운영자에게 보내는 문의 양식의 URL이나 운영자의 연락처 등이 적힌 웹 페이지의 URL을 설정합니다."
|
||||||
_accountMigration:
|
_accountMigration:
|
||||||
moveFrom: "다른 계정에서 이 계정으로 이사"
|
moveFrom: "다른 계정에서 이 계정으로 이사"
|
||||||
moveFromSub: "다른 계정에 대한 별칭을 생성"
|
moveFromSub: "다른 계정에 대한 별칭을 생성"
|
||||||
|
@ -1678,7 +1697,7 @@ _role:
|
||||||
pinMax: "고정할 수 있는 노트 수"
|
pinMax: "고정할 수 있는 노트 수"
|
||||||
antennaMax: "만들 수 있는 안테나 수"
|
antennaMax: "만들 수 있는 안테나 수"
|
||||||
wordMuteMax: "단어 뮤트할 수 있는 문자 수"
|
wordMuteMax: "단어 뮤트할 수 있는 문자 수"
|
||||||
webhookMax: "만들 수 있는 웹후크 수"
|
webhookMax: "만들 수 있는 Webhook 수"
|
||||||
clipMax: "만들 수 있는 클립 수"
|
clipMax: "만들 수 있는 클립 수"
|
||||||
noteEachClipsMax: "클립에 넣을 수 있는 노트 수"
|
noteEachClipsMax: "클립에 넣을 수 있는 노트 수"
|
||||||
userListMax: "만들 수 있는 사용자 리스트 수"
|
userListMax: "만들 수 있는 사용자 리스트 수"
|
||||||
|
@ -1693,6 +1712,11 @@ _role:
|
||||||
roleAssignedTo: "수동 역할에 이미 할당됨"
|
roleAssignedTo: "수동 역할에 이미 할당됨"
|
||||||
isLocal: "로컬 사용자"
|
isLocal: "로컬 사용자"
|
||||||
isRemote: "리모트 사용자"
|
isRemote: "리모트 사용자"
|
||||||
|
isCat: "고양이 사용자"
|
||||||
|
isBot: "봇 사용자"
|
||||||
|
isSuspended: "정지된 사용자"
|
||||||
|
isLocked: "잠금 계정 사용자"
|
||||||
|
isExplorable: "‘계정을 쉽게 발견하도록 하기’를 활성화한 사용자"
|
||||||
createdLessThan: "가입한 지 다음 일수 이내인 유저"
|
createdLessThan: "가입한 지 다음 일수 이내인 유저"
|
||||||
createdMoreThan: "가입한 지 다음 일수 이상인 유저"
|
createdMoreThan: "가입한 지 다음 일수 이상인 유저"
|
||||||
followersLessThanOrEq: "팔로워 수가 다음 이하인 유저"
|
followersLessThanOrEq: "팔로워 수가 다음 이하인 유저"
|
||||||
|
@ -1913,8 +1937,6 @@ _sfx:
|
||||||
note: "새 노트"
|
note: "새 노트"
|
||||||
noteMy: "내 노트"
|
noteMy: "내 노트"
|
||||||
notification: "알림"
|
notification: "알림"
|
||||||
antenna: "안테나 수신"
|
|
||||||
channel: "채널 알림"
|
|
||||||
reaction: "리액션 선택"
|
reaction: "리액션 선택"
|
||||||
_soundSettings:
|
_soundSettings:
|
||||||
driveFile: "드라이브에 있는 오디오를 사용"
|
driveFile: "드라이브에 있는 오디오를 사용"
|
||||||
|
@ -1975,6 +1997,7 @@ _2fa:
|
||||||
backupCodesDescription: "인증 앱을 사용할 수 없게 된 경우 아래 백업 코드를 사용하여 계정에 액세스 할 수 있습니다.이 코드들은 반드시 안전한 장소에 보관하십시오.각 코드는 한 번만 사용할 수 있습니다."
|
backupCodesDescription: "인증 앱을 사용할 수 없게 된 경우 아래 백업 코드를 사용하여 계정에 액세스 할 수 있습니다.이 코드들은 반드시 안전한 장소에 보관하십시오.각 코드는 한 번만 사용할 수 있습니다."
|
||||||
backupCodeUsedWarning: "백업 코드가 사용되었습니다.인증 앱을 사용할 수 없게 된 경우, 조속히 인증 앱을 다시 설정해 주십시오."
|
backupCodeUsedWarning: "백업 코드가 사용되었습니다.인증 앱을 사용할 수 없게 된 경우, 조속히 인증 앱을 다시 설정해 주십시오."
|
||||||
backupCodesExhaustedWarning: "백업 코드가 모두 사용되었습니다.인증 앱을 사용할 수 없는 경우 더 이상 계정에 액세스하는 것이 불가능합니다.인증 앱을 다시 등록해 주세요."
|
backupCodesExhaustedWarning: "백업 코드가 모두 사용되었습니다.인증 앱을 사용할 수 없는 경우 더 이상 계정에 액세스하는 것이 불가능합니다.인증 앱을 다시 등록해 주세요."
|
||||||
|
moreDetailedGuideHere: "여기에 자세한 설명이 있습니다"
|
||||||
_permissions:
|
_permissions:
|
||||||
"read:account": "계정의 정보를 봅니다"
|
"read:account": "계정의 정보를 봅니다"
|
||||||
"write:account": "계정의 정보를 변경합니다"
|
"write:account": "계정의 정보를 변경합니다"
|
||||||
|
@ -2163,7 +2186,7 @@ _postForm:
|
||||||
c: "무엇을 생각하고 있나요?"
|
c: "무엇을 생각하고 있나요?"
|
||||||
d: "말하고 싶은 게 있나요?"
|
d: "말하고 싶은 게 있나요?"
|
||||||
e: "여기에 적어 주세요"
|
e: "여기에 적어 주세요"
|
||||||
f: "글 쓰기를 기다려요…"
|
f: "작성해주시길 기다리고 있어요..."
|
||||||
_profile:
|
_profile:
|
||||||
name: "이름"
|
name: "이름"
|
||||||
username: "사용자 이름"
|
username: "사용자 이름"
|
||||||
|
@ -2338,6 +2361,7 @@ _deck:
|
||||||
alwaysShowMainColumn: "메인 칼럼 항상 표시"
|
alwaysShowMainColumn: "메인 칼럼 항상 표시"
|
||||||
columnAlign: "칼럼 정렬"
|
columnAlign: "칼럼 정렬"
|
||||||
addColumn: "칼럼 추가"
|
addColumn: "칼럼 추가"
|
||||||
|
newNoteNotificationSettings: "새 노트 알림 설정"
|
||||||
configureColumn: "칼럼 설정"
|
configureColumn: "칼럼 설정"
|
||||||
swapLeft: "왼쪽으로 이동"
|
swapLeft: "왼쪽으로 이동"
|
||||||
swapRight: "오른쪽으로 이동"
|
swapRight: "오른쪽으로 이동"
|
||||||
|
@ -2376,6 +2400,7 @@ _drivecleaner:
|
||||||
orderByCreatedAtAsc: "등록일이 오래된 순"
|
orderByCreatedAtAsc: "등록일이 오래된 순"
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
createWebhook: "Webhook 생성"
|
createWebhook: "Webhook 생성"
|
||||||
|
modifyWebhook: "Webhook 수정"
|
||||||
name: "이름"
|
name: "이름"
|
||||||
secret: "시크릿"
|
secret: "시크릿"
|
||||||
events: "Webhook을 실행할 타이밍"
|
events: "Webhook을 실행할 타이밍"
|
||||||
|
@ -2388,6 +2413,25 @@ _webhookSettings:
|
||||||
renote: "누군가 내 글을 리노트했을 때"
|
renote: "누군가 내 글을 리노트했을 때"
|
||||||
reaction: "누군가 내 노트에 리액션했을 때"
|
reaction: "누군가 내 노트에 리액션했을 때"
|
||||||
mention: "누군가 나를 멘션했을 때"
|
mention: "누군가 나를 멘션했을 때"
|
||||||
|
_systemEvents:
|
||||||
|
abuseReport: "유저로부터 신고를 받았을 때"
|
||||||
|
abuseReportResolved: "받은 신고를 처리했을 때"
|
||||||
|
deleteConfirm: "Webhook을 삭제할까요?"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
createRecipient: "신고 수신자 추가"
|
||||||
|
modifyRecipient: "신고 수신자 편집"
|
||||||
|
recipientType: "알림 수신 유형"
|
||||||
|
_recipientType:
|
||||||
|
mail: "이메일"
|
||||||
|
webhook: "Webhook"
|
||||||
|
_captions:
|
||||||
|
mail: "모더레이터 권한을 가진 사용자의 이메일 주소에 알림을 보냅니다 (신고를 받은 때에만)"
|
||||||
|
webhook: "지정한 SystemWebhook에 알림을 보냅니다 (신고를 받은 때와 해결했을 때에 송신)"
|
||||||
|
keywords: "키워드"
|
||||||
|
notifiedUser: "신고 알림을 보낼 유저"
|
||||||
|
notifiedWebhook: "사용할 Webhook"
|
||||||
|
deleteConfirm: "수신자를 삭제하시겠습니까?"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
createRole: "역할 생성"
|
createRole: "역할 생성"
|
||||||
deleteRole: "역할 삭제"
|
deleteRole: "역할 삭제"
|
||||||
|
@ -2403,7 +2447,7 @@ _moderationLogTypes:
|
||||||
updateUserNote: "조정 기록 갱신"
|
updateUserNote: "조정 기록 갱신"
|
||||||
deleteDriveFile: "파일 삭제"
|
deleteDriveFile: "파일 삭제"
|
||||||
deleteNote: "노트 삭제"
|
deleteNote: "노트 삭제"
|
||||||
createGlobalAnnouncement: "모든 공지사항 만들기"
|
createGlobalAnnouncement: "전역 공지사항 생성"
|
||||||
createUserAnnouncement: "사용자 공지사항 만들기"
|
createUserAnnouncement: "사용자 공지사항 만들기"
|
||||||
updateGlobalAnnouncement: "모든 공지사항 수정"
|
updateGlobalAnnouncement: "모든 공지사항 수정"
|
||||||
updateUserAnnouncement: "사용자 공지사항 수정"
|
updateUserAnnouncement: "사용자 공지사항 수정"
|
||||||
|
@ -2425,6 +2469,12 @@ _moderationLogTypes:
|
||||||
deleteAvatarDecoration: "아바타 장식 삭제"
|
deleteAvatarDecoration: "아바타 장식 삭제"
|
||||||
unsetUserAvatar: "유저 아바타 제거"
|
unsetUserAvatar: "유저 아바타 제거"
|
||||||
unsetUserBanner: "유저 배너 제거"
|
unsetUserBanner: "유저 배너 제거"
|
||||||
|
createSystemWebhook: "SystemWebhook을 생성"
|
||||||
|
updateSystemWebhook: "SystemWebhook을 수정"
|
||||||
|
deleteSystemWebhook: "SystemWebhook을 삭제"
|
||||||
|
createAbuseReportNotificationRecipient: "신고 알림 수신자 생성"
|
||||||
|
updateAbuseReportNotificationRecipient: "신고 알림 수신자 편집"
|
||||||
|
deleteAbuseReportNotificationRecipient: "신고 알림 수신자 삭제"
|
||||||
_fileViewer:
|
_fileViewer:
|
||||||
title: "파일 상세"
|
title: "파일 상세"
|
||||||
type: "파일 유형"
|
type: "파일 유형"
|
||||||
|
|
|
@ -18,15 +18,15 @@ enterUsername: "ປ້ອນຊື່ຜູ້ໃຊ້"
|
||||||
renotedBy: "Renoted ໂດຍ {user}"
|
renotedBy: "Renoted ໂດຍ {user}"
|
||||||
noNotes: "ບໍ່ມີ note"
|
noNotes: "ບໍ່ມີ note"
|
||||||
noNotifications: "ບໍ່ມີການແຈ້ງເຕືອນ"
|
noNotifications: "ບໍ່ມີການແຈ້ງເຕືອນ"
|
||||||
instance: "ອີນສະແຕນ"
|
instance: "ເຊີຟເວີຣ໌"
|
||||||
settings: "ກຳນົດຄ່າ"
|
settings: "ຕັ້ງຄ່າ"
|
||||||
notificationSettings: "ຕັ້ງຄ່າການແຈ້ງເຕືອນ"
|
notificationSettings: "ຕັ້ງຄ່າການແຈ້ງເຕືອນ"
|
||||||
basicSettings: "ການຕັ້ງຄ່າພື້ນຖານ"
|
basicSettings: "ການຕັ້ງຄ່າພື້ນຖານ"
|
||||||
otherSettings: "ການຕັ້ງຄ່າອື່ນໆ"
|
otherSettings: "ການຕັ້ງຄ່າອື່ນໆ"
|
||||||
openInWindow: "ເປີດໃນປ່ອງຢ້ຽມ"
|
openInWindow: "ເປີດໃນ window"
|
||||||
profile: "ໂພຼຟາຍ"
|
profile: "ໂປຣໄຟລ໌"
|
||||||
timeline: "ໄທມ໌ໄລນ໌"
|
timeline: "ໄທມ໌ໄລນ໌"
|
||||||
noAccountDescription: "ຜູ້ໃຊ້ນີ້ຍັງບໍ່ໄດ້ຂຽນໃນຊີວະປະຫວັດຂອງເຂົາເຈົ້າເທື່ອ"
|
noAccountDescription: "ຜູ້ໃຊ້ຄົນນີ້ຍັງບໍ່ໄດ້ຂຽນຄຳແນະນຳໂຕ"
|
||||||
login: "ເຂົ້າສູ່ລະບົບ"
|
login: "ເຂົ້າສູ່ລະບົບ"
|
||||||
loggingIn: "ກຳລັງເຂົ້າສູ່ລະບົບ..."
|
loggingIn: "ກຳລັງເຂົ້າສູ່ລະບົບ..."
|
||||||
logout: "ອອກຈາກລະບົບ"
|
logout: "ອອກຈາກລະບົບ"
|
||||||
|
@ -37,7 +37,7 @@ users: "ຜູ້ໃຊ້"
|
||||||
addUser: "ເພີ່ມຜູ້ໃຊ້"
|
addUser: "ເພີ່ມຜູ້ໃຊ້"
|
||||||
favorite: "ເພີ່ມໃສ່ລາຍການທີ່ມັກ"
|
favorite: "ເພີ່ມໃສ່ລາຍການທີ່ມັກ"
|
||||||
favorites: "ລາຍການທີ່ມັກ"
|
favorites: "ລາຍການທີ່ມັກ"
|
||||||
unfavorite: "ລຶບອອກຈາກລາຍການທີ່ມັກ"
|
unfavorite: "ເອົາອອກຈາກລາຍການທີ່ມັກ"
|
||||||
favorited: "ເພີ່ມໃສ່ລາຍການທີ່ມັກແລ້ວ"
|
favorited: "ເພີ່ມໃສ່ລາຍການທີ່ມັກແລ້ວ"
|
||||||
alreadyFavorited: "ເພີ່ມເຂົ້າໃນລາຍການທີ່ມັກແລ້ວ."
|
alreadyFavorited: "ເພີ່ມເຂົ້າໃນລາຍການທີ່ມັກແລ້ວ."
|
||||||
cantFavorite: "ບໍ່ສາມາດເພີ່ມໃສ່ລາຍການທີ່ມັກໄດ້."
|
cantFavorite: "ບໍ່ສາມາດເພີ່ມໃສ່ລາຍການທີ່ມັກໄດ້."
|
||||||
|
@ -48,41 +48,41 @@ copyLink: "ຄັດລອກລິ້ງ"
|
||||||
copyLinkRenote: "ຄັດລອກລິ້ງຂອງ renote"
|
copyLinkRenote: "ຄັດລອກລິ້ງຂອງ renote"
|
||||||
delete: "ລຶບ"
|
delete: "ລຶບ"
|
||||||
deleteAndEdit: "ລຶບແລະແກ້ໄຂ"
|
deleteAndEdit: "ລຶບແລະແກ້ໄຂ"
|
||||||
deleteAndEditConfirm: "ເຈົ້າແນ່ໃຈບໍ່? ທີ່ທ່ານຕ້ອງການທີ່ຈະລຶບ note ນີ້ ແລະແກ້ໄຂມັນ ທ່ານອາດຈະສູນເສຍ reaction, renote, ແລະການຕອບກັບທັງໝົດ"
|
deleteAndEditConfirm: "ຕ້ອງການລຶບ note ນີ້ແລະແກ້ໄຂໃໝ່ແມ່ນບໍ່? reaction, renote ແລະການຕອບກັບຕໍ່ note ນີ້ ທັງເບິດຈະຖືກລຶບອອກ"
|
||||||
addToList: "ເພີ່ມໃສ່ລາຍຊື່"
|
addToList: "ເພີ່ມໃສ່ລາຍຊື່"
|
||||||
addToAntenna: "ເພີ່ມໃສ່ເສົາອາກາດ"
|
addToAntenna: "ເພີ່ມໃສ່ເສົາອາກາດ"
|
||||||
sendMessage: "ສົ່ງຂໍ້ຄວາມ"
|
sendMessage: "ສົ່ງຂໍ້ຄວາມ"
|
||||||
copyRSS: "ສຳເນົາ RSS"
|
copyRSS: "ຄັດລອກ RSS"
|
||||||
copyUsername: "ສຳເນົາຊື່ຜູ້ໃຊ້"
|
copyUsername: "ຄັດລອກຊື່ຜູ້ໃຊ້"
|
||||||
copyUserId: "ສຳເນົາ ID ຜູ້ໃຊ້"
|
copyUserId: "ຄັດລອກ ID ຜູ້ໃຊ້"
|
||||||
copyNoteId: "ສຳເນົາ ID ບັນທຶກ"
|
copyNoteId: "ຄັດລອກ ID ຂອງ note"
|
||||||
copyFileId: "ສຳເນົາ ID ໄຟລ໌"
|
copyFileId: "ຄັດລອກ ID ໄຟລ໌"
|
||||||
copyFolderId: "ສຳເນົາ ID ໂຟນເດີ"
|
copyFolderId: "ຄັດລອກ ID ໂຟລ໌ເດີຣ໌"
|
||||||
copyProfileUrl: "ສຳເນົາ URL ໂປຣໄຟລ໌"
|
copyProfileUrl: "ຄັດລອກ URL ໂປຣໄຟລ໌"
|
||||||
searchUser: "ຄົ້ນຫາຜູ້ໃຊ້"
|
searchUser: "ຄົ້ນຫາຜູ້ໃຊ້"
|
||||||
reply: "ຕອບໄປທີ"
|
reply: "ຕອບກັບ"
|
||||||
loadMore: "ໂຫຼດເພີ່ມເຕີມ"
|
loadMore: "ໂຫຼດເພີ່ມເຕີມ"
|
||||||
showMore: "ໂຫຼດເພີ່ມເຕີມ"
|
showMore: "ໂຫຼດເພີ່ມເຕີມ"
|
||||||
showLess: "ປິດ"
|
showLess: "ປິດ"
|
||||||
youGotNewFollower: "ໄດ້ຕິດຕາມທ່ານ"
|
youGotNewFollower: "ໄດ້ຕິດຕາມເຈົ້າ"
|
||||||
receiveFollowRequest: "ປະຕິບັດຕາມຄໍາຮ້ອງຂໍທີ່ໄດ້ຮັບ"
|
receiveFollowRequest: "ມີຄຳຂໍຕິດຕາມສົ່ງມາ"
|
||||||
followRequestAccepted: "ຜູ້ຕິດຕາມໄດ້ຍອມຮັບຄໍາຮ້ອງຂໍຂອງທ່ານ"
|
followRequestAccepted: "ການຕິດຕາມໄດ້ຮັບອນຸຍາດແລ້ວ"
|
||||||
mention: "ກ່າວຖືງ"
|
mention: "ເວົ້າເຖີງ"
|
||||||
mentions: "ກ່າວເຖິງ"
|
mentions: "ເວົ້າເຖີງເຈົ້າ"
|
||||||
directNotes: "ໂພສ Direct note"
|
directNotes: "ໂພສ Direct note"
|
||||||
importAndExport: "ນໍາເຂົ້າ / ສົ່ງອອກ"
|
importAndExport: "ນໍາເຂົ້າ / ສົ່ງອອກ"
|
||||||
import: "ນຳເຂົ້າ"
|
import: "ນຳເຂົ້າ"
|
||||||
export: "ສົ່ງອອກ"
|
export: "ສົ່ງອອກ"
|
||||||
files: "ໄຟລ໌"
|
files: "ໄຟລ໌"
|
||||||
download: "ດາວໂຫລດ"
|
download: "ດາວໂຫລດ"
|
||||||
driveFileDeleteConfirm: "ທ່ານແນ່ໃຈບໍ່ວ່າຕ້ອງການລຶບໄຟລ໌ \"{name}\"? note ທີ່ມີໄຟລ໌ແນບນີ້ຈະຖືກລຶບຖິ້ມ"
|
driveFileDeleteConfirm: "ຕ້ອງການລຶບໄຟລ໌ “{name}” ແມ່ນບໍ່? Note ທີ່ແນບມາກັບໄຟລ໌ນີ້ຈະຖືກລຶບອອກ"
|
||||||
unfollowConfirm: "ທ່ານແນ່ໃຈບໍ່ວ່າຕ້ອງການເຊົາຕິດຕາມ {name}?"
|
unfollowConfirm: "ຕ້ອງການເລີກຕິດຕາມ {name} ແມ່ນບໍ່?"
|
||||||
exportRequested: "ໃນເວລາທີ່ທ່ານໄດ້ຮ້ອງຂໍການສົ່ງອອກ ມັນອາດຈະໃຊ້ເວລາບາງເວລາ ແລະມັນຈະຖືກເພີ່ມໃສ່ drive ຂອງທ່ານເມື່ອມັນສຳເລັດແລ້ວ"
|
exportRequested: "ເຈົ້າໄດ້ຮ້ອງຂໍການສົ່ງອອກ ອາດໃຊ້ເວລາຈັກໜ່ອຍ ເມື່ອແລ້ວຈະຖືກເພີ່ມໃສ່ drive"
|
||||||
importRequested: "ໃນເວລາທີ່ທ່ານໄດ້ຮ້ອງຂໍການນໍາເຂົ້າ ມັນອາດຈະໃຊ້ເວລາບາງເວລາ"
|
importRequested: "ເຈົ້າໄດ້ຮ້ອງຂໍການນຳເຂົ້າ ການດຳເນິນການນີ້ອາດໃຊ້ເວລາຈັກໜ່ອຍ"
|
||||||
lists: "ລາຍການ"
|
lists: "ລາຍການ"
|
||||||
noLists: "ທ່ານບໍ່ມີລາຍການໃດໆ"
|
noLists: "ບໍ່ມີລາຍການໃດໆ"
|
||||||
note: "ບັນທຶກ"
|
note: "Note"
|
||||||
notes: "ບັນທຶກ"
|
notes: "Note"
|
||||||
following: "ກຳລັງຕິດຕາມ"
|
following: "ກຳລັງຕິດຕາມ"
|
||||||
followers: "ຜູ້ຕິດຕາມ"
|
followers: "ຜູ້ຕິດຕາມ"
|
||||||
followsYou: "ຕິດຕາມເຈົ້າ"
|
followsYou: "ຕິດຕາມເຈົ້າ"
|
||||||
|
@ -124,11 +124,11 @@ reactions: "reaction"
|
||||||
attachCancel: "ເອົາໄຟລ໌ແນບ"
|
attachCancel: "ເອົາໄຟລ໌ແນບ"
|
||||||
mute: "ປີດສຽງ"
|
mute: "ປີດສຽງ"
|
||||||
unmute: "ເປີດສຽງ"
|
unmute: "ເປີດສຽງ"
|
||||||
block: "ບ໋ອກ"
|
block: "ບລັອກ"
|
||||||
unblock: "ຍົກເລີກກາຮົບລັອກ"
|
unblock: "ເລີກບລັອກ"
|
||||||
suspend: "ລະງັບ"
|
suspend: "ລະງັບ"
|
||||||
unsuspend: "ເຊົາລະງັບ"
|
unsuspend: "ເຊົາລະງັບ"
|
||||||
selectList: "ເລືອກບັນຊີລາຍການ"
|
selectList: "ເລືອກລາຍຊື່"
|
||||||
editList: "ແກ້ໄຂລາຍຊື່"
|
editList: "ແກ້ໄຂລາຍຊື່"
|
||||||
selectChannel: "ເລືອກຊ່ອງ"
|
selectChannel: "ເລືອກຊ່ອງ"
|
||||||
selectAntenna: "ເລືອກເສົາອາກາດ"
|
selectAntenna: "ເລືອກເສົາອາກາດ"
|
||||||
|
@ -151,30 +151,30 @@ flagShowTimelineRepliesDescription: "ສະແດງການຕອບກັບ
|
||||||
autoAcceptFollowed: "ອະນຸມັດອັດຕະໂນມັດຕາມຄຳຮ້ອງຂໍຈາກຜູ້ໃຊ້ທີ່ທ່ານກຳລັງຕິດຕາມຢູ່"
|
autoAcceptFollowed: "ອະນຸມັດອັດຕະໂນມັດຕາມຄຳຮ້ອງຂໍຈາກຜູ້ໃຊ້ທີ່ທ່ານກຳລັງຕິດຕາມຢູ່"
|
||||||
addAccount: "ເພີ່ມບັນຊີ"
|
addAccount: "ເພີ່ມບັນຊີ"
|
||||||
loginFailed: "ການເຂົ້າສູ່ລະບົບບໍ່ສຳເລັດ"
|
loginFailed: "ການເຂົ້າສູ່ລະບົບບໍ່ສຳເລັດ"
|
||||||
showOnRemote: "ເບິ່ງຢູ່ໃນຕົວຢ່າງໄລຍະໄກ"
|
showOnRemote: "ເບິ່ງໃນເຊີຟເວີຣ໌ໄລຍະໄກ"
|
||||||
general: "ທົ່ວໄປ"
|
general: "ທົ່ວໄປ"
|
||||||
wallpaper: "ພາບພື້ນຫລັງ"
|
wallpaper: "ພາບພື້ນຫລັງ"
|
||||||
setWallpaper: "ຕັ້ງເປັນພາບພື້ນຫຼັງ"
|
setWallpaper: "ຕັ້ງເປັນພາບພື້ນຫຼັງ"
|
||||||
removeWallpaper: "ລຶບຮູບວໍເປເປີອອກ"
|
removeWallpaper: "ລຶບຮູບວໍເປເປີອອກ"
|
||||||
searchWith: "ຊອກຫາ: {q}"
|
searchWith: "ຊອກຫາ: {q}"
|
||||||
youHaveNoLists: "ທ່ານບໍ່ມີລາຍການໃດໆ"
|
youHaveNoLists: "ເຈົ້າບໍ່ມີລາຍຊື່ໃດໆ"
|
||||||
proxyAccount: "ບັນຊີພຣັອກຊີ"
|
proxyAccount: "ບັນຊີພຣັອກຊີ"
|
||||||
host: "ໂຮດສ"
|
host: "ໂຮສຕ໌"
|
||||||
selectUser: "ເລືອກຜູ້ໃຊ້"
|
selectUser: "ເລືອກຜູ້ໃຊ້"
|
||||||
recipient: "ເຖິງ"
|
recipient: "ເຖິງ"
|
||||||
annotation: "ຄຳເຫັນ"
|
annotation: "ຄຳເຫັນ"
|
||||||
federation: "ສະຫະພັນ"
|
federation: "ສະຫະພັນ"
|
||||||
instances: "ອີນສະແຕນ"
|
instances: "ເຊີຟເວີຣ໌"
|
||||||
registeredAt: "ລົງທະບຽນຢູ່"
|
registeredAt: "ລົງທະບຽນຢູ່"
|
||||||
storageUsage: "ບ່ອນຈັດເກັບຂໍ້ມູນທີ່ໃຊ້"
|
storageUsage: "ບ່ອນຈັດເກັບຂໍ້ມູນທີ່ໃຊ້"
|
||||||
charts: "ອັນດັບເພງ"
|
charts: "ແຜນພູມ"
|
||||||
perHour: "ຕໍ່ຊົ່ວໂມງ"
|
perHour: "ຕໍ່ຊົ່ວໂມງ"
|
||||||
perDay: "ຕໍ່ມື້"
|
perDay: "ຕໍ່ມື້"
|
||||||
stopActivityDelivery: "ຢຸດເຊົາການສົ່ງກິດຈະກໍາ"
|
stopActivityDelivery: "ຢຸດເຊົາການສົ່ງກິດຈະກໍາ"
|
||||||
blockThisInstance: "ຂັດຂວາງຕົວຢ່າງນີ້"
|
blockThisInstance: "ຂັດຂວາງຕົວຢ່າງນີ້"
|
||||||
operations: "ການດຳເນີນງານ"
|
operations: "ການດຳເນີນງານ"
|
||||||
software: "ຊອບແວ"
|
software: "ຊອບແວ"
|
||||||
version: "ສະບັບ"
|
version: "ເວີຣ໌ຊັນ"
|
||||||
metadata: "Metadata"
|
metadata: "Metadata"
|
||||||
withNFiles: "{n} ໄຟລ໌(s)"
|
withNFiles: "{n} ໄຟລ໌(s)"
|
||||||
monitor: "ຈໍພາບ"
|
monitor: "ຈໍພາບ"
|
||||||
|
@ -199,15 +199,15 @@ federating: "ສະຫະພັນ"
|
||||||
blocked: "ບລັອກແລ້ວ "
|
blocked: "ບລັອກແລ້ວ "
|
||||||
suspended: "ໂຈະ"
|
suspended: "ໂຈະ"
|
||||||
all: "ທັງໝົດ"
|
all: "ທັງໝົດ"
|
||||||
subscribing: "ສະໝັກສະມາຊິກແລັວ"
|
subscribing: "ກຳລັງສະມັກສະມາຊິກ"
|
||||||
publishing: "ການພິມເຜີຍແຜ່"
|
publishing: "ກຳລັງເຜີຍແພ່"
|
||||||
notResponding: "ບໍ່ຕອບສະໜອງ"
|
notResponding: "ບໍ່ຕອບສະໜອງ"
|
||||||
instanceFollowing: "ກຳລັງຕິດຕາມສຸດຕົວຢ່າງ"
|
instanceFollowing: "ກຳລັງຕິດຕາມບົນເຊີຟເວີຣ໌"
|
||||||
instanceFollowers: "ຜູ້ຕິດຕາມຕົວຢ່າງ"
|
instanceFollowers: "ຜູ້ຕິດຕາມຂອງເຊີຟເວີຣ໌"
|
||||||
instanceUsers: "ຜູ້ຊົມໃຊ້ຂອງຕົວຢ່າງນີ້"
|
instanceUsers: "ຜູ້ໃຊ້ຂອງເຊີຟເວີຣ໌ນີ້"
|
||||||
changePassword: "ປ່ຽນລະຫັດຜ່ານ"
|
changePassword: "ປ່ຽນລະຫັດຜ່ານ"
|
||||||
security: "ຄວາມປອດໄພ"
|
security: "ຄວາມປອດໄພ"
|
||||||
retypedNotMatch: "ວັດສະດຸປ້ອນບໍ່ກົງກັນ"
|
retypedNotMatch: "ປ້ອນຂໍ້ມູນບໍ່ກົງກັນ"
|
||||||
currentPassword: "ລະຫັດຜ່ານປະຈຸບັນ"
|
currentPassword: "ລະຫັດຜ່ານປະຈຸບັນ"
|
||||||
newPassword: "ລະຫັດຜ່ານໃໝ່"
|
newPassword: "ລະຫັດຜ່ານໃໝ່"
|
||||||
newPasswordRetype: "ໃສ່ລະຫັດຜ່ານໃໝ່ອີກເທື່ອໜຶ່ງ"
|
newPasswordRetype: "ໃສ່ລະຫັດຜ່ານໃໝ່ອີກເທື່ອໜຶ່ງ"
|
||||||
|
@ -223,14 +223,14 @@ remove: "ລຶບ"
|
||||||
removed: "ລຶບແລ້ວ"
|
removed: "ລຶບແລ້ວ"
|
||||||
resetAreYouSure: "ຣີເຊັດບໍ?"
|
resetAreYouSure: "ຣີເຊັດບໍ?"
|
||||||
saved: "ບັນທຶກແລ້ວ"
|
saved: "ບັນທຶກແລ້ວ"
|
||||||
messaging: "ແຊ໋ດ"
|
messaging: "ແຊັຕ"
|
||||||
upload: "ອັບໂຫຼດ"
|
upload: "ອັບໂຫຼດ"
|
||||||
keepOriginalUploading: "ຮັກສາຮູບພາບຕົ້ນສະບັບ"
|
keepOriginalUploading: "ຮັກສາຮູບພາບຕົ້ນສະບັບ"
|
||||||
fromDrive: "ຈາກ Drive"
|
fromDrive: "ຈາກ Drive"
|
||||||
fromUrl: "ຈາກ URL"
|
fromUrl: "ຈາກ URL"
|
||||||
uploadFromUrl: "ອັບໂຫຼດຈາກ URL"
|
uploadFromUrl: "ອັບໂຫຼດຈາກ URL"
|
||||||
uploadFromUrlDescription: "URL ຂອງໄຟລ໌ທີ່ທ່ານຕ້ອງການອັບໂຫລດ"
|
uploadFromUrlDescription: "URL ຂອງໄຟລ໌ທີ່ທ່ານຕ້ອງການອັບໂຫລດ"
|
||||||
uploadFromUrlRequested: "ຮ້ອງຂໍການອັບໂຫລດ"
|
uploadFromUrlRequested: "ຮ້ອງຂໍການອັບໂຫລດແລ້ວ"
|
||||||
explore: "ສຳຫຼວດ"
|
explore: "ສຳຫຼວດ"
|
||||||
messageRead: "ອ່ານແລ້ວ"
|
messageRead: "ອ່ານແລ້ວ"
|
||||||
startMessaging: "ເລີ່ມການສົນທະນາໃໝ່"
|
startMessaging: "ເລີ່ມການສົນທະນາໃໝ່"
|
||||||
|
@ -244,47 +244,47 @@ images: "ຮູບພາບ"
|
||||||
image: "ຮູບພາບ"
|
image: "ຮູບພາບ"
|
||||||
birthday: "ວັນເກີດ"
|
birthday: "ວັນເກີດ"
|
||||||
yearsOld: "{age} ປີ"
|
yearsOld: "{age} ປີ"
|
||||||
registeredDate: "ວັນທີ່ເປັນສະມາຊິກ"
|
registeredDate: "ວັນທີ່ລົງທະບຽນ"
|
||||||
location: "ທີ່ຕັ້ງ"
|
location: "ທີ່ຕັ້ງ"
|
||||||
theme: "ແທ໋ມ"
|
theme: "Theme"
|
||||||
themeForLightMode: "ຮູບແບບສີສັນເພື່ອໃຊ້ໃນໂໝດແສງ"
|
themeForLightMode: "Theme ໃຊ້ໃນໂໝດສະຫວ່າງ"
|
||||||
themeForDarkMode: "ຮູບແບບສີສັນທີ່ຈະໃຊ້ຢູ່ໃນໂໝດມືດ"
|
themeForDarkMode: "Theme ໃຊ້ໃນໂໝດມືດ"
|
||||||
light: "ສະຫວ່າງ"
|
light: "ສະຫວ່າງ"
|
||||||
dark: "ມືດ"
|
dark: "ມືດ"
|
||||||
lightThemes: "ຊຸດຮູບແບບສະຫວ່າງ"
|
lightThemes: "ຊຸດຮູບແບບສະຫວ່າງ"
|
||||||
darkThemes: "ຮູບແບບສີສັນມືດ"
|
darkThemes: "ຮູບແບບສີສັນມືດ"
|
||||||
syncDeviceDarkMode: "ຊິງຄ໌ໂໝດມືດກັບການຕັ້ງຄ່າທົ່ວອຸປະກອນ"
|
syncDeviceDarkMode: "ຊິງຄ໌ໂໝດມືດກັບການຕັ້ງຄ່າທົ່ວອຸປະກອນ"
|
||||||
drive: "ຂັບ"
|
drive: "Drive"
|
||||||
fileName: "ຊື່ໄຟລ໌"
|
fileName: "ຊື່ໄຟລ໌"
|
||||||
selectFile: "ເລືອກໄຟລ໌"
|
selectFile: "ເລືອກໄຟລ໌"
|
||||||
selectFiles: "ເລືອກໄຟລ໌"
|
selectFiles: "ເລືອກໄຟລ໌"
|
||||||
selectFolder: "ເລືອກໂຟລເດີ"
|
selectFolder: "ເລືອກໂຟລເດີ"
|
||||||
selectFolders: "ເລືອກໂຟລເດີ"
|
selectFolders: "ເລືອກໂຟລເດີ"
|
||||||
renameFile: "ປ່ຽນຊື່ໄຟລ໌"
|
renameFile: "ປ່ຽນຊື່ໄຟລ໌"
|
||||||
folderName: "ຊື່ໂຟນເດີ"
|
folderName: "ຊື່ໂຟລເດີຣ໌"
|
||||||
createFolder: "ສ້າງໂຟລເດີ"
|
createFolder: "ສ້າງໂຟລເດີ"
|
||||||
renameFolder: "ປ່ຽນຊື່ໂຟນເດີນີ້"
|
renameFolder: "ປ່ຽນຊື່ໂຟນເດີນີ້"
|
||||||
deleteFolder: "ລົບໂຟລເດີ"
|
deleteFolder: "ລົບໂຟລເດີ"
|
||||||
addFile: "ເພີ່ມໄຟລ໌"
|
addFile: "ເພີ່ມໄຟລ໌"
|
||||||
emptyDrive: "Drive ຂອງທ່ານຫວ່າງເປົ່າ"
|
emptyDrive: "Drive ຂອງທ່ານຫວ່າງເປົ່າ"
|
||||||
emptyFolder: "ໂຟນເດີນີ້ເປົ່າຫວ່າງ"
|
emptyFolder: "ໂຟລເດີຣ໌ນີ້ວ່າງເປົ່າ"
|
||||||
unableToDelete: "ບໍ່ສາມາດລົບໄດ້"
|
unableToDelete: "ບໍ່ສາມາດລົບໄດ້"
|
||||||
inputNewFileName: "ໃສ່ຊື່ໄຟລ໌ໃໝ່"
|
inputNewFileName: "ໃສ່ຊື່ໄຟລ໌ໃໝ່"
|
||||||
inputNewDescription: "ໃສ່ຄຳບັນຍາຍໃໝ່"
|
inputNewDescription: "ໃສ່ຄຳບັນຍາຍໃໝ່"
|
||||||
inputNewFolderName: "ໃສ່ຊື່ໂຟນເດີໃໝ່"
|
inputNewFolderName: "ໃສ່ຊື່ໂຟນເດີໃໝ່"
|
||||||
circularReferenceFolder: "ໂຟນເດີປາຍທາງແມ່ນໂຟນເດີຍ່ອຍຂອງໂຟນເດີທີ່ທ່ານຕ້ອງການຍ້າຍ"
|
circularReferenceFolder: "ໂຟນເດີປາຍທາງແມ່ນໂຟນເດີຍ່ອຍຂອງໂຟນເດີທີ່ທ່ານຕ້ອງການຍ້າຍ"
|
||||||
rename: "ປ່ຽນຊື່"
|
rename: "ປ່ຽນຊື່"
|
||||||
doNothing: "ບໍ່ສົນໃຈ"
|
doNothing: "ຢ່າມັນ"
|
||||||
watch: "ເບິ່ງ"
|
watch: "ເພັ່ງເລັງ"
|
||||||
unwatch: "ຢຸດເບິ່ງ"
|
unwatch: "ຢຸດເພັ່ງເລັງ"
|
||||||
accept: "ອະນຸຍາດ"
|
accept: "ອະນຸຍາດ"
|
||||||
reject: "ປະຕິເສດ"
|
reject: "ປະຕິເສດ"
|
||||||
normal: "ປົກກະຕິ"
|
normal: "ປົກກະຕິ"
|
||||||
instanceName: "ຊື່ເຊີເວີ້"
|
instanceName: "ຊື່ເຊີເວີ້"
|
||||||
instanceDescription: "ຄໍາອະທິບາຍຕົວຢ່າງ"
|
instanceDescription: "ຄຳອະທິບາຍແນະນຳເຊີຟເວີຣ໌"
|
||||||
maintainerName: "ຜູ້ດູແລ"
|
maintainerName: "ຜູ້ດູແລ"
|
||||||
maintainerEmail: "ອີເມວ admin"
|
maintainerEmail: "ອີເມລຜູ້ດູແລ"
|
||||||
tosUrl: "ເງື່ອນໄຂການໃຫ້ບໍລິການ URL"
|
tosUrl: " URL ເງື່ອນໄຂການໃຫ້ບໍລິການ"
|
||||||
thisYear: "ປີນີ້"
|
thisYear: "ປີນີ້"
|
||||||
thisMonth: "ເດືອນນີ້"
|
thisMonth: "ເດືອນນີ້"
|
||||||
today: "ມື້ນີ້"
|
today: "ມື້ນີ້"
|
||||||
|
@ -292,34 +292,34 @@ dayX: "ວັນ {day}"
|
||||||
monthX: "ເດືອນ {month}"
|
monthX: "ເດືອນ {month}"
|
||||||
yearX: "ປີ {year}"
|
yearX: "ປີ {year}"
|
||||||
pages: "ໜ້າ"
|
pages: "ໜ້າ"
|
||||||
integration: "ຄວາມສຳພັນຂອງ"
|
integration: "ເຊື່ອມໂຍງ"
|
||||||
connectService: "ເຊື່ອມຕໍ່"
|
connectService: "ເຊື່ອມຕໍ່"
|
||||||
disconnectService: "ຕັດການເຊື່ອມຕໍ່"
|
disconnectService: "ຕັດການເຊື່ອມຕໍ່"
|
||||||
enableLocalTimeline: "ເປີດໃຊ້ທາມລາຍທ້ອງຖິ່ນ"
|
enableLocalTimeline: "ເປີດໃຊ້ທາມລາຍທ້ອງຖິ່ນ"
|
||||||
enableGlobalTimeline: "ເປີດໃຊ້ທາມລາຍທົ່ວໂລກ"
|
enableGlobalTimeline: "ເປີດໃຊ້ທາມລາຍທົ່ວໂລກ"
|
||||||
disablingTimelinesInfo: "ຜູ້ເບິ່ງແຍງລະບົບ ແລະຜູ້ຄວບຄຸມຈະມີການເຂົ້າເຖິງທຸກກຳນົດເວລາ, ເຖິງແມ່ນວ່າຈະບໍ່ໄດ້ເປີດໃຊ້ງານກໍຕາມ"
|
disablingTimelinesInfo: "ຜູ້ດູແລລະບບແລະຜູ້ຄວບຄຸມຈະສາມາດເຂົ້າເຖີງໄທມ໌ໄລນ໌ທັ້ງເບີດ ເຖີງວ່າຈະບໍ່ໄດ້ເປີດໃຊ້ງານກໍ່ຕາມ"
|
||||||
registration: "ລົງທະບຽນ"
|
registration: "ລົງທະບຽນ"
|
||||||
enableRegistration: "ເປີດໃຊ້ການລົງທະບຽນຜູ້ໃຊ້ໃໝ່"
|
enableRegistration: "ເປີດໃຊ້ການລົງທະບຽນຜູ້ໃຊ້ໃໝ່"
|
||||||
invite: "ເຊີນ"
|
invite: "ເຊີນ"
|
||||||
driveCapacityPerLocalAccount: "ຄວາມອາດສາມາດຂັບຕໍ່ຜູ້ໃຊ້ທ້ອງຖິ່ນ"
|
driveCapacityPerLocalAccount: "ຄວາມຈຸຂອງ drive ຕໍ່ຜູ້ໃຊ້ທ້ອງຖິ່ນ"
|
||||||
driveCapacityPerRemoteAccount: "ໄດຣຟ໌ຄວາມອາດສາມາດຕໍ່ຜູ້ໃຊ້ທາງໄກ"
|
driveCapacityPerRemoteAccount: "ຄວາມຈຸຂອງ drive ຕໍ່ຜູ້ໃຊ້ໄລຍະໄກ"
|
||||||
basicInfo: "ຂໍ້ມຸນເບື້ອງຕົ້ນ"
|
basicInfo: "ຂໍ້ມຸນເບື້ອງຕົ້ນ"
|
||||||
pinnedNotes: "ບັນທຶກທີ່ປັກໝຸດໄວ້"
|
pinnedNotes: "Note ທີ່ປັກໝຸດໄວ້"
|
||||||
hcaptchaSiteKey: "ກະແຈໄຊທ໌"
|
hcaptchaSiteKey: "Site key"
|
||||||
hcaptchaSecretKey: "ກະແຈລັບ"
|
hcaptchaSecretKey: "Secret key"
|
||||||
mcaptchaSiteKey: "ກະແຈໄຊທ໌"
|
mcaptchaSiteKey: "Site key"
|
||||||
mcaptchaSecretKey: "ກະແຈລັບ"
|
mcaptchaSecretKey: "Secret Key"
|
||||||
recaptcha: "reCAPTCHA"
|
recaptcha: "reCAPTCHA"
|
||||||
enableRecaptcha: "ເປີດໃຊ້ງານລີແຄ໋ບຈາ"
|
enableRecaptcha: "ເປີດໃຊ້ງານ reCAPTCHA"
|
||||||
recaptchaSiteKey: "ກະແຈໄຊທ໌"
|
recaptchaSiteKey: "Site key"
|
||||||
recaptchaSecretKey: "ກະແຈລັບ"
|
recaptchaSecretKey: "Secret key"
|
||||||
turnstileSiteKey: "ກະແຈໄຊທ໌"
|
turnstileSiteKey: "Site key"
|
||||||
turnstileSecretKey: "ກະແຈລັບ"
|
turnstileSecretKey: "Secret key"
|
||||||
name: "ຊື່"
|
name: "ຊື່"
|
||||||
userList: "ລາຍການ"
|
userList: "ລາຍການ"
|
||||||
about: "ກ່ຽວກັບ"
|
about: "ກ່ຽວກັບ"
|
||||||
aboutMisskey: "ກ່ຽວກັບ Misskey"
|
aboutMisskey: "ກ່ຽວກັບ Misskey"
|
||||||
administrator: "ຜູ້ບໍລິຫານ"
|
administrator: "ຜູ້ດູແລ"
|
||||||
token: "ໂທເຄັນ"
|
token: "ໂທເຄັນ"
|
||||||
share: "ແບ່ງປັນ"
|
share: "ແບ່ງປັນ"
|
||||||
notFound: "ບໍ່ພົບ"
|
notFound: "ບໍ່ພົບ"
|
||||||
|
@ -332,27 +332,27 @@ title: "ຫົວຂໍ້"
|
||||||
text: "ຂໍ້ຄວາມ"
|
text: "ຂໍ້ຄວາມ"
|
||||||
enable: "ເປີດໃຊ້"
|
enable: "ເປີດໃຊ້"
|
||||||
next: "ຕໍ່ໄປ"
|
next: "ຕໍ່ໄປ"
|
||||||
retype: "ເຂົ້າໄປອີກຄັ້ງ"
|
retype: "ລອງພິມລະຫັດອີກເທື່ອໜຶ່ງ"
|
||||||
quoteAttached: "ວົງຢືມ"
|
quoteAttached: "ອ້າງອິງ"
|
||||||
invitations: "ເຊີນ"
|
invitations: "ເຊີນ"
|
||||||
unavailable: "ບໍ່ສາມາດໃຊ້ໄດ້"
|
unavailable: "ບໍ່ສາມາດໃຊ້ໄດ້"
|
||||||
language: "ພາສາ"
|
language: "ພາສາ"
|
||||||
aboutX: "ກ່ຽວກັບ {x}"
|
aboutX: "ກ່ຽວກັບ {x}"
|
||||||
emojiStyle: "ຮູບແບບອີໂມຈິ"
|
emojiStyle: "ຮູບແບບອີໂມຈິ"
|
||||||
native: "ພາສາແມ່"
|
native: "ພາສາແມ່"
|
||||||
noHistory: "ບໍ່ມີລາຍການຢູ່ບ່ອນນີ້"
|
noHistory: "ບໍ່ມີປະຫວັດ"
|
||||||
doing: "ກຳລັງປະມວນຜົນ..."
|
doing: "ກຳລັງປະມວນຜົນ..."
|
||||||
category: "ຫມວດຫມູ່"
|
category: "ຫມວດຫມູ່"
|
||||||
tags: "ແທ໋ກ"
|
tags: "Aliases"
|
||||||
createAccount: "ສ້າງບັນຊີ"
|
createAccount: "ສ້າງບັນຊີ"
|
||||||
existingAccount: "ທີ່ມີຢູ່"
|
existingAccount: "ບັນຊີທີ່ມີຢູ່ແລ້ວ"
|
||||||
dashboard: "ໜ້າປັດ"
|
dashboard: "Dashboard"
|
||||||
local: "ທ້ອງຖິ່ນ"
|
local: "ທ້ອງຖິ່ນ"
|
||||||
numberOfDays: "ຈຳນວນມື້"
|
numberOfDays: "ຈຳນວນມື້"
|
||||||
objectStorageBucket: "Bucket"
|
objectStorageBucket: "Bucket"
|
||||||
objectStoragePrefix: "Prefix"
|
objectStoragePrefix: "Prefix"
|
||||||
objectStorageEndpoint: "Endpoint"
|
objectStorageEndpoint: "Endpoint"
|
||||||
objectStorageRegion: "ພາກພື້ນ"
|
objectStorageRegion: "ພູມິພາກ"
|
||||||
deleteAll: "ລຶບທັງໝົດ"
|
deleteAll: "ລຶບທັງໝົດ"
|
||||||
sounds: "ສຽງ"
|
sounds: "ສຽງ"
|
||||||
sound: "ສຽງ"
|
sound: "ສຽງ"
|
||||||
|
@ -365,11 +365,11 @@ state: "ສະຖານະ"
|
||||||
sort: "ຈັດຮຽງໂດຍ"
|
sort: "ຈັດຮຽງໂດຍ"
|
||||||
ascendingOrder: "ນ້ອຍໄປຫາໃຫຍ່"
|
ascendingOrder: "ນ້ອຍໄປຫາໃຫຍ່"
|
||||||
descendingOrder: "ໃຫຍ່ຫານ້ອຍ"
|
descendingOrder: "ໃຫຍ່ຫານ້ອຍ"
|
||||||
output: "ຜົນຜະລິດ"
|
output: "Output"
|
||||||
script: "ບົດຄວາມ"
|
script: "Script"
|
||||||
menu: "ເມນູ"
|
menu: "ເມນູ"
|
||||||
rearrange: "ຈັດລຽງຄືນ"
|
rearrange: "ຈັດລຽງໃໝ່"
|
||||||
poll: "ການພູນ"
|
poll: "Poll"
|
||||||
description: "ລາຍລະອຽດ"
|
description: "ລາຍລະອຽດ"
|
||||||
author: "ຜູ້ຂຽນ"
|
author: "ຜູ້ຂຽນ"
|
||||||
manage: "ການຈັດການ"
|
manage: "ການຈັດການ"
|
||||||
|
@ -383,7 +383,7 @@ permission: "ການອະນຸຍາດ"
|
||||||
notificationType: "ປະເພດການແຈ້ງເຕືອນ"
|
notificationType: "ປະເພດການແຈ້ງເຕືອນ"
|
||||||
edit: "ແກ້ໄຂ"
|
edit: "ແກ້ໄຂ"
|
||||||
email: "ອີເມວ"
|
email: "ອີເມວ"
|
||||||
smtpHost: "ໂຮດສ"
|
smtpHost: "ໂຮສຕ໌"
|
||||||
smtpUser: "ຊື່ຜູ້ໃຊ້"
|
smtpUser: "ຊື່ຜູ້ໃຊ້"
|
||||||
smtpPass: "ລະຫັດຜ່ານ"
|
smtpPass: "ລະຫັດຜ່ານ"
|
||||||
clearCache: "ລຶບລ້າງແຄສ"
|
clearCache: "ລຶບລ້າງແຄສ"
|
||||||
|
@ -393,12 +393,12 @@ administration: "ການຈັດການ"
|
||||||
middle: "ປານກາງ"
|
middle: "ປານກາງ"
|
||||||
searchByGoogle: "ຄົ້ນຫາ"
|
searchByGoogle: "ຄົ້ນຫາ"
|
||||||
file: "ໄຟລ໌"
|
file: "ໄຟລ໌"
|
||||||
replies: "ຕອບໄປທີ"
|
replies: "ຕອບກັບ"
|
||||||
renotes: "Renote"
|
renotes: "Renote"
|
||||||
_delivery:
|
_delivery:
|
||||||
stop: "ໂຈະ"
|
stop: "ໂຈະ"
|
||||||
_type:
|
_type:
|
||||||
none: "ການພິມເຜີຍແຜ່"
|
none: "ກຳລັງເຜີຍແພ່"
|
||||||
_role:
|
_role:
|
||||||
_priority:
|
_priority:
|
||||||
middle: "ປານກາງ"
|
middle: "ປານກາງ"
|
||||||
|
@ -416,8 +416,8 @@ _sfx:
|
||||||
_2fa:
|
_2fa:
|
||||||
renewTOTPCancel: "ບໍ່ແມ່ນຕອນນີ້"
|
renewTOTPCancel: "ບໍ່ແມ່ນຕອນນີ້"
|
||||||
_widgets:
|
_widgets:
|
||||||
profile: "ໂພຼຟາຍ"
|
profile: "ໂປຣໄຟລ໌"
|
||||||
instanceInfo: "ອີນສະແຕນ"
|
instanceInfo: "ຂໍ້ມູລເຊີຟເວີຣ໌"
|
||||||
notifications: "ການແຈ້ງເຕືອນ"
|
notifications: "ການແຈ້ງເຕືອນ"
|
||||||
timeline: "ເສັ້ນກຳນົດເວລາ"
|
timeline: "ເສັ້ນກຳນົດເວລາ"
|
||||||
activity: "ກິດຈະກຳ"
|
activity: "ກິດຈະກຳ"
|
||||||
|
@ -436,28 +436,28 @@ _profile:
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
followingList: "ກຳລັງຕິດຕາມ"
|
followingList: "ກຳລັງຕິດຕາມ"
|
||||||
muteList: "ປີດສຽງ"
|
muteList: "ປີດສຽງ"
|
||||||
blockingList: "ບ໋ອກ"
|
blockingList: "ບລັອກ"
|
||||||
userLists: "ລາຍການ"
|
userLists: "ລາຍການ"
|
||||||
_charts:
|
_charts:
|
||||||
federation: "ສະຫະພັນ"
|
federation: "ສະຫະພັນ"
|
||||||
_timelines:
|
_timelines:
|
||||||
home: "ໜ້າຫຼັກ"
|
home: "ໜ້າຫຼັກ"
|
||||||
_play:
|
_play:
|
||||||
script: "ບົດຄວາມ"
|
script: "Script"
|
||||||
summary: "ລາຍລະອຽດ"
|
summary: "ລາຍລະອຽດ"
|
||||||
_pages:
|
_pages:
|
||||||
blocks:
|
blocks:
|
||||||
image: "ຮູບພາບ"
|
image: "ຮູບພາບ"
|
||||||
_notification:
|
_notification:
|
||||||
youWereFollowed: "ໄດ້ຕິດຕາມທ່ານ"
|
youWereFollowed: "ໄດ້ຕິດຕາມເຈົ້າ"
|
||||||
_types:
|
_types:
|
||||||
follow: "ກຳລັງຕິດຕາມ"
|
follow: "ກຳລັງຕິດຕາມ"
|
||||||
mention: "ໄດ້ກ່າວມາ"
|
mention: "ໄດ້ກ່າວເຖິງ"
|
||||||
renote: "Renote"
|
renote: "Renote"
|
||||||
quote: "ລວມຂໍ້ຄວາມອ້າງອີງ"
|
quote: "ອ້າງອີງ"
|
||||||
reaction: "ປະຕິກິລິຍາ"
|
reaction: "Reaction"
|
||||||
_actions:
|
_actions:
|
||||||
reply: "ຕອບໄປທີ"
|
reply: "ຕອບກັບ"
|
||||||
renote: "Renote"
|
renote: "Renote"
|
||||||
_deck:
|
_deck:
|
||||||
_columns:
|
_columns:
|
||||||
|
@ -465,8 +465,12 @@ _deck:
|
||||||
tl: "ເສັ້ນກຳນົດເວລາ"
|
tl: "ເສັ້ນກຳນົດເວລາ"
|
||||||
list: "ລາຍການ"
|
list: "ລາຍການ"
|
||||||
channel: "ຊ່ອງ"
|
channel: "ຊ່ອງ"
|
||||||
mentions: "ກ່າວເຖິງ"
|
mentions: "ກ່າວເຖິງເຈົ້າ"
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
name: "ຊື່"
|
name: "ຊື່"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "ອີເມວ"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "ລະງັບ"
|
suspend: "ລະງັບ"
|
||||||
|
|
|
@ -721,5 +721,9 @@ _deck:
|
||||||
direct: "Direkte"
|
direct: "Direkte"
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
name: "Navn"
|
name: "Navn"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "E-post"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "Suspender"
|
suspend: "Suspender"
|
||||||
|
|
|
@ -1221,8 +1221,6 @@ _sfx:
|
||||||
note: "Wpisy"
|
note: "Wpisy"
|
||||||
noteMy: "Mój wpis"
|
noteMy: "Mój wpis"
|
||||||
notification: "Powiadomienia"
|
notification: "Powiadomienia"
|
||||||
antenna: "Anteny"
|
|
||||||
channel: "Powiadomienia kanału"
|
|
||||||
_ago:
|
_ago:
|
||||||
future: "W przyszłości"
|
future: "W przyszłości"
|
||||||
justNow: "Przed chwilą"
|
justNow: "Przed chwilą"
|
||||||
|
@ -1556,6 +1554,10 @@ _webhookSettings:
|
||||||
renote: "Po udostępnieniu wpisu"
|
renote: "Po udostępnieniu wpisu"
|
||||||
reaction: "Po otrzymaniu reakcji"
|
reaction: "Po otrzymaniu reakcji"
|
||||||
mention: "Po zostaniu wspomnianym"
|
mention: "Po zostaniu wspomnianym"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "Adres e-mail"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "Zawieś"
|
suspend: "Zawieś"
|
||||||
resetPassword: "Zresetuj hasło"
|
resetPassword: "Zresetuj hasło"
|
||||||
|
|
|
@ -1500,6 +1500,10 @@ _webhookSettings:
|
||||||
follow: "Quando seguindo um usuário"
|
follow: "Quando seguindo um usuário"
|
||||||
followed: "Quando sendo seguido"
|
followed: "Quando sendo seguido"
|
||||||
renote: "Quando repostado"
|
renote: "Quando repostado"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "E-mail"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "Suspender"
|
suspend: "Suspender"
|
||||||
resetPassword: "Redefinir senha"
|
resetPassword: "Redefinir senha"
|
||||||
|
|
|
@ -728,6 +728,10 @@ _deck:
|
||||||
mentions: "Mențiuni"
|
mentions: "Mențiuni"
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
name: "Nume"
|
name: "Nume"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "Email"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "Suspendă"
|
suspend: "Suspendă"
|
||||||
resetPassword: "Resetează parola"
|
resetPassword: "Resetează parola"
|
||||||
|
|
|
@ -1612,8 +1612,6 @@ _sfx:
|
||||||
note: "Заметки"
|
note: "Заметки"
|
||||||
noteMy: "Собственные заметки"
|
noteMy: "Собственные заметки"
|
||||||
notification: "Уведомления"
|
notification: "Уведомления"
|
||||||
antenna: "Антенна"
|
|
||||||
channel: "Канал"
|
|
||||||
_ago:
|
_ago:
|
||||||
future: "Из будущего"
|
future: "Из будущего"
|
||||||
justNow: "Только что"
|
justNow: "Только что"
|
||||||
|
@ -1983,6 +1981,10 @@ _webhookSettings:
|
||||||
createWebhook: "Создать вебхук"
|
createWebhook: "Создать вебхук"
|
||||||
name: "Название"
|
name: "Название"
|
||||||
active: "Вкл."
|
active: "Вкл."
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "Электронная почта"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "Заморозить"
|
suspend: "Заморозить"
|
||||||
addCustomEmoji: "Добавлено эмодзи"
|
addCustomEmoji: "Добавлено эмодзи"
|
||||||
|
|
|
@ -1124,8 +1124,6 @@ _sfx:
|
||||||
note: "Poznámky"
|
note: "Poznámky"
|
||||||
noteMy: "Vlastná poznámka"
|
noteMy: "Vlastná poznámka"
|
||||||
notification: "Oznámenia"
|
notification: "Oznámenia"
|
||||||
antenna: "Antény"
|
|
||||||
channel: "Upozornenia kanála"
|
|
||||||
_ago:
|
_ago:
|
||||||
future: "Budúcnosť"
|
future: "Budúcnosť"
|
||||||
justNow: "Teraz"
|
justNow: "Teraz"
|
||||||
|
@ -1447,6 +1445,10 @@ _deck:
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
name: "Názov"
|
name: "Názov"
|
||||||
active: "Zapnuté"
|
active: "Zapnuté"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "Email"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "Zmraziť"
|
suspend: "Zmraziť"
|
||||||
resetPassword: "Resetovať heslo"
|
resetPassword: "Resetovať heslo"
|
||||||
|
|
|
@ -512,7 +512,6 @@ _theme:
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "Noter"
|
note: "Noter"
|
||||||
notification: "Notifikationer"
|
notification: "Notifikationer"
|
||||||
antenna: "Antenner"
|
|
||||||
_2fa:
|
_2fa:
|
||||||
renewTOTPCancel: "Nej tack"
|
renewTOTPCancel: "Nej tack"
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
|
@ -577,6 +576,10 @@ _deck:
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
name: "Namn"
|
name: "Namn"
|
||||||
active: "Aktiverad"
|
active: "Aktiverad"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "E-post"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "Suspendera"
|
suspend: "Suspendera"
|
||||||
resetPassword: "Återställ Lösenord"
|
resetPassword: "Återställ Lösenord"
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1318,8 +1318,6 @@ _sfx:
|
||||||
note: "Нотатки"
|
note: "Нотатки"
|
||||||
noteMy: "Мої нотатки"
|
noteMy: "Мої нотатки"
|
||||||
notification: "Сповіщення"
|
notification: "Сповіщення"
|
||||||
antenna: "Прийом антени"
|
|
||||||
channel: "Повідомлення каналу"
|
|
||||||
_ago:
|
_ago:
|
||||||
future: "Майбутнє"
|
future: "Майбутнє"
|
||||||
justNow: "Щойно"
|
justNow: "Щойно"
|
||||||
|
@ -1622,6 +1620,10 @@ _deck:
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
name: "Ім'я"
|
name: "Ім'я"
|
||||||
active: "Увімкнено"
|
active: "Увімкнено"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "E-mail"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "Призупинити"
|
suspend: "Призупинити"
|
||||||
resetPassword: "Скинути пароль"
|
resetPassword: "Скинути пароль"
|
||||||
|
|
|
@ -1089,6 +1089,10 @@ _webhookSettings:
|
||||||
_events:
|
_events:
|
||||||
renote: "Qayta qayd qilinganda"
|
renote: "Qayta qayd qilinganda"
|
||||||
mention: "Eslanganda"
|
mention: "Eslanganda"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "Email"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "To'xtatish"
|
suspend: "To'xtatish"
|
||||||
resetPassword: "Parolni tiklash"
|
resetPassword: "Parolni tiklash"
|
||||||
|
|
|
@ -376,6 +376,7 @@ mcaptcha: "mCaptcha"
|
||||||
enableMcaptcha: "Bật mCaptcha"
|
enableMcaptcha: "Bật mCaptcha"
|
||||||
mcaptchaSiteKey: "Khóa của trang"
|
mcaptchaSiteKey: "Khóa của trang"
|
||||||
mcaptchaSecretKey: "Khóa bí mật"
|
mcaptchaSecretKey: "Khóa bí mật"
|
||||||
|
mcaptchaInstanceUrl: "URL mCaptcha máy chủ"
|
||||||
recaptcha: "reCAPTCHA"
|
recaptcha: "reCAPTCHA"
|
||||||
enableRecaptcha: "Bật reCAPTCHA"
|
enableRecaptcha: "Bật reCAPTCHA"
|
||||||
recaptchaSiteKey: "Khóa của trang"
|
recaptchaSiteKey: "Khóa của trang"
|
||||||
|
@ -426,6 +427,7 @@ moderator: "Kiểm duyệt viên"
|
||||||
moderation: "Kiểm duyệt"
|
moderation: "Kiểm duyệt"
|
||||||
moderationNote: "Ghi chú kiểm duyệt"
|
moderationNote: "Ghi chú kiểm duyệt"
|
||||||
addModerationNote: "Thêm ghi chú kiểm duyệt"
|
addModerationNote: "Thêm ghi chú kiểm duyệt"
|
||||||
|
moderationLogs: "Nhật kí quản trị"
|
||||||
nUsersMentioned: "Dùng bởi {n} người"
|
nUsersMentioned: "Dùng bởi {n} người"
|
||||||
securityKeyAndPasskey: "Mã bảo mật・Passkey"
|
securityKeyAndPasskey: "Mã bảo mật・Passkey"
|
||||||
securityKey: "Khóa bảo mật"
|
securityKey: "Khóa bảo mật"
|
||||||
|
@ -458,6 +460,7 @@ retype: "Nhập lại"
|
||||||
noteOf: "Tút của {user}"
|
noteOf: "Tút của {user}"
|
||||||
quoteAttached: "Trích dẫn"
|
quoteAttached: "Trích dẫn"
|
||||||
quoteQuestion: "Trích dẫn lại?"
|
quoteQuestion: "Trích dẫn lại?"
|
||||||
|
attachAsFileQuestion: "Văn bản ở trong bộ nhớ tạm rất dài. Bạn có muốn đăng nó dưới dạng một tệp văn bản không?"
|
||||||
noMessagesYet: "Chưa có tin nhắn"
|
noMessagesYet: "Chưa có tin nhắn"
|
||||||
newMessageExists: "Bạn có tin nhắn mới"
|
newMessageExists: "Bạn có tin nhắn mới"
|
||||||
onlyOneFileCanBeAttached: "Bạn chỉ có thể đính kèm một tập tin"
|
onlyOneFileCanBeAttached: "Bạn chỉ có thể đính kèm một tập tin"
|
||||||
|
@ -1559,8 +1562,6 @@ _sfx:
|
||||||
note: "Tút"
|
note: "Tút"
|
||||||
noteMy: "Tút của tôi"
|
noteMy: "Tút của tôi"
|
||||||
notification: "Thông báo"
|
notification: "Thông báo"
|
||||||
antenna: "Trạm phát sóng"
|
|
||||||
channel: "Kênh"
|
|
||||||
_ago:
|
_ago:
|
||||||
future: "Tương lai"
|
future: "Tương lai"
|
||||||
justNow: "Vừa xong"
|
justNow: "Vừa xong"
|
||||||
|
@ -1922,6 +1923,10 @@ _webhookSettings:
|
||||||
_events:
|
_events:
|
||||||
reaction: "Khi nhận được sự kiện"
|
reaction: "Khi nhận được sự kiện"
|
||||||
mention: "Khi có người nhắc tới bạn"
|
mention: "Khi có người nhắc tới bạn"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
_recipientType:
|
||||||
|
mail: "Email"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
suspend: "Vô hiệu hóa"
|
suspend: "Vô hiệu hóa"
|
||||||
resetPassword: "Đặt lại mật khẩu"
|
resetPassword: "Đặt lại mật khẩu"
|
||||||
|
|
|
@ -180,6 +180,10 @@ addAccount: "添加账户"
|
||||||
reloadAccountsList: "更新账户列表"
|
reloadAccountsList: "更新账户列表"
|
||||||
loginFailed: "登录失败"
|
loginFailed: "登录失败"
|
||||||
showOnRemote: "转到所在服务器显示"
|
showOnRemote: "转到所在服务器显示"
|
||||||
|
continueOnRemote: "转到所在服务器继续"
|
||||||
|
chooseServerOnMisskeyHub: "从 Misskey Hub 选择服务器"
|
||||||
|
specifyServerHost: "直接输入服务器域名"
|
||||||
|
inputHostName: "请输入域名"
|
||||||
general: "常规设置"
|
general: "常规设置"
|
||||||
wallpaper: "壁纸"
|
wallpaper: "壁纸"
|
||||||
setWallpaper: "设置壁纸"
|
setWallpaper: "设置壁纸"
|
||||||
|
@ -351,7 +355,7 @@ instanceName: "服务器名称"
|
||||||
instanceDescription: "服务器简介"
|
instanceDescription: "服务器简介"
|
||||||
maintainerName: "管理员名称"
|
maintainerName: "管理员名称"
|
||||||
maintainerEmail: "管理员电子邮箱"
|
maintainerEmail: "管理员电子邮箱"
|
||||||
tosUrl: "服务条款 URL"
|
tosUrl: "服务条款地址"
|
||||||
thisYear: "今年"
|
thisYear: "今年"
|
||||||
thisMonth: "本月"
|
thisMonth: "本月"
|
||||||
today: "今天"
|
today: "今天"
|
||||||
|
@ -433,8 +437,8 @@ administrator: "管理员"
|
||||||
token: "Token (令牌)"
|
token: "Token (令牌)"
|
||||||
2fa: "双因素认证"
|
2fa: "双因素认证"
|
||||||
setupOf2fa: "设置双因素认证"
|
setupOf2fa: "设置双因素认证"
|
||||||
totp: "身份验证应用"
|
totp: "验证器"
|
||||||
totpDescription: "使用认证应用输入一次性密码。"
|
totpDescription: "使用验证器输入一次性密码"
|
||||||
moderator: "监察员"
|
moderator: "监察员"
|
||||||
moderation: "管理"
|
moderation: "管理"
|
||||||
moderationNote: "管理笔记"
|
moderationNote: "管理笔记"
|
||||||
|
@ -477,6 +481,7 @@ noMessagesYet: "现在没有新的聊天"
|
||||||
newMessageExists: "新信息"
|
newMessageExists: "新信息"
|
||||||
onlyOneFileCanBeAttached: "只能添加一个附件"
|
onlyOneFileCanBeAttached: "只能添加一个附件"
|
||||||
signinRequired: "请先登录"
|
signinRequired: "请先登录"
|
||||||
|
signinOrContinueOnRemote: "若要继续,需要转到您所使用的实例,或者在此服务器上注册或登录。"
|
||||||
invitations: "邀请"
|
invitations: "邀请"
|
||||||
invitationCode: "邀请码"
|
invitationCode: "邀请码"
|
||||||
checking: "正在确认"
|
checking: "正在确认"
|
||||||
|
@ -837,6 +842,7 @@ administration: "管理"
|
||||||
accounts: "账户"
|
accounts: "账户"
|
||||||
switch: "切换"
|
switch: "切换"
|
||||||
noMaintainerInformationWarning: "管理人员信息未设置。"
|
noMaintainerInformationWarning: "管理人员信息未设置。"
|
||||||
|
noInquiryUrlWarning: "尚未设置联络地址。"
|
||||||
noBotProtectionWarning: "Bot 防御未设置。"
|
noBotProtectionWarning: "Bot 防御未设置。"
|
||||||
configure: "设置"
|
configure: "设置"
|
||||||
postToGallery: "发送到图库"
|
postToGallery: "发送到图库"
|
||||||
|
@ -848,7 +854,7 @@ shareWithNote: "在帖子中分享"
|
||||||
ads: "广告"
|
ads: "广告"
|
||||||
expiration: "截止时间"
|
expiration: "截止时间"
|
||||||
startingperiod: "开始时间"
|
startingperiod: "开始时间"
|
||||||
memo: "便笺"
|
memo: "备注"
|
||||||
priority: "优先级"
|
priority: "优先级"
|
||||||
high: "高"
|
high: "高"
|
||||||
middle: "中"
|
middle: "中"
|
||||||
|
@ -1180,7 +1186,7 @@ externalServices: "外部服务"
|
||||||
sourceCode: "源代码"
|
sourceCode: "源代码"
|
||||||
sourceCodeIsNotYetProvided: "还未提供源代码。要解决此问题请联系管理员。"
|
sourceCodeIsNotYetProvided: "还未提供源代码。要解决此问题请联系管理员。"
|
||||||
repositoryUrl: "仓库地址"
|
repositoryUrl: "仓库地址"
|
||||||
repositoryUrlDescription: "若源代码所在的仓库是公开的,请填入对应的 URL。若是按原样使用 Misskey(并未追加或者修改代码)的情况请填入 https://github.com/misskey-dev/misskey。"
|
repositoryUrlDescription: "若源代码所在的仓库是公开的,请填入对应的 URL。若并未追加或者修改 Misskey 的代码,请填入 https://github.com/misskey-dev/misskey。"
|
||||||
repositoryUrlOrTarballRequired: "若仓库并未公开,则需要提供 tarball 作为替代。详情请看 .config/example.yml。"
|
repositoryUrlOrTarballRequired: "若仓库并未公开,则需要提供 tarball 作为替代。详情请看 .config/example.yml。"
|
||||||
feedback: "反馈"
|
feedback: "反馈"
|
||||||
feedbackUrl: "反馈地址"
|
feedbackUrl: "反馈地址"
|
||||||
|
@ -1241,6 +1247,9 @@ keepOriginalFilenameDescription: "若关闭此设置,上传文件时文件名
|
||||||
noDescription: "没有描述"
|
noDescription: "没有描述"
|
||||||
alwaysConfirmFollow: "总是确认关注"
|
alwaysConfirmFollow: "总是确认关注"
|
||||||
inquiry: "联系我们"
|
inquiry: "联系我们"
|
||||||
|
tryAgain: "请再试一次"
|
||||||
|
confirmWhenRevealingSensitiveMedia: "显示敏感内容前需要确认"
|
||||||
|
sensitiveMediaRevealConfirm: "这是敏感内容。是否显示?"
|
||||||
_delivery:
|
_delivery:
|
||||||
status: "投递状态"
|
status: "投递状态"
|
||||||
stop: "停止投递"
|
stop: "停止投递"
|
||||||
|
@ -1375,6 +1384,8 @@ _serverSettings:
|
||||||
fanoutTimelineDescription: "当启用时,可显著提高获取各种时间线时的性能,并减轻数据库的负荷。但是相对的 Redis 的内存使用量将会增加。如果服务器的内存不是很大,又或者运行不稳定的话可以把它关掉。"
|
fanoutTimelineDescription: "当启用时,可显著提高获取各种时间线时的性能,并减轻数据库的负荷。但是相对的 Redis 的内存使用量将会增加。如果服务器的内存不是很大,又或者运行不稳定的话可以把它关掉。"
|
||||||
fanoutTimelineDbFallback: "回退到数据库"
|
fanoutTimelineDbFallback: "回退到数据库"
|
||||||
fanoutTimelineDbFallbackDescription: "当启用时,若时间线未被缓存,则将额外查询数据库。禁用该功能可通过不执行回退处理进一步减少服务器负载,但会限制可检索的时间线范围。"
|
fanoutTimelineDbFallbackDescription: "当启用时,若时间线未被缓存,则将额外查询数据库。禁用该功能可通过不执行回退处理进一步减少服务器负载,但会限制可检索的时间线范围。"
|
||||||
|
inquiryUrl: "联络地址"
|
||||||
|
inquiryUrlDescription: "用来指定诸如向服务运营商咨询的论坛地址,或记载了运营商联系方式之类的网页地址。"
|
||||||
_accountMigration:
|
_accountMigration:
|
||||||
moveFrom: "从别的账号迁移到此账户"
|
moveFrom: "从别的账号迁移到此账户"
|
||||||
moveFromSub: "为另一个账户建立别名"
|
moveFromSub: "为另一个账户建立别名"
|
||||||
|
@ -1670,8 +1681,8 @@ _role:
|
||||||
descriptionOfIsExplorable: "打开后将公开角色时间线。如果角色不是公开的,就无法公开时间线。"
|
descriptionOfIsExplorable: "打开后将公开角色时间线。如果角色不是公开的,就无法公开时间线。"
|
||||||
displayOrder: "显示顺序"
|
displayOrder: "显示顺序"
|
||||||
descriptionOfDisplayOrder: "数字越大,显示位置越靠前。"
|
descriptionOfDisplayOrder: "数字越大,显示位置越靠前。"
|
||||||
canEditMembersByModerator: "允许监察者编辑成员"
|
canEditMembersByModerator: "允许监察员编辑成员"
|
||||||
descriptionOfCanEditMembersByModerator: "如果选中,监察者和管理员都能够为用户分配/取消分配角色。如果未选中,则只有管理员可以执行此操作。"
|
descriptionOfCanEditMembersByModerator: "如果选中,监察员和管理员都能够为用户分配/取消分配角色。如果未选中,则只有管理员可以执行此操作。"
|
||||||
priority: "优先级"
|
priority: "优先级"
|
||||||
_priority:
|
_priority:
|
||||||
low: "低"
|
low: "低"
|
||||||
|
@ -1690,6 +1701,7 @@ _role:
|
||||||
canManageAvatarDecorations: "管理头像挂件"
|
canManageAvatarDecorations: "管理头像挂件"
|
||||||
driveCapacity: "网盘容量"
|
driveCapacity: "网盘容量"
|
||||||
alwaysMarkNsfw: "总是将文件标记为 NSFW"
|
alwaysMarkNsfw: "总是将文件标记为 NSFW"
|
||||||
|
canUpdateBioMedia: "可以更新头像和横幅"
|
||||||
pinMax: "帖子置顶数量限制"
|
pinMax: "帖子置顶数量限制"
|
||||||
antennaMax: "可创建的最大天线数量"
|
antennaMax: "可创建的最大天线数量"
|
||||||
wordMuteMax: "屏蔽词的字数限制"
|
wordMuteMax: "屏蔽词的字数限制"
|
||||||
|
@ -1933,8 +1945,6 @@ _sfx:
|
||||||
note: "帖子"
|
note: "帖子"
|
||||||
noteMy: "我的帖子"
|
noteMy: "我的帖子"
|
||||||
notification: "通知"
|
notification: "通知"
|
||||||
antenna: "天线接收"
|
|
||||||
channel: "频道通知"
|
|
||||||
reaction: "选择回应时"
|
reaction: "选择回应时"
|
||||||
_soundSettings:
|
_soundSettings:
|
||||||
driveFile: "使用网盘内的音频"
|
driveFile: "使用网盘内的音频"
|
||||||
|
@ -1969,7 +1979,7 @@ _time:
|
||||||
day: "日"
|
day: "日"
|
||||||
_2fa:
|
_2fa:
|
||||||
alreadyRegistered: "此设备已被注册"
|
alreadyRegistered: "此设备已被注册"
|
||||||
registerTOTP: "开始设置认证应用"
|
registerTOTP: "开始设置验证器"
|
||||||
step1: "首先,在您的设备上安装验证应用,例如 {a} 或 {b}。"
|
step1: "首先,在您的设备上安装验证应用,例如 {a} 或 {b}。"
|
||||||
step2: "然后,扫描屏幕上显示的二维码。"
|
step2: "然后,扫描屏幕上显示的二维码。"
|
||||||
step2Uri: "如果使用桌面应用程序的话,请输入下面的 URI"
|
step2Uri: "如果使用桌面应用程序的话,请输入下面的 URI"
|
||||||
|
@ -1978,23 +1988,23 @@ _2fa:
|
||||||
setupCompleted: "设置完成"
|
setupCompleted: "设置完成"
|
||||||
step4: "从现在开始,任何登录操作都将要求您提供动态口令。"
|
step4: "从现在开始,任何登录操作都将要求您提供动态口令。"
|
||||||
securityKeyNotSupported: "您的浏览器不支持安全密钥。"
|
securityKeyNotSupported: "您的浏览器不支持安全密钥。"
|
||||||
registerTOTPBeforeKey: "要注册安全密钥或 Passkey,请先设置验证器应用程序。"
|
registerTOTPBeforeKey: "要注册安全密钥或 Passkey,请先设置验证器。"
|
||||||
securityKeyInfo: "注册兼容 WebAuthn 的密钥,例如支持 FIDO2 的硬件安全密钥、设备上的生物识别功能、PIN 码以及 Passkey 等。"
|
securityKeyInfo: "注册兼容 WebAuthn 的密钥,例如支持 FIDO2 的硬件安全密钥、设备上的生物识别功能、PIN 码以及 Passkey 等。"
|
||||||
registerSecurityKey: "注册安全密钥或 Passkey"
|
registerSecurityKey: "注册安全密钥或 Passkey"
|
||||||
securityKeyName: "输入密钥名称"
|
securityKeyName: "输入密钥名称"
|
||||||
tapSecurityKey: "请按照浏览器说明操作来注册安全密钥或 Passkey。"
|
tapSecurityKey: "请按照浏览器说明操作来注册安全密钥或 Passkey。"
|
||||||
removeKey: "删除安全密钥"
|
removeKey: "删除安全密钥"
|
||||||
removeKeyConfirm: "您确定要删除 {name} 吗?"
|
removeKeyConfirm: "您确定要删除 {name} 吗?"
|
||||||
whyTOTPOnlyRenew: "如果注册了安全密钥,则无法取消验证器应用程序上的设置。"
|
whyTOTPOnlyRenew: "当注册了安全密钥时,无法取消使用验证器。"
|
||||||
renewTOTP: "重置验证器应用程序"
|
renewTOTP: "重置验证器"
|
||||||
renewTOTPConfirm: "当前验证器应用程序的验证码将不再有效"
|
renewTOTPConfirm: "当前验证器的验证码及备用代码已失效"
|
||||||
renewTOTPOk: "重新配置"
|
renewTOTPOk: "重新配置"
|
||||||
renewTOTPCancel: "不用,谢谢"
|
renewTOTPCancel: "不用,谢谢"
|
||||||
checkBackupCodesBeforeCloseThisWizard: "在关闭此窗口前,请确认下面的备用代码"
|
checkBackupCodesBeforeCloseThisWizard: "在关闭此窗口前,请确认下面的备用代码"
|
||||||
backupCodes: "备用代码"
|
backupCodes: "备用代码"
|
||||||
backupCodesDescription: "如果无法使用认证应用,可以使用以下的备用代码来访问账户。请务必将这些代码保存在安全的地方。每个代码仅可使用一次。"
|
backupCodesDescription: "如果无法使用验证器,可以使用以下的备用代码来访问账户。请务必将这些代码保存在安全的地方。每个代码仅可使用一次。"
|
||||||
backupCodeUsedWarning: "已使用备用代码。如果无法使用认证应用,请尽快重新设定。"
|
backupCodeUsedWarning: "已使用备用代码。若验证器无法使用,请尽快重置验证器。"
|
||||||
backupCodesExhaustedWarning: "已使用完所有的备用代码。如果无法使用认证应用,将无法再访问您的账户。请再次设定认证应用。"
|
backupCodesExhaustedWarning: "已使用完所有的备用代码。若验证器无法使用,则无法再访问您的账户。请重置验证器。"
|
||||||
moreDetailedGuideHere: "此处为详细指南"
|
moreDetailedGuideHere: "此处为详细指南"
|
||||||
_permissions:
|
_permissions:
|
||||||
"read:account": "查看账户信息"
|
"read:account": "查看账户信息"
|
||||||
|
@ -2398,6 +2408,7 @@ _drivecleaner:
|
||||||
orderByCreatedAtAsc: "按添加日期降序排列"
|
orderByCreatedAtAsc: "按添加日期降序排列"
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
createWebhook: "创建 Webhook"
|
createWebhook: "创建 Webhook"
|
||||||
|
modifyWebhook: "编辑 webhook"
|
||||||
name: "名称"
|
name: "名称"
|
||||||
secret: "密钥"
|
secret: "密钥"
|
||||||
events: "何时运行 Webhook"
|
events: "何时运行 Webhook"
|
||||||
|
@ -2410,6 +2421,25 @@ _webhookSettings:
|
||||||
renote: "被转发时"
|
renote: "被转发时"
|
||||||
reaction: "被回应时"
|
reaction: "被回应时"
|
||||||
mention: "被提及时"
|
mention: "被提及时"
|
||||||
|
_systemEvents:
|
||||||
|
abuseReport: "当收到举报时"
|
||||||
|
abuseReportResolved: "当举报被处理时"
|
||||||
|
deleteConfirm: "要删除 webhook 吗?"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
createRecipient: "新建举报通知"
|
||||||
|
modifyRecipient: "编辑举报通知"
|
||||||
|
recipientType: "通知类型"
|
||||||
|
_recipientType:
|
||||||
|
mail: "邮箱"
|
||||||
|
webhook: "Webhook"
|
||||||
|
_captions:
|
||||||
|
mail: "当收到新举报时,向持有监察员权限的用户发送通知邮件"
|
||||||
|
webhook: "当收到新举报及举报被处理时,使用指定的 SystemWebhook 发送通知"
|
||||||
|
keywords: "关键字"
|
||||||
|
notifiedUser: "通知的用户"
|
||||||
|
notifiedWebhook: "使用的 webhook"
|
||||||
|
deleteConfirm: "要删除通知吗?"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
createRole: "创建角色"
|
createRole: "创建角色"
|
||||||
deleteRole: "删除角色"
|
deleteRole: "删除角色"
|
||||||
|
@ -2447,6 +2477,12 @@ _moderationLogTypes:
|
||||||
deleteAvatarDecoration: "删除头像挂件"
|
deleteAvatarDecoration: "删除头像挂件"
|
||||||
unsetUserAvatar: "清除用户头像"
|
unsetUserAvatar: "清除用户头像"
|
||||||
unsetUserBanner: "清除用户横幅"
|
unsetUserBanner: "清除用户横幅"
|
||||||
|
createSystemWebhook: "新建了 SystemWebhook"
|
||||||
|
updateSystemWebhook: "更新了 SystemWebhook"
|
||||||
|
deleteSystemWebhook: "删除了 SystemWebhook"
|
||||||
|
createAbuseReportNotificationRecipient: "新建了举报通知"
|
||||||
|
updateAbuseReportNotificationRecipient: "更新了举报通知"
|
||||||
|
deleteAbuseReportNotificationRecipient: "删除了举报通知"
|
||||||
_fileViewer:
|
_fileViewer:
|
||||||
title: "文件信息"
|
title: "文件信息"
|
||||||
type: "文件类型"
|
type: "文件类型"
|
||||||
|
|
|
@ -180,6 +180,10 @@ addAccount: "新增帳戶"
|
||||||
reloadAccountsList: "更新帳戶清單的資訊"
|
reloadAccountsList: "更新帳戶清單的資訊"
|
||||||
loginFailed: "登入失敗"
|
loginFailed: "登入失敗"
|
||||||
showOnRemote: "轉到所在實例顯示"
|
showOnRemote: "轉到所在實例顯示"
|
||||||
|
continueOnRemote: "在遠端伺服器繼續"
|
||||||
|
chooseServerOnMisskeyHub: "從 Misskey Hub 選擇伺服器"
|
||||||
|
specifyServerHost: "直接指定伺服器網域"
|
||||||
|
inputHostName: "請輸入域名"
|
||||||
general: "一般"
|
general: "一般"
|
||||||
wallpaper: "桌布"
|
wallpaper: "桌布"
|
||||||
setWallpaper: "設定桌布"
|
setWallpaper: "設定桌布"
|
||||||
|
@ -243,10 +247,10 @@ noCustomEmojis: "沒有自訂的表情符號"
|
||||||
noJobs: "沒有任務"
|
noJobs: "沒有任務"
|
||||||
federating: "聯邦運作中"
|
federating: "聯邦運作中"
|
||||||
blocked: "已封鎖"
|
blocked: "已封鎖"
|
||||||
suspended: "已凍結"
|
suspended: "停止發送"
|
||||||
all: "全部"
|
all: "全部"
|
||||||
subscribing: "訂閱中"
|
subscribing: "訂閱中"
|
||||||
publishing: "直播中"
|
publishing: "發送中"
|
||||||
notResponding: "沒有回應"
|
notResponding: "沒有回應"
|
||||||
instanceFollowing: "追隨的伺服器"
|
instanceFollowing: "追隨的伺服器"
|
||||||
instanceFollowers: "伺服器的追隨者"
|
instanceFollowers: "伺服器的追隨者"
|
||||||
|
@ -343,7 +347,7 @@ reload: "重新整理"
|
||||||
doNothing: "無視"
|
doNothing: "無視"
|
||||||
reloadConfirm: "確定要重新整理嗎?"
|
reloadConfirm: "確定要重新整理嗎?"
|
||||||
watch: "關注"
|
watch: "關注"
|
||||||
unwatch: "取消追隨"
|
unwatch: "取消關注"
|
||||||
accept: "接受"
|
accept: "接受"
|
||||||
reject: "拒絕"
|
reject: "拒絕"
|
||||||
normal: "正常"
|
normal: "正常"
|
||||||
|
@ -477,6 +481,7 @@ noMessagesYet: "沒有訊息"
|
||||||
newMessageExists: "有新的訊息"
|
newMessageExists: "有新的訊息"
|
||||||
onlyOneFileCanBeAttached: "只能加入一個附件"
|
onlyOneFileCanBeAttached: "只能加入一個附件"
|
||||||
signinRequired: "請先登入"
|
signinRequired: "請先登入"
|
||||||
|
signinOrContinueOnRemote: "若要繼續,需前往您所在的伺服器,或者註冊並登入此伺服器"
|
||||||
invitations: "邀請"
|
invitations: "邀請"
|
||||||
invitationCode: "邀請碼"
|
invitationCode: "邀請碼"
|
||||||
checking: "確認中"
|
checking: "確認中"
|
||||||
|
@ -837,6 +842,7 @@ administration: "管理"
|
||||||
accounts: "帳戶"
|
accounts: "帳戶"
|
||||||
switch: "切換"
|
switch: "切換"
|
||||||
noMaintainerInformationWarning: "尚未設定管理員訊息。"
|
noMaintainerInformationWarning: "尚未設定管理員訊息。"
|
||||||
|
noInquiryUrlWarning: "尚未設定聯絡表單網址。"
|
||||||
noBotProtectionWarning: "尚未設定 Bot 防護。"
|
noBotProtectionWarning: "尚未設定 Bot 防護。"
|
||||||
configure: "設定"
|
configure: "設定"
|
||||||
postToGallery: "發佈到相簿"
|
postToGallery: "發佈到相簿"
|
||||||
|
@ -1241,12 +1247,15 @@ keepOriginalFilenameDescription: "如果關閉此設置,上傳時檔案名稱
|
||||||
noDescription: "沒有說明文字"
|
noDescription: "沒有說明文字"
|
||||||
alwaysConfirmFollow: "點擊追隨時總是顯示確認訊息"
|
alwaysConfirmFollow: "點擊追隨時總是顯示確認訊息"
|
||||||
inquiry: "聯絡我們"
|
inquiry: "聯絡我們"
|
||||||
|
tryAgain: "請再試一次。"
|
||||||
|
confirmWhenRevealingSensitiveMedia: "要顯示敏感媒體時需確認"
|
||||||
|
sensitiveMediaRevealConfirm: "這是敏感媒體。確定要顯示嗎?"
|
||||||
_delivery:
|
_delivery:
|
||||||
status: "傳送狀態"
|
status: "傳送狀態"
|
||||||
stop: "停止傳送"
|
stop: "停止發送"
|
||||||
resume: "恢復傳送"
|
resume: "恢復發送"
|
||||||
_type:
|
_type:
|
||||||
none: "直播中"
|
none: "發送中"
|
||||||
manuallySuspended: "手動暫停中"
|
manuallySuspended: "手動暫停中"
|
||||||
goneSuspended: "因為伺服器刪除所以暫停中"
|
goneSuspended: "因為伺服器刪除所以暫停中"
|
||||||
autoSuspendedForNotResponding: "因為伺服器沒有回應所以暫停中"
|
autoSuspendedForNotResponding: "因為伺服器沒有回應所以暫停中"
|
||||||
|
@ -1376,7 +1385,7 @@ _serverSettings:
|
||||||
fanoutTimelineDbFallback: "資料庫的回退"
|
fanoutTimelineDbFallback: "資料庫的回退"
|
||||||
fanoutTimelineDbFallbackDescription: "若啟用,在時間軸沒有快取的情況下將執行回退處理以額外查詢資料庫。若停用,可以透過不執行回退處理來進一步減少伺服器的負荷,但會限制可取得的時間軸範圍。"
|
fanoutTimelineDbFallbackDescription: "若啟用,在時間軸沒有快取的情況下將執行回退處理以額外查詢資料庫。若停用,可以透過不執行回退處理來進一步減少伺服器的負荷,但會限制可取得的時間軸範圍。"
|
||||||
inquiryUrl: "聯絡表單網址"
|
inquiryUrl: "聯絡表單網址"
|
||||||
inquiryUrlDescription: "指定伺服器運營者的聯絡表單網址或包含運營者聯絡資訊網頁的網址。"
|
inquiryUrlDescription: "指定伺服器運營者的聯絡表單網址,或包含運營者聯絡資訊網頁的網址。"
|
||||||
_accountMigration:
|
_accountMigration:
|
||||||
moveFrom: "從其他帳戶遷移到這個帳戶"
|
moveFrom: "從其他帳戶遷移到這個帳戶"
|
||||||
moveFromSub: "為另一個帳戶建立別名"
|
moveFromSub: "為另一個帳戶建立別名"
|
||||||
|
@ -1693,6 +1702,7 @@ _role:
|
||||||
canManageAvatarDecorations: "管理頭像裝飾"
|
canManageAvatarDecorations: "管理頭像裝飾"
|
||||||
driveCapacity: "雲端硬碟容量"
|
driveCapacity: "雲端硬碟容量"
|
||||||
alwaysMarkNsfw: "總是將檔案標記為NSFW"
|
alwaysMarkNsfw: "總是將檔案標記為NSFW"
|
||||||
|
canUpdateBioMedia: "允許更新大頭貼和橫幅"
|
||||||
pinMax: "置頂貼文的最大數量"
|
pinMax: "置頂貼文的最大數量"
|
||||||
antennaMax: "可建立的天線數量"
|
antennaMax: "可建立的天線數量"
|
||||||
wordMuteMax: "靜音文字的最大字數"
|
wordMuteMax: "靜音文字的最大字數"
|
||||||
|
@ -1936,8 +1946,6 @@ _sfx:
|
||||||
note: "貼文"
|
note: "貼文"
|
||||||
noteMy: "我的貼文"
|
noteMy: "我的貼文"
|
||||||
notification: "通知"
|
notification: "通知"
|
||||||
antenna: "天線接收"
|
|
||||||
channel: "頻道通知"
|
|
||||||
reaction: "選擇反應時"
|
reaction: "選擇反應時"
|
||||||
_soundSettings:
|
_soundSettings:
|
||||||
driveFile: "使用雲端硬碟的音效檔案"
|
driveFile: "使用雲端硬碟的音效檔案"
|
||||||
|
@ -2217,7 +2225,7 @@ _charts:
|
||||||
federation: "聯邦宇宙"
|
federation: "聯邦宇宙"
|
||||||
apRequest: "請求"
|
apRequest: "請求"
|
||||||
usersIncDec: "使用者增減"
|
usersIncDec: "使用者增減"
|
||||||
usersTotal: "使用者總數"
|
usersTotal: "使用者合計"
|
||||||
activeUsers: "活躍使用者"
|
activeUsers: "活躍使用者"
|
||||||
notesIncDec: "貼文増減"
|
notesIncDec: "貼文増減"
|
||||||
localNotesIncDec: "本地貼文増減"
|
localNotesIncDec: "本地貼文増減"
|
||||||
|
@ -2401,6 +2409,7 @@ _drivecleaner:
|
||||||
orderByCreatedAtAsc: "按新增日期降序排列"
|
orderByCreatedAtAsc: "按新增日期降序排列"
|
||||||
_webhookSettings:
|
_webhookSettings:
|
||||||
createWebhook: "建立 Webhook"
|
createWebhook: "建立 Webhook"
|
||||||
|
modifyWebhook: "編輯 Webhook"
|
||||||
name: "名字"
|
name: "名字"
|
||||||
secret: "密鑰"
|
secret: "密鑰"
|
||||||
events: "何時運行 Webhook"
|
events: "何時運行 Webhook"
|
||||||
|
@ -2413,6 +2422,25 @@ _webhookSettings:
|
||||||
renote: "當被轉發時"
|
renote: "當被轉發時"
|
||||||
reaction: "當獲得反應時"
|
reaction: "當獲得反應時"
|
||||||
mention: "當被提到時"
|
mention: "當被提到時"
|
||||||
|
_systemEvents:
|
||||||
|
abuseReport: "當使用者檢舉時"
|
||||||
|
abuseReportResolved: "當處理了使用者的檢舉時"
|
||||||
|
deleteConfirm: "請問是否要刪除 Webhook?"
|
||||||
|
_abuseReport:
|
||||||
|
_notificationRecipient:
|
||||||
|
createRecipient: "新增接收檢舉的通知對象"
|
||||||
|
modifyRecipient: "編輯接收檢舉的通知對象"
|
||||||
|
recipientType: "通知對象的種類"
|
||||||
|
_recipientType:
|
||||||
|
mail: "電子郵件"
|
||||||
|
webhook: "Webhook"
|
||||||
|
_captions:
|
||||||
|
mail: "寄送到擁有監察員權限的使用者電子郵件地址(僅在收到檢舉時)"
|
||||||
|
webhook: "向指定的 SystemWebhook 發送通知(在收到檢舉和解決檢舉時發送)"
|
||||||
|
keywords: "關鍵字"
|
||||||
|
notifiedUser: "被通知的使用者"
|
||||||
|
notifiedWebhook: "使用的 Webhook"
|
||||||
|
deleteConfirm: "確定要刪除通知對象嗎?"
|
||||||
_moderationLogTypes:
|
_moderationLogTypes:
|
||||||
createRole: "新增角色"
|
createRole: "新增角色"
|
||||||
deleteRole: "刪除角色 "
|
deleteRole: "刪除角色 "
|
||||||
|
@ -2450,6 +2478,12 @@ _moderationLogTypes:
|
||||||
deleteAvatarDecoration: "刪除頭像裝飾"
|
deleteAvatarDecoration: "刪除頭像裝飾"
|
||||||
unsetUserAvatar: "移除使用者的大頭貼"
|
unsetUserAvatar: "移除使用者的大頭貼"
|
||||||
unsetUserBanner: "移除使用者的橫幅圖像"
|
unsetUserBanner: "移除使用者的橫幅圖像"
|
||||||
|
createSystemWebhook: "建立 SystemWebhook"
|
||||||
|
updateSystemWebhook: "更新 SystemWebhook"
|
||||||
|
deleteSystemWebhook: "刪除 SystemWebhook"
|
||||||
|
createAbuseReportNotificationRecipient: "建立接收檢舉的通知對象"
|
||||||
|
updateAbuseReportNotificationRecipient: "更新接收檢舉的通知對象"
|
||||||
|
deleteAbuseReportNotificationRecipient: "刪除接收檢舉的通知對象"
|
||||||
_fileViewer:
|
_fileViewer:
|
||||||
title: "檔案詳細資訊"
|
title: "檔案詳細資訊"
|
||||||
type: "檔案類型 "
|
type: "檔案類型 "
|
||||||
|
|
30
package.json
30
package.json
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"version": "2024.7.0-beta.1",
|
"version": "2024.7.0-rc.4",
|
||||||
"codename": "nasubi",
|
"codename": "nasubi",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/misskey-dev/misskey.git"
|
"url": "https://github.com/misskey-dev/misskey.git"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.5.0",
|
"packageManager": "pnpm@9.6.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/frontend",
|
"packages/frontend",
|
||||||
"packages/backend",
|
"packages/backend",
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
"build-assets": "node ./scripts/build-assets.mjs",
|
"build-assets": "node ./scripts/build-assets.mjs",
|
||||||
"build": "pnpm build-pre && pnpm -r build && pnpm build-assets",
|
"build": "pnpm build-pre && pnpm -r build && pnpm build-assets",
|
||||||
"build-storybook": "pnpm --filter frontend build-storybook",
|
"build-storybook": "pnpm --filter frontend build-storybook",
|
||||||
"build-misskey-js-with-types": "pnpm build-pre && pnpm --filter backend... --filter=!misskey-js build && pnpm --filter backend generate-api-json && ncp packages/backend/built/api.json packages/misskey-js/generator/api.json && pnpm --filter misskey-js update-autogen-code && pnpm --filter misskey-js build && pnpm --filter misskey-js api",
|
"build-misskey-js-with-types": "pnpm build-pre && pnpm --filter backend... --filter=!misskey-js build && pnpm --filter backend generate-api-json --no-build && ncp packages/backend/built/api.json packages/misskey-js/generator/api.json && pnpm --filter misskey-js update-autogen-code && pnpm --filter misskey-js build && pnpm --filter misskey-js api",
|
||||||
"start": "pnpm check:connect && cd packages/backend && node ./built/boot/entry.js",
|
"start": "pnpm check:connect && cd packages/backend && node ./built/boot/entry.js",
|
||||||
"start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/entry.js",
|
"start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/entry.js",
|
||||||
"init": "pnpm migrate",
|
"init": "pnpm migrate",
|
||||||
|
@ -51,24 +51,24 @@
|
||||||
"cssnano": "6.1.2",
|
"cssnano": "6.1.2",
|
||||||
"execa": "8.0.1",
|
"execa": "8.0.1",
|
||||||
"fast-glob": "3.3.2",
|
"fast-glob": "3.3.2",
|
||||||
"ignore-walk": "6.0.4",
|
"ignore-walk": "6.0.5",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"postcss": "8.4.38",
|
"postcss": "8.4.40",
|
||||||
"tar": "6.2.1",
|
"tar": "6.2.1",
|
||||||
"terser": "5.31.1",
|
"terser": "5.31.3",
|
||||||
"typescript": "5.5.3",
|
"typescript": "5.5.4",
|
||||||
"esbuild": "0.22.0",
|
"esbuild": "0.23.0",
|
||||||
"glob": "10.3.12"
|
"glob": "11.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@misskey-dev/eslint-plugin": "2.0.2",
|
"@misskey-dev/eslint-plugin": "2.0.2",
|
||||||
"@types/node": "20.14.9",
|
"@types/node": "20.14.12",
|
||||||
"@typescript-eslint/eslint-plugin": "7.15.0",
|
"@typescript-eslint/eslint-plugin": "7.17.0",
|
||||||
"@typescript-eslint/parser": "7.15.0",
|
"@typescript-eslint/parser": "7.17.0",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"cypress": "13.13.0",
|
"cypress": "13.13.1",
|
||||||
"eslint": "9.6.0",
|
"eslint": "9.8.0",
|
||||||
"globals": "15.7.0",
|
"globals": "15.8.0",
|
||||||
"ncp": "2.0.0",
|
"ncp": "2.0.0",
|
||||||
"start-server-and-test": "2.0.4"
|
"start-server-and-test": "2.0.4"
|
||||||
},
|
},
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
"test:e2e": "pnpm build && pnpm build:test && pnpm jest:e2e",
|
"test:e2e": "pnpm build && pnpm build:test && pnpm jest:e2e",
|
||||||
"test-and-coverage": "pnpm jest-and-coverage",
|
"test-and-coverage": "pnpm jest-and-coverage",
|
||||||
"test-and-coverage:e2e": "pnpm build && pnpm build:test && pnpm jest-and-coverage:e2e",
|
"test-and-coverage:e2e": "pnpm build && pnpm build:test && pnpm jest-and-coverage:e2e",
|
||||||
"generate-api-json": "pnpm build && node ./scripts/generate_api_json.js"
|
"generate-api-json": "node ./scripts/generate_api_json.js"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@swc/core-android-arm64": "1.3.11",
|
"@swc/core-android-arm64": "1.3.11",
|
||||||
|
@ -65,11 +65,11 @@
|
||||||
"utf-8-validate": "6.0.3"
|
"utf-8-validate": "6.0.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "3.600.0",
|
"@aws-sdk/client-s3": "3.620.0",
|
||||||
"@aws-sdk/lib-storage": "3.600.0",
|
"@aws-sdk/lib-storage": "3.620.0",
|
||||||
"@bull-board/api": "5.20.5",
|
"@bull-board/api": "5.21.1",
|
||||||
"@bull-board/fastify": "5.20.5",
|
"@bull-board/fastify": "5.21.1",
|
||||||
"@bull-board/ui": "5.20.5",
|
"@bull-board/ui": "5.21.1",
|
||||||
"@discordapp/twemoji": "15.0.3",
|
"@discordapp/twemoji": "15.0.3",
|
||||||
"@fastify/accepts": "4.3.0",
|
"@fastify/accepts": "4.3.0",
|
||||||
"@fastify/cookie": "9.3.1",
|
"@fastify/cookie": "9.3.1",
|
||||||
|
@ -86,22 +86,22 @@
|
||||||
"@nestjs/core": "10.3.10",
|
"@nestjs/core": "10.3.10",
|
||||||
"@nestjs/testing": "10.3.10",
|
"@nestjs/testing": "10.3.10",
|
||||||
"@peertube/http-signature": "1.7.0",
|
"@peertube/http-signature": "1.7.0",
|
||||||
"@sentry/node": "8.13.0",
|
"@sentry/node": "8.20.0",
|
||||||
"@sentry/profiling-node": "8.13.0",
|
"@sentry/profiling-node": "8.20.0",
|
||||||
"@simplewebauthn/server": "10.0.0",
|
"@simplewebauthn/server": "10.0.1",
|
||||||
"@sinonjs/fake-timers": "11.2.2",
|
"@sinonjs/fake-timers": "11.2.2",
|
||||||
"@smithy/node-http-handler": "2.5.0",
|
"@smithy/node-http-handler": "2.5.0",
|
||||||
"@swc/cli": "0.3.12",
|
"@swc/cli": "0.3.12",
|
||||||
"@swc/core": "1.6.6",
|
"@swc/core": "1.6.6",
|
||||||
"@twemoji/parser": "15.1.1",
|
"@twemoji/parser": "15.1.1",
|
||||||
"accepts": "1.3.8",
|
"accepts": "1.3.8",
|
||||||
"ajv": "8.16.0",
|
"ajv": "8.17.1",
|
||||||
"archiver": "7.0.1",
|
"archiver": "7.0.1",
|
||||||
"async-mutex": "0.5.0",
|
"async-mutex": "0.5.0",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"blurhash": "2.0.5",
|
"blurhash": "2.0.5",
|
||||||
"body-parser": "1.20.2",
|
"body-parser": "1.20.2",
|
||||||
"bullmq": "5.8.3",
|
"bullmq": "5.10.4",
|
||||||
"cacheable-lookup": "7.0.0",
|
"cacheable-lookup": "7.0.0",
|
||||||
"cbor": "9.0.2",
|
"cbor": "9.0.2",
|
||||||
"chalk": "5.3.0",
|
"chalk": "5.3.0",
|
||||||
|
@ -115,10 +115,10 @@
|
||||||
"fastify": "4.28.1",
|
"fastify": "4.28.1",
|
||||||
"fastify-raw-body": "4.3.0",
|
"fastify-raw-body": "4.3.0",
|
||||||
"feed": "4.2.2",
|
"feed": "4.2.2",
|
||||||
"file-type": "19.0.0",
|
"file-type": "19.3.0",
|
||||||
"fluent-ffmpeg": "2.1.3",
|
"fluent-ffmpeg": "2.1.3",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
"got": "14.4.1",
|
"got": "14.4.2",
|
||||||
"happy-dom": "10.0.3",
|
"happy-dom": "10.0.3",
|
||||||
"hpagent": "1.2.0",
|
"hpagent": "1.2.0",
|
||||||
"htmlescape": "1.1.1",
|
"htmlescape": "1.1.1",
|
||||||
|
@ -128,7 +128,7 @@
|
||||||
"ipaddr.js": "2.2.0",
|
"ipaddr.js": "2.2.0",
|
||||||
"is-svg": "5.0.1",
|
"is-svg": "5.0.1",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"jsdom": "24.1.0",
|
"jsdom": "24.1.1",
|
||||||
"json5": "2.2.3",
|
"json5": "2.2.3",
|
||||||
"jsonld": "8.3.2",
|
"jsonld": "8.3.2",
|
||||||
"jsrsasign": "11.1.0",
|
"jsrsasign": "11.1.0",
|
||||||
|
@ -177,11 +177,11 @@
|
||||||
"tsc-alias": "1.8.10",
|
"tsc-alias": "1.8.10",
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"typeorm": "0.3.20",
|
"typeorm": "0.3.20",
|
||||||
"typescript": "5.5.3",
|
"typescript": "5.5.4",
|
||||||
"ulid": "2.3.0",
|
"ulid": "2.3.0",
|
||||||
"vary": "1.1.2",
|
"vary": "1.1.2",
|
||||||
"web-push": "3.6.7",
|
"web-push": "3.6.7",
|
||||||
"ws": "8.17.1",
|
"ws": "8.18.0",
|
||||||
"xev": "3.0.2"
|
"xev": "3.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -201,11 +201,11 @@
|
||||||
"@types/jest": "29.5.12",
|
"@types/jest": "29.5.12",
|
||||||
"@types/js-yaml": "4.0.9",
|
"@types/js-yaml": "4.0.9",
|
||||||
"@types/jsdom": "21.1.7",
|
"@types/jsdom": "21.1.7",
|
||||||
"@types/jsonld": "1.5.14",
|
"@types/jsonld": "1.5.15",
|
||||||
"@types/jsrsasign": "10.5.14",
|
"@types/jsrsasign": "10.5.14",
|
||||||
"@types/mime-types": "2.1.4",
|
"@types/mime-types": "2.1.4",
|
||||||
"@types/ms": "0.7.34",
|
"@types/ms": "0.7.34",
|
||||||
"@types/node": "20.14.9",
|
"@types/node": "20.14.12",
|
||||||
"@types/nodemailer": "6.4.15",
|
"@types/nodemailer": "6.4.15",
|
||||||
"@types/oauth": "0.9.5",
|
"@types/oauth": "0.9.5",
|
||||||
"@types/oauth2orize": "1.11.5",
|
"@types/oauth2orize": "1.11.5",
|
||||||
|
@ -225,18 +225,18 @@
|
||||||
"@types/tmp": "0.2.6",
|
"@types/tmp": "0.2.6",
|
||||||
"@types/vary": "1.1.3",
|
"@types/vary": "1.1.3",
|
||||||
"@types/web-push": "3.6.3",
|
"@types/web-push": "3.6.3",
|
||||||
"@types/ws": "8.5.10",
|
"@types/ws": "8.5.11",
|
||||||
"@typescript-eslint/eslint-plugin": "7.15.0",
|
"@typescript-eslint/eslint-plugin": "7.17.0",
|
||||||
"@typescript-eslint/parser": "7.15.0",
|
"@typescript-eslint/parser": "7.17.0",
|
||||||
"aws-sdk-client-mock": "4.0.1",
|
"aws-sdk-client-mock": "4.0.1",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"eslint-plugin-import": "2.29.1",
|
"eslint-plugin-import": "2.29.1",
|
||||||
"execa": "9.2.0",
|
"execa": "9.3.0",
|
||||||
"fkill": "9.0.0",
|
"fkill": "9.0.0",
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"jest-mock": "29.7.0",
|
"jest-mock": "29.7.0",
|
||||||
"nodemon": "3.1.4",
|
"nodemon": "3.1.4",
|
||||||
"pid-port": "1.0.0",
|
"pid-port": "1.0.0",
|
||||||
"simple-oauth2": "5.0.1"
|
"simple-oauth2": "5.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,34 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { loadConfig } from '../built/config.js'
|
import { execa } from 'execa';
|
||||||
import { genOpenapiSpec } from '../built/server/api/openapi/gen-spec.js'
|
import { writeFileSync, existsSync } from "node:fs";
|
||||||
import { writeFileSync } from "node:fs";
|
|
||||||
|
|
||||||
const config = loadConfig();
|
async function main() {
|
||||||
const spec = genOpenapiSpec(config, true);
|
if (!process.argv.includes('--no-build')) {
|
||||||
|
await execa('pnpm', ['run', 'build'], {
|
||||||
|
stdout: process.stdout,
|
||||||
|
stderr: process.stderr,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
writeFileSync('./built/api.json', JSON.stringify(spec), 'utf-8');
|
if (!existsSync('./built')) {
|
||||||
|
throw new Error('`built` directory does not exist.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {import('../src/config.js')} */
|
||||||
|
const { loadConfig } = await import('../built/config.js');
|
||||||
|
|
||||||
|
/** @type {import('../src/server/api/openapi/gen-spec.js')} */
|
||||||
|
const { genOpenapiSpec } = await import('../built/server/api/openapi/gen-spec.js');
|
||||||
|
|
||||||
|
const config = loadConfig();
|
||||||
|
const spec = genOpenapiSpec(config, true);
|
||||||
|
|
||||||
|
writeFileSync('./built/api.json', JSON.stringify(spec), 'utf-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(e => {
|
||||||
|
console.error(e);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
|
@ -44,7 +44,7 @@ export class AbuseReportNotificationService implements OnApplicationShutdown {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 管理者用Redisイベントを用いて{@link abuseReports}の内容を管理者各位に通知する.
|
* 管理者用Redisイベントを用いて{@link abuseReports}の内容を管理者各位に通知する.
|
||||||
* 通知先ユーザは{@link RoleService.getModeratorIds}の取得結果に依る.
|
* 通知先ユーザは{@link getModeratorIds}の取得結果に依る.
|
||||||
*
|
*
|
||||||
* @see RoleService.getModeratorIds
|
* @see RoleService.getModeratorIds
|
||||||
* @see GlobalEventService.publishAdminStream
|
* @see GlobalEventService.publishAdminStream
|
||||||
|
|
|
@ -933,10 +933,13 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note.visibility !== 'specified' || !note.visibleUserIds.some(v => v === user.id)) { // 自分自身のHTL
|
// 自分自身のHTL
|
||||||
this.fanoutTimelineService.push(`homeTimeline:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax, r);
|
if (note.userHost == null) {
|
||||||
if (note.fileIds.length > 0) {
|
if (note.visibility !== 'specified' || !note.visibleUserIds.some(v => v === user.id)) {
|
||||||
this.fanoutTimelineService.push(`homeTimelineWithFiles:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r);
|
this.fanoutTimelineService.push(`homeTimeline:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax, r);
|
||||||
|
if (note.fileIds.length > 0) {
|
||||||
|
this.fanoutTimelineService.push(`homeTimelineWithFiles:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -505,14 +505,15 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
|
||||||
|
|
||||||
this.globalEventService.publishInternalEvent('userRoleAssigned', created);
|
this.globalEventService.publishInternalEvent('userRoleAssigned', created);
|
||||||
|
|
||||||
if (role.isPublic) {
|
const user = await this.usersRepository.findOneByOrFail({ id: userId });
|
||||||
|
|
||||||
|
if (role.isPublic && user.host === null) {
|
||||||
this.notificationService.createNotification(userId, 'roleAssigned', {
|
this.notificationService.createNotification(userId, 'roleAssigned', {
|
||||||
roleId: roleId,
|
roleId: roleId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moderator) {
|
if (moderator) {
|
||||||
const user = await this.usersRepository.findOneByOrFail({ id: userId });
|
|
||||||
this.moderationLogService.log(moderator, 'assignRole', {
|
this.moderationLogService.log(moderator, 'assignRole', {
|
||||||
roleId: roleId,
|
roleId: roleId,
|
||||||
roleName: role.name,
|
roleName: role.name,
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { bindThis } from '@/decorators.js';
|
||||||
import UsersChart from '@/core/chart/charts/users.js';
|
import UsersChart from '@/core/chart/charts/users.js';
|
||||||
import { UtilityService } from '@/core/UtilityService.js';
|
import { UtilityService } from '@/core/UtilityService.js';
|
||||||
import { MetaService } from '@/core/MetaService.js';
|
import { MetaService } from '@/core/MetaService.js';
|
||||||
|
import { UserService } from '@/core/UserService.js';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SignupService {
|
export class SignupService {
|
||||||
|
@ -35,6 +36,7 @@ export class SignupService {
|
||||||
private usedUsernamesRepository: UsedUsernamesRepository,
|
private usedUsernamesRepository: UsedUsernamesRepository,
|
||||||
|
|
||||||
private utilityService: UtilityService,
|
private utilityService: UtilityService,
|
||||||
|
private userService: UserService,
|
||||||
private userEntityService: UserEntityService,
|
private userEntityService: UserEntityService,
|
||||||
private idService: IdService,
|
private idService: IdService,
|
||||||
private metaService: MetaService,
|
private metaService: MetaService,
|
||||||
|
@ -148,7 +150,8 @@ export class SignupService {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.usersChart.update(account, true);
|
this.usersChart.update(account, true).then();
|
||||||
|
this.userService.notifySystemWebhook(account, 'userCreated').then();
|
||||||
|
|
||||||
return { account, secret };
|
return { account, secret };
|
||||||
}
|
}
|
||||||
|
|
|
@ -279,8 +279,10 @@ export class UserFollowingService implements OnModuleInit {
|
||||||
});
|
});
|
||||||
|
|
||||||
// 通知を作成
|
// 通知を作成
|
||||||
this.notificationService.createNotification(follower.id, 'followRequestAccepted', {
|
if (follower.host === null) {
|
||||||
}, followee.id);
|
this.notificationService.createNotification(follower.id, 'followRequestAccepted', {
|
||||||
|
}, followee.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alreadyFollowed) return;
|
if (alreadyFollowed) return;
|
||||||
|
|
|
@ -8,15 +8,18 @@ import type { FollowingsRepository, UsersRepository } from '@/models/_.js';
|
||||||
import type { MiUser } from '@/models/User.js';
|
import type { MiUser } from '@/models/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 { SystemWebhookService } from '@/core/SystemWebhookService.js';
|
||||||
|
import { UserEntityService } from '@/core/entities/UserEntityService.js';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserService {
|
export class UserService {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.usersRepository)
|
@Inject(DI.usersRepository)
|
||||||
private usersRepository: UsersRepository,
|
private usersRepository: UsersRepository,
|
||||||
|
|
||||||
@Inject(DI.followingsRepository)
|
@Inject(DI.followingsRepository)
|
||||||
private followingsRepository: FollowingsRepository,
|
private followingsRepository: FollowingsRepository,
|
||||||
|
private systemWebhookService: SystemWebhookService,
|
||||||
|
private userEntityService: UserEntityService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,4 +53,23 @@ export class UserService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SystemWebhookを用いてユーザに関する操作内容を管理者各位に通知する.
|
||||||
|
* ここではJobQueueへのエンキューのみを行うため、即時実行されない.
|
||||||
|
*
|
||||||
|
* @see SystemWebhookService.enqueueSystemWebhook
|
||||||
|
*/
|
||||||
|
@bindThis
|
||||||
|
public async notifySystemWebhook(user: MiUser, type: 'userCreated') {
|
||||||
|
const packedUser = await this.userEntityService.pack(user, null, { schema: 'UserLite' });
|
||||||
|
const recipientWebhookIds = await this.systemWebhookService.fetchSystemWebhooks({ isActive: true, on: [type] });
|
||||||
|
for (const webhookId of recipientWebhookIds) {
|
||||||
|
await this.systemWebhookService.enqueueSystemWebhook(
|
||||||
|
webhookId,
|
||||||
|
type,
|
||||||
|
packedUser,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ export const systemWebhookEventTypes = [
|
||||||
'abuseReport',
|
'abuseReport',
|
||||||
// 通報を処理したとき
|
// 通報を処理したとき
|
||||||
'abuseReportResolved',
|
'abuseReportResolved',
|
||||||
|
// ユーザが作成された時
|
||||||
|
'userCreated',
|
||||||
] as const;
|
] as const;
|
||||||
export type SystemWebhookEventType = typeof systemWebhookEventTypes[number];
|
export type SystemWebhookEventType = typeof systemWebhookEventTypes[number];
|
||||||
|
|
||||||
|
|
|
@ -204,6 +204,7 @@ export const packedNoteSchema = {
|
||||||
reactionAcceptance: {
|
reactionAcceptance: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
optional: false, nullable: true,
|
optional: false, nullable: true,
|
||||||
|
enum: ['likeOnly', 'likeOnlyForRemote', 'nonSensitiveOnly', 'nonSensitiveOnlyForLocalLikeOnlyForRemote', null],
|
||||||
},
|
},
|
||||||
reactionEmojis: {
|
reactionEmojis: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { PollVotesRepository, NotesRepository } from '@/models/_.js';
|
import type { PollVotesRepository, NotesRepository } from '@/models/_.js';
|
||||||
import type Logger from '@/logger.js';
|
import type Logger from '@/logger.js';
|
||||||
|
import { CacheService } from '@/core/CacheService.js';
|
||||||
import { NotificationService } from '@/core/NotificationService.js';
|
import { NotificationService } from '@/core/NotificationService.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { QueueLoggerService } from '../QueueLoggerService.js';
|
import { QueueLoggerService } from '../QueueLoggerService.js';
|
||||||
|
@ -24,6 +25,7 @@ export class EndedPollNotificationProcessorService {
|
||||||
@Inject(DI.pollVotesRepository)
|
@Inject(DI.pollVotesRepository)
|
||||||
private pollVotesRepository: PollVotesRepository,
|
private pollVotesRepository: PollVotesRepository,
|
||||||
|
|
||||||
|
private cacheService: CacheService,
|
||||||
private notificationService: NotificationService,
|
private notificationService: NotificationService,
|
||||||
private queueLoggerService: QueueLoggerService,
|
private queueLoggerService: QueueLoggerService,
|
||||||
) {
|
) {
|
||||||
|
@ -47,9 +49,12 @@ export class EndedPollNotificationProcessorService {
|
||||||
const userIds = [...new Set([note.userId, ...votes.map(v => v.userId)])];
|
const userIds = [...new Set([note.userId, ...votes.map(v => v.userId)])];
|
||||||
|
|
||||||
for (const userId of userIds) {
|
for (const userId of userIds) {
|
||||||
this.notificationService.createNotification(userId, 'pollEnded', {
|
const profile = await this.cacheService.userProfileCache.fetch(userId);
|
||||||
noteId: note.id,
|
if (profile.userHost === null) {
|
||||||
});
|
this.notificationService.createNotification(userId, 'pollEnded', {
|
||||||
|
noteId: note.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,65 +5,24 @@
|
||||||
|
|
||||||
import { entities } from 'misskey-js';
|
import { entities } from 'misskey-js';
|
||||||
import { beforeEach, describe, test } from '@jest/globals';
|
import { beforeEach, describe, test } from '@jest/globals';
|
||||||
import Fastify from 'fastify';
|
import {
|
||||||
import { api, randomString, role, signup, startJobQueue, UserToken } from '../../utils.js';
|
api,
|
||||||
|
captureWebhook,
|
||||||
|
randomString,
|
||||||
|
role,
|
||||||
|
signup,
|
||||||
|
startJobQueue,
|
||||||
|
UserToken,
|
||||||
|
WEBHOOK_HOST,
|
||||||
|
} from '../../utils.js';
|
||||||
import type { INestApplicationContext } from '@nestjs/common';
|
import type { INestApplicationContext } from '@nestjs/common';
|
||||||
|
|
||||||
const WEBHOOK_HOST = 'http://localhost:15080';
|
|
||||||
const WEBHOOK_PORT = 15080;
|
|
||||||
process.env.NODE_ENV = 'test';
|
|
||||||
|
|
||||||
describe('[シナリオ] ユーザ通報', () => {
|
describe('[シナリオ] ユーザ通報', () => {
|
||||||
let queue: INestApplicationContext;
|
let queue: INestApplicationContext;
|
||||||
let admin: entities.SignupResponse;
|
let admin: entities.SignupResponse;
|
||||||
let alice: entities.SignupResponse;
|
let alice: entities.SignupResponse;
|
||||||
let bob: entities.SignupResponse;
|
let bob: entities.SignupResponse;
|
||||||
|
|
||||||
type SystemWebhookPayload = {
|
|
||||||
server: string;
|
|
||||||
hookId: string;
|
|
||||||
eventId: string;
|
|
||||||
createdAt: string;
|
|
||||||
type: string;
|
|
||||||
body: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
async function captureWebhook<T = SystemWebhookPayload>(postAction: () => Promise<void>): Promise<T> {
|
|
||||||
const fastify = Fastify();
|
|
||||||
|
|
||||||
let timeoutHandle: NodeJS.Timeout | null = null;
|
|
||||||
const result = await new Promise<string>(async (resolve, reject) => {
|
|
||||||
fastify.all('/', async (req, res) => {
|
|
||||||
timeoutHandle && clearTimeout(timeoutHandle);
|
|
||||||
|
|
||||||
const body = JSON.stringify(req.body);
|
|
||||||
res.status(200).send('ok');
|
|
||||||
await fastify.close();
|
|
||||||
resolve(body);
|
|
||||||
});
|
|
||||||
|
|
||||||
await fastify.listen({ port: WEBHOOK_PORT });
|
|
||||||
|
|
||||||
timeoutHandle = setTimeout(async () => {
|
|
||||||
await fastify.close();
|
|
||||||
reject(new Error('timeout'));
|
|
||||||
}, 3000);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await postAction();
|
|
||||||
} catch (e) {
|
|
||||||
await fastify.close();
|
|
||||||
reject(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await fastify.close();
|
|
||||||
|
|
||||||
return JSON.parse(result) as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createSystemWebhook(args?: Partial<entities.AdminSystemWebhookCreateRequest>, credential?: UserToken): Promise<entities.AdminSystemWebhookCreateResponse> {
|
async function createSystemWebhook(args?: Partial<entities.AdminSystemWebhookCreateRequest>, credential?: UserToken): Promise<entities.AdminSystemWebhookCreateResponse> {
|
||||||
const res = await api(
|
const res = await api(
|
||||||
'admin/system-webhook/create',
|
'admin/system-webhook/create',
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { setTimeout } from 'node:timers/promises';
|
||||||
|
import { entities } from 'misskey-js';
|
||||||
|
import { beforeEach, describe, test } from '@jest/globals';
|
||||||
|
import {
|
||||||
|
api,
|
||||||
|
captureWebhook,
|
||||||
|
randomString,
|
||||||
|
role,
|
||||||
|
signup,
|
||||||
|
startJobQueue,
|
||||||
|
UserToken,
|
||||||
|
WEBHOOK_HOST,
|
||||||
|
} from '../../utils.js';
|
||||||
|
import type { INestApplicationContext } from '@nestjs/common';
|
||||||
|
|
||||||
|
describe('[シナリオ] ユーザ作成', () => {
|
||||||
|
let queue: INestApplicationContext;
|
||||||
|
let admin: entities.SignupResponse;
|
||||||
|
|
||||||
|
async function createSystemWebhook(args?: Partial<entities.AdminSystemWebhookCreateRequest>, credential?: UserToken): Promise<entities.AdminSystemWebhookCreateResponse> {
|
||||||
|
const res = await api(
|
||||||
|
'admin/system-webhook/create',
|
||||||
|
{
|
||||||
|
isActive: true,
|
||||||
|
name: randomString(),
|
||||||
|
on: ['userCreated'],
|
||||||
|
url: WEBHOOK_HOST,
|
||||||
|
secret: randomString(),
|
||||||
|
...args,
|
||||||
|
},
|
||||||
|
credential ?? admin,
|
||||||
|
);
|
||||||
|
return res.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
queue = await startJobQueue();
|
||||||
|
admin = await signup({ username: 'admin' });
|
||||||
|
|
||||||
|
await role(admin, { isAdministrator: true });
|
||||||
|
}, 1000 * 60 * 2);
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await queue.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
describe('SystemWebhook', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
const webhooks = await api('admin/system-webhook/list', {}, admin);
|
||||||
|
for (const webhook of webhooks.body) {
|
||||||
|
await api('admin/system-webhook/delete', { id: webhook.id }, admin);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('ユーザが作成された -> userCreatedが送出される', async () => {
|
||||||
|
const webhook = await createSystemWebhook({
|
||||||
|
on: ['userCreated'],
|
||||||
|
isActive: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
let alice: any = null;
|
||||||
|
const webhookBody = await captureWebhook(async () => {
|
||||||
|
alice = await signup({ username: 'alice' });
|
||||||
|
});
|
||||||
|
|
||||||
|
// webhookの送出後にいろいろやってるのでちょっと待つ必要がある
|
||||||
|
await setTimeout(2000);
|
||||||
|
|
||||||
|
console.log(alice);
|
||||||
|
console.log(JSON.stringify(webhookBody, null, 2));
|
||||||
|
|
||||||
|
expect(webhookBody.hookId).toBe(webhook.id);
|
||||||
|
expect(webhookBody.type).toBe('userCreated');
|
||||||
|
|
||||||
|
const body = webhookBody.body as entities.UserLite;
|
||||||
|
expect(alice.id).toBe(body.id);
|
||||||
|
expect(alice.name).toBe(body.name);
|
||||||
|
expect(alice.username).toBe(body.username);
|
||||||
|
expect(alice.host).toBe(body.host);
|
||||||
|
expect(alice.avatarUrl).toBe(body.avatarUrl);
|
||||||
|
expect(alice.avatarBlurhash).toBe(body.avatarBlurhash);
|
||||||
|
expect(alice.avatarDecorations).toEqual(body.avatarDecorations);
|
||||||
|
expect(alice.isBot).toBe(body.isBot);
|
||||||
|
expect(alice.isCat).toBe(body.isCat);
|
||||||
|
expect(alice.instance).toEqual(body.instance);
|
||||||
|
expect(alice.emojis).toEqual(body.emojis);
|
||||||
|
expect(alice.onlineStatus).toBe(body.onlineStatus);
|
||||||
|
expect(alice.badgeRoles).toEqual(body.badgeRoles);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('ユーザ作成 -> userCreatedが未許可の場合は送出されない', async () => {
|
||||||
|
await createSystemWebhook({
|
||||||
|
on: [],
|
||||||
|
isActive: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
let alice: any = null;
|
||||||
|
const webhookBody = await captureWebhook(async () => {
|
||||||
|
alice = await signup({ username: 'alice' });
|
||||||
|
}).catch(e => e.message);
|
||||||
|
|
||||||
|
expect(webhookBody).toBe('timeout');
|
||||||
|
expect(alice.id).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('ユーザ作成 -> Webhookが無効の場合は送出されない', async () => {
|
||||||
|
await createSystemWebhook({
|
||||||
|
on: ['userCreated'],
|
||||||
|
isActive: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
let alice: any = null;
|
||||||
|
const webhookBody = await captureWebhook(async () => {
|
||||||
|
alice = await signup({ username: 'alice' });
|
||||||
|
}).catch(e => e.message);
|
||||||
|
|
||||||
|
expect(webhookBody).toBe('timeout');
|
||||||
|
expect(alice.id).not.toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -9,8 +9,8 @@
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { setTimeout } from 'node:timers/promises';
|
import { setTimeout } from 'node:timers/promises';
|
||||||
import { Redis } from 'ioredis';
|
import { Redis } from 'ioredis';
|
||||||
import { loadConfig } from '@/config.js';
|
|
||||||
import { api, post, randomString, sendEnvUpdateRequest, signup, uploadUrl } from '../utils.js';
|
import { api, post, randomString, sendEnvUpdateRequest, signup, uploadUrl } from '../utils.js';
|
||||||
|
import { loadConfig } from '@/config.js';
|
||||||
|
|
||||||
function genHost() {
|
function genHost() {
|
||||||
return randomString() + '.example.com';
|
return randomString() + '.example.com';
|
||||||
|
@ -492,6 +492,44 @@ describe('Timelines', () => {
|
||||||
|
|
||||||
assert.strictEqual(res.body.some(note => note.id === bobNote.id), false);
|
assert.strictEqual(res.body.some(note => note.id === bobNote.id), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.concurrent('FTT: ローカルユーザーの HTL にはプッシュされる', async () => {
|
||||||
|
const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]);
|
||||||
|
|
||||||
|
await api('following/create', {
|
||||||
|
userId: alice.id,
|
||||||
|
}, bob);
|
||||||
|
|
||||||
|
const aliceNote = await post(alice, { text: 'I\'m Alice.' });
|
||||||
|
const bobNote = await post(bob, { text: 'I\'m Bob.' });
|
||||||
|
const carolNote = await post(carol, { text: 'I\'m Carol.' });
|
||||||
|
|
||||||
|
await waitForPushToTl();
|
||||||
|
|
||||||
|
// NOTE: notes/timeline だと DB へのフォールバックが効くので Redis を直接見て確かめる
|
||||||
|
assert.strictEqual(await redisForTimelines.exists(`list:homeTimeline:${bob.id}`), 1);
|
||||||
|
|
||||||
|
const bobHTL = await redisForTimelines.lrange(`list:homeTimeline:${bob.id}`, 0, -1);
|
||||||
|
assert.strictEqual(bobHTL.includes(aliceNote.id), true);
|
||||||
|
assert.strictEqual(bobHTL.includes(bobNote.id), true);
|
||||||
|
assert.strictEqual(bobHTL.includes(carolNote.id), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.concurrent('FTT: リモートユーザーの HTL にはプッシュされない', async () => {
|
||||||
|
const [alice, bob] = await Promise.all([signup(), signup({ host: genHost() })]);
|
||||||
|
|
||||||
|
await api('following/create', {
|
||||||
|
userId: alice.id,
|
||||||
|
}, bob);
|
||||||
|
|
||||||
|
await post(alice, { text: 'I\'m Alice.' });
|
||||||
|
await post(bob, { text: 'I\'m Bob.' });
|
||||||
|
|
||||||
|
await waitForPushToTl();
|
||||||
|
|
||||||
|
// NOTE: notes/timeline だと DB へのフォールバックが効くので Redis を直接見て確かめる
|
||||||
|
assert.strictEqual(await redisForTimelines.exists(`list:homeTimeline:${bob.id}`), 0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Local TL', () => {
|
describe('Local TL', () => {
|
||||||
|
|
|
@ -12,13 +12,14 @@ import WebSocket, { ClientOptions } from 'ws';
|
||||||
import fetch, { File, RequestInit, type Headers } from 'node-fetch';
|
import fetch, { File, RequestInit, type Headers } from 'node-fetch';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
import { JSDOM } from 'jsdom';
|
import { JSDOM } from 'jsdom';
|
||||||
import { DEFAULT_POLICIES } from '@/core/RoleService.js';
|
import { type Response } from 'node-fetch';
|
||||||
import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js';
|
import Fastify from 'fastify';
|
||||||
import { entities } from '../src/postgres.js';
|
import { entities } from '../src/postgres.js';
|
||||||
import { loadConfig } from '../src/config.js';
|
import { loadConfig } from '../src/config.js';
|
||||||
import type * as misskey from 'misskey-js';
|
import type * as misskey from 'misskey-js';
|
||||||
import { type Response } from 'node-fetch';
|
import { DEFAULT_POLICIES } from '@/core/RoleService.js';
|
||||||
import { ApiError } from "@/server/api/error.js";
|
import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js';
|
||||||
|
import { ApiError } from '@/server/api/error.js';
|
||||||
|
|
||||||
export { server as startServer, jobQueue as startJobQueue } from '@/boot/common.js';
|
export { server as startServer, jobQueue as startJobQueue } from '@/boot/common.js';
|
||||||
|
|
||||||
|
@ -27,11 +28,23 @@ export interface UserToken {
|
||||||
bearer?: boolean;
|
bearer?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SystemWebhookPayload = {
|
||||||
|
server: string;
|
||||||
|
hookId: string;
|
||||||
|
eventId: string;
|
||||||
|
createdAt: string;
|
||||||
|
type: string;
|
||||||
|
body: any;
|
||||||
|
}
|
||||||
|
|
||||||
const config = loadConfig();
|
const config = loadConfig();
|
||||||
export const port = config.port;
|
export const port = config.port;
|
||||||
export const origin = config.url;
|
export const origin = config.url;
|
||||||
export const host = new URL(config.url).host;
|
export const host = new URL(config.url).host;
|
||||||
|
|
||||||
|
export const WEBHOOK_HOST = 'http://localhost:15080';
|
||||||
|
export const WEBHOOK_PORT = 15080;
|
||||||
|
|
||||||
export const cookie = (me: UserToken): string => {
|
export const cookie = (me: UserToken): string => {
|
||||||
return `token=${me.token};`;
|
return `token=${me.token};`;
|
||||||
};
|
};
|
||||||
|
@ -645,3 +658,37 @@ export async function sendEnvResetRequest() {
|
||||||
export function castAsError(obj: Record<string, unknown>): { error: ApiError } {
|
export function castAsError(obj: Record<string, unknown>): { error: ApiError } {
|
||||||
return obj as { error: ApiError };
|
return obj as { error: ApiError };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function captureWebhook<T = SystemWebhookPayload>(postAction: () => Promise<void>, port = WEBHOOK_PORT): Promise<T> {
|
||||||
|
const fastify = Fastify();
|
||||||
|
|
||||||
|
let timeoutHandle: NodeJS.Timeout | null = null;
|
||||||
|
const result = await new Promise<string>(async (resolve, reject) => {
|
||||||
|
fastify.all('/', async (req, res) => {
|
||||||
|
timeoutHandle && clearTimeout(timeoutHandle);
|
||||||
|
|
||||||
|
const body = JSON.stringify(req.body);
|
||||||
|
res.status(200).send('ok');
|
||||||
|
await fastify.close();
|
||||||
|
resolve(body);
|
||||||
|
});
|
||||||
|
|
||||||
|
await fastify.listen({ port });
|
||||||
|
|
||||||
|
timeoutHandle = setTimeout(async () => {
|
||||||
|
await fastify.close();
|
||||||
|
reject(new Error('timeout'));
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await postAction();
|
||||||
|
} catch (e) {
|
||||||
|
await fastify.close();
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await fastify.close();
|
||||||
|
|
||||||
|
return JSON.parse(result) as T;
|
||||||
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
"@syuilo/aiscript": "0.19.0",
|
"@syuilo/aiscript": "0.19.0",
|
||||||
"@tabler/icons-webfont": "3.3.0",
|
"@tabler/icons-webfont": "3.3.0",
|
||||||
"@twemoji/parser": "15.1.1",
|
"@twemoji/parser": "15.1.1",
|
||||||
"@vitejs/plugin-vue": "5.0.5",
|
"@vitejs/plugin-vue": "5.1.0",
|
||||||
"@vue/compiler-sfc": "3.4.31",
|
"@vue/compiler-sfc": "3.4.34",
|
||||||
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.11",
|
"aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.11",
|
||||||
"astring": "1.8.6",
|
"astring": "1.8.6",
|
||||||
"broadcast-channel": "7.0.0",
|
"broadcast-channel": "7.0.0",
|
||||||
|
@ -39,9 +39,9 @@
|
||||||
"chartjs-chart-matrix": "2.0.1",
|
"chartjs-chart-matrix": "2.0.1",
|
||||||
"chartjs-plugin-gradient": "0.6.1",
|
"chartjs-plugin-gradient": "0.6.1",
|
||||||
"chartjs-plugin-zoom": "2.0.1",
|
"chartjs-plugin-zoom": "2.0.1",
|
||||||
"chromatic": "11.5.4",
|
"chromatic": "11.5.6",
|
||||||
"compare-versions": "6.1.0",
|
"compare-versions": "6.1.1",
|
||||||
"cropperjs": "2.0.0-beta.5",
|
"cropperjs": "2.0.0-rc.1",
|
||||||
"date-fns": "2.30.0",
|
"date-fns": "2.30.0",
|
||||||
"escape-regexp": "0.0.1",
|
"escape-regexp": "0.0.1",
|
||||||
"estree-walker": "3.0.3",
|
"estree-walker": "3.0.3",
|
||||||
|
@ -57,85 +57,85 @@
|
||||||
"misskey-reversi": "workspace:*",
|
"misskey-reversi": "workspace:*",
|
||||||
"photoswipe": "5.4.4",
|
"photoswipe": "5.4.4",
|
||||||
"punycode": "2.3.1",
|
"punycode": "2.3.1",
|
||||||
"rollup": "4.18.0",
|
"rollup": "4.19.1",
|
||||||
"sanitize-html": "2.13.0",
|
"sanitize-html": "2.13.0",
|
||||||
"sass": "1.77.6",
|
"sass": "1.77.8",
|
||||||
"shiki": "1.10.0",
|
"shiki": "1.12.0",
|
||||||
"strict-event-emitter-types": "2.0.0",
|
"strict-event-emitter-types": "2.0.0",
|
||||||
"textarea-caret": "3.1.0",
|
"textarea-caret": "3.1.0",
|
||||||
"three": "0.165.0",
|
"three": "0.167.0",
|
||||||
"throttle-debounce": "5.0.2",
|
"throttle-debounce": "5.0.2",
|
||||||
"tinycolor2": "1.6.0",
|
"tinycolor2": "1.6.0",
|
||||||
"tsc-alias": "1.8.10",
|
"tsc-alias": "1.8.10",
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"typescript": "5.5.3",
|
"typescript": "5.5.4",
|
||||||
"uuid": "10.0.0",
|
"uuid": "10.0.0",
|
||||||
"v-code-diff": "1.12.0",
|
"v-code-diff": "1.12.0",
|
||||||
"vite": "5.3.2",
|
"vite": "5.3.5",
|
||||||
"vue": "3.4.31",
|
"vue": "3.4.34",
|
||||||
"vuedraggable": "next"
|
"vuedraggable": "next"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@misskey-dev/summaly": "5.1.0",
|
"@misskey-dev/summaly": "5.1.0",
|
||||||
"@storybook/addon-actions": "8.1.11",
|
"@storybook/addon-actions": "8.2.6",
|
||||||
"@storybook/addon-essentials": "8.1.11",
|
"@storybook/addon-essentials": "8.2.6",
|
||||||
"@storybook/addon-interactions": "8.1.11",
|
"@storybook/addon-interactions": "8.2.6",
|
||||||
"@storybook/addon-links": "8.1.11",
|
"@storybook/addon-links": "8.2.6",
|
||||||
"@storybook/addon-mdx-gfm": "8.1.11",
|
"@storybook/addon-mdx-gfm": "8.2.6",
|
||||||
"@storybook/addon-storysource": "8.1.11",
|
"@storybook/addon-storysource": "8.2.6",
|
||||||
"@storybook/blocks": "8.1.11",
|
"@storybook/blocks": "8.2.6",
|
||||||
"@storybook/components": "8.1.11",
|
"@storybook/components": "8.2.6",
|
||||||
"@storybook/core-events": "8.1.11",
|
"@storybook/core-events": "8.2.6",
|
||||||
"@storybook/manager-api": "8.1.11",
|
"@storybook/manager-api": "8.2.6",
|
||||||
"@storybook/preview-api": "8.1.11",
|
"@storybook/preview-api": "8.2.6",
|
||||||
"@storybook/react": "8.1.11",
|
"@storybook/react": "8.2.6",
|
||||||
"@storybook/react-vite": "8.1.11",
|
"@storybook/react-vite": "8.2.6",
|
||||||
"@storybook/test": "8.1.11",
|
"@storybook/test": "8.2.6",
|
||||||
"@storybook/theming": "8.1.11",
|
"@storybook/theming": "8.2.6",
|
||||||
"@storybook/types": "8.1.11",
|
"@storybook/types": "8.2.6",
|
||||||
"@storybook/vue3": "8.1.11",
|
"@storybook/vue3": "8.2.6",
|
||||||
"@storybook/vue3-vite": "8.1.11",
|
"@storybook/vue3-vite": "8.1.11",
|
||||||
"@testing-library/vue": "8.1.0",
|
"@testing-library/vue": "8.1.0",
|
||||||
"@types/escape-regexp": "0.0.3",
|
"@types/escape-regexp": "0.0.3",
|
||||||
"@types/estree": "1.0.5",
|
"@types/estree": "1.0.5",
|
||||||
"@types/matter-js": "0.19.6",
|
"@types/matter-js": "0.19.7",
|
||||||
"@types/micromatch": "4.0.9",
|
"@types/micromatch": "4.0.9",
|
||||||
"@types/node": "20.14.9",
|
"@types/node": "20.14.12",
|
||||||
"@types/punycode": "2.1.4",
|
"@types/punycode": "2.1.4",
|
||||||
"@types/sanitize-html": "2.11.0",
|
"@types/sanitize-html": "2.11.0",
|
||||||
"@types/seedrandom": "3.0.8",
|
"@types/seedrandom": "3.0.8",
|
||||||
"@types/throttle-debounce": "5.0.2",
|
"@types/throttle-debounce": "5.0.2",
|
||||||
"@types/tinycolor2": "1.4.6",
|
"@types/tinycolor2": "1.4.6",
|
||||||
"@types/uuid": "10.0.0",
|
"@types/uuid": "10.0.0",
|
||||||
"@types/ws": "8.5.10",
|
"@types/ws": "8.5.11",
|
||||||
"@typescript-eslint/eslint-plugin": "7.15.0",
|
"@typescript-eslint/eslint-plugin": "7.17.0",
|
||||||
"@typescript-eslint/parser": "7.15.0",
|
"@typescript-eslint/parser": "7.17.0",
|
||||||
"@vitest/coverage-v8": "1.6.0",
|
"@vitest/coverage-v8": "1.6.0",
|
||||||
"@vue/runtime-core": "3.4.31",
|
"@vue/runtime-core": "3.4.34",
|
||||||
"acorn": "8.12.0",
|
"acorn": "8.12.1",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"cypress": "13.13.0",
|
"cypress": "13.13.1",
|
||||||
"eslint-plugin-import": "2.29.1",
|
"eslint-plugin-import": "2.29.1",
|
||||||
"eslint-plugin-vue": "9.26.0",
|
"eslint-plugin-vue": "9.27.0",
|
||||||
"fast-glob": "3.3.2",
|
"fast-glob": "3.3.2",
|
||||||
"happy-dom": "10.0.3",
|
"happy-dom": "10.0.3",
|
||||||
"intersection-observer": "0.12.2",
|
"intersection-observer": "0.12.2",
|
||||||
"micromatch": "4.0.7",
|
"micromatch": "4.0.7",
|
||||||
"msw": "2.3.1",
|
"msw": "2.3.4",
|
||||||
"msw-storybook-addon": "2.0.2",
|
"msw-storybook-addon": "2.0.3",
|
||||||
"nodemon": "3.1.4",
|
"nodemon": "3.1.4",
|
||||||
"prettier": "3.3.2",
|
"prettier": "3.3.3",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"seedrandom": "3.0.5",
|
"seedrandom": "3.0.5",
|
||||||
"start-server-and-test": "2.0.4",
|
"start-server-and-test": "2.0.4",
|
||||||
"storybook": "8.1.11",
|
"storybook": "8.2.6",
|
||||||
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
"storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme",
|
||||||
"vite-plugin-turbosnap": "1.0.3",
|
"vite-plugin-turbosnap": "1.0.3",
|
||||||
"vitest": "1.6.0",
|
"vitest": "1.6.0",
|
||||||
"vitest-fetch-mock": "0.2.2",
|
"vitest-fetch-mock": "0.2.2",
|
||||||
"vue-component-type-helpers": "2.0.24",
|
"vue-component-type-helpers": "2.0.29",
|
||||||
"vue-eslint-parser": "9.4.3",
|
"vue-eslint-parser": "9.4.3",
|
||||||
"vue-tsc": "2.0.24"
|
"vue-tsc": "2.0.29"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,12 @@
|
||||||
|
|
||||||
import { createApp, defineAsyncComponent } from 'vue';
|
import { createApp, defineAsyncComponent } from 'vue';
|
||||||
import { common } from './common.js';
|
import { common } from './common.js';
|
||||||
|
import { emojiPicker } from '@/scripts/emoji-picker.js';
|
||||||
|
|
||||||
export async function subBoot() {
|
export async function subBoot() {
|
||||||
const { isClientUpdated } = await common(() => createApp(
|
const { isClientUpdated } = await common(() => createApp(
|
||||||
defineAsyncComponent(() => import('@/ui/minimum.vue')),
|
defineAsyncComponent(() => import('@/ui/minimum.vue')),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
emojiPicker.init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkModal ref="modal" :preferType="'dialog'" @click="onBgClick" @closed="emit('closed')" @esc="emit('esc')">
|
<MkModal ref="modal" :preferType="'dialog'" @click="onBgClick" @closed="emit('closed')" @esc="emit('esc')">
|
||||||
<div ref="rootEl" :class="$style.root" :style="{ width: `${width}px`, height: `min(${height}px, 100%)` }">
|
<div ref="rootEl" :class="$style.root" :style="{ width: `${width}px`, height: `min(${height}px, 100%)` }">
|
||||||
<div ref="headerEl" :class="$style.header">
|
<div ref="headerEl" :class="$style.header">
|
||||||
<button v-if="withOkButton" :class="$style.headerButton" class="_button" @click="$emit('close')"><i class="ti ti-x"></i></button>
|
<button v-if="withOkButton && withCloseButton" :class="$style.headerButton" class="_button" @click="emit('close')"><i class="ti ti-x"></i></button>
|
||||||
<span :class="$style.title">
|
<span :class="$style.title">
|
||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
</span>
|
</span>
|
||||||
<button v-if="!withOkButton" :class="$style.headerButton" class="_button" data-cy-modal-window-close @click="$emit('close')"><i class="ti ti-x"></i></button>
|
<button v-if="!withOkButton && withCloseButton" :class="$style.headerButton" class="_button" data-cy-modal-window-close @click="emit('close')"><i class="ti ti-x"></i></button>
|
||||||
<button v-if="withOkButton" :class="$style.headerButton" class="_button" :disabled="okButtonDisabled" @click="$emit('ok')"><i class="ti ti-check"></i></button>
|
<button v-if="withOkButton" :class="$style.headerButton" class="_button" :disabled="okButtonDisabled" @click="emit('ok')"><i class="ti ti-check"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.body">
|
<div :class="$style.body">
|
||||||
<slot :width="bodyWidth" :height="bodyHeight"></slot>
|
<slot :width="bodyWidth" :height="bodyHeight"></slot>
|
||||||
|
@ -27,11 +27,13 @@ import MkModal from './MkModal.vue';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
withOkButton: boolean;
|
withOkButton: boolean;
|
||||||
|
withCloseButton: boolean;
|
||||||
okButtonDisabled: boolean;
|
okButtonDisabled: boolean;
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
}>(), {
|
}>(), {
|
||||||
withOkButton: false,
|
withOkButton: false,
|
||||||
|
withCloseButton: true,
|
||||||
okButtonDisabled: false,
|
okButtonDisabled: false,
|
||||||
width: 400,
|
width: 400,
|
||||||
height: 500,
|
height: 500,
|
||||||
|
@ -51,13 +53,13 @@ const headerEl = shallowRef<HTMLElement>();
|
||||||
const bodyWidth = ref(0);
|
const bodyWidth = ref(0);
|
||||||
const bodyHeight = ref(0);
|
const bodyHeight = ref(0);
|
||||||
|
|
||||||
const close = () => {
|
function close() {
|
||||||
modal.value?.close();
|
modal.value?.close();
|
||||||
};
|
}
|
||||||
|
|
||||||
const onBgClick = () => {
|
function onBgClick() {
|
||||||
emit('click');
|
emit('click');
|
||||||
};
|
}
|
||||||
|
|
||||||
const ro = new ResizeObserver((entries, observer) => {
|
const ro = new ResizeObserver((entries, observer) => {
|
||||||
if (rootEl.value == null || headerEl.value == null) return;
|
if (rootEl.value == null || headerEl.value == null) return;
|
||||||
|
|
|
@ -37,7 +37,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</section>
|
</section>
|
||||||
<section v-else-if="expiration === 'after'">
|
<section v-else-if="expiration === 'after'">
|
||||||
<MkInput v-model="after" small type="number" class="input">
|
<MkInput v-model="after" small type="number" min="1" class="input">
|
||||||
<template #label>{{ i18n.ts._poll.duration }}</template>
|
<template #label>{{ i18n.ts._poll.duration }}</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
<MkSelect v-model="unit" small>
|
<MkSelect v-model="unit" small>
|
||||||
|
|
|
@ -367,6 +367,8 @@ function watchForDraft() {
|
||||||
watch(files, () => saveDraft(), { deep: true });
|
watch(files, () => saveDraft(), { deep: true });
|
||||||
watch(visibility, () => saveDraft());
|
watch(visibility, () => saveDraft());
|
||||||
watch(localOnly, () => saveDraft());
|
watch(localOnly, () => saveDraft());
|
||||||
|
watch(quoteId, () => saveDraft());
|
||||||
|
watch(reactionAcceptance, () => saveDraft());
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkMissingMention() {
|
function checkMissingMention() {
|
||||||
|
@ -703,6 +705,8 @@ function saveDraft() {
|
||||||
files: files.value,
|
files: files.value,
|
||||||
poll: poll.value,
|
poll: poll.value,
|
||||||
visibleUserIds: visibility.value === 'specified' ? visibleUsers.value.map(x => x.id) : undefined,
|
visibleUserIds: visibility.value === 'specified' ? visibleUsers.value.map(x => x.id) : undefined,
|
||||||
|
quoteId: quoteId.value,
|
||||||
|
reactionAcceptance: reactionAcceptance.value,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -991,6 +995,8 @@ onMounted(() => {
|
||||||
users.forEach(u => pushVisibleUser(u));
|
users.forEach(u => pushVisibleUser(u));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
quoteId.value = draft.data.quoteId;
|
||||||
|
reactionAcceptance.value = draft.data.reactionAcceptance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -998,9 +1004,11 @@ onMounted(() => {
|
||||||
if (props.initialNote) {
|
if (props.initialNote) {
|
||||||
const init = props.initialNote;
|
const init = props.initialNote;
|
||||||
text.value = init.text ? init.text : '';
|
text.value = init.text ? init.text : '';
|
||||||
files.value = init.files ?? [];
|
|
||||||
cw.value = init.cw ?? null;
|
|
||||||
useCw.value = init.cw != null;
|
useCw.value = init.cw != null;
|
||||||
|
cw.value = init.cw ?? null;
|
||||||
|
visibility.value = init.visibility;
|
||||||
|
localOnly.value = init.localOnly ?? false;
|
||||||
|
files.value = init.files ?? [];
|
||||||
if (init.poll) {
|
if (init.poll) {
|
||||||
poll.value = {
|
poll.value = {
|
||||||
choices: init.poll.choices.map(x => x.text),
|
choices: init.poll.choices.map(x => x.text),
|
||||||
|
@ -1009,9 +1017,13 @@ onMounted(() => {
|
||||||
expiredAfter: null,
|
expiredAfter: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
visibility.value = init.visibility;
|
if (init.visibleUserIds) {
|
||||||
localOnly.value = init.localOnly ?? false;
|
misskeyApi('users/show', { userIds: init.visibleUserIds }).then(users => {
|
||||||
|
users.forEach(u => pushVisibleUser(u));
|
||||||
|
});
|
||||||
|
}
|
||||||
quoteId.value = init.renote ? init.renote.id : null;
|
quoteId.value = init.renote ? init.renote.id : null;
|
||||||
|
reactionAcceptance.value = init.reactionAcceptance;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextTick(() => watchForDraft());
|
nextTick(() => watchForDraft());
|
||||||
|
|
|
@ -81,6 +81,7 @@ function getReactionName(reaction: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
.user {
|
.user {
|
||||||
|
display: flex;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
|
@ -24,22 +24,23 @@ export type MkSystemWebhookResult = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function showSystemWebhookEditorDialog(props: MkSystemWebhookEditorProps): Promise<MkSystemWebhookResult | null> {
|
export async function showSystemWebhookEditorDialog(props: MkSystemWebhookEditorProps): Promise<MkSystemWebhookResult | null> {
|
||||||
const { dispose, result } = await new Promise<{ dispose: () => void, result: MkSystemWebhookResult | null }>(async resolve => {
|
const { result } = await new Promise<{ result: MkSystemWebhookResult | null }>(async resolve => {
|
||||||
const { dispose: _dispose } = os.popup(
|
const { dispose } = os.popup(
|
||||||
defineAsyncComponent(() => import('@/components/MkSystemWebhookEditor.vue')),
|
defineAsyncComponent(() => import('@/components/MkSystemWebhookEditor.vue')),
|
||||||
props,
|
props,
|
||||||
{
|
{
|
||||||
submitted: (ev: MkSystemWebhookResult) => {
|
submitted: (ev: MkSystemWebhookResult) => {
|
||||||
resolve({ dispose: _dispose, result: ev });
|
resolve({ result: ev });
|
||||||
|
},
|
||||||
|
canceled: () => {
|
||||||
|
resolve({ result: null });
|
||||||
},
|
},
|
||||||
closed: () => {
|
closed: () => {
|
||||||
resolve({ dispose: _dispose, result: null });
|
dispose();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
dispose();
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<MkModalWindow
|
<MkModalWindow
|
||||||
|
ref="dialogEl"
|
||||||
:width="450"
|
:width="450"
|
||||||
:height="590"
|
:height="590"
|
||||||
:canClose="true"
|
:canClose="true"
|
||||||
|
@ -12,55 +13,59 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:okButtonDisabled="false"
|
:okButtonDisabled="false"
|
||||||
@click="onCancelClicked"
|
@click="onCancelClicked"
|
||||||
@close="onCancelClicked"
|
@close="onCancelClicked"
|
||||||
@closed="onCancelClicked"
|
@closed="emit('closed')"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
{{ mode === 'create' ? i18n.ts._webhookSettings.createWebhook : i18n.ts._webhookSettings.modifyWebhook }}
|
{{ mode === 'create' ? i18n.ts._webhookSettings.createWebhook : i18n.ts._webhookSettings.modifyWebhook }}
|
||||||
</template>
|
</template>
|
||||||
<MkSpacer :marginMin="20" :marginMax="28">
|
|
||||||
<MkLoading v-if="loading !== 0"/>
|
|
||||||
<div v-else :class="$style.root" class="_gaps_m">
|
|
||||||
<MkInput v-model="title">
|
|
||||||
<template #label>{{ i18n.ts._webhookSettings.name }}</template>
|
|
||||||
</MkInput>
|
|
||||||
<MkInput v-model="url">
|
|
||||||
<template #label>URL</template>
|
|
||||||
</MkInput>
|
|
||||||
<MkInput v-model="secret">
|
|
||||||
<template #label>{{ i18n.ts._webhookSettings.secret }}</template>
|
|
||||||
</MkInput>
|
|
||||||
<MkFolder :defaultOpen="true">
|
|
||||||
<template #label>{{ i18n.ts._webhookSettings.events }}</template>
|
|
||||||
|
|
||||||
<div class="_gaps_s">
|
<div>
|
||||||
<MkSwitch v-model="events.abuseReport" :disabled="disabledEvents.abuseReport">
|
<MkSpacer :marginMin="20" :marginMax="28">
|
||||||
<template #label>{{ i18n.ts._webhookSettings._systemEvents.abuseReport }}</template>
|
<MkLoading v-if="loading !== 0"/>
|
||||||
</MkSwitch>
|
<div v-else :class="$style.root" class="_gaps_m">
|
||||||
<MkSwitch v-model="events.abuseReportResolved" :disabled="disabledEvents.abuseReportResolved">
|
<MkInput v-model="title">
|
||||||
<template #label>{{ i18n.ts._webhookSettings._systemEvents.abuseReportResolved }}</template>
|
<template #label>{{ i18n.ts._webhookSettings.name }}</template>
|
||||||
</MkSwitch>
|
</MkInput>
|
||||||
</div>
|
<MkInput v-model="url">
|
||||||
</MkFolder>
|
<template #label>URL</template>
|
||||||
|
</MkInput>
|
||||||
|
<MkInput v-model="secret">
|
||||||
|
<template #label>{{ i18n.ts._webhookSettings.secret }}</template>
|
||||||
|
</MkInput>
|
||||||
|
<MkFolder :defaultOpen="true">
|
||||||
|
<template #label>{{ i18n.ts._webhookSettings.events }}</template>
|
||||||
|
|
||||||
<MkSwitch v-model="isActive">
|
<div class="_gaps_s">
|
||||||
<template #label>{{ i18n.ts.enable }}</template>
|
<MkSwitch v-model="events.abuseReport" :disabled="disabledEvents.abuseReport">
|
||||||
</MkSwitch>
|
<template #label>{{ i18n.ts._webhookSettings._systemEvents.abuseReport }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
<MkSwitch v-model="events.abuseReportResolved" :disabled="disabledEvents.abuseReportResolved">
|
||||||
|
<template #label>{{ i18n.ts._webhookSettings._systemEvents.abuseReportResolved }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
<MkSwitch v-model="events.userCreated" :disabled="disabledEvents.userCreated">
|
||||||
|
<template #label>{{ i18n.ts._webhookSettings._systemEvents.userCreated }}</template>
|
||||||
|
</MkSwitch>
|
||||||
|
</div>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
<div :class="$style.footer" class="_buttonsCenter">
|
<MkSwitch v-model="isActive">
|
||||||
<MkButton primary :disabled="disableSubmitButton" @click="onSubmitClicked">
|
<template #label>{{ i18n.ts.enable }}</template>
|
||||||
<i class="ti ti-check"></i>
|
</MkSwitch>
|
||||||
{{ i18n.ts.ok }}
|
|
||||||
</MkButton>
|
|
||||||
<MkButton @click="onCancelClicked"><i class="ti ti-x"></i> {{ i18n.ts.cancel }}</MkButton>
|
|
||||||
</div>
|
</div>
|
||||||
|
</MkSpacer>
|
||||||
|
<div :class="$style.footer" class="_buttonsCenter">
|
||||||
|
<MkButton primary rounded :disabled="disableSubmitButton" @click="onSubmitClicked">
|
||||||
|
<i class="ti ti-check"></i>
|
||||||
|
{{ i18n.ts.ok }}
|
||||||
|
</MkButton>
|
||||||
|
<MkButton rounded @click="onCancelClicked"><i class="ti ti-x"></i> {{ i18n.ts.cancel }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</MkSpacer>
|
</div>
|
||||||
</MkModalWindow>
|
</MkModalWindow>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref, toRefs } from 'vue';
|
import { computed, onMounted, ref, shallowRef, toRefs } from 'vue';
|
||||||
import FormSection from '@/components/form/section.vue';
|
|
||||||
import MkInput from '@/components/MkInput.vue';
|
import MkInput from '@/components/MkInput.vue';
|
||||||
import MkSwitch from '@/components/MkSwitch.vue';
|
import MkSwitch from '@/components/MkSwitch.vue';
|
||||||
import {
|
import {
|
||||||
|
@ -78,13 +83,17 @@ import * as os from '@/os.js';
|
||||||
type EventType = {
|
type EventType = {
|
||||||
abuseReport: boolean;
|
abuseReport: boolean;
|
||||||
abuseReportResolved: boolean;
|
abuseReportResolved: boolean;
|
||||||
|
userCreated: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'submitted', result: MkSystemWebhookResult): void;
|
(ev: 'submitted', result: MkSystemWebhookResult): void;
|
||||||
|
(ev: 'canceled'): void;
|
||||||
(ev: 'closed'): void;
|
(ev: 'closed'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const dialogEl = shallowRef<InstanceType<typeof MkModalWindow>>();
|
||||||
|
|
||||||
const props = defineProps<MkSystemWebhookEditorProps>();
|
const props = defineProps<MkSystemWebhookEditorProps>();
|
||||||
|
|
||||||
const { mode, id, requiredEvents } = toRefs(props);
|
const { mode, id, requiredEvents } = toRefs(props);
|
||||||
|
@ -97,12 +106,14 @@ const secret = ref<string>('');
|
||||||
const events = ref<EventType>({
|
const events = ref<EventType>({
|
||||||
abuseReport: true,
|
abuseReport: true,
|
||||||
abuseReportResolved: true,
|
abuseReportResolved: true,
|
||||||
|
userCreated: true,
|
||||||
});
|
});
|
||||||
const isActive = ref<boolean>(true);
|
const isActive = ref<boolean>(true);
|
||||||
|
|
||||||
const disabledEvents = ref<EventType>({
|
const disabledEvents = ref<EventType>({
|
||||||
abuseReport: false,
|
abuseReport: false,
|
||||||
abuseReportResolved: false,
|
abuseReportResolved: false,
|
||||||
|
userCreated: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const disableSubmitButton = computed(() => {
|
const disableSubmitButton = computed(() => {
|
||||||
|
@ -133,12 +144,14 @@ async function onSubmitClicked() {
|
||||||
switch (mode.value) {
|
switch (mode.value) {
|
||||||
case 'create': {
|
case 'create': {
|
||||||
const result = await misskeyApi('admin/system-webhook/create', params);
|
const result = await misskeyApi('admin/system-webhook/create', params);
|
||||||
|
dialogEl.value?.close();
|
||||||
emit('submitted', result);
|
emit('submitted', result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'edit': {
|
case 'edit': {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const result = await misskeyApi('admin/system-webhook/update', { id: id.value!, ...params });
|
const result = await misskeyApi('admin/system-webhook/update', { id: id.value!, ...params });
|
||||||
|
dialogEl.value?.close();
|
||||||
emit('submitted', result);
|
emit('submitted', result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -147,13 +160,15 @@ async function onSubmitClicked() {
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
const msg = ex.message ?? i18n.ts.internalServerErrorDescription;
|
const msg = ex.message ?? i18n.ts.internalServerErrorDescription;
|
||||||
await os.alert({ type: 'error', title: i18n.ts.error, text: msg });
|
await os.alert({ type: 'error', title: i18n.ts.error, text: msg });
|
||||||
emit('closed');
|
dialogEl.value?.close();
|
||||||
|
emit('canceled');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCancelClicked() {
|
function onCancelClicked() {
|
||||||
emit('closed');
|
dialogEl.value?.close();
|
||||||
|
emit('canceled');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadingScope<T>(fn: () => Promise<T>): Promise<T> {
|
async function loadingScope<T>(fn: () => Promise<T>): Promise<T> {
|
||||||
|
@ -183,11 +198,12 @@ onMounted(async () => {
|
||||||
for (const ev of Object.keys(events.value)) {
|
for (const ev of Object.keys(events.value)) {
|
||||||
events.value[ev] = res.on.includes(ev as SystemWebhookEventType);
|
events.value[ev] = res.on.includes(ev as SystemWebhookEventType);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
const msg = ex.message ?? i18n.ts.internalServerErrorDescription;
|
const msg = ex.message ?? i18n.ts.internalServerErrorDescription;
|
||||||
await os.alert({ type: 'error', title: i18n.ts.error, text: msg });
|
await os.alert({ type: 'error', title: i18n.ts.error, text: msg });
|
||||||
emit('closed');
|
dialogEl.value?.close();
|
||||||
|
emit('canceled');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -209,9 +225,12 @@ onMounted(async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
display: flex;
|
position: sticky;
|
||||||
justify-content: center;
|
bottom: 0;
|
||||||
align-items: flex-end;
|
left: 0;
|
||||||
margin-top: 20px;
|
padding: 12px;
|
||||||
|
border-top: solid 0.5px var(--divider);
|
||||||
|
-webkit-backdrop-filter: var(--blur, blur(15px));
|
||||||
|
backdrop-filter: var(--blur, blur(15px));
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -61,7 +61,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref, shallowRef } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import MkInput from '@/components/MkInput.vue';
|
import MkInput from '@/components/MkInput.vue';
|
||||||
import FormSplit from '@/components/form/split.vue';
|
import FormSplit from '@/components/form/split.vue';
|
||||||
|
@ -91,7 +91,7 @@ const host = ref('');
|
||||||
const users = ref<Misskey.entities.UserLite[]>([]);
|
const users = ref<Misskey.entities.UserLite[]>([]);
|
||||||
const recentUsers = ref<Misskey.entities.UserDetailed[]>([]);
|
const recentUsers = ref<Misskey.entities.UserDetailed[]>([]);
|
||||||
const selected = ref<Misskey.entities.UserLite | null>(null);
|
const selected = ref<Misskey.entities.UserLite | null>(null);
|
||||||
const dialogEl = ref();
|
const dialogEl = shallowRef<InstanceType<typeof MkModalWindow>>();
|
||||||
|
|
||||||
function search() {
|
function search() {
|
||||||
if (username.value === '' && host.value === '') {
|
if (username.value === '' && host.value === '') {
|
||||||
|
@ -122,7 +122,7 @@ async function ok() {
|
||||||
});
|
});
|
||||||
emit('ok', user);
|
emit('ok', user);
|
||||||
|
|
||||||
dialogEl.value.close();
|
dialogEl.value?.close();
|
||||||
|
|
||||||
// 最近使ったユーザー更新
|
// 最近使ったユーザー更新
|
||||||
let recents = defaultStore.state.recentlyUsedUsers;
|
let recents = defaultStore.state.recentlyUsedUsers;
|
||||||
|
@ -133,7 +133,7 @@ async function ok() {
|
||||||
|
|
||||||
function cancel() {
|
function cancel() {
|
||||||
emit('cancel');
|
emit('cancel');
|
||||||
dialogEl.value.close();
|
dialogEl.value?.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -53,7 +53,7 @@ function resolveNested(current: Resolved, d = 0): Resolved | null {
|
||||||
const current = resolveNested(router.current)!;
|
const current = resolveNested(router.current)!;
|
||||||
const currentPageComponent = shallowRef('component' in current.route ? current.route.component : MkLoadingPage);
|
const currentPageComponent = shallowRef('component' in current.route ? current.route.component : MkLoadingPage);
|
||||||
const currentPageProps = ref(current.props);
|
const currentPageProps = ref(current.props);
|
||||||
const key = ref(current.route.path + JSON.stringify(Object.fromEntries(current.props)));
|
const key = ref(router.getCurrentKey() + JSON.stringify(Object.fromEntries(current.props)));
|
||||||
|
|
||||||
function onChange({ resolved, key: newKey }) {
|
function onChange({ resolved, key: newKey }) {
|
||||||
const current = resolveNested(resolved);
|
const current = resolveNested(resolved);
|
||||||
|
|
|
@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<MkModalWindow
|
<MkModalWindow
|
||||||
ref="dialog"
|
ref="dialogEl"
|
||||||
:width="400"
|
:width="400"
|
||||||
:height="490"
|
:height="490"
|
||||||
:withOkButton="false"
|
:withOkButton="false"
|
||||||
|
@ -71,7 +71,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, onMounted, ref, toRefs } from 'vue';
|
import { computed, onMounted, ref, shallowRef, toRefs } from 'vue';
|
||||||
import { entities } from 'misskey-js';
|
import { entities } from 'misskey-js';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import MkModalWindow from '@/components/MkModalWindow.vue';
|
import MkModalWindow from '@/components/MkModalWindow.vue';
|
||||||
|
@ -88,6 +88,7 @@ type NotificationRecipientMethod = 'email' | 'webhook';
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(ev: 'submitted'): void;
|
(ev: 'submitted'): void;
|
||||||
|
(ev: 'canceled'): void;
|
||||||
(ev: 'closed'): void;
|
(ev: 'closed'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
@ -98,6 +99,8 @@ const props = defineProps<{
|
||||||
|
|
||||||
const { mode, id } = toRefs(props);
|
const { mode, id } = toRefs(props);
|
||||||
|
|
||||||
|
const dialogEl = shallowRef<InstanceType<typeof MkModalWindow>>();
|
||||||
|
|
||||||
const loading = ref<number>(0);
|
const loading = ref<number>(0);
|
||||||
|
|
||||||
const title = ref<string>('');
|
const title = ref<string>('');
|
||||||
|
@ -166,18 +169,21 @@ async function onSubmitClicked() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialogEl.value?.close();
|
||||||
emit('submitted');
|
emit('submitted');
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
const msg = ex.message ?? i18n.ts.internalServerErrorDescription;
|
const msg = ex.message ?? i18n.ts.internalServerErrorDescription;
|
||||||
await os.alert({ type: 'error', title: i18n.ts.error, text: msg });
|
await os.alert({ type: 'error', title: i18n.ts.error, text: msg });
|
||||||
emit('closed');
|
dialogEl.value?.close();
|
||||||
|
emit('canceled');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCancelClicked() {
|
function onCancelClicked() {
|
||||||
emit('closed');
|
dialogEl.value?.close();
|
||||||
|
emit('canceled');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onEditSystemWebhookClicked() {
|
async function onEditSystemWebhookClicked() {
|
||||||
|
@ -262,7 +268,8 @@ onMounted(async () => {
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
const msg = ex.message ?? i18n.ts.internalServerErrorDescription;
|
const msg = ex.message ?? i18n.ts.internalServerErrorDescription;
|
||||||
await os.alert({ type: 'error', title: i18n.ts.error, text: msg });
|
await os.alert({ type: 'error', title: i18n.ts.error, text: msg });
|
||||||
emit('closed');
|
dialogEl.value?.close();
|
||||||
|
emit('canceled');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
userId.value = moderators.value[0]?.id ?? null;
|
userId.value = moderators.value[0]?.id ?? null;
|
||||||
|
@ -296,11 +303,13 @@ onMounted(async () => {
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
width: 2.5em;
|
min-width: 0;
|
||||||
height: 2.5em;
|
min-height: 0;
|
||||||
min-width: 2.5em;
|
width: 34px;
|
||||||
min-height: 2.5em;
|
height: 34px;
|
||||||
|
flex-shrink: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
margin: 1px 0;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,26 +108,27 @@ async function onDeleteButtonClicked(id: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function showEditor(mode: 'create' | 'edit', id?: string) {
|
async function showEditor(mode: 'create' | 'edit', id?: string) {
|
||||||
const { dispose, needLoad } = await new Promise<{ dispose: () => void, needLoad: boolean }>(async resolve => {
|
const { needLoad } = await new Promise<{ needLoad: boolean }>(async resolve => {
|
||||||
const { dispose: _dispose } = os.popup(
|
const { dispose } = os.popup(
|
||||||
defineAsyncComponent(() => import('./notification-recipient.editor.vue')),
|
defineAsyncComponent(() => import('./notification-recipient.editor.vue')),
|
||||||
{
|
{
|
||||||
mode,
|
mode,
|
||||||
id,
|
id,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
submitted: async () => {
|
submitted: () => {
|
||||||
resolve({ dispose: _dispose, needLoad: true });
|
resolve({ needLoad: true });
|
||||||
|
},
|
||||||
|
canceled: () => {
|
||||||
|
resolve({ needLoad: false });
|
||||||
},
|
},
|
||||||
closed: () => {
|
closed: () => {
|
||||||
resolve({ dispose: _dispose, needLoad: false });
|
dispose();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
dispose();
|
|
||||||
|
|
||||||
if (needLoad) {
|
if (needLoad) {
|
||||||
await fetchRecipients();
|
await fetchRecipients();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkInput v-if="!noExpirationDate" v-model="expiresAt" type="datetime-local">
|
<MkInput v-if="!noExpirationDate" v-model="expiresAt" type="datetime-local">
|
||||||
<template #label>{{ i18n.ts.expirationDate }}</template>
|
<template #label>{{ i18n.ts.expirationDate }}</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
<MkInput v-model="createCount" type="number">
|
<MkInput v-model="createCount" type="number" min="1">
|
||||||
<template #label>{{ i18n.ts.createCount }}</template>
|
<template #label>{{ i18n.ts.createCount }}</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
<MkButton primary rounded @click="createWithOptions">{{ i18n.ts.create }}</MkButton>
|
<MkButton primary rounded @click="createWithOptions">{{ i18n.ts.create }}</MkButton>
|
||||||
|
|
|
@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkSwitch v-model="statusbar.props.shuffle">
|
<MkSwitch v-model="statusbar.props.shuffle">
|
||||||
<template #label>{{ i18n.ts.shuffle }}</template>
|
<template #label>{{ i18n.ts.shuffle }}</template>
|
||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
<MkInput v-model="statusbar.props.refreshIntervalSec" manualSave type="number">
|
<MkInput v-model="statusbar.props.refreshIntervalSec" manualSave type="number" min="1">
|
||||||
<template #label>{{ i18n.ts.refreshInterval }}</template>
|
<template #label>{{ i18n.ts.refreshInterval }}</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
<MkRange v-model="statusbar.props.marqueeDuration" :min="5" :max="150" :step="1">
|
<MkRange v-model="statusbar.props.marqueeDuration" :min="5" :max="150" :step="1">
|
||||||
|
@ -48,7 +48,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="statusbar.type === 'federation'">
|
<template v-else-if="statusbar.type === 'federation'">
|
||||||
<MkInput v-model="statusbar.props.refreshIntervalSec" manualSave type="number">
|
<MkInput v-model="statusbar.props.refreshIntervalSec" manualSave type="number" min="1">
|
||||||
<template #label>{{ i18n.ts.refreshInterval }}</template>
|
<template #label>{{ i18n.ts.refreshInterval }}</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
<MkRange v-model="statusbar.props.marqueeDuration" :min="5" :max="150" :step="1">
|
<MkRange v-model="statusbar.props.marqueeDuration" :min="5" :max="150" :step="1">
|
||||||
|
|
|
@ -124,10 +124,23 @@ export async function loadAudio(url: string, options?: { useCache?: boolean; })
|
||||||
*/
|
*/
|
||||||
export function playMisskeySfx(operationType: OperationType) {
|
export function playMisskeySfx(operationType: OperationType) {
|
||||||
const sound = defaultStore.state[`sound_${operationType}`];
|
const sound = defaultStore.state[`sound_${operationType}`];
|
||||||
if (sound.type == null || !canPlay || ('userActivation' in navigator && !navigator.userActivation.hasBeenActive)) return;
|
playMisskeySfxFile(sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* サウンド設定形式で指定された音声を再生する
|
||||||
|
* @param soundStore サウンド設定
|
||||||
|
*/
|
||||||
|
export function playMisskeySfxFile(soundStore: SoundStore) {
|
||||||
|
// 連続して再生しない
|
||||||
|
if (!canPlay) return;
|
||||||
|
// ユーザーアクティベーションが必要な場合はそれがない場合は再生しない
|
||||||
|
if ('userActivation' in navigator && !navigator.userActivation.hasBeenActive) return;
|
||||||
|
// サウンドがない場合は再生しない
|
||||||
|
if (soundStore.type === null || soundStore.type === '_driveFile_' && !soundStore.fileUrl) return;
|
||||||
|
|
||||||
canPlay = false;
|
canPlay = false;
|
||||||
playMisskeySfxFile(sound).finally(() => {
|
playMisskeySfxFileInternal(soundStore).finally(() => {
|
||||||
// ごく短時間に音が重複しないように
|
// ごく短時間に音が重複しないように
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
canPlay = true;
|
canPlay = true;
|
||||||
|
@ -135,11 +148,7 @@ export function playMisskeySfx(operationType: OperationType) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async function playMisskeySfxFileInternal(soundStore: SoundStore) {
|
||||||
* サウンド設定形式で指定された音声を再生する
|
|
||||||
* @param soundStore サウンド設定
|
|
||||||
*/
|
|
||||||
export async function playMisskeySfxFile(soundStore: SoundStore) {
|
|
||||||
if (soundStore.type === null || (soundStore.type === '_driveFile_' && !soundStore.fileUrl)) {
|
if (soundStore.type === null || (soundStore.type === '_driveFile_' && !soundStore.fileUrl)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ const devConfig: UserConfig = {
|
||||||
'/bios': httpUrl,
|
'/bios': httpUrl,
|
||||||
'/cli': httpUrl,
|
'/cli': httpUrl,
|
||||||
'/inbox': httpUrl,
|
'/inbox': httpUrl,
|
||||||
|
'/emoji/': httpUrl,
|
||||||
'/notes': {
|
'/notes': {
|
||||||
target: httpUrl,
|
target: httpUrl,
|
||||||
bypass: varyHandler,
|
bypass: varyHandler,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import tsParser from '@typescript-eslint/parser';
|
import tsParser from '@typescript-eslint/parser';
|
||||||
import sharedConfig from '../shared/eslint.config.js';
|
import sharedConfig from '../shared/eslint.config.js';
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-default-export
|
||||||
export default [
|
export default [
|
||||||
...sharedConfig,
|
...sharedConfig,
|
||||||
{
|
{
|
||||||
|
|
|
@ -551,7 +551,7 @@ type Channel = components['schemas']['Channel'];
|
||||||
// Warning: (ae-forgotten-export) The symbol "AnyOf" needs to be exported by the entry point index.d.ts
|
// Warning: (ae-forgotten-export) The symbol "AnyOf" needs to be exported by the entry point index.d.ts
|
||||||
//
|
//
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export abstract class ChannelConnection<Channel extends AnyOf<Channels> = any> extends EventEmitter<Channel['events']> {
|
export abstract class ChannelConnection<Channel extends AnyOf<Channels> = AnyOf<Channels>> extends EventEmitter<Channel['events']> {
|
||||||
constructor(stream: Stream, channel: string, name?: string);
|
constructor(stream: Stream, channel: string, name?: string);
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
channel: string;
|
channel: string;
|
||||||
|
@ -771,12 +771,12 @@ export type Channels = {
|
||||||
user1: boolean;
|
user1: boolean;
|
||||||
user2: boolean;
|
user2: boolean;
|
||||||
}) => void;
|
}) => void;
|
||||||
updateSettings: (payload: {
|
updateSettings: <K extends ReversiUpdateKey>(payload: {
|
||||||
userId: User['id'];
|
userId: User['id'];
|
||||||
key: string;
|
key: K;
|
||||||
value: any;
|
value: ReversiGameDetailed[K];
|
||||||
}) => void;
|
}) => void;
|
||||||
log: (payload: Record<string, any>) => void;
|
log: (payload: Record<string, unknown>) => void;
|
||||||
};
|
};
|
||||||
receives: {
|
receives: {
|
||||||
putStone: {
|
putStone: {
|
||||||
|
@ -785,10 +785,7 @@ export type Channels = {
|
||||||
};
|
};
|
||||||
ready: boolean;
|
ready: boolean;
|
||||||
cancel: null | Record<string, never>;
|
cancel: null | Record<string, never>;
|
||||||
updateSettings: {
|
updateSettings: ReversiUpdateSettings<ReversiUpdateKey>;
|
||||||
key: string;
|
|
||||||
value: any;
|
|
||||||
};
|
|
||||||
claimTimeIsUp: null | Record<string, never>;
|
claimTimeIsUp: null | Record<string, never>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -2730,7 +2727,7 @@ type PagesUnlikeRequest = operations['pages___unlike']['requestBody']['content']
|
||||||
type PagesUpdateRequest = operations['pages___update']['requestBody']['content']['application/json'];
|
type PagesUpdateRequest = operations['pages___update']['requestBody']['content']['application/json'];
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
function parse(acct: string): Acct;
|
function parse(_acct: string): Acct;
|
||||||
|
|
||||||
// Warning: (ae-forgotten-export) The symbol "Values" needs to be exported by the entry point index.d.ts
|
// Warning: (ae-forgotten-export) The symbol "Values" needs to be exported by the entry point index.d.ts
|
||||||
//
|
//
|
||||||
|
@ -2969,7 +2966,7 @@ export class Stream extends EventEmitter<StreamEvents> {
|
||||||
constructor(origin: string, user: {
|
constructor(origin: string, user: {
|
||||||
token: string;
|
token: string;
|
||||||
} | null, options?: {
|
} | null, options?: {
|
||||||
WebSocket?: any;
|
WebSocket?: WebSocket;
|
||||||
});
|
});
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
close(): void;
|
close(): void;
|
||||||
|
@ -2992,9 +2989,9 @@ export class Stream extends EventEmitter<StreamEvents> {
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
send(typeOrPayload: string): void;
|
send(typeOrPayload: string): void;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
send(typeOrPayload: string, payload: any): void;
|
send(typeOrPayload: string, payload: unknown): void;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
send(typeOrPayload: Record<string, any> | any[]): void;
|
send(typeOrPayload: Record<string, unknown> | unknown[]): void;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
state: 'initializing' | 'reconnecting' | 'connected';
|
state: 'initializing' | 'reconnecting' | 'connected';
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
|
@ -3229,7 +3226,9 @@ type UsersUpdateMemoRequest = operations['users___update-memo']['requestBody']['
|
||||||
|
|
||||||
// Warnings were encountered during analysis:
|
// Warnings were encountered during analysis:
|
||||||
//
|
//
|
||||||
// src/entities.ts:34:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts
|
// src/entities.ts:35:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts
|
||||||
|
// src/streaming.types.ts:220:4 - (ae-forgotten-export) The symbol "ReversiUpdateKey" needs to be exported by the entry point index.d.ts
|
||||||
|
// src/streaming.types.ts:230:4 - (ae-forgotten-export) The symbol "ReversiUpdateSettings" needs to be exported by the entry point index.d.ts
|
||||||
|
|
||||||
// (No @packageDocumentation comment for this package)
|
// (No @packageDocumentation comment for this package)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"name": "misskey-js",
|
"name": "misskey-js",
|
||||||
"version": "2024.7.0-beta.1",
|
"version": "2024.7.0-rc.4",
|
||||||
"description": "Misskey SDK for JavaScript",
|
"description": "Misskey SDK for JavaScript",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "./built/index.js",
|
"main": "./built/index.js",
|
||||||
|
@ -35,23 +35,23 @@
|
||||||
"directory": "packages/misskey-js"
|
"directory": "packages/misskey-js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@microsoft/api-extractor": "7.47.0",
|
"@microsoft/api-extractor": "7.47.4",
|
||||||
"@swc/jest": "0.2.36",
|
"@swc/jest": "0.2.36",
|
||||||
"@types/jest": "29.5.12",
|
"@types/jest": "29.5.12",
|
||||||
"@types/node": "20.14.9",
|
"@types/node": "20.14.12",
|
||||||
"@typescript-eslint/eslint-plugin": "7.15.0",
|
"@typescript-eslint/eslint-plugin": "7.17.0",
|
||||||
"@typescript-eslint/parser": "7.15.0",
|
"@typescript-eslint/parser": "7.17.0",
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"jest-fetch-mock": "3.0.3",
|
"jest-fetch-mock": "3.0.3",
|
||||||
"jest-websocket-mock": "2.5.0",
|
"jest-websocket-mock": "2.5.0",
|
||||||
"mock-socket": "9.3.1",
|
"mock-socket": "9.3.1",
|
||||||
"ncp": "2.0.0",
|
"ncp": "2.0.0",
|
||||||
"nodemon": "3.1.4",
|
"nodemon": "3.1.4",
|
||||||
"execa": "9.2.0",
|
"execa": "9.3.0",
|
||||||
"tsd": "0.31.1",
|
"tsd": "0.31.1",
|
||||||
"typescript": "5.5.3",
|
"typescript": "5.5.4",
|
||||||
"esbuild": "0.22.0",
|
"esbuild": "0.23.0",
|
||||||
"glob": "10.4.2"
|
"glob": "11.0.0"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"built"
|
"built"
|
||||||
|
|
|
@ -3,7 +3,8 @@ export type Acct = {
|
||||||
host: string | null;
|
host: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function parse(acct: string): Acct {
|
export function parse(_acct: string): Acct {
|
||||||
|
let acct = _acct;
|
||||||
if (acct.startsWith('@')) acct = acct.substring(1);
|
if (acct.startsWith('@')) acct = acct.substring(1);
|
||||||
const split = acct.split('@', 2);
|
const split = acct.split('@', 2);
|
||||||
return { username: split[0], host: split[1] || null };
|
return { username: split[0], host: split[1] || null };
|
||||||
|
|
|
@ -14,6 +14,7 @@ export type APIError = {
|
||||||
code: string;
|
code: string;
|
||||||
message: string;
|
message: string;
|
||||||
kind: 'client' | 'server';
|
kind: 'client' | 'server';
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
info: Record<string, any>;
|
info: Record<string, any>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,6 +30,7 @@ export type FetchLike = (input: string, init?: {
|
||||||
headers: { [key in string]: string }
|
headers: { [key in string]: string }
|
||||||
}) => Promise<{
|
}) => Promise<{
|
||||||
status: number;
|
status: number;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
json(): Promise<any>;
|
json(): Promise<any>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
@ -49,6 +51,7 @@ export class APIClient {
|
||||||
this.fetch = opts.fetch ?? ((...args) => fetch(...args));
|
this.fetch = opts.fetch ?? ((...args) => fetch(...args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
private assertIsRecord<T>(obj: T): obj is T & Record<string, any> {
|
private assertIsRecord<T>(obj: T): obj is T & Record<string, any> {
|
||||||
return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
|
return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,13 @@ type StrictExtract<Union, Cond> = Cond extends Union ? Union : never;
|
||||||
|
|
||||||
type IsCaseMatched<E extends keyof Endpoints, P extends Endpoints[E]['req'], C extends number> =
|
type IsCaseMatched<E extends keyof Endpoints, P extends Endpoints[E]['req'], C extends number> =
|
||||||
Endpoints[E]['res'] extends SwitchCase
|
Endpoints[E]['res'] extends SwitchCase
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
? IsNeverType<StrictExtract<Endpoints[E]['res']['$switch']['$cases'][C], [P, any]>> extends false ? true : false
|
? IsNeverType<StrictExtract<Endpoints[E]['res']['$switch']['$cases'][C], [P, any]>> extends false ? true : false
|
||||||
: false
|
: false
|
||||||
|
|
||||||
type GetCaseResult<E extends keyof Endpoints, P extends Endpoints[E]['req'], C extends number> =
|
type GetCaseResult<E extends keyof Endpoints, P extends Endpoints[E]['req'], C extends number> =
|
||||||
Endpoints[E]['res'] extends SwitchCase
|
Endpoints[E]['res'] extends SwitchCase
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
? StrictExtract<Endpoints[E]['res']['$switch']['$cases'][C], [P, any]>[1]
|
? StrictExtract<Endpoints[E]['res']['$switch']['$cases'][C], [P, any]>[1]
|
||||||
: never
|
: never
|
||||||
|
|
||||||
|
|
|
@ -4089,7 +4089,8 @@ export type components = {
|
||||||
userId: string | null;
|
userId: string | null;
|
||||||
}) | null;
|
}) | null;
|
||||||
localOnly?: boolean;
|
localOnly?: boolean;
|
||||||
reactionAcceptance: string | null;
|
/** @enum {string|null} */
|
||||||
|
reactionAcceptance: 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote' | null;
|
||||||
reactionEmojis: {
|
reactionEmojis: {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
};
|
};
|
||||||
|
@ -4969,7 +4970,7 @@ export type components = {
|
||||||
latestSentAt: string | null;
|
latestSentAt: string | null;
|
||||||
latestStatus: number | null;
|
latestStatus: number | null;
|
||||||
name: string;
|
name: string;
|
||||||
on: ('abuseReport' | 'abuseReportResolved')[];
|
on: ('abuseReport' | 'abuseReportResolved' | 'userCreated')[];
|
||||||
url: string;
|
url: string;
|
||||||
secret: string;
|
secret: string;
|
||||||
};
|
};
|
||||||
|
@ -10041,7 +10042,7 @@ export type operations = {
|
||||||
'application/json': {
|
'application/json': {
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
on: ('abuseReport' | 'abuseReportResolved')[];
|
on: ('abuseReport' | 'abuseReportResolved' | 'userCreated')[];
|
||||||
url: string;
|
url: string;
|
||||||
secret: string;
|
secret: string;
|
||||||
};
|
};
|
||||||
|
@ -10151,7 +10152,7 @@ export type operations = {
|
||||||
content: {
|
content: {
|
||||||
'application/json': {
|
'application/json': {
|
||||||
isActive?: boolean;
|
isActive?: boolean;
|
||||||
on?: ('abuseReport' | 'abuseReportResolved')[];
|
on?: ('abuseReport' | 'abuseReportResolved' | 'userCreated')[];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -10264,7 +10265,7 @@ export type operations = {
|
||||||
id: string;
|
id: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
on: ('abuseReport' | 'abuseReportResolved')[];
|
on: ('abuseReport' | 'abuseReportResolved' | 'userCreated')[];
|
||||||
url: string;
|
url: string;
|
||||||
secret: string;
|
secret: string;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
import type { operations } from './autogen/types.js';
|
||||||
|
import type {
|
||||||
|
AbuseReportNotificationRecipient, Ad,
|
||||||
|
Announcement,
|
||||||
|
EmojiDetailed, InviteCode,
|
||||||
|
MetaDetailed,
|
||||||
|
Note,
|
||||||
|
Role, SystemWebhook, UserLite,
|
||||||
|
} from './autogen/models.js';
|
||||||
|
|
||||||
export const notificationTypes = ['note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app', 'roleAssigned', 'achievementEarned'] as const;
|
export const notificationTypes = ['note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app', 'roleAssigned', 'achievementEarned'] as const;
|
||||||
|
|
||||||
export const noteVisibilities = ['public', 'home', 'followers', 'specified'] as const;
|
export const noteVisibilities = ['public', 'home', 'followers', 'specified'] as const;
|
||||||
|
@ -135,10 +145,30 @@ export const moderationLogTypes = [
|
||||||
'unsetUserBanner',
|
'unsetUserBanner',
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
// See: packages/backend/src/core/ReversiService.ts@L410
|
||||||
|
export const reversiUpdateKeys = [
|
||||||
|
'map',
|
||||||
|
'bw',
|
||||||
|
'isLlotheo',
|
||||||
|
'canPutEverywhere',
|
||||||
|
'loopedBoard',
|
||||||
|
'timeLimitForEachTurn',
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export type ReversiUpdateKey = typeof reversiUpdateKeys[number];
|
||||||
|
|
||||||
|
type AvatarDecoration = UserLite['avatarDecorations'][number];
|
||||||
|
|
||||||
|
type ReceivedAbuseReport = {
|
||||||
|
reportId: AbuseReportNotificationRecipient['id'];
|
||||||
|
report: operations['admin___abuse-user-reports']['responses'][200]['content']['application/json'];
|
||||||
|
forwarded: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type ModerationLogPayloads = {
|
export type ModerationLogPayloads = {
|
||||||
updateServerSettings: {
|
updateServerSettings: {
|
||||||
before: any | null;
|
before: MetaDetailed | null;
|
||||||
after: any | null;
|
after: MetaDetailed | null;
|
||||||
};
|
};
|
||||||
suspend: {
|
suspend: {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
@ -159,16 +189,16 @@ export type ModerationLogPayloads = {
|
||||||
};
|
};
|
||||||
addCustomEmoji: {
|
addCustomEmoji: {
|
||||||
emojiId: string;
|
emojiId: string;
|
||||||
emoji: any;
|
emoji: EmojiDetailed;
|
||||||
};
|
};
|
||||||
updateCustomEmoji: {
|
updateCustomEmoji: {
|
||||||
emojiId: string;
|
emojiId: string;
|
||||||
before: any;
|
before: EmojiDetailed;
|
||||||
after: any;
|
after: EmojiDetailed;
|
||||||
};
|
};
|
||||||
deleteCustomEmoji: {
|
deleteCustomEmoji: {
|
||||||
emojiId: string;
|
emojiId: string;
|
||||||
emoji: any;
|
emoji: EmojiDetailed;
|
||||||
};
|
};
|
||||||
assignRole: {
|
assignRole: {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
@ -187,16 +217,16 @@ export type ModerationLogPayloads = {
|
||||||
};
|
};
|
||||||
createRole: {
|
createRole: {
|
||||||
roleId: string;
|
roleId: string;
|
||||||
role: any;
|
role: Role;
|
||||||
};
|
};
|
||||||
updateRole: {
|
updateRole: {
|
||||||
roleId: string;
|
roleId: string;
|
||||||
before: any;
|
before: Role;
|
||||||
after: any;
|
after: Role;
|
||||||
};
|
};
|
||||||
deleteRole: {
|
deleteRole: {
|
||||||
roleId: string;
|
roleId: string;
|
||||||
role: any;
|
role: Role;
|
||||||
};
|
};
|
||||||
clearQueue: Record<string, never>;
|
clearQueue: Record<string, never>;
|
||||||
promoteQueue: Record<string, never>;
|
promoteQueue: Record<string, never>;
|
||||||
|
@ -211,39 +241,39 @@ export type ModerationLogPayloads = {
|
||||||
noteUserId: string;
|
noteUserId: string;
|
||||||
noteUserUsername: string;
|
noteUserUsername: string;
|
||||||
noteUserHost: string | null;
|
noteUserHost: string | null;
|
||||||
note: any;
|
note: Note;
|
||||||
};
|
};
|
||||||
createGlobalAnnouncement: {
|
createGlobalAnnouncement: {
|
||||||
announcementId: string;
|
announcementId: string;
|
||||||
announcement: any;
|
announcement: Announcement;
|
||||||
};
|
};
|
||||||
createUserAnnouncement: {
|
createUserAnnouncement: {
|
||||||
announcementId: string;
|
announcementId: string;
|
||||||
announcement: any;
|
announcement: Announcement;
|
||||||
userId: string;
|
userId: string;
|
||||||
userUsername: string;
|
userUsername: string;
|
||||||
userHost: string | null;
|
userHost: string | null;
|
||||||
};
|
};
|
||||||
updateGlobalAnnouncement: {
|
updateGlobalAnnouncement: {
|
||||||
announcementId: string;
|
announcementId: string;
|
||||||
before: any;
|
before: Announcement;
|
||||||
after: any;
|
after: Announcement;
|
||||||
};
|
};
|
||||||
updateUserAnnouncement: {
|
updateUserAnnouncement: {
|
||||||
announcementId: string;
|
announcementId: string;
|
||||||
before: any;
|
before: Announcement;
|
||||||
after: any;
|
after: Announcement;
|
||||||
userId: string;
|
userId: string;
|
||||||
userUsername: string;
|
userUsername: string;
|
||||||
userHost: string | null;
|
userHost: string | null;
|
||||||
};
|
};
|
||||||
deleteGlobalAnnouncement: {
|
deleteGlobalAnnouncement: {
|
||||||
announcementId: string;
|
announcementId: string;
|
||||||
announcement: any;
|
announcement: Announcement;
|
||||||
};
|
};
|
||||||
deleteUserAnnouncement: {
|
deleteUserAnnouncement: {
|
||||||
announcementId: string;
|
announcementId: string;
|
||||||
announcement: any;
|
announcement: Announcement;
|
||||||
userId: string;
|
userId: string;
|
||||||
userUsername: string;
|
userUsername: string;
|
||||||
userHost: string | null;
|
userHost: string | null;
|
||||||
|
@ -281,37 +311,37 @@ export type ModerationLogPayloads = {
|
||||||
};
|
};
|
||||||
resolveAbuseReport: {
|
resolveAbuseReport: {
|
||||||
reportId: string;
|
reportId: string;
|
||||||
report: any;
|
report: ReceivedAbuseReport;
|
||||||
forwarded: boolean;
|
forwarded: boolean;
|
||||||
};
|
};
|
||||||
createInvitation: {
|
createInvitation: {
|
||||||
invitations: any[];
|
invitations: InviteCode[];
|
||||||
};
|
};
|
||||||
createAd: {
|
createAd: {
|
||||||
adId: string;
|
adId: string;
|
||||||
ad: any;
|
ad: Ad;
|
||||||
};
|
};
|
||||||
updateAd: {
|
updateAd: {
|
||||||
adId: string;
|
adId: string;
|
||||||
before: any;
|
before: Ad;
|
||||||
after: any;
|
after: Ad;
|
||||||
};
|
};
|
||||||
deleteAd: {
|
deleteAd: {
|
||||||
adId: string;
|
adId: string;
|
||||||
ad: any;
|
ad: Ad;
|
||||||
};
|
};
|
||||||
createAvatarDecoration: {
|
createAvatarDecoration: {
|
||||||
avatarDecorationId: string;
|
avatarDecorationId: string;
|
||||||
avatarDecoration: any;
|
avatarDecoration: AvatarDecoration;
|
||||||
};
|
};
|
||||||
updateAvatarDecoration: {
|
updateAvatarDecoration: {
|
||||||
avatarDecorationId: string;
|
avatarDecorationId: string;
|
||||||
before: any;
|
before: AvatarDecoration;
|
||||||
after: any;
|
after: AvatarDecoration;
|
||||||
};
|
};
|
||||||
deleteAvatarDecoration: {
|
deleteAvatarDecoration: {
|
||||||
avatarDecorationId: string;
|
avatarDecorationId: string;
|
||||||
avatarDecoration: any;
|
avatarDecoration: AvatarDecoration;
|
||||||
};
|
};
|
||||||
unsetUserAvatar: {
|
unsetUserAvatar: {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
@ -327,28 +357,28 @@ export type ModerationLogPayloads = {
|
||||||
};
|
};
|
||||||
createSystemWebhook: {
|
createSystemWebhook: {
|
||||||
systemWebhookId: string;
|
systemWebhookId: string;
|
||||||
webhook: any;
|
webhook: SystemWebhook;
|
||||||
};
|
};
|
||||||
updateSystemWebhook: {
|
updateSystemWebhook: {
|
||||||
systemWebhookId: string;
|
systemWebhookId: string;
|
||||||
before: any;
|
before: SystemWebhook;
|
||||||
after: any;
|
after: SystemWebhook;
|
||||||
};
|
};
|
||||||
deleteSystemWebhook: {
|
deleteSystemWebhook: {
|
||||||
systemWebhookId: string;
|
systemWebhookId: string;
|
||||||
webhook: any;
|
webhook: SystemWebhook;
|
||||||
};
|
};
|
||||||
createAbuseReportNotificationRecipient: {
|
createAbuseReportNotificationRecipient: {
|
||||||
recipientId: string;
|
recipientId: string;
|
||||||
recipient: any;
|
recipient: AbuseReportNotificationRecipient;
|
||||||
};
|
};
|
||||||
updateAbuseReportNotificationRecipient: {
|
updateAbuseReportNotificationRecipient: {
|
||||||
recipientId: string;
|
recipientId: string;
|
||||||
before: any;
|
before: AbuseReportNotificationRecipient;
|
||||||
after: any;
|
after: AbuseReportNotificationRecipient;
|
||||||
};
|
};
|
||||||
deleteAbuseReportNotificationRecipient: {
|
deleteAbuseReportNotificationRecipient: {
|
||||||
recipientId: string;
|
recipientId: string;
|
||||||
recipient: any;
|
recipient: AbuseReportNotificationRecipient;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
Role,
|
Role,
|
||||||
RolePolicies,
|
RolePolicies,
|
||||||
User,
|
User,
|
||||||
UserDetailedNotMe
|
UserDetailedNotMe,
|
||||||
} from './autogen/models.js';
|
} from './autogen/models.js';
|
||||||
|
|
||||||
export * from './autogen/entities.js';
|
export * from './autogen/entities.js';
|
||||||
|
@ -19,6 +19,7 @@ export type DateString = string;
|
||||||
export type PageEvent = {
|
export type PageEvent = {
|
||||||
pageId: Page['id'];
|
pageId: Page['id'];
|
||||||
event: string;
|
event: string;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
var: any;
|
var: any;
|
||||||
userId: User['id'];
|
userId: User['id'];
|
||||||
user: User;
|
user: User;
|
||||||
|
|
|
@ -15,7 +15,7 @@ export function urlQuery(obj: Record<string, string | number | boolean | undefin
|
||||||
.join('&');
|
.join('&');
|
||||||
}
|
}
|
||||||
|
|
||||||
type AnyOf<T extends Record<any, any>> = T[keyof T];
|
type AnyOf<T extends Record<PropertyKey, unknown>> = T[keyof T];
|
||||||
|
|
||||||
type StreamEvents = {
|
type StreamEvents = {
|
||||||
_connected_: void;
|
_connected_: void;
|
||||||
|
@ -25,6 +25,7 @@ type StreamEvents = {
|
||||||
/**
|
/**
|
||||||
* Misskey stream connection
|
* Misskey stream connection
|
||||||
*/
|
*/
|
||||||
|
// eslint-disable-next-line import/no-default-export
|
||||||
export default class Stream extends EventEmitter<StreamEvents> {
|
export default class Stream extends EventEmitter<StreamEvents> {
|
||||||
private stream: _ReconnectingWebsocket.default;
|
private stream: _ReconnectingWebsocket.default;
|
||||||
public state: 'initializing' | 'reconnecting' | 'connected' = 'initializing';
|
public state: 'initializing' | 'reconnecting' | 'connected' = 'initializing';
|
||||||
|
@ -34,7 +35,7 @@ export default class Stream extends EventEmitter<StreamEvents> {
|
||||||
private idCounter = 0;
|
private idCounter = 0;
|
||||||
|
|
||||||
constructor(origin: string, user: { token: string; } | null, options?: {
|
constructor(origin: string, user: { token: string; } | null, options?: {
|
||||||
WebSocket?: any;
|
WebSocket?: WebSocket;
|
||||||
}) {
|
}) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
@ -51,6 +52,7 @@ export default class Stream extends EventEmitter<StreamEvents> {
|
||||||
this.send = this.send.bind(this);
|
this.send = this.send.bind(this);
|
||||||
this.close = this.close.bind(this);
|
this.close = this.close.bind(this);
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
options = options ?? { };
|
options = options ?? { };
|
||||||
|
|
||||||
const query = urlQuery({
|
const query = urlQuery({
|
||||||
|
@ -91,8 +93,8 @@ export default class Stream extends EventEmitter<StreamEvents> {
|
||||||
this.sharedConnectionPools.push(pool);
|
this.sharedConnectionPools.push(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
const connection = new SharedConnection(this, channel, pool, name);
|
const connection = new SharedConnection<Channels[C]>(this, channel, pool, name);
|
||||||
this.sharedConnections.push(connection);
|
this.sharedConnections.push(connection as unknown as SharedConnection);
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +108,7 @@ export default class Stream extends EventEmitter<StreamEvents> {
|
||||||
|
|
||||||
private connectToChannel<C extends keyof Channels>(channel: C, params: Channels[C]['params']): NonSharedConnection<Channels[C]> {
|
private connectToChannel<C extends keyof Channels>(channel: C, params: Channels[C]['params']): NonSharedConnection<Channels[C]> {
|
||||||
const connection = new NonSharedConnection(this, channel, this.genId(), params);
|
const connection = new NonSharedConnection(this, channel, this.genId(), params);
|
||||||
this.nonSharedConnections.push(connection);
|
this.nonSharedConnections.push(connection as unknown as NonSharedConnection);
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,9 +176,9 @@ export default class Stream extends EventEmitter<StreamEvents> {
|
||||||
* ! ストリーム上のやり取りはすべてJSONで行われます !
|
* ! ストリーム上のやり取りはすべてJSONで行われます !
|
||||||
*/
|
*/
|
||||||
public send(typeOrPayload: string): void
|
public send(typeOrPayload: string): void
|
||||||
public send(typeOrPayload: string, payload: any): void
|
public send(typeOrPayload: string, payload: unknown): void
|
||||||
public send(typeOrPayload: Record<string, any> | any[]): void
|
public send(typeOrPayload: Record<string, unknown> | unknown[]): void
|
||||||
public send(typeOrPayload: string | Record<string, any> | any[], payload?: any): void {
|
public send(typeOrPayload: string | Record<string, unknown> | unknown[], payload?: unknown): void {
|
||||||
if (typeof typeOrPayload === 'string') {
|
if (typeof typeOrPayload === 'string') {
|
||||||
this.stream.send(JSON.stringify({
|
this.stream.send(JSON.stringify({
|
||||||
type: typeOrPayload,
|
type: typeOrPayload,
|
||||||
|
@ -211,7 +213,7 @@ class Pool {
|
||||||
public id: string;
|
public id: string;
|
||||||
protected stream: Stream;
|
protected stream: Stream;
|
||||||
public users = 0;
|
public users = 0;
|
||||||
private disposeTimerId: any;
|
private disposeTimerId: ReturnType<typeof setTimeout> | null = null;
|
||||||
private isConnected = false;
|
private isConnected = false;
|
||||||
|
|
||||||
constructor(stream: Stream, channel: string, id: string) {
|
constructor(stream: Stream, channel: string, id: string) {
|
||||||
|
@ -275,7 +277,7 @@ class Pool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class Connection<Channel extends AnyOf<Channels> = any> extends EventEmitter<Channel['events']> {
|
export abstract class Connection<Channel extends AnyOf<Channels> = AnyOf<Channels>> extends EventEmitter<Channel['events']> {
|
||||||
public channel: string;
|
public channel: string;
|
||||||
protected stream: Stream;
|
protected stream: Stream;
|
||||||
public abstract id: string;
|
public abstract id: string;
|
||||||
|
@ -309,7 +311,7 @@ export abstract class Connection<Channel extends AnyOf<Channels> = any> extends
|
||||||
public abstract dispose(): void;
|
public abstract dispose(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SharedConnection<Channel extends AnyOf<Channels> = any> extends Connection<Channel> {
|
class SharedConnection<Channel extends AnyOf<Channels> = AnyOf<Channels>> extends Connection<Channel> {
|
||||||
private pool: Pool;
|
private pool: Pool;
|
||||||
|
|
||||||
public get id(): string {
|
public get id(): string {
|
||||||
|
@ -328,11 +330,11 @@ class SharedConnection<Channel extends AnyOf<Channels> = any> extends Connection
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
this.pool.dec();
|
this.pool.dec();
|
||||||
this.removeAllListeners();
|
this.removeAllListeners();
|
||||||
this.stream.removeSharedConnection(this);
|
this.stream.removeSharedConnection(this as unknown as SharedConnection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NonSharedConnection<Channel extends AnyOf<Channels> = any> extends Connection<Channel> {
|
class NonSharedConnection<Channel extends AnyOf<Channels> = AnyOf<Channels>> extends Connection<Channel> {
|
||||||
public id: string;
|
public id: string;
|
||||||
protected params: Channel['params'];
|
protected params: Channel['params'];
|
||||||
|
|
||||||
|
@ -359,6 +361,6 @@ class NonSharedConnection<Channel extends AnyOf<Channels> = any> extends Connect
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
this.removeAllListeners();
|
this.removeAllListeners();
|
||||||
this.stream.send('disconnect', { id: this.id });
|
this.stream.send('disconnect', { id: this.id });
|
||||||
this.stream.disconnectToChannel(this);
|
this.stream.disconnectToChannel(this as unknown as NonSharedConnection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,14 @@ import {
|
||||||
ServerStatsLog,
|
ServerStatsLog,
|
||||||
ReversiGameDetailed,
|
ReversiGameDetailed,
|
||||||
} from './entities.js';
|
} from './entities.js';
|
||||||
|
import {
|
||||||
|
ReversiUpdateKey,
|
||||||
|
} from './consts.js';
|
||||||
|
|
||||||
|
type ReversiUpdateSettings<K extends ReversiUpdateKey> = {
|
||||||
|
key: K;
|
||||||
|
value: ReversiGameDetailed[K];
|
||||||
|
};
|
||||||
|
|
||||||
export type Channels = {
|
export type Channels = {
|
||||||
main: {
|
main: {
|
||||||
|
@ -51,6 +59,7 @@ export type Channels = {
|
||||||
registryUpdated: (payload: {
|
registryUpdated: (payload: {
|
||||||
scope?: string[];
|
scope?: string[];
|
||||||
key: string;
|
key: string;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
value: any | null;
|
value: any | null;
|
||||||
}) => void;
|
}) => void;
|
||||||
driveFileCreated: (payload: DriveFile) => void;
|
driveFileCreated: (payload: DriveFile) => void;
|
||||||
|
@ -208,8 +217,8 @@ export type Channels = {
|
||||||
ended: (payload: { winnerId: User['id'] | null; game: ReversiGameDetailed; }) => void;
|
ended: (payload: { winnerId: User['id'] | null; game: ReversiGameDetailed; }) => void;
|
||||||
canceled: (payload: { userId: User['id']; }) => void;
|
canceled: (payload: { userId: User['id']; }) => void;
|
||||||
changeReadyStates: (payload: { user1: boolean; user2: boolean; }) => void;
|
changeReadyStates: (payload: { user1: boolean; user2: boolean; }) => void;
|
||||||
updateSettings: (payload: { userId: User['id']; key: string; value: any; }) => void;
|
updateSettings: <K extends ReversiUpdateKey>(payload: { userId: User['id']; key: K; value: ReversiGameDetailed[K]; }) => void;
|
||||||
log: (payload: Record<string, any>) => void;
|
log: (payload: Record<string, unknown>) => void;
|
||||||
};
|
};
|
||||||
receives: {
|
receives: {
|
||||||
putStone: {
|
putStone: {
|
||||||
|
@ -218,10 +227,7 @@ export type Channels = {
|
||||||
};
|
};
|
||||||
ready: boolean;
|
ready: boolean;
|
||||||
cancel: null | Record<string, never>;
|
cancel: null | Record<string, never>;
|
||||||
updateSettings: {
|
updateSettings: ReversiUpdateSettings<ReversiUpdateKey>;
|
||||||
key: string;
|
|
||||||
value: any;
|
|
||||||
};
|
|
||||||
claimTimeIsUp: null | Record<string, never>;
|
claimTimeIsUp: null | Record<string, never>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,16 +9,16 @@
|
||||||
"lint": "pnpm typecheck && pnpm eslint"
|
"lint": "pnpm typecheck && pnpm eslint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "0.22.0",
|
"esbuild": "0.23.0",
|
||||||
"idb-keyval": "6.2.1",
|
"idb-keyval": "6.2.1",
|
||||||
"misskey-js": "workspace:*"
|
"misskey-js": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/parser": "7.15.0",
|
"@typescript-eslint/parser": "7.17.0",
|
||||||
"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.67",
|
"@typescript/lib-webworker": "npm:@types/serviceworker@0.0.67",
|
||||||
"eslint-plugin-import": "2.29.1",
|
"eslint-plugin-import": "2.29.1",
|
||||||
"nodemon": "3.1.4",
|
"nodemon": "3.1.4",
|
||||||
"typescript": "5.5.3"
|
"typescript": "5.5.4"
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module"
|
||||||
}
|
}
|
||||||
|
|
5436
pnpm-lock.yaml
5436
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue