Merge branch 'develop' of github.com:misskey-dev/misskey into feature/post-channel-everywhere

This commit is contained in:
mesi 2024-01-18 15:10:47 +09:00
commit 125acea00f
828 changed files with 23169 additions and 4778 deletions

View File

@ -2,3 +2,4 @@
POSTGRES_PASSWORD=example-misskey-pass POSTGRES_PASSWORD=example-misskey-pass
POSTGRES_USER=example-misskey-user POSTGRES_USER=example-misskey-user
POSTGRES_DB=misskey POSTGRES_DB=misskey
DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}"

View File

@ -89,3 +89,9 @@ body:
render: markdown render: markdown
validations: validations:
required: false required: false
- type: checkboxes
attributes:
label: Do you want to address this bug yourself?
options:
- label: Yes, I will patch the bug myself and send a pull request

View File

@ -15,3 +15,8 @@ body:
description: Describe the specific problem or need you think this feature will solve, and who it will help. description: Describe the specific problem or need you think this feature will solve, and who it will help.
validations: validations:
required: true required: true
- type: checkboxes
attributes:
label: Do you want to implement this feature yourself?
options:
- label: Yes, I will implement this by myself and send a pull request

View File

@ -17,16 +17,32 @@ updates:
directory: "/" directory: "/"
schedule: schedule:
interval: daily interval: daily
# PNPM has an issue with dependabot. See: open-pull-requests-limit: 10
# https://github.com/dependabot/dependabot-core/issues/7258 # List dependencies required to be updated together, sharing the same version numbers.
# https://github.com/pnpm/pnpm/issues/6530 # Those who simply have the common owner (e.g. @fastify) don't need to be listed.
# TODO: Restore this when the issue is solved
open-pull-requests-limit: 0
groups: groups:
swc: aws-sdk:
patterns: patterns:
- "@swc/*" - "@aws-sdk/*"
bull-board:
patterns:
- "@bull-board/*"
nestjs:
patterns:
- "@nestjs/*"
slacc:
patterns:
- "slacc-*"
storybook: storybook:
patterns: patterns:
- "storybook*" - "storybook*"
- "@storybook/*" - "@storybook/*"
swc-core:
patterns:
- "@swc/core*"
typescript-eslint:
patterns:
- "@typescript-eslint/*"
tensorflow:
patterns:
- "@tensorflow/*"

View File

@ -1,6 +1,12 @@
name: API report (misskey.js) name: API report (misskey.js)
on: [push, pull_request] on:
push:
paths:
- packages/misskey-js/**
pull_request:
paths:
- packages/misskey-js/**
jobs: jobs:
report: report:
@ -14,7 +20,7 @@ jobs:
- run: corepack enable - run: corepack enable
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4.0.0 uses: actions/setup-node@v4.0.1
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'

43
.github/workflows/changelog-check.yml vendored Normal file
View File

@ -0,0 +1,43 @@
name: Check the description in CHANGELOG.md
on:
pull_request:
branches:
- master
- develop
jobs:
check-changelog:
runs-on: ubuntu-latest
steps:
- name: Checkout head
uses: actions/checkout@v4.1.1
- name: Setup Node.js
uses: actions/setup-node@v4.0.1
with:
node-version-file: '.node-version'
- name: Checkout base
run: |
mkdir _base
cp -r .git _base/.git
cd _base
git fetch --depth 1 origin ${{ github.base_ref }}
git checkout origin/${{ github.base_ref }} CHANGELOG.md
- name: Copy to Checker directory for CHANGELOG-base.md
run: cp _base/CHANGELOG.md scripts/changelog-checker/CHANGELOG-base.md
- name: Copy to Checker directory for CHANGELOG-head.md
run: cp CHANGELOG.md scripts/changelog-checker/CHANGELOG-head.md
- name: diff
continue-on-error: true
run: diff -u CHANGELOG-base.md CHANGELOG-head.md
working-directory: scripts/changelog-checker
- name: Setup Checker
run: npm install
working-directory: scripts/changelog-checker
- name: Run Checker
run: npm run run
working-directory: scripts/changelog-checker

View File

@ -0,0 +1,127 @@
name: Check Misskey JS autogen
on:
pull_request:
branches:
- master
- develop
paths:
- packages/backend/**
jobs:
check-misskey-js-autogen:
runs-on: ubuntu-latest
permissions:
pull-requests: write
env:
api_json_names: "api-base.json api-head.json"
steps:
- name: checkout
uses: actions/checkout@v4
with:
submodules: true
- name: setup pnpm
uses: pnpm/action-setup@v2
with:
version: 8
- name: setup node
id: setup-node
uses: actions/setup-node@v4
with:
node-version-file: '.node-version'
cache: pnpm
- name: install dependencies
run: pnpm i --frozen-lockfile
- name: wait get-api-diff
uses: lewagon/wait-on-check-action@v1.3.3
with:
ref: ${{ github.event.pull_request.head.sha }}
check-regexp: get-from-misskey .+
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 30
- name: Download artifact
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const workflows = await github.rest.actions.listWorkflowRunsForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
head_sha: `${{ github.event.pull_request.head.sha }}`
}).then(x => x.data.workflow_runs);
console.log(workflows.map(x => ({name: x.name, title: x.display_title})));
const run_id = workflows.find(x => x.name.includes("Get api.json from Misskey")).id;
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: run_id,
});
let matchArtifacts = allArtifacts.data.artifacts.filter((artifact) => {
return artifact.name.startsWith("api-artifact-") || artifact.name == "api-artifact"
});
await Promise.all(matchArtifacts.map(async (artifact) => {
let download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: artifact.id,
archive_format: 'zip',
});
await fs.promises.writeFile(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data));
}));
- name: unzip artifacts
run: |-
find . -mindepth 1 -maxdepth 1 -type f -name '*.zip' -exec unzip {} -d . ';'
ls -la
- name: build autogen
run: |-
for name in $(echo $api_json_names)
do
checksum=$(mktemp)
mv $name packages/misskey-js/generator/api.json
cd packages/misskey-js/generator
pnpm run generate
find built -type f -exec sh -c 'echo $(sed -E "s/^\s+\*\s+generatedAt:.+$//" {} | sha256sum | cut -d" " -f 1) {}' \; > $checksum
cd ../../..
cp $checksum ${name}_checksum
done
- name: check update for type definitions
run: diff $(echo -n ${api_json_names} | awk -v RS=" " '{ printf "%s_checksum ", $0 }')
- name: send message
if: failure()
uses: thollander/actions-comment-pull-request@v2
with:
comment_tag: check-misskey-js-autogen
message: |-
Thank you for sending us a great Pull Request! 👍
Please regenerate misskey-js type definitions! 🙏
example:
```sh
pnpm run build-misskey-js-with-types
```
- name: send message
if: success()
uses: thollander/actions-comment-pull-request@v2
with:
comment_tag: check-misskey-js-autogen
mode: delete
message: "Thank you!"

View File

@ -37,7 +37,7 @@ jobs:
version: 8 version: 8
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.0 uses: actions/setup-node@v4.0.1
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
cache: 'pnpm' cache: 'pnpm'
@ -56,7 +56,7 @@ jobs:
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: api-artifact name: api-artifact-${{ matrix.api-json-name }}
path: ${{ matrix.api-json-name }} path: ${{ matrix.api-json-name }}
save-pr-number: save-pr-number:
@ -69,5 +69,5 @@ jobs:
echo "$PR_NUMBER" > ./pr_number echo "$PR_NUMBER" > ./pr_number
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
with: with:
name: api-artifact name: api-artifact-pr-number
path: pr_number path: pr_number

View File

@ -5,7 +5,19 @@ on:
branches: branches:
- master - master
- develop - develop
paths:
- packages/backend/**
- packages/frontend/**
- packages/sw/**
- packages/misskey-js/**
- packages/shared/.eslintrc.js
pull_request: pull_request:
paths:
- packages/backend/**
- packages/frontend/**
- packages/sw/**
- packages/misskey-js/**
- packages/shared/.eslintrc.js
jobs: jobs:
pnpm_install: pnpm_install:
@ -19,7 +31,7 @@ jobs:
with: with:
version: 8 version: 8
run_install: false run_install: false
- uses: actions/setup-node@v4.0.0 - uses: actions/setup-node@v4.0.1
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
@ -46,7 +58,7 @@ jobs:
with: with:
version: 7 version: 7
run_install: false run_install: false
- uses: actions/setup-node@v4.0.0 - uses: actions/setup-node@v4.0.1
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
@ -72,10 +84,12 @@ jobs:
with: with:
version: 7 version: 7
run_install: false run_install: false
- uses: actions/setup-node@v4.0.0 - uses: actions/setup-node@v4.0.1
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
cache: 'pnpm' cache: 'pnpm'
- run: corepack enable - run: corepack enable
- run: pnpm i --frozen-lockfile - run: pnpm i --frozen-lockfile
- run: pnpm --filter misskey-js run build
if: ${{ matrix.workspace == 'backend' }}
- run: pnpm --filter ${{ matrix.workspace }} run typecheck - run: pnpm --filter ${{ matrix.workspace }} run typecheck

View File

@ -19,24 +19,28 @@ jobs:
uses: actions/github-script@v7 uses: actions/github-script@v7
with: with:
script: | script: |
const fs = require('fs');
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
run_id: context.payload.workflow_run.id, run_id: context.payload.workflow_run.id,
}); });
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { let matchArtifacts = allArtifacts.data.artifacts.filter((artifact) => {
return artifact.name == "api-artifact" return artifact.name.startsWith("api-artifact-") || artifact.name == "api-artifact"
})[0];
let download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
}); });
let fs = require('fs'); await Promise.all(matchArtifacts.map(async (artifact) => {
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/api-artifact.zip`, Buffer.from(download.data)); let download = await github.rest.actions.downloadArtifact({
- name: Extract artifact owner: context.repo.owner,
run: unzip api-artifact.zip -d artifacts repo: context.repo.repo,
artifact_id: artifact.id,
archive_format: 'zip',
});
await fs.promises.writeFile(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data));
}));
- name: Extract all artifacts
run: |
find . -mindepth 1 -maxdepth 1 -type f -name '*.zip' -exec unzip {} -d artifacts ';'
ls -la
- name: Load PR Number - name: Load PR Number
id: load-pr-num id: load-pr-num
run: echo "pr-number=$(cat artifacts/pr_number)" >> "$GITHUB_OUTPUT" run: echo "pr-number=$(cat artifacts/pr_number)" >> "$GITHUB_OUTPUT"
@ -83,3 +87,11 @@ jobs:
pr_number: ${{ steps.load-pr-num.outputs.pr-number }} pr_number: ${{ steps.load-pr-num.outputs.pr-number }}
comment_tag: show_diff comment_tag: show_diff
filePath: ./output.md filePath: ./output.md
- name: Tell error to PR
uses: thollander/actions-comment-pull-request@v2
if: failure() && steps.load-pr-num.outputs.pr-number
with:
pr_number: ${{ steps.load-pr-num.outputs.pr-number }}
comment_tag: show_diff_error
message: |
api.jsonの差分作成中にエラーが発生しました。詳細は[Workflowのログ](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})を確認してください。

View File

@ -5,10 +5,18 @@ on:
branches: branches:
- master - master
- develop - develop
paths:
- packages/backend/**
# for permissions
- packages/misskey-js/**
pull_request: pull_request:
paths:
- packages/backend/**
# for permissions
- packages/misskey-js/**
jobs: jobs:
jest: unit:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
@ -17,7 +25,7 @@ jobs:
services: services:
postgres: postgres:
image: postgres:13 image: postgres:15
ports: ports:
- 54312:5432 - 54312:5432
env: env:
@ -38,7 +46,7 @@ jobs:
version: 8 version: 8
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.0 uses: actions/setup-node@v4.0.1
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
cache: 'pnpm' cache: 'pnpm'
@ -51,9 +59,59 @@ jobs:
- name: Build - name: Build
run: pnpm build run: pnpm build
- name: Test - name: Test
run: pnpm jest-and-coverage run: pnpm --filter backend test-and-coverage
- name: Upload Coverage - name: Upload to Codecov
uses: codecov/codecov-action@v3 uses: codecov/codecov-action@v3
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json files: ./packages/backend/coverage/coverage-final.json
e2e:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.10.0]
services:
postgres:
image: postgres:15
ports:
- 54312:5432
env:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:7
ports:
- 56312:6379
steps:
- uses: actions/checkout@v4.1.1
with:
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: 8
run_install: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.1
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- run: corepack enable
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure
run: cp .github/misskey/test.yml .config
- name: Build
run: pnpm build
- name: Test
run: pnpm --filter backend test-and-coverage:e2e
- name: Upload to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json

View File

@ -5,7 +5,20 @@ on:
branches: branches:
- master - master
- develop - develop
paths:
- packages/frontend/**
# for permissions
- packages/misskey-js/**
# for e2e
- packages/backend/**
pull_request: pull_request:
paths:
- packages/frontend/**
# for permissions
- packages/misskey-js/**
# for e2e
- packages/backend/**
jobs: jobs:
vitest: vitest:
@ -25,7 +38,7 @@ jobs:
version: 8 version: 8
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.0 uses: actions/setup-node@v4.0.1
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
cache: 'pnpm' cache: 'pnpm'
@ -56,7 +69,7 @@ jobs:
services: services:
postgres: postgres:
image: postgres:13 image: postgres:15
ports: ports:
- 54312:5432 - 54312:5432
env: env:
@ -83,7 +96,7 @@ jobs:
version: 7 version: 7
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.0 uses: actions/setup-node@v4.0.1
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
cache: 'pnpm' cache: 'pnpm'

View File

@ -6,8 +6,12 @@ name: Test (misskey.js)
on: on:
push: push:
branches: [ develop ] branches: [ develop ]
paths:
- packages/misskey-js/**
pull_request: pull_request:
branches: [ develop ] branches: [ develop ]
paths:
- packages/misskey-js/**
jobs: jobs:
test: test:
@ -26,7 +30,7 @@ jobs:
- run: corepack enable - run: corepack enable
- name: Setup Node.js ${{ matrix.node-version }} - name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.0 uses: actions/setup-node@v4.0.1
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
cache: 'pnpm' cache: 'pnpm'

View File

@ -28,7 +28,7 @@ jobs:
version: 8 version: 8
run_install: false run_install: false
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.0 uses: actions/setup-node@v4.0.1
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
cache: 'pnpm' cache: 'pnpm'

47
.github/workflows/validate-api-json.yml vendored Normal file
View File

@ -0,0 +1,47 @@
name: Test (backend)
on:
push:
branches:
- master
- develop
paths:
- packages/backend/**
pull_request:
paths:
- packages/backend/**
jobs:
validate-api-json:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.10.0]
steps:
- uses: actions/checkout@v4.1.1
with:
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: 8
run_install: false
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.1
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Install Redocly CLI
run: npm i -g @redocly/cli
- run: corepack enable
- run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
- name: Copy Configure
run: cp .config/example.yml .config/default.yml
- name: Build and generate
run: pnpm build && pnpm --filter backend generate-api-json
- name: Validation
run: npx @redocly/cli lint --extends=minimal ./packages/backend/built/api.json

1
.gitignore vendored
View File

@ -41,6 +41,7 @@ docker-compose.yml
# misskey # misskey
/build /build
built built
built-test
/data /data
/.cache-loader /.cache-loader
/db /db

1
.npmrc Normal file
View File

@ -0,0 +1 @@
engine-strict = true

22
.vscode/settings.json vendored
View File

@ -1,11 +1,15 @@
{ {
"search.exclude": { "search.exclude": {
"**/node_modules": true "**/node_modules": true
}, },
"typescript.tsdk": "node_modules/typescript/lib", "typescript.tsdk": "node_modules/typescript/lib",
"files.associations": { "files.associations": {
"*.test.ts": "typescript" "*.test.ts": "typescript"
}, },
"jest.jestCommandLine": "pnpm run jest", "jest.jestCommandLine": "pnpm run jest",
"jest.autoRun": "off" "jest.autoRun": "off",
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
},
"editor.formatOnSave": false
} }

View File

@ -5,34 +5,111 @@
- -
### Client ### Client
- Fix: ページ一覧ページの表示がモバイル環境において崩れているのを修正 -
- Fix: MFMでルビの中のテキストがnyaizeされない問題を修正
### Server ### Server
- -
--> -->
## 2023.x.x (unreleased) ## 202x.x.x (Unreleased)
### General
- Feat: [mCaptcha](https://github.com/mCaptcha/mCaptcha)のサポートを追加
- Fix: リストライムラインの「リノートを表示」が正しく機能しない問題を修正
### Client
- Feat: 新しいゲームを追加
- Feat: 音声・映像プレイヤーを追加
- Feat: 絵文字の詳細ダイアログを追加
- Feat: 枠線をつけるMFM`$[border.width=1,style=solid,color=fff,radius=0 ...]`を追加
- デフォルトで枠線からはみ出る部分が隠されるようにしました。初期と同じ挙動にするには`$[border.noclip`が必要です
- Enhance: MFM等のコードブロックに全文コピー用のボタンを追加
- Enhance: ハッシュタグ入力時に、本文の末尾の行に何も書かれていない場合は新たにスペースを追加しないように
- Enhance: チャンネルノートのピン留めをノートのメニューからできるように
- Enhance: 管理者の場合はAPI tokenの発行画面で管理機能に関する権限を付与できるように
- Enhance: AiScriptを0.17.0に更新 [CHANGELOG](https://github.com/aiscript-dev/aiscript/blob/bb89d132b633a622d3cb0eff0d0cc7e476c0cfdd/CHANGELOG.md)
- 配列の範囲外・非整数のインデックスへの代入が完全禁止になるので注意
- Enhance: 絵文字ピッカー・オートコンプリートで、完全一致した絵文字を優先的に表示するように
- Enhance: Playの説明欄にMFMを使えるように
- Enhance: チャンネルノートの場合は詳細ページからその前後のノートを見れるように
- Fix: ネイティブモードの絵文字がモノクロにならないように
- Fix: v2023.12.0で追加された「モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能」が管理画面上で正しく表示されていない問題を修正
- Fix: AiScriptの`readline`関数が不正な値を返すことがある問題のv2023.12.0時点での修正がPlay以外に適用されていないのを修正
- Fix: v2023.12.1で追加された`$[clickable ...]`および`onClickEv`が正しく機能していないのを修正
- Enhance: ページ遷移時にPlayerを閉じるように
### Server
- Enhance: 連合先のレートリミットに引っかかった際にリトライするようになりました
- Enhance: ActivityPub Deliver queueでBodyを事前処理するように (#12916)
- Enhance: クリップをエクスポートできるように
- Enhance: `/files`のファイルに対してHTTP Rangeリクエストを行えるように
- Enhance: `api.json`のOpenAPI Specificationを3.1.0に更新
- Fix: `drive/files/update`でファイル名のバリデーションが機能していない問題を修正
- Fix: `notes/create`で、`text`が空白文字のみで構成されているか`null`であって、かつ`text`だけであるリクエストに対するレスポンスが400になるように変更
- Fix: `notes/create`で、`text`が空白文字のみで構成されていてかつリノート、ファイルまたは投票を含んでいるリクエストに対するレスポンスの`text`が`""`から`null`になるように変更
- Fix: ipv4とipv6の両方が利用可能な環境でallowedPrivateNetworksが設定されていた場合プライベートipの検証ができていなかった問題を修正
- Fix: properly handle cc followers
## 2023.12.2
### General
- v2023.12.1でDockerを利用してサーバーを起動できない問題を修正
### Client
- Enhance: 検索画面においてEnterキー押下で検索できるように
## 2023.12.1
### Note ### Note
- Node.js 20.10.0が最小要件になりました - アクセストークンの権限が再整理されたため、一部のAPIが古いAPIトークンでは動作しなくなりました。\
権限不足になる場合には権限を再設定して再生成してください。
### General
- Enhance: ローカリゼーションの更新
- Fix: 自分のdirect noteがuser list timelineに追加されない
### Client
- Feat: AiScript専用のMFM構文`$[clickable.ev=EVENTNAME ...]`を追加。`Mk:C:mfm`のオプション`onClickEv`に関数を渡すと、クリック時に`EVENTNAME`を引数にして呼び出す
- Enhance: MFM入力補助ボタンを投稿フォームに表示できるように #12787
- Fix: 一部のモデログ(logYellowでの表示対象)について、表示の色が変わらない問題を修正
- Fix: `fg`/`bg`MFMに長い単語を指定すると、オーバーフローされずはみ出る問題を修正
### Server
- Enhance: センシティブワードの設定がハッシュタグトレンドにも適用されるようになりました
- Enhance: `oauth/token`エンドポイントのCORS対応
- Fix: 1702718871541-ffVisibility.jsのdownが壊れている
- Fix:「非センシティブのみ(リモートはいいねのみ)」を設定していても、センシティブに設定されたカスタム絵文字をリアクションできる問題を修正
- Fix: ロールアサイン時の通知で,ロールアイコンが縮小されずに表示される問題を修正
- Fix: サードパーティアプリケーションがWebsocket APIに無条件にアクセスできる問題を修正
- Fix: サードパーティアプリケーションがユーザーの許可なしに非公開の情報を見ることができる問題を修正
## 2023.12.0
### Note
- 依存関係の更新に伴い、Node.js 20.10.0が最小要件になりました
- 絵文字の追加辞書を既にインストールしている場合は、お手数ですが再インストールのほどお願いします
- 絵文字ピッカーにピン留め表示する絵文字設定が「リアクション用」と「絵文字入力用」に分かれました。以前の設定は「リアクション用」として使用されます。 - 絵文字ピッカーにピン留め表示する絵文字設定が「リアクション用」と「絵文字入力用」に分かれました。以前の設定は「リアクション用」として使用されます。
**影響:** **影響:**
それにより、投稿フォームから表示される絵文字ピッカーのピン留め絵文字がリセットされたように感じるかもしれません(新設された投稿用のピン留め絵文字が使われるため)。 それにより、投稿フォームから表示される絵文字ピッカーのピン留め絵文字がリセットされたように感じるかもしれません(新設された"ピン留め(全般)"の設定が使われるため)。
投稿用のピン留め絵文字をアップデート前の状態にするには、以下の手順で操作します。 投稿用のピン留め絵文字をアップデート前の状態にするには、以下の手順で操作します。
1. 「設定」メニューに移動し、「絵文字ピッカー」タブを選択します。 1. 「設定」メニューに移動し、「絵文字ピッカー」タブを選択します。
2. 「ピン留 (全般)」のタブを選択します。 2. 「ピン留 (全般)」のタブを選択します。
3. 「リアクション設定からコピーする」ボタンを押すことで、アップデート前の状態に戻すことができます。 3. 「リアクション設定から上書きする」ボタンを押すことで、アップデート前の状態に戻すことができます。
### General ### General
- Feat: メールアドレスの認証にverifymail.ioを使えるように (cherry-pick from https://github.com/TeamNijimiss/misskey/commit/971ba07a44550f68d2ba31c62066db2d43a0caed) - Feat: メールアドレスの認証にverifymail.ioを使えるように (cherry-pick from https://github.com/TeamNijimiss/misskey/commit/971ba07a44550f68d2ba31c62066db2d43a0caed)
- Feat: モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能を追加 (cherry-pick from https://github.com/TeamNijimiss/misskey/commit/e0eb5a752f6e5616d6312bb7c9790302f9dbff83) - Feat: モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能を追加 (cherry-pick from https://github.com/TeamNijimiss/misskey/commit/e0eb5a752f6e5616d6312bb7c9790302f9dbff83)
- Feat: TL上からートが見えなくなるワードミュートであるハードミュートを追加 - Feat: TL上からートが見えなくなるワードミュートであるハードミュートを追加
- Enhance: 指定したドメインのメールアドレスの登録を弾くことができるように
- Enhance: 公開ロールにアサインされたときに通知が作成されるように
- Enhance: アイコンデコレーションを複数設定できるように - Enhance: アイコンデコレーションを複数設定できるように
- Enhance: アイコンデコレーションの位置を微調整できるように - Enhance: アイコンデコレーションの位置を微調整できるように
- Enhance: つながりの公開範囲をフォロー/フォロワーで個別に設定可能に #12072
- Enhance: ローカリゼーションの更新
- Enhance: 依存関係の更新
- Fix: MFM `$[unixtime ]` に不正な値を入力した際に発生する各種エラーを修正 - Fix: MFM `$[unixtime ]` に不正な値を入力した際に発生する各種エラーを修正
### Client ### Client
@ -58,10 +135,17 @@
- Enhance: ユーザー名、プロフィール、お知らせ、ページの編集画面でMFMや絵文字のオートコンプリートが使用できるように - Enhance: ユーザー名、プロフィール、お知らせ、ページの編集画面でMFMや絵文字のオートコンプリートが使用できるように
- Enhance: プロフィール、お知らせの編集画面でMFMのプレビューを表示できるように - Enhance: プロフィール、お知らせの編集画面でMFMのプレビューを表示できるように
- Enhance: 絵文字の詳細ページに記載される情報を追加 - Enhance: 絵文字の詳細ページに記載される情報を追加
- Enhance: リアクションの表示幅制限を設定可能に
- Enhance: Unicode 15.0のサポート
- Enhance: コードブロックのハイライト機能を利用するには言語を明示的に指定させるように - Enhance: コードブロックのハイライト機能を利用するには言語を明示的に指定させるように
- MFMでコードブロックを利用する際に意図しないハイライトが起こらないようになりました - MFMでコードブロックを利用する際に意図しないハイライトが起こらないようになりました
- 逆に、MFMでコードハイライトを利用したい際は言語を明示的に指定する必要があります - 逆に、MFMでコードハイライトを利用したい際は言語を明示的に指定する必要があります
(例: ` ```js ` → Javascript, ` ```ais ` → AiScript (例: ` ```js ` → Javascript, ` ```ais ` → AiScript
- Enhance: 絵文字などのオートコンプリートでShift+Tabを押すと前の候補を選択できるように
- Enhance: チャンネルに新規の投稿がある場合にバッジを表示させる
- Enhance: サウンド設定に「サウンドを出力しない」と「Misskeyがアクティブな時のみサウンドを出力する」を追加
- Enhance: 設定したタグをトレンドに表示させないようにする項目を管理画面で設定できるように
- Enhance: 絵文字ピッカーのカテゴリに「/」を入れることでフォルダ分け表示できるように
- Fix: 「設定のバックアップ」で一部の項目がバックアップに含まれていなかった問題を修正 - Fix: 「設定のバックアップ」で一部の項目がバックアップに含まれていなかった問題を修正
- Fix: ウィジェットのジョブキューにて音声の発音方法変更に追従できていなかったのを修正 #12367 - Fix: ウィジェットのジョブキューにて音声の発音方法変更に追従できていなかったのを修正 #12367
- Fix: コードエディタが正しく表示されない問題を修正 - Fix: コードエディタが正しく表示されない問題を修正
@ -74,10 +158,20 @@
- Fix: ノート中の絵文字をタップして「リアクションする」からリアクションした際にリアクションサウンドが鳴らない不具合を修正 - Fix: ノート中の絵文字をタップして「リアクションする」からリアクションした際にリアクションサウンドが鳴らない不具合を修正
- Fix: ノート中のリアクションの表示を微調整 #12650 - Fix: ノート中のリアクションの表示を微調整 #12650
- Fix: AiScriptの`readline`が不正な値を返すことがある問題を修正 - Fix: AiScriptの`readline`が不正な値を返すことがある問題を修正
- Fix: 投票のみ/画像のみの引用RNが、通知欄でただのRNとして判定されるバグを修正
- Fix: CWをつけて引用RNしても、普通のRNとして扱われてしまうバグを修正しました。
- Fix: 「画像が1枚のみのメディアリストの高さ」を「デフォルト」以外に設定していると、CWの中などに添付された画像が見られないバグを修正
- Fix: DeepL TranslationのPro accountトグルスイッチが表示されていなかったのを修正
- Fix: twitterの埋め込みカード内リンクからリンク先を開けない問題を修正
- Fix: WebKitブラウザー上でも「デバイスの画面を常にオンにする」機能が効くように
- Fix: ページ一覧ページの表示がモバイル環境において崩れているのを修正
- Fix: MFMでルビの中のテキストがnyaizeされない問題を修正
### Server ### Server
- Enhance: MFM `$[ruby ]` が他ソフトウェアと連合されるように - Enhance: MFM `$[ruby ]` が他ソフトウェアと連合されるように
- Enhance: Meilisearchを有効にした検索で、ユーザーのミュートやブロックを考慮するように - Enhance: Meilisearchを有効にした検索で、ユーザーのミュートやブロックを考慮するように
- Enhance: カスタム絵文字のインポート時の動作を改善
- Enhance: json-schema(OpenAPIの戻り値として使用されるスキーマ定義)を出来る限り最新化 #12311
- Fix: 時間経過により無効化されたアンテナを再有効化したとき、サーバ再起動までその状況が反映されないのを修正 #12303 - Fix: 時間経過により無効化されたアンテナを再有効化したとき、サーバ再起動までその状況が反映されないのを修正 #12303
- Fix: ロールタイムラインが保存されない問題を修正 - Fix: ロールタイムラインが保存されない問題を修正
- Fix: api.jsonの生成ロジックを改善 #12402 - Fix: api.jsonの生成ロジックを改善 #12402
@ -92,6 +186,7 @@
- Fix: 「みつける」が年越し時に壊れる問題を修正 - Fix: 「みつける」が年越し時に壊れる問題を修正
- Fix: アカウントをブロックした際に、自身のユーザーのページでノートが相手に表示される問題を修正 - Fix: アカウントをブロックした際に、自身のユーザーのページでノートが相手に表示される問題を修正
- Fix: モデレーションログがモデレーターは閲覧できないように修正 - Fix: モデレーションログがモデレーターは閲覧できないように修正
- Fix: ハッシュタグのトレンド除外設定が即時に効果を持つように修正
- Fix: HTTP Digestヘッダのアルゴリズム部分に大文字の"SHA-256"しか使えない - Fix: HTTP Digestヘッダのアルゴリズム部分に大文字の"SHA-256"しか使えない
## 2023.11.1 ## 2023.11.1
@ -103,7 +198,6 @@
- Feat: 管理者がコントロールパネルからメールアドレスの照会を行えるようになりました - Feat: 管理者がコントロールパネルからメールアドレスの照会を行えるようになりました
- Enhance: ローカリゼーションの更新 - Enhance: ローカリゼーションの更新
- Enhance: 依存関係の更新 - Enhance: 依存関係の更新
- Enhance: json-schema(OpenAPIの戻り値として使用されるスキーマ定義)を出来る限り最新化 #12311
### Client ### Client
- Enhance: MFMでルビを振れるように - Enhance: MFMでルビを振れるように
@ -112,7 +206,6 @@
- 例: `$[unixtime 1701356400]` - 例: `$[unixtime 1701356400]`
- Enhance: プラグインでエラーが発生した場合のハンドリングを強化 - Enhance: プラグインでエラーが発生した場合のハンドリングを強化
- Enhance: 細かなUIのブラッシュアップ - Enhance: 細かなUIのブラッシュアップ
- Enhance: サウンド設定に「サウンドを出力しない」と「Misskeyがアクティブな時のみサウンドを出力する」を追加
- Fix: 効果音が再生されるとデバイスで再生している動画や音声が停止する問題を修正 #12339 - Fix: 効果音が再生されるとデバイスで再生している動画や音声が停止する問題を修正 #12339
- Fix: デッキに表示されたチャンネルの表示先チャンネルを切り替えた際、即座に反映されない問題を修正 #12236 - Fix: デッキに表示されたチャンネルの表示先チャンネルを切り替えた際、即座に反映されない問題を修正 #12236
- Fix: プラグインでノートの表示を書き換えられない問題を修正 - Fix: プラグインでノートの表示を書き換えられない問題を修正
@ -140,7 +233,7 @@
### General ### General
- Feat: アイコンデコレーション機能 - Feat: アイコンデコレーション機能
- サーバーで用意された画像をアイコンに重ねることができます - サーバーで用意された画像をアイコンに重ねることができます
- 画像のテンプレートはこちらです: https://misskey-hub.net/avatar-decoration-template.png - 画像のテンプレートはこちらです: https://misskey-hub.net/brand-assets/
- 最大でも黄色いエリア内にデコレーションを収めることを推奨します。 - 最大でも黄色いエリア内にデコレーションを収めることを推奨します。
- 画像は512x512pxを推奨します。 - 画像は512x512pxを推奨します。
- Feat: チャンネル設定にリノート/引用リノートの可否を設定できる項目を追加 - Feat: チャンネル設定にリノート/引用リノートの可否を設定できる項目を追加
@ -157,7 +250,7 @@
### Client ### Client
- Feat: プラグイン・テーマを外部サイトから直接インストールできるようになりました - Feat: プラグイン・テーマを外部サイトから直接インストールできるようになりました
- 外部サイトでの実装が必要です。詳細は Misskey Hub をご覧ください - 外部サイトでの実装が必要です。詳細は Misskey Hub をご覧ください
https://misskey-hub.net/docs/advanced/publish-on-your-website.html https://misskey-hub.net/docs/for-developers/publish-on-your-website/
- Feat: 通知をグルーピングして表示するオプション(オプトアウト) - Feat: 通知をグルーピングして表示するオプション(オプトアウト)
- Feat: Misskeyの基本的なチュートリアルを実装 - Feat: Misskeyの基本的なチュートリアルを実装
- Feat: スワイプしてタイムラインを再読込できるように - Feat: スワイプしてタイムラインを再読込できるように
@ -222,7 +315,6 @@
### Client ### Client
- Enhance: TLの返信表示オプションを記憶するように - Enhance: TLの返信表示オプションを記憶するように
- Enhance: 投稿されてから時間が経過しているノートであることを視覚的に分かりやすく - Enhance: 投稿されてから時間が経過しているノートであることを視覚的に分かりやすく
- Feat: 絵文字ピッカーのカテゴリに「/」を入れることでフォルダ分け表示できるように
### Server ### Server
- Enhance: タイムライン取得時のパフォーマンスを向上 - Enhance: タイムライン取得時のパフォーマンスを向上

View File

@ -1,5 +1,5 @@
Unless otherwise stated this repository is Unless otherwise stated this repository is
Copyright © 2014-2023 syuilo and contributers Copyright © 2014-2024 syuilo and contributors
And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE. And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE.

View File

@ -51,6 +51,7 @@ WORKDIR /misskey
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"] COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
COPY --link ["scripts", "./scripts"] COPY --link ["scripts", "./scripts"]
COPY --link ["packages/backend/package.json", "./packages/backend/"] COPY --link ["packages/backend/package.json", "./packages/backend/"]
COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \ RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
pnpm i --frozen-lockfile --aggregate-output pnpm i --frozen-lockfile --aggregate-output
@ -77,7 +78,9 @@ WORKDIR /misskey
COPY --chown=misskey:misskey --from=target-builder /misskey/node_modules ./node_modules COPY --chown=misskey:misskey --from=target-builder /misskey/node_modules ./node_modules
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/backend/node_modules ./packages/backend/node_modules COPY --chown=misskey:misskey --from=target-builder /misskey/packages/backend/node_modules ./packages/backend/node_modules
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-js/node_modules ./packages/misskey-js/node_modules
COPY --chown=misskey:misskey --from=native-builder /misskey/built ./built COPY --chown=misskey:misskey --from=native-builder /misskey/built ./built
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-js/built ./packages/misskey-js/built
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/built ./packages/backend/built COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/built ./packages/backend/built
COPY --chown=misskey:misskey --from=native-builder /misskey/fluent-emojis /misskey/fluent-emojis COPY --chown=misskey:misskey --from=native-builder /misskey/fluent-emojis /misskey/fluent-emojis
COPY --chown=misskey:misskey . ./ COPY --chown=misskey:misskey . ./

View File

@ -7,10 +7,10 @@
--- ---
<a href="https://misskey-hub.net/instances.html"> <a href="https://misskey-hub.net/servers/">
<img src="https://custom-icon-badges.herokuapp.com/badge/find_an-instance-acea31?logoColor=acea31&style=for-the-badge&logo=misskey&labelColor=363B40" alt="find an instance"/></a> <img src="https://custom-icon-badges.herokuapp.com/badge/find_an-instance-acea31?logoColor=acea31&style=for-the-badge&logo=misskey&labelColor=363B40" alt="find an instance"/></a>
<a href="https://misskey-hub.net/docs/install.html"> <a href="https://misskey-hub.net/docs/for-admin/install/guides/">
<img src="https://custom-icon-badges.herokuapp.com/badge/create_an-instance-FBD53C?logoColor=FBD53C&style=for-the-badge&logo=server&labelColor=363B40" alt="create an instance"/></a> <img src="https://custom-icon-badges.herokuapp.com/badge/create_an-instance-FBD53C?logoColor=FBD53C&style=for-the-badge&logo=server&labelColor=363B40" alt="create an instance"/></a>
<a href="./CONTRIBUTING.md"> <a href="./CONTRIBUTING.md">
@ -51,7 +51,7 @@ With Misskey's built in drive, you get cloud storage right in your social media,
## Documentation ## Documentation
Misskey Documentation can be found at [Misskey Hub](https://misskey-hub.net/), some of the links and graphics above also lead to specific portions of it. Misskey Documentation can be found at [Misskey Hub](https://misskey-hub.net/docs/), some of the links and graphics above also lead to specific portions of it.
## Sponsors ## Sponsors

View File

@ -6,6 +6,7 @@ Also, the later tasks are more indefinite and are subject to change as developme
This is the phase we are at now. We need to make a high-maintenance environment that can withstand future development. This is the phase we are at now. We need to make a high-maintenance environment that can withstand future development.
- ~~Make the number of type errors zero (backend)~~ → Done ✔️ - ~~Make the number of type errors zero (backend)~~ → Done ✔️
- Make the number of type errors zero (frontend)
- Improve CI - Improve CI
- ~~Fix tests~~ → Done ✔️ - ~~Fix tests~~ → Done ✔️
- Fix random test failures - https://github.com/misskey-dev/misskey/issues/7985 and https://github.com/misskey-dev/misskey/issues/7986 - Fix random test failures - https://github.com/misskey-dev/misskey/issues/7985 and https://github.com/misskey-dev/misskey/issues/7986

View File

@ -1,7 +1,6 @@
# Reporting Security Issues # Reporting Security Issues
If you discover a security issue in Misskey, please report it by sending an If you discover a security issue in Misskey, please report it by **[this form](https://github.com/misskey-dev/misskey/security/advisories/new)**.
email to [syuilotan@yahoo.co.jp](mailto:syuilotan@yahoo.co.jp).
This will allow us to assess the risk, and make a fix available before we add a This will allow us to assess the risk, and make a fix available before we add a
bug report to the GitHub repository. bug report to the GitHub repository.

View File

@ -27,7 +27,7 @@ spec:
ports: ports:
- containerPort: 3000 - containerPort: 3000
- name: postgres - name: postgres
image: postgres:14-alpine image: postgres:15-alpine
env: env:
- name: POSTGRES_USER - name: POSTGRES_USER
value: "example-misskey-user" value: "example-misskey-user"
@ -38,7 +38,7 @@ spec:
ports: ports:
- containerPort: 5432 - containerPort: 5432
- name: redis - name: redis
image: redis:alpine image: redis:7-alpine
ports: ports:
- containerPort: 6379 - containerPort: 6379
volumes: volumes:

View File

@ -7,6 +7,7 @@ services:
links: links:
- db - db
- redis - redis
# - mcaptcha
# - meilisearch # - meilisearch
depends_on: depends_on:
db: db:
@ -48,6 +49,36 @@ services:
interval: 5s interval: 5s
retries: 20 retries: 20
# mcaptcha:
# restart: always
# image: mcaptcha/mcaptcha:latest
# networks:
# internal_network:
# external_network:
# aliases:
# - localhost
# ports:
# - 7493:7493
# env_file:
# - .config/docker.env
# environment:
# PORT: 7493
# MCAPTCHA_redis_URL: "redis://mcaptcha_redis/"
# depends_on:
# db:
# condition: service_healthy
# mcaptcha_redis:
# condition: service_healthy
#
# mcaptcha_redis:
# image: mcaptcha/cache:latest
# networks:
# - internal_network
# healthcheck:
# test: "redis-cli ping"
# interval: 5s
# retries: 20
# meilisearch: # meilisearch:
# restart: always # restart: always
# image: getmeili/meilisearch:v1.3.4 # image: getmeili/meilisearch:v1.3.4

View File

@ -120,7 +120,6 @@ sensitive: "محتوى حساس"
add: "إضافة" add: "إضافة"
reaction: "التفاعلات" reaction: "التفاعلات"
reactions: "التفاعلات" reactions: "التفاعلات"
reactionSetting: "التفاعلات المراد عرضها في منتقي التفاعلات."
reactionSettingDescription2: "اسحب لترتيب ، انقر للحذف ، استخدم \"+\" للإضافة." reactionSettingDescription2: "اسحب لترتيب ، انقر للحذف ، استخدم \"+\" للإضافة."
rememberNoteVisibility: "تذكر إعدادت مدى رؤية الملاحظات" rememberNoteVisibility: "تذكر إعدادت مدى رؤية الملاحظات"
attachCancel: "أزل المرفق" attachCancel: "أزل المرفق"
@ -817,8 +816,6 @@ makeReactionsPublicDescription: "هذا سيجعل قائمة تفاعلاتك
classic: "تقليدي" classic: "تقليدي"
muteThread: "اكتم النقاش" muteThread: "اكتم النقاش"
unmuteThread: "ارفع الكتم عن النقاش" unmuteThread: "ارفع الكتم عن النقاش"
ffVisibility: "مرئية المتابِعين/المتابَعين"
ffVisibilityDescription: "يسمح لك بتحديد من يمكنهم رؤية متابِعيك ومتابَعيك."
continueThread: "اعرض بقية النقاش" continueThread: "اعرض بقية النقاش"
deleteAccountConfirm: "سيحذف حسابك نهائيًا، أتريد المتابعة؟" deleteAccountConfirm: "سيحذف حسابك نهائيًا، أتريد المتابعة؟"
incorrectPassword: "كلمة السر خاطئة." incorrectPassword: "كلمة السر خاطئة."
@ -947,9 +944,12 @@ rolesAssignedToMe: "الأدوار المسندة إلي"
resetPasswordConfirm: "هل تريد إعادة تعيين كلمة السر؟" resetPasswordConfirm: "هل تريد إعادة تعيين كلمة السر؟"
license: "الرخصة" license: "الرخصة"
unfavoriteConfirm: "أتريد إزالتها من المفضلة؟" unfavoriteConfirm: "أتريد إزالتها من المفضلة؟"
reactionsDisplaySize: "حجم التفاعلات"
limitWidthOfReaction: "تصغير حجم التفاعلات"
noteIdOrUrl: "معرف الملاحظة أو رابطها" noteIdOrUrl: "معرف الملاحظة أو رابطها"
video: "فيديو" video: "فيديو"
videos: "فيديوهات" videos: "فيديوهات"
dataSaver: "موفر البيانات"
accountMigration: "ترحيل الحساب" accountMigration: "ترحيل الحساب"
accountMoved: "نقل هذا المستخدم حسابه:" accountMoved: "نقل هذا المستخدم حسابه:"
accountMovedShort: "رُحل هذا الحساب." accountMovedShort: "رُحل هذا الحساب."
@ -957,6 +957,7 @@ operationForbidden: "عملية ممنوعة"
forceShowAds: "أظهر الإعلانات التجارية دائما" forceShowAds: "أظهر الإعلانات التجارية دائما"
reactionsList: "التفاعلات" reactionsList: "التفاعلات"
renotesList: "إعادات النشر" renotesList: "إعادات النشر"
notificationDisplay: "إشعارات"
leftTop: "أعلى اليسار" leftTop: "أعلى اليسار"
rightTop: "أعلى اليمين" rightTop: "أعلى اليمين"
leftBottom: "أسفل اليسار" leftBottom: "أسفل اليسار"
@ -979,6 +980,7 @@ thisChannelArchived: "أُرشفت هذه القناة."
displayOfNote: "عرض الملاحظة" displayOfNote: "عرض الملاحظة"
initialAccountSetting: "إعداد الملف الشخصي" initialAccountSetting: "إعداد الملف الشخصي"
youFollowing: "متابَع" youFollowing: "متابَع"
preventAiLearning: "منع استخدام البيانات في تعليم الآلة"
options: "خيارات" options: "خيارات"
specifyUser: "مستخدم محدد" specifyUser: "مستخدم محدد"
failedToPreviewUrl: "تتعذر المعاينة" failedToPreviewUrl: "تتعذر المعاينة"
@ -992,7 +994,16 @@ later: "لاحقاً"
goToMisskey: "لميسكي" goToMisskey: "لميسكي"
additionalEmojiDictionary: "قواميس إيموجي إضافية" additionalEmojiDictionary: "قواميس إيموجي إضافية"
installed: "مُثبت" installed: "مُثبت"
enableServerMachineStats: "نشر إحصائيات عتاد الخادم"
turnOffToImprovePerformance: "تفعيله قد يزيد الأداء."
createInviteCode: "ولِّد دعوة"
inviteCodeCreated: "ولِّدت دعوة"
inviteLimitExceeded: "وصلتَ لحد عدد الدعوات المسموح لك توليدها."
createLimitRemaining: "حد عدد الدعوات: {limit} دعوة"
expirationDate: "تاريخ انتهاء الصلاحية" expirationDate: "تاريخ انتهاء الصلاحية"
noExpirationDate: "لا نهاية لصلاحيتها"
inviteCodeUsedAt: "اُستخدم رمز الدعوة في"
registeredUserUsingInviteCode: "اِستخدم رمز الدعوة"
unused: "غير مستعمَل" unused: "غير مستعمَل"
expired: "منتهية صلاحيته" expired: "منتهية صلاحيته"
icon: "الصورة الرمزية" icon: "الصورة الرمزية"
@ -1549,3 +1560,4 @@ _webhookSettings:
_moderationLogTypes: _moderationLogTypes:
suspend: "علِق" suspend: "علِق"
resetPassword: "أعد تعيين كلمتك السرية" resetPassword: "أعد تعيين كلمتك السرية"
createInvitation: "ولِّد دعوة"

View File

@ -2,6 +2,7 @@
_lang_: "বাংলা" _lang_: "বাংলা"
headlineMisskey: "নোট ব্যাবহার করে সংযুক্ত নেটওয়ার্ক" headlineMisskey: "নোট ব্যাবহার করে সংযুক্ত নেটওয়ার্ক"
introMisskey: "স্বাগতম! মিসকি একটি ওপেন সোর্স, ডিসেন্ট্রালাইজড মাইক্রোব্লগিং পরিষেবা। \n\"নোট\" তৈরির মাধ্যমে যা ঘটছে তা সবার সাথে শেয়ার করুন 📡\n\"রিঅ্যাকশন\" গুলির মাধ্যমে যেকোনো নোট সম্পর্কে আপনার অনুভূতি ব্যাক্ত করতে পারেন 👍\nএকটি নতুন দুনিয়া ঘুরে দেখুন 🚀\n" introMisskey: "স্বাগতম! মিসকি একটি ওপেন সোর্স, ডিসেন্ট্রালাইজড মাইক্রোব্লগিং পরিষেবা। \n\"নোট\" তৈরির মাধ্যমে যা ঘটছে তা সবার সাথে শেয়ার করুন 📡\n\"রিঅ্যাকশন\" গুলির মাধ্যমে যেকোনো নোট সম্পর্কে আপনার অনুভূতি ব্যাক্ত করতে পারেন 👍\nএকটি নতুন দুনিয়া ঘুরে দেখুন 🚀\n"
poweredByMisskeyDescription: "{name} হল ওপেন সোর্স প্ল্যাটফর্ম <b>Misskey</b>-এর সার্ভারগুলির একটি৷"
monthAndDay: "{day}/{month}" monthAndDay: "{day}/{month}"
search: "খুঁজুন" search: "খুঁজুন"
notifications: "বিজ্ঞপ্তি" notifications: "বিজ্ঞপ্তি"
@ -12,12 +13,14 @@ fetchingAsApObject: "ফেডিভার্স থেকে খবর আন
ok: "ঠিক" ok: "ঠিক"
gotIt: "বুঝেছি" gotIt: "বুঝেছি"
cancel: "বাতিল" cancel: "বাতিল"
noThankYou: "না, ধন্যবাদ"
enterUsername: "ইউজারনেম লিখুন" enterUsername: "ইউজারনেম লিখুন"
renotedBy: "{user} রিনোট করেছেন" renotedBy: "{user} রিনোট করেছেন"
noNotes: "কোন নোট নেই" noNotes: "কোন নোট নেই"
noNotifications: "কোনো বিজ্ঞপ্তি নেই" noNotifications: "কোনো বিজ্ঞপ্তি নেই"
instance: "ইন্সট্যান্স" instance: "ইন্সট্যান্স"
settings: "সেটিংস" settings: "সেটিংস"
notificationSettings: "বিজ্ঞপ্তির সেটিংস"
basicSettings: "সাধারণ সেটিংস" basicSettings: "সাধারণ সেটিংস"
otherSettings: "অন্যান্য সেটিংস" otherSettings: "অন্যান্য সেটিংস"
openInWindow: "নতুন উইন্ডোতে খুলা" openInWindow: "নতুন উইন্ডোতে খুলা"
@ -42,12 +45,20 @@ pin: "পিন করা"
unpin: "পিন সরান" unpin: "পিন সরান"
copyContent: "বিষয়বস্তু কপি করুন" copyContent: "বিষয়বস্তু কপি করুন"
copyLink: "লিঙ্ক কপি করুন" copyLink: "লিঙ্ক কপি করুন"
copyLinkRenote: "রিনোট লিঙ্ক কপি করুন"
delete: "মুছুন" delete: "মুছুন"
deleteAndEdit: "মুছুন এবং সম্পাদনা করুন" deleteAndEdit: "মুছুন এবং সম্পাদনা করুন"
deleteAndEditConfirm: "আপনি কি এই নোটটি মুছে এটি সম্পাদনা করার বিষয়ে নিশ্চিত? আপনি এটির সমস্ত রিঅ্যাকশন, রিনোট এবং জবাব হারাবেন।" deleteAndEditConfirm: "আপনি কি এই নোটটি মুছে এটি সম্পাদনা করার বিষয়ে নিশ্চিত? আপনি এটির সমস্ত রিঅ্যাকশন, রিনোট এবং জবাব হারাবেন।"
addToList: "লিস্ট এ যোগ করুন" addToList: "লিস্ট এ যোগ করুন"
addToAntenna: "অ্যান্টেনা এ যোগ করুন"
sendMessage: "একটি বার্তা পাঠান" sendMessage: "একটি বার্তা পাঠান"
copyRSS: "RSS কপি করুন"
copyUsername: "ব্যবহারকারীর নাম কপি করুন" copyUsername: "ব্যবহারকারীর নাম কপি করুন"
copyUserId: "ব্যবহারকারীর ID কপি করুন"
copyNoteId: "নোটের ID কপি করুন"
copyFileId: "ফাইল ID কপি করুন"
copyFolderId: "ফোল্ডার ID কপি করুন"
copyProfileUrl: "প্রোফাইল URL কপি করুন"
searchUser: "ব্যবহারকারী খুঁজুন..." searchUser: "ব্যবহারকারী খুঁজুন..."
reply: "জবাব" reply: "জবাব"
loadMore: "আরও দেখুন" loadMore: "আরও দেখুন"
@ -100,6 +111,8 @@ renoted: "রিনোট করা হয়েছে"
cantRenote: "এই নোটটি রিনোট করা যাবে না।" cantRenote: "এই নোটটি রিনোট করা যাবে না।"
cantReRenote: "রিনোটকে রিনোট করা যাবে না।" cantReRenote: "রিনোটকে রিনোট করা যাবে না।"
quote: "উদ্ধৃতি" quote: "উদ্ধৃতি"
inChannelRenote: "চ্যানেলে রিনোট"
inChannelQuote: "চ্যানেলে উদ্ধৃতি"
pinnedNote: "পিন করা নোট" pinnedNote: "পিন করা নোট"
pinned: "পিন করা" pinned: "পিন করা"
you: "আপনি" you: "আপনি"
@ -108,7 +121,10 @@ sensitive: "সংবেদনশীল বিষয়বস্তু"
add: "যুক্ত করুন" add: "যুক্ত করুন"
reaction: "প্রতিক্রিয়া" reaction: "প্রতিক্রিয়া"
reactions: "প্রতিক্রিয়া" reactions: "প্রতিক্রিয়া"
reactionSetting: "রিঅ্যাকশন পিকারে যেসকল প্রতিক্রিয়া দেখানো হবে" emojiPicker: "ইমোজি পিকার"
pinnedEmojisForReactionSettingDescription: "রিঅ্যাকশন দেয়ার সময় আপনি ইমোজিটিকে পিন করা এবং প্রদর্শিত হওয়ার জন্য সেট করতে পারেন।"
pinnedEmojisSettingDescription: "ইমোজি ইনপুট দেয়ার সময় আপনি ইমোজিটিকে পিন করা এবং প্রদর্শিত হওয়ার জন্য সেট করতে পারেন।"
emojiPickerDisplay: "পিকার ডিসপ্লে"
reactionSettingDescription2: "পুনরায় সাজাতে টেনে আনুন, মুছতে ক্লিক করুন, যোগ করতে + টিপুন।" reactionSettingDescription2: "পুনরায় সাজাতে টেনে আনুন, মুছতে ক্লিক করুন, যোগ করতে + টিপুন।"
rememberNoteVisibility: "নোটের দৃশ্যমান্যতার সেটিংস মনে রাখুন" rememberNoteVisibility: "নোটের দৃশ্যমান্যতার সেটিংস মনে রাখুন"
attachCancel: "অ্যাটাচমেন্ট সরান " attachCancel: "অ্যাটাচমেন্ট সরান "
@ -794,8 +810,6 @@ makeReactionsPublicDescription: "আপনার পূর্ববর্তী
classic: "ক্লাসিক" classic: "ক্লাসিক"
muteThread: "থ্রেড মিউট করুন" muteThread: "থ্রেড মিউট করুন"
unmuteThread: "থ্রেড আনমিউট করুন" unmuteThread: "থ্রেড আনমিউট করুন"
ffVisibility: "অনুসরণ/অনুসরণকারীদের দৃশ্যমান্যতা"
ffVisibilityDescription: "আপনি কাকে অনুসরণ করেন এবং কে আপনাকে অনুসরণ করে, সেটা কারা দেখতে পাবে তা নির্ধারণ করে।"
continueThread: "আরো থ্রেড দেখুন" continueThread: "আরো থ্রেড দেখুন"
deleteAccountConfirm: "আপনার অ্যাকাউন্ট মুছে ফেলা হবে। ঠিক আছে?" deleteAccountConfirm: "আপনার অ্যাকাউন্ট মুছে ফেলা হবে। ঠিক আছে?"
incorrectPassword: "আপনার দেওয়া পাসওয়ার্ডটি ভুল।" incorrectPassword: "আপনার দেওয়া পাসওয়ার্ডটি ভুল।"
@ -1037,6 +1051,7 @@ _2fa:
step3: "অ্যাপে প্রদর্শিত টোকেনটি লিখুন এবং আপনার কাজ শেষ।" step3: "অ্যাপে প্রদর্শিত টোকেনটি লিখুন এবং আপনার কাজ শেষ।"
step4: "আপনাকে এখন থেকে লগ ইন করার সময়, এইভাবে টোকেন লিখতে হবে।" step4: "আপনাকে এখন থেকে লগ ইন করার সময়, এইভাবে টোকেন লিখতে হবে।"
securityKeyInfo: "আপনি একটি হার্ডওয়্যার সিকিউরিটি কী ব্যবহার করে লগ ইন করতে পারেন যা FIDO2 বা ডিভাইসের ফিঙ্গারপ্রিন্ট সেন্সর বা পিন সমর্থন করে৷" securityKeyInfo: "আপনি একটি হার্ডওয়্যার সিকিউরিটি কী ব্যবহার করে লগ ইন করতে পারেন যা FIDO2 বা ডিভাইসের ফিঙ্গারপ্রিন্ট সেন্সর বা পিন সমর্থন করে৷"
renewTOTPCancel: "না, ধন্যবাদ"
_permissions: _permissions:
"read:account": "অ্যাকাউন্টের তথ্য দেখুন" "read:account": "অ্যাকাউন্টের তথ্য দেখুন"
"write:account": "অ্যাকাউন্টের তথ্য সম্পাদন করুন" "write:account": "অ্যাকাউন্টের তথ্য সম্পাদন করুন"

View File

@ -121,7 +121,12 @@ sensitive: "NSFW"
add: "Afegir" add: "Afegir"
reaction: "Reaccions" reaction: "Reaccions"
reactions: "Reaccions" reactions: "Reaccions"
reactionSetting: "Reaccions a mostrar al selector de reaccions" emojiPicker: "Selecció d'emojis"
pinnedEmojisForReactionSettingDescription: "Selecciona l'emoji amb el qual reaccionar"
pinnedEmojisSettingDescription: "Selecciona l'emoji amb el qual reaccionar"
emojiPickerDisplay: "Visualitza el selector d'emojis"
overwriteFromPinnedEmojisForReaction: "Reemplaça els emojis de la reacció"
overwriteFromPinnedEmojis: "Sobreescriu des dels emojis fixats"
reactionSettingDescription2: "Arrossega per reordenar, fes clic per suprimir, prem \"+\" per afegir." reactionSettingDescription2: "Arrossega per reordenar, fes clic per suprimir, prem \"+\" per afegir."
rememberNoteVisibility: "Recorda la configuració de visibilitat de les notes" rememberNoteVisibility: "Recorda la configuració de visibilitat de les notes"
attachCancel: "Eliminar el fitxer adjunt" attachCancel: "Eliminar el fitxer adjunt"
@ -214,6 +219,9 @@ clearQueueConfirmText: "Les notes no lliurades que quedin a la cua no es federar
clearCachedFiles: "Esborra la memòria cau" clearCachedFiles: "Esborra la memòria cau"
clearCachedFilesConfirm: "Segur que voleu eliminar tots els fitxers de la memòria cau?" clearCachedFilesConfirm: "Segur que voleu eliminar tots els fitxers de la memòria cau?"
blockedInstances: "Instàncies bloquejades" blockedInstances: "Instàncies bloquejades"
blockedInstancesDescription: "Llista els enllaços d'amfitrió de les instàncies que vols bloquejar separades per un salt de pàgina. Les instàncies llistades no podran comunicar-se amb aquesta instància."
silencedInstances: "Instàncies silenciades"
silencedInstancesDescription: "Llista els enllaços d'amfitrió de les instàncies que vols silenciar. Tots els comptes de les instàncies llistades s'establiran com silenciades i només podran fer sol·licitacions de seguiment, i no podran mencionar als comptes locals si no els segueixen. Això no afectarà les instàncies bloquejades."
muteAndBlock: "Silencia i bloca" muteAndBlock: "Silencia i bloca"
mutedUsers: "Usuaris silenciats" mutedUsers: "Usuaris silenciats"
blockedUsers: "Usuaris bloquejats" blockedUsers: "Usuaris bloquejats"
@ -228,9 +236,12 @@ preview: "Vista prèvia"
default: "Per defecte" default: "Per defecte"
defaultValueIs: "Per defecte: {value}" defaultValueIs: "Per defecte: {value}"
noCustomEmojis: "Cap emoji personalitzat" noCustomEmojis: "Cap emoji personalitzat"
noJobs: "No hi ha feines"
federating: "Federant" federating: "Federant"
blocked: "Bloquejat" blocked: "Bloquejat"
suspended: "Suspés" suspended: "Suspés"
all: "tot"
subscribing: "Subscrit a"
publishing: "S'està publicant" publishing: "S'està publicant"
notResponding: "Sense resposta" notResponding: "Sense resposta"
instanceFollowing: "Seguits del servidor" instanceFollowing: "Seguits del servidor"
@ -255,11 +266,31 @@ removed: "Eliminat"
removeAreYouSure: "Segur que voleu retirar «{x}»?" removeAreYouSure: "Segur que voleu retirar «{x}»?"
deleteAreYouSure: "Segur que voleu retirar «{x}»?" deleteAreYouSure: "Segur que voleu retirar «{x}»?"
resetAreYouSure: "Segur que voleu restablir-ho?" resetAreYouSure: "Segur que voleu restablir-ho?"
areYouSure: "Està segur?"
saved: "S'ha desat" saved: "S'ha desat"
messaging: "Xat" messaging: "Xat"
upload: "Puja" upload: "Puja"
keepOriginalUploading: "Guarda la imatge original"
keepOriginalUploadingDescription: "Guarda la imatge pujada com hi és. Si està apagat, una versió per a la visualització a la xarxa serà generada quan sigui pujada."
fromDrive: "Des de la unitat"
fromUrl: "Des d'un enllaç"
uploadFromUrl: "Carrega des d'un enllaç"
uploadFromUrlDescription: "Enllaç del fitxer que vols carregar"
uploadFromUrlRequested: "Càrrega sol·licitada"
uploadFromUrlMayTakeTime: "La càrrega des de l'enllaç pot prendre un temps"
explore: "Explora"
messageRead: "Vist"
noMoreHistory: "No hi resta més per veure"
startMessaging: "Començar a xatejar"
nUsersRead: "Vist per {n}"
agreeTo: "Accepto que {0}"
agree: "Hi estic d'acord"
agreeBelow: "Hi estic d'acord amb el següent"
basicNotesBeforeCreateAccount: "Notes importants"
termsOfService: "Condicions d'ús"
start: "Comença" start: "Comença"
home: "Inici" home: "Inici"
remoteUserCaution: "Ja que aquest usuari resideix a una instància remota, la informació mostrada es podria trobar incompleta."
activity: "Activitat" activity: "Activitat"
images: "Imatges" images: "Imatges"
image: "Imatges" image: "Imatges"
@ -275,16 +306,34 @@ dark: "Fosc"
lightThemes: "Temes clars" lightThemes: "Temes clars"
darkThemes: "Temes foscos" darkThemes: "Temes foscos"
syncDeviceDarkMode: "Sincronitza el mode fosc amb la configuració del dispositiu" syncDeviceDarkMode: "Sincronitza el mode fosc amb la configuració del dispositiu"
drive: "Unitat"
fileName: "Nom del Fitxer"
selectFile: "Selecciona fitxers"
selectFiles: "Selecciona fitxers"
selectFolder: "Selecció de carpeta"
selectFolders: "Selecció de carpeta"
renameFile: "Canvia el nom del fitxer" renameFile: "Canvia el nom del fitxer"
folderName: "Nom de la carpeta" folderName: "Nom de la carpeta"
createFolder: "Crea una carpeta" createFolder: "Crea una carpeta"
renameFolder: "Canvia el nom de la carpeta" renameFolder: "Canvia el nom de la carpeta"
deleteFolder: "Elimina la carpeta" deleteFolder: "Elimina la carpeta"
folder: "Carpeta "
addFile: "Afegeix un fitxer" addFile: "Afegeix un fitxer"
emptyDrive: "La teva unitat és buida"
emptyFolder: "La carpeta està buida" emptyFolder: "La carpeta està buida"
unableToDelete: "No es pot eliminar" unableToDelete: "No es pot eliminar"
inputNewFileName: "Introduïu el nom de fitxer nou"
inputNewDescription: "Inserta una nova llegenda"
inputNewFolderName: "Introduïu el nom de la carpeta nova"
circularReferenceFolder: "La carpeta destinatària és una subcarpeta de la carpeta a la qual la desitges moure"
hasChildFilesOrFolders: "No és possible esborrar aquesta carpeta ja que no és buida"
copyUrl: "Copia l'URL" copyUrl: "Copia l'URL"
rename: "Canvia el nom" rename: "Canvia el nom"
avatar: "Icona"
banner: "Bàner"
displayOfSensitiveMedia: "Visualització de contingut sensible"
whenServerDisconnected: "Quan es perdi la connexió al servidor"
disconnectedFromServer: "Desconnectat pel servidor"
reload: "Actualitza" reload: "Actualitza"
doNothing: "Ignora" doNothing: "Ignora"
accept: "Accepta" accept: "Accepta"
@ -354,33 +403,132 @@ notFound: "No s'ha trobat"
markAsReadAllUnreadNotes: "Marca-ho tot com a llegit" markAsReadAllUnreadNotes: "Marca-ho tot com a llegit"
help: "Ajuda" help: "Ajuda"
invites: "Convida" invites: "Convida"
title: "Títol"
text: "Text"
enable: "Habilita"
next: "Següent" next: "Següent"
retype: "Torneu a introduir-la"
noteOf: "Publicació de: {user}" noteOf: "Publicació de: {user}"
quoteAttached: "Frase adjunta"
quoteQuestion: "Vols annexar-la com a cita?"
noMessagesYet: "Encara no hi ha missatges"
newMessageExists: "Has rebut un nou missatge"
onlyOneFileCanBeAttached: "Només pots adjuntar un fitxer a un missatge"
signinRequired: "Si us plau, Registra't o inicia la sessió abans de continuar"
invitations: "Convida" invitations: "Convida"
invitationCode: "Codi d'invitació"
checking: "Comprovació en curs..."
available: "Disponible"
unavailable: "No és disponible"
usernameInvalidFormat: "Pots fer servir lletres (majúscules i minúscules), números i barres baixes (\"_\")"
tooShort: "Massa curt"
tooLong: "Massa llarg"
weakPassword: "Contrasenya insegura"
normalPassword: "Bona contrasenya"
strongPassword: "Contrasenya segura"
passwordMatched: "Correcte!"
passwordNotMatched: "No coincideix"
signinWith: "Inicia sessió amb amb {x}"
signinFailed: "Autenticació sense èxit. Intenta-ho un altre cop utilitzant la contrasenya i el nom correctes."
or: "O"
language: "Idioma"
uiLanguage: "Idioma de l'interfície"
aboutX: "Respecte a {x}"
emojiStyle: "Estil d'emoji"
native: "Nadiu"
disableDrawer: "No mostrar els menús en calaixos"
showNoteActionsOnlyHover: "Només mostra accions de la nota en passar amb el cursor"
noHistory: "No hi ha un registre previ"
signinHistory: "Historial d'autenticacions"
enableAdvancedMfm: "Habilitar l'MFM avançat"
enableAnimatedMfm: "Habilitar l'MFM amb moviment"
doing: "Processant..."
category: "Categoria"
tags: "Etiquetes" tags: "Etiquetes"
docSource: "Font del document" docSource: "Font del document"
createAccount: "Crea un compte" createAccount: "Crea un compte"
existingAccount: "Compte existent" existingAccount: "Compte existent"
regenerate: "Regenera" regenerate: "Regenera"
fontSize: "Mida del text" fontSize: "Mida del text"
mediaListWithOneImageAppearance: "Altura de la llista de fitxers amb una única imatge"
limitTo: "Limita a {x}"
noFollowRequests: "No tens sol·licituds de seguiment" noFollowRequests: "No tens sol·licituds de seguiment"
openImageInNewTab: "Obre imatges a una nova pestanya"
dashboard: "Panell de control" dashboard: "Panell de control"
local: "Local" local: "Local"
remote: "Remot" remote: "Remot"
total: "Total" total: "Total"
weekOverWeekChanges: "Canvis l'última setmana"
dayOverDayChanges: "Canvis ahir"
appearance: "Aparença" appearance: "Aparença"
clientSettings: "Configuració del client" clientSettings: "Configuració del client"
accountSettings: "Configuració del compte" accountSettings: "Configuració del compte"
promotion: "Promocionat"
promote: "Promoure"
numberOfDays: "Nombre de dies"
hideThisNote: "Amaga la publicació" hideThisNote: "Amaga la publicació"
showFeaturedNotesInTimeline: "Mostra publicacions destacades en la línia de temps" showFeaturedNotesInTimeline: "Mostra publicacions destacades en la línia de temps"
objectStorage: "Emmagatzematge d'objectes\n"
useObjectStorage: "Utilitzar l'emmagatzematge d'objectes"
objectStorageBaseUrl: "Base d'enllaç"
objectStorageBaseUrlDesc: "Prefix d'enllaç utilitzat per a fer referencia als fitxers. Especifica l'enllaç del teu CDN o Proxy si n'estàs utilitzant qualsevol, en cas contrari, especifica l'enllaç al que es pot accedir públicament segons la guia de servei que vosté utilitza.\nPer l'ús d'S3 utilitza 'https://<bucket>.s3.amazonaws.com' I per a GCS o serveis equivalents utilitza 'https://storage.googleapis.com/<bucket>'."
newNoteRecived: "Hi ha publicacions noves" newNoteRecived: "Hi ha publicacions noves"
installedDate: "Data d'instal·lació" installedDate: "Data d'instal·lació"
state: "Estat" state: "Estat"
sort: "Ordena" sort: "Ordena"
ascendingOrder: "Ascendent" ascendingOrder: "Ascendent"
descendingOrder: "Descendent" descendingOrder: "Descendent"
removeAllFollowing: "Deixar de seguir tots els usuaris seguits"
removeAllFollowingDescription: "El fet d'executar això, et farà deixar de seguir a tots els usuaris de {host}. Si us plau, executa això si l'amfitrió, per exemple, ja no existeix."
userSuspended: "Aquest usuari ha sigut suspès"
userSilenced: "Aquest usuari està sent silenciat"
yourAccountSuspendedTitle: "Aquest compte és suspès"
yourAccountSuspendedDescription: "Aquest compte ha sigut suspès a causa de la violació de les condicions d'ús o similars. Contacta l'administrador si en vol saber més. Si us plau, no en faci un altre compte."
tokenRevoked: "Codi de seguretat no vàlid"
tokenRevokedDescription: "La petició més recent ha estat denegada perquè contenia un codi de seguretat no vàlid. Actualitza la pàgina i torna-ho a provar."
accountDeleted: "Compte eliminat amb èxit"
accountDeletedDescription: "Aquest compte ha sigut eliminat"
menu: "Menú"
divider: "Divisor"
addItem: "Afegir element"
rearrange: "Torna a ordenar"
relays: "Relés"
addRelay: "Afegeix relés"
inboxUrl: "Enllaç de la safata d'entrada"
addedRelays: "Relés afegits"
serviceworkerInfo: "És obligatòria l'activació per a obtenir notificacions push"
deletedNote: "Publicacions eliminades" deletedNote: "Publicacions eliminades"
invisibleNote: "Publicacions amagades" invisibleNote: "Publicacions amagades"
enableInfiniteScroll: "Carrega més automàticament\n"
visibility: "Visibilitat"
poll: "Enquesta"
useCw: "Amaga el contingut"
enablePlayer: "Obre el reproductor de vídeo"
disablePlayer: "Tanca el reproductor de vídeo"
expandTweet: "Expandir post"
themeEditor: "Editor de temes"
description: "Descripció"
describeFile: "Afegir subtitulació"
enterFileDescription: "Afegeix un títol"
author: "Autor"
leaveConfirm: "Hi ha canvis sense guardar. Els vols descartar?"
manage: "Administració"
plugins: "Extensions"
preferencesBackups: "Configuracions de les Còpies de seguretat"
deck: "Escriptori"
undeck: "Tanca l'escriptori"
useBlurEffectForModal: "Utilitzar l'efecte de difuminació a modals"
useFullReactionPicker: "Utilitza el cercador de reaccions d'escala sencera"
width: "Amplada"
height: "Alçària"
large: "Gran"
medium: "Mitjà"
small: "Petit"
generateAccessToken: "Genera codi d'accés"
permission: "Permisos"
enableAll: "Habilita tot"
disableAll: "Deshabilita tot"
tokenRequested: "Donar accés al compte"
smtpHost: "Amfitrió" smtpHost: "Amfitrió"
smtpUser: "Nom d'usuari" smtpUser: "Nom d'usuari"
smtpPass: "Contrasenya" smtpPass: "Contrasenya"
@ -390,12 +538,17 @@ clearCache: "Esborra la memòria cau"
showingPastTimeline: "Estàs veient una línia de temps antiga" showingPastTimeline: "Estàs veient una línia de temps antiga"
info: "Informació" info: "Informació"
user: "Usuaris" user: "Usuaris"
administration: "Administració"
middle: "Mitjà"
global: "Global" global: "Global"
searchByGoogle: "Cercar" searchByGoogle: "Cercar"
file: "Fitxers" file: "Fitxers"
icon: "Icona"
replies: "Respondre" replies: "Respondre"
renotes: "Impulsa" renotes: "Impulsa"
_role: _role:
_priority:
middle: "Mitjà"
_options: _options:
antennaMax: "Nombre màxim d'antenes" antennaMax: "Nombre màxim d'antenes"
_email: _email:
@ -404,9 +557,11 @@ _email:
_instanceMute: _instanceMute:
instanceMuteDescription: "Silencia tots els impulsos dels servidors seleccionats, també els usuaris que responen a altres d'un servidor silenciat." instanceMuteDescription: "Silencia tots els impulsos dels servidors seleccionats, també els usuaris que responen a altres d'un servidor silenciat."
_theme: _theme:
description: "Descripció"
keys: keys:
mention: "Menció" mention: "Menció"
renote: "Renotar" renote: "Renotar"
divider: "Divisor"
_sfx: _sfx:
note: "Notes" note: "Notes"
notification: "Notificacions" notification: "Notificacions"
@ -448,6 +603,8 @@ _timelines:
local: "Local" local: "Local"
social: "Social" social: "Social"
global: "Global" global: "Global"
_play:
summary: "Descripció"
_pages: _pages:
contents: "Contingut" contents: "Contingut"
blocks: blocks:

View File

@ -120,7 +120,6 @@ sensitive: "NSFW"
add: "Přidat" add: "Přidat"
reaction: "Reakce" reaction: "Reakce"
reactions: "Reakce" reactions: "Reakce"
reactionSetting: "Reakce zobrazené ve výběru reakcí"
reactionSettingDescription2: "Přetažením změníte pořadí, kliknutím smažete, zmáčkněte \"+\" k přidání" reactionSettingDescription2: "Přetažením změníte pořadí, kliknutím smažete, zmáčkněte \"+\" k přidání"
rememberNoteVisibility: "Zapamatovat nastavení zobrazení poznámky" rememberNoteVisibility: "Zapamatovat nastavení zobrazení poznámky"
attachCancel: "Odstranit přílohu" attachCancel: "Odstranit přílohu"
@ -855,8 +854,6 @@ makeReactionsPublicDescription: "Tohle zviditelný seznam vašich předchozích
classic: "Klasický" classic: "Klasický"
muteThread: "Ztlumit vlákno" muteThread: "Ztlumit vlákno"
unmuteThread: "Zrušit ztlumení vlákna" unmuteThread: "Zrušit ztlumení vlákna"
ffVisibility: "Viditelnost Sledovaných/Sledujících"
ffVisibilityDescription: "Umožní vám nastavit kdo uvidí koho sledujete a kdo vás sleduje."
continueThread: "Zobrazit pokračování vlákna" continueThread: "Zobrazit pokračování vlákna"
deleteAccountConfirm: "Tohle nenávratně smaže váš účet, chcete pokračovat?" deleteAccountConfirm: "Tohle nenávratně smaže váš účet, chcete pokračovat?"
incorrectPassword: "Nesprávné heslo." incorrectPassword: "Nesprávné heslo."

View File

@ -121,7 +121,6 @@ sensitive: "Sensibel"
add: "Hinzufügen" add: "Hinzufügen"
reaction: "Reaktionen" reaction: "Reaktionen"
reactions: "Reaktionen" reactions: "Reaktionen"
reactionSetting: "In der Reaktionsauswahl anzuzeigende Reaktionen"
reactionSettingDescription2: "Ziehe um Anzuordnen, klicke um zu löschen, drücke „+“ um hinzuzufügen" reactionSettingDescription2: "Ziehe um Anzuordnen, klicke um zu löschen, drücke „+“ um hinzuzufügen"
rememberNoteVisibility: "Notizsichtbarkeit merken" rememberNoteVisibility: "Notizsichtbarkeit merken"
attachCancel: "Anhang entfernen" attachCancel: "Anhang entfernen"
@ -874,8 +873,6 @@ makeReactionsPublicDescription: "Jeder wird die Liste deiner gesendeten Reaktion
classic: "Classic" classic: "Classic"
muteThread: "Thread stummschalten" muteThread: "Thread stummschalten"
unmuteThread: "Threadstummschaltung aufheben" unmuteThread: "Threadstummschaltung aufheben"
ffVisibility: "Sichtbarkeit von Gefolgten/Followern"
ffVisibilityDescription: "Konfiguriere wer sehen kann, wem du folgst sowie wer dir folgt."
continueThread: "Weiteren Threadverlauf anzeigen" continueThread: "Weiteren Threadverlauf anzeigen"
deleteAccountConfirm: "Dein Benutzerkonto wird unwiderruflich gelöscht. Trotzdem fortfahren?" deleteAccountConfirm: "Dein Benutzerkonto wird unwiderruflich gelöscht. Trotzdem fortfahren?"
incorrectPassword: "Falsches Passwort." incorrectPassword: "Falsches Passwort."

View File

@ -104,7 +104,6 @@ clickToShow: "Κάντε κλικ για εμφάνιση"
add: "Προσθέστε" add: "Προσθέστε"
reaction: "Αντιδράσεις" reaction: "Αντιδράσεις"
reactions: "Αντιδράσεις" reactions: "Αντιδράσεις"
reactionSetting: "Αντιδράσεις για εμφάνιση στην επιλογή αντίδρασης"
reactionSettingDescription2: "Σύρετε για να αλλάξετε τη σειρά, κάντε κλικ για να διαγράψετε, πατήστε \"+\" για να προσθέσετε." reactionSettingDescription2: "Σύρετε για να αλλάξετε τη σειρά, κάντε κλικ για να διαγράψετε, πατήστε \"+\" για να προσθέσετε."
rememberNoteVisibility: "Θυμήσου τις ρυθμίσεις ορατότητας σημειώματος" rememberNoteVisibility: "Θυμήσου τις ρυθμίσεις ορατότητας σημειώματος"
attachCancel: "Διαγραφή αρχείου" attachCancel: "Διαγραφή αρχείου"

View File

@ -121,7 +121,8 @@ sensitive: "Sensitive"
add: "Add" add: "Add"
reaction: "Reactions" reaction: "Reactions"
reactions: "Reactions" reactions: "Reactions"
reactionSetting: "Reactions to show in the reaction picker" emojiPicker: "Emoji picker"
emojiPickerDisplay: "Emoji picker display"
reactionSettingDescription2: "Drag to reorder, click to delete, press \"+\" to add." reactionSettingDescription2: "Drag to reorder, click to delete, press \"+\" to add."
rememberNoteVisibility: "Remember note visibility settings" rememberNoteVisibility: "Remember note visibility settings"
attachCancel: "Remove attachment" attachCancel: "Remove attachment"
@ -261,6 +262,7 @@ removed: "Successfully deleted"
removeAreYouSure: "Are you sure that you want to remove \"{x}\"?" removeAreYouSure: "Are you sure that you want to remove \"{x}\"?"
deleteAreYouSure: "Are you sure that you want to delete \"{x}\"?" deleteAreYouSure: "Are you sure that you want to delete \"{x}\"?"
resetAreYouSure: "Really reset?" resetAreYouSure: "Really reset?"
areYouSure: "Are you sure?"
saved: "Saved" saved: "Saved"
messaging: "Chat" messaging: "Chat"
upload: "Upload" upload: "Upload"
@ -544,7 +546,7 @@ showInPage: "Show in page"
popout: "Pop-out" popout: "Pop-out"
volume: "Volume" volume: "Volume"
masterVolume: "Master volume" masterVolume: "Master volume"
notUseSound: "No sounds output." notUseSound: "Disable sound"
useSoundOnlyWhenActive: "Output sounds only if Misskey is active." useSoundOnlyWhenActive: "Output sounds only if Misskey is active."
details: "Details" details: "Details"
chooseEmoji: "Select an emoji" chooseEmoji: "Select an emoji"
@ -875,8 +877,8 @@ makeReactionsPublicDescription: "This will make the list of all your past reacti
classic: "Classic" classic: "Classic"
muteThread: "Mute thread" muteThread: "Mute thread"
unmuteThread: "Unmute thread" unmuteThread: "Unmute thread"
ffVisibility: "Follows/Followers Visibility" followingVisibility: "Visibility of follows"
ffVisibilityDescription: "Allows you to configure who can see who you follow and who follows you." followersVisibility: "Visibility of followers"
continueThread: "View thread continuation" continueThread: "View thread continuation"
deleteAccountConfirm: "This will irreversibly delete your account. Proceed?" deleteAccountConfirm: "This will irreversibly delete your account. Proceed?"
incorrectPassword: "Incorrect password." incorrectPassword: "Incorrect password."
@ -1170,6 +1172,7 @@ cwNotationRequired: "If \"Hide content\" is enabled, a description must be provi
doReaction: "Add reaction" doReaction: "Add reaction"
code: "Code" code: "Code"
reloadRequiredToApplySettings: "Reloading is required to apply the settings." reloadRequiredToApplySettings: "Reloading is required to apply the settings."
decorate: "Decorate"
_announcement: _announcement:
forExistingUsers: "Existing users only" forExistingUsers: "Existing users only"
forExistingUsersDescription: "This announcement will only be shown to users existing at the point of publishment if enabled. If disabled, those newly signing up after it has been posted will also see it." forExistingUsersDescription: "This announcement will only be shown to users existing at the point of publishment if enabled. If disabled, those newly signing up after it has been posted will also see it."
@ -1259,7 +1262,7 @@ _initialTutorial:
sensitiveSucceeded: "When attaching files, please set sensitivities in accordance with the server guidelines." sensitiveSucceeded: "When attaching files, please set sensitivities in accordance with the server guidelines."
doItToContinue: "Mark the attachment file as sensitive to proceed." doItToContinue: "Mark the attachment file as sensitive to proceed."
_done: _done:
title: "The tutorial is complete! 🎉" title: "You've completed the tutorial! 🎉"
description: "The functions introduced here are just a small part. For a more detailed understanding of using Misskey, please refer to {link}." description: "The functions introduced here are just a small part. For a more detailed understanding of using Misskey, please refer to {link}."
_timelineDescription: _timelineDescription:
home: "In the Home timeline, you can see notes from accounts you follow." home: "In the Home timeline, you can see notes from accounts you follow."
@ -1974,6 +1977,7 @@ _widgets:
_userList: _userList:
chooseList: "Select a list" chooseList: "Select a list"
clicker: "Clicker" clicker: "Clicker"
birthdayFollowings: "Users who celebrate their birthday today"
_cw: _cw:
hide: "Hide" hide: "Hide"
show: "Show content" show: "Show content"
@ -2157,6 +2161,7 @@ _notification:
pollEnded: "Poll results have become available" pollEnded: "Poll results have become available"
newNote: "New note" newNote: "New note"
unreadAntennaNote: "Antenna {name}" unreadAntennaNote: "Antenna {name}"
roleAssigned: "Role given"
emptyPushNotificationMessage: "Push notifications have been updated" emptyPushNotificationMessage: "Push notifications have been updated"
achievementEarned: "Achievement unlocked" achievementEarned: "Achievement unlocked"
testNotification: "Test notification" testNotification: "Test notification"
@ -2178,6 +2183,7 @@ _notification:
pollEnded: "Polls ending" pollEnded: "Polls ending"
receiveFollowRequest: "Received follow requests" receiveFollowRequest: "Received follow requests"
followRequestAccepted: "Accepted follow requests" followRequestAccepted: "Accepted follow requests"
roleAssigned: "Role given"
achievementEarned: "Achievement unlocked" achievementEarned: "Achievement unlocked"
app: "Notifications from linked apps" app: "Notifications from linked apps"
_actions: _actions:
@ -2329,6 +2335,8 @@ _dataSaver:
_avatar: _avatar:
title: "Avatar image" title: "Avatar image"
description: "Stop avatar image animation. Animated images can be larger in file size than normal images, potentially leading to further reductions in data traffic." description: "Stop avatar image animation. Animated images can be larger in file size than normal images, potentially leading to further reductions in data traffic."
_urlPreview:
title: "URL preview thumbnails"
_code: _code:
title: "Code highlighting" title: "Code highlighting"
description: "If code highlighting notations are used in MFM, etc., they will not load until tapped. Syntax highlighting requires downloading the highlight definition files for each programming language. Therefore, disabling the automatic loading of these files is expected to reduce the amount of communication data." description: "If code highlighting notations are used in MFM, etc., they will not load until tapped. Syntax highlighting requires downloading the highlight definition files for each programming language. Therefore, disabling the automatic loading of these files is expected to reduce the amount of communication data."

View File

@ -121,7 +121,12 @@ sensitive: "Marcado como sensible"
add: "Agregar" add: "Agregar"
reaction: "Reacción" reaction: "Reacción"
reactions: "Reacción" reactions: "Reacción"
reactionSetting: "Reacciones para mostrar en el menú de reacciones" emojiPicker: "Selector de emojis"
pinnedEmojisForReactionSettingDescription: "Puedes seleccionar reacciones para fijarlos en el selector"
pinnedEmojisSettingDescription: "Puedes seleccionar emojis para fijarlos en el selector"
emojiPickerDisplay: "Mostrar el selector de emojis"
overwriteFromPinnedEmojisForReaction: "Sobreescribir las reacciones fijadas"
overwriteFromPinnedEmojis: "Sobreescribir los emojis fijados"
reactionSettingDescription2: "Arrastre para reordenar, click para borrar, apriete la tecla + para añadir." reactionSettingDescription2: "Arrastre para reordenar, click para borrar, apriete la tecla + para añadir."
rememberNoteVisibility: "Recordar visibilidad" rememberNoteVisibility: "Recordar visibilidad"
attachCancel: "Quitar adjunto" attachCancel: "Quitar adjunto"
@ -261,6 +266,7 @@ removed: "Borrado"
removeAreYouSure: "¿Desea borrar \"{x}\"?" removeAreYouSure: "¿Desea borrar \"{x}\"?"
deleteAreYouSure: "¿Desea borrar \"{x}\"?" deleteAreYouSure: "¿Desea borrar \"{x}\"?"
resetAreYouSure: "¿Desea reestablecer?" resetAreYouSure: "¿Desea reestablecer?"
areYouSure: "¿Estás conforme?"
saved: "Guardado" saved: "Guardado"
messaging: "Chat" messaging: "Chat"
upload: "Subir" upload: "Subir"
@ -641,6 +647,7 @@ smtpSecure: "Usar SSL/TLS implícito en la conexión SMTP"
smtpSecureInfo: "Apagar cuando se use STARTTLS" smtpSecureInfo: "Apagar cuando se use STARTTLS"
testEmail: "Prueba de envío" testEmail: "Prueba de envío"
wordMute: "Silenciar palabras" wordMute: "Silenciar palabras"
hardWordMute: "Filtro de palabra fuerte"
regexpError: "Error de la expresión regular" regexpError: "Error de la expresión regular"
regexpErrorDescription: "Ocurrió un error en la expresión regular en la linea {line} de las palabras muteadas {tab}" regexpErrorDescription: "Ocurrió un error en la expresión regular en la linea {line} de las palabras muteadas {tab}"
instanceMute: "Instancias silenciadas" instanceMute: "Instancias silenciadas"
@ -874,8 +881,8 @@ makeReactionsPublicDescription: "Todas las reacciones que hayas hecho serán pú
classic: "Clásico" classic: "Clásico"
muteThread: "Silenciar hilo" muteThread: "Silenciar hilo"
unmuteThread: "Mostrar hilo" unmuteThread: "Mostrar hilo"
ffVisibility: "Visibilidad de seguidores y seguidos" followingVisibility: "Visibilidad de seguidos"
ffVisibilityDescription: "Puedes configurar quien puede ver a quienes sigues y quienes te siguen" followersVisibility: "Visibilidad de seguidores"
continueThread: "Ver la continuación del hilo" continueThread: "Ver la continuación del hilo"
deleteAccountConfirm: "La cuenta será borrada. ¿Está seguro?" deleteAccountConfirm: "La cuenta será borrada. ¿Está seguro?"
incorrectPassword: "La contraseña es incorrecta" incorrectPassword: "La contraseña es incorrecta"
@ -1027,6 +1034,7 @@ sensitiveWords: "Palabras sensibles"
sensitiveWordsDescription: "La visibilidad de todas las notas que contienen cualquiera de las palabras configuradas serán puestas en \"Inicio\" automáticamente. Puedes enumerás varias separándolas con saltos de línea" sensitiveWordsDescription: "La visibilidad de todas las notas que contienen cualquiera de las palabras configuradas serán puestas en \"Inicio\" automáticamente. Puedes enumerás varias separándolas con saltos de línea"
sensitiveWordsDescription2: "Si se usan espacios se crearán expresiones AND y las palabras subsecuentes con barras inclinadas se convertirán en expresiones regulares." sensitiveWordsDescription2: "Si se usan espacios se crearán expresiones AND y las palabras subsecuentes con barras inclinadas se convertirán en expresiones regulares."
hiddenTags: "Hashtags ocultos" hiddenTags: "Hashtags ocultos"
hiddenTagsDescription: "Selecciona las etiquetas que no se mostrarán en tendencias. Una etiqueta por línea."
notesSearchNotAvailable: "No se puede buscar una nota" notesSearchNotAvailable: "No se puede buscar una nota"
license: "Licencia" license: "Licencia"
unfavoriteConfirm: "¿Desea quitar de favoritos?" unfavoriteConfirm: "¿Desea quitar de favoritos?"
@ -1155,6 +1163,7 @@ tosAndPrivacyPolicy: "Condiciones de Uso y Política de Privacidad"
avatarDecorations: "Decoraciones de avatar" avatarDecorations: "Decoraciones de avatar"
attach: "Acoplar" attach: "Acoplar"
detach: "Quitar" detach: "Quitar"
detachAll: "Quitar todo"
angle: "Ángulo" angle: "Ángulo"
flip: "Echar de un capirotazo" flip: "Echar de un capirotazo"
showAvatarDecorations: "Mostrar decoraciones de avatar" showAvatarDecorations: "Mostrar decoraciones de avatar"
@ -1168,6 +1177,10 @@ cwNotationRequired: "Si se ha activado \"ocultar contenido\", es necesario propo
doReaction: "Añadir reacción" doReaction: "Añadir reacción"
code: "Código" code: "Código"
reloadRequiredToApplySettings: "Es necesario recargar para que se aplique la configuración." reloadRequiredToApplySettings: "Es necesario recargar para que se aplique la configuración."
remainingN: "Faltan: {n}"
overwriteContentConfirm: "¿Quieres sustituir todo el contenido actual?"
seasonalScreenEffect: "Efectos de pantalla asociados a estaciones"
decorate: "Decorar"
_announcement: _announcement:
forExistingUsers: "Solo para usuarios registrados" forExistingUsers: "Solo para usuarios registrados"
forExistingUsersDescription: "Este anuncio solo se mostrará a aquellos usuarios registrados en el momento de su publicación. Si se deshabilita esta opción, aquellos usuarios que se registren tras su publicación también lo verán." forExistingUsersDescription: "Este anuncio solo se mostrará a aquellos usuarios registrados en el momento de su publicación. Si se deshabilita esta opción, aquellos usuarios que se registren tras su publicación también lo verán."
@ -1225,6 +1238,45 @@ _initialTutorial:
home: "Puedes ver los posts de las cuentas que sigues." home: "Puedes ver los posts de las cuentas que sigues."
local: "Puedes ver los posts de todos los usuarios de este servidor." local: "Puedes ver los posts de todos los usuarios de este servidor."
social: "Se ven los posts de la línea de tiempo de inicio junto con los de la línea de tiempo local." social: "Se ven los posts de la línea de tiempo de inicio junto con los de la línea de tiempo local."
global: "Puedes ver notas de todos los servidores conectados."
description2: "Puedes cambiar la línea de tiempo en la parte superior de la pantalla cuando quieras."
description3: "Además, hay listas de líneas de tiempo y listas de canales. Para más detalle, por favor visita este enlace: {link}"
_postNote:
title: "Ajustes de publicación de nota"
description1: "Cuando publicas una nota en Misskey, hay varias opciones disponibles. El formulario tiene este aspecto."
_visibility:
description: "Puedes limitar quién puede ver tu nota."
public: "Tu nota será visible para todos los usuarios."
home: "Publicar solo en la línea de tiempo de Inicio. La nota se verá en tu perfil, la verán tus seguidores y también cuando sea renotada."
followers: "Visible solo para seguidores. Sólo tus seguidores podrán ver la nota, y no podrá ser renotada por otras personas."
direct: "Visible sólo para usuarios específicos, y el destinatario será notificado. Puede usarse como alternativa a la mensajería directa."
doNotSendConfidencialOnDirect1: "¡Ten cuidado cuando vayas a enviar información sensible!"
doNotSendConfidencialOnDirect2: "Los administradores del servidor pueden leer lo que escribes. Ten cuidado cuando envíes información sensible en notas directas en servidores no confiables."
localOnly: "Publicando con esta opción seleccionada, la nota no se federará hacia otros servidores. Los usuarios de otros servidores no podrán ver estas notas directamente, sin importar los ajustes seleccionados más arriba."
_cw:
title: "Alerta de contenido (CW)"
description: "En lugar de mostrarse el contenido de la nota, se mostrará lo que escribas en el campo \"comentarios\". Pulsando en \"leer más\" desplegará el contenido de la nota."
_exampleNote:
cw: "¡Esto te hará tener hambre!"
note: "Acabo de comerme un donut de chocolate glaseado 🍩😋"
useCases: "Esto se usa cuando las normas del servidor lo requieren, o para ocultar spoilers o contenido sensible."
_howToMakeAttachmentsSensitive:
title: "¿Cómo puedo marcar adjuntos como contenido sensible?"
description: "Cuando las normas del servidor lo requieran, o el contenido lo requiera, marca la opción de \"contenido sensible\" para el adjunto."
tryThisFile: "¡Prueba a marcar la imagen adjunta como contenido sensible!"
_exampleNote:
note: "Ups, la he liado al abrir la tapa del natto..."
method: "Para marcar un adjunto como sensible, haz clic en la miniatura, abre el menú, y haz clic en \"Marcar como sensible\"."
sensitiveSucceeded: "Cuando adjuntes archivos, por favor, ten en cuenta las normas del servidor para marcarlos como contenido sensible."
doItToContinue: "Marca el archivo adjunto como sensible para continuar."
_done:
title: "¡Has completado el tutorial! 🎉"
description: "Las funciones que mostramos aquí son sólo una pequeña parte. Para más detalles sobre el funcionamiento de Misskey, pulsa en este enlace: {link}"
_timelineDescription:
home: "En la línea de tiempo de Inicio puedes ver las notas de las cuentas a las que sigues."
local: "En la línea de tiempo Local puedes ver las notas de todos los usuarios del servidor."
social: "En la línea de tiempo Social verás las notas de Inicio y Local a la vez."
global: "En la línea de tiempo Global verás las notas de todos los servidores conectados."
_serverRules: _serverRules:
description: "Un conjunto de reglas que serán mostradas antes del registro. Configurar un sumario de términos de servicio es recomendado." description: "Un conjunto de reglas que serán mostradas antes del registro. Configurar un sumario de términos de servicio es recomendado."
_serverSettings: _serverSettings:
@ -1236,6 +1288,9 @@ _serverSettings:
manifestJsonOverride: "Sobreescribir manifest.json" manifestJsonOverride: "Sobreescribir manifest.json"
shortName: "Nombre corto" shortName: "Nombre corto"
shortNameDescription: "Forma corta del nombre de la instancia que puede mostrarse si el nombre completo es demasiado largo." shortNameDescription: "Forma corta del nombre de la instancia que puede mostrarse si el nombre completo es demasiado largo."
fanoutTimelineDescription: "Incrementa el rendimiento de forma significativa cuando se obtienen las líneas de tiempo y reduce la carga en la base de datos. A cambio, el uso de la memoria en Redis incrementará. Considera desactivar esta opción en caso de que tu servidor tenga poca memoria o detectes inestabilidad."
fanoutTimelineDbFallback: "Cargar desde la base de datos"
fanoutTimelineDbFallbackDescription: "Cuando esta opción está habilitada, la carga de peticiones adicionales de la línea de tiempo se hará desde la base de datos cuando éstas no se encuentren en la caché. Al deshabilitar esta opción se reduce la carga del servidor, pero limita el número de líneas de tiempo que pueden obtenerse."
_accountMigration: _accountMigration:
moveFrom: "Trasladar de otra cuenta a ésta" moveFrom: "Trasladar de otra cuenta a ésta"
moveFromSub: "Crear un alias para otra cuenta." moveFromSub: "Crear un alias para otra cuenta."
@ -1493,6 +1548,9 @@ _achievements:
_smashTestNotificationButton: _smashTestNotificationButton:
title: "Sobrecarga de pruebas" title: "Sobrecarga de pruebas"
description: "Envía muchas notificaciones de prueba en un corto espacio de tiempo" description: "Envía muchas notificaciones de prueba en un corto espacio de tiempo"
_tutorialCompleted:
title: "Diploma del Curso Básico de Misskey"
description: "Tutorial completado"
_role: _role:
new: "Crear rol" new: "Crear rol"
edit: "Editar rol" edit: "Editar rol"
@ -1503,7 +1561,9 @@ _role:
assignTarget: "Asignar objetivo" assignTarget: "Asignar objetivo"
descriptionOfAssignTarget: "<b>Manual</b> Para cambiar manualmente lo que se incluye en este rol.\n<b>Condicional</b> configura una condición, y los usuarios que cumplan la condición serán incluídos automáticamente." descriptionOfAssignTarget: "<b>Manual</b> Para cambiar manualmente lo que se incluye en este rol.\n<b>Condicional</b> configura una condición, y los usuarios que cumplan la condición serán incluídos automáticamente."
manual: "manual" manual: "manual"
manualRoles: "Roles manuales"
conditional: "condicional" conditional: "condicional"
conditionalRoles: "Roles condicionales"
condition: "condición" condition: "condición"
isConditionalRole: "Esto es un rol condicional" isConditionalRole: "Esto es un rol condicional"
isPublic: "Publicar rol" isPublic: "Publicar rol"
@ -1552,6 +1612,7 @@ _role:
canHideAds: "Puede ocultar anuncios" canHideAds: "Puede ocultar anuncios"
canSearchNotes: "Uso de la búsqueda de notas" canSearchNotes: "Uso de la búsqueda de notas"
canUseTranslator: "Uso de traductor" canUseTranslator: "Uso de traductor"
avatarDecorationLimit: "Número máximo de decoraciones de avatar"
_condition: _condition:
isLocal: "Usuario local" isLocal: "Usuario local"
isRemote: "Usuario remoto" isRemote: "Usuario remoto"
@ -1580,6 +1641,7 @@ _emailUnavailable:
disposable: "No es un correo reutilizable" disposable: "No es un correo reutilizable"
mx: "Servidor de correo inválido" mx: "Servidor de correo inválido"
smtp: "Servidor de correo no disponible" smtp: "Servidor de correo no disponible"
banned: "Email no disponible"
_ffVisibility: _ffVisibility:
public: "Publicar" public: "Publicar"
followers: "Visible solo para seguidores" followers: "Visible solo para seguidores"
@ -1656,6 +1718,7 @@ _aboutMisskey:
donate: "Donar a Misskey" donate: "Donar a Misskey"
morePatrons: "Muchas más personas nos apoyan. Muchas gracias🥰" morePatrons: "Muchas más personas nos apoyan. Muchas gracias🥰"
patrons: "Patrocinadores" patrons: "Patrocinadores"
projectMembers: "Miembros del proyecto"
_displayOfSensitiveMedia: _displayOfSensitiveMedia:
respect: "Esconder medios marcados como sensibles" respect: "Esconder medios marcados como sensibles"
ignore: "Mostrar medios marcados como sensibles" ignore: "Mostrar medios marcados como sensibles"
@ -1680,6 +1743,7 @@ _channel:
notesCount: "{n} notas" notesCount: "{n} notas"
nameAndDescription: "Nombre y descripción" nameAndDescription: "Nombre y descripción"
nameOnly: "Sólo nombre" nameOnly: "Sólo nombre"
allowRenoteToExternal: "Permitir renotas y menciones fuera del canal"
_menuDisplay: _menuDisplay:
sideFull: "Horizontal" sideFull: "Horizontal"
sideIcon: "Horizontal (ícono)" sideIcon: "Horizontal (ícono)"
@ -1771,6 +1835,14 @@ _sfx:
notification: "Notificaciones" notification: "Notificaciones"
antenna: "Antena receptora" antenna: "Antena receptora"
channel: "Notificaciones del canal" channel: "Notificaciones del canal"
reaction: "Al seleccionar una reacción"
_soundSettings:
driveFile: "Usar un archivo de audio en Drive"
driveFileWarn: "Selecciona un archivo de audio en Drive."
driveFileTypeWarn: "Este archivo es incompatible"
driveFileTypeWarnDescription: "Selecciona un archivo de audio"
driveFileDurationWarn: "La duración del audio es demasiado larga."
driveFileDurationWarnDescription: "Usar un audio de larga duración puede llegar a molestar mientras usas Misskey. ¿Quieres continuar?"
_ago: _ago:
future: "Futuro" future: "Futuro"
justNow: "Justo ahora" justNow: "Justo ahora"
@ -1783,6 +1855,12 @@ _ago:
yearsAgo: "Hace {n} años" yearsAgo: "Hace {n} años"
invalid: "No hay nada que ver aqui" invalid: "No hay nada que ver aqui"
_timeIn: _timeIn:
seconds: "En {n} segundos"
minutes: "En {n}m"
hours: "En {n}h"
days: "En {n}d"
weeks: "En {n}sem."
months: "En {n}M"
years: "En {n} años" years: "En {n} años"
_time: _time:
second: "Segundos" second: "Segundos"
@ -1909,6 +1987,7 @@ _widgets:
_userList: _userList:
chooseList: "Seleccione una lista" chooseList: "Seleccione una lista"
clicker: "Cliqueador" clicker: "Cliqueador"
birthdayFollowings: "Hoy cumplen años"
_cw: _cw:
hide: "Ocultar" hide: "Ocultar"
show: "Ver más" show: "Ver más"
@ -1971,6 +2050,7 @@ _profile:
changeAvatar: "Cambiar avatar" changeAvatar: "Cambiar avatar"
changeBanner: "Cambiar banner" changeBanner: "Cambiar banner"
verifiedLinkDescription: "Introduciendo una URL que contiene un enlace a tu perfil, se puede mostrar un icono de verificación de propiedad al lado del campo." verifiedLinkDescription: "Introduciendo una URL que contiene un enlace a tu perfil, se puede mostrar un icono de verificación de propiedad al lado del campo."
avatarDecorationMax: "Puedes añadir un máximo de {max} decoraciones de avatar."
_exportOrImport: _exportOrImport:
allNotes: "Todas las notas" allNotes: "Todas las notas"
favoritedNotes: "Notas favoritas" favoritedNotes: "Notas favoritas"
@ -2092,6 +2172,7 @@ _notification:
pollEnded: "Estan disponibles los resultados de la encuesta" pollEnded: "Estan disponibles los resultados de la encuesta"
newNote: "Nueva nota" newNote: "Nueva nota"
unreadAntennaNote: "Antena {name}" unreadAntennaNote: "Antena {name}"
roleAssigned: "Rol asignado"
emptyPushNotificationMessage: "Se han actualizado las notificaciones push" emptyPushNotificationMessage: "Se han actualizado las notificaciones push"
achievementEarned: "Logro desbloqueado" achievementEarned: "Logro desbloqueado"
testNotification: "Notificación de prueba" testNotification: "Notificación de prueba"
@ -2113,6 +2194,7 @@ _notification:
pollEnded: "La encuesta terminó" pollEnded: "La encuesta terminó"
receiveFollowRequest: "Recibió una solicitud de seguimiento" receiveFollowRequest: "Recibió una solicitud de seguimiento"
followRequestAccepted: "El seguimiento fue aceptado" followRequestAccepted: "El seguimiento fue aceptado"
roleAssigned: "Rol asignado"
achievementEarned: "Logro desbloqueado" achievementEarned: "Logro desbloqueado"
app: "Notificaciones desde aplicaciones" app: "Notificaciones desde aplicaciones"
_actions: _actions:
@ -2258,3 +2340,16 @@ _externalResourceInstaller:
_themeInstallFailed: _themeInstallFailed:
title: "Instalación de tema fallida" title: "Instalación de tema fallida"
description: "Ha ocurrido un problema al instalar el tema. Por favor, inténtalo de nuevo. Se pueden ver más detalles del error en la consola de Javascript." description: "Ha ocurrido un problema al instalar el tema. Por favor, inténtalo de nuevo. Se pueden ver más detalles del error en la consola de Javascript."
_dataSaver:
_media:
title: "Cargando Multimedia"
description: "Desactiva la carga automática de imágenes y vídeos. Tendrás que tocar en las imágenes y vídeos ocultos para cargarlos."
_avatar:
title: "Avatares animados"
description: "Desactiva la animación de los avatares. Las imágenes animadas pueden llegar a ser de mayor tamaño que las normales, por lo que al desactivarlas puedes reducir el consumo de datos."
_urlPreview:
title: "Vista previa de URLs"
description: "Desactiva la carga de vistas previas de las URLs."
_code:
title: "Resaltar código"
description: "Si se usa resaltado de código en MFM, etc., no se cargará hasta pulsar en ello. El resaltado de sintaxis requiere la descarga de archivos de definición para cada lenguaje de programación. Debido a esto, al deshabilitar la carga automática de estos archivos reducirás el consumo de datos."

View File

@ -121,7 +121,12 @@ sensitive: "Contenu sensible"
add: "Ajouter" add: "Ajouter"
reaction: "Réactions" reaction: "Réactions"
reactions: "Réactions" reactions: "Réactions"
reactionSetting: "Réactions à afficher dans le sélecteur de réactions" emojiPicker: "Sélecteur démojis"
pinnedEmojisForReactionSettingDescription: "Vous pouvez définir les émojis épinglés lors de la réaction"
pinnedEmojisSettingDescription: "Vous pouvez définir les émojis épinglés lors de la saisie de l'émoji"
emojiPickerDisplay: "Affichage du sélecteur d'émojis"
overwriteFromPinnedEmojisForReaction: "Remplacer par les émojis épinglés pour la réaction"
overwriteFromPinnedEmojis: "Remplacer par les émojis épinglés globalement"
reactionSettingDescription2: "Déplacer pour réorganiser, cliquer pour effacer, utiliser « + » pour ajouter." reactionSettingDescription2: "Déplacer pour réorganiser, cliquer pour effacer, utiliser « + » pour ajouter."
rememberNoteVisibility: "Se souvenir de la visibilité des notes" rememberNoteVisibility: "Se souvenir de la visibilité des notes"
attachCancel: "Supprimer le fichier attaché" attachCancel: "Supprimer le fichier attaché"
@ -157,6 +162,7 @@ addEmoji: "Ajouter un émoji"
settingGuide: "Configuration proposée" settingGuide: "Configuration proposée"
cacheRemoteFiles: "Mise en cache des fichiers distants" cacheRemoteFiles: "Mise en cache des fichiers distants"
cacheRemoteFilesDescription: "Lorsque cette option est désactivée, les fichiers distants sont chargés directement depuis linstance distante. La désactiver diminuera certes lutilisation de lespace de stockage local mais augmentera le trafic réseau puisque les miniatures ne seront plus générées." cacheRemoteFilesDescription: "Lorsque cette option est désactivée, les fichiers distants sont chargés directement depuis linstance distante. La désactiver diminuera certes lutilisation de lespace de stockage local mais augmentera le trafic réseau puisque les miniatures ne seront plus générées."
youCanCleanRemoteFilesCache: "Vous pouvez supprimer tous les caches en cliquant le bouton 🗑️ dans la gestion des fichiers."
cacheRemoteSensitiveFiles: "Mettre en cache les fichiers distants sensibles" cacheRemoteSensitiveFiles: "Mettre en cache les fichiers distants sensibles"
cacheRemoteSensitiveFilesDescription: "Si vous désactivez ce paramètre, les fichiers sensibles distants ne seront pas mis en cache et un lien direct sera utilisé à la place" cacheRemoteSensitiveFilesDescription: "Si vous désactivez ce paramètre, les fichiers sensibles distants ne seront pas mis en cache et un lien direct sera utilisé à la place"
flagAsBot: "Ce compte est un robot" flagAsBot: "Ce compte est un robot"
@ -721,6 +727,7 @@ lockedAccountInfo: "À moins que vous ne définissiez la visibilité de votre no
alwaysMarkSensitive: "Marquer les médias comme contenu sensible par défaut" alwaysMarkSensitive: "Marquer les médias comme contenu sensible par défaut"
loadRawImages: "Affichage complet des images jointes au lieu des vignettes" loadRawImages: "Affichage complet des images jointes au lieu des vignettes"
disableShowingAnimatedImages: "Désactiver l'animation des images" disableShowingAnimatedImages: "Désactiver l'animation des images"
highlightSensitiveMedia: "Mettre en évidence les médias sensibles"
verificationEmailSent: "Un e-mail de vérification a été envoyé. Veuillez accéder au lien pour compléter la vérification." verificationEmailSent: "Un e-mail de vérification a été envoyé. Veuillez accéder au lien pour compléter la vérification."
notSet: "Non défini" notSet: "Non défini"
emailVerified: "Votre adresse e-mail a été vérifiée." emailVerified: "Votre adresse e-mail a été vérifiée."
@ -873,8 +880,8 @@ makeReactionsPublicDescription: "Ceci rendra la liste de toutes vos réactions d
classic: "Classique" classic: "Classique"
muteThread: "Masquer cette discussion" muteThread: "Masquer cette discussion"
unmuteThread: "Ne plus masquer le fil" unmuteThread: "Ne plus masquer le fil"
ffVisibility: "Visibilité des abonnés/abonnements" followingVisibility: "Visibilité des abonnements"
ffVisibilityDescription: "Permet de configurer qui peut voir les personnes que tu suis et les personnes qui te suivent." followersVisibility: "Visibilité des abonnés"
continueThread: "Afficher la suite du fil" continueThread: "Afficher la suite du fil"
deleteAccountConfirm: "Votre compte sera supprimé. Êtes vous certain ?" deleteAccountConfirm: "Votre compte sera supprimé. Êtes vous certain ?"
incorrectPassword: "Le mot de passe est incorrect." incorrectPassword: "Le mot de passe est incorrect."
@ -974,6 +981,7 @@ show: "Affichage"
neverShow: "Ne plus afficher" neverShow: "Ne plus afficher"
remindMeLater: "Peut-être plus tard" remindMeLater: "Peut-être plus tard"
didYouLikeMisskey: "Avez-vous aimé Misskey ?" didYouLikeMisskey: "Avez-vous aimé Misskey ?"
pleaseDonate: "Misskey est le logiciel libre utilisé par {host}. Merci de faire un don pour que nous puissions continuer à le développer !"
roles: "Rôles" roles: "Rôles"
role: "Rôles" role: "Rôles"
noRole: "Aucun rôle" noRole: "Aucun rôle"
@ -986,8 +994,10 @@ manageCustomEmojis: "Gestion des émojis personnalisés"
manageAvatarDecorations: "Gérer les décorations d'avatar" manageAvatarDecorations: "Gérer les décorations d'avatar"
youCannotCreateAnymore: "Vous avez atteint la limite de création." youCannotCreateAnymore: "Vous avez atteint la limite de création."
cannotPerformTemporary: "Temporairement indisponible" cannotPerformTemporary: "Temporairement indisponible"
cannotPerformTemporaryDescription: "Temporairement indisponible puisque le nombre d'opérations dépasse la limite. Veuillez patienter un peu, puis réessayer."
invalidParamError: "Paramètres invalides" invalidParamError: "Paramètres invalides"
permissionDeniedError: "Opération refusée" permissionDeniedError: "Opération refusée"
permissionDeniedErrorDescription: "Ce compte n'a pas la permission d'effectuer cette opération."
preset: "Préréglage" preset: "Préréglage"
selectFromPresets: "Sélectionner à partir des préréglages" selectFromPresets: "Sélectionner à partir des préréglages"
achievements: "Accomplissements" achievements: "Accomplissements"
@ -1016,6 +1026,7 @@ likeOnlyForRemote: "Toutes (mentions j'aime seulement pour les instances distant
nonSensitiveOnly: "Non sensibles seulement" nonSensitiveOnly: "Non sensibles seulement"
nonSensitiveOnlyForLocalLikeOnlyForRemote: "Non sensibles seulement (mentions j'aime seulement pour les instances distantes)" nonSensitiveOnlyForLocalLikeOnlyForRemote: "Non sensibles seulement (mentions j'aime seulement pour les instances distantes)"
rolesAssignedToMe: "Rôles attribués à moi" rolesAssignedToMe: "Rôles attribués à moi"
resetPasswordConfirm: "Souhaitez-vous réinitialiser votre mot de passe ?"
sensitiveWords: "Mots sensibles" sensitiveWords: "Mots sensibles"
hiddenTags: "Hashtags cachés" hiddenTags: "Hashtags cachés"
hiddenTagsDescription: "Les hashtags définis ne s'afficheront pas dans les tendances. Vous pouvez définir plusieurs hashtags en faisant un saut de ligne." hiddenTagsDescription: "Les hashtags définis ne s'afficheront pas dans les tendances. Vous pouvez définir plusieurs hashtags en faisant un saut de ligne."
@ -1024,6 +1035,8 @@ license: "Licence"
myClips: "Mes clips" myClips: "Mes clips"
drivecleaner: "Nettoyeur du Disque" drivecleaner: "Nettoyeur du Disque"
retryAllQueuesConfirmText: "Cela peut augmenter temporairement la charge du serveur." retryAllQueuesConfirmText: "Cela peut augmenter temporairement la charge du serveur."
enableChartsForRemoteUser: "Générer les graphiques pour les utilisateurs distants"
enableChartsForFederatedInstances: "Générer les graphiques pour les instances distantes"
showClipButtonInNoteFooter: "Ajouter « Clip » au menu d'action de la note" showClipButtonInNoteFooter: "Ajouter « Clip » au menu d'action de la note"
reactionsDisplaySize: "Taille de l'affichage des réactions" reactionsDisplaySize: "Taille de l'affichage des réactions"
limitWidthOfReaction: "Limiter la largeur maximale des réactions et les afficher en taille réduite" limitWidthOfReaction: "Limiter la largeur maximale des réactions et les afficher en taille réduite"
@ -1067,6 +1080,7 @@ options: "Options"
specifyUser: "Spécifier l'utilisateur·rice" specifyUser: "Spécifier l'utilisateur·rice"
failedToPreviewUrl: "Aperçu d'URL échoué" failedToPreviewUrl: "Aperçu d'URL échoué"
update: "Mettre à jour" update: "Mettre à jour"
rolesThatCanBeUsedThisEmojiAsReaction: "Rôles qui peuvent utiliser cet émoji comme réaction"
later: "Plus tard" later: "Plus tard"
goToMisskey: "Retour vers Misskey" goToMisskey: "Retour vers Misskey"
additionalEmojiDictionary: "Dictionnaires d'émojis additionnels" additionalEmojiDictionary: "Dictionnaires d'émojis additionnels"
@ -1074,6 +1088,7 @@ installed: "Installé"
branding: "Image de marque" branding: "Image de marque"
expirationDate: "Date dexpiration" expirationDate: "Date dexpiration"
waitingForMailAuth: "En attente de la vérification de l'adresse courriel" waitingForMailAuth: "En attente de la vérification de l'adresse courriel"
inviteCodeCreator: "Créateur·rice de ce code d'invitation"
usedAt: "Utilisé le" usedAt: "Utilisé le"
unused: "Non-utilisé" unused: "Non-utilisé"
used: "Utilisé" used: "Utilisé"
@ -1129,6 +1144,9 @@ doReaction: "Réagir"
code: "Code" code: "Code"
reloadRequiredToApplySettings: "Le rafraîchissement est nécessaire pour que les paramètres prennent effet." reloadRequiredToApplySettings: "Le rafraîchissement est nécessaire pour que les paramètres prennent effet."
remainingN: "Restants : {n}" remainingN: "Restants : {n}"
overwriteContentConfirm: "Voulez-vous remplacer le contenu actuel ?"
seasonalScreenEffect: "Effet d'écran saisonnier"
decorate: "Décorer"
_announcement: _announcement:
readConfirmTitle: "Marquer comme lu ?" readConfirmTitle: "Marquer comme lu ?"
shouldNotBeUsedToPresentPermanentInfo: "Puisque cela pourrait nuire considérablement à l'expérience utilisateur pour les nouveaux utilisateurs, il est recommandé d'utiliser les annonces pour afficher des informations temporaires plutôt que des informations persistantes." shouldNotBeUsedToPresentPermanentInfo: "Puisque cela pourrait nuire considérablement à l'expérience utilisateur pour les nouveaux utilisateurs, il est recommandé d'utiliser les annonces pour afficher des informations temporaires plutôt que des informations persistantes."
@ -1754,6 +1772,7 @@ _visibility:
followersDescription: "Publier à vos abonné·e·s uniquement" followersDescription: "Publier à vos abonné·e·s uniquement"
specified: "Direct" specified: "Direct"
specifiedDescription: "Publier uniquement aux utilisateur·rice·s mentionné·e·s" specifiedDescription: "Publier uniquement aux utilisateur·rice·s mentionné·e·s"
disableFederation: "Défédérer"
_postForm: _postForm:
replyPlaceholder: "Répondre à cette note ..." replyPlaceholder: "Répondre à cette note ..."
quotePlaceholder: "Citez cette note ..." quotePlaceholder: "Citez cette note ..."
@ -1888,6 +1907,7 @@ _notification:
yourFollowRequestAccepted: "Votre demande dabonnement a été accepté" yourFollowRequestAccepted: "Votre demande dabonnement a été accepté"
pollEnded: "Les résultats du sondage sont disponibles" pollEnded: "Les résultats du sondage sont disponibles"
unreadAntennaNote: "Antenne {name}" unreadAntennaNote: "Antenne {name}"
roleAssigned: "Rôle attribué"
emptyPushNotificationMessage: "Les notifications push ont été mises à jour" emptyPushNotificationMessage: "Les notifications push ont été mises à jour"
achievementEarned: "Accomplissement" achievementEarned: "Accomplissement"
testNotification: "Tester la notification" testNotification: "Tester la notification"
@ -1905,6 +1925,7 @@ _notification:
pollEnded: "Sondages se cloturant" pollEnded: "Sondages se cloturant"
receiveFollowRequest: "Demande d'abonnement reçue" receiveFollowRequest: "Demande d'abonnement reçue"
followRequestAccepted: "Demande d'abonnement acceptée" followRequestAccepted: "Demande d'abonnement acceptée"
roleAssigned: "Rôle reçu"
achievementEarned: "Accomplissement" achievementEarned: "Accomplissement"
app: "Notifications provenant des apps" app: "Notifications provenant des apps"
_actions: _actions:

View File

@ -121,7 +121,10 @@ sensitive: "Konten sensitif"
add: "Tambahkan" add: "Tambahkan"
reaction: "Reaksi" reaction: "Reaksi"
reactions: "Reaksi" reactions: "Reaksi"
reactionSetting: "Reaksi untuk dimunculkan di bilah reaksi" emojiPicker: "Emoji Picker"
pinnedEmojisForReactionSettingDescription: "Atur sematan emoji pada reaksi"
pinnedEmojisSettingDescription: "Atur sematan emoji pada masukan emoji"
emojiPickerDisplay: "Tampilan Emoji Picker"
reactionSettingDescription2: "Geser untuk memindah urutan emoji, klik untuk menghapus, tekan \"+\" untuk menambahkan" reactionSettingDescription2: "Geser untuk memindah urutan emoji, klik untuk menghapus, tekan \"+\" untuk menambahkan"
rememberNoteVisibility: "Ingat pengaturan visibilitas catatan" rememberNoteVisibility: "Ingat pengaturan visibilitas catatan"
attachCancel: "Hapus lampiran" attachCancel: "Hapus lampiran"
@ -261,6 +264,7 @@ removed: "Telah dihapus"
removeAreYouSure: "Apakah kamu yakin ingin menghapus \"{x}\"?" removeAreYouSure: "Apakah kamu yakin ingin menghapus \"{x}\"?"
deleteAreYouSure: "Apakah kamu yakin ingin menghapus \"{x}\"?" deleteAreYouSure: "Apakah kamu yakin ingin menghapus \"{x}\"?"
resetAreYouSure: "Yakin mau atur ulang?" resetAreYouSure: "Yakin mau atur ulang?"
areYouSure: "Apakah kamu yakin?"
saved: "Telah disimpan" saved: "Telah disimpan"
messaging: "Pesan" messaging: "Pesan"
upload: "Unggah" upload: "Unggah"
@ -311,6 +315,7 @@ folderName: "Nama folder"
createFolder: "Buat folder" createFolder: "Buat folder"
renameFolder: "Ubah nama folder" renameFolder: "Ubah nama folder"
deleteFolder: "Hapus folder" deleteFolder: "Hapus folder"
folder: "Folder"
addFile: "Tambahkan berkas" addFile: "Tambahkan berkas"
emptyDrive: "Drive kosong" emptyDrive: "Drive kosong"
emptyFolder: "Folder kosong" emptyFolder: "Folder kosong"
@ -543,6 +548,8 @@ showInPage: "Tampilkan di halaman"
popout: "Pop-out" popout: "Pop-out"
volume: "Volume" volume: "Volume"
masterVolume: "Master volume" masterVolume: "Master volume"
notUseSound: "Tidak ada keluaran suara"
useSoundOnlyWhenActive: "Hanya keluarkan suara jika Misskey sedang aktif"
details: "Selengkapnya" details: "Selengkapnya"
chooseEmoji: "Pilih emoji" chooseEmoji: "Pilih emoji"
unableToProcess: "Operasi tersebut tidak dapat diselesaikan." unableToProcess: "Operasi tersebut tidak dapat diselesaikan."
@ -638,6 +645,7 @@ smtpSecure: "Gunakan SSL/TLS implisit untuk koneksi SMTP"
smtpSecureInfo: "Matikan ini ketika menggunakan STARTTLS" smtpSecureInfo: "Matikan ini ketika menggunakan STARTTLS"
testEmail: "Tes pengiriman surel" testEmail: "Tes pengiriman surel"
wordMute: "Bisukan kata" wordMute: "Bisukan kata"
hardWordMute: "Pembisuan kata keras"
regexpError: "Kesalahan ekspresi reguler" regexpError: "Kesalahan ekspresi reguler"
regexpErrorDescription: "Galat terjadi pada baris {line} ekspresi reguler dari {tab} kata yang dibisukan:" regexpErrorDescription: "Galat terjadi pada baris {line} ekspresi reguler dari {tab} kata yang dibisukan:"
instanceMute: "Bisukan instansi" instanceMute: "Bisukan instansi"
@ -871,8 +879,6 @@ makeReactionsPublicDescription: "Pengaturan ini akan membuat daftar dari semua r
classic: "Klasik" classic: "Klasik"
muteThread: "Bisukan thread" muteThread: "Bisukan thread"
unmuteThread: "Suarakan thread" unmuteThread: "Suarakan thread"
ffVisibility: "Visibilitas Mengikuti/Pengikut"
ffVisibilityDescription: "Mengatur siapa yang dapat melihat pengikutmu dan yang kamu ikuti."
continueThread: "Lihat lanjutan thread" continueThread: "Lihat lanjutan thread"
deleteAccountConfirm: "Akun akan dihapus. Apakah kamu yakin?" deleteAccountConfirm: "Akun akan dihapus. Apakah kamu yakin?"
incorrectPassword: "Kata sandi salah." incorrectPassword: "Kata sandi salah."
@ -1023,6 +1029,8 @@ resetPasswordConfirm: "Yakin untuk mereset kata sandimu?"
sensitiveWords: "Kata sensitif" sensitiveWords: "Kata sensitif"
sensitiveWordsDescription: "Visibilitas dari semua catatan mengandung kata yang telah diatur akan dijadikan \"Beranda\" secara otomatis. Kamu dapat mendaftarkan kata tersebut lebih dari satu dengan menuliskannya di baris baru." sensitiveWordsDescription: "Visibilitas dari semua catatan mengandung kata yang telah diatur akan dijadikan \"Beranda\" secara otomatis. Kamu dapat mendaftarkan kata tersebut lebih dari satu dengan menuliskannya di baris baru."
sensitiveWordsDescription2: "Menggunakan spasi akan membuat ekspresi AND dan kata kunci disekitarnya dengan garis miring akan mengubahnya menjadi ekspresi reguler." sensitiveWordsDescription2: "Menggunakan spasi akan membuat ekspresi AND dan kata kunci disekitarnya dengan garis miring akan mengubahnya menjadi ekspresi reguler."
hiddenTags: "Tagar tersembunyi"
hiddenTagsDescription: "Pilih tanda yang mana akan tidak diperlihatkan dalam daftar tren.\nTanda lebih dari satu dapat didaftarkan dengan tiap baris."
notesSearchNotAvailable: "Pencarian catatan tidak tersedia." notesSearchNotAvailable: "Pencarian catatan tidak tersedia."
license: "Lisensi" license: "Lisensi"
unfavoriteConfirm: "Yakin ingin menghapusnya dari favorit?" unfavoriteConfirm: "Yakin ingin menghapusnya dari favorit?"
@ -1035,6 +1043,7 @@ enableChartsForRemoteUser: "Buat bagan data pengguna instansi luar"
enableChartsForFederatedInstances: "Buat bagan data peladen instansi luar" enableChartsForFederatedInstances: "Buat bagan data peladen instansi luar"
showClipButtonInNoteFooter: "Tambahkan \"Klip\" ke menu aksi catatan" showClipButtonInNoteFooter: "Tambahkan \"Klip\" ke menu aksi catatan"
reactionsDisplaySize: "Ukuran tampilan reaksi" reactionsDisplaySize: "Ukuran tampilan reaksi"
limitWidthOfReaction: "Batasi lebar maksimum reaksi dan tampilkan dalam ukuran terbatasi."
noteIdOrUrl: "ID catatan atau URL" noteIdOrUrl: "ID catatan atau URL"
video: "Video" video: "Video"
videos: "Video" videos: "Video"
@ -1150,6 +1159,7 @@ tosAndPrivacyPolicy: "Syarat dan Ketentuan serta Kebijakan Privasi"
avatarDecorations: "Dekorasi avatar" avatarDecorations: "Dekorasi avatar"
attach: "Lampirkan" attach: "Lampirkan"
detach: "Hapus" detach: "Hapus"
detachAll: "Lepas Semua"
angle: "Sudut" angle: "Sudut"
flip: "Balik" flip: "Balik"
showAvatarDecorations: "Tampilkan dekorasi avatar" showAvatarDecorations: "Tampilkan dekorasi avatar"
@ -1161,6 +1171,10 @@ useGroupedNotifications: "Tampilkan notifikasi secara dikelompokkan"
signupPendingError: "Terdapat masalah ketika memverifikasi alamat surel. Tautan kemungkinan telah kedaluwarsa." signupPendingError: "Terdapat masalah ketika memverifikasi alamat surel. Tautan kemungkinan telah kedaluwarsa."
cwNotationRequired: "Jika \"Sembunyikan konten\" diaktifkan, deskripsi harus disediakan." cwNotationRequired: "Jika \"Sembunyikan konten\" diaktifkan, deskripsi harus disediakan."
doReaction: "Tambahkan reaksi" doReaction: "Tambahkan reaksi"
code: "Kode"
reloadRequiredToApplySettings: "Muat ulang diperlukan untuk menerapkan pengaturan."
remainingN: "Sisa : {n}"
decorate: "Dekor"
_announcement: _announcement:
forExistingUsers: "Hanya pengguna yang telah ada" forExistingUsers: "Hanya pengguna yang telah ada"
forExistingUsersDescription: "Pengumuman ini akan dimunculkan ke pengguna yang sudah ada dari titik waktu publikasi jika dinyalakan. Apabila dimatikan, mereka yang baru mendaftar setelah publikasi ini akan juga melihatnya." forExistingUsersDescription: "Pengumuman ini akan dimunculkan ke pengguna yang sudah ada dari titik waktu publikasi jika dinyalakan. Apabila dimatikan, mereka yang baru mendaftar setelah publikasi ini akan juga melihatnya."
@ -1189,12 +1203,17 @@ _initialAccountSetting:
_initialTutorial: _initialTutorial:
launchTutorial: "Lihat Tutorial" launchTutorial: "Lihat Tutorial"
title: "Tutorial" title: "Tutorial"
wellDone: "Kerja bagus!"
skipAreYouSure: "Berhenti dari Tutorial?" skipAreYouSure: "Berhenti dari Tutorial?"
_landing: _landing:
title: "Selamat datang di Tutorial" title: "Selamat datang di Tutorial"
description: "Di sini kamu dapat mempelajari dasar-dasar dari penggunaan Misskey dan fitur-fiturnya." description: "Di sini kamu dapat mempelajari dasar-dasar dari penggunaan Misskey dan fitur-fiturnya."
_note: _note:
title: "Apa itu Catatan?" title: "Apa itu Catatan?"
_reaction:
title: "Apa itu Reaksi?"
_timeline:
title: "Konsep Lini Masa"
_postNote: _postNote:
title: "Pengaturan posting Catatan" title: "Pengaturan posting Catatan"
_visibility: _visibility:
@ -1202,6 +1221,13 @@ _initialTutorial:
home: "Hanya publik ke lini masa Beranda. Pengguna yang mengunjungi profilmu melalui pengikut dan renote dapat melihatnya." home: "Hanya publik ke lini masa Beranda. Pengguna yang mengunjungi profilmu melalui pengikut dan renote dapat melihatnya."
followers: "Perlihatkan ke pengikut saja. Hanya pengikut yang dapat melihat postinganmu dan tidak dapat direnote oleh siapapun." followers: "Perlihatkan ke pengikut saja. Hanya pengikut yang dapat melihat postinganmu dan tidak dapat direnote oleh siapapun."
direct: "Hanya perlihatkan ke pengguna spesifik dan penerima akan diberi tahu. Dapat juga digunakan sebagai alternatif dari pesan langsung." direct: "Hanya perlihatkan ke pengguna spesifik dan penerima akan diberi tahu. Dapat juga digunakan sebagai alternatif dari pesan langsung."
_cw:
title: "Peringatan Konten (CW)"
_exampleNote:
cw: "Peringatan: Bikin Lapar!"
note: "Baru aja makan donat berlapis coklat 🍩😋"
_howToMakeAttachmentsSensitive:
title: "Bagaimana menandai lampiran sebagai sensitif?"
_serverRules: _serverRules:
description: "Daftar peraturan akan ditampilkan sebelum pendaftaran. Mengatur ringkasan dari Syarat dan Ketentuan sangat direkomendasikan." description: "Daftar peraturan akan ditampilkan sebelum pendaftaran. Mengatur ringkasan dari Syarat dan Ketentuan sangat direkomendasikan."
_serverSettings: _serverSettings:

94
locales/index.d.ts vendored
View File

@ -382,6 +382,11 @@ export interface Locale {
"enableHcaptcha": string; "enableHcaptcha": string;
"hcaptchaSiteKey": string; "hcaptchaSiteKey": string;
"hcaptchaSecretKey": string; "hcaptchaSecretKey": string;
"mcaptcha": string;
"enableMcaptcha": string;
"mcaptchaSiteKey": string;
"mcaptchaSecretKey": string;
"mcaptchaInstanceUrl": string;
"recaptcha": string; "recaptcha": string;
"enableRecaptcha": string; "enableRecaptcha": string;
"recaptchaSiteKey": string; "recaptchaSiteKey": string;
@ -629,6 +634,7 @@ export interface Locale {
"small": string; "small": string;
"generateAccessToken": string; "generateAccessToken": string;
"permission": string; "permission": string;
"adminPermission": string;
"enableAll": string; "enableAll": string;
"disableAll": string; "disableAll": string;
"tokenRequested": string; "tokenRequested": string;
@ -672,6 +678,7 @@ export interface Locale {
"other": string; "other": string;
"regenerateLoginToken": string; "regenerateLoginToken": string;
"regenerateLoginTokenDescription": string; "regenerateLoginTokenDescription": string;
"theKeywordWhenSearchingForCustomEmoji": string;
"setMultipleBySeparatingWithSpace": string; "setMultipleBySeparatingWithSpace": string;
"fileIdOrUrl": string; "fileIdOrUrl": string;
"behavior": string; "behavior": string;
@ -884,8 +891,8 @@ export interface Locale {
"classic": string; "classic": string;
"muteThread": string; "muteThread": string;
"unmuteThread": string; "unmuteThread": string;
"ffVisibility": string; "followingVisibility": string;
"ffVisibilityDescription": string; "followersVisibility": string;
"continueThread": string; "continueThread": string;
"deleteAccountConfirm": string; "deleteAccountConfirm": string;
"incorrectPassword": string; "incorrectPassword": string;
@ -1054,6 +1061,8 @@ export interface Locale {
"noteIdOrUrl": string; "noteIdOrUrl": string;
"video": string; "video": string;
"videos": string; "videos": string;
"audio": string;
"audioFiles": string;
"dataSaver": string; "dataSaver": string;
"accountMigration": string; "accountMigration": string;
"accountMoved": string; "accountMoved": string;
@ -1184,6 +1193,25 @@ export interface Locale {
"overwriteContentConfirm": string; "overwriteContentConfirm": string;
"seasonalScreenEffect": string; "seasonalScreenEffect": string;
"decorate": string; "decorate": string;
"addMfmFunction": string;
"enableQuickAddMfmFunction": string;
"bubbleGame": string;
"sfx": string;
"soundWillBePlayed": string;
"showReplay": string;
"replay": string;
"replaying": string;
"ranking": string;
"lastNDays": string;
"backToTitle": string;
"_bubbleGame": {
"howToPlay": string;
"_howToPlay": {
"section1": string;
"section2": string;
"section3": string;
};
};
"_announcement": { "_announcement": {
"forExistingUsers": string; "forExistingUsers": string;
"forExistingUsersDescription": string; "forExistingUsersDescription": string;
@ -1648,6 +1676,15 @@ export interface Locale {
"title": string; "title": string;
"description": string; "description": string;
}; };
"_bubbleGameExplodingHead": {
"title": string;
"description": string;
};
"_bubbleGameDoubleExplodingHead": {
"title": string;
"description": string;
"flavor": string;
};
}; };
}; };
"_role": { "_role": {
@ -1745,6 +1782,7 @@ export interface Locale {
"disposable": string; "disposable": string;
"mx": string; "mx": string;
"smtp": string; "smtp": string;
"banned": string;
}; };
"_ffVisibility": { "_ffVisibility": {
"public": string; "public": string;
@ -2065,6 +2103,55 @@ export interface Locale {
"write:flash": string; "write:flash": string;
"read:flash-likes": string; "read:flash-likes": string;
"write:flash-likes": string; "write:flash-likes": string;
"read:admin:abuse-user-reports": string;
"write:admin:delete-account": string;
"write:admin:delete-all-files-of-a-user": string;
"read:admin:index-stats": string;
"read:admin:table-stats": string;
"read:admin:user-ips": string;
"read:admin:meta": string;
"write:admin:reset-password": string;
"write:admin:resolve-abuse-user-report": string;
"write:admin:send-email": string;
"read:admin:server-info": string;
"read:admin:show-moderation-log": string;
"read:admin:show-user": string;
"read:admin:show-users": string;
"write:admin:suspend-user": string;
"write:admin:unset-user-avatar": string;
"write:admin:unset-user-banner": string;
"write:admin:unsuspend-user": string;
"write:admin:meta": string;
"write:admin:user-note": string;
"write:admin:roles": string;
"read:admin:roles": string;
"write:admin:relays": string;
"read:admin:relays": string;
"write:admin:invite-codes": string;
"read:admin:invite-codes": string;
"write:admin:announcements": string;
"read:admin:announcements": string;
"write:admin:avatar-decorations": string;
"read:admin:avatar-decorations": string;
"write:admin:federation": string;
"write:admin:account": string;
"read:admin:account": string;
"write:admin:emoji": string;
"read:admin:emoji": string;
"write:admin:queue": string;
"read:admin:queue": string;
"write:admin:promo": string;
"write:admin:drive": string;
"read:admin:drive": string;
"read:admin:stream": string;
"write:admin:ad": string;
"read:admin:ad": string;
"write:invite-codes": string;
"read:invite-codes": string;
"write:clip-favorite": string;
"read:clip-favorite": string;
"read:federation": string;
"write:report-abuse": string;
}; };
"_auth": { "_auth": {
"shareAccessTitle": string; "shareAccessTitle": string;
@ -2201,6 +2288,7 @@ export interface Locale {
"_exportOrImport": { "_exportOrImport": {
"allNotes": string; "allNotes": string;
"favoritedNotes": string; "favoritedNotes": string;
"clips": string;
"followingList": string; "followingList": string;
"muteList": string; "muteList": string;
"blockingList": string; "blockingList": string;
@ -2328,6 +2416,7 @@ export interface Locale {
"pollEnded": string; "pollEnded": string;
"newNote": string; "newNote": string;
"unreadAntennaNote": string; "unreadAntennaNote": string;
"roleAssigned": string;
"emptyPushNotificationMessage": string; "emptyPushNotificationMessage": string;
"achievementEarned": string; "achievementEarned": string;
"testNotification": string; "testNotification": string;
@ -2349,6 +2438,7 @@ export interface Locale {
"pollEnded": string; "pollEnded": string;
"receiveFollowRequest": string; "receiveFollowRequest": string;
"followRequestAccepted": string; "followRequestAccepted": string;
"roleAssigned": string;
"achievementEarned": string; "achievementEarned": string;
"app": string; "app": string;
}; };

View File

@ -121,7 +121,12 @@ sensitive: "Allegato esplicito"
add: "Aggiungi" add: "Aggiungi"
reaction: "Reazioni" reaction: "Reazioni"
reactions: "Reazioni" reactions: "Reazioni"
reactionSetting: "Reazioni visualizzate sul pannello" emojiPicker: "Selettore emoji"
pinnedEmojisForReactionSettingDescription: "Scegli quale sia l'emoji in cima, quando reagisci"
pinnedEmojisSettingDescription: "Scegli quale sia l'emoji in cima, quando reagisci"
emojiPickerDisplay: "Visualizza selettore"
overwriteFromPinnedEmojisForReaction: "Sovrascrivi con le impostazioni reazioni"
overwriteFromPinnedEmojis: "Sovrascrivi con le impostazioni globali"
reactionSettingDescription2: "Trascina per riorganizzare, clicca per cancellare, usa il pulsante \"+\" per aggiungere." reactionSettingDescription2: "Trascina per riorganizzare, clicca per cancellare, usa il pulsante \"+\" per aggiungere."
rememberNoteVisibility: "Ricordare le impostazioni di visibilità delle note" rememberNoteVisibility: "Ricordare le impostazioni di visibilità delle note"
attachCancel: "Rimuovi allegato" attachCancel: "Rimuovi allegato"
@ -261,6 +266,7 @@ removed: "Eliminato con successo"
removeAreYouSure: "Vuoi davvero eliminare \"{x}\"?" removeAreYouSure: "Vuoi davvero eliminare \"{x}\"?"
deleteAreYouSure: "Vuoi davvero eliminare \"{x}\"?" deleteAreYouSure: "Vuoi davvero eliminare \"{x}\"?"
resetAreYouSure: "Ripristinare?" resetAreYouSure: "Ripristinare?"
areYouSure: "Confermi?"
saved: "Salvato" saved: "Salvato"
messaging: "Messaggi" messaging: "Messaggi"
upload: "Carica" upload: "Carica"
@ -875,8 +881,6 @@ makeReactionsPublicDescription: "La lista delle reazioni che avete fatto è a di
classic: "Classico" classic: "Classico"
muteThread: "Silenzia conversazione" muteThread: "Silenzia conversazione"
unmuteThread: "Riattiva la conversazione" unmuteThread: "Riattiva la conversazione"
ffVisibility: "Visibilità delle connessioni"
ffVisibilityDescription: "Puoi scegliere a chi mostrare le tue relazioni con altri profili nel fediverso."
continueThread: "Altre conversazioni" continueThread: "Altre conversazioni"
deleteAccountConfirm: "Così verrà eliminato il profilo. Vuoi procedere?" deleteAccountConfirm: "Così verrà eliminato il profilo. Vuoi procedere?"
incorrectPassword: "La password è errata." incorrectPassword: "La password è errata."
@ -1157,6 +1161,7 @@ tosAndPrivacyPolicy: "Condizioni d'uso e informativa privacy"
avatarDecorations: "Decorazioni foto profilo" avatarDecorations: "Decorazioni foto profilo"
attach: "Applica" attach: "Applica"
detach: "Rimuovi" detach: "Rimuovi"
detachAll: "Togli tutto"
angle: "Angolo" angle: "Angolo"
flip: "Inverti" flip: "Inverti"
showAvatarDecorations: "Mostra decorazione della foto profilo" showAvatarDecorations: "Mostra decorazione della foto profilo"
@ -1170,6 +1175,10 @@ cwNotationRequired: "Devi indicare perché il contenuto è indicato come esplici
doReaction: "Reagisci" doReaction: "Reagisci"
code: "Codice" code: "Codice"
reloadRequiredToApplySettings: "Per applicare le impostazioni, occorre ricaricare." reloadRequiredToApplySettings: "Per applicare le impostazioni, occorre ricaricare."
remainingN: "Rimangono: {n}"
overwriteContentConfirm: "Vuoi davvero sostituire l'attuale contenuto?"
seasonalScreenEffect: "Schermate in base alla stagione"
decorate: "Decora"
_announcement: _announcement:
forExistingUsers: "Solo ai profili attuali" forExistingUsers: "Solo ai profili attuali"
forExistingUsersDescription: "L'annuncio sarà visibile solo ai profili esistenti in questo momento. Se disabilitato, sarà visibile anche ai profili che verranno creati dopo la pubblicazione di questo annuncio." forExistingUsersDescription: "L'annuncio sarà visibile solo ai profili esistenti in questo momento. Se disabilitato, sarà visibile anche ai profili che verranno creati dopo la pubblicazione di questo annuncio."
@ -1601,6 +1610,7 @@ _role:
canHideAds: "Nascondere i banner" canHideAds: "Nascondere i banner"
canSearchNotes: "Ricercare nelle Note" canSearchNotes: "Ricercare nelle Note"
canUseTranslator: "Tradurre le Note" canUseTranslator: "Tradurre le Note"
avatarDecorationLimit: "Numero massimo di decorazioni foto profilo installabili"
_condition: _condition:
isLocal: "Profilo locale" isLocal: "Profilo locale"
isRemote: "Profilo remoto" isRemote: "Profilo remoto"
@ -2037,6 +2047,7 @@ _profile:
changeAvatar: "Modifica immagine profilo" changeAvatar: "Modifica immagine profilo"
changeBanner: "Cambia intestazione" changeBanner: "Cambia intestazione"
verifiedLinkDescription: "Puoi verificare il tuo profilo mostrando una icona. Devi inserire la URL alla pagina che contiene un link al tuo profilo." verifiedLinkDescription: "Puoi verificare il tuo profilo mostrando una icona. Devi inserire la URL alla pagina che contiene un link al tuo profilo."
avatarDecorationMax: "Puoi aggiungere fino a {max} decorazioni."
_exportOrImport: _exportOrImport:
allNotes: "Tutte le note" allNotes: "Tutte le note"
favoritedNotes: "Note preferite" favoritedNotes: "Note preferite"

View File

@ -379,6 +379,11 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "hCaptchaを有効にする" enableHcaptcha: "hCaptchaを有効にする"
hcaptchaSiteKey: "サイトキー" hcaptchaSiteKey: "サイトキー"
hcaptchaSecretKey: "シークレットキー" hcaptchaSecretKey: "シークレットキー"
mcaptcha: "mCaptcha"
enableMcaptcha: "mCaptchaを有効にする"
mcaptchaSiteKey: "サイトキー"
mcaptchaSecretKey: "シークレットキー"
mcaptchaInstanceUrl: "mCaptchaのインスタンスのURL"
recaptcha: "reCAPTCHA" recaptcha: "reCAPTCHA"
enableRecaptcha: "reCAPTCHAを有効にする" enableRecaptcha: "reCAPTCHAを有効にする"
recaptchaSiteKey: "サイトキー" recaptchaSiteKey: "サイトキー"
@ -626,6 +631,7 @@ medium: "中"
small: "小" small: "小"
generateAccessToken: "アクセストークンの発行" generateAccessToken: "アクセストークンの発行"
permission: "権限" permission: "権限"
adminPermission: "管理者権限"
enableAll: "全て有効にする" enableAll: "全て有効にする"
disableAll: "全て無効にする" disableAll: "全て無効にする"
tokenRequested: "アカウントへのアクセス許可" tokenRequested: "アカウントへのアクセス許可"
@ -669,6 +675,7 @@ useGlobalSettingDesc: "オンにすると、アカウントの通知設定が使
other: "その他" other: "その他"
regenerateLoginToken: "ログイントークンを再生成" regenerateLoginToken: "ログイントークンを再生成"
regenerateLoginTokenDescription: "ログインに使用される内部トークンを再生成します。通常この操作を行う必要はありません。再生成すると、全てのデバイスでログアウトされます。" regenerateLoginTokenDescription: "ログインに使用される内部トークンを再生成します。通常この操作を行う必要はありません。再生成すると、全てのデバイスでログアウトされます。"
theKeywordWhenSearchingForCustomEmoji: "カスタム絵文字を検索する時のキーワードになります。"
setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。" setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。"
fileIdOrUrl: "ファイルIDまたはURL" fileIdOrUrl: "ファイルIDまたはURL"
behavior: "動作" behavior: "動作"
@ -881,8 +888,8 @@ makeReactionsPublicDescription: "あなたがしたリアクション一覧を
classic: "クラシック" classic: "クラシック"
muteThread: "スレッドをミュート" muteThread: "スレッドをミュート"
unmuteThread: "スレッドのミュートを解除" unmuteThread: "スレッドのミュートを解除"
ffVisibility: "つながりの公開範囲" followingVisibility: "フォローの公開範囲"
ffVisibilityDescription: "自分のフォロー/フォロワー情報の公開範囲を設定できます。" followersVisibility: "フォロワーの公開範囲"
continueThread: "さらにスレッドを見る" continueThread: "さらにスレッドを見る"
deleteAccountConfirm: "アカウントが削除されます。よろしいですか?" deleteAccountConfirm: "アカウントが削除されます。よろしいですか?"
incorrectPassword: "パスワードが間違っています。" incorrectPassword: "パスワードが間違っています。"
@ -1051,6 +1058,8 @@ limitWidthOfReaction: "リアクションの最大横幅を制限し、縮小し
noteIdOrUrl: "ートIDまたはURL" noteIdOrUrl: "ートIDまたはURL"
video: "動画" video: "動画"
videos: "動画" videos: "動画"
audio: "音声"
audioFiles: "音声"
dataSaver: "データセーバー" dataSaver: "データセーバー"
accountMigration: "アカウントの移行" accountMigration: "アカウントの移行"
accountMoved: "このユーザーは新しいアカウントに移行しました:" accountMoved: "このユーザーは新しいアカウントに移行しました:"
@ -1181,6 +1190,24 @@ remainingN: "残り: {n}"
overwriteContentConfirm: "現在の内容に上書きされますがよろしいですか?" overwriteContentConfirm: "現在の内容に上書きされますがよろしいですか?"
seasonalScreenEffect: "季節に応じた画面の演出" seasonalScreenEffect: "季節に応じた画面の演出"
decorate: "デコる" decorate: "デコる"
addMfmFunction: "装飾を追加"
enableQuickAddMfmFunction: "高度なMFMのピッカーを表示する"
bubbleGame: "バブルゲーム"
sfx: "効果音"
soundWillBePlayed: "サウンドが再生されます"
showReplay: "リプレイを見る"
replay: "リプレイ"
replaying: "リプレイ中"
ranking: "ランキング"
lastNDays: "直近{n}日"
backToTitle: "タイトルへ"
_bubbleGame:
howToPlay: "遊び方"
_howToPlay:
section1: "位置を調整してハコにモノを落とします。"
section2: "同じ種類のモノがくっつくと別のモノに変化して、スコアが得られます。"
section3: "モノがハコからあふれるとゲームオーバーです。ハコからあふれないようにしつつモノを融合させてハイスコアを目指そう!"
_announcement: _announcement:
forExistingUsers: "既存ユーザーのみ" forExistingUsers: "既存ユーザーのみ"
@ -1559,6 +1586,13 @@ _achievements:
_tutorialCompleted: _tutorialCompleted:
title: "Misskey初心者講座 修了証" title: "Misskey初心者講座 修了証"
description: "チュートリアルを完了した" description: "チュートリアルを完了した"
_bubbleGameExplodingHead:
title: "🤯"
description: "バブルゲームで最も大きいモノを出した"
_bubbleGameDoubleExplodingHead:
title: "ダブル🤯"
description: "バブルゲームで最も大きいモを2つ同時に出した"
flavor: "これくらいの おべんとばこに 🤯 🤯 ちょっとつめて"
_role: _role:
new: "ロールの作成" new: "ロールの作成"
@ -1652,6 +1686,7 @@ _emailUnavailable:
disposable: "恒久的に使用可能なアドレスではありません" disposable: "恒久的に使用可能なアドレスではありません"
mx: "正しいメールサーバーではありません" mx: "正しいメールサーバーではありません"
smtp: "メールサーバーが応答しません" smtp: "メールサーバーが応答しません"
banned: "このメールアドレスでは登録できません"
_ffVisibility: _ffVisibility:
public: "公開" public: "公開"
@ -1970,6 +2005,55 @@ _permissions:
"write:flash": "Playを操作する" "write:flash": "Playを操作する"
"read:flash-likes": "Playのいいねを見る" "read:flash-likes": "Playのいいねを見る"
"write:flash-likes": "Playのいいねを操作する" "write:flash-likes": "Playのいいねを操作する"
"read:admin:abuse-user-reports": "ユーザーからの通報を見る"
"write:admin:delete-account": "ユーザーアカウントを削除する"
"write:admin:delete-all-files-of-a-user": "ユーザーのすべてのファイルを削除する"
"read:admin:index-stats": "データベースインデックスに関する情報を見る"
"read:admin:table-stats": "データベーステーブルに関する情報を見る"
"read:admin:user-ips": "ユーザーのIPアドレスを見る"
"read:admin:meta": "インスタンスのメタデータを見る"
"write:admin:reset-password": "ユーザーのパスワードをリセットする"
"write:admin:resolve-abuse-user-report": "ユーザーからの通報を解決する"
"write:admin:send-email": "メールを送る"
"read:admin:server-info": "サーバーの情報を見る"
"read:admin:show-moderation-log": "モデレーションログを見る"
"read:admin:show-user": "ユーザーのプライベートな情報を見る"
"read:admin:show-users": "ユーザーのプライベートな情報を見る"
"write:admin:suspend-user": "ユーザーを凍結する"
"write:admin:unset-user-avatar": "ユーザーのアバターを削除する"
"write:admin:unset-user-banner": "ユーザーのバーナーを削除する"
"write:admin:unsuspend-user": "ユーザーの凍結を解除する"
"write:admin:meta": "インスタンスのメタデータを操作する"
"write:admin:user-note": "モデレーションノートを操作する"
"write:admin:roles": "ロールを操作する"
"read:admin:roles": "ロールを見る"
"write:admin:relays": "リレーを操作する"
"read:admin:relays": "リレーを見る"
"write:admin:invite-codes": "招待コードを操作する"
"read:admin:invite-codes": "招待コードを見る"
"write:admin:announcements": "お知らせを操作する"
"read:admin:announcements": "お知らせを見る"
"write:admin:avatar-decorations": "アバターデコレーションを操作する"
"read:admin:avatar-decorations": "アバターデコレーションを見る"
"write:admin:federation": "連合に関する情報を操作する"
"write:admin:account": "ユーザーアカウントを操作する"
"read:admin:account": "ユーザーに関する情報を見る"
"write:admin:emoji": "絵文字を操作する"
"read:admin:emoji": "絵文字を見る"
"write:admin:queue": "ジョブキューを操作する"
"read:admin:queue": "ジョブキューに関する情報を見る"
"write:admin:promo": "プロモーションノートを操作する"
"write:admin:drive": "ユーザーのドライブを操作する"
"read:admin:drive": "ユーザーのドライブの関する情報を見る"
"read:admin:stream": "管理者用のWebsocket APIを使う"
"write:admin:ad": "広告を操作する"
"read:admin:ad": "広告を見る"
"write:invite-codes": "招待コードを作成する"
"read:invite-codes": "招待コードを取得する"
"write:clip-favorite": "クリップのいいねを操作する"
"read:clip-favorite": "クリップのいいねを見る"
"read:federation": "連合に関する情報を取得する"
"write:report-abuse": "違反を報告する"
_auth: _auth:
shareAccessTitle: "アプリへのアクセス許可" shareAccessTitle: "アプリへのアクセス許可"
@ -2104,6 +2188,7 @@ _profile:
_exportOrImport: _exportOrImport:
allNotes: "全てのノート" allNotes: "全てのノート"
favoritedNotes: "お気に入りにしたノート" favoritedNotes: "お気に入りにしたノート"
clips: "クリップ"
followingList: "フォロー" followingList: "フォロー"
muteList: "ミュート" muteList: "ミュート"
blockingList: "ブロック" blockingList: "ブロック"
@ -2230,6 +2315,7 @@ _notification:
pollEnded: "アンケートの結果が出ました" pollEnded: "アンケートの結果が出ました"
newNote: "新しい投稿" newNote: "新しい投稿"
unreadAntennaNote: "アンテナ {name}" unreadAntennaNote: "アンテナ {name}"
roleAssigned: "ロールが付与されました"
emptyPushNotificationMessage: "プッシュ通知の更新をしました" emptyPushNotificationMessage: "プッシュ通知の更新をしました"
achievementEarned: "実績を獲得" achievementEarned: "実績を獲得"
testNotification: "通知テスト" testNotification: "通知テスト"
@ -2252,6 +2338,7 @@ _notification:
pollEnded: "アンケートが終了" pollEnded: "アンケートが終了"
receiveFollowRequest: "フォロー申請を受け取った" receiveFollowRequest: "フォロー申請を受け取った"
followRequestAccepted: "フォローが受理された" followRequestAccepted: "フォローが受理された"
roleAssigned: "ロールが付与された"
achievementEarned: "実績の獲得" achievementEarned: "実績の獲得"
app: "連携アプリからの通知" app: "連携アプリからの通知"

View File

@ -121,7 +121,12 @@ sensitive: "気いつけて見いや"
add: "増やす" add: "増やす"
reaction: "ツッコミ" reaction: "ツッコミ"
reactions: "ツッコミ" reactions: "ツッコミ"
reactionSetting: "ピッカーに出しとくツッコミ" emojiPicker: "絵文字ピッカー"
pinnedEmojisForReactionSettingDescription: "リアクションしたときにピンで留めてる表示をする絵文字を設定するで"
pinnedEmojisSettingDescription: "絵文字打ったときにピン留め表示する絵文字設定できるで"
emojiPickerDisplay: "ピッカーの表示"
overwriteFromPinnedEmojisForReaction: "リアクション設定から上書きする"
overwriteFromPinnedEmojis: "全般設定から上書きする"
reactionSettingDescription2: "ドラッグで並び替え、クリックで削除、+を押して追加やで。" reactionSettingDescription2: "ドラッグで並び替え、クリックで削除、+を押して追加やで。"
rememberNoteVisibility: "公開範囲覚えといて" rememberNoteVisibility: "公開範囲覚えといて"
attachCancel: "のっけるのやめる" attachCancel: "のっけるのやめる"
@ -261,6 +266,7 @@ removed: "ほかしたで!"
removeAreYouSure: "「{x}」はほかしてええか?" removeAreYouSure: "「{x}」はほかしてええか?"
deleteAreYouSure: "「{x}」はほかしてええか?" deleteAreYouSure: "「{x}」はほかしてええか?"
resetAreYouSure: "リセットしてええん?" resetAreYouSure: "リセットしてええん?"
areYouSure: "いいん?"
saved: "保存したで!" saved: "保存したで!"
messaging: "チャット" messaging: "チャット"
upload: "アップロード" upload: "アップロード"
@ -875,8 +881,6 @@ makeReactionsPublicDescription: "あんたがしたツッコミ一覧を誰で
classic: "クラシック" classic: "クラシック"
muteThread: "スレッドをミュート" muteThread: "スレッドをミュート"
unmuteThread: "スレッドのミュートを解除" unmuteThread: "スレッドのミュートを解除"
ffVisibility: "つながりの公開範囲"
ffVisibilityDescription: "あんたのフォロー/フォロワー情報の公開範囲を設定できるで。"
continueThread: "さらにスレッドを見るで" continueThread: "さらにスレッドを見るで"
deleteAccountConfirm: "アカウントを消すで?ええんか?" deleteAccountConfirm: "アカウントを消すで?ええんか?"
incorrectPassword: "パスワードがちゃうわ。" incorrectPassword: "パスワードがちゃうわ。"
@ -1157,6 +1161,7 @@ tosAndPrivacyPolicy: "利用規約・プライバシーポリシー"
avatarDecorations: "アイコンデコレーション" avatarDecorations: "アイコンデコレーション"
attach: "のっける" attach: "のっける"
detach: "取る" detach: "取る"
detachAll: "全部とる"
angle: "角度" angle: "角度"
flip: "反転" flip: "反転"
showAvatarDecorations: "アイコンのデコレーション映す" showAvatarDecorations: "アイコンのデコレーション映す"
@ -1170,6 +1175,10 @@ cwNotationRequired: "「内容を隠す」んやったら注釈書かなアカ
doReaction: "ツッコむで" doReaction: "ツッコむで"
code: "コード" code: "コード"
reloadRequiredToApplySettings: "設定を見るんにはリロードが必要やで。" reloadRequiredToApplySettings: "設定を見るんにはリロードが必要やで。"
remainingN: "残り:{n}"
overwriteContentConfirm: "今の内容に上書きされるけどいい?"
seasonalScreenEffect: "季節にあった画面の動き"
decorate: "デコる"
_announcement: _announcement:
forExistingUsers: "もうおるユーザーのみ" forExistingUsers: "もうおるユーザーのみ"
forExistingUsersDescription: "オンにしたらこのお知らせができた時点でおる人らにだけお知らせが行くで。切ったらこの知らせが行ったあとにアカウント作った人にもちゃんとお知らせが行くで。" forExistingUsersDescription: "オンにしたらこのお知らせができた時点でおる人らにだけお知らせが行くで。切ったらこの知らせが行ったあとにアカウント作った人にもちゃんとお知らせが行くで。"
@ -1601,6 +1610,7 @@ _role:
canHideAds: "広告映さへん" canHideAds: "広告映さへん"
canSearchNotes: "ノート探せるかどうか" canSearchNotes: "ノート探せるかどうか"
canUseTranslator: "翻訳使えるかどうか" canUseTranslator: "翻訳使えるかどうか"
avatarDecorationLimit: "アイコンデコのいっちばんつけれる数"
_condition: _condition:
isLocal: "ローカルユーザー" isLocal: "ローカルユーザー"
isRemote: "リモートユーザー" isRemote: "リモートユーザー"
@ -2037,6 +2047,7 @@ _profile:
changeAvatar: "アバター画像を変更するで" changeAvatar: "アバター画像を変更するで"
changeBanner: "バナー画像を変更するで" changeBanner: "バナー画像を変更するで"
verifiedLinkDescription: "内容をURLに設定すると、リンク先のwebサイトに自分のプロフのリンクが含まれてる場合に所有者確認済みアイコンを表示させることができるで。" verifiedLinkDescription: "内容をURLに設定すると、リンク先のwebサイトに自分のプロフのリンクが含まれてる場合に所有者確認済みアイコンを表示させることができるで。"
avatarDecorationMax: "最大{max}つまでデコつけれんで"
_exportOrImport: _exportOrImport:
allNotes: "全てのノート" allNotes: "全てのノート"
favoritedNotes: "お気に入りにしたノート" favoritedNotes: "お気に入りにしたノート"

View File

@ -15,7 +15,7 @@ gotIt: "알것어예"
cancel: "아이예" cancel: "아이예"
noThankYou: "뎃어예" noThankYou: "뎃어예"
enterUsername: "사용자 이럼 서기" enterUsername: "사용자 이럼 서기"
renotedBy: "{user}님이 리노트햇십니다" renotedBy: "{user}님이 리노트햇어예"
noNotes: "노트가 없십니다" noNotes: "노트가 없십니다"
noNotifications: "알림이 없십니다" noNotifications: "알림이 없십니다"
instance: "서버" instance: "서버"
@ -76,7 +76,7 @@ export: "내가기"
files: "파일" files: "파일"
download: "내리받기" download: "내리받기"
driveFileDeleteConfirm: "{name} 파일얼 뭉캡니꺼? 요 파일얼 서넌 콘텐츠도 뭉캐집니다." driveFileDeleteConfirm: "{name} 파일얼 뭉캡니꺼? 요 파일얼 서넌 콘텐츠도 뭉캐집니다."
unfollowConfirm: "{name}님얼 고 팔로잉합니꺼?" unfollowConfirm: "{name}님얼 고 팔로잉합니꺼?"
exportRequested: "내가기 요청얼 햇십니다. 시간이 쪼매 걸릴 깁니다. 요청이 껕나모 ‘드라이브’에 옇십니다." exportRequested: "내가기 요청얼 햇십니다. 시간이 쪼매 걸릴 깁니다. 요청이 껕나모 ‘드라이브’에 옇십니다."
importRequested: "가오기 요청얼 햇십니다. 시간이 쪼매 걸릴 깁니다." importRequested: "가오기 요청얼 햇십니다. 시간이 쪼매 걸릴 깁니다."
lists: "리스트" lists: "리스트"
@ -113,7 +113,7 @@ cantReRenote: "리노트넌 지럴 리노트 몬 합니다."
quote: "따오기" quote: "따오기"
inChannelRenote: "채널 안 리노트" inChannelRenote: "채널 안 리노트"
inChannelQuote: "채널 안 따오기" inChannelQuote: "채널 안 따오기"
pinnedNote: "프로필에 붙인 노트" pinnedNote: "붙인 노트"
pinned: "프로필에 붙이기" pinned: "프로필에 붙이기"
you: "나" you: "나"
clickToShow: "누질라서 보기" clickToShow: "누질라서 보기"
@ -121,7 +121,6 @@ sensitive: "수ᇚ힛섭니다"
add: "옇기" add: "옇기"
reaction: "반엉" reaction: "반엉"
reactions: "반엉" reactions: "반엉"
reactionSetting: "모엄함서 포시할 반엉"
reactionSettingDescription2: "꺼시서 두고, 누질라서 뭉캐고, +’럴 누질라서 옇십니다." reactionSettingDescription2: "꺼시서 두고, 누질라서 뭉캐고, +’럴 누질라서 옇십니다."
rememberNoteVisibility: "공개 범위럴 기억하기" rememberNoteVisibility: "공개 범위럴 기억하기"
attachCancel: "붙임 빼기" attachCancel: "붙임 빼기"
@ -261,6 +260,7 @@ removed: "뭉캣십니다"
removeAreYouSure: "{x}(얼)럴 뭉캡니꺼?" removeAreYouSure: "{x}(얼)럴 뭉캡니꺼?"
deleteAreYouSure: "{x}(얼)럴 뭉캡니꺼?" deleteAreYouSure: "{x}(얼)럴 뭉캡니꺼?"
resetAreYouSure: "아시로 데돌립니꺼?" resetAreYouSure: "아시로 데돌립니꺼?"
areYouSure: "갠찮십니꺼?"
saved: "저장햇십니다" saved: "저장햇십니다"
messaging: "대화" messaging: "대화"
upload: "올리기" upload: "올리기"
@ -299,7 +299,7 @@ light: "볽엄"
dark: "어덥엄" dark: "어덥엄"
lightThemes: "볽언 테마" lightThemes: "볽언 테마"
darkThemes: "어덥언 테마" darkThemes: "어덥언 테마"
syncDeviceDarkMode: "드라이브으 어덥엄 모드하고 같구로 마추기" syncDeviceDarkMode: "디바이스 쪽 어덥엄 모드하고 같구로 마추기"
drive: "드라이브" drive: "드라이브"
fileName: "파일 이럼" fileName: "파일 이럼"
selectFile: "파일 개리기" selectFile: "파일 개리기"
@ -330,7 +330,7 @@ whenServerDisconnected: "서버하고 옌겔이 껂기모"
disconnectedFromServer: "서버하고 옌겔이 껂깃십니다" disconnectedFromServer: "서버하고 옌겔이 껂깃십니다"
reload: "새로곤침" reload: "새로곤침"
doNothing: "무시하기" doNothing: "무시하기"
reloadConfirm: "새로곤침합니?" reloadConfirm: "새로곤침합니?"
watch: "간심 갖기" watch: "간심 갖기"
unwatch: "간심 고마 갖기" unwatch: "간심 고마 갖기"
accept: "받기" accept: "받기"
@ -368,7 +368,7 @@ pinnedUsersDescription: "‘살펴보기’서 붙일라넌 사용자럴 줄 바
pinnedPages: "붙인 바닥" pinnedPages: "붙인 바닥"
pinnedPagesDescription: "서버으 대문서 붙일라넌 바닥으 겡로럴 줄 바꿈해서로 적십니다." pinnedPagesDescription: "서버으 대문서 붙일라넌 바닥으 겡로럴 줄 바꿈해서로 적십니다."
pinnedClipId: "붙일 클립으 아이디" pinnedClipId: "붙일 클립으 아이디"
pinnedNotes: "프로필에 붙인 노트" pinnedNotes: "붙인 노트"
hcaptcha: "에이치캡차" hcaptcha: "에이치캡차"
enableHcaptcha: "에이치캡차 키기" enableHcaptcha: "에이치캡차 키기"
hcaptchaSiteKey: "사이트키" hcaptchaSiteKey: "사이트키"
@ -381,7 +381,7 @@ turnstile: "턴스타일"
enableTurnstile: "턴스타일 키기" enableTurnstile: "턴스타일 키기"
turnstileSiteKey: "사이트키" turnstileSiteKey: "사이트키"
turnstileSecretKey: "시크릿키" turnstileSecretKey: "시크릿키"
avoidMultiCaptchaConfirm: "오만 캡차럴 서모 간섭이 잇얼 깁니다. 다린 캡차를 껍니? ‘아이예’럴 누질리모 오만 캡차럴 키 둘 수도 잇십니다." avoidMultiCaptchaConfirm: "오만 캡차럴 서모 간섭이 잇얼 깁니다. 다린 캡차를 껍니? ‘아이예’럴 누질리모 오만 캡차럴 키 둘 수도 잇십니다."
antennas: "안테나" antennas: "안테나"
manageAntennas: "안테나 간리" manageAntennas: "안테나 간리"
name: "이럼" name: "이럼"
@ -413,7 +413,7 @@ userList: "리스트"
about: "정보" about: "정보"
aboutMisskey: "Misskey넌예" aboutMisskey: "Misskey넌예"
administrator: "간리자" administrator: "간리자"
token: "학인 코드" token: "학인 기호"
2fa: "두 단게 정멩" 2fa: "두 단게 정멩"
setupOf2fa: "두 단게 정멩 설정" setupOf2fa: "두 단게 정멩 설정"
totp: "정멩 앱" totp: "정멩 앱"
@ -426,13 +426,179 @@ moderationLogs: "중재 일지"
nUsersMentioned: "{n}멩이 이바구하고 잇어예" nUsersMentioned: "{n}멩이 이바구하고 잇어예"
securityKeyAndPasskey: "보안키·패스키" securityKeyAndPasskey: "보안키·패스키"
securityKey: "보안키" securityKey: "보안키"
lastUsed: "마지막 쓰임"
lastUsedAt: "마지막 쓰임: {t}"
unregister: "맨걸기 무루기"
passwordLessLogin: "비밀번호 없시 로그인"
passwordLessLoginDescription: "비밀번호 말고 보안키나 패스키 같은 것만 써 가 로그인합니다."
resetPassword: "비밀번호 재설정"
newPasswordIs: "새 비밀번호는 \"{password}\" 입니다"
reduceUiAnimation: "화면 움직임 효과들을 수ᇚ후기"
share: "노누기"
notFound: "몬 찾앗십니다"
notFoundDescription: "고런 주소로 들어가는 하멘은 없십니다."
uploadFolder: "기본 업로드 위치"
markAsReadAllNotifications: "모든 알림 이럿다고 표시"
markAsReadAllUnreadNotes: "모든 글 이럿다고 표시"
markAsReadAllTalkMessages: "모든 대화 이럿다고 표시"
help: "도움말"
inputMessageHere: "여따가 메시지를 입력해주이소"
close: "닫기"
invites: "초대하기" invites: "초대하기"
members: "멤버"
transfer: "양도"
title: "제목"
text: "글"
enable: "키기"
next: "다음"
retype: "다시 서기"
noteOf: "{user}님으 노트"
quoteAttached: "따옴"
quoteQuestion: "따와가 작성하겠십니까?"
noMessagesYet: "아직 대화가 없십니다"
newMessageExists: "새 메시지가 있십니다"
onlyOneFileCanBeAttached: "메시지엔 파일 하나까제밖에 몬 넣십니다"
invitations: "초대하기" invitations: "초대하기"
invitationCode: "초대장"
checking: "학인하고 잇십니다"
passwordMatched: "맞십니다"
passwordNotMatched: "안 맞십니다"
signinFailed: "로그인 몬 했십니다. 고 이름이랑 비밀번호 제대로 썼는가 확인해 주이소."
or: "아니면"
language: "언어" language: "언어"
uiLanguage: "UI 표시 언어"
aboutX: "{x}에 대해서"
emojiStyle: "이모지 모양"
native: "기본"
disableDrawer: "드로어 메뉴 쓰지 않기"
showNoteActionsOnlyHover: "마우스 올맀을 때만 노트 액션 버턴 보이기"
noHistory: "기록이 없십니다"
signinHistory: "로그인 기록"
enableAdvancedMfm: "복잡한 MFM 키기"
enableAnimatedMfm: "정신사나운 MFM 키기"
doing: "잠만예"
category: "카테고리"
tags: "태그"
docSource: "요 문서의 원본"
createAccount: "게정 맨걸기"
existingAccount: "원래 게정"
regenerate: "엎고 다시 맨걸기"
fontSize: "글자 크기"
mediaListWithOneImageAppearance: "사진 하나짜리 미디어 목록의 높이"
limitTo: "{x}로 제한"
noFollowRequests: "지둘리는 팔로우 요청이 없십니다"
openImageInNewTab: "새 탭서 사진 열기"
dashboard: "대시보드"
local: "로컬"
remote: "웬겍"
total: "합계"
weekOverWeekChanges: "저번주보다"
dayOverDayChanges: "어제보다"
appearance: "모냥"
clientSettings: "클라이언트 설정"
accountSettings: "게정 설정"
promotion: "선전"
promote: "선전하기"
numberOfDays: "며칠동안"
hideThisNote: "요 노트를 수ᇚ후기"
showFeaturedNotesInTimeline: "타임라인에다 추천 노트 보이기"
objectStorage: "오브젝트 스토리지"
useObjectStorage: "오브젝트 스토리지 키기"
objectStorageBaseUrl: "Base URL"
objectStorageBaseUrlDesc: "오브젝트 (미디어) 참조 링크 만들 때 쓰는 URL임다. CDN 내지 프락시를 쓴다 카멘은 그 URL을 갖다 늫고, 아이면 써먹을 서비스네 가이드를 봐봐가 공개적으로 접근할 수 있는 주소를 여 넣어 주이소. 그니께, 내가 AWS S3을 쓴다 카면은 'https://<bucket>.s3.amazonaws.com', GCS를 쓴다 카면 'https://storage.googleapis.com/<bucket>' 처럼 쓰믄 되입니더."
objectStorageBucket: "Bucket"
objectStorageBucketDesc: "써먹을 서비스의 바께쓰 이름을 여 써 주이소."
objectStoragePrefix: "Prefix"
objectStoragePrefixDesc: "요 Prefix 디렉토리 안에다가 파일이 들어감다."
objectStorageEndpoint: "Endpoint"
objectStorageEndpointDesc: "AWS S3을 쓸라멘 요는 비워두고, 아이멘은 그 서비스 가이드에 맞게 endpoint를 넣어 주이소. '<host>' 내지 '<host>:<port>'처럼 넣십니다."
objectStorageRegion: "Region"
objectStorageRegionDesc: "'xx-east-1' 같은 region 이름을 옇어 주이소. 써먹을 서비스에 region 개념 같은 게 읎다! 카면은 대신에 'us-east-1'을 옇어 놓으이소. AWS 설정 파일이나 환경 변수를 갖다 끌어다 쓸 거면은 요는 비워 두이소."
objectStorageUseSSL: "SSL 쓰기"
objectStorageUseSSLDesc: "API 호출할 때 HTTPS 안 쓸거면은 꺼 두이소"
objectStorageUseProxy: "연결에 프락시 사용"
objectStorageUseProxyDesc: "오브젝트 스토리지 API 호출에 프락시 안 쓸 거면 꺼 두이소"
objectStorageSetPublicRead: "업로드할 때 'public-read' 설정하기"
s3ForcePathStyleDesc: "s3ForcePathStyle을 키면, 바께쓰 이름을 URL의 호스트명 말고 경로의 일부로써 취급합니다. 셀프 호스트 Minio 같은 걸 굴릴라믄 켜놔야 될 수도 있십니다."
serverLogs: "서버 로그"
deleteAll: "말캉 뭉캐기"
showFixedPostForm: "타임라인 우에 글 작성 칸 박기"
showFixedPostFormInChannel: "채널 타임라인 우에 글 작성 칸 박기"
withRepliesByDefaultForNewlyFollowed: "팔로우 할 때 기본적으로 답걸도 타임라인에 나오게 하기"
newNoteRecived: "새 노트 있어예"
sounds: "소리"
sound: "소리"
listen: "듣기"
none: "없음"
showInPage: "바닥서 보기"
popout: "새 창 열기"
volume: "음량"
masterVolume: "대빵 음량"
notUseSound: "음소거하기"
useSoundOnlyWhenActive: "Misskey가 활성화되어 있을 때만 소리 내기"
details: "좀 더"
chooseEmoji: "이모지 선택"
unableToProcess: "작업 다 몬 했십니다"
recentUsed: "최근 쓴 놈"
install: "설치"
uninstall: "삭제"
installedApps: "설치된 애플리케이션"
nothing: "뭣도 없어예"
installedDate: "설치한 날"
lastUsedDate: "마지막 사용"
state: "상태"
sort: "정렬하기"
ascendingOrder: "작은 순"
descendingOrder: "큰 순"
scratchpad: "스크래치 패드"
scratchpadDescription: "스크래치 패드는 AiScript를 끼적거리는 창입니더. Misskey랑 갖다 이리저리 상호작용하는 코드를 서가 굴리멘은 그 결과도 바로 확인할 수 있십니다."
output: "출력"
script: "스크립트"
disablePagesScript: "온갖 바닥서 AiScript를 쓰지 않음"
updateRemoteUser: "원겍 사용자 근황 알아오기"
unsetUserAvatar: "아바타 치우기"
unsetUserAvatarConfirm: "아바타 갖다 치울까예?"
unsetUserBanner: "배너 치우기"
unsetUserBannerConfirm: "배너 갖다 치울까예?"
deleteAllFiles: "파일 말캉 뭉캐기"
deleteAllFilesConfirm: "파일을 싸그리 다 뭉캐삐릴까예?"
removeAllFollowing: "팔로잉 말캉 무루기"
removeAllFollowingDescription: "{host} 서버랑 걸어놓은 모든 팔로잉을 무룹니다. 고 서버가 아예 없어지삐맀든가, 그런 경우에 하이소."
userSuspended: "요 게정은... 얼어 있십니다."
userSilenced: "요 게정은... 수ᇚ혀 있십니다."
relays: "릴레이"
addRelay: "릴레이 옇기"
addedRelays: "옇은 릴레이"
enableInfiniteScroll: "알아서 더 보기"
author: "맨던 사람"
manage: "간리" manage: "간리"
emailServer: "전자우펜 서버"
email: "전자우펜"
emailAddress: "전자우펜 주소"
smtpHost: "호스트 이럼" smtpHost: "호스트 이럼"
smtpPort: "포트"
smtpUser: "사용자 이럼" smtpUser: "사용자 이럼"
smtpPass: "비밀번호" smtpPass: "비밀번호"
display: "보기"
create: "맨걸기"
abuseReports: "신고하기"
reportAbuse: "신고하기"
reportAbuseRenote: "리노트 신고하기"
reportAbuseOf: "{name}님얼 신고하기"
reporter: "신고한 사람"
reporteeOrigin: "신고덴 사람"
reporterOrigin: "신고한 곳"
forwardReport: "웬겍 서버에 신고 보내기"
random: "무작이"
system: "시스템"
clip: "클립 맨걸기"
createNew: "새로 맨걸기"
notesCount: "노트 수"
renotesCount: "리노트한 수"
renotedCount: "리노트덴 수"
followingCount: "팔로우 수"
followersCount: "팔로워 수"
clips: "클립 맨걸기"
clearCache: "캐시 비우기" clearCache: "캐시 비우기"
unlikeConfirm: "좋네예럴 무룹니꺼?" unlikeConfirm: "좋네예럴 무룹니꺼?"
info: "정보" info: "정보"
@ -440,6 +606,7 @@ user: "사용자"
administration: "간리" administration: "간리"
on: "킴" on: "킴"
off: "껌" off: "껌"
clickToFinishEmailVerification: "[{ok}]럴 누질라서 전자우펜 정멩얼 껕내이소."
searchByGoogle: "찾기" searchByGoogle: "찾기"
tenMinutes: "십 분" tenMinutes: "십 분"
oneHour: "한 시간" oneHour: "한 시간"
@ -451,6 +618,7 @@ tools: "도구"
like: "좋네예!" like: "좋네예!"
unlike: "좋네예 무루기" unlike: "좋네예 무루기"
numberOfLikes: "좋네예 수" numberOfLikes: "좋네예 수"
show: "보기"
roles: "옉할" roles: "옉할"
role: "옉할" role: "옉할"
noRole: "옉할이 없십니다" noRole: "옉할이 없십니다"
@ -459,6 +627,20 @@ likeOnly: "좋네예마"
icon: "아바타" icon: "아바타"
replies: "답하기" replies: "답하기"
renotes: "리노트" renotes: "리노트"
_initialAccountSetting:
startTutorial: "길라잡이 하기"
_initialTutorial:
launchTutorial: "길라잡이 보기"
title: "길라잡이"
skipAreYouSure: "길라잡이럴 껕냅니까?"
_landing:
title: "길라잡이에 어서 오이소"
_done:
title: "길라잡이가 껕낫십니다!🎉"
_achievements:
_types:
_tutorialCompleted:
description: "길라잡이럴 껕냇십니다"
_gallery: _gallery:
liked: "좋네예한 걸" liked: "좋네예한 걸"
like: "좋네예!" like: "좋네예!"
@ -466,13 +648,18 @@ _gallery:
_email: _email:
_follow: _follow:
title: "새 팔로워가 잇십니다" title: "새 팔로워가 잇십니다"
_serverDisconnectedBehavior:
reload: "알아서 새로곤침"
_channel:
removeBanner: "배너 뭉캐기"
_theme: _theme:
keys: keys:
mention: "멘션" mention: "멘션"
_sfx: _sfx:
note: "노트" note: "노트"
notification: "알림" notification: "알림"
_2fa: _2fa:
step3Title: "학인 기호럴 서기"
renewTOTPCancel: "뎃어예" renewTOTPCancel: "뎃어예"
_widgets: _widgets:
profile: "프로필" profile: "프로필"
@ -501,11 +688,15 @@ _charts:
federation: "옌합" federation: "옌합"
_timelines: _timelines:
home: "덜머리" home: "덜머리"
_play:
script: "스크립트"
_pages: _pages:
like: "좋네예" like: "좋네예"
unlike: "좋네예 무루기" unlike: "좋네예 무루기"
blocks: blocks:
image: "이미지" image: "이미지"
_note:
id: "노트 아이디"
_notification: _notification:
youWereFollowed: "새 팔로워가 잇십니다" youWereFollowed: "새 팔로워가 잇십니다"
_types: _types:
@ -526,3 +717,7 @@ _webhookSettings:
name: "이럼" name: "이럼"
_moderationLogTypes: _moderationLogTypes:
suspend: "얼우기" suspend: "얼우기"
deleteNote: "노트 뭉캐기"
deleteUserAnnouncement: "사용자 공지 걸 뭉캐기"
resetPassword: "비밀번호 재설정"
resolveAbuseReport: "신고 해겔하기"

View File

@ -114,14 +114,19 @@ quote: "인용"
inChannelRenote: "채널 내 리노트" inChannelRenote: "채널 내 리노트"
inChannelQuote: "채널 내 인용" inChannelQuote: "채널 내 인용"
pinnedNote: "고정된 노트" pinnedNote: "고정된 노트"
pinned: "프로필에 고정" pinned: "고정하기"
you: "나" you: "나"
clickToShow: "클릭하여 보기" clickToShow: "클릭하여 보기"
sensitive: "열람 주의" sensitive: "열람 주의"
add: "추가" add: "추가"
reaction: "리액션" reaction: "리액션"
reactions: "리액션" reactions: "리액션"
reactionSetting: "선택기에 표시할 리액션" emojiPicker: "이모지 선택기"
pinnedEmojisForReactionSettingDescription: "리액션을 할 때 프로필에 고정하여 표시할 이모지를 설정할 수 있습니다"
pinnedEmojisSettingDescription: "이모지를 입력할 때 프로필에 고정하여 표시할 이모지를 설정할 수 있습니다"
emojiPickerDisplay: "선택기 표시"
overwriteFromPinnedEmojisForReaction: "리액션 설정을 덮어쓰기"
overwriteFromPinnedEmojis: "일반 설정을 덮어쓰기"
reactionSettingDescription2: "끌어서 순서 변경, 클릭해서 삭제, +를 눌러서 추가할 수 있습니다." reactionSettingDescription2: "끌어서 순서 변경, 클릭해서 삭제, +를 눌러서 추가할 수 있습니다."
rememberNoteVisibility: "공개 범위를 기억하기" rememberNoteVisibility: "공개 범위를 기억하기"
attachCancel: "첨부 취소" attachCancel: "첨부 취소"
@ -261,6 +266,7 @@ removed: "삭제하였습니다"
removeAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?" removeAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
deleteAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?" deleteAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
resetAreYouSure: "초기화 하시겠습니까?" resetAreYouSure: "초기화 하시겠습니까?"
areYouSure: "계속 진행하시겠습니까?"
saved: "저장하였습니다" saved: "저장하였습니다"
messaging: "대화" messaging: "대화"
upload: "업로드" upload: "업로드"
@ -419,9 +425,9 @@ setupOf2fa: "2단계 인증 설정"
totp: "인증 앱" totp: "인증 앱"
totpDescription: "인증 앱을 사용하여 일회성 비밀번호 입력" totpDescription: "인증 앱을 사용하여 일회성 비밀번호 입력"
moderator: "모더레이터" moderator: "모더레이터"
moderation: "모더레이션" moderation: "조정"
moderationNote: "모더레이션 노트" moderationNote: "조정 기록"
addModerationNote: "모더레이션 노트 추가하기" addModerationNote: "조정 기록 추가하기"
moderationLogs: "모더레이션 로그" moderationLogs: "모더레이션 로그"
nUsersMentioned: "{n}명이 언급함" nUsersMentioned: "{n}명이 언급함"
securityKeyAndPasskey: "보안 키 또는 패스 키" securityKeyAndPasskey: "보안 키 또는 패스 키"
@ -507,7 +513,7 @@ dayOverDayChanges: "어제보다"
appearance: "모양" appearance: "모양"
clientSettings: "클라이언트 설정" clientSettings: "클라이언트 설정"
accountSettings: "계정 설정" accountSettings: "계정 설정"
promotion: "프로모션" promotion: "홍보"
promote: "프로모션하기" promote: "프로모션하기"
numberOfDays: "며칠동안" numberOfDays: "며칠동안"
hideThisNote: "이 노트를 숨기기" hideThisNote: "이 노트를 숨기기"
@ -686,7 +692,7 @@ defaultNavigationBehaviour: "기본 탐색 동작"
editTheseSettingsMayBreakAccount: "이 설정을 변경하면 계정이 손상될 수 있습니다." editTheseSettingsMayBreakAccount: "이 설정을 변경하면 계정이 손상될 수 있습니다."
instanceTicker: "노트의 서버 정보" instanceTicker: "노트의 서버 정보"
waitingFor: "{x}을(를) 기다리고 있습니다" waitingFor: "{x}을(를) 기다리고 있습니다"
random: "랜덤" random: "무작위"
system: "시스템" system: "시스템"
switchUi: "UI 전환" switchUi: "UI 전환"
desktop: "데스크탑" desktop: "데스크탑"
@ -857,8 +863,8 @@ devMode: "개발자 모드"
keepCw: "CW 유지하기" keepCw: "CW 유지하기"
pubSub: "Pub/Sub 계정" pubSub: "Pub/Sub 계정"
lastCommunication: "마지막 통신" lastCommunication: "마지막 통신"
resolved: "해결됨" resolved: "처리함"
unresolved: "해결되지 않음" unresolved: "처리되지 않음"
breakFollow: "팔로워 해제" breakFollow: "팔로워 해제"
breakFollowConfirm: "팔로우를 해제하시겠습니까?" breakFollowConfirm: "팔로우를 해제하시겠습니까?"
itsOn: "켜져 있습니다" itsOn: "켜져 있습니다"
@ -875,8 +881,8 @@ makeReactionsPublicDescription: "나의 리액션을 누구나 볼 수 있게
classic: "클래식" classic: "클래식"
muteThread: "글타래 뮤트" muteThread: "글타래 뮤트"
unmuteThread: "글타래 뮤트 해제" unmuteThread: "글타래 뮤트 해제"
ffVisibility: "내 인맥의 공개 범위" followingVisibility: "팔로우의 공개 범위"
ffVisibilityDescription: "나의 팔로우와 팔로워 정보에 대한 공개 범위를 설정할 수 있습니다." followersVisibility: "팔로워의 공개 범위"
continueThread: "글타래 더 보기" continueThread: "글타래 더 보기"
deleteAccountConfirm: "계정이 삭제되고 되돌릴 수 없게 됩니다. 계속하시겠습니까? " deleteAccountConfirm: "계정이 삭제되고 되돌릴 수 없게 됩니다. 계속하시겠습니까? "
incorrectPassword: "비밀번호가 올바르지 않습니다." incorrectPassword: "비밀번호가 올바르지 않습니다."
@ -1156,7 +1162,8 @@ privacyPolicyUrl: "개인정보 보호 정책 URL"
tosAndPrivacyPolicy: "약관 및 개인정보 보호 정책" tosAndPrivacyPolicy: "약관 및 개인정보 보호 정책"
avatarDecorations: "아바타 장식" avatarDecorations: "아바타 장식"
attach: "붙이기" attach: "붙이기"
detach: "떼기" detach: "빼기"
detachAll: "모두 빼기"
angle: "각도" angle: "각도"
flip: "플립" flip: "플립"
showAvatarDecorations: "아바타 장식 표시" showAvatarDecorations: "아바타 장식 표시"
@ -1170,6 +1177,12 @@ cwNotationRequired: "'내용을 숨기기'를 체크한 경우 주석을 써야
doReaction: "리액션 추가" doReaction: "리액션 추가"
code: "문자열" code: "문자열"
reloadRequiredToApplySettings: "설정을 적용하려면 새로고침을 해야 합니다." reloadRequiredToApplySettings: "설정을 적용하려면 새로고침을 해야 합니다."
remainingN: "나머지: {n}"
overwriteContentConfirm: "현재 내용을 덮어쓰기 합니다. 계속 진행하시겠습니까?"
seasonalScreenEffect: "계절에 따른 효과 보이기"
decorate: "장식하기"
addMfmFunction: "장식 추가하기"
enableQuickAddMfmFunction: "상급자용 MFM 선택기 표시하기"
_announcement: _announcement:
forExistingUsers: "기존 유저에게만 알림" forExistingUsers: "기존 유저에게만 알림"
forExistingUsersDescription: "활성화하면 이 공지사항을 게시한 시점에서 이미 가입한 유저에게만 표시합니다. 비활성화하면 게시 후에 가입한 유저에게도 표시합니다." forExistingUsersDescription: "활성화하면 이 공지사항을 게시한 시점에서 이미 가입한 유저에게만 표시합니다. 비활성화하면 게시 후에 가입한 유저에게도 표시합니다."
@ -1546,7 +1559,7 @@ _role:
name: "역할 이름" name: "역할 이름"
description: "역할 설명" description: "역할 설명"
permission: "역할 권한" permission: "역할 권한"
descriptionOfPermission: "<b>모더레이터</b>는 기본적인 중재와 관련된 작업을 수행할 수 있습니다.\n<b>관리자</b>는 서버의 모든 설정을 변경할 수 있습니다." descriptionOfPermission: "<b>조정자</b>는 기본적인 조정 작업을 진행할 수 있습니다.\n<b>관리자</b>는 서버의 모든 설정을 변경할 수 있습니다."
assignTarget: "할당 대상" assignTarget: "할당 대상"
descriptionOfAssignTarget: "<b>수동</b>을 선택하면 누가 이 역할에 포함되는지를 수동으로 관리할 수 있습니다.\n<b>조건부</b>를 선택하면 조건을 설정해 일치하는 사용자를 자동으로 포함되게 할 수 있습니다." descriptionOfAssignTarget: "<b>수동</b>을 선택하면 누가 이 역할에 포함되는지를 수동으로 관리할 수 있습니다.\n<b>조건부</b>를 선택하면 조건을 설정해 일치하는 사용자를 자동으로 포함되게 할 수 있습니다."
manual: "수동" manual: "수동"
@ -1601,6 +1614,7 @@ _role:
canHideAds: "광고 숨기기" canHideAds: "광고 숨기기"
canSearchNotes: "노트 검색 이용 가능 여부" canSearchNotes: "노트 검색 이용 가능 여부"
canUseTranslator: "번역 기능의 사용" canUseTranslator: "번역 기능의 사용"
avatarDecorationLimit: "아바타 장식의 최대 붙임 개수"
_condition: _condition:
isLocal: "로컬 사용자" isLocal: "로컬 사용자"
isRemote: "리모트 사용자" isRemote: "리모트 사용자"
@ -1616,7 +1630,7 @@ _role:
or: "다음을 하나라도 만족" or: "다음을 하나라도 만족"
not: "다음을 만족하지 않음" not: "다음을 만족하지 않음"
_sensitiveMediaDetection: _sensitiveMediaDetection:
description: "기계학습을 통해 자동으로 민감한 미디어를 탐지하여, 모더레이션에 참고할 수 있도록 합니다. 서버의 부하를 약간 증가시킵니다." description: "기계 학습으로 민감한 미디어를 알아서 찾아내어 조정에 참고하도록 합니다. 서버가 부하를 다소 받습니다."
sensitivity: "탐지 민감도" sensitivity: "탐지 민감도"
sensitivityDescription: "민감도가 낮을수록 안전한 미디어가 잘못 탐지될 확률이 줄어들며, 높을수록 민감한 미디어가 탐지되지 않을 확률이 줄어듭니다." sensitivityDescription: "민감도가 낮을수록 안전한 미디어가 잘못 탐지될 확률이 줄어들며, 높을수록 민감한 미디어가 탐지되지 않을 확률이 줄어듭니다."
setSensitiveFlagAutomatically: "자동으로 NSFW로 설정하기" setSensitiveFlagAutomatically: "자동으로 NSFW로 설정하기"
@ -1629,6 +1643,7 @@ _emailUnavailable:
disposable: "임시 이메일 주소는 사용할 수 없습니다" disposable: "임시 이메일 주소는 사용할 수 없습니다"
mx: "메일 서버가 올바르지 않습니다" mx: "메일 서버가 올바르지 않습니다"
smtp: "메일 서버가 응답하지 않습니다" smtp: "메일 서버가 응답하지 않습니다"
banned: "이 메일 주소는 사용할 수 없습니다"
_ffVisibility: _ffVisibility:
public: "공개" public: "공개"
followers: "팔로워에게만 공개" followers: "팔로워에게만 공개"
@ -1828,8 +1843,8 @@ _soundSettings:
driveFileWarn: "드라이브에 있는 파일을 선택하세요." driveFileWarn: "드라이브에 있는 파일을 선택하세요."
driveFileTypeWarn: "이 파일은 지원되지 않습니다." driveFileTypeWarn: "이 파일은 지원되지 않습니다."
driveFileTypeWarnDescription: "오디오 파일을 선택하세요." driveFileTypeWarnDescription: "오디오 파일을 선택하세요."
driveFileDurationWarn: "오디오가 너무 길어요." driveFileDurationWarn: "오디오가 너무 깁니다"
driveFileDurationWarnDescription: "길은 오디오를 사용하시는 경우 미스키 사용에 지장이 갈 수도 있습니다. 그래도 괜찮습니까?" driveFileDurationWarnDescription: "긴 오디오로 설정할 경우 미스키 사용에 지장이 갈 수도 있습니다. 그래도 괜찮습니까?"
_ago: _ago:
future: "미래" future: "미래"
justNow: "방금 전" justNow: "방금 전"
@ -1920,6 +1935,55 @@ _permissions:
"write:flash": "Play를 조작합니다" "write:flash": "Play를 조작합니다"
"read:flash-likes": "Play의 좋아요를 봅니다" "read:flash-likes": "Play의 좋아요를 봅니다"
"write:flash-likes": "Play의 좋아요를 조작합니다" "write:flash-likes": "Play의 좋아요를 조작합니다"
"read:admin:abuse-user-reports": "사용자 신고 보기"
"write:admin:delete-account": "사용자 계정 삭제하기"
"write:admin:delete-all-files-of-a-user": "모든 사용자 파일 삭제하기"
"read:admin:index-stats": "데이터베이스 색인 정보 보기"
"read:admin:table-stats": "데이터베이스 테이블 정보 보기"
"read:admin:user-ips": "사용자 IP 주소 보기"
"read:admin:meta": "인스턴스 메타데이터 보기"
"write:admin:reset-password": "사용자 비밀번호 재설정하기"
"write:admin:resolve-abuse-user-report": "사용자 신고 처리하기"
"write:admin:send-email": "이메일 보내기"
"read:admin:server-info": "서버 정보 보기"
"read:admin:show-moderation-log": "조정 기록 보기"
"read:admin:show-user": "사용자 개인정보 보기"
"read:admin:show-users": "사용자 개인정보 보기"
"write:admin:suspend-user": "사용자 정지하기"
"write:admin:unset-user-avatar": "사용자 아바타 삭제하기"
"write:admin:unset-user-banner": "사용자 배너 삭제하기"
"write:admin:unsuspend-user": "사용자 정지 해제하기"
"write:admin:meta": "인스턴스 메타데이터 수정하기"
"write:admin:user-note": "조정 기록 수정하기"
"write:admin:roles": "역할 수정하기"
"read:admin:roles": "역할 보기"
"write:admin:relays": "릴레이 수정하기"
"read:admin:relays": "릴레이 보기"
"write:admin:invite-codes": "초대 코드 수정하기"
"read:admin:invite-codes": "초대 코드 보기"
"write:admin:announcements": "공지사항 수정하기"
"read:admin:announcements": "공지사항 보기"
"write:admin:avatar-decorations": "아바타 꾸미기 수정하기"
"read:admin:avatar-decorations": "아바타 꾸미기 보기"
"write:admin:federation": "연합 정보 수정하기"
"write:admin:account": "사용자 계정 수정하기"
"read:admin:account": "사용자 정보 보기"
"write:admin:emoji": "이모지 수정하기"
"read:admin:emoji": "이모지 보기"
"write:admin:queue": "작업 대기열 수정하기"
"read:admin:queue": "작업 대기열 정보 보기"
"write:admin:promo": "홍보 기록 수정하기"
"write:admin:drive": "사용자 드라이브 수정하기"
"read:admin:drive": "사용자 드라이브 정보 보기"
"read:admin:stream": "관리자용 Websocket API 사용하기"
"write:admin:ad": "광고 수정하기"
"read:admin:ad": "광고 보기"
"write:invite-codes": "초대 코드 만들기"
"read:invite-codes": "초대 코드 불러오기"
"write:clip-favorite": "클립의 좋아요 수정하기"
"read:clip-favorite": "클립의 좋아요 보기"
"read:federation": "연합 정보 불러오기"
"write:report-abuse": "위반 내용 신고하기"
_auth: _auth:
shareAccessTitle: "어플리케이션의 접근 허가" shareAccessTitle: "어플리케이션의 접근 허가"
shareAccess: "\"{name}\" 이 계정에 접근하는 것을 허용하시겠습니까?" shareAccess: "\"{name}\" 이 계정에 접근하는 것을 허용하시겠습니까?"
@ -2037,6 +2101,7 @@ _profile:
changeAvatar: "아바타 이미지 변경" changeAvatar: "아바타 이미지 변경"
changeBanner: "배너 이미지 변경" changeBanner: "배너 이미지 변경"
verifiedLinkDescription: "내용에 자신의 프로필로 향하는 링크가 포함된 페이지의 URL을 삽입하면 소유자 인증 마크가 표시됩니다." verifiedLinkDescription: "내용에 자신의 프로필로 향하는 링크가 포함된 페이지의 URL을 삽입하면 소유자 인증 마크가 표시됩니다."
avatarDecorationMax: "최대 {max}개까지 장식을 할 수 있습니다."
_exportOrImport: _exportOrImport:
allNotes: "모든 노트" allNotes: "모든 노트"
favoritedNotes: "즐겨찾기한 노트" favoritedNotes: "즐겨찾기한 노트"
@ -2158,6 +2223,7 @@ _notification:
pollEnded: "투표 결과가 발표되었습니다" pollEnded: "투표 결과가 발표되었습니다"
newNote: "새 게시물" newNote: "새 게시물"
unreadAntennaNote: "안테나 {name}" unreadAntennaNote: "안테나 {name}"
roleAssigned: "역할이 부여 되었습니다."
emptyPushNotificationMessage: "푸시 알림이 갱신되었습니다" emptyPushNotificationMessage: "푸시 알림이 갱신되었습니다"
achievementEarned: "도전 과제를 달성했습니다" achievementEarned: "도전 과제를 달성했습니다"
testNotification: "알림 테스트" testNotification: "알림 테스트"
@ -2179,6 +2245,7 @@ _notification:
pollEnded: "투표가 종료됨" pollEnded: "투표가 종료됨"
receiveFollowRequest: "팔로우 요청을 받았을 때" receiveFollowRequest: "팔로우 요청을 받았을 때"
followRequestAccepted: "팔로우 요청이 승인되었을 때" followRequestAccepted: "팔로우 요청이 승인되었을 때"
roleAssigned: "역할이 부여 됨"
achievementEarned: "도전 과제 획득" achievementEarned: "도전 과제 획득"
app: "연동된 앱을 통한 알림" app: "연동된 앱을 통한 알림"
_actions: _actions:
@ -2251,28 +2318,28 @@ _moderationLogTypes:
updateCustomEmoji: "커스텀 이모지 수정" updateCustomEmoji: "커스텀 이모지 수정"
deleteCustomEmoji: "커스텀 이모지 삭제" deleteCustomEmoji: "커스텀 이모지 삭제"
updateServerSettings: "서버 설정 갱신" updateServerSettings: "서버 설정 갱신"
updateUserNote: "모더레이션 노트 갱신" updateUserNote: "조정 기록 갱신"
deleteDriveFile: "파일 삭제" deleteDriveFile: "파일 삭제"
deleteNote: "노트 삭제" deleteNote: "노트 삭제"
createGlobalAnnouncement: "전역 공지사항 생성" createGlobalAnnouncement: "모든 공지사항 만들기"
createUserAnnouncement: "유저 공지사항 생성" createUserAnnouncement: "사용자 공지사항 만들기"
updateGlobalAnnouncement: "전역 공지사항 수정" updateGlobalAnnouncement: "모든 공지사항 수정"
updateUserAnnouncement: "유저 공지사항 수정" updateUserAnnouncement: "사용자 공지사항 수정"
deleteGlobalAnnouncement: "전역 공지사항 삭제" deleteGlobalAnnouncement: "모든 공지사항 삭제"
deleteUserAnnouncement: "유저 공지사항 삭제" deleteUserAnnouncement: "사용자 공지사항 삭제"
resetPassword: "비밀번호 재설정" resetPassword: "비밀번호 재설정"
suspendRemoteInstance: "리모트 서버를 정지" suspendRemoteInstance: "리모트 서버를 정지"
unsuspendRemoteInstance: "리모트 서버의 정지를 해제" unsuspendRemoteInstance: "리모트 서버의 정지를 해제"
markSensitiveDriveFile: "파일에 열람주의를 설정" markSensitiveDriveFile: "파일에 열람주의를 설정"
unmarkSensitiveDriveFile: "파일에 열람주의를 해제" unmarkSensitiveDriveFile: "파일에 열람주의를 해제"
resolveAbuseReport: "신고 해결" resolveAbuseReport: "신고 처리"
createInvitation: "초대 코드 생성" createInvitation: "초대 코드 생성"
createAd: "광고 생성" createAd: "광고 생성"
deleteAd: "광고 삭제" deleteAd: "광고 삭제"
updateAd: "광고 수정" updateAd: "광고 수정"
createAvatarDecoration: "아이콘 장식 추가" createAvatarDecoration: "아바타 장식 만들기"
updateAvatarDecoration: "아이콘 장식 수정" updateAvatarDecoration: "아바타 장식 수정"
deleteAvatarDecoration: "아이콘 장식 삭제" deleteAvatarDecoration: "아바타 장식 삭제"
unsetUserAvatar: "유저 아바타 제거" unsetUserAvatar: "유저 아바타 제거"
unsetUserBanner: "유저 배너 제거" unsetUserBanner: "유저 배너 제거"
_fileViewer: _fileViewer:

View File

@ -119,7 +119,6 @@ sensitive: "NSFW"
add: "Toevoegen" add: "Toevoegen"
reaction: "Reacties" reaction: "Reacties"
reactions: "Reacties" reactions: "Reacties"
reactionSetting: "Reacties die in de reactie-selector worden getoond"
reactionSettingDescription2: "Sleep om opnieuw te ordenen, Klik om te verwijderen, Druk op \"+\" om toe te voegen" reactionSettingDescription2: "Sleep om opnieuw te ordenen, Klik om te verwijderen, Druk op \"+\" om toe te voegen"
rememberNoteVisibility: "Vergeet niet de notitie zichtbaarheidsinstellingen" rememberNoteVisibility: "Vergeet niet de notitie zichtbaarheidsinstellingen"
attachCancel: "Verwijder bijlage" attachCancel: "Verwijder bijlage"

View File

@ -102,7 +102,6 @@ clickToShow: "Klikk for å vise"
add: "Legg til" add: "Legg til"
reaction: "Reaksjon" reaction: "Reaksjon"
reactions: "Reaksjoner" reactions: "Reaksjoner"
reactionSetting: "Reaksjoner som vises i reaksjonsvelgeren"
reactionSettingDescription2: "Dra for å endre rekkefølgen, klikk for å slette, trykk \"+\" for å legge til." reactionSettingDescription2: "Dra for å endre rekkefølgen, klikk for å slette, trykk \"+\" for å legge til."
rememberNoteVisibility: "Husk innstillingene for synlighet av Notes" rememberNoteVisibility: "Husk innstillingene for synlighet av Notes"
attachCancel: "Fjern vedlegg" attachCancel: "Fjern vedlegg"

View File

@ -111,7 +111,6 @@ sensitive: "NSFW"
add: "Dodaj" add: "Dodaj"
reaction: "Reakcja" reaction: "Reakcja"
reactions: "Reakcja" reactions: "Reakcja"
reactionSetting: "Reakcje do pokazania w wyborniku reakcji"
reactionSettingDescription2: "Przeciągnij aby zmienić kolejność, naciśnij aby usunąć, naciśnij „+” aby dodać" reactionSettingDescription2: "Przeciągnij aby zmienić kolejność, naciśnij aby usunąć, naciśnij „+” aby dodać"
rememberNoteVisibility: "Zapamiętuj ustawienia widoczności wpisu" rememberNoteVisibility: "Zapamiętuj ustawienia widoczności wpisu"
attachCancel: "Usuń załącznik" attachCancel: "Usuń załącznik"
@ -807,8 +806,6 @@ makeReactionsPublicDescription: "To spowoduje, że lista wszystkich Twoich dotyc
classic: "Klasyczny" classic: "Klasyczny"
muteThread: "Wycisz wątek" muteThread: "Wycisz wątek"
unmuteThread: "Wyłącz wyciszenie wątku" unmuteThread: "Wyłącz wyciszenie wątku"
ffVisibility: "Widoczność obserwowanych/obserwujących"
ffVisibilityDescription: "Pozwala skonfigurować, kto może zobaczyć, kogo obserwujesz i kto Cię obserwuje."
continueThread: "Pokaż kontynuację wątku" continueThread: "Pokaż kontynuację wątku"
deleteAccountConfirm: "Spowoduje to nieodwracalne usunięcie Twojego konta. Kontynuować?" deleteAccountConfirm: "Spowoduje to nieodwracalne usunięcie Twojego konta. Kontynuować?"
incorrectPassword: "Nieprawidłowe hasło." incorrectPassword: "Nieprawidłowe hasło."

View File

@ -121,7 +121,6 @@ sensitive: "Conteúdo sensível"
add: "Adicionar" add: "Adicionar"
reaction: "Reações" reaction: "Reações"
reactions: "Reações" reactions: "Reações"
reactionSetting: "Quais reações exibir no seletor de reações"
reactionSettingDescription2: "Arraste para reordenar, clique para excluir, pressione + para adicionar." reactionSettingDescription2: "Arraste para reordenar, clique para excluir, pressione + para adicionar."
rememberNoteVisibility: "Lembrar das configurações de visibilidade de notas" rememberNoteVisibility: "Lembrar das configurações de visibilidade de notas"
attachCancel: "Remover anexo" attachCancel: "Remover anexo"
@ -859,8 +858,6 @@ makeReactionsPublicDescription: "Isto vai deixar o histórico de todas as suas r
classic: "Clássico" classic: "Clássico"
muteThread: "Silenciar esta conversa" muteThread: "Silenciar esta conversa"
unmuteThread: "Desativar silêncio desta conversa" unmuteThread: "Desativar silêncio desta conversa"
ffVisibility: "Visibilidade de Seguidos/Seguidores"
ffVisibilityDescription: "Permite configurar quem pode ver quem lhe segue e quem você está seguindo."
continueThread: "Ver mais desta conversa" continueThread: "Ver mais desta conversa"
deleteAccountConfirm: "Deseja realmente excluir a conta?" deleteAccountConfirm: "Deseja realmente excluir a conta?"
incorrectPassword: "Senha inválida." incorrectPassword: "Senha inválida."

View File

@ -121,7 +121,6 @@ sensitive: "NSFW"
add: "Adaugă" add: "Adaugă"
reaction: "Reacție" reaction: "Reacție"
reactions: "Reacție" reactions: "Reacție"
reactionSetting: "Reacții care să apară in selectorul de reacții"
reactionSettingDescription2: "Trage pentru a rearanja, apasă pe \"+\" pentru a adăuga." reactionSettingDescription2: "Trage pentru a rearanja, apasă pe \"+\" pentru a adăuga."
rememberNoteVisibility: "Amintește setarea de vizibilitate a notelor" rememberNoteVisibility: "Amintește setarea de vizibilitate a notelor"
attachCancel: "Înlătură atașament" attachCancel: "Înlătură atașament"

View File

@ -120,7 +120,12 @@ sensitive: "Содержимое не для всех"
add: "Добавить" add: "Добавить"
reaction: "Реакции" reaction: "Реакции"
reactions: "Реакции" reactions: "Реакции"
reactionSetting: "Реакции, отображаемые в палитре" emojiPicker: "Палитра эмодзи"
pinnedEmojisForReactionSettingDescription: "Здесь можно закрепить эмодзи для реакций"
pinnedEmojisSettingDescription: "Здесь можно закрепить эмодзи в общей палитре"
emojiPickerDisplay: "Внешний вид палитры"
overwriteFromPinnedEmojisForReaction: "Заменить на эмодзи из списка реакций"
overwriteFromPinnedEmojis: "Заменить на эмодзи из общего списка закреплённых"
reactionSettingDescription2: "Расставляйте перетаскиванием, удаляйте нажатием, добавляйте кнопкой «+»." reactionSettingDescription2: "Расставляйте перетаскиванием, удаляйте нажатием, добавляйте кнопкой «+»."
rememberNoteVisibility: "Запоминать видимость заметок" rememberNoteVisibility: "Запоминать видимость заметок"
attachCancel: "Удалить вложение" attachCancel: "Удалить вложение"
@ -857,8 +862,6 @@ makeReactionsPublicDescription: "Список сделанных вами реа
classic: "Классика" classic: "Классика"
muteThread: "Скрыть цепочку" muteThread: "Скрыть цепочку"
unmuteThread: "Отменить сокрытие цепочки" unmuteThread: "Отменить сокрытие цепочки"
ffVisibility: "Видимость подписок и подписчиков"
ffVisibilityDescription: "Здесь можно настроить, кто будет видеть ваши подписки и подписчиков."
continueThread: "Показать следующие ответы" continueThread: "Показать следующие ответы"
deleteAccountConfirm: "Учётная запись будет безвозвратно удалена. Подтверждаете?" deleteAccountConfirm: "Учётная запись будет безвозвратно удалена. Подтверждаете?"
incorrectPassword: "Пароль неверен." incorrectPassword: "Пароль неверен."
@ -1056,6 +1059,8 @@ options: "Настройки ролей"
specifyUser: "Указанный пользователь" specifyUser: "Указанный пользователь"
failedToPreviewUrl: "Предварительный просмотр недоступен" failedToPreviewUrl: "Предварительный просмотр недоступен"
update: "Обновить" update: "Обновить"
rolesThatCanBeUsedThisEmojiAsReaction: "Роли тех, кому можно использовать эти эмодзи как реакцию"
rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "Если здесь ничего не указать, в качестве реакции эту эмодзи сможет использовать каждый."
later: "Позже" later: "Позже"
goToMisskey: "К Misskey" goToMisskey: "К Misskey"
additionalEmojiDictionary: "Дополнительные словари эмодзи" additionalEmojiDictionary: "Дополнительные словари эмодзи"

View File

@ -113,7 +113,6 @@ sensitive: "NSFW"
add: "Pridať" add: "Pridať"
reaction: "Reakcie" reaction: "Reakcie"
reactions: "Reakcie" reactions: "Reakcie"
reactionSetting: "Reakcie zobrazené vo výbere reakcií"
reactionSettingDescription2: "Ťahaním preusporiadate, kliknutím odstránite, Stlačením \"+\" pridáte" reactionSettingDescription2: "Ťahaním preusporiadate, kliknutím odstránite, Stlačením \"+\" pridáte"
rememberNoteVisibility: "Zapamätať nastavenia viditeľnosti poznámky" rememberNoteVisibility: "Zapamätať nastavenia viditeľnosti poznámky"
attachCancel: "Odstrániť prílohu" attachCancel: "Odstrániť prílohu"
@ -822,8 +821,6 @@ makeReactionsPublicDescription: "Toto spraví všetky vaše minulé reakcie vidi
classic: "Klasika" classic: "Klasika"
muteThread: "Ztíšiť vlákno" muteThread: "Ztíšiť vlákno"
unmuteThread: "Zrušiť stíšenie vlákna" unmuteThread: "Zrušiť stíšenie vlákna"
ffVisibility: "Viditeľnosť sledujúcich/sledovaných"
ffVisibilityDescription: "Umožňuje nastaviť kto vidí koho sledujete a kto vás sleduje."
continueThread: "Zobraziť pokračovanie vlákna" continueThread: "Zobraziť pokračovanie vlákna"
deleteAccountConfirm: "Toto nezvrátiteľne vymaže váš účet. Pokračovať?" deleteAccountConfirm: "Toto nezvrátiteľne vymaže váš účet. Pokračovať?"
incorrectPassword: "Nesprávne heslo." incorrectPassword: "Nesprávne heslo."

View File

@ -118,7 +118,6 @@ sensitive: "Känsligt innehåll"
add: "Lägg till" add: "Lägg till"
reaction: "Reaktioner" reaction: "Reaktioner"
reactions: "Reaktioner" reactions: "Reaktioner"
reactionSetting: "Reaktioner som ska visas i reaktionsväljaren"
reactionSettingDescription2: "Dra för att omordna, klicka för att radera, tryck \"+\" för att lägga till." reactionSettingDescription2: "Dra för att omordna, klicka för att radera, tryck \"+\" för att lägga till."
rememberNoteVisibility: "Komihåg notvisningsinställningar" rememberNoteVisibility: "Komihåg notvisningsinställningar"
attachCancel: "Ta bort bilaga" attachCancel: "Ta bort bilaga"

View File

@ -121,7 +121,6 @@ sensitive: "เนื้อหาที่ละเอียดอ่อน NSFW
add: "เพิ่ม" add: "เพิ่ม"
reaction: "รีแอคชั่น" reaction: "รีแอคชั่น"
reactions: "รีแอคชั่น" reactions: "รีแอคชั่น"
reactionSetting: "รีแอคชั่นไปยังแสดงผลในตัวเลือกการรีแอคชั่น"
reactionSettingDescription2: "กดลากเพื่อจัดลำดับใหม่ กดคลิกเพื่อลบ กด \"+\" เพื่อเพิ่ม" reactionSettingDescription2: "กดลากเพื่อจัดลำดับใหม่ กดคลิกเพื่อลบ กด \"+\" เพื่อเพิ่ม"
rememberNoteVisibility: "จดจำการตั้งค่าการมองเห็นตัวโน้ต" rememberNoteVisibility: "จดจำการตั้งค่าการมองเห็นตัวโน้ต"
attachCancel: "ลบไฟล์ออกที่แนบมา" attachCancel: "ลบไฟล์ออกที่แนบมา"
@ -870,8 +869,6 @@ makeReactionsPublicDescription: "การทำเช่นนี้จะท
classic: "คลาสสิค" classic: "คลาสสิค"
muteThread: "ปิดเสียงเธรด" muteThread: "ปิดเสียงเธรด"
unmuteThread: "เปิดเสียงเธรด" unmuteThread: "เปิดเสียงเธรด"
ffVisibility: "การมองเห็นผู้ติดตาม/ผู้ติดตาม"
ffVisibilityDescription: "ช่วยให้คุณสามารถกำหนดค่าได้ว่าใครสามารถดูได้ว่าคุณติดตามใครและใครติดตามคุณบ้าง"
continueThread: "ดูความต่อเนื่องเธรด" continueThread: "ดูความต่อเนื่องเธรด"
deleteAccountConfirm: "การดำเนินการนี้จะลบบัญชีของคุณอย่างถาวรเลยนะ แน่ใจหรอดำเนินการ?" deleteAccountConfirm: "การดำเนินการนี้จะลบบัญชีของคุณอย่างถาวรเลยนะ แน่ใจหรอดำเนินการ?"
incorrectPassword: "รหัสผ่านไม่ถูกต้อง" incorrectPassword: "รหัสผ่านไม่ถูกต้อง"

View File

@ -121,7 +121,6 @@ sensitive: "Hassas içerik"
add: "Ekle" add: "Ekle"
reaction: "Tepkiler" reaction: "Tepkiler"
reactions: "Tepkiler" reactions: "Tepkiler"
reactionSetting: "Palette görünecek tepkiler"
reactionSettingDescription2: "Sıralamak için sürükleyin, silmek için tıklayın, eklemek için \"+\" tuşuna tıklayın." reactionSettingDescription2: "Sıralamak için sürükleyin, silmek için tıklayın, eklemek için \"+\" tuşuna tıklayın."
rememberNoteVisibility: "Görünürlük ayarlarını hatırla" rememberNoteVisibility: "Görünürlük ayarlarını hatırla"
attachCancel: "Eki sil" attachCancel: "Eki sil"

View File

@ -55,6 +55,7 @@ copyRSS: "Скопіювати RSS"
copyUsername: "Скопіювати ім’я користувача" copyUsername: "Скопіювати ім’я користувача"
copyUserId: "Копіювати ID користувача" copyUserId: "Копіювати ID користувача"
copyNoteId: "блокнот ID користувача" copyNoteId: "блокнот ID користувача"
copyFileId: "Скопіювати ідентифікатор файлу."
searchUser: "Пошук користувачів" searchUser: "Пошук користувачів"
reply: "Відповісти" reply: "Відповісти"
loadMore: "Показати більше" loadMore: "Показати більше"
@ -115,7 +116,6 @@ sensitive: "NSFW"
add: "Додати" add: "Додати"
reaction: "Реакції" reaction: "Реакції"
reactions: "Реакції" reactions: "Реакції"
reactionSetting: "Налаштування реакцій"
reactionSettingDescription2: "Перемістити щоб змінити порядок, Клацнути мишою щоб видалити, Натиснути \"+\" щоб додати." reactionSettingDescription2: "Перемістити щоб змінити порядок, Клацнути мишою щоб видалити, Натиснути \"+\" щоб додати."
rememberNoteVisibility: "Пам’ятати параметри видимісті" rememberNoteVisibility: "Пам’ятати параметри видимісті"
attachCancel: "Видалити вкладення" attachCancel: "Видалити вкладення"
@ -133,6 +133,7 @@ unblockConfirm: "Ви впевнені, що хочете розблокуват
suspendConfirm: "Ви впевнені, що хочете призупинити цей акаунт?" suspendConfirm: "Ви впевнені, що хочете призупинити цей акаунт?"
unsuspendConfirm: "Ви впевнені, що хочете відновити цей акаунт?" unsuspendConfirm: "Ви впевнені, що хочете відновити цей акаунт?"
selectList: "Виберіть список" selectList: "Виберіть список"
editList: "Редагувати список."
selectChannel: "Виберіть канал" selectChannel: "Виберіть канал"
selectAntenna: "Виберіть антену" selectAntenna: "Виберіть антену"
selectWidget: "Виберіть віджет" selectWidget: "Виберіть віджет"
@ -448,6 +449,7 @@ or: "або"
language: "Мова" language: "Мова"
uiLanguage: "Мова інтерфейсу" uiLanguage: "Мова інтерфейсу"
aboutX: "Про {x}" aboutX: "Про {x}"
native: "місцевий"
disableDrawer: "Не використовувати висувні меню" disableDrawer: "Не використовувати висувні меню"
noHistory: "Історія порожня" noHistory: "Історія порожня"
signinHistory: "Історія входів" signinHistory: "Історія входів"
@ -526,6 +528,8 @@ output: "Вихід"
script: "Скрипт" script: "Скрипт"
disablePagesScript: "Вимкнути AiScript на Сторінках" disablePagesScript: "Вимкнути AiScript на Сторінках"
updateRemoteUser: "Оновити інформацію про віддаленого користувача" updateRemoteUser: "Оновити інформацію про віддаленого користувача"
unsetUserAvatar: "Деактивувати піктограму."
unsetUserBanner: "Випустити прапор."
deleteAllFiles: "Видалити всі файли" deleteAllFiles: "Видалити всі файли"
deleteAllFilesConfirm: "Ви дійсно хочете видалити всі файли?" deleteAllFilesConfirm: "Ви дійсно хочете видалити всі файли?"
removeAllFollowing: "Скасувати всі підписки" removeAllFollowing: "Скасувати всі підписки"
@ -813,7 +817,6 @@ makeReactionsPublicDescription: "Це зробить список усіх ва
classic: "Класичний" classic: "Класичний"
muteThread: "Приглушити тред" muteThread: "Приглушити тред"
unmuteThread: "Скасувати глушіння" unmuteThread: "Скасувати глушіння"
ffVisibility: "Видимість підписок/підписників"
continueThread: "Показати продовження треду" continueThread: "Показати продовження треду"
deleteAccountConfirm: "Це незворотно видалить ваш акаунт. Продовжити?" deleteAccountConfirm: "Це незворотно видалить ваш акаунт. Продовжити?"
incorrectPassword: "Неправильний пароль." incorrectPassword: "Неправильний пароль."

View File

@ -120,7 +120,6 @@ sensitive: "Sezuvchan"
add: "Qo'shish" add: "Qo'shish"
reaction: "Reaktsiyalar" reaction: "Reaktsiyalar"
reactions: "Reaktsiyalar" reactions: "Reaktsiyalar"
reactionSetting: "Reaksiyalar ro'yxati"
reactionSettingDescription2: "Qayta tartiblash uchun ushlab turib siljiting, oʻchirish uchun bosing, qoʻshish uchun “+” tugmasini bosing." reactionSettingDescription2: "Qayta tartiblash uchun ushlab turib siljiting, oʻchirish uchun bosing, qoʻshish uchun “+” tugmasini bosing."
rememberNoteVisibility: "Qaydning ko'rinish sozlamarini eslab qolish" rememberNoteVisibility: "Qaydning ko'rinish sozlamarini eslab qolish"
attachCancel: "Qo'shimchani olib tashlash" attachCancel: "Qo'shimchani olib tashlash"

View File

@ -121,7 +121,6 @@ sensitive: "Nhạy cảm"
add: "Thêm" add: "Thêm"
reaction: "Biểu cảm" reaction: "Biểu cảm"
reactions: "Biểu cảm" reactions: "Biểu cảm"
reactionSetting: "Chọn những biểu cảm hiển thị"
reactionSettingDescription2: "Kéo để sắp xếp, nhấn để xóa, nhấn \"+\" để thêm." reactionSettingDescription2: "Kéo để sắp xếp, nhấn để xóa, nhấn \"+\" để thêm."
rememberNoteVisibility: "Lưu kiểu tút mặc định" rememberNoteVisibility: "Lưu kiểu tút mặc định"
attachCancel: "Gỡ tập tin đính kèm" attachCancel: "Gỡ tập tin đính kèm"
@ -858,8 +857,6 @@ makeReactionsPublicDescription: "Điều này sẽ hiển thị công khai danh
classic: "Cổ điển" classic: "Cổ điển"
muteThread: "Không quan tâm nữa" muteThread: "Không quan tâm nữa"
unmuteThread: "Quan tâm tút này" unmuteThread: "Quan tâm tút này"
ffVisibility: "Hiển thị Theo dõi/Người theo dõi"
ffVisibilityDescription: "Quyết định ai có thể xem những người bạn theo dõi và những người theo dõi bạn."
continueThread: "Tiếp tục xem chuỗi tút" continueThread: "Tiếp tục xem chuỗi tút"
deleteAccountConfirm: "Điều này sẽ khiến tài khoản bị xóa vĩnh viễn. Vẫn tiếp tục?" deleteAccountConfirm: "Điều này sẽ khiến tài khoản bị xóa vĩnh viễn. Vẫn tiếp tục?"
incorrectPassword: "Sai mật khẩu." incorrectPassword: "Sai mật khẩu."

View File

@ -121,7 +121,6 @@ sensitive: "敏感内容"
add: "添加" add: "添加"
reaction: "回应" reaction: "回应"
reactions: "回应" reactions: "回应"
reactionSetting: "在选择器中显示回应"
reactionSettingDescription2: "拖动重新排序,单击删除,点击 + 添加。" reactionSettingDescription2: "拖动重新排序,单击删除,点击 + 添加。"
rememberNoteVisibility: "保存上次设置的可见性" rememberNoteVisibility: "保存上次设置的可见性"
attachCancel: "删除附件" attachCancel: "删除附件"
@ -867,8 +866,6 @@ makeReactionsPublicDescription: "将您发表过的回应设置成公开可见
classic: "经典" classic: "经典"
muteThread: "屏蔽帖子列表" muteThread: "屏蔽帖子列表"
unmuteThread: "取消屏蔽帖子列表" unmuteThread: "取消屏蔽帖子列表"
ffVisibility: "关注关系的可见范围"
ffVisibilityDescription: "您可以设置您的关注/关注者信息的公开范围"
continueThread: "查看更多帖子" continueThread: "查看更多帖子"
deleteAccountConfirm: "将要删除账户。是否确认?" deleteAccountConfirm: "将要删除账户。是否确认?"
incorrectPassword: "密码错误" incorrectPassword: "密码错误"
@ -1164,7 +1161,7 @@ _serverSettings:
appIconUsageExample: "例如:作为书签添加到 PWA 或手机主屏幕的时候" appIconUsageExample: "例如:作为书签添加到 PWA 或手机主屏幕的时候"
appIconStyleRecommendation: "因为有可能会被裁切为圆形或者圆角矩形,建议使用边缘带有留白背景的图标。" appIconStyleRecommendation: "因为有可能会被裁切为圆形或者圆角矩形,建议使用边缘带有留白背景的图标。"
appIconResolutionMustBe: "分辨率必须为 {resolution}。" appIconResolutionMustBe: "分辨率必须为 {resolution}。"
manifestJsonOverride: "覆盖 mainfest.json" manifestJsonOverride: "覆盖 manifest.json"
shortName: "简称" shortName: "简称"
shortNameDescription: "如果服务器的正式名称很长,可以用简称或者別名来替代。" shortNameDescription: "如果服务器的正式名称很长,可以用简称或者別名来替代。"
_accountMigration: _accountMigration:

View File

@ -121,7 +121,12 @@ sensitive: "敏感內容"
add: "新增" add: "新增"
reaction: "反應" reaction: "反應"
reactions: "反應" reactions: "反應"
reactionSetting: "在選擇器中顯示反應" emojiPicker: "表情符號選擇器"
pinnedEmojisForReactionSettingDescription: "選擇反應時可以設定要固定顯示在頂端的表情符號"
pinnedEmojisSettingDescription: "輸入表情符號時可以設定要固定顯示在頂端的表情符號"
emojiPickerDisplay: "顯示表情符號選擇器"
overwriteFromPinnedEmojisForReaction: "從反應複寫設定"
overwriteFromPinnedEmojis: "從一般複寫設定"
reactionSettingDescription2: "拖動以交換,點擊以刪除,按下「+」以新增。" reactionSettingDescription2: "拖動以交換,點擊以刪除,按下「+」以新增。"
rememberNoteVisibility: "記住貼文可見性" rememberNoteVisibility: "記住貼文可見性"
attachCancel: "移除附件" attachCancel: "移除附件"
@ -261,7 +266,7 @@ removed: "已刪除"
removeAreYouSure: "確定要刪掉「{x}」嗎?" removeAreYouSure: "確定要刪掉「{x}」嗎?"
deleteAreYouSure: "確定要刪掉「{x}」嗎?" deleteAreYouSure: "確定要刪掉「{x}」嗎?"
resetAreYouSure: "確定要重設嗎?" resetAreYouSure: "確定要重設嗎?"
areYouSure: "您確定要移除所有裝飾嗎" areYouSure: "是否確定"
saved: "已儲存" saved: "已儲存"
messaging: "聊天" messaging: "聊天"
upload: "上傳" upload: "上傳"
@ -627,11 +632,11 @@ tokenRequested: "允許存取帳戶"
pluginTokenRequestedDescription: "此外掛將擁有在此設定的權限。" pluginTokenRequestedDescription: "此外掛將擁有在此設定的權限。"
notificationType: "通知形式" notificationType: "通知形式"
edit: "編輯" edit: "編輯"
emailServer: "電郵伺服器" emailServer: "電伺服器"
enableEmail: "啟用發送電郵功能" enableEmail: "啟用發送電功能"
emailConfigInfo: "用於確認電郵地址及密碼重置" emailConfigInfo: "用於確認電地址及密碼重置"
email: "電子郵件" email: "電子郵件"
emailAddress: "電郵地址" emailAddress: "電子郵件位址"
smtpConfig: "SMTP 伺服器設定" smtpConfig: "SMTP 伺服器設定"
smtpHost: "主機" smtpHost: "主機"
smtpPort: "埠" smtpPort: "埠"
@ -726,7 +731,7 @@ disableShowingAnimatedImages: "不播放動態圖檔"
highlightSensitiveMedia: "強調敏感標記" highlightSensitiveMedia: "強調敏感標記"
verificationEmailSent: "已發送驗證電子郵件。請點擊進入電子郵件中的鏈接完成驗證。" verificationEmailSent: "已發送驗證電子郵件。請點擊進入電子郵件中的鏈接完成驗證。"
notSet: "未設定" notSet: "未設定"
emailVerified: "已成功驗證您的電郵" emailVerified: "已成功驗證您的電件地址"
noteFavoritesCount: "我的最愛貼文的數目" noteFavoritesCount: "我的最愛貼文的數目"
pageLikesCount: "頁面被按讚次數" pageLikesCount: "頁面被按讚次數"
pageLikedCount: "頁面被按讚次數" pageLikedCount: "頁面被按讚次數"
@ -778,11 +783,11 @@ capacity: "容量"
inUse: "已使用" inUse: "已使用"
editCode: "編輯代碼" editCode: "編輯代碼"
apply: "套用" apply: "套用"
receiveAnnouncementFromInstance: "接收由本實例發出的電郵通知" receiveAnnouncementFromInstance: "接收來自伺服器的通知"
emailNotification: "郵件通知" emailNotification: "郵件通知"
publish: "發布" publish: "發布"
inChannelSearch: "頻道内搜尋" inChannelSearch: "頻道内搜尋"
useReactionPickerForContextMenu: "點擊右鍵開啟反應工具欄" useReactionPickerForContextMenu: "點擊右鍵開啟反應選擇器"
typingUsers: "{users}輸入中" typingUsers: "{users}輸入中"
jumpToSpecifiedDate: "跳轉到特定日期" jumpToSpecifiedDate: "跳轉到特定日期"
showingPastTimeline: "顯示過往的時間軸" showingPastTimeline: "顯示過往的時間軸"
@ -876,8 +881,8 @@ makeReactionsPublicDescription: "將您做過的反應設為公開可見。"
classic: "經典" classic: "經典"
muteThread: "將貼文串設為靜音" muteThread: "將貼文串設為靜音"
unmuteThread: "將貼文串的靜音解除" unmuteThread: "將貼文串的靜音解除"
ffVisibility: "連繫的可見性" followingVisibility: "追隨中的可見性"
ffVisibilityDescription: "您可以設定追隨或追隨者資訊的公開範圍" followersVisibility: "追隨者的可見性"
continueThread: "查看更多貼文" continueThread: "查看更多貼文"
deleteAccountConfirm: "將要刪除帳戶。是否確定?" deleteAccountConfirm: "將要刪除帳戶。是否確定?"
incorrectPassword: "密碼錯誤。" incorrectPassword: "密碼錯誤。"
@ -950,7 +955,7 @@ cannotUploadBecauseExceedsFileSizeLimit: "由於超過了檔案大小的限制
beta: "測試版" beta: "測試版"
enableAutoSensitive: "自動 NSFW 判定" enableAutoSensitive: "自動 NSFW 判定"
enableAutoSensitiveDescription: "如果可用,它將使用機器學習技術判斷檔案是否需要標記為敏感。即使關閉此功能,也可能會依實例規則而自動啟用。" enableAutoSensitiveDescription: "如果可用,它將使用機器學習技術判斷檔案是否需要標記為敏感。即使關閉此功能,也可能會依實例規則而自動啟用。"
activeEmailValidationDescription: "積極驗證使用者的電郵地址,以判斷它是否可以通訊。關閉此選項代表只會檢查地址是否符合格式。" activeEmailValidationDescription: "主動地驗證使用者的電子郵件地址,以確定是否是一次性地址以及是否可以真正與其進行通訊。關閉時,僅檢查格式是否正確。"
navbar: "導覽列" navbar: "導覽列"
shuffle: "隨機" shuffle: "隨機"
account: "帳戶" account: "帳戶"
@ -1173,6 +1178,11 @@ doReaction: "做出反應"
code: "程式碼" code: "程式碼"
reloadRequiredToApplySettings: "需要重新載入頁面設定才能生效。" reloadRequiredToApplySettings: "需要重新載入頁面設定才能生效。"
remainingN: "剩餘:{n}" remainingN: "剩餘:{n}"
overwriteContentConfirm: "確定要覆蓋目前的內容嗎?"
seasonalScreenEffect: "隨季節變換畫面的呈現"
decorate: "設置頭像裝飾"
addMfmFunction: "插入MFM功能語法"
enableQuickAddMfmFunction: "顯示高級MFM選擇器"
_announcement: _announcement:
forExistingUsers: "僅限既有的使用者" forExistingUsers: "僅限既有的使用者"
forExistingUsersDescription: "啟用代表僅向現存使用者顯示;停用代表張貼後註冊的新使用者也會看到。" forExistingUsersDescription: "啟用代表僅向現存使用者顯示;停用代表張貼後註冊的新使用者也會看到。"
@ -1209,7 +1219,7 @@ _initialTutorial:
skipAreYouSure: "結束教學模式?" skipAreYouSure: "結束教學模式?"
_landing: _landing:
title: "歡迎使用本教學課程" title: "歡迎使用本教學課程"
description: "在這裡您可以查看Misskey的基本使用方法和功能。" description: "在這裡您可以查看 Misskey 的基本使用方法和功能。"
_note: _note:
title: "什麼是貼文?" title: "什麼是貼文?"
description: "在Misskey上發布的內容稱為「貼文」。貼文在時間軸上按時間順序排列並即時更新。" description: "在Misskey上發布的內容稱為「貼文」。貼文在時間軸上按時間順序排列並即時更新。"
@ -1633,6 +1643,7 @@ _emailUnavailable:
disposable: "不是永久可用的地址" disposable: "不是永久可用的地址"
mx: "郵件伺服器不正確" mx: "郵件伺服器不正確"
smtp: "郵件伺服器沒有應答" smtp: "郵件伺服器沒有應答"
banned: "無法使用此電子郵件地址註冊"
_ffVisibility: _ffVisibility:
public: "公開" public: "公開"
followers: "只有關注您的使用者能看到" followers: "只有關注您的使用者能看到"
@ -2041,7 +2052,7 @@ _profile:
changeAvatar: "更換大頭貼" changeAvatar: "更換大頭貼"
changeBanner: "變更橫幅圖像" changeBanner: "變更橫幅圖像"
verifiedLinkDescription: "如果輸入包含您個人資料的網站 URL欄位旁邊將出現驗證圖示。" verifiedLinkDescription: "如果輸入包含您個人資料的網站 URL欄位旁邊將出現驗證圖示。"
avatarDecorationMax: "最多可以設置{max}個裝飾。" avatarDecorationMax: "最多可以設置 {max} 個裝飾。"
_exportOrImport: _exportOrImport:
allNotes: "所有貼文" allNotes: "所有貼文"
favoritedNotes: "「我的最愛」貼文" favoritedNotes: "「我的最愛」貼文"
@ -2163,6 +2174,7 @@ _notification:
pollEnded: "問卷調查已產生結果" pollEnded: "問卷調查已產生結果"
newNote: "新的貼文" newNote: "新的貼文"
unreadAntennaNote: "天線 {name}" unreadAntennaNote: "天線 {name}"
roleAssigned: "已授予角色"
emptyPushNotificationMessage: "推送通知已更新" emptyPushNotificationMessage: "推送通知已更新"
achievementEarned: "獲得成就" achievementEarned: "獲得成就"
testNotification: "通知測試" testNotification: "通知測試"
@ -2184,6 +2196,7 @@ _notification:
pollEnded: "問卷調查結束" pollEnded: "問卷調查結束"
receiveFollowRequest: "已收到追隨請求" receiveFollowRequest: "已收到追隨請求"
followRequestAccepted: "追隨請求已接受" followRequestAccepted: "追隨請求已接受"
roleAssigned: "已授予角色"
achievementEarned: "獲得成就" achievementEarned: "獲得成就"
app: "應用程式通知" app: "應用程式通知"
_actions: _actions:

View File

@ -1,6 +1,6 @@
{ {
"name": "misskey", "name": "misskey",
"version": "2023.12.0-beta.5", "version": "2023.12.2",
"codename": "nasubi", "codename": "nasubi",
"repository": { "repository": {
"type": "git", "type": "git",
@ -18,7 +18,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 --filter backend 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", "build-misskey-js-with-types": "pnpm --filter backend 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",
"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",

View File

@ -160,7 +160,6 @@ module.exports = {
testMatch: [ testMatch: [
"<rootDir>/test/unit/**/*.ts", "<rootDir>/test/unit/**/*.ts",
"<rootDir>/src/**/*.test.ts", "<rootDir>/src/**/*.test.ts",
"<rootDir>/test/e2e/**/*.ts",
], ],
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped

View File

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

View File

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

View File

@ -0,0 +1,37 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class ffVisibility1702718871541 {
constructor() {
this.name = 'ffVisibility1702718871541';
}
async up(queryRunner) {
await queryRunner.query(`CREATE TYPE "public"."user_profile_followingvisibility_enum" AS ENUM('public', 'followers', 'private')`);
await queryRunner.query(`CREATE CAST ("public"."user_profile_ffvisibility_enum" AS "public"."user_profile_followingvisibility_enum") WITH INOUT AS ASSIGNMENT`);
await queryRunner.query(`CREATE TYPE "public"."user_profile_followersVisibility_enum" AS ENUM('public', 'followers', 'private')`);
await queryRunner.query(`CREATE CAST ("public"."user_profile_ffvisibility_enum" AS "public"."user_profile_followersVisibility_enum") WITH INOUT AS ASSIGNMENT`);
await queryRunner.query(`ALTER TABLE "user_profile" ADD "followingVisibility" "public"."user_profile_followingvisibility_enum" NOT NULL DEFAULT 'public'`);
await queryRunner.query(`ALTER TABLE "user_profile" ADD "followersVisibility" "public"."user_profile_followersVisibility_enum" NOT NULL DEFAULT 'public'`);
await queryRunner.query(`UPDATE "user_profile" SET "followingVisibility" = "ffVisibility"`);
await queryRunner.query(`UPDATE "user_profile" SET "followersVisibility" = "ffVisibility"`);
await queryRunner.query(`DROP CAST ("public"."user_profile_ffvisibility_enum" AS "public"."user_profile_followersVisibility_enum")`);
await queryRunner.query(`DROP CAST ("public"."user_profile_ffvisibility_enum" AS "public"."user_profile_followingvisibility_enum")`);
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "ffVisibility"`);
await queryRunner.query(`DROP TYPE "public"."user_profile_ffvisibility_enum"`);
}
async down(queryRunner) {
await queryRunner.query(`CREATE TYPE "public"."user_profile_ffvisibility_enum" AS ENUM('public', 'followers', 'private')`);
await queryRunner.query(`ALTER TABLE "user_profile" ADD "ffVisibility" "public"."user_profile_ffvisibility_enum" NOT NULL DEFAULT 'public'`);
await queryRunner.query(`CREATE CAST ("public"."user_profile_followingvisibility_enum" AS "public"."user_profile_ffvisibility_enum") WITH INOUT AS ASSIGNMENT`);
await queryRunner.query(`UPDATE "user_profile" SET "ffVisibility" = "followingVisibility"`);
await queryRunner.query(`DROP CAST ("public"."user_profile_followingvisibility_enum" AS "public"."user_profile_ffvisibility_enum")`);
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "followersVisibility"`);
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "followingVisibility"`);
await queryRunner.query(`DROP TYPE "public"."user_profile_followersVisibility_enum"`);
await queryRunner.query(`DROP TYPE "public"."user_profile_followingvisibility_enum"`);
}
}

View File

@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class bannedEmailDomains1703209889304 {
constructor() {
this.name = 'bannedEmailDomains1703209889304';
}
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "bannedEmailDomains" character varying(1024) array NOT NULL DEFAULT '{}'`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "bannedEmailDomains"`);
}
}

View File

@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class SupportTrueMailApi1703658526000 {
name = 'SupportTrueMailApi1703658526000'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "truemailInstance" character varying(1024)`);
await queryRunner.query(`ALTER TABLE "meta" ADD "truemailAuthKey" character varying(1024)`);
await queryRunner.query(`ALTER TABLE "meta" ADD "enableTruemailApi" boolean NOT NULL DEFAULT false`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableTruemailApi"`);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "truemailInstance"`);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "truemailAuthKey"`);
}
}

View File

@ -0,0 +1,22 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class SupportMcaptcha1704373210054 {
name = 'SupportMcaptcha1704373210054'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "enableMcaptcha" boolean NOT NULL DEFAULT false`);
await queryRunner.query(`ALTER TABLE "meta" ADD "mcaptchaSitekey" character varying(1024)`);
await queryRunner.query(`ALTER TABLE "meta" ADD "mcaptchaSecretKey" character varying(1024)`);
await queryRunner.query(`ALTER TABLE "meta" ADD "mcaptchaInstanceUrl" character varying(1024)`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "mcaptchaInstanceUrl"`);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "mcaptchaSecretKey"`);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "mcaptchaSitekey"`);
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableMcaptcha"`);
}
}

View File

@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class BubbleGameRecord1704959805077 {
name = 'BubbleGameRecord1704959805077'
async up(queryRunner) {
await queryRunner.query(`CREATE TABLE "bubble_game_record" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "seededAt" TIMESTAMP WITH TIME ZONE NOT NULL, "seed" character varying(1024) NOT NULL, "gameVersion" integer NOT NULL, "gameMode" character varying(128) NOT NULL, "score" integer NOT NULL, "logs" jsonb NOT NULL DEFAULT '[]', "isVerified" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_a75395fe404b392e2893b50d7ea" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_75276757070d21fdfaf4c05290" ON "bubble_game_record" ("userId") `);
await queryRunner.query(`CREATE INDEX "IDX_4ae7053179014915d1432d3f40" ON "bubble_game_record" ("seededAt") `);
await queryRunner.query(`CREATE INDEX "IDX_26d4ee490b5a487142d35466ee" ON "bubble_game_record" ("score") `);
await queryRunner.query(`ALTER TABLE "bubble_game_record" ADD CONSTRAINT "FK_75276757070d21fdfaf4c052909" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "bubble_game_record" DROP CONSTRAINT "FK_75276757070d21fdfaf4c052909"`);
await queryRunner.query(`DROP INDEX "public"."IDX_26d4ee490b5a487142d35466ee"`);
await queryRunner.query(`DROP INDEX "public"."IDX_4ae7053179014915d1432d3f40"`);
await queryRunner.query(`DROP INDEX "public"."IDX_75276757070d21fdfaf4c05290"`);
await queryRunner.query(`DROP TABLE "bubble_game_record"`);
}
}

View File

@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export class OptimizeNoteIndexForArrayColumns1705222772858 {
name = 'OptimizeNoteIndexForArrayColumns1705222772858'
async up(queryRunner) {
await queryRunner.query(`DROP INDEX "public"."IDX_796a8c03959361f97dc2be1d5c"`);
await queryRunner.query(`DROP INDEX "public"."IDX_54ebcb6d27222913b908d56fd8"`);
await queryRunner.query(`DROP INDEX "public"."IDX_88937d94d7443d9a99a76fa5c0"`);
await queryRunner.query(`DROP INDEX "public"."IDX_51c063b6a133a9cb87145450f5"`);
await queryRunner.query(`CREATE INDEX "IDX_NOTE_FILE_IDS" ON "note" using gin ("fileIds")`)
}
async down(queryRunner) {
await queryRunner.query(`DROP INDEX "IDX_NOTE_FILE_IDS"`)
await queryRunner.query(`CREATE INDEX "IDX_51c063b6a133a9cb87145450f5" ON "note" ("fileIds") `);
await queryRunner.query(`CREATE INDEX "IDX_88937d94d7443d9a99a76fa5c0" ON "note" ("tags") `);
await queryRunner.query(`CREATE INDEX "IDX_54ebcb6d27222913b908d56fd8" ON "note" ("mentions") `);
await queryRunner.query(`CREATE INDEX "IDX_796a8c03959361f97dc2be1d5c" ON "note" ("visibleUserIds") `);
}
}

View File

@ -13,6 +13,7 @@
"revert": "pnpm typeorm migration:revert -d ormconfig.js", "revert": "pnpm typeorm migration:revert -d ormconfig.js",
"check:connect": "node ./check_connect.js", "check:connect": "node ./check_connect.js",
"build": "swc src -d built -D", "build": "swc src -d built -D",
"build:test": "swc test-server -d built-test -D --config-file test-server/.swcrc",
"watch:swc": "swc src -d built -D -w", "watch:swc": "swc src -d built -D -w",
"build:tsc": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json", "build:tsc": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
"watch": "node watch.mjs", "watch": "node watch.mjs",
@ -21,11 +22,15 @@
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"eslint": "eslint --quiet \"src/**/*.ts\"", "eslint": "eslint --quiet \"src/**/*.ts\"",
"lint": "pnpm typecheck && pnpm eslint", "lint": "pnpm typecheck && pnpm eslint",
"jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit", "jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --config jest.config.unit.cjs",
"jest-and-coverage": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit", "jest:e2e": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --config jest.config.e2e.cjs",
"jest-and-coverage": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit --config jest.config.unit.cjs",
"jest-and-coverage:e2e": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit --config jest.config.e2e.cjs",
"jest-clear": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --clearCache", "jest-clear": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --clearCache",
"test": "pnpm jest", "test": "pnpm jest",
"test: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",
"generate-api-json": "node ./generate_api_json.js" "generate-api-json": "node ./generate_api_json.js"
}, },
"optionalDependencies": { "optionalDependencies": {
@ -65,15 +70,17 @@
"@bull-board/api": "5.10.2", "@bull-board/api": "5.10.2",
"@bull-board/fastify": "5.10.2", "@bull-board/fastify": "5.10.2",
"@bull-board/ui": "5.10.2", "@bull-board/ui": "5.10.2",
"@discordapp/twemoji": "14.1.2", "@discordapp/twemoji": "15.0.2",
"@fastify/accepts": "4.3.0", "@fastify/accepts": "4.3.0",
"@fastify/cookie": "9.2.0", "@fastify/cookie": "9.2.0",
"@fastify/cors": "8.4.2", "@fastify/cors": "8.5.0",
"@fastify/express": "2.3.0", "@fastify/express": "2.3.0",
"@fastify/http-proxy": "9.3.0", "@fastify/http-proxy": "9.3.0",
"@fastify/multipart": "8.0.0", "@fastify/multipart": "8.0.0",
"@fastify/static": "6.12.0", "@fastify/static": "6.12.0",
"@fastify/view": "8.2.0", "@fastify/view": "8.2.0",
"@misskey-dev/sharp-read-bmp": "^1.1.1",
"@misskey-dev/summaly": "^5.0.3",
"@nestjs/common": "10.2.10", "@nestjs/common": "10.2.10",
"@nestjs/core": "10.2.10", "@nestjs/core": "10.2.10",
"@nestjs/testing": "10.2.10", "@nestjs/testing": "10.2.10",
@ -83,6 +90,7 @@
"@smithy/node-http-handler": "2.1.10", "@smithy/node-http-handler": "2.1.10",
"@swc/cli": "0.1.63", "@swc/cli": "0.1.63",
"@swc/core": "1.3.100", "@swc/core": "1.3.100",
"@twemoji/parser": "15.0.0",
"accepts": "1.3.8", "accepts": "1.3.8",
"ajv": "8.12.0", "ajv": "8.12.0",
"archiver": "6.0.1", "archiver": "6.0.1",
@ -121,8 +129,8 @@
"jsonld": "8.3.2", "jsonld": "8.3.2",
"jsrsasign": "10.9.0", "jsrsasign": "10.9.0",
"meilisearch": "0.36.0", "meilisearch": "0.36.0",
"mfm-js": "0.23.3", "mfm-js": "0.24.0",
"microformats-parser": "1.5.2", "microformats-parser": "2.0.2",
"mime-types": "2.1.35", "mime-types": "2.1.35",
"misskey-js": "workspace:*", "misskey-js": "workspace:*",
"ms": "3.0.0-canary.1", "ms": "3.0.0-canary.1",
@ -156,17 +164,14 @@
"sanitize-html": "2.11.0", "sanitize-html": "2.11.0",
"secure-json-parse": "2.7.0", "secure-json-parse": "2.7.0",
"sharp": "0.32.6", "sharp": "0.32.6",
"sharp-read-bmp": "github:misskey-dev/sharp-read-bmp",
"slacc": "0.0.10", "slacc": "0.0.10",
"strict-event-emitter-types": "2.0.0", "strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0", "stringz": "2.1.0",
"summaly": "github:misskey-dev/summaly",
"systeminformation": "5.21.20", "systeminformation": "5.21.20",
"tinycolor2": "1.6.0", "tinycolor2": "1.6.0",
"tmp": "0.2.1", "tmp": "0.2.1",
"tsc-alias": "1.8.8", "tsc-alias": "1.8.8",
"tsconfig-paths": "4.2.0", "tsconfig-paths": "4.2.0",
"twemoji-parser": "14.0.0",
"typeorm": "0.3.17", "typeorm": "0.3.17",
"typescript": "5.3.3", "typescript": "5.3.3",
"ulid": "2.3.0", "ulid": "2.3.0",
@ -177,6 +182,8 @@
}, },
"devDependencies": { "devDependencies": {
"@jest/globals": "29.7.0", "@jest/globals": "29.7.0",
"@misskey-dev/eslint-plugin": "^1.0.0",
"@nestjs/platform-express": "^10.3.0",
"@simplewebauthn/typescript-types": "8.3.4", "@simplewebauthn/typescript-types": "8.3.4",
"@swc/jest": "0.2.29", "@swc/jest": "0.2.29",
"@types/accepts": "1.3.7", "@types/accepts": "1.3.7",
@ -195,7 +202,7 @@
"@types/jsrsasign": "10.5.12", "@types/jsrsasign": "10.5.12",
"@types/mime-types": "2.1.4", "@types/mime-types": "2.1.4",
"@types/ms": "0.7.34", "@types/ms": "0.7.34",
"@types/node": "20.10.4", "@types/node": "20.10.5",
"@types/node-fetch": "3.0.3", "@types/node-fetch": "3.0.3",
"@types/nodemailer": "6.4.14", "@types/nodemailer": "6.4.14",
"@types/oauth": "0.9.4", "@types/oauth": "0.9.4",
@ -225,9 +232,11 @@
"eslint": "8.56.0", "eslint": "8.56.0",
"eslint-plugin-import": "2.29.1", "eslint-plugin-import": "2.29.1",
"execa": "8.0.1", "execa": "8.0.1",
"fkill": "^9.0.0",
"jest": "29.7.0", "jest": "29.7.0",
"jest-mock": "29.7.0", "jest-mock": "29.7.0",
"nodemon": "3.0.2", "nodemon": "3.0.2",
"pid-port": "^1.0.0",
"simple-oauth2": "5.0.0" "simple-oauth2": "5.0.0"
} }
} }

View File

@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { setTimeout } from 'node:timers/promises';
import { Global, Inject, Module } from '@nestjs/common'; import { Global, Inject, Module } from '@nestjs/common';
import * as Redis from 'ioredis'; import * as Redis from 'ioredis';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
@ -12,6 +11,7 @@ import { DI } from './di-symbols.js';
import { Config, loadConfig } from './config.js'; import { Config, loadConfig } from './config.js';
import { createPostgresDataSource } from './postgres.js'; import { createPostgresDataSource } from './postgres.js';
import { RepositoryModule } from './models/RepositoryModule.js'; import { RepositoryModule } from './models/RepositoryModule.js';
import { allSettled } from './misc/promise-tracker.js';
import type { Provider, OnApplicationShutdown } from '@nestjs/common'; import type { Provider, OnApplicationShutdown } from '@nestjs/common';
const $config: Provider = { const $config: Provider = {
@ -33,7 +33,7 @@ const $meilisearch: Provider = {
useFactory: (config: Config) => { useFactory: (config: Config) => {
if (config.meilisearch) { if (config.meilisearch) {
return new MeiliSearch({ return new MeiliSearch({
host: `${config.meilisearch.ssl ? 'https' : 'http' }://${config.meilisearch.host}:${config.meilisearch.port}`, host: `${config.meilisearch.ssl ? 'https' : 'http'}://${config.meilisearch.host}:${config.meilisearch.port}`,
apiKey: config.meilisearch.apiKey, apiKey: config.meilisearch.apiKey,
}); });
} else { } else {
@ -91,17 +91,12 @@ export class GlobalModule implements OnApplicationShutdown {
@Inject(DI.redisForPub) private redisForPub: Redis.Redis, @Inject(DI.redisForPub) private redisForPub: Redis.Redis,
@Inject(DI.redisForSub) private redisForSub: Redis.Redis, @Inject(DI.redisForSub) private redisForSub: Redis.Redis,
@Inject(DI.redisForTimelines) private redisForTimelines: Redis.Redis, @Inject(DI.redisForTimelines) private redisForTimelines: Redis.Redis,
) {} ) { }
public async dispose(): Promise<void> { public async dispose(): Promise<void> {
if (process.env.NODE_ENV === 'test') { // Wait for all potential DB queries
// XXX: await allSettled();
// Shutting down the existing connections causes errors on Jest as // And then disconnect from DB
// Misskey has asynchronous postgres/redis connections that are not
// awaited.
// Let's wait for some random time for them to finish.
await setTimeout(5000);
}
await Promise.all([ await Promise.all([
this.db.destroy(), this.db.destroy(),
this.redisClient.disconnect(), this.redisClient.disconnect(),

View File

@ -87,6 +87,8 @@ export const ACHIEVEMENT_TYPES = [
'brainDiver', 'brainDiver',
'smashTestNotificationButton', 'smashTestNotificationButton',
'tutorialCompleted', 'tutorialCompleted',
'bubbleGameExplodingHead',
'bubbleGameDoubleExplodingHead',
] as const; ] as const;
@Injectable() @Injectable()

View File

@ -73,6 +73,37 @@ export class CaptchaService {
} }
} }
// https://codeberg.org/Gusted/mCaptcha/src/branch/main/mcaptcha.go
@bindThis
public async verifyMcaptcha(secret: string, siteKey: string, instanceHost: string, response: string | null | undefined): Promise<void> {
if (response == null) {
throw new Error('mcaptcha-failed: no response provided');
}
const endpointUrl = new URL('/api/v1/pow/siteverify', instanceHost);
const result = await this.httpRequestService.send(endpointUrl.toString(), {
method: 'POST',
body: JSON.stringify({
key: siteKey,
secret: secret,
token: response,
}),
headers: {
'Content-Type': 'application/json',
},
});
if (result.status !== 200) {
throw new Error('mcaptcha-failed: mcaptcha didn\'t return 200 OK');
}
const resp = (await result.json()) as { valid: boolean };
if (!resp.valid) {
throw new Error('mcaptcha-request-failed');
}
}
@bindThis @bindThis
public async verifyTurnstile(secret: string, response: string | null | undefined): Promise<void> { public async verifyTurnstile(secret: string, response: string | null | undefined): Promise<void> {
if (response == null) { if (response == null) {

View File

@ -145,7 +145,8 @@ export class DownloadService {
const parsedIp = ipaddr.parse(ip); const parsedIp = ipaddr.parse(ip);
for (const net of this.config.allowedPrivateNetworks ?? []) { for (const net of this.config.allowedPrivateNetworks ?? []) {
if (parsedIp.match(ipaddr.parseCIDR(net))) { const cidr = ipaddr.parseCIDR(net);
if (cidr[0].kind() === parsedIp.kind() && parsedIp.match(ipaddr.parseCIDR(net))) {
return false; return false;
} }
} }

View File

@ -7,7 +7,7 @@ import { randomUUID } from 'node:crypto';
import * as fs from 'node:fs'; import * as fs from 'node:fs';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import sharp from 'sharp'; import sharp from 'sharp';
import { sharpBmp } from 'sharp-read-bmp'; import { sharpBmp } from '@misskey-dev/sharp-read-bmp';
import { IsNull } from 'typeorm'; import { IsNull } from 'typeorm';
import { DeleteObjectCommandInput, PutObjectCommandInput, NoSuchKey } from '@aws-sdk/client-s3'; import { DeleteObjectCommandInput, PutObjectCommandInput, NoSuchKey } from '@aws-sdk/client-s3';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
@ -655,7 +655,7 @@ export class DriveService {
public async updateFile(file: MiDriveFile, values: Partial<MiDriveFile>, updater: MiUser) { public async updateFile(file: MiDriveFile, values: Partial<MiDriveFile>, updater: MiUser) {
const alwaysMarkNsfw = (await this.roleService.getUserPolicies(file.userId)).alwaysMarkNsfw; const alwaysMarkNsfw = (await this.roleService.getUserPolicies(file.userId)).alwaysMarkNsfw;
if (values.name && !this.driveFileEntityService.validateFileName(file.name)) { if (values.name != null && !this.driveFileEntityService.validateFileName(values.name)) {
throw new DriveService.InvalidFileNameError(); throw new DriveService.InvalidFileNameError();
} }

View File

@ -7,8 +7,8 @@ import { URLSearchParams } from 'node:url';
import * as nodemailer from 'nodemailer'; import * as nodemailer from 'nodemailer';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { validate as validateEmail } from 'deep-email-validator'; import { validate as validateEmail } from 'deep-email-validator';
import { SubOutputFormat } from 'deep-email-validator/dist/output/output.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { UtilityService } from '@/core/UtilityService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
@ -30,6 +30,7 @@ export class EmailService {
private metaService: MetaService, private metaService: MetaService,
private loggerService: LoggerService, private loggerService: LoggerService,
private utilityService: UtilityService,
private httpRequestService: HttpRequestService, private httpRequestService: HttpRequestService,
) { ) {
this.logger = this.loggerService.getLogger('email'); this.logger = this.loggerService.getLogger('email');
@ -155,7 +156,7 @@ export class EmailService {
@bindThis @bindThis
public async validateEmailForAccount(emailAddress: string): Promise<{ public async validateEmailForAccount(emailAddress: string): Promise<{
available: boolean; available: boolean;
reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp'; reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp' | 'banned' | 'network' | 'blacklist';
}> { }> {
const meta = await this.metaService.fetch(); const meta = await this.metaService.fetch();
@ -164,36 +165,46 @@ export class EmailService {
email: emailAddress, email: emailAddress,
}); });
const verifymailApi = meta.enableVerifymailApi && meta.verifymailAuthKey != null; let validated: {
let validated; valid: boolean,
reason?: string | null,
};
if (meta.enableActiveEmailValidation && meta.verifymailAuthKey) { if (meta.enableActiveEmailValidation) {
if (verifymailApi) { if (meta.enableVerifymailApi && meta.verifymailAuthKey != null) {
validated = await this.verifyMail(emailAddress, meta.verifymailAuthKey); validated = await this.verifyMail(emailAddress, meta.verifymailAuthKey);
} else if (meta.enableTruemailApi && meta.truemailInstance && meta.truemailAuthKey != null) {
validated = await this.trueMail(meta.truemailInstance, emailAddress, meta.truemailAuthKey);
} else { } else {
validated = meta.enableActiveEmailValidation ? await validateEmail({ validated = await validateEmail({
email: emailAddress, email: emailAddress,
validateRegex: true, validateRegex: true,
validateMx: true, validateMx: true,
validateTypo: false, // TLDを見ているみたいだけどclubとか弾かれるので validateTypo: false, // TLDを見ているみたいだけどclubとか弾かれるので
validateDisposable: true, // 捨てアドかどうかチェック validateDisposable: true, // 捨てアドかどうかチェック
validateSMTP: false, // 日本だと25ポートが殆どのプロバイダーで塞がれていてタイムアウトになるので validateSMTP: false, // 日本だと25ポートが殆どのプロバイダーで塞がれていてタイムアウトになるので
}) : { valid: true, reason: null }; });
} }
} else { } else {
validated = { valid: true, reason: null }; validated = { valid: true, reason: null };
} }
const available = exist === 0 && validated.valid; const emailDomain: string = emailAddress.split('@')[1];
const isBanned = this.utilityService.isBlockedHost(meta.bannedEmailDomains, emailDomain);
const available = exist === 0 && validated.valid && !isBanned;
return { return {
available, available,
reason: available ? null : reason: available ? null :
exist !== 0 ? 'used' : exist !== 0 ? 'used' :
isBanned ? 'banned' :
validated.reason === 'regex' ? 'format' : validated.reason === 'regex' ? 'format' :
validated.reason === 'disposable' ? 'disposable' : validated.reason === 'disposable' ? 'disposable' :
validated.reason === 'mx' ? 'mx' : validated.reason === 'mx' ? 'mx' :
validated.reason === 'smtp' ? 'smtp' : validated.reason === 'smtp' ? 'smtp' :
validated.reason === 'network' ? 'network' :
validated.reason === 'blacklist' ? 'blacklist' :
null, null,
}; };
} }
@ -258,4 +269,67 @@ export class EmailService {
reason: null, reason: null,
}; };
} }
private async trueMail<T>(truemailInstance: string, emailAddress: string, truemailAuthKey: string): Promise<{
valid: boolean;
reason: 'used' | 'format' | 'blacklist' | 'mx' | 'smtp' | 'network' | T | null;
}> {
const endpoint = truemailInstance + '?email=' + emailAddress;
try {
const res = await this.httpRequestService.send(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: truemailAuthKey
},
});
const json = (await res.json()) as {
email: string;
success: boolean;
errors?: {
list_match?: string;
regex?: string;
mx?: string;
smtp?: string;
} | null;
};
if (json.email === undefined || (json.email !== undefined && json.errors?.regex)) {
return {
valid: false,
reason: 'format',
};
}
if (json.errors?.smtp) {
return {
valid: false,
reason: 'smtp',
};
}
if (json.errors?.mx) {
return {
valid: false,
reason: 'mx',
};
}
if (!json.success) {
return {
valid: false,
reason: json.errors?.list_match as T || 'blacklist',
};
}
return {
valid: true,
reason: null,
};
} catch (error) {
return {
valid: false,
reason: 'network',
};
}
}
} }

View File

@ -77,6 +77,17 @@ export class FeaturedService {
return Array.from(ranking.keys()); return Array.from(ranking.keys());
} }
@bindThis
private async removeFromRanking(name: string, windowRange: number, element: string): Promise<void> {
const currentWindow = this.getCurrentWindow(windowRange);
const previousWindow = currentWindow - 1;
const redisPipeline = this.redisClient.pipeline();
redisPipeline.zrem(`${name}:${currentWindow}`, element);
redisPipeline.zrem(`${name}:${previousWindow}`, element);
await redisPipeline.exec();
}
@bindThis @bindThis
public updateGlobalNotesRanking(noteId: MiNote['id'], score = 1): Promise<void> { public updateGlobalNotesRanking(noteId: MiNote['id'], score = 1): Promise<void> {
return this.updateRankingOf('featuredGlobalNotesRanking', GLOBAL_NOTES_RANKING_WINDOW, noteId, score); return this.updateRankingOf('featuredGlobalNotesRanking', GLOBAL_NOTES_RANKING_WINDOW, noteId, score);
@ -126,4 +137,9 @@ export class FeaturedService {
public getHashtagsRanking(threshold: number): Promise<string[]> { public getHashtagsRanking(threshold: number): Promise<string[]> {
return this.getRankingOf('featuredHashtagsRanking', HASHTAG_RANKING_WINDOW, threshold); return this.getRankingOf('featuredHashtagsRanking', HASHTAG_RANKING_WINDOW, threshold);
} }
@bindThis
public removeHashtagsFromRanking(hashtag: string): Promise<void> {
return this.removeFromRanking('featuredHashtagsRanking', HASHTAG_RANKING_WINDOW, hashtag);
}
} }

View File

@ -15,6 +15,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { FeaturedService } from '@/core/FeaturedService.js'; import { FeaturedService } from '@/core/FeaturedService.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { UtilityService } from '@/core/UtilityService.js';
@Injectable() @Injectable()
export class HashtagService { export class HashtagService {
@ -29,6 +30,7 @@ export class HashtagService {
private featuredService: FeaturedService, private featuredService: FeaturedService,
private idService: IdService, private idService: IdService,
private metaService: MetaService, private metaService: MetaService,
private utilityService: UtilityService,
) { ) {
} }
@ -161,6 +163,7 @@ export class HashtagService {
const instance = await this.metaService.fetch(); const instance = await this.metaService.fetch();
const hiddenTags = instance.hiddenTags.map(t => normalizeForSearch(t)); const hiddenTags = instance.hiddenTags.map(t => normalizeForSearch(t));
if (hiddenTags.includes(hashtag)) return; if (hiddenTags.includes(hashtag)) return;
if (this.utilityService.isSensitiveWordIncluded(hashtag, instance.sensitiveWords)) return;
// YYYYMMDDHHmm (10分間隔) // YYYYMMDDHHmm (10分間隔)
const now = new Date(); const now = new Date();

View File

@ -11,6 +11,7 @@ import { MiMeta } from '@/models/Meta.js';
import { GlobalEventService } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js'; import type { GlobalEvents } from '@/core/GlobalEventService.js';
import { FeaturedService } from '@/core/FeaturedService.js';
import type { OnApplicationShutdown } from '@nestjs/common'; import type { OnApplicationShutdown } from '@nestjs/common';
@Injectable() @Injectable()
@ -25,6 +26,7 @@ export class MetaService implements OnApplicationShutdown {
@Inject(DI.db) @Inject(DI.db)
private db: DataSource, private db: DataSource,
private featuredService: FeaturedService,
private globalEventService: GlobalEventService, private globalEventService: GlobalEventService,
) { ) {
//this.onMessage = this.onMessage.bind(this); //this.onMessage = this.onMessage.bind(this);
@ -95,6 +97,8 @@ export class MetaService implements OnApplicationShutdown {
@bindThis @bindThis
public async update(data: Partial<MiMeta>): Promise<MiMeta> { public async update(data: Partial<MiMeta>): Promise<MiMeta> {
let before: MiMeta | undefined;
const updated = await this.db.transaction(async transactionalEntityManager => { const updated = await this.db.transaction(async transactionalEntityManager => {
const metas = await transactionalEntityManager.find(MiMeta, { const metas = await transactionalEntityManager.find(MiMeta, {
order: { order: {
@ -102,10 +106,10 @@ export class MetaService implements OnApplicationShutdown {
}, },
}); });
const meta = metas[0]; before = metas[0];
if (meta) { if (before) {
await transactionalEntityManager.update(MiMeta, meta.id, data); await transactionalEntityManager.update(MiMeta, before.id, data);
const metas = await transactionalEntityManager.find(MiMeta, { const metas = await transactionalEntityManager.find(MiMeta, {
order: { order: {
@ -119,6 +123,21 @@ export class MetaService implements OnApplicationShutdown {
} }
}); });
if (data.hiddenTags) {
process.nextTick(() => {
const hiddenTags = new Set<string>(data.hiddenTags);
if (before) {
for (const previousHiddenTag of before.hiddenTags) {
hiddenTags.delete(previousHiddenTag);
}
}
for (const hiddenTag of hiddenTags) {
this.featuredService.removeHashtagsFromRanking(hiddenTag);
}
});
}
this.globalEventService.publishInternalEvent('metaUpdated', updated); this.globalEventService.publishInternalEvent('metaUpdated', updated);
return updated; return updated;

View File

@ -58,6 +58,7 @@ import { FanoutTimelineService } from '@/core/FanoutTimelineService.js';
import { UtilityService } from '@/core/UtilityService.js'; import { UtilityService } from '@/core/UtilityService.js';
import { UserBlockingService } from '@/core/UserBlockingService.js'; import { UserBlockingService } from '@/core/UserBlockingService.js';
import { isReply } from '@/misc/is-reply.js'; import { isReply } from '@/misc/is-reply.js';
import { trackPromise } from '@/misc/promise-tracker.js';
type NotificationType = 'reply' | 'renote' | 'quote' | 'mention'; type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
@ -253,7 +254,7 @@ export class NoteCreateService implements OnApplicationShutdown {
if (data.visibility === 'public' && data.channel == null) { if (data.visibility === 'public' && data.channel == null) {
const sensitiveWords = meta.sensitiveWords; const sensitiveWords = meta.sensitiveWords;
if (this.isSensitive(data, sensitiveWords)) { if (this.utilityService.isSensitiveWordIncluded(data.cw ?? data.text ?? '', sensitiveWords)) {
data.visibility = 'home'; data.visibility = 'home';
} else if ((await this.roleService.getUserPolicies(user.id)).canPublicNote === false) { } else if ((await this.roleService.getUserPolicies(user.id)).canPublicNote === false) {
data.visibility = 'home'; data.visibility = 'home';
@ -293,7 +294,7 @@ export class NoteCreateService implements OnApplicationShutdown {
} }
// Check blocking // Check blocking
if (data.renote && data.text == null && data.poll == null && (data.files == null || data.files.length === 0)) { if (data.renote && !this.isQuote(data)) {
if (data.renote.userHost === null) { if (data.renote.userHost === null) {
if (data.renote.userId !== user.id) { if (data.renote.userId !== user.id) {
const blocked = await this.userBlockingService.checkBlocked(data.renote.userId, user.id); const blocked = await this.userBlockingService.checkBlocked(data.renote.userId, user.id);
@ -324,6 +325,9 @@ export class NoteCreateService implements OnApplicationShutdown {
data.text = data.text.slice(0, DB_MAX_NOTE_TEXT_LENGTH); data.text = data.text.slice(0, DB_MAX_NOTE_TEXT_LENGTH);
} }
data.text = data.text.trim(); data.text = data.text.trim();
if (data.text === '') {
data.text = null;
}
} else { } else {
data.text = null; data.text = null;
} }
@ -622,7 +626,7 @@ export class NoteCreateService implements OnApplicationShutdown {
// If it is renote // If it is renote
if (data.renote) { if (data.renote) {
const type = data.text ? 'quote' : 'renote'; const type = this.isQuote(data) ? 'quote' : 'renote';
// Notify // Notify
if (data.renote.userHost === null) { if (data.renote.userHost === null) {
@ -676,7 +680,7 @@ export class NoteCreateService implements OnApplicationShutdown {
this.relayService.deliverToRelays(user, noteActivity); this.relayService.deliverToRelays(user, noteActivity);
} }
dm.execute(); trackPromise(dm.execute());
})(); })();
} }
//#endregion //#endregion
@ -705,28 +709,9 @@ export class NoteCreateService implements OnApplicationShutdown {
} }
@bindThis @bindThis
private isSensitive(note: Option, sensitiveWord: string[]): boolean { private isQuote(note: Option): note is Option & { renote: MiNote } {
if (sensitiveWord.length > 0) { // sync with misc/is-quote.ts
const text = note.cw ?? note.text ?? ''; return !!note.renote && (!!note.text || !!note.cw || (!!note.files && !!note.files.length) || !!note.poll);
if (text === '') return false;
const matched = sensitiveWord.some(filter => {
// represents RegExp
const regexp = filter.match(/^\/(.+)\/(.*)$/);
// This should never happen due to input sanitisation.
if (!regexp) {
const words = filter.split(' ');
return words.every(keyword => text.includes(keyword));
}
try {
return new RE2(regexp[1], regexp[2]).test(text);
} catch (err) {
// This should never happen due to input sanitisation.
return false;
}
});
if (matched) return true;
}
return false;
} }
@bindThis @bindThis
@ -794,7 +779,7 @@ export class NoteCreateService implements OnApplicationShutdown {
private async renderNoteOrRenoteActivity(data: Option, note: MiNote) { private async renderNoteOrRenoteActivity(data: Option, note: MiNote) {
if (data.localOnly) return null; if (data.localOnly) return null;
const content = data.renote && data.text == null && data.poll == null && (data.files == null || data.files.length === 0) const content = data.renote && !this.isQuote(data)
? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note) ? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note)
: this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false), note); : this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false), note);
@ -906,6 +891,7 @@ export class NoteCreateService implements OnApplicationShutdown {
// ダイレクトのとき、そのリストが対象外のユーザーの場合 // ダイレクトのとき、そのリストが対象外のユーザーの場合
if ( if (
note.visibility === 'specified' && note.visibility === 'specified' &&
note.userId !== userListMembership.userListUserId &&
!note.visibleUserIds.some(v => v === userListMembership.userListUserId) !note.visibleUserIds.some(v => v === userListMembership.userListUserId)
) continue; ) continue;

View File

@ -14,6 +14,7 @@ import { IdService } from '@/core/IdService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js';
import type { NoteUnreadsRepository, MutingsRepository, NoteThreadMutingsRepository } from '@/models/_.js'; import type { NoteUnreadsRepository, MutingsRepository, NoteThreadMutingsRepository } from '@/models/_.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { trackPromise } from '@/misc/promise-tracker.js';
@Injectable() @Injectable()
export class NoteReadService implements OnApplicationShutdown { export class NoteReadService implements OnApplicationShutdown {
@ -107,7 +108,7 @@ export class NoteReadService implements OnApplicationShutdown {
// TODO: ↓まとめてクエリしたい // TODO: ↓まとめてクエリしたい
this.noteUnreadsRepository.countBy({ trackPromise(this.noteUnreadsRepository.countBy({
userId: userId, userId: userId,
isMentioned: true, isMentioned: true,
}).then(mentionsCount => { }).then(mentionsCount => {
@ -115,9 +116,9 @@ export class NoteReadService implements OnApplicationShutdown {
// 全て既読になったイベントを発行 // 全て既読になったイベントを発行
this.globalEventService.publishMainStream(userId, 'readAllUnreadMentions'); this.globalEventService.publishMainStream(userId, 'readAllUnreadMentions');
} }
}); }));
this.noteUnreadsRepository.countBy({ trackPromise(this.noteUnreadsRepository.countBy({
userId: userId, userId: userId,
isSpecified: true, isSpecified: true,
}).then(specifiedCount => { }).then(specifiedCount => {
@ -125,7 +126,7 @@ export class NoteReadService implements OnApplicationShutdown {
// 全て既読になったイベントを発行 // 全て既読になったイベントを発行
this.globalEventService.publishMainStream(userId, 'readAllUnreadSpecifiedNotes'); this.globalEventService.publishMainStream(userId, 'readAllUnreadSpecifiedNotes');
} }
}); }));
} }
} }

View File

@ -20,6 +20,7 @@ import { CacheService } from '@/core/CacheService.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import { UserListService } from '@/core/UserListService.js'; import { UserListService } from '@/core/UserListService.js';
import type { FilterUnionByProperty } from '@/types.js'; import type { FilterUnionByProperty } from '@/types.js';
import { trackPromise } from '@/misc/promise-tracker.js';
@Injectable() @Injectable()
export class NotificationService implements OnApplicationShutdown { export class NotificationService implements OnApplicationShutdown {
@ -74,7 +75,18 @@ export class NotificationService implements OnApplicationShutdown {
} }
@bindThis @bindThis
public async createNotification<T extends MiNotification['type']>( public createNotification<T extends MiNotification['type']>(
notifieeId: MiUser['id'],
type: T,
data: Omit<FilterUnionByProperty<MiNotification, 'type', T>, 'type' | 'id' | 'createdAt' | 'notifierId'>,
notifierId?: MiUser['id'] | null,
) {
trackPromise(
this.#createNotificationInternal(notifieeId, type, data, notifierId),
);
}
async #createNotificationInternal<T extends MiNotification['type']>(
notifieeId: MiUser['id'], notifieeId: MiUser['id'],
type: T, type: T,
data: Omit<FilterUnionByProperty<MiNotification, 'type', T>, 'type' | 'id' | 'createdAt' | 'notifierId'>, data: Omit<FilterUnionByProperty<MiNotification, 'type', T>, 'type' | 'id' | 'createdAt' | 'notifierId'>,

View File

@ -212,8 +212,8 @@ export class QueryService {
// または 自分自身 // または 自分自身
.orWhere('note.userId = :meId') .orWhere('note.userId = :meId')
// または 自分宛て // または 自分宛て
.orWhere(':meId = ANY(note.visibleUserIds)') .orWhere(':meIdAsList <@ note.visibleUserIds')
.orWhere(':meId = ANY(note.mentions)') .orWhere(':meIdAsList <@ note.mentions')
.orWhere(new Brackets(qb => { .orWhere(new Brackets(qb => {
qb qb
// または フォロワー宛ての投稿であり、 // または フォロワー宛ての投稿であり、
@ -228,7 +228,7 @@ export class QueryService {
})); }));
})); }));
q.setParameters({ meId: me.id }); q.setParameters({ meId: me.id, meIdAsList: [me.id] });
} }
} }

View File

@ -3,12 +3,12 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { setTimeout } from 'node:timers/promises';
import { Inject, Module, OnApplicationShutdown } from '@nestjs/common'; import { Inject, Module, OnApplicationShutdown } from '@nestjs/common';
import * as Bull from 'bullmq'; import * as Bull from 'bullmq';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import { QUEUE, baseQueueOptions } from '@/queue/const.js'; import { QUEUE, baseQueueOptions } from '@/queue/const.js';
import { allSettled } from '@/misc/promise-tracker.js';
import type { Provider } from '@nestjs/common'; import type { Provider } from '@nestjs/common';
import type { DeliverJobData, InboxJobData, EndedPollNotificationJobData, WebhookDeliverJobData, RelationshipJobData } from '../queue/types.js'; import type { DeliverJobData, InboxJobData, EndedPollNotificationJobData, WebhookDeliverJobData, RelationshipJobData } from '../queue/types.js';
@ -106,14 +106,9 @@ export class QueueModule implements OnApplicationShutdown {
) {} ) {}
public async dispose(): Promise<void> { public async dispose(): Promise<void> {
if (process.env.NODE_ENV === 'test') { // Wait for all potential queue jobs
// XXX: await allSettled();
// Shutting down the existing connections causes errors on Jest as // And then close all queues
// Misskey has asynchronous postgres/redis connections that are not
// awaited.
// Let's wait for some random time for them to finish.
await setTimeout(5000);
}
await Promise.all([ await Promise.all([
this.systemQueue.close(), this.systemQueue.close(),
this.endedPollNotificationQueue.close(), this.endedPollNotificationQueue.close(),

View File

@ -16,6 +16,7 @@ import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, Obj
import type { DbJobData, DeliverJobData, RelationshipJobData, ThinUser } from '../queue/types.js'; import type { DbJobData, DeliverJobData, RelationshipJobData, ThinUser } from '../queue/types.js';
import type httpSignature from '@peertube/http-signature'; import type httpSignature from '@peertube/http-signature';
import type * as Bull from 'bullmq'; import type * as Bull from 'bullmq';
import { ApRequestCreator } from '@/core/activitypub/ApRequestService.js';
@Injectable() @Injectable()
export class QueueService { export class QueueService {
@ -74,11 +75,15 @@ export class QueueService {
if (content == null) return null; if (content == null) return null;
if (to == null) return null; if (to == null) return null;
const contentBody = JSON.stringify(content);
const digest = ApRequestCreator.createDigest(contentBody);
const data: DeliverJobData = { const data: DeliverJobData = {
user: { user: {
id: user.id, id: user.id,
}, },
content, content: contentBody,
digest,
to, to,
isSharedInbox, isSharedInbox,
}; };
@ -103,6 +108,8 @@ export class QueueService {
@bindThis @bindThis
public async deliverMany(user: ThinUser, content: IActivity | null, inboxes: Map<string, boolean>) { public async deliverMany(user: ThinUser, content: IActivity | null, inboxes: Map<string, boolean>) {
if (content == null) return null; if (content == null) return null;
const contentBody = JSON.stringify(content);
const digest = ApRequestCreator.createDigest(contentBody);
const opts = { const opts = {
attempts: this.config.deliverJobMaxAttempts ?? 12, attempts: this.config.deliverJobMaxAttempts ?? 12,
@ -117,7 +124,8 @@ export class QueueService {
name: d[0], name: d[0],
data: { data: {
user, user,
content, content: contentBody,
digest,
to: d[0], to: d[0],
isSharedInbox: d[1], isSharedInbox: d[1],
} as DeliverJobData, } as DeliverJobData,
@ -174,6 +182,16 @@ export class QueueService {
}); });
} }
@bindThis
public createExportClipsJob(user: ThinUser) {
return this.dbQueue.add('exportClips', {
user: { id: user.id },
}, {
removeOnComplete: true,
removeOnFail: true,
});
}
@bindThis @bindThis
public createExportFavoritesJob(user: ThinUser) { public createExportFavoritesJob(user: ThinUser) {
return this.dbQueue.add('exportFavorites', { return this.dbQueue.add('exportFavorites', {

View File

@ -28,6 +28,7 @@ import { UserBlockingService } from '@/core/UserBlockingService.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js'; import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { RoleService } from '@/core/RoleService.js'; import { RoleService } from '@/core/RoleService.js';
import { FeaturedService } from '@/core/FeaturedService.js'; import { FeaturedService } from '@/core/FeaturedService.js';
import { trackPromise } from '@/misc/promise-tracker.js';
const FALLBACK = '❤'; const FALLBACK = '❤';
const PER_NOTE_REACTION_USER_PAIR_CACHE_MAX = 16; const PER_NOTE_REACTION_USER_PAIR_CACHE_MAX = 16;
@ -138,7 +139,7 @@ export class ReactionService {
reaction = reacterHost ? `:${name}@${reacterHost}:` : `:${name}:`; reaction = reacterHost ? `:${name}@${reacterHost}:` : `:${name}:`;
// センシティブ // センシティブ
if ((note.reactionAcceptance === 'nonSensitiveOnly') && emoji.isSensitive) { if ((note.reactionAcceptance === 'nonSensitiveOnly' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote') && emoji.isSensitive) {
reaction = FALLBACK; reaction = FALLBACK;
} }
} else { } else {
@ -268,7 +269,7 @@ export class ReactionService {
} }
} }
dm.execute(); trackPromise(dm.execute());
} }
//#endregion //#endregion
} }
@ -316,7 +317,7 @@ export class ReactionService {
dm.addDirectRecipe(reactee as MiRemoteUser); dm.addDirectRecipe(reactee as MiRemoteUser);
} }
dm.addFollowersRecipe(); dm.addFollowersRecipe();
dm.execute(); trackPromise(dm.execute());
} }
//#endregion //#endregion
} }

View File

@ -6,7 +6,14 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis'; import * as Redis from 'ioredis';
import { In } from 'typeorm'; import { In } from 'typeorm';
import type { MiRole, MiRoleAssignment, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/_.js'; import { ModuleRef } from '@nestjs/core';
import type {
MiRole,
MiRoleAssignment,
RoleAssignmentsRepository,
RolesRepository,
UsersRepository,
} from '@/models/_.js';
import { MemoryKVCache, MemorySingleCache } from '@/misc/cache.js'; import { MemoryKVCache, MemorySingleCache } from '@/misc/cache.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';
@ -16,12 +23,13 @@ import { CacheService } from '@/core/CacheService.js';
import type { RoleCondFormulaValue } from '@/models/Role.js'; import type { RoleCondFormulaValue } from '@/models/Role.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js'; import type { GlobalEvents } from '@/core/GlobalEventService.js';
import { IdService } from '@/core/IdService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js';
import { IdService } from '@/core/IdService.js';
import { ModerationLogService } from '@/core/ModerationLogService.js'; import { ModerationLogService } from '@/core/ModerationLogService.js';
import type { Packed } from '@/misc/json-schema.js'; import type { Packed } from '@/misc/json-schema.js';
import { FanoutTimelineService } from '@/core/FanoutTimelineService.js'; import { FanoutTimelineService } from '@/core/FanoutTimelineService.js';
import type { OnApplicationShutdown } from '@nestjs/common'; import { NotificationService } from '@/core/NotificationService.js';
import type { OnApplicationShutdown, OnModuleInit } from '@nestjs/common';
export type RolePolicies = { export type RolePolicies = {
gtlAvailable: boolean; gtlAvailable: boolean;
@ -78,14 +86,17 @@ export const DEFAULT_POLICIES: RolePolicies = {
}; };
@Injectable() @Injectable()
export class RoleService implements OnApplicationShutdown { export class RoleService implements OnApplicationShutdown, OnModuleInit {
private rolesCache: MemorySingleCache<MiRole[]>; private rolesCache: MemorySingleCache<MiRole[]>;
private roleAssignmentByUserIdCache: MemoryKVCache<MiRoleAssignment[]>; private roleAssignmentByUserIdCache: MemoryKVCache<MiRoleAssignment[]>;
private notificationService: NotificationService;
public static AlreadyAssignedError = class extends Error {}; public static AlreadyAssignedError = class extends Error {};
public static NotAssignedError = class extends Error {}; public static NotAssignedError = class extends Error {};
constructor( constructor(
private moduleRef: ModuleRef,
@Inject(DI.redis) @Inject(DI.redis)
private redisClient: Redis.Redis, private redisClient: Redis.Redis,
@ -120,6 +131,10 @@ export class RoleService implements OnApplicationShutdown {
this.redisForSub.on('message', this.onMessage); this.redisForSub.on('message', this.onMessage);
} }
async onModuleInit() {
this.notificationService = this.moduleRef.get(NotificationService.name);
}
@bindThis @bindThis
private async onMessage(_: string, data: string): Promise<void> { private async onMessage(_: string, data: string): Promise<void> {
const obj = JSON.parse(data); const obj = JSON.parse(data);
@ -427,6 +442,12 @@ export class RoleService implements OnApplicationShutdown {
this.globalEventService.publishInternalEvent('userRoleAssigned', created); this.globalEventService.publishInternalEvent('userRoleAssigned', created);
if (role.isPublic) {
this.notificationService.createNotification(userId, 'roleAssigned', {
roleId: roleId,
});
}
if (moderator) { if (moderator) {
const user = await this.usersRepository.findOneByOrFail({ id: userId }); const user = await this.usersRepository.findOneByOrFail({ id: userId });
this.moderationLogService.log(moderator, 'assignRole', { this.moderationLogService.log(moderator, 'assignRole', {

View File

@ -3,30 +3,34 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import { Inject, Injectable, OnApplicationShutdown, OnModuleInit } from '@nestjs/common';
import * as Redis from 'ioredis'; import * as Redis from 'ioredis';
import { ModuleRef } from '@nestjs/core';
import type { UserListMembershipsRepository } from '@/models/_.js'; import type { UserListMembershipsRepository } from '@/models/_.js';
import type { MiUser } from '@/models/User.js'; import type { MiUser } from '@/models/User.js';
import type { MiUserList } from '@/models/UserList.js'; import type { MiUserList } from '@/models/UserList.js';
import type { MiUserListMembership } from '@/models/UserListMembership.js'; import type { MiUserListMembership } from '@/models/UserListMembership.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { ProxyAccountService } from '@/core/ProxyAccountService.js'; import { ProxyAccountService } from '@/core/ProxyAccountService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { RoleService } from '@/core/RoleService.js';
import { QueueService } from '@/core/QueueService.js'; import { QueueService } from '@/core/QueueService.js';
import { RedisKVCache } from '@/misc/cache.js'; import { RedisKVCache } from '@/misc/cache.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js'; import { RoleService } from '@/core/RoleService.js';
@Injectable() @Injectable()
export class UserListService implements OnApplicationShutdown { export class UserListService implements OnApplicationShutdown, OnModuleInit {
public static TooManyUsersError = class extends Error {}; public static TooManyUsersError = class extends Error {};
public membersCache: RedisKVCache<Set<string>>; public membersCache: RedisKVCache<Set<string>>;
private roleService: RoleService;
constructor( constructor(
private moduleRef: ModuleRef,
@Inject(DI.redis) @Inject(DI.redis)
private redisClient: Redis.Redis, private redisClient: Redis.Redis,
@ -38,7 +42,6 @@ export class UserListService implements OnApplicationShutdown {
private userEntityService: UserEntityService, private userEntityService: UserEntityService,
private idService: IdService, private idService: IdService,
private roleService: RoleService,
private globalEventService: GlobalEventService, private globalEventService: GlobalEventService,
private proxyAccountService: ProxyAccountService, private proxyAccountService: ProxyAccountService,
private queueService: QueueService, private queueService: QueueService,
@ -54,6 +57,10 @@ export class UserListService implements OnApplicationShutdown {
this.redisForSub.on('message', this.onMessage); this.redisForSub.on('message', this.onMessage);
} }
async onModuleInit() {
this.roleService = this.moduleRef.get(RoleService.name);
}
@bindThis @bindThis
private async onMessage(_: string, data: string): Promise<void> { private async onMessage(_: string, data: string): Promise<void> {
const obj = JSON.parse(data); const obj = JSON.parse(data);

View File

@ -6,6 +6,7 @@
import { URL } from 'node:url'; import { URL } from 'node:url';
import { toASCII } from 'punycode'; import { toASCII } from 'punycode';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import RE2 from 're2';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js'; import type { Config } from '@/config.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
@ -41,6 +42,33 @@ export class UtilityService {
return silencedHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`)); return silencedHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`));
} }
@bindThis
public isSensitiveWordIncluded(text: string, sensitiveWords: string[]): boolean {
if (sensitiveWords.length === 0) return false;
if (text === '') return false;
const regexpregexp = /^\/(.+)\/(.*)$/;
const matched = sensitiveWords.some(filter => {
// represents RegExp
const regexp = filter.match(regexpregexp);
// This should never happen due to input sanitisation.
if (!regexp) {
const words = filter.split(' ');
return words.every(keyword => text.includes(keyword));
}
try {
// TODO: RE2インスタンスをキャッシュ
return new RE2(regexp[1], regexp[2]).test(text);
} catch (err) {
// This should never happen due to input sanitisation.
return false;
}
});
return matched;
}
@bindThis @bindThis
public extractDbHost(uri: string): string { public extractDbHost(uri: string): string {
const url = new URL(uri); const url = new URL(uri);

View File

@ -58,7 +58,7 @@ export class ApAudienceService {
}; };
} }
if (toGroups.followers.length > 0) { if (toGroups.followers.length > 0 || ccGroups.followers.length > 0) {
return { return {
visibility: 'followers', visibility: 'followers',
mentionedUsers, mentionedUsers,

View File

@ -144,7 +144,7 @@ class DeliverManager {
} }
// deliver // deliver
this.queueService.deliverMany(this.actor, this.activity, inboxes); await this.queueService.deliverMany(this.actor, this.activity, inboxes);
} }
} }

View File

@ -97,6 +97,8 @@ export class ApInboxService {
} catch (err) { } catch (err) {
if (err instanceof Error || typeof err === 'string') { if (err instanceof Error || typeof err === 'string') {
this.logger.error(err); this.logger.error(err);
} else {
throw err;
} }
} }
} }
@ -256,7 +258,7 @@ export class ApInboxService {
const targetUri = getApId(activity.object); const targetUri = getApId(activity.object);
this.announceNote(actor, activity, targetUri); await this.announceNote(actor, activity, targetUri);
} }
@bindThis @bindThis
@ -288,7 +290,7 @@ export class ApInboxService {
} catch (err) { } catch (err) {
// 対象が4xxならスキップ // 対象が4xxならスキップ
if (err instanceof StatusError) { if (err instanceof StatusError) {
if (err.isClientError) { if (!err.isRetryable) {
this.logger.warn(`Ignored announce target ${targetUri} - ${err.statusCode}`); this.logger.warn(`Ignored announce target ${targetUri} - ${err.statusCode}`);
return; return;
} }
@ -373,7 +375,7 @@ export class ApInboxService {
}); });
if (isPost(object)) { if (isPost(object)) {
this.createNote(resolver, actor, object, false, activity); await this.createNote(resolver, actor, object, false, activity);
} else { } else {
this.logger.warn(`Unknown type: ${getApType(object)}`); this.logger.warn(`Unknown type: ${getApType(object)}`);
} }
@ -404,7 +406,7 @@ export class ApInboxService {
await this.apNoteService.createNote(note, resolver, silent); await this.apNoteService.createNote(note, resolver, silent);
return 'ok'; return 'ok';
} catch (err) { } catch (err) {
if (err instanceof StatusError && err.isClientError) { if (err instanceof StatusError && !err.isRetryable) {
return `skip ${err.statusCode}`; return `skip ${err.statusCode}`;
} else { } else {
throw err; throw err;

View File

@ -34,9 +34,9 @@ type PrivateKey = {
}; };
export class ApRequestCreator { export class ApRequestCreator {
static createSignedPost(args: { key: PrivateKey, url: string, body: string, additionalHeaders: Record<string, string> }): Signed { static createSignedPost(args: { key: PrivateKey, url: string, body: string, digest?: string, additionalHeaders: Record<string, string> }): Signed {
const u = new URL(args.url); const u = new URL(args.url);
const digestHeader = `SHA-256=${crypto.createHash('sha256').update(args.body).digest('base64')}`; const digestHeader = args.digest ?? this.createDigest(args.body);
const request: Request = { const request: Request = {
url: u.href, url: u.href,
@ -59,6 +59,10 @@ export class ApRequestCreator {
}; };
} }
static createDigest(body: string) {
return `SHA-256=${crypto.createHash('sha256').update(body).digest('base64')}`;
}
static createSignedGet(args: { key: PrivateKey, url: string, additionalHeaders: Record<string, string> }): Signed { static createSignedGet(args: { key: PrivateKey, url: string, additionalHeaders: Record<string, string> }): Signed {
const u = new URL(args.url); const u = new URL(args.url);
@ -145,8 +149,8 @@ export class ApRequestService {
} }
@bindThis @bindThis
public async signedPost(user: { id: MiUser['id'] }, url: string, object: unknown): Promise<void> { public async signedPost(user: { id: MiUser['id'] }, url: string, object: unknown, digest?: string): Promise<void> {
const body = JSON.stringify(object); const body = typeof object === 'string' ? object : JSON.stringify(object);
const keypair = await this.userKeypairService.getUserKeypair(user.id); const keypair = await this.userKeypairService.getUserKeypair(user.id);
@ -157,6 +161,7 @@ export class ApRequestService {
}, },
url, url,
body, body,
digest,
additionalHeaders: { additionalHeaders: {
}, },
}); });

View File

@ -216,7 +216,7 @@ export class ApNoteService {
return { status: 'ok', res }; return { status: 'ok', res };
} catch (e) { } catch (e) {
return { return {
status: (e instanceof StatusError && e.isClientError) ? 'permerror' : 'temperror', status: (e instanceof StatusError && !e.isRetryable) ? 'permerror' : 'temperror',
}; };
} }
}; };

View File

@ -351,6 +351,7 @@ export class NoteEntityService implements OnModuleInit {
color: channel.color, color: channel.color,
isSensitive: channel.isSensitive, isSensitive: channel.isSensitive,
allowRenoteToExternal: channel.allowRenoteToExternal, allowRenoteToExternal: channel.allowRenoteToExternal,
userId: channel.userId,
} : undefined, } : undefined,
mentions: note.mentions.length > 0 ? note.mentions : undefined, mentions: note.mentions.length > 0 ? note.mentions : undefined,
uri: note.uri ?? undefined, uri: note.uri ?? undefined,

View File

@ -15,8 +15,8 @@ import type { Packed } from '@/misc/json-schema.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { isNotNull } from '@/misc/is-not-null.js'; import { isNotNull } from '@/misc/is-not-null.js';
import { FilterUnionByProperty, notificationTypes } from '@/types.js'; import { FilterUnionByProperty, notificationTypes } from '@/types.js';
import { RoleEntityService } from './RoleEntityService.js';
import type { OnModuleInit } from '@nestjs/common'; import type { OnModuleInit } from '@nestjs/common';
import type { CustomEmojiService } from '../CustomEmojiService.js';
import type { UserEntityService } from './UserEntityService.js'; import type { UserEntityService } from './UserEntityService.js';
import type { NoteEntityService } from './NoteEntityService.js'; import type { NoteEntityService } from './NoteEntityService.js';
@ -27,7 +27,7 @@ const NOTE_REQUIRED_GROUPED_NOTIFICATION_TYPES = new Set(['note', 'mention', 're
export class NotificationEntityService implements OnModuleInit { export class NotificationEntityService implements OnModuleInit {
private userEntityService: UserEntityService; private userEntityService: UserEntityService;
private noteEntityService: NoteEntityService; private noteEntityService: NoteEntityService;
private customEmojiService: CustomEmojiService; private roleEntityService: RoleEntityService;
constructor( constructor(
private moduleRef: ModuleRef, private moduleRef: ModuleRef,
@ -43,14 +43,13 @@ export class NotificationEntityService implements OnModuleInit {
//private userEntityService: UserEntityService, //private userEntityService: UserEntityService,
//private noteEntityService: NoteEntityService, //private noteEntityService: NoteEntityService,
//private customEmojiService: CustomEmojiService,
) { ) {
} }
onModuleInit() { onModuleInit() {
this.userEntityService = this.moduleRef.get('UserEntityService'); this.userEntityService = this.moduleRef.get('UserEntityService');
this.noteEntityService = this.moduleRef.get('NoteEntityService'); this.noteEntityService = this.moduleRef.get('NoteEntityService');
this.customEmojiService = this.moduleRef.get('CustomEmojiService'); this.roleEntityService = this.moduleRef.get('RoleEntityService');
} }
@bindThis @bindThis
@ -81,6 +80,7 @@ export class NotificationEntityService implements OnModuleInit {
detail: false, detail: false,
}) })
) : undefined; ) : undefined;
const role = notification.type === 'roleAssigned' ? await this.roleEntityService.pack(notification.roleId) : undefined;
return await awaitAll({ return await awaitAll({
id: notification.id, id: notification.id,
@ -92,6 +92,9 @@ export class NotificationEntityService implements OnModuleInit {
...(notification.type === 'reaction' ? { ...(notification.type === 'reaction' ? {
reaction: notification.reaction, reaction: notification.reaction,
} : {}), } : {}),
...(notification.type === 'roleAssigned' ? {
role: role,
} : {}),
...(notification.type === 'achievementEarned' ? { ...(notification.type === 'achievementEarned' ? {
achievement: notification.achievement, achievement: notification.achievement,
} : {}), } : {}),
@ -216,6 +219,8 @@ export class NotificationEntityService implements OnModuleInit {
}); });
} }
const role = notification.type === 'roleAssigned' ? await this.roleEntityService.pack(notification.roleId) : undefined;
return await awaitAll({ return await awaitAll({
id: notification.id, id: notification.id,
createdAt: new Date(notification.createdAt).toISOString(), createdAt: new Date(notification.createdAt).toISOString(),
@ -226,6 +231,9 @@ export class NotificationEntityService implements OnModuleInit {
...(notification.type === 'reaction' ? { ...(notification.type === 'reaction' ? {
reaction: notification.reaction, reaction: notification.reaction,
} : {}), } : {}),
...(notification.type === 'roleAssigned' ? {
role: role,
} : {}),
...(notification.type === 'achievementEarned' ? { ...(notification.type === 'achievementEarned' ? {
achievement: notification.achievement, achievement: notification.achievement,
} : {}), } : {}),

View File

@ -332,13 +332,13 @@ export class UserEntityService implements OnModuleInit {
const profile = opts.detail ? (opts.userProfile ?? await this.userProfilesRepository.findOneByOrFail({ userId: user.id })) : null; const profile = opts.detail ? (opts.userProfile ?? await this.userProfilesRepository.findOneByOrFail({ userId: user.id })) : null;
const followingCount = profile == null ? null : const followingCount = profile == null ? null :
(profile.ffVisibility === 'public') || isMe ? user.followingCount : (profile.followingVisibility === 'public') || isMe ? user.followingCount :
(profile.ffVisibility === 'followers') && (relation && relation.isFollowing) ? user.followingCount : (profile.followingVisibility === 'followers') && (relation && relation.isFollowing) ? user.followingCount :
null; null;
const followersCount = profile == null ? null : const followersCount = profile == null ? null :
(profile.ffVisibility === 'public') || isMe ? user.followersCount : (profile.followersVisibility === 'public') || isMe ? user.followersCount :
(profile.ffVisibility === 'followers') && (relation && relation.isFollowing) ? user.followersCount : (profile.followersVisibility === 'followers') && (relation && relation.isFollowing) ? user.followersCount :
null; null;
const isModerator = isMe && opts.detail ? this.roleService.isModerator(user) : null; const isModerator = isMe && opts.detail ? this.roleService.isModerator(user) : null;
@ -417,7 +417,8 @@ export class UserEntityService implements OnModuleInit {
pinnedPageId: profile!.pinnedPageId, pinnedPageId: profile!.pinnedPageId,
pinnedPage: profile!.pinnedPageId ? this.pageEntityService.pack(profile!.pinnedPageId, me) : null, pinnedPage: profile!.pinnedPageId ? this.pageEntityService.pack(profile!.pinnedPageId, me) : null,
publicReactions: profile!.publicReactions, publicReactions: profile!.publicReactions,
ffVisibility: profile!.ffVisibility, followersVisibility: profile!.followersVisibility,
followingVisibility: profile!.followingVisibility,
twoFactorEnabled: profile!.twoFactorEnabled, twoFactorEnabled: profile!.twoFactorEnabled,
usePasswordLessLogin: profile!.usePasswordLessLogin, usePasswordLessLogin: profile!.usePasswordLessLogin,
securityKeys: profile!.twoFactorEnabled securityKeys: profile!.twoFactorEnabled

View File

@ -37,7 +37,7 @@ export class ServerStatsService implements OnApplicationShutdown {
const log = [] as any[]; const log = [] as any[];
ev.on('requestServerStatsLog', x => { ev.on('requestServerStatsLog', x => {
ev.emit(`serverStatsLog:${x.id}`, log.slice(0, x.length ?? 50)); ev.emit(`serverStatsLog:${x.id}`, log.slice(0, x.length));
}); });
const tick = async () => { const tick = async () => {

View File

@ -78,5 +78,6 @@ export const DI = {
flashsRepository: Symbol('flashsRepository'), flashsRepository: Symbol('flashsRepository'),
flashLikesRepository: Symbol('flashLikesRepository'), flashLikesRepository: Symbol('flashLikesRepository'),
userMemosRepository: Symbol('userMemosRepository'), userMemosRepository: Symbol('userMemosRepository'),
bubbleGameRecordsRepository: Symbol('bubbleGameRecordsRepository'),
//#endregion //#endregion
}; };

View File

@ -71,8 +71,11 @@ export default class Logger {
let log = `${l} ${worker}\t[${contexts.join(' ')}]\t${m}`; let log = `${l} ${worker}\t[${contexts.join(' ')}]\t${m}`;
if (envOption.withLogTime) log = chalk.gray(time) + ' ' + log; if (envOption.withLogTime) log = chalk.gray(time) + ' ' + log;
console.log(important ? chalk.bold(log) : log); const args: unknown[] = [important ? chalk.bold(log) : log];
if (level === 'error' && data) console.log(data); if (data != null) {
args.push(data);
}
console.log(...args);
} }
@bindThis @bindThis

View File

@ -1,40 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and other misskey contributors
* SPDX-License-Identifier: AGPL-3.0-only
*/
export const kinds = [
'read:account',
'write:account',
'read:blocks',
'write:blocks',
'read:drive',
'write:drive',
'read:favorites',
'write:favorites',
'read:following',
'write:following',
'read:messaging',
'write:messaging',
'read:mutes',
'write:mutes',
'write:notes',
'read:notifications',
'write:notifications',
'read:reactions',
'write:reactions',
'write:votes',
'read:pages',
'write:pages',
'write:page-likes',
'read:page-likes',
'read:user-groups',
'write:user-groups',
'read:channels',
'write:channels',
'read:gallery',
'write:gallery',
'read:gallery-likes',
'write:gallery-likes',
];
// IF YOU ADD KINDS(PERMISSIONS), YOU MUST ADD TRANSLATIONS (under _permissions).

File diff suppressed because one or more lines are too long

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