mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-06 23:25:39 +02:00
Compare commits
6 Commits
room
...
sp-reactio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f08d6e46df | ||
|
|
d53b2f532a | ||
|
|
40f6acd720 | ||
|
|
9dc4762fe0 | ||
|
|
f3d26722bb | ||
|
|
5eb873ff91 |
@@ -19,6 +19,7 @@
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"Vue.volar",
|
||||
"Orta.vscode-jest",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"mrmlnc.vscode-json5"
|
||||
]
|
||||
|
||||
3
.github/dependabot.yml
vendored
3
.github/dependabot.yml
vendored
@@ -34,6 +34,9 @@ updates:
|
||||
patterns:
|
||||
- "storybook*"
|
||||
- "@storybook/*"
|
||||
swc-core:
|
||||
patterns:
|
||||
- "@swc/core*"
|
||||
typescript-eslint:
|
||||
patterns:
|
||||
- "@typescript-eslint/*"
|
||||
|
||||
6
.github/workflows/api-misskey-js.yml
vendored
6
.github/workflows/api-misskey-js.yml
vendored
@@ -16,13 +16,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v6.0.1
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
4
.github/workflows/changelog-check.yml
vendored
4
.github/workflows/changelog-check.yml
vendored
@@ -12,9 +12,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout head
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v6.0.1
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
|
||||
- name: setup node
|
||||
id: setup-node
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: pnpm
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v6.0.1
|
||||
- name: Check version
|
||||
run: |
|
||||
if [ "$(jq -r '.version' package.json)" != "$(jq -r '.version' packages/misskey-js/package.json)" ]; then
|
||||
|
||||
2
.github/workflows/check-spdx-license-id.yml
vendored
2
.github/workflows/check-spdx-license-id.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v6.0.1
|
||||
- name: Check
|
||||
run: |
|
||||
counter=0
|
||||
|
||||
2
.github/workflows/check_copyright_year.yml
vendored
2
.github/workflows/check_copyright_year.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
check_copyright_year:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
- run: |
|
||||
if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then
|
||||
echo "Please change copyright year!"
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
wait_time: ${{ steps.get-wait-time.outputs.wait_time }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v6.0.1
|
||||
|
||||
- name: Check allowed users
|
||||
id: check-allowed-users
|
||||
|
||||
2
.github/workflows/docker-develop.yml
vendored
2
.github/workflows/docker-develop.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v6.0.1
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Log in to Docker Hub
|
||||
|
||||
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v6.0.1
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Docker meta
|
||||
|
||||
2
.github/workflows/dockle.yml
vendored
2
.github/workflows/dockle.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
DOCKLE_VERSION: 0.4.15
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
|
||||
- name: Download and install dockle v${{ env.DOCKLE_VERSION }}
|
||||
run: |
|
||||
|
||||
6
.github/workflows/get-api-diff.yml
vendored
6
.github/workflows/get-api-diff.yml
vendored
@@ -25,14 +25,14 @@ jobs:
|
||||
ref: refs/pull/${{ github.event.number }}/merge
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
ref: ${{ matrix.ref }}
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
6
.github/workflows/get-backend-memory.yml
vendored
6
.github/workflows/get-backend-memory.yml
vendored
@@ -40,14 +40,14 @@ jobs:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
ref: ${{ matrix.ref }}
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
18
.github/workflows/lint.yml
vendored
18
.github/workflows/lint.yml
vendored
@@ -36,13 +36,13 @@ jobs:
|
||||
pnpm_install:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- uses: actions/setup-node@v6.3.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
@@ -69,13 +69,13 @@ jobs:
|
||||
eslint-cache-version: v1
|
||||
eslint-cache-path: ${{ github.workspace }}/node_modules/.cache/eslint-${{ matrix.workspace }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- uses: actions/setup-node@v6.3.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
@@ -100,13 +100,13 @@ jobs:
|
||||
- sw
|
||||
- misskey-js
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- uses: actions/setup-node@v6.3.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
6
.github/workflows/locale.yml
vendored
6
.github/workflows/locale.yml
vendored
@@ -16,13 +16,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
- uses: actions/setup-node@v6.3.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: ".node-version"
|
||||
cache: "pnpm"
|
||||
|
||||
9
.github/workflows/on-release-created.yml
vendored
9
.github/workflows/on-release-created.yml
vendored
@@ -16,21 +16,18 @@ jobs:
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
# see https://docs.github.com/actions/use-cases-and-examples/publishing-packages/publishing-nodejs-packages#publishing-packages-to-the-npm-registry
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
# Ensure npm 11.5.1 or later is installed
|
||||
- name: Update npm
|
||||
run: npm install -g npm@latest
|
||||
- name: Publish package
|
||||
run: |
|
||||
pnpm i --frozen-lockfile
|
||||
|
||||
8
.github/workflows/storybook.yml
vendored
8
.github/workflows/storybook.yml
vendored
@@ -22,12 +22,12 @@ jobs:
|
||||
NODE_OPTIONS: "--max_old_space_size=7168"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
if: github.event_name != 'pull_request_target'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
if: github.event_name == 'pull_request_target'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
@@ -37,9 +37,9 @@ jobs:
|
||||
if: github.event_name == 'pull_request_target'
|
||||
run: git checkout "$(git rev-list --parents -n1 HEAD | cut -d" " -f3)"
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
20
.github/workflows/test-backend.yml
vendored
20
.github/workflows/test-backend.yml
vendored
@@ -49,7 +49,7 @@ jobs:
|
||||
ports:
|
||||
- 56312:6379
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.38.2
|
||||
image: getmeili/meilisearch:v1.3.4
|
||||
ports:
|
||||
- 57712:7700
|
||||
env:
|
||||
@@ -57,11 +57,11 @@ jobs:
|
||||
MEILI_ENV: development
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
fi
|
||||
done
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
@@ -136,13 +136,13 @@ jobs:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
@@ -180,16 +180,16 @@ jobs:
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
|
||||
4
.github/workflows/test-federation.yml
vendored
4
.github/workflows/test-federation.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
fi
|
||||
done
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
|
||||
12
.github/workflows/test-frontend.yml
vendored
12
.github/workflows/test-frontend.yml
vendored
@@ -28,13 +28,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
# https://github.com/cypress-io/cypress-docker-images/issues/150
|
||||
@@ -86,9 +86,9 @@ jobs:
|
||||
#- uses: browser-actions/setup-firefox@latest
|
||||
# if: ${{ matrix.browser == 'firefox' }}
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
6
.github/workflows/test-misskey-js.yml
vendored
6
.github/workflows/test-misskey-js.yml
vendored
@@ -22,13 +22,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v6.0.1
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
6
.github/workflows/test-production.yml
vendored
6
.github/workflows/test-production.yml
vendored
@@ -16,13 +16,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
6
.github/workflows/validate-api-json.yml
vendored
6
.github/workflows/validate-api-json.yml
vendored
@@ -17,13 +17,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.4.0
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.3.0
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -81,6 +81,3 @@ vite.config.local-dev.ts.timestamp-*
|
||||
|
||||
# VSCode addon
|
||||
.favorites.json
|
||||
|
||||
# Affinity
|
||||
*.af~lock~
|
||||
|
||||
252
CHANGELOG.md
252
CHANGELOG.md
@@ -1,88 +1,12 @@
|
||||
## Unreleased
|
||||
|
||||
### General
|
||||
-
|
||||
|
||||
### Client
|
||||
-
|
||||
|
||||
### Server
|
||||
-
|
||||
|
||||
|
||||
## 2026.5.0
|
||||
|
||||
### General
|
||||
- Enhance: アバターデコレーションにカテゴリを設定できるように
|
||||
|
||||
### Client
|
||||
- Enhance: チャンネル指定リノートでリノート先のチャンネルに移動できるように
|
||||
- Enhance: ベータ版でのアップデート時のダイアログの更新情報リンクをGitHubのReleasesページに遷移するようにし、正しく閲覧できるように
|
||||
- Fix: 一部のページ内リンクが正しく動作しない問題を修正
|
||||
- Fix: ドライブへの画像アップロード時にファイル名の変更が無視される不具合を修正
|
||||
- Fix: 連合が無効化されたサーバーで一部の設定項目が空欄で表示される問題を修正
|
||||
- Fix: オーディオ、動画の再生速度メニューが開けない問題を修正
|
||||
|
||||
### Server
|
||||
- Enhance: メモリ使用量を削減
|
||||
- Enhance: 起動の高速化
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1410)
|
||||
- Enhance: バックエンドの開発モード時の安定性向上
|
||||
- Enhance: バックエンドビルド・テスト時に使用する依存関係の整理(swc/esbuild→Rolldown, Jest→Vitest)
|
||||
- Fix: ファイルシステムを用いる処理におけるパスの取り扱いを改善
|
||||
- Fix: `/api-doc` にアクセスできない問題を修正
|
||||
- Fix: support `alsoKnownAs` from remote actors as either array or unwrapped singleton
|
||||
- Fix: ローカルに存在しないリモートアカウントに対するアカウント削除リクエストを受信した際に、そのユーザーを新規作成して削除する挙動を修正
|
||||
- Fix: Inboxでの特定のエラーによる失敗はDelayedにしない
|
||||
- Fix: ID生成アルゴリズムにULIDを使用している場合にMisskeyが正しく動作しない問題を修正
|
||||
- Fix: リレー経由で届いたノートがリノートとして表示される問題を修正
|
||||
- Fix: robots.txtの内容を調整
|
||||
- Fix: 特定のユーザーに管理者権限を持つロールが複数ついている際に、取得できるユーザーIDが重複する問題を修正
|
||||
(Cherry-picked from https://github.com/lqvp/misskey-tempura/commit/17ed4108cec4b6bd2fd989db5a9091db91fa37a7)
|
||||
- Fix: ブロックしたサーバーからのInboxジョブが蓄積し続ける問題を修正
|
||||
(Cherry-picked from https://github.com/lqvp/misskey-tempura/commit/3f0f4bfe923f2b3a7837017b54841598f421c6ef)
|
||||
- Fix: support activity with `actor` as an id string or embedded object in inbox processor and ActivityPub inbox service
|
||||
- Fix: コンフィグファイルに `meilisearch` の設定がある状態でほかの検索プロバイダを利用すると、UI上からリモートのノートの検索ができない問題を修正
|
||||
- Fix: ノートに関する通知で公開範囲が考慮されていない問題を修正
|
||||
(Cherry-picked from https://github.com/lqvp/misskey-tempura/commit/cbce96c520a138b8bcd16890ff6f2952830fa166 originally presented in https://github.com/yojo-art/cherrypick/pull/743)
|
||||
|
||||
## 2026.3.2
|
||||
|
||||
### General
|
||||
- 依存関係の更新
|
||||
|
||||
### Client
|
||||
- Enhance: アプリ内ウィンドウの初期サイズを画面サイズに応じて自動で調整するように
|
||||
- Fix: 絵文字パレットが空の状態でMisskeyについてのページが閲覧できない問題を修正
|
||||
- Fix: ウィンドウのタイトルをクリックしても最前面に出ないことがある問題を修正
|
||||
|
||||
### Server
|
||||
- Fix: 自分の行ったフォロワー限定投稿または指名投稿に自分自身でリアクションなどを行った場合のイベントが流れない問題を修正
|
||||
- Fix: 署名付きGETリクエストにおいてAcceptヘッダを署名の対象から除外(Acceptヘッダを正規化するCDNやリバースプロキシを使用している際に挙動がおかしくなる問題を修正)
|
||||
- Fix: WebSocket接続におけるノートの非表示ロジックを修正
|
||||
- Fix: チャンネルミュートを有効にしている際に、一部のタイムラインやノート一覧が空になる問題を修正
|
||||
- Fix: 初期読込時に必要なフロントエンドのアセットがすべて読み込まれていない問題を修正
|
||||
|
||||
|
||||
## 2026.3.1
|
||||
|
||||
### General
|
||||
- 依存関係の更新
|
||||
|
||||
### Server
|
||||
- Fix: セキュリティに関する修正
|
||||
|
||||
|
||||
## 2026.3.0
|
||||
## 2026.1.0
|
||||
|
||||
### Note
|
||||
- `users/following` の `birthday` プロパティは非推奨になりました。代わりに `users/get-following-users-by-birthday` をご利用ください。
|
||||
- `users/following` の `birthday` プロパティは非推奨になりました。代わりに `users/get-following-birthday-users` をご利用ください。
|
||||
|
||||
### General
|
||||
- Enhance: 「もうすぐ誕生日のユーザー」ウィジェットで、誕生日が至近のユーザーも表示できるように
|
||||
- Enhance: 「もうすぐ誕生日のユーザー」ウィジェットで、誕生日が至近のユーザーも表示できるように
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey)
|
||||
- 「今日誕生日のユーザー」は「もうすぐ誕生日のユーザー」に名称変更されました
|
||||
- Fix: ユーザーハッシュタグページでユーザーの読み込みが重複する問題を修正
|
||||
- 依存関係の更新
|
||||
|
||||
### Client
|
||||
@@ -101,22 +25,12 @@
|
||||
- Fix: `Mk:C:container` の `borderWidth` が正しく反映されない問題を修正
|
||||
- Fix: mCaptchaが正しく動作しない問題を修正
|
||||
- Fix: 非ログイン時にリバーシの対局が表示されない問題を修正
|
||||
- Fix: ノートの詳細表示でリアクションが全件表示されない問題を修正
|
||||
- Fix: 動画埋め込みプレイヤーなどの一部ウィンドウで、ウィンドウのサイズ変更や移動が正常に行えない問題を修正
|
||||
- Fix: 画像エフェクトの修正
|
||||
- 塗りつぶし・モザイク・ぼかしエフェクトを回転させると歪む問題を修正
|
||||
- モザイクの格子のサイズが画像の縦横比によって長方形となる問題を修正
|
||||
- モザイクの色味がより自然になるように修正
|
||||
- ぼかしに不自然な縦線が入る問題を修正
|
||||
- Fix: フォロー承認通知でフォローされた際のメッセージの絵文字が表示されない問題を修正
|
||||
- Fix: HTTP環境など(Secure Contextのない環境)で、設定画面が閲覧できない問題を修正
|
||||
|
||||
### Server
|
||||
- Enhance: OAuthのクライアント情報取得(Client Information Discovery)において、IndieWeb Living Standard 11 July 2024で定義されているJSONドキュメント形式に対応しました
|
||||
- JSONによるClient Information Discoveryを行うには、レスポンスの`Content-Type`ヘッダーが`application/json`である必要があります
|
||||
- 従来の実装(12 February 2022版・HTML Microformat形式)も引き続きサポートされます
|
||||
- Enhance: メモリ使用量を削減
|
||||
- Fix: `/admin/get-user-ips` エンドポイントのアクセス権限を管理者のみに修正
|
||||
|
||||
## 2025.12.2
|
||||
|
||||
@@ -135,9 +49,9 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
### Client
|
||||
- Enhance: デッキのUI説明を追加
|
||||
- Enhance: 設定がブラウザによって消去されないようにするオプションを追加
|
||||
- Fix: バージョン表記のないPlayが正しく動作しない問題を修正
|
||||
- Fix: バージョン表記のないPlayが正しく動作しない問題を修正
|
||||
バージョン表記のないものは v0.x 系として実行されます。v1.x 系で動作させたい場合は必ずバージョン表記を含めてください。
|
||||
- Fix: デッキUIでメニュー位置を下にしているとプロファイル削除ボタンが表示されないのを修正
|
||||
- Fix: デッキUIでメニュー位置を下にしているとプロファイル削除ボタンが表示されないのを修正
|
||||
- Fix: 一部のUnicode絵文字のリアクションがボタンにならない問題を修正
|
||||
|
||||
### Server
|
||||
@@ -182,11 +96,11 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Fix: ページの内容がはみ出ることがある問題を修正
|
||||
- Fix: ナビゲーションバーを下に表示しているときに、項目数が多いと表示が崩れる問題を修正
|
||||
- Fix: ヘッダーメニューのチャンネルの新規作成の項目でチャンネル作成ページに飛べない問題を修正 #16816
|
||||
- Fix: ラジオボタンに空白の選択肢が表示される問題を修正
|
||||
- Fix: ラジオボタンに空白の選択肢が表示される問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1105)
|
||||
- Fix: 一部のシチュエーションで投稿フォームのツアーが正しく表示されない問題を修正
|
||||
- Fix: 投稿フォームのリセットボタンで注釈がリセットされない問題を修正
|
||||
- Fix: PlayのAiScriptバージョン判定(v0.x系・v1.x系の判定)が正しく動作しない問題を修正
|
||||
- Fix: PlayのAiScriptバージョン判定(v0.x系・v1.x系の判定)が正しく動作しない問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1129)
|
||||
- Fix: フォロー申請をキャンセルする際の確認ダイアログの文言が不正確な問題を修正
|
||||
- Fix: 初回読み込み時にエラーになることがある問題を修正
|
||||
@@ -196,12 +110,12 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
### Server
|
||||
- Enhance: メモリ使用量を削減しました
|
||||
- Enhance: 依存関係の更新
|
||||
- Fix: ワードミュートの文字数計算を修正
|
||||
- Fix: ワードミュートの文字数計算を修正
|
||||
- Fix: チャンネルのリアルタイム更新時に、ロックダウン設定にて非ログイン時にノートを表示しない設定にしている場合でもノートが表示されてしまう問題を修正
|
||||
- Fix: DeepL APIのAPIキー指定方式変更に対応
|
||||
- Fix: DeepL APIのAPIキー指定方式変更に対応
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1096)
|
||||
- 内部実装の変更にて対応可能な更新です。Misskey側の設定方法に変更はありません。
|
||||
- Fix: DBレプリケーションを利用する環境でクエリーが失敗する問題を修正
|
||||
- Fix: DBレプリケーションを利用する環境でクエリーが失敗する問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/1123)
|
||||
|
||||
## 2025.11.0
|
||||
@@ -244,7 +158,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
## 2025.10.1
|
||||
|
||||
### General
|
||||
- Enhance: リモートユーザーに付与したロールバッジを表示できるように(オプトイン)
|
||||
- Enhance: リモートユーザーに付与したロールバッジを表示できるように(オプトイン)
|
||||
パフォーマンス上の問題からデフォルトで無効化されています。「コントロールパネル > パフォーマンス」から有効化できます。
|
||||
- 依存関係の更新
|
||||
|
||||
@@ -371,7 +285,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Enhance: レンダリングパフォーマンスの向上
|
||||
- Enhance: 依存ソフトウェアの更新
|
||||
- Fix: 投稿フォームでファイルのアップロードが中止または失敗した際のハンドリングを修正
|
||||
- Fix: 一部の設定検索結果が存在しないパスになる問題を修正
|
||||
- Fix: 一部の設定検索結果が存在しないパスになる問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1171)
|
||||
- Fix: テーマエディタが動作しない問題を修正
|
||||
- Fix: チャンネルのハイライトページにノートが表示されない問題を修正
|
||||
@@ -531,7 +445,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Enhance: 画像の高品質なプレースホルダを無効化してパフォーマンスを向上させるオプションを追加
|
||||
- Enhance: 招待されているが参加していないルームを開いたときに、招待を承認するかどうか尋ねるように
|
||||
- Enhance: リプライ元にアンケートがあることが表示されるように
|
||||
- Enhance: ノートのサーバー情報のデザインを改善・パフォーマンス向上
|
||||
- Enhance: ノートのサーバー情報のデザインを改善・パフォーマンス向上
|
||||
(Based on https://github.com/taiyme/misskey/pull/198, https://github.com/taiyme/misskey/pull/211, https://github.com/taiyme/misskey/pull/283)
|
||||
- Enhance: ユーザー設定でURLプレビューを無効化できるように
|
||||
- Enhance: ヒントとコツを追加
|
||||
@@ -620,7 +534,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
|
||||
### Server
|
||||
- Enhance: ジョブキューの成功/失敗したジョブも一定数・一定期間保存するようにし、後から問題を調査することを容易に
|
||||
- Enhance: フォローしているユーザーならフォロワー限定投稿のノートでもアンテナで検知できるように
|
||||
- Enhance: フォローしているユーザーならフォロワー限定投稿のノートでもアンテナで検知できるように
|
||||
(Cherry-picked from https://github.com/yojo-art/cherrypick/pull/568 and https://github.com/team-shahu/misskey/pull/38)
|
||||
- Enhance: ユーザーごとにノートの表示が高速化するように
|
||||
- Fix: システムアカウントの名前がサーバー名と同期されない問題を修正
|
||||
@@ -726,7 +640,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
|
||||
### General
|
||||
- Enhance: プロキシアカウントをシステムアカウントとして作成するように
|
||||
- Enhance: OAuthで外部アプリからロゴが提供されている場合、それを表示できるように
|
||||
- Enhance: OAuthで外部アプリからロゴが提供されている場合、それを表示できるように
|
||||
書式は https://indieauth.spec.indieweb.org/20220212/#example-2 に準じます。
|
||||
- Fix: システムアカウントが削除できる問題を修正
|
||||
|
||||
@@ -740,7 +654,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
|
||||
### Server
|
||||
- Fix: 特定のケースでActivityPubの処理がデッドロックになることがあるのを修正
|
||||
- Fix: S3互換オブジェクトストレージでファイルのアップロードに失敗することがある問題を修正
|
||||
- Fix: S3互換オブジェクトストレージでファイルのアップロードに失敗することがある問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/895)
|
||||
|
||||
|
||||
@@ -761,7 +675,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Enhance: リアクションする際に確認ダイアログを表示できるように
|
||||
- Enhance: コントロールパネルのユーザ検索で入力された情報をページ遷移で損なわないように `#15437`
|
||||
- Enhance: CWの注釈で入力済みの文字数を表示
|
||||
- Enhance: ノート検索ページのデザイン調整
|
||||
- Enhance: ノート検索ページのデザイン調整
|
||||
(Cherry-picked from https://github.com/taiyme/misskey/pull/273)
|
||||
- Fix: ノートページで、クリップ一覧が表示されないことがある問題を修正
|
||||
- Fix: コンディショナルロールを手動で割り当てできる導線を削除 `#13529`
|
||||
@@ -778,7 +692,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Fix: `following/invalidate`でフォロワーを解除しようとしているユーザーの情報を返すように
|
||||
- Fix: オブジェクトストレージの設定でPrefixを設定していなかった場合nullまたは空文字になる問題を修正
|
||||
- Fix: HTTPプロキシとその除外設定を行った状態でカスタム絵文字の一括インポートをしたとき、除外設定が効かないのを修正( #8766 )
|
||||
- Fix: pgroongaでの検索時にはじめのキーワードのみが検索に使用される問題を修正
|
||||
- Fix: pgroongaでの検索時にはじめのキーワードのみが検索に使用される問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/886)
|
||||
- Fix: メールアドレスの形式が正しくなければ以降の処理を行わないように
|
||||
- Fix: `update-meta`でobjectStoragePrefixにS3_SAFEかつURL-safeでない文字列を使えないように
|
||||
@@ -788,12 +702,12 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
## 2025.2.0
|
||||
|
||||
### General
|
||||
- Fix: Docker のビルドに失敗する問題を修正
|
||||
- Fix: Docker のビルドに失敗する問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/883)
|
||||
|
||||
### Client
|
||||
- Fix: パスキーでパスワードレスログインが出来ない問題を修正
|
||||
- Fix: 一部環境でセンシティブなファイルを含むノートの非表示が効かない問題
|
||||
- Fix: 一部環境でセンシティブなファイルを含むノートの非表示が効かない問題
|
||||
- Fix: データセーバー有効時にもユーザーページの「ファイル」タブで画像が読み込まれてしまう問題を修正
|
||||
- Fix: MFMの `sparkle` エフェクトが正しく表示されない問題を修正
|
||||
- Fix: ページのURLにスラッシュが含まれている場合にページが正しく表示されない問題を修正
|
||||
@@ -820,14 +734,14 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
* β版として公開のため、旧画面も引き続き利用可能です
|
||||
|
||||
### Client
|
||||
- Enhance: PC画面でチャンネルが複数列で表示されるように
|
||||
- Enhance: PC画面でチャンネルが複数列で表示されるように
|
||||
(Cherry-picked from https://github.com/Otaku-Social/maniakey/pull/13)
|
||||
- Enhance: 照会に失敗した場合、その理由を表示するように
|
||||
- Enhance: ワードミュートで検知されたワードを表示できるように
|
||||
- Enhance: リモートのノートのリンクをコピーできるように
|
||||
- Enhance: 連合がホワイトリスト化・無効化されているサーバー向けのデザイン修正
|
||||
- Enhance: AiScriptのセーブデータを明示的に削除する関数`Mk:remove`を追加
|
||||
- Enhance: ノートの添付ファイルを一覧で遡れる「ファイル」タブを追加
|
||||
- Enhance: ノートの添付ファイルを一覧で遡れる「ファイル」タブを追加
|
||||
(Based on https://github.com/Otaku-Social/maniakey/pull/14)
|
||||
- Enhance: AiScriptの拡張API関数において引数の型チェックをより厳格に
|
||||
- Enhance: クエリパラメータでuiを一時的に変更できるように #15240
|
||||
@@ -835,26 +749,26 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Fix: 画面サイズが変わった際にナビゲーションバーが自動で折りたたまれない問題を修正
|
||||
- Fix: サーバー情報メニューに区切り線が不足していたのを修正
|
||||
- Fix: ノートがログインしているユーザーしか見れない場合にログインダイアログを閉じるとその後の動線がなくなる問題を修正
|
||||
- Fix: 公開範囲がホームのノートの埋め込みウィジェットが読み込まれない問題を修正
|
||||
- Fix: 公開範囲がホームのノートの埋め込みウィジェットが読み込まれない問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/803)
|
||||
- Fix: 絵文字管理画面で一部の絵文字が表示されない問題を修正
|
||||
- Fix: プラグイン `register_note_view_interruptor` でノートのサーバー情報の書き換えができない問題を修正
|
||||
- Fix: Botプロテクションの設定変更時は実際に検証を通過しないと保存できないように( #15137 )
|
||||
- Fix: ノート検索が使用できない場合でもチャンネルのノート検索欄がでていた問題を修正
|
||||
- Fix: `Ui:C:select`で値の変更が画面に反映されない問題を修正
|
||||
- Fix: MiAuth認可画面で、認可処理に失敗した場合でもコールバックURLに遷移してしまう問題を修正
|
||||
- Fix: MiAuth認可画面で、認可処理に失敗した場合でもコールバックURLに遷移してしまう問題を修正
|
||||
(Cherry-picked from https://github.com/TeamNijimiss/misskey/commit/800359623e41a662551d774de15b0437b6849bb4)
|
||||
- Fix: ノート作成画面でファイルの添付可能個数を超えてもノートボタンが押せていた問題を修正
|
||||
- Fix: 「アカウントを管理」画面で、ユーザー情報の取得に失敗したアカウント(削除されたアカウントなど)が表示されない問題を修正
|
||||
- Fix: MacOSでChrome系ブラウザを使用している場合に、Misskeyを閉じた際に他のタブのオーディオ機能と干渉する問題を修正
|
||||
- Fix: 言語データのキャッシュ状況によっては、埋め込みウィジェットが正しく起動しない問題を修正
|
||||
- Fix: 「削除して編集」でノートの引用を解除出来なかった問題を修正( #14476 )
|
||||
- Fix: RSSウィジェットが正しく表示されない問題を修正
|
||||
- Fix: RSSウィジェットが正しく表示されない問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/857)
|
||||
- Fix: ワードミュートの保存失敗時にAPIエラーが握りつぶされる事があるのを修正
|
||||
- Fix: アンケートでリモートの絵文字が正しく描画できない問題の修正
|
||||
(Cherry-picked from https://github.com/yojo-art/cherrypick/pull/153)
|
||||
- Fix: 非ログイン時のサーバー概要画面のメニューボタンが押せないことがあるのを修正
|
||||
- Fix: 非ログイン時のサーバー概要画面のメニューボタンが押せないことがあるのを修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/656)
|
||||
- Fix: URLにはじめから`#pswp`が含まれている場合に画像ビューワーがブラウザの戻るボタンで閉じられない問題を修正
|
||||
- Fix: ロール作成画面で設定できるアイコンデコレーションの最大取付個数を16に制限
|
||||
@@ -863,18 +777,18 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
### Server
|
||||
- Enhance: pg_bigmが利用できるよう、ノートの検索をILIKE演算子でなくLIKE演算子でLOWER()をかけたテキストに対して行うように
|
||||
- Enhance: ノート検索の選択肢としてpgroongaに対応 ( #14730 )
|
||||
- Enhance: チャート更新時にDBに同時接続しないように
|
||||
- Enhance: チャート更新時にDBに同時接続しないように
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/830)
|
||||
- Enhance: config(default.yml)からSQLログ全文を出力するか否かを設定可能に ( #15266 )
|
||||
- Fix: ユーザーのプロフィール画面をアドレス入力などで直接表示した際に概要タブの描画に失敗する問題の修正( #15032 )
|
||||
- Fix: 起動前の疎通チェックが機能しなくなっていた問題を修正
|
||||
- Fix: 起動前の疎通チェックが機能しなくなっていた問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/737)
|
||||
- Fix: ノートの閲覧にログイン必須にしてもFeedでノートが表示されてしまう問題を修正
|
||||
- Fix: 絵文字の連合でライセンス欄を相互にやり取りするように ( #10859, #14109 )
|
||||
- Fix: ロックダウンされた期間指定のノートがStreaming経由でLTLに出現するのを修正 ( #15200 )
|
||||
- Fix: disableClustering設定時の初期化ロジックを調整( #15223 )
|
||||
- Fix: URLとURIが異なるエンティティの照会に失敗する問題を修正( #15039 )
|
||||
- Fix: ActivityPubリクエストかどうかの判定が正しくない問題を修正
|
||||
- Fix: ActivityPubリクエストかどうかの判定が正しくない問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/869)
|
||||
- Fix: `/api/pages/update`にて`name`を指定せずにリクエストするとエラーが発生する問題を修正
|
||||
- Fix: AIセンシティブ判定が arm64 環境で動作しない問題を修正
|
||||
@@ -900,12 +814,12 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Fix: お知らせ作成時に画像URL入力欄を空欄に変更できないのを修正 ( #14976 )
|
||||
|
||||
### Client
|
||||
- Enhance: Bull DashboardでRelationship Queueの状態も確認できるように
|
||||
- Enhance: Bull DashboardでRelationship Queueの状態も確認できるように
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/751)
|
||||
- Enhance: ドライブでソートができるように
|
||||
- Enhance: アイコンデコレーション管理画面の改善
|
||||
- Enhance: 「単なるラッキー」の取得条件を変更
|
||||
- Enhance: 投稿フォームでEscキーを押したときIME入力中ならフォームを閉じないように( #10866 )
|
||||
- Enhance: 投稿フォームでEscキーを押したときIME入力中ならフォームを閉じないように( #10866 )
|
||||
- Enhance: MiAuth, OAuthの認可画面の改善
|
||||
- どのアカウントで認証しようとしているのかがわかるように
|
||||
- 認証するアカウントを切り替えられるように
|
||||
@@ -913,29 +827,29 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Enhance: カタルーニャ語 (ca-ES) に対応
|
||||
- Enhance: 個別お知らせページではMetaタグを出力するように
|
||||
- Enhance: ノート詳細画面にロールのバッジを表示
|
||||
- Enhance: 過去に送信したフォローリクエストを確認できるように
|
||||
- Enhance: 過去に送信したフォローリクエストを確認できるように
|
||||
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/663)
|
||||
- Enhance: サイドバーを簡単に展開・折りたたみできるように ( #14981 )
|
||||
- Enhance: リノートメニューに「リノートの詳細」を追加
|
||||
- Enhance: 非ログイン状態でMisskeyを開いた際のパフォーマンスを向上
|
||||
- Fix: 通知の範囲指定の設定項目が必要ない通知設定でも範囲指定の設定がでている問題を修正
|
||||
- Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正
|
||||
- Fix: Turnstileが失敗・期限切れした際にも成功扱いとなってしまう問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/768)
|
||||
- Fix: デッキのタイムラインカラムで「センシティブなファイルを含むノートを表示」設定が使用できなかった問題を修正
|
||||
- Fix: Encode RSS urls with escape sequences before fetching allowing query parameters to be used
|
||||
- Fix: リンク切れを修正
|
||||
- Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正
|
||||
- Fix: ノート投稿ボタンにホバー時のスタイルが適用されていないのを修正
|
||||
(Cherry-picked from https://github.com/taiyme/misskey/pull/305)
|
||||
- Fix: メールアドレス登録有効化時の「完了」ダイアログボックスの表示条件を修正
|
||||
- Fix: 画面幅が狭い環境でデザインが崩れる問題を修正
|
||||
- Fix: 画面幅が狭い環境でデザインが崩れる問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/815)
|
||||
- Fix: TypeScriptの型チェック対象ファイルを限定してビルドを高速化するように
|
||||
- Fix: TypeScriptの型チェック対象ファイルを限定してビルドを高速化するように
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/725)
|
||||
|
||||
### Server
|
||||
- Enhance: DockerのNode.jsを22.11.0に更新
|
||||
- Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように
|
||||
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)
|
||||
- Enhance: 起動前の疎通チェックで、DBとメイン以外のRedisの疎通確認も行うように
|
||||
(Based on https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/588)
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/715)
|
||||
- Enhance: リモートユーザーの照会をオリジナルにリダイレクトするように
|
||||
- Fix: sharedInboxが無いActorに紐づくリモートユーザーを照会できない
|
||||
@@ -943,18 +857,18 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Fix: フォロワーへのメッセージの絵文字をemojisに含めるように
|
||||
- Fix: Nested proxy requestsを検出した際にブロックするように
|
||||
[ghsa-gq5q-c77c-v236](https://github.com/misskey-dev/misskey/security/advisories/ghsa-gq5q-c77c-v236)
|
||||
- Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正
|
||||
- Fix: 招待コードの発行可能な残り数算出に使用すべきロールポリシーの値が違う問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/706)
|
||||
- Fix: 連合への配信時に、acctの大小文字が区別されてしまい正しくメンションが処理されないことがある問題を修正
|
||||
- Fix: 連合への配信時に、acctの大小文字が区別されてしまい正しくメンションが処理されないことがある問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/711)
|
||||
- Fix: ローカルユーザーへのメンションを含むノートが連合される際に正しいURLに変換されないことがある問題を修正
|
||||
- Fix: ローカルユーザーへのメンションを含むノートが連合される際に正しいURLに変換されないことがある問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/712)
|
||||
- Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正
|
||||
- Fix: FTT無効時にユーザーリストタイムラインが使用できない問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/709)
|
||||
- Fix: User Webhookテスト機能のMock Payloadを修正
|
||||
- Fix: アカウント削除のモデレーションログが動作していないのを修正 (#14996)
|
||||
- Fix: User Webhookテスト機能のMock Payloadを修正
|
||||
- Fix: アカウント削除のモデレーションログが動作していないのを修正 (#14996)
|
||||
- Fix: リノートミュートが新規投稿通知に対して作用していなかった問題を修正
|
||||
- Fix: Inboxの処理で生じるエラーを誤ってActivityとして処理することがある問題を修正
|
||||
- Fix: Inboxの処理で生じるエラーを誤ってActivityとして処理することがある問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/730)
|
||||
- Fix: セキュリティに関する修正
|
||||
|
||||
@@ -981,13 +895,13 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Enhance: 個人宛のお知らせは「わかった」を押すと自動的にアーカイブされるように
|
||||
- Fix: `admin/emoji/update`エンドポイントのidのみ指定した時不正なエラーが発生するバグを修正
|
||||
- Fix: RBT有効時、リノートのリアクションが反映されない問題を修正
|
||||
- Fix: キューのエラーログを簡略化するように
|
||||
- Fix: キューのエラーログを簡略化するように
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/649)
|
||||
|
||||
## 2024.10.0
|
||||
|
||||
### Note
|
||||
- セキュリティ向上のため、サーバー初期設定時に使用する初期パスワードを設定できるようになりました。今後Misskeyサーバーを新たに設置する際には、初回の起動前にコンフィグファイルの`setupPassword`をコメントアウトし、初期パスワードを設定することをおすすめします。(すでに初期設定を完了しているサーバーについては、この変更に伴い対応する必要はありません)
|
||||
- セキュリティ向上のため、サーバー初期設定時に使用する初期パスワードを設定できるようになりました。今後Misskeyサーバーを新たに設置する際には、初回の起動前にコンフィグファイルの`setupPassword`をコメントアウトし、初期パスワードを設定することをおすすめします。(すでに初期設定を完了しているサーバーについては、この変更に伴い対応する必要はありません)
|
||||
- ホスティングサービスを運営している場合は、コンフィグファイルを構築する際に`setupPassword`をランダムな値に設定し、ユーザーに通知するようにシステムを更新することをおすすめします。
|
||||
- なお、初期パスワードが設定されていない場合でも初期設定を行うことが可能です(UI上で初期パスワードの入力欄を空欄にすると続行できます)。
|
||||
- ユーザーデータを読み込む際の型が一部変更されました。
|
||||
@@ -1007,7 +921,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
### Client
|
||||
- Enhance: デザインの調整
|
||||
- Enhance: ログイン画面の認証フローを改善
|
||||
- Fix: クライアント上での時間ベースの実績獲得動作が実績獲得後も発動していた問題を修正
|
||||
- Fix: クライアント上での時間ベースの実績獲得動作が実績獲得後も発動していた問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/657)
|
||||
|
||||
### Server
|
||||
@@ -1025,7 +939,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Feat: フォローされた際のメッセージを設定できるように
|
||||
- Feat: 連合をホワイトリスト制にできるように
|
||||
- Feat: UserWebhookとSystemWebhookのテスト送信機能を追加 (#14445)
|
||||
- Feat: モデレーターはユーザーにかかわらずファイルが添付されているノートを検索できるように
|
||||
- Feat: モデレーターはユーザーにかかわらずファイルが添付されているノートを検索できるように
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/680)
|
||||
- Feat: データエクスポートが完了した際に通知を発行するように
|
||||
- Enhance: ユーザーによるコンテンツインポートの可否をロールポリシーで制御できるように
|
||||
@@ -1044,12 +958,12 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Fix: サーバーメトリクスが2つ以上あるとリロード直後の表示がおかしくなる問題を修正
|
||||
- Fix: コントロールパネル内のAp requests内のチャートの表示がおかしかった問題を修正
|
||||
- Fix: 月の違う同じ日はセパレータが表示されないのを修正
|
||||
- Fix: タッチ画面でレンジスライダーを操作するとツールチップが複数表示される問題を修正
|
||||
- Fix: タッチ画面でレンジスライダーを操作するとツールチップが複数表示される問題を修正
|
||||
(Cherry-picked from https://github.com/taiyme/misskey/pull/265)
|
||||
- Fix: 縦横比が極端なカスタム絵文字を表示する際にレイアウトが崩れる箇所があるのを修正
|
||||
- Fix: 縦横比が極端なカスタム絵文字を表示する際にレイアウトが崩れる箇所があるのを修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/725)
|
||||
- Fix: 設定変更時のリロード確認ダイアログが複数個表示されることがある問題を修正
|
||||
- Fix: ファイルの詳細ページのファイルの説明で改行が正しく表示されない問題を修正
|
||||
- Fix: ファイルの詳細ページのファイルの説明で改行が正しく表示されない問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/bde6bb0bd2e8b0d027e724d2acdb8ae0585a8110)
|
||||
- Fix: 一部画面のページネーションが動作しにくくなっていたのを修正 ( #12766 , #11449 )
|
||||
|
||||
@@ -1058,14 +972,14 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Fix: アンテナの書き込み時にキーワードが与えられなかった場合のエラーをApiErrorとして投げるように
|
||||
- この変更により、公式フロントエンドでは入力の不備が内部エラーとして報告される代わりに一般的なエラーダイアログで報告されます
|
||||
- Fix: ファイルがサイズの制限を超えてアップロードされた際にエラーを返さなかった問題を修正
|
||||
- Fix: 外部ページを解析する際に、ページに紐づけられた関連リソースも読み込まれてしまう問題を修正
|
||||
- Fix: 外部ページを解析する際に、ページに紐づけられた関連リソースも読み込まれてしまう問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/26e0412fbb91447c37e8fb06ffb0487346063bb8)
|
||||
- Fix: Continue importing from file if single emoji import fails
|
||||
- Fix: `Retry-After`ヘッダーが送信されなかった問題を修正
|
||||
- Fix: `Retry-After`ヘッダーが送信されなかった問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/commit/8a982c61c01909e7540ff1be9f019df07c3f0624)
|
||||
- Fix: サーバーサイドのDOM解析完了時にリソースを開放するように
|
||||
- Fix: サーバーサイドのDOM解析完了時にリソースを開放するように
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/634)
|
||||
- Fix: `<link rel="alternate">`を追って照会するのはOKレスポンスが返却された場合のみに
|
||||
- Fix: `<link rel="alternate">`を追って照会するのはOKレスポンスが返却された場合のみに
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/633)
|
||||
- Fix: メールにスタイルが適用されていなかった問題を修正
|
||||
|
||||
@@ -1094,15 +1008,15 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- 通知ページや通知カラム(デッキ)を開いている状態において、新たに発生した通知が既読されない問題が修正されます。
|
||||
- これにより、プッシュ通知が有効な同条件下の環境において、プッシュ通知が常に発生してしまう問題も修正されます。
|
||||
- Fix: Play各種エンドポイントの返り値に`visibility`が含まれていない問題を修正
|
||||
- Fix: サーバー情報取得の際にモデレーター限定の情報が取得できないことがあるのを修正
|
||||
- Fix: サーバー情報取得の際にモデレーター限定の情報が取得できないことがあるのを修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/582)
|
||||
- Fix: 公開範囲がダイレクトのノートをユーザーアクティビティのチャート生成に使用しないように
|
||||
- Fix: 公開範囲がダイレクトのノートをユーザーアクティビティのチャート生成に使用しないように
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/679)
|
||||
- Fix: ActivityPubのエンティティタイプ判定で不明なタイプを受け取った場合でも処理を継続するように
|
||||
- キュー処理のつまりが改善される可能性があります
|
||||
- Fix: リバーシの対局設定の変更が反映されないのを修正
|
||||
- Fix: 無制限にストリーミングのチャンネルに接続できる問題を修正
|
||||
- Fix: ベースロールのポリシーを変更した際にモデログに記録されないのを修正
|
||||
- Fix: ベースロールのポリシーを変更した際にモデログに記録されないのを修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/700)
|
||||
- Fix: Prevent memory leak from memory caches (#14310)
|
||||
- Fix: More reliable memory cache eviction (#14311)
|
||||
@@ -1134,9 +1048,9 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Enhance: 内蔵APIドキュメントのデザイン・パフォーマンスを改善
|
||||
- Enhance: 非ログイン時に他サーバーに遷移するアクションを追加
|
||||
- Enhance: 非ログイン時のハイライトTLのデザインを改善
|
||||
- Enhance: フロントエンドのアクセシビリティ改善
|
||||
- Enhance: フロントエンドのアクセシビリティ改善
|
||||
(Based on https://github.com/taiyme/misskey/pull/226)
|
||||
- Enhance: サーバー情報ページ・お問い合わせページを改善
|
||||
- Enhance: サーバー情報ページ・お問い合わせページを改善
|
||||
(Cherry-picked from https://github.com/taiyme/misskey/pull/238)
|
||||
- Enhance: AiScriptを0.19.0にアップデート
|
||||
- Enhance: Allow negative delay for MFM animation elements (`tada`, `jelly`, `twitch`, `shake`, `spin`, `jump`, `bounce`, `rainbow`)
|
||||
@@ -1145,7 +1059,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Enhance: 検索(ノート/ユーザー)において、入力に空白が含まれている場合は照会を行わないように
|
||||
- Enhance: 検索(ノート/ユーザー)において、照会を行うかどうか、ハッシュタグのノート/ユーザー一覧ページを表示するかどうかの確認ダイアログを出すように
|
||||
- Enhance: 検索(ノート/ユーザー)で `@` から始まる文字列(`@user@host`など)を入力すると、そのユーザーを照会できるように
|
||||
- Enhance: ドライブのファイル・フォルダをドラッグしなくても移動できるように
|
||||
- Enhance: ドライブのファイル・フォルダをドラッグしなくても移動できるように
|
||||
(Cherry-picked from https://github.com/nafu-at/misskey/commit/b89c2af6945c6a9f9f10e83f54d2bcf0f240b0b4, https://github.com/nafu-at/misskey/commit/8a7d710c6acb83f50c83f050bd1423c764d60a99)
|
||||
- Enhance: デッキのアンテナ・リスト選択画面からそれぞれを新規作成できるように
|
||||
- Enhance: ブラウザのコンテキストメニューを使用できるように
|
||||
@@ -1153,19 +1067,19 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Fix: `/about#federation` ページなどで各インスタンスのチャートが表示されなくなっていた問題を修正
|
||||
- Fix: ユーザーページの追加情報のラベルを投稿者のサーバーの絵文字で表示する (#13968)
|
||||
- Fix: リバーシの対局を正しく共有できないことがある問題を修正
|
||||
- Fix: コントロールパネルでベースロールのポリシーを編集してもUI上では変更が反映されない問題を修正
|
||||
- Fix: コントロールパネルでベースロールのポリシーを編集してもUI上では変更が反映されない問題を修正
|
||||
- Fix: アンテナの編集画面のボタンに隙間を追加
|
||||
- Fix: テーマプレビューが見れない問題を修正
|
||||
- Fix: ショートカットキーが連打できる問題を修正
|
||||
- Fix: ショートカットキーが連打できる問題を修正
|
||||
(Cherry-picked from https://github.com/taiyme/misskey/pull/234)
|
||||
- Fix: MkSignin.vueのcredentialRequestからReactivityを削除(ProxyがPasskey認証処理に渡ることを避けるため)
|
||||
- Fix: 「アニメーション画像を再生しない」がオンのときでもサーバーのバナー画像・背景画像がアニメーションしてしまう問題を修正
|
||||
- Fix: 「アニメーション画像を再生しない」がオンのときでもサーバーのバナー画像・背景画像がアニメーションしてしまう問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/574)
|
||||
- Fix: Twitchの埋め込みが開けない問題を修正
|
||||
- Fix: 子メニューの高さがウィンドウからはみ出ることがある問題を修正
|
||||
- Fix: 個人宛てのダイアログ形式のお知らせが即時表示されない問題を修正
|
||||
- Fix: 一部の画像がセンシティブ指定されているときに画面に何も表示されないことがあるのを修正
|
||||
- Fix: リアクションしたユーザー一覧のユーザー名がはみ出る問題を修正
|
||||
- Fix: リアクションしたユーザー一覧のユーザー名がはみ出る問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/672)
|
||||
- Fix: `/share`ページにおいて絵文字ピッカーを開くことができない問題を修正
|
||||
- Fix: deck uiの通知音が重なる問題 (#14029)
|
||||
@@ -1208,14 +1122,14 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
4. フォローしていない非アクティブなユーザ
|
||||
|
||||
また、自分自身のアカウントもサジェストされるようになりました。
|
||||
- Fix: 一般ユーザーから見たユーザーのバッジの一覧に公開されていないものが含まれることがある問題を修正
|
||||
- Fix: 一般ユーザーから見たユーザーのバッジの一覧に公開されていないものが含まれることがある問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/652)
|
||||
- Fix: ユーザーのリアクション一覧でミュート/ブロックが機能していなかった問題を修正
|
||||
- Fix: FTT有効時にリモートユーザーのノートがHTLにキャッシュされる問題を修正
|
||||
- Fix: 一部の通知がローカル上のリモートユーザーに対して行われていた問題を修正
|
||||
- Fix: エラーメッセージの誤字を修正 (#14213)
|
||||
- Fix: ソーシャルタイムラインにローカルタイムラインに表示される自分へのリプライが表示されない問題を修正
|
||||
- Fix: リノートのミュートが適用されるまでに時間がかかることがある問題を修正
|
||||
- Fix: リノートのミュートが適用されるまでに時間がかかることがある問題を修正
|
||||
(Cherry-picked from https://github.com/Type4ny-Project/Type4ny/commit/e9601029b52e0ad43d9131b555b614e56c84ebc1)
|
||||
- Fix: Steaming APIが不正なデータを受けた場合の動作が不安定である問題 #14251
|
||||
- Fix: `users/search`において `@` から始まる文字列が与えられた際の処理が正しくなかった問題を修正
|
||||
@@ -1242,7 +1156,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
### General
|
||||
- Feat: エラートラッキングにSentryを使用できるようになりました
|
||||
- Enhance: URLプレビューの有効化・無効化を設定できるように #13569
|
||||
- Enhance: アンテナでBotによるノートを除外できるように
|
||||
- Enhance: アンテナでBotによるノートを除外できるように
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/545)
|
||||
- Enhance: クリップのノート数を表示するように
|
||||
- Enhance: コンディショナルロールの条件として以下を新たに追加 (#13667)
|
||||
@@ -1261,7 +1175,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
|
||||
### Client
|
||||
- Feat: アップロードするファイルの名前をランダム文字列にできるように
|
||||
- Feat: 個別のお知らせにリンクで飛べるように
|
||||
- Feat: 個別のお知らせにリンクで飛べるように
|
||||
(Based on https://github.com/MisskeyIO/misskey/pull/639)
|
||||
- Enhance: 自分のノートの添付ファイルから直接ファイルの詳細ページに飛べるように
|
||||
- Enhance: 広告がMisskeyと同一ドメインの場合はRouterで遷移するように
|
||||
@@ -1291,9 +1205,9 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Fix: 一部のページ内リンクが正しく動作しない問題を修正
|
||||
- Fix: 周年の実績が閏年を考慮しない問題を修正
|
||||
- Fix: ローカルURLのプレビューポップアップが左上に表示される
|
||||
- Fix: WebGL2をサポートしないブラウザで「季節に応じた画面の演出」が有効になっているとき、Misskeyが起動できなくなる問題を修正
|
||||
- Fix: WebGL2をサポートしないブラウザで「季節に応じた画面の演出」が有効になっているとき、Misskeyが起動できなくなる問題を修正
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/459)
|
||||
- Fix: ページタイトルでローカルユーザーとリモートユーザーの区別がつかない問題を修正
|
||||
- Fix: ページタイトルでローカルユーザーとリモートユーザーの区別がつかない問題を修正
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/528)
|
||||
- Fix: コードブロックのシンタックスハイライトで使用される定義ファイルをCDNから取得するように #13177
|
||||
- CDNから取得せずMisskey本体にバンドルする場合は`pacakges/frontend/vite.config.ts`を修正してください。
|
||||
@@ -1316,13 +1230,13 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Enhance: ドライブのファイルがNSFWかどうか個別に連合されるように (#13756)
|
||||
- 可能な場合、ノートの添付ファイルのセンシティブ判定がファイル単位になります
|
||||
- Fix: リモートから配送されたアクティビティにJSON-LD compactionをかける
|
||||
- Fix: フォローリクエストを作成する際に既存のものは削除するように
|
||||
- Fix: フォローリクエストを作成する際に既存のものは削除するように
|
||||
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/440)
|
||||
- Fix: エンドポイント`notes/translate`のエラーを改善
|
||||
- Fix: CleanRemoteFilesProcessorService report progress from 100% (#13632)
|
||||
- Fix: 一部の音声ファイルが映像ファイルとして扱われる問題を修正
|
||||
- Fix: リプライのみの引用リノートと、CWのみの引用リノートが純粋なリノートとして誤って扱われてしまう問題を修正
|
||||
- Fix: 登録にメール認証が必須になっている場合、登録されているメールアドレスを削除できないように
|
||||
- Fix: 登録にメール認証が必須になっている場合、登録されているメールアドレスを削除できないように
|
||||
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/606)
|
||||
- Fix: Add Cache-Control to Bull Board
|
||||
- Fix: nginx経由で/files/にRangeリクエストされた場合に正しく応答できないのを修正
|
||||
@@ -1515,10 +1429,10 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
### Note
|
||||
- 依存関係の更新に伴い、Node.js 20.10.0が最小要件になりました
|
||||
- 絵文字の追加辞書を既にインストールしている場合は、お手数ですが再インストールのほどお願いします
|
||||
- 絵文字ピッカーにピン留め表示する絵文字設定が「リアクション用」と「絵文字入力用」に分かれました。以前の設定は「リアクション用」として使用されます。
|
||||
- 絵文字ピッカーにピン留め表示する絵文字設定が「リアクション用」と「絵文字入力用」に分かれました。以前の設定は「リアクション用」として使用されます。
|
||||
|
||||
**影響:**
|
||||
それにより、投稿フォームから表示される絵文字ピッカーのピン留め絵文字がリセットされたように感じるかもしれません(新設された"ピン留め(全般)"の設定が使われるため)。
|
||||
**影響:**
|
||||
それにより、投稿フォームから表示される絵文字ピッカーのピン留め絵文字がリセットされたように感じるかもしれません(新設された"ピン留め(全般)"の設定が使われるため)。
|
||||
投稿用のピン留め絵文字をアップデート前の状態にするには、以下の手順で操作します。
|
||||
|
||||
1. 「設定」メニューに移動し、「絵文字ピッカー」タブを選択します。
|
||||
@@ -1565,7 +1479,7 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
- Enhance: Unicode 15.0のサポート
|
||||
- Enhance: コードブロックのハイライト機能を利用するには言語を明示的に指定させるように
|
||||
- MFMでコードブロックを利用する際に意図しないハイライトが起こらないようになりました
|
||||
- 逆に、MFMでコードハイライトを利用したい際は言語を明示的に指定する必要があります
|
||||
- 逆に、MFMでコードハイライトを利用したい際は言語を明示的に指定する必要があります
|
||||
(例: ` ```js ` → Javascript, ` ```ais ` → AiScript)
|
||||
- Enhance: 絵文字などのオートコンプリートでShift+Tabを押すと前の候補を選択できるように
|
||||
- Enhance: チャンネルに新規の投稿がある場合にバッジを表示させる
|
||||
@@ -1972,9 +1886,9 @@ v2025.12.0で行われた「configの`trustProxy`のデフォルト値を`false`
|
||||
|
||||
### General
|
||||
- 招待機能を改善しました
|
||||
* 過去に発行した招待コードを確認できるようになりました
|
||||
* ロールごとに招待コードの発行数制限と制限対象期間、有効期限を設定できるようになりました
|
||||
* 招待コードを作成したユーザーと使用したユーザーを確認できるようになりました
|
||||
* 過去に発行した招待コードを確認できるようになりました
|
||||
* ロールごとに招待コードの発行数制限と制限対象期間、有効期限を設定できるようになりました
|
||||
* 招待コードを作成したユーザーと使用したユーザーを確認できるようになりました
|
||||
- ユーザーにロールが期限付きでアサインされている場合、その期限をユーザーのモデレーションページで確認できるようになりました
|
||||
- identicon生成を無効にしてパフォーマンスを向上させることができるようになりました
|
||||
- サーバーのマシン情報の公開を無効にしてパフォーマンスを向上させることができるようになりました
|
||||
@@ -2137,9 +2051,9 @@ Meilisearchの設定に`index`が必要になりました。値はMisskeyサー
|
||||
* 「フォロワーのみ」の投稿は検索結果に表示されません。
|
||||
- 新規登録前に簡潔なルールをユーザーに表示できる、サーバールール機能を追加
|
||||
- ユーザーへの自分用メモ機能
|
||||
* ユーザーに対して、自分だけが見られるメモを追加できるようになりました。
|
||||
* ユーザーに対して、自分だけが見られるメモを追加できるようになりました。
|
||||
(自分自身に対してもメモを追加できます。)
|
||||
* ユーザーメニューから追加できます。
|
||||
* ユーザーメニューから追加できます。
|
||||
(デスクトップ表示ではusernameの右側のボタンからも追加可能)
|
||||
- チャンネルに色を設定できるようになりました。各ノートに設定した色のインジケーターが表示されます。
|
||||
- チャンネルをアーカイブできるようになりました。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax = docker/dockerfile:1.21
|
||||
# syntax = docker/dockerfile:1.20
|
||||
|
||||
ARG NODE_VERSION=22.22.0-bookworm
|
||||
ARG NODE_VERSION=22.21.1-bookworm
|
||||
|
||||
# build assets & compile TypeScript
|
||||
|
||||
@@ -102,6 +102,7 @@ COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-js/
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-reversi/built ./packages/misskey-reversi/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-bubble-game/built ./packages/misskey-bubble-game/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/built ./packages/backend/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/src-js ./packages/backend/src-js
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/i18n/built ./packages/i18n/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/fluent-emojis /misskey/fluent-emojis
|
||||
COPY --chown=misskey:misskey . ./
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["dom"],
|
||||
"target": "esnext",
|
||||
"lib": ["dom", "es5"],
|
||||
"target": "es5",
|
||||
"types": ["cypress", "node"]
|
||||
},
|
||||
"include": ["./**/*.ts"]
|
||||
|
||||
@@ -264,7 +264,7 @@ noJobs: "No hi ha feines"
|
||||
federating: "Federant"
|
||||
blocked: "Bloquejat"
|
||||
suspended: "Anul·lar subscripció "
|
||||
all: "Tot"
|
||||
all: "tot"
|
||||
subscribing: "Subscrit a"
|
||||
publishing: "S'està publicant"
|
||||
notResponding: "Sense resposta"
|
||||
@@ -543,7 +543,6 @@ regenerate: "Regenera"
|
||||
fontSize: "Mida del text"
|
||||
mediaListWithOneImageAppearance: "Altura de la llista de fitxers amb una única imatge"
|
||||
limitTo: "Limita a {x}"
|
||||
showMediaListByGridInWideArea: "Mostra la llista de medis en vista quadrícula quan l'amplada de la pantalla ho permeti"
|
||||
noFollowRequests: "No tens sol·licituds de seguiment"
|
||||
openImageInNewTab: "Obre imatges a una nova pestanya"
|
||||
dashboard: "Tauler de control"
|
||||
@@ -1073,8 +1072,8 @@ thisPostMayBeAnnoying: "Aquesta nota pot ser molesta per algú."
|
||||
thisPostMayBeAnnoyingHome: "Publicar a la línia de temps d'Inici"
|
||||
thisPostMayBeAnnoyingCancel: "Cancel·lar "
|
||||
thisPostMayBeAnnoyingIgnore: "Publicar de totes maneres"
|
||||
collapseRenotes: "Col·lapsar els impulsos que ja has vist"
|
||||
collapseRenotesDescription: "Col·lapse les notes a les quals ja has reaccionat o que ja has impulsat."
|
||||
collapseRenotes: "Col·lapsar les renotes que ja has vist"
|
||||
collapseRenotesDescription: "Col·lapse les notes a les quals ja has reaccionat o que ja has renotat"
|
||||
internalServerError: "Error intern del servidor"
|
||||
internalServerErrorDescription: "El servidor ha fallat de manera inexplicable."
|
||||
copyErrorInfo: "Copiar la informació de l'error "
|
||||
@@ -1390,7 +1389,7 @@ defaultCompressionLevel_description: "Si el redueixes augmentaràs la qualitat d
|
||||
inMinutes: "Minut(s)"
|
||||
inDays: "Di(a)(es)"
|
||||
safeModeEnabled: "Mode segur activat"
|
||||
pluginsAreDisabledBecauseSafeMode: "Les extensions no estan activades perquè el mode segur està activat."
|
||||
pluginsAreDisabledBecauseSafeMode: "Els afegits no estan activats perquè el mode segur està activat."
|
||||
customCssIsDisabledBecauseSafeMode: "El CSS personalitzat no s'aplica perquè el mode segur es troba activat."
|
||||
themeIsDefaultBecauseSafeMode: "El tema predeterminat es farà servir mentre el mode segur estigui activat. Una vegada es desactivi el mode segur es restablirà el tema escollit."
|
||||
thankYouForTestingBeta: "Gràcies per ajudar-nos a provar la versió beta!"
|
||||
@@ -1408,7 +1407,6 @@ frame: "Marc"
|
||||
presets: "Predefinit"
|
||||
zeroPadding: "Sense omplir"
|
||||
nothingToConfigure: "No hi ha res a configurar"
|
||||
viewRenotedChannel: "Mirar el canal d'impulsos "
|
||||
_imageEditing:
|
||||
_vars:
|
||||
caption: "Títol de l'arxiu"
|
||||
@@ -1688,7 +1686,7 @@ _initialTutorial:
|
||||
description: "Pots limitar qui pot veure les teves notes."
|
||||
public: "La teva nota serà visible per a tots els usuaris."
|
||||
home: "Publicar només a línia de temps d'Inici. La gent que visiti el teu perfil o mitjançant les remotes també la podran veure."
|
||||
followers: "Només visible per a seguidors. Només els teus seguidors la podran veure i ningú més. Ningú més podrà fer impulsos."
|
||||
followers: "Només visible per a seguidors. Només els teus seguidors la podran veure i ningú més. Ningú més podrà fer renotes."
|
||||
direct: "Només visible per a alguns seguidors, el destinatari rebre una notificació. Es pot fer servir com una alternativa als missatges directes."
|
||||
doNotSendConfidencialOnDirect1: "Tingues cura quan enviïs informació sensible."
|
||||
doNotSendConfidencialOnDirect2: "Els administradors del servidor poden veure tot el que escrius. Ves compte quan enviïs informació sensible en enviar notes directes a altres usuaris en servidors de poca confiança."
|
||||
@@ -2186,8 +2184,8 @@ _email:
|
||||
title: "Has rebut una sol·licitud de seguiment"
|
||||
_plugin:
|
||||
install: "Instal·lar un afegit "
|
||||
installWarn: "Si us plau, no instal·lis extensions que no siguin de confiança."
|
||||
manage: "Gestiona les extensions"
|
||||
installWarn: "Si us plau, no instal·lis afegits que no siguin de confiança."
|
||||
manage: "Gestionar els afegits"
|
||||
viewSource: "Veure l'origen "
|
||||
viewLog: "Mostra el registre"
|
||||
_preferencesBackups:
|
||||
@@ -3402,9 +3400,11 @@ _imageEffector:
|
||||
threshold: "Llindar"
|
||||
centerX: "Centre de X"
|
||||
centerY: "Centre de Y"
|
||||
density: "Densitat"
|
||||
zoomLinesOutlineThickness: "Amplada de les vores exteriors"
|
||||
zoomLinesSmoothing: "Suavitzat"
|
||||
zoomLinesSmoothingDescription: "Els paràmetres de suavitzat i amplada de línia en augmentar no es poden fer servir junts."
|
||||
zoomLinesThreshold: "Amplada de línia a l'augmentar "
|
||||
zoomLinesMaskSize: "Diàmetre del centre"
|
||||
zoomLinesBlack: "Obscurir"
|
||||
circle: "Cercle"
|
||||
drafts: "Esborrany "
|
||||
_drafts:
|
||||
|
||||
@@ -130,7 +130,6 @@ reactions: "Reakce"
|
||||
reactionSettingDescription2: "Přetažením změníte pořadí, kliknutím smažete, zmáčkněte \"+\" k přidání"
|
||||
rememberNoteVisibility: "Zapamatovat nastavení zobrazení poznámky"
|
||||
attachCancel: "Odstranit přílohu"
|
||||
deleteFile: "Smazat soubor"
|
||||
markAsSensitive: "Označit jako NSFW"
|
||||
unmarkAsSensitive: "Odznačit jako NSFW"
|
||||
enterFileName: "Zadejte název souboru"
|
||||
@@ -206,7 +205,6 @@ blockThisInstance: "Blokovat tuto instanci"
|
||||
silenceThisInstance: "Utišit tuto instanci"
|
||||
operations: "Operace"
|
||||
software: "Software"
|
||||
softwareName: "Software"
|
||||
version: "Verze"
|
||||
metadata: "Metadata"
|
||||
withNFiles: "{n} soubor(ů)"
|
||||
@@ -233,7 +231,6 @@ noteDeleteConfirm: "Jste si jistí že chcete smazat tuhle poznámku?"
|
||||
pinLimitExceeded: "Nemůžete připnout další poznámky."
|
||||
done: "Hotovo"
|
||||
processing: "Zpracovávám"
|
||||
preprocessing: "Připravuji..."
|
||||
preview: "Náhled"
|
||||
default: "Výchozí"
|
||||
defaultValueIs: "Základní hodnota: {value}"
|
||||
@@ -268,7 +265,6 @@ removed: "Smazáno"
|
||||
removeAreYouSure: "Jste si jistí že chcete smazat \"{x}\"?"
|
||||
deleteAreYouSure: "Jste si jistí že chcete smazat \"{x}\"?"
|
||||
resetAreYouSure: "Opravdu resetovat?"
|
||||
areYouSure: "Jste si jistí?"
|
||||
saved: "Uloženo"
|
||||
upload: "Nahrát soubory"
|
||||
keepOriginalUploading: "Ponechat originální obrázek"
|
||||
@@ -279,12 +275,9 @@ uploadFromUrl: "Nahrát z URL adresy"
|
||||
uploadFromUrlDescription: "URL adresa souboru, který chcete nahrát"
|
||||
uploadFromUrlRequested: "Upload zažádán"
|
||||
uploadFromUrlMayTakeTime: "Může trvat nějakou dobu, dokud nebude dokončeno nahrávání."
|
||||
uploadNFiles: "Uploadovat {n} souborů"
|
||||
explore: "Objevovat"
|
||||
messageRead: "Přečtené"
|
||||
readAllChatMessages: "Označit všechny zprávy za přečtené"
|
||||
noMoreHistory: "To je vše"
|
||||
startChat: "Začít chat"
|
||||
nUsersRead: "přečteno {n} uživateli"
|
||||
agreeTo: "Souhlasím s {0}"
|
||||
agree: "Souhlasím"
|
||||
@@ -315,15 +308,12 @@ selectFile: "Vybrat soubor"
|
||||
selectFiles: "Vybrat soubory"
|
||||
selectFolder: "Vyberte složku"
|
||||
selectFolders: "Vyberte složky"
|
||||
fileNotSelected: "Nebyl vybrán žádný soubor"
|
||||
renameFile: "Přejmenovat soubor"
|
||||
folderName: "Název složky"
|
||||
createFolder: "Vytvořit složku"
|
||||
renameFolder: "Přejmenovat složku"
|
||||
deleteFolder: "Odstranit složku"
|
||||
folder: "Složka "
|
||||
addFile: "Přidat soubor"
|
||||
showFile: "Procházet soubory"
|
||||
emptyDrive: "Váš disk je prázdný"
|
||||
emptyFolder: "Tato složka je prázdná"
|
||||
unableToDelete: "Nelze smazat"
|
||||
@@ -434,7 +424,6 @@ totp: "Ověřovací aplikace"
|
||||
totpDescription: "Použít ověřovací aplikaci pro použití jednorázových hesel"
|
||||
moderator: "Moderátor"
|
||||
moderation: "Moderování"
|
||||
moderationNote: "Poznámka moderátora"
|
||||
nUsersMentioned: "{n} uživatelů zmínilo"
|
||||
securityKeyAndPasskey: "Bezpečnostní klíče a tokeny"
|
||||
securityKey: "Bezpečnostní klíč"
|
||||
@@ -490,9 +479,7 @@ uiLanguage: "Jazyk uživatelského rozhraní"
|
||||
aboutX: "O {x}"
|
||||
emojiStyle: "Styl emoji"
|
||||
native: "Výchozí"
|
||||
menuStyle: "Styl nabídky"
|
||||
style: "Vzhled"
|
||||
drawer: "Boční menu"
|
||||
popup: "Vyskakovací okno"
|
||||
showNoteActionsOnlyHover: "Zobrazit akce poznámky jenom při naběhnutí myši"
|
||||
noHistory: "Žádná historie"
|
||||
@@ -548,7 +535,6 @@ deleteAll: "Smazat vše"
|
||||
showFixedPostForm: "Zobrazit formulář pro nové příspěvky nad časovou osou"
|
||||
showFixedPostFormInChannel: "Zobrazit vkládací formulář na vrcholu časové osy (Kanály)"
|
||||
newNoteRecived: "Jsou k dispozici nové poznámky"
|
||||
newNote: "Nová poznámka"
|
||||
sounds: "Zvuky"
|
||||
sound: "Zvuky"
|
||||
listen: "Poslouchat"
|
||||
@@ -628,7 +614,6 @@ medium: "Střední"
|
||||
small: "Malé"
|
||||
generateAccessToken: "Vygenerovat přístupový token"
|
||||
permission: "Oprávnění"
|
||||
adminPermission: "Administrátorská práva"
|
||||
enableAll: "Povolit vše"
|
||||
disableAll: "Vypnout vše"
|
||||
tokenRequested: "Povolit přístup k účtu"
|
||||
@@ -904,9 +889,6 @@ oneHour: "1 hodina"
|
||||
oneDay: "1 den"
|
||||
oneWeek: "1 týden"
|
||||
oneMonth: "1 měsíc"
|
||||
threeMonths: "3 měsíce"
|
||||
oneYear: "1 rok"
|
||||
threeDays: "3 dny"
|
||||
reflectMayTakeTime: "Může trvat nějakou dobu, než se projeví změny."
|
||||
failedToFetchAccountInformation: "Nepodařily se načíst informace o účtě"
|
||||
rateLimitExceeded: "Překročení rychlostního limitu"
|
||||
@@ -1044,8 +1026,6 @@ showClipButtonInNoteFooter: "Přidat \"Připnout\" do akčního menu poznámky"
|
||||
noteIdOrUrl: "ID nebo URL poznámky"
|
||||
video: "Video"
|
||||
videos: "Videa"
|
||||
audio: "Zvuk"
|
||||
audioFiles: "Zvuk"
|
||||
dataSaver: "Spořič dat"
|
||||
accountMigration: "Migrace účtu"
|
||||
accountMoved: "Tenhle uživatel se přesunul na nový účet:"
|
||||
@@ -1073,8 +1053,6 @@ preservedUsernames: "Rezervované uživatelské jména"
|
||||
preservedUsernamesDescription: "Seznam uživatelských jmén na rezervaci oddělené mezerama. Tyhle jména se potom nebudou moc použít při normálním procesu vytvoření účtu ale můžou být použiti manuálně administratorém. Existujících účtů se to nedotkne."
|
||||
createNoteFromTheFile: "Vytvořit poznámku z tohodle souboru"
|
||||
archive: "Archiv"
|
||||
archived: "Archivované"
|
||||
unarchive: "Obnovit"
|
||||
channelArchiveConfirmTitle: "Opravdu chcete archivovat {name}?"
|
||||
channelArchiveConfirmDescription: "Archivovaný kanál se objeví v seznamu kanálů nebo ve výsledcích hledání. Nové poznámky se nedají vložit do seznamu."
|
||||
thisChannelArchived: "Tenhle kanál je archivovaný"
|
||||
@@ -1121,7 +1099,6 @@ doYouAgree: "Souhlasíte?"
|
||||
beSureToReadThisAsItIsImportant: "Přečtěte si prosím tyto důležité informace."
|
||||
iHaveReadXCarefullyAndAgree: "Přečetl jsem si text \"{x}\" a souhlasím s ním."
|
||||
icon: "Avatar"
|
||||
forYou: "Pro vás"
|
||||
replies: "Odpovědět"
|
||||
renotes: "Přeposlat"
|
||||
sourceCode: "Zdrojový kód"
|
||||
|
||||
@@ -543,7 +543,6 @@ regenerate: "Regenerieren"
|
||||
fontSize: "Schriftgröße"
|
||||
mediaListWithOneImageAppearance: "Höhe von Medienlisten mit nur einem Bild"
|
||||
limitTo: "Auf {x} begrenzen"
|
||||
showMediaListByGridInWideArea: "Medienlisten auf breiteren Bildschirmen nebeneinander anzeigen"
|
||||
noFollowRequests: "Keine ausstehenden Follow-Anfragen vorhanden"
|
||||
openImageInNewTab: "Bilder in neuem Tab öffnen"
|
||||
dashboard: "Dashboard"
|
||||
@@ -1407,7 +1406,6 @@ youAreAdmin: "Sie sind ein Administrator"
|
||||
frame: "Rahmen"
|
||||
presets: "Vorlage"
|
||||
zeroPadding: "Nullauffüllung"
|
||||
nothingToConfigure: "Es sind keine Einstellungen verfügbar"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
caption: "Dateibeschriftung"
|
||||
@@ -1423,40 +1421,12 @@ _imageEditing:
|
||||
camera_lens_model: "Objektivname"
|
||||
camera_mm: "Brennweite"
|
||||
camera_mm_35: "Brennweite (35-mm-Äquivalent)"
|
||||
camera_f: "Blende"
|
||||
camera_s: "Verschlusszeit"
|
||||
camera_iso: "ISO-Empfindlichkeit"
|
||||
gps_lat: "Breitengrad"
|
||||
gps_long: "Längengrad"
|
||||
_imageFrameEditor:
|
||||
title: "Rahmenbearbeitung"
|
||||
tip: "Sie können das Bild dekorieren, indem Sie einen Rahmen sowie ein Etikett mit Metadaten hinzufügen."
|
||||
header: "Kopfzeile"
|
||||
footer: "Fußzeile"
|
||||
borderThickness: "Randbreite"
|
||||
labelThickness: "Beschriftungsbreite"
|
||||
labelScale: "Etikettenskala"
|
||||
centered: "Zentriert"
|
||||
captionMain: "Überschrift (groß)"
|
||||
captionSub: "Beschriftung (klein)"
|
||||
availableVariables: "Verfügbare Variablen"
|
||||
withQrCode: "QR-Code"
|
||||
backgroundColor: "Hintergrundfarbe"
|
||||
textColor: "Textfarbe"
|
||||
font: "Schriftart"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
quitWithoutSaveConfirm: "Nicht gespeicherte Änderungen verwerfen?"
|
||||
failedToLoadImage: "Das Laden des Bildes ist fehlgeschlagen."
|
||||
_compression:
|
||||
_quality:
|
||||
high: "Hohe Qualität"
|
||||
medium: "Mittlere Qualität"
|
||||
low: "Niedrige Qualität"
|
||||
_size:
|
||||
large: "Groß"
|
||||
medium: "Medium"
|
||||
small: "Klein"
|
||||
_order:
|
||||
newest: "Neueste zuerst"
|
||||
oldest: "Älteste zuerst"
|
||||
@@ -1549,12 +1519,6 @@ _settings:
|
||||
contentsUpdateFrequency_description2: "Wenn der Echtzeitmodus aktiviert ist, werden die Inhalte unabhängig von dieser Einstellung in Echtzeit aktualisiert."
|
||||
showUrlPreview: "URL-Vorschau anzeigen"
|
||||
showAvailableReactionsFirstInNote: "Zeige die verfügbaren Reaktionen im oberen Bereich an."
|
||||
showPageTabBarBottom: "Tab-Leiste der Seite unten anzeigen"
|
||||
emojiPaletteBanner: "Sie können Voreinstellungen, die im Emoji-Picker dauerhaft angezeigt werden sollen, als Palette registrieren oder die Anzeigeart des Pickers anpassen."
|
||||
enableAnimatedImages: "Animierte Bilder aktivieren"
|
||||
settingsPersistence_title: "Persistenz der Einstellungen"
|
||||
settingsPersistence_description1: "Durch das Aktivieren der persistenten Speicherung der Einstellungen kann verhindert werden, dass Einstellungsinformationen verloren gehen."
|
||||
settingsPersistence_description2: "Je nach Umgebung ist eine Aktivierung möglicherweise nicht möglich."
|
||||
_chat:
|
||||
showSenderName: "Name des Absenders anzeigen"
|
||||
sendOnEnter: "Eingabetaste sendet Nachricht"
|
||||
@@ -1563,8 +1527,6 @@ _preferencesProfile:
|
||||
profileNameDescription: "Lege einen Namen fest, der dieses Gerät identifiziert."
|
||||
profileNameDescription2: "Beispiel: \"Haupt-PC\", \"Smartphone\""
|
||||
manageProfiles: "Profile verwalten"
|
||||
shareSameProfileBetweenDevicesIsNotRecommended: "Es wird nicht empfohlen, dasselbe Profil auf mehreren Geräten zu teilen."
|
||||
useSyncBetweenDevicesOptionIfYouWantToSyncSetting: "Wenn es Einstellungselemente gibt, die Sie über mehrere Geräte synchronisieren möchten, aktivieren Sie bitte die Option „Über mehrere Geräte synchronisieren“ jeweils einzeln."
|
||||
_preferencesBackup:
|
||||
autoBackup: "Automatische Sicherung"
|
||||
restoreFromBackup: "Wiederherstellen aus der Sicherung"
|
||||
@@ -1574,7 +1536,6 @@ _preferencesBackup:
|
||||
youNeedToNameYourProfileToEnableAutoBackup: "Um die automatische Sicherung zu aktivieren, müssen Profilnamen festgelegt werden."
|
||||
autoPreferencesBackupIsNotEnabledForThisDevice: "Die automatische Sicherung der Einstellungen ist auf diesem Gerät nicht aktiviert."
|
||||
backupFound: "Konfigurationssicherung gefunden."
|
||||
forceBackup: "Erzwungenes Backup der Einstellungen"
|
||||
_accountSettings:
|
||||
requireSigninToViewContents: "Anmeldung erfordern, um Inhalte anzuzeigen"
|
||||
requireSigninToViewContentsDescription1: "Erfordere eine Anmeldung, um alle Notizen und andere Inhalte anzuzeigen, die du erstellt hast. Dadurch wird verhindert, dass Crawler deine Informationen sammeln."
|
||||
@@ -1731,10 +1692,6 @@ _serverSettings:
|
||||
fanoutTimelineDbFallback: "Auf die Datenbank zurückfallen"
|
||||
fanoutTimelineDbFallbackDescription: "Ist diese Option aktiviert, wird die Chronik auf zusätzliche Abfragen in der Datenbank zurückgreifen, wenn sich die Chronik nicht im Cache befindet. Eine Deaktivierung führt zu geringerer Serverlast, aber schränkt den Zeitraum der abrufbaren Chronik ein. "
|
||||
reactionsBufferingDescription: "Wenn diese Option aktiviert ist, kann sie die Leistung beim Erstellen von Reaktionen erheblich verbessern und die Belastung der Datenbank verringern. Allerdings steigt die Speichernutzung von Redis."
|
||||
remoteNotesCleaning: "Automatische Bereinigung von Remote-Beiträgen"
|
||||
remoteNotesCleaning_description: "Wenn diese Option aktiviert ist, werden Remote-Beiträge, die eine bestimmte Zeit überschritten haben, regelmäßig bereinigt, um ein Aufblähen der Datenbank zu verhindern."
|
||||
remoteNotesCleaningMaxProcessingDuration: "Maximale fortlaufende Dauer des Reinigungsverarbeitungsprozesses"
|
||||
remoteNotesCleaningExpiryDaysForEachNotes: "Mindestaufbewahrungsdauer für Notizen"
|
||||
inquiryUrl: "Kontakt-URL"
|
||||
inquiryUrlDescription: "Gib eine URL für das Kontaktformular der Serverbetreiber oder eine Webseite an, die Kontaktinformationen enthält."
|
||||
openRegistration: "Registrierung von Konten aktivieren"
|
||||
@@ -1753,11 +1710,6 @@ _serverSettings:
|
||||
userGeneratedContentsVisibilityForVisitor: "Sichtbarkeit von nutzergenerierten Inhalten für Gäste"
|
||||
userGeneratedContentsVisibilityForVisitor_description: "Dies ist nützlich, um zu verhindern, dass unangemessene Inhalte, die nicht gut moderiert sind, ungewollt über deinen eigenen Server im Internet veröffentlicht werden."
|
||||
userGeneratedContentsVisibilityForVisitor_description2: "Die uneingeschränkte Veröffentlichung aller Inhalte des Servers im Internet, einschließlich der vom Server empfangenen Fremdinhalte, birgt Risiken. Dies ist besonders wichtig für Betrachter, die sich des dezentralen Charakters der Inhalte nicht bewusst sind, da sie selbst fremde Inhalte fälschlicherweise als auf dem Server erstellte Inhalte wahrnehmen könnten."
|
||||
restartServerSetupWizardConfirm_title: "Möchten Sie den Assistenten für die Ersteinrichtung des Servers erneut ausführen?"
|
||||
restartServerSetupWizardConfirm_text: "Einige aktuelle Einstellungen werden zurückgesetzt."
|
||||
entrancePageStyle: "Stil der Einstiegsseite"
|
||||
showTimelineForVisitor: "Zeitleiste anzeigen"
|
||||
showActivitiesForVisitor: "Aktivitäten anzeigen"
|
||||
_userGeneratedContentsVisibilityForVisitor:
|
||||
all: "Alles ist öffentlich"
|
||||
localOnly: "Nur lokale Inhalte werden veröffentlicht, fremde Inhalte bleiben privat"
|
||||
@@ -2080,7 +2032,6 @@ _role:
|
||||
canManageAvatarDecorations: "Profilbilddekorationen verwalten"
|
||||
driveCapacity: "Drive-Kapazität"
|
||||
maxFileSize: "Maximale Dateigröße, die hochgeladen werden kann"
|
||||
maxFileSize_caption: "Bei einem Reverse Proxy oder einem CDN können andere vorgelagerte Konfigurationswerte vorhanden sein."
|
||||
alwaysMarkNsfw: "Dateien immer als NSFW markieren"
|
||||
canUpdateBioMedia: "Kann ein Profil- oder ein Bannerbild bearbeiten"
|
||||
pinMax: "Maximale Anzahl an angehefteten Notizen"
|
||||
@@ -2095,7 +2046,6 @@ _role:
|
||||
descriptionOfRateLimitFactor: "Je niedriger desto weniger restriktiv, je höher destro restriktiver."
|
||||
canHideAds: "Kann Werbung ausblenden"
|
||||
canSearchNotes: "Nutzung der Notizsuchfunktion"
|
||||
canSearchUsers: "Nutzung der Benutzersuche"
|
||||
canUseTranslator: "Verwendung des Übersetzers"
|
||||
avatarDecorationLimit: "Maximale Anzahl an Profilbilddekorationen, die angebracht werden können"
|
||||
canImportAntennas: "Importieren von Antennen erlauben"
|
||||
@@ -2108,7 +2058,6 @@ _role:
|
||||
uploadableFileTypes_caption: "Gibt die zulässigen MIME-/Dateitypen an. Mehrere MIME-Typen können durch einen Zeilenumbruch getrennt angegeben werden, und Platzhalter können mit einem Sternchen (*) angegeben werden. (z. B. image/*)"
|
||||
uploadableFileTypes_caption2: "Bei manchen Dateien ist es nicht möglich, den Typ zu bestimmen. Um solche Dateien zuzulassen, füge {x} der Spezifikation hinzu."
|
||||
noteDraftLimit: "Anzahl der möglichen Entwürfe für serverseitige Notizen"
|
||||
scheduledNoteLimit: "Maximale Anzahl gleichzeitig erstellbarer geplanter Beiträge"
|
||||
watermarkAvailable: "Kann die Wasserzeichenfunktion verwenden"
|
||||
_condition:
|
||||
roleAssignedTo: "Manuellen Rollen zugewiesen"
|
||||
@@ -2369,7 +2318,6 @@ _time:
|
||||
minute: "Minute(n)"
|
||||
hour: "Stunde(n)"
|
||||
day: "Tag(en)"
|
||||
month: "Monat(e)"
|
||||
_2fa:
|
||||
alreadyRegistered: "Du hast bereits ein Gerät für Zwei-Faktor-Authentifizierung registriert."
|
||||
registerTOTP: "Authentifizierungs-App registrieren"
|
||||
@@ -2499,7 +2447,6 @@ _auth:
|
||||
scopeUser: "Als folgender Benutzer agieren"
|
||||
pleaseLogin: "Bitte logge dich ein, um Apps zu authorisieren."
|
||||
byClickingYouWillBeRedirectedToThisUrl: "Wenn der Zugang gewährt wird, wirst du automatisch zu folgender URL weitergeleitet"
|
||||
alreadyAuthorized: "Dieser Anwendung wurde bereits Zugriff gewährt."
|
||||
_antennaSources:
|
||||
all: "Alle Notizen"
|
||||
homeTimeline: "Notizen von Benutzern, denen gefolgt wird"
|
||||
@@ -2548,40 +2495,11 @@ _widgets:
|
||||
chat: "Mit dem Benutzer chatten"
|
||||
_widgetOptions:
|
||||
showHeader: "Kopfzeile anzeigen"
|
||||
transparent: "Hintergrund transparent machen"
|
||||
height: "Höhe"
|
||||
_button:
|
||||
colored: "Farbig"
|
||||
_clock:
|
||||
size: "Größe"
|
||||
thickness: "Dicke"
|
||||
thicknessThin: "Dünn"
|
||||
thicknessMedium: "Normal"
|
||||
thicknessThick: "Dick"
|
||||
graduations: "Zifferblattskala"
|
||||
graduationDots: "Punkt"
|
||||
graduationArabic: "Zahlen"
|
||||
fadeGraduations: "Skala ausblenden"
|
||||
sAnimation: "Zweite Animation"
|
||||
sAnimationElastic: "Elastisch"
|
||||
sAnimationEaseOut: "Weich"
|
||||
twentyFour: "24-Stunden-Format"
|
||||
labelTime: "Uhrzeit"
|
||||
labelTz: "Zeitzone"
|
||||
labelTimeAndTz: "Zeit und Zeitzone"
|
||||
timezone: "Zeitzone"
|
||||
showMs: "Millisekunden anzeigen"
|
||||
showLabel: "Beschriftung anzeigen"
|
||||
_jobQueue:
|
||||
sound: "Ton abspielen"
|
||||
_rss:
|
||||
url: "RSS-Feed-URL"
|
||||
refreshIntervalSec: "Aktualisierungsintervall (Sekunden)"
|
||||
maxEntries: "Maximale Anzahl der angezeigten Einträge"
|
||||
_rssTicker:
|
||||
shuffle: "Zufällige Anzeigereihenfolge"
|
||||
duration: "Banner-Scrollgeschwindigkeit (in Sekunden)"
|
||||
reverse: "In andere Richtung scrollen"
|
||||
_birthdayFollowings:
|
||||
period: "Dauer"
|
||||
_cw:
|
||||
@@ -2628,20 +2546,9 @@ _postForm:
|
||||
replyPlaceholder: "Dieser Notiz antworten …"
|
||||
quotePlaceholder: "Diese Notiz zitieren …"
|
||||
channelPlaceholder: "In einen Kanal senden"
|
||||
showHowToUse: "Formularbeschreibung anzeigen"
|
||||
_howToUse:
|
||||
content_title: "Dieser Text"
|
||||
content_description: "Bitte geben Sie den Inhalt ein, den Sie veröffentlichen möchten."
|
||||
toolbar_title: "Symbolleiste"
|
||||
toolbar_description: "Sie können Dateien oder Umfragen anhängen, Anmerkungen und Hashtags festlegen sowie Emojis und Erwähnungen einfügen."
|
||||
account_title: "Profilmenü"
|
||||
account_description: "Du kannst das Konto wechseln, von dem du postest, und dir eine Liste der im Konto gespeicherten Entwürfe und geplanten Beiträge anzeigen lassen."
|
||||
visibility_title: "Sichtbarkeit"
|
||||
visibility_description: "Sie können den Umfang festlegen, in dem die Notizen veröffentlicht werden."
|
||||
menu_title: "Menü"
|
||||
menu_description: "Sie können außerdem weitere Aktionen durchführen, z. B. als Entwurf speichern, das Posten planen oder Reaktionen einstellen."
|
||||
submit_title: "Senden-Button"
|
||||
submit_description: "Du kannst die Notiz posten. Du kannst sie auch mit Strg + Enter / Cmd + Enter posten."
|
||||
_placeholders:
|
||||
a: "Was machst du momentan?"
|
||||
b: "Was ist um dich herum los?"
|
||||
@@ -2787,8 +2694,6 @@ _notification:
|
||||
youReceivedFollowRequest: "Du hast eine Follow-Anfrage erhalten"
|
||||
yourFollowRequestAccepted: "Deine Follow-Anfrage wurde akzeptiert"
|
||||
pollEnded: "Umfrageergebnisse sind verfügbar"
|
||||
scheduledNotePosted: "Geplante Notiz wurde veröffentlicht"
|
||||
scheduledNotePostFailed: "Veröffentlichen der geplanten Notiz fehlgeschlagen"
|
||||
newNote: "Neue Notiz"
|
||||
unreadAntennaNote: "Antenne {name}"
|
||||
roleAssigned: "Rolle zugewiesen"
|
||||
@@ -2818,8 +2723,6 @@ _notification:
|
||||
quote: "Zitationen"
|
||||
reaction: "Reaktionen"
|
||||
pollEnded: "Ende von Umfragen"
|
||||
scheduledNotePosted: "Der geplante Beitrag wurde erfolgreich veröffentlicht."
|
||||
scheduledNotePostFailed: "Der geplante Beitrag ist fehlgeschlagen."
|
||||
receiveFollowRequest: "Erhaltene Follow-Anfragen"
|
||||
followRequestAccepted: "Akzeptierte Follow-Anfragen"
|
||||
roleAssigned: "Rolle zugewiesen"
|
||||
@@ -2859,14 +2762,6 @@ _deck:
|
||||
usedAsMinWidthWhenFlexible: "Ist \"Automatische Breitenanpassung\" aktiviert, wird hierfür die minimale Breite verwendet"
|
||||
flexible: "Automatische Breitenanpassung"
|
||||
enableSyncBetweenDevicesForProfiles: "Aktivieren der Synchronisierung von Profilinformationen zwischen Geräten"
|
||||
showHowToUse: "Siehe dir die UI-Beschreibung an."
|
||||
_howToUse:
|
||||
addColumn_title: "Spalte hinzufügen"
|
||||
addColumn_description: "Sie können den Spaltentyp auswählen und hinzufügen."
|
||||
settings_title: "UI-Einstellungen"
|
||||
settings_description: "Sie können die detaillierten Einstellungen der Deck-UI vornehmen."
|
||||
switchProfile_title: "Profil wechseln"
|
||||
switchProfile_description: "Das UI-Layout kann als Profil gespeichert werden, sodass du jederzeit zwischen den Profilen wechseln kannst."
|
||||
_columns:
|
||||
main: "Hauptspalte"
|
||||
widgets: "Widgets"
|
||||
@@ -2927,8 +2822,6 @@ _abuseReport:
|
||||
notifiedWebhook: "Zu verwendender Webhook"
|
||||
deleteConfirm: "Bist du sicher, dass du den Empfänger der Benachrichtigung entfernen möchtest?"
|
||||
_moderationLogTypes:
|
||||
clearQueue: "Warteschlange leeren"
|
||||
promoteQueue: "Warteschlange erneut ausführen"
|
||||
createRole: "Rolle erstellt"
|
||||
deleteRole: "Rolle gelöscht"
|
||||
updateRole: "Rolle aktualisiert"
|
||||
@@ -2986,7 +2879,6 @@ _fileViewer:
|
||||
url: "URL"
|
||||
uploadedAt: "Hochgeladen am"
|
||||
attachedNotes: "Zugehörige Notizen"
|
||||
usage: "Nutzung"
|
||||
thisPageCanBeSeenFromTheAuthor: "Nur der Benutzer, der diese Datei hochgeladen hat, kann diese Seite sehen."
|
||||
_externalResourceInstaller:
|
||||
title: "Von externer Seite installieren"
|
||||
@@ -3239,7 +3131,6 @@ _bootErrors:
|
||||
otherOption1: "Client-Einstellungen und Cache löschen"
|
||||
otherOption2: "Einfachen Client starten"
|
||||
otherOption3: "Starte das Reparaturwerkzeug"
|
||||
otherOption4: "Misskey im abgesicherten Modus starten"
|
||||
_search:
|
||||
searchScopeAll: "Alle"
|
||||
searchScopeLocal: "Lokal"
|
||||
@@ -3276,8 +3167,6 @@ _serverSetupWizard:
|
||||
doYouConnectToFediverse_description1: "Bei Anschluss an ein Netz von verteilten Servern (Fediverse) können Inhalte mit anderen Servern ausgetauscht werden."
|
||||
doYouConnectToFediverse_description2: "Die Verbindung mit dem Fediverse wird auch als „Föderation“ bezeichnet."
|
||||
youCanConfigureMoreFederationSettingsLater: "Erweiterte Einstellungen, wie z. B. die Angabe von föderierbaren Servern, können später vorgenommen werden."
|
||||
remoteContentsCleaning: "Automatische Bereinigung von Remote-Inhalten"
|
||||
remoteContentsCleaning_description: "Wenn Sie eine Föderation durchführen, empfangen Sie fortlaufend viele Inhalte. Wenn Sie die automatische Bereinigung aktivieren, werden Remote-Inhalte, deren bestimmter Zeitraum abgelaufen ist, automatisch vom Server gelöscht, wodurch Speicherplatz eingespart werden kann."
|
||||
adminInfo: "Administrator-Informationen"
|
||||
adminInfo_description: "Legt die Administrator-Informationen fest, die für den Empfang von Anfragen verwendet werden."
|
||||
adminInfo_mustBeFilled: "Dies ist auf einem offenen Server oder bei aktivierter Föderation erforderlich."
|
||||
@@ -3302,7 +3191,6 @@ _uploader:
|
||||
allowedTypes: "Hochladbare Dateitypen"
|
||||
tip: "Die Datei ist noch nicht hochgeladen worden. In diesem Dialog kannst du die Datei vor dem Hochladen anzeigen, umbenennen, komprimieren und zuschneiden. Wenn du fertig bist, klicke auf „Hochladen“, um den Upload zu starten."
|
||||
_clientPerformanceIssueTip:
|
||||
title: "Wenn du das Gefühl hast, dass der Akku sich schnell entlädt."
|
||||
makeSureDisabledAdBlocker: "Deaktiviere deinen Adblocker"
|
||||
makeSureDisabledAdBlocker_description: "Adblocker können die Leistung beeinträchtigen; vergewissere dich, ob in deinem Betriebssystem, Browser oder deinen Add-ons Adblocker aktiviert sind."
|
||||
makeSureDisabledCustomCss: "Benutzerdefiniertes CSS deaktivieren"
|
||||
@@ -3322,14 +3210,10 @@ _watermarkEditor:
|
||||
driveFileTypeWarnDescription: "Bilddatei auswählen"
|
||||
title: "Wasserzeichen bearbeiten"
|
||||
cover: "Alles bedecken"
|
||||
repeat: "Wiederholen"
|
||||
preserveBoundingRect: "So einstellen, dass beim Drehen nichts herausragt"
|
||||
opacity: "Transparenz"
|
||||
scale: "Größe"
|
||||
text: "Text"
|
||||
qr: "QR-Code"
|
||||
position: "Position"
|
||||
margin: "Abstand"
|
||||
type: "Art"
|
||||
image: "Bilder"
|
||||
advanced: "Fortgeschritten"
|
||||
@@ -3338,71 +3222,35 @@ _watermarkEditor:
|
||||
stripeWidth: "Linienbreite"
|
||||
stripeFrequency: "Linienanzahl"
|
||||
polkadot: "Punktmuster"
|
||||
checker: "Prüfer"
|
||||
polkadotMainDotOpacity: "Deckkraft des Hauptpunktes"
|
||||
polkadotMainDotRadius: "Größe des Hauptpunktes"
|
||||
polkadotSubDotOpacity: "Deckkraft des Unterpunktes"
|
||||
polkadotSubDotRadius: "Größe des Unterpunktes"
|
||||
polkadotSubDotDivisions: "Anzahl der Unterpunkte"
|
||||
leaveBlankToAccountUrl: "Wenn Sie es leer lassen, wird das Profilbild des Kontos verwendet."
|
||||
failedToLoadImage: "Bild konnte nicht geladen werden"
|
||||
_imageEffector:
|
||||
title: "Effekte"
|
||||
addEffect: "Effekte hinzufügen"
|
||||
discardChangesConfirm: "Änderungen verwerfen und beenden?"
|
||||
failedToLoadImage: "Bild konnte nicht geladen werden"
|
||||
_fxs:
|
||||
chromaticAberration: "Chromatische Abweichung"
|
||||
glitch: "Glitch"
|
||||
mirror: "Spiegeln"
|
||||
invert: "Farben umkehren"
|
||||
grayscale: "Schwarzweiß"
|
||||
blur: "Verwischen"
|
||||
pixelate: "Verpixeln"
|
||||
colorAdjust: "Farbkorrektur"
|
||||
colorClamp: "Farbkomprimierung"
|
||||
colorClampAdvanced: "Farbkomprimierung (erweitert)"
|
||||
distort: "Verzerrung"
|
||||
threshold: "inarisierun"
|
||||
zoomLines: "Konzentrationslinien"
|
||||
stripe: "Streifen"
|
||||
polkadot: "Punktmuster"
|
||||
checker: "Prüfer"
|
||||
blockNoise: "Blockrauschen"
|
||||
tearing: "Tearing"
|
||||
fill: "Ausfüllen"
|
||||
_fxProps:
|
||||
angle: "Winkel"
|
||||
scale: "Größe"
|
||||
size: "Größe"
|
||||
radius: "Radius"
|
||||
samples: "Stichprobengröße"
|
||||
offset: "Position"
|
||||
color: "Farbe"
|
||||
opacity: "Transparenz"
|
||||
normalize: "Normalisierung"
|
||||
amount: "Menge"
|
||||
lightness: "Erhellen"
|
||||
contrast: "Kontrast"
|
||||
hue: "Farbton"
|
||||
brightness: "Helligkeit"
|
||||
saturation: "Sättigung"
|
||||
max: "Maximum"
|
||||
min: "Minimum"
|
||||
direction: "Richtung"
|
||||
phase: "Sättigung"
|
||||
frequency: "Häufigkeit"
|
||||
strength: "Stärke"
|
||||
glitchChannelShift: "Verschiebung"
|
||||
seed: "Seed-Wert"
|
||||
redComponent: "Rot-Anteil"
|
||||
greenComponent: "Grün-Anteil"
|
||||
blueComponent: "Blau-Anteil"
|
||||
threshold: "Schwellenwert"
|
||||
centerX: "Zentrum X"
|
||||
centerY: "Zentrum Y"
|
||||
zoomLinesMaskSize: "Mitteldurchmesser"
|
||||
circle: "Kreisförmig"
|
||||
drafts: "Entwurf"
|
||||
_drafts:
|
||||
select: "Entwurf auswählen"
|
||||
@@ -3413,27 +3261,10 @@ _drafts:
|
||||
noDrafts: "Keine Entwürfe"
|
||||
replyTo: "Antwort an {user}"
|
||||
quoteOf: "Zitat von {user}s Notiz"
|
||||
postTo: "Beitrag im {channel}"
|
||||
saveToDraft: "Als Entwurf speichern"
|
||||
restoreFromDraft: "Aus Entwurf wiederherstellen"
|
||||
restore: "Wiederherstellen"
|
||||
listDrafts: "Liste der Entwürfe"
|
||||
schedule: "Beitragsplanung"
|
||||
listScheduledNotes: "Liste der geplanten Beiträge"
|
||||
cancelSchedule: "Reservierung stornieren"
|
||||
qr: "QR-Code"
|
||||
_qr:
|
||||
showTabTitle: "Anzeigeart"
|
||||
readTabTitle: "Auslesen"
|
||||
shareTitle: "{name} {acct}"
|
||||
shareText: "Bitte folge mir im Fediverse!"
|
||||
chooseCamera: "Kamera auswählen"
|
||||
cannotToggleFlash: "Blitzauswahl nicht möglich"
|
||||
turnOnFlash: "Blitz einschalten"
|
||||
turnOffFlash: "Blitz ausschalten"
|
||||
startQr: "QR-Code-Leser starten"
|
||||
stopQr: "QR-Code-Leser stoppen"
|
||||
noQrCodeFound: "QR-Code wurde nicht gefunden"
|
||||
scanFile: "Gerätebilder scannen"
|
||||
raw: "Text"
|
||||
mfm: "MFM"
|
||||
|
||||
@@ -543,7 +543,6 @@ regenerate: "Regenerate"
|
||||
fontSize: "Font size"
|
||||
mediaListWithOneImageAppearance: "Height of media lists with one image only"
|
||||
limitTo: "Limit to {x}"
|
||||
showMediaListByGridInWideArea: "Display the media list in a grid when the screen width is wide"
|
||||
noFollowRequests: "You don't have any pending follow requests"
|
||||
openImageInNewTab: "Open images in new tab"
|
||||
dashboard: "Dashboard"
|
||||
@@ -3401,7 +3400,11 @@ _imageEffector:
|
||||
threshold: "Threshold"
|
||||
centerX: "Center X"
|
||||
centerY: "Center Y"
|
||||
zoomLinesSmoothing: "Smoothing"
|
||||
zoomLinesSmoothingDescription: "Smoothing and zoom line width cannot be used together."
|
||||
zoomLinesThreshold: "Zoom line width"
|
||||
zoomLinesMaskSize: "Center diameter"
|
||||
zoomLinesBlack: "Make black"
|
||||
circle: "Circular"
|
||||
drafts: "Drafts"
|
||||
_drafts:
|
||||
|
||||
@@ -543,7 +543,6 @@ regenerate: "Regenerar"
|
||||
fontSize: "Tamaño de la letra"
|
||||
mediaListWithOneImageAppearance: "Altura de la lista de medios con una sola imagen."
|
||||
limitTo: "{x} hasta un máximo de"
|
||||
showMediaListByGridInWideArea: "Cuando el ancho de la pantalla sea grande, muestra la lista de multimedia uno al lado del otro."
|
||||
noFollowRequests: "No hay solicitudes de seguimiento"
|
||||
openImageInNewTab: "Abrir imagen en nueva pestaña"
|
||||
dashboard: "Panel de control"
|
||||
@@ -3312,7 +3311,7 @@ _clientPerformanceIssueTip:
|
||||
_clip:
|
||||
tip: "Clip es una función que permite organizar varias notas."
|
||||
_userLists:
|
||||
tip: "Puedes crear listas que incluyan a cualquier usuario. Las listas creadas se pueden visualizar en forma de cronología."
|
||||
tip: "Las listas pueden contener cualquier usuario que especifiques al crearlas, la lista creada puede mostrarse entonces como una línea de tiempo mostrando solo los usuarios especificados."
|
||||
watermark: "Marca de Agua"
|
||||
defaultPreset: "Por defecto"
|
||||
_watermarkEditor:
|
||||
@@ -3401,9 +3400,11 @@ _imageEffector:
|
||||
threshold: "Umbral"
|
||||
centerX: "Centrar X"
|
||||
centerY: "Centrar Y"
|
||||
density: "Densidad"
|
||||
zoomLinesOutlineThickness: "Grosor del borde"
|
||||
zoomLinesSmoothing: "Suavizado"
|
||||
zoomLinesSmoothingDescription: "El suavizado y el ancho de línea de zoom no se pueden utilizar juntos."
|
||||
zoomLinesThreshold: "Ancho de línea del zoom"
|
||||
zoomLinesMaskSize: "Diámetro del centro"
|
||||
zoomLinesBlack: "Cambiar color de las líneas de impacto a negro."
|
||||
circle: "Círculo"
|
||||
drafts: "Borrador"
|
||||
_drafts:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
_lang_: "Italiano"
|
||||
headlineMisskey: "Rete collegata tramite Note"
|
||||
introMisskey: "Eccoci! Misskey è un servizio di microblogging decentralizzato, libero e aperto. \n📡 Puoi pubblicare «Note» per condividere ciò che sta succedendo o per dire a tutti qualcosa su di te. \n👍 Puoi reagire inviando emoji rapidi alle «Note» provenienti da altri profili nel Fediverso.\n🚀 Esplora un nuovo mondo insieme a noi!"
|
||||
introMisskey: "Eccoci! Misskey è un servizio di microblogging decentralizzato, libero e aperto. \n\n📡 Puoi pubblicare «Note» per condividere ciò che sta succedendo o per dire a tutti qualcosa su di te. \n\n👍 Puoi reagire inviando emoji rapidi alle «Note» provenienti da altri profili nel Fediverso.\n\n🚀 Esplora un nuovo mondo insieme a noi!"
|
||||
poweredByMisskeyDescription: "{name} è uno dei servizi (chiamati istanze) che utilizzano la piattaforma open source <b>Misskey</b>."
|
||||
monthAndDay: "{day}/{month}"
|
||||
search: "Cerca"
|
||||
@@ -127,7 +127,7 @@ renoteToOtherChannel: "Rinota a un altro canale"
|
||||
pinnedNote: "Nota in primo piano"
|
||||
pinned: "Fissa sul profilo"
|
||||
you: "Tu"
|
||||
clickToShow: "Media nascosto, cliccare solo se si intende vedere"
|
||||
clickToShow: "Contenuto occultato, cliccare solo se si intende vedere"
|
||||
sensitive: "Esplicito"
|
||||
add: "Aggiungi"
|
||||
reaction: "Reazioni"
|
||||
@@ -543,7 +543,6 @@ regenerate: "Generare di nuovo"
|
||||
fontSize: "Dimensione carattere"
|
||||
mediaListWithOneImageAppearance: "Altezza dell'elenco media con una sola immagine "
|
||||
limitTo: "Limita a {x}"
|
||||
showMediaListByGridInWideArea: "Quando la larghezza dello schermo è ampia, mostra i media affiancati"
|
||||
noFollowRequests: "Non ci sono richieste di relazione"
|
||||
openImageInNewTab: "Apri le immagini in un nuovo tab"
|
||||
dashboard: "Pannello di controllo"
|
||||
@@ -557,7 +556,7 @@ clientSettings: "Impostazioni client"
|
||||
accountSettings: "Impostazioni profilo"
|
||||
promotion: "Promossa"
|
||||
promote: "Pubblicizza"
|
||||
numberOfDays: ""
|
||||
numberOfDays: "Numero di giorni"
|
||||
hideThisNote: "Nasconda la nota"
|
||||
showFeaturedNotesInTimeline: "Mostrare le note di tendenza nella tua timeline"
|
||||
objectStorage: "Storage S3"
|
||||
@@ -702,7 +701,7 @@ hardWordMuteDescription: "Ignora le Note con la parola o la regola specificata.
|
||||
regexpError: "errore regex"
|
||||
regexpErrorDescription: "Si è verificato un errore nell'espressione regolare alla riga {line} della parola muta {tab}:"
|
||||
instanceMute: "Silenziare l'istanza"
|
||||
userSaysSomething: "{name} ha scritto qualcosa"
|
||||
userSaysSomething: "{name} ha detto qualcosa"
|
||||
userSaysSomethingAbout: "{name} ha anNotato qualcosa su \"{word}\""
|
||||
makeActive: "Attiva"
|
||||
display: "Visualizza"
|
||||
@@ -1408,7 +1407,6 @@ frame: "Cornice"
|
||||
presets: "Preimpostato"
|
||||
zeroPadding: "Al vivo"
|
||||
nothingToConfigure: "Niente da configurare"
|
||||
viewRenotedChannel: "Visualizza il canale del Rinota"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
caption: "Didascalia dell'immagine"
|
||||
@@ -2072,7 +2070,7 @@ _role:
|
||||
gtlAvailable: "Disponibilità della Timeline Federata"
|
||||
ltlAvailable: "Disponibilità della Timeline Locale"
|
||||
canPublicNote: "Scrivere Note con Visibilità Pubblica"
|
||||
mentionMax: ""
|
||||
mentionMax: "Numero massimo di menzioni in una nota"
|
||||
canInvite: "Generare codici di invito all'istanza"
|
||||
inviteLimit: "Limite di codici invito"
|
||||
inviteLimitCycle: "Intervallo di emissione del codice di invito"
|
||||
@@ -2401,59 +2399,59 @@ _2fa:
|
||||
backupCodesExhaustedWarning: "Hai esaurito i codici usa-e-getta. Se l'App che genera il codice OTP non è più disponibile, non potrai più accedere al tuo profilo. Ripeti la configurazione per l'autenticazione a due fattori."
|
||||
moreDetailedGuideHere: "Informazioni dettagliate sull'autenticazione multi fattore (2FA/MFA)"
|
||||
_permissions:
|
||||
"read:account": "Vedere le informazioni sul profilo"
|
||||
"write:account": "Modificare le informazioni sul profilo"
|
||||
"read:blocks": "Vedere i profili bloccati"
|
||||
"write:blocks": "Gestire il blocco profili"
|
||||
"read:drive": "Leggere file nel Drive"
|
||||
"write:drive": "Gestire file nel Drive"
|
||||
"read:favorites": "Vedere le Note Preferite"
|
||||
"write:favorites": "Gestire Note Preferite"
|
||||
"read:following": "Vedere i Following"
|
||||
"write:following": "Gestire i Following"
|
||||
"read:messaging": "Vedere Messaggi Privati"
|
||||
"write:messaging": "Modificare Messaggi Privati"
|
||||
"read:mutes": "Vedere profili silenziati"
|
||||
"write:mutes": "Gestire profili silenziati"
|
||||
"write:notes": "Gestire le Note"
|
||||
"read:notifications": "Vedere le notifiche"
|
||||
"write:notifications": "Gestire le notifiche"
|
||||
"read:reactions": "Vedere le reazioni"
|
||||
"write:reactions": "Gestire le reazioni"
|
||||
"read:account": "Visualizza le informazioni sul profilo"
|
||||
"write:account": "Modifica le informazioni sul profilo"
|
||||
"read:blocks": "Visualizza i profili bloccati"
|
||||
"write:blocks": "Gestisci i profili bloccati"
|
||||
"read:drive": "Apri il Drive"
|
||||
"write:drive": "Gestisci il Drive"
|
||||
"read:favorites": "Visualizza i tuoi preferiti"
|
||||
"write:favorites": "Gestisci i tuoi preferiti"
|
||||
"read:following": "Vedi le informazioni di follow"
|
||||
"write:following": "Aggiungere e togliere Following"
|
||||
"read:messaging": "Visualizzare la chat"
|
||||
"write:messaging": "Gestire la chat"
|
||||
"read:mutes": "Vedi i profili silenziati"
|
||||
"write:mutes": "Gestione dei profili silenziati"
|
||||
"write:notes": "Creare / Eliminare note"
|
||||
"read:notifications": "Visualizzare notifiche"
|
||||
"write:notifications": "Gestione delle notifiche"
|
||||
"read:reactions": "Vedi reazioni"
|
||||
"write:reactions": "Gestione delle reazioni"
|
||||
"write:votes": "Votare"
|
||||
"read:pages": "Vedere le pagine"
|
||||
"write:pages": "Gestire le pagine"
|
||||
"read:page-likes": "Vedere le Pagine piaciute"
|
||||
"write:page-likes": "Modificare le Pagine piaciute"
|
||||
"read:pages": "Visualizzare pagine"
|
||||
"write:pages": "Gestire pagine"
|
||||
"read:page-likes": "Visualizzare i \"Mi piace\" di pagine"
|
||||
"write:page-likes": "Gestire i \"Mi piace\" di pagine"
|
||||
"read:user-groups": "Vedere i gruppi di utenti"
|
||||
"write:user-groups": "Gestire i gruppi di utenti"
|
||||
"read:channels": "Vedere i canali"
|
||||
"write:channels": "Gestire i canali"
|
||||
"read:gallery": "Vedere le gallerie"
|
||||
"write:gallery": "Gestire le gallerie"
|
||||
"read:gallery-likes": "Vedere le Gallerie piaciute"
|
||||
"write:gallery-likes": "Gestire le Gallerie piaciute"
|
||||
"read:flash": "Vedere i Play"
|
||||
"write:flash": "Gestire i Play"
|
||||
"read:flash-likes": "Vedere la lista di Play piaciuti"
|
||||
"write:flash-likes": "Modificare la lista di Play piaciuti"
|
||||
"read:admin:abuse-user-reports": "Vedere le segnalazioni"
|
||||
"write:admin:delete-account": "Eliminare profili"
|
||||
"write:admin:delete-all-files-of-a-user": "Eliminare file dal Drive dei profili"
|
||||
"read:admin:index-stats": "Vedere gli indici del database"
|
||||
"read:admin:table-stats": "Vedere le statistiche database"
|
||||
"read:admin:user-ips": "Vedere gli indirizzi IP dei profili"
|
||||
"read:admin:meta": "Vedere i metadati dell'istanza"
|
||||
"write:admin:reset-password": "Ripristinare la password del profilo"
|
||||
"write:admin:resolve-abuse-user-report": "Risolvere le segnalazioni"
|
||||
"read:channels": "Visualizza canali"
|
||||
"write:channels": "Gestione dei canali"
|
||||
"read:gallery": "Visualizza la galleria."
|
||||
"write:gallery": "Gestione della galleria"
|
||||
"read:gallery-likes": "Visualizza i contenuti della galleria."
|
||||
"write:gallery-likes": "Manipolazione dei \"Mi piace\" della galleria."
|
||||
"read:flash": "Visualizza Play"
|
||||
"write:flash": "Modifica Play"
|
||||
"read:flash-likes": "Visualizza lista di Play piaciuti"
|
||||
"write:flash-likes": "Modifica lista di Play piaciuti"
|
||||
"read:admin:abuse-user-reports": "Mostra i report dai profili utente"
|
||||
"write:admin:delete-account": "Elimina l'account utente"
|
||||
"write:admin:delete-all-files-of-a-user": "Elimina i file dell'account utente"
|
||||
"read:admin:index-stats": "Visualizza informazioni sugli indici del database"
|
||||
"read:admin:table-stats": "Visualizza informazioni sulle tabelle del database"
|
||||
"read:admin:user-ips": "Visualizza indirizzi IP degli account"
|
||||
"read:admin:meta": "Visualizza i metadati dell'istanza"
|
||||
"write:admin:reset-password": "Ripristina la password dell'account utente"
|
||||
"write:admin:resolve-abuse-user-report": "Risolvere le segnalazioni dagli account utente"
|
||||
"write:admin:send-email": "Spedire email"
|
||||
"read:admin:server-info": "Vedere le informazioni sul server"
|
||||
"read:admin:show-moderation-log": "Vedere lo storico di moderazione"
|
||||
"read:admin:show-user": "Vedere le informazioni private dei profili"
|
||||
"read:admin:show-user": "Vedere le informazioni private degli account utente"
|
||||
"write:admin:suspend-user": "Sospendere i profili"
|
||||
"write:admin:unset-user-avatar": "Rimuovere la foto profilo dai profili"
|
||||
"write:admin:unset-user-banner": "Rimuovere l'immagine testata dai profili"
|
||||
"write:admin:unsuspend-user": "Rimuovere la sospensione ai profili"
|
||||
"write:admin:unsuspend-user": "Togliere la sospensione ai profili"
|
||||
"write:admin:meta": "Modificare i metadati dell'istanza"
|
||||
"write:admin:user-note": "Scrivere annotazioni di moderazione"
|
||||
"write:admin:roles": "Gestire i ruoli"
|
||||
@@ -2481,11 +2479,11 @@ _permissions:
|
||||
"read:admin:ad": "Vedere i banner pubblicitari"
|
||||
"write:invite-codes": "Creare codici di invito"
|
||||
"read:invite-codes": "Vedere i codici di invito"
|
||||
"write:clip-favorite": "Modificare Clip preferite"
|
||||
"write:clip-favorite": "Impostare Clip preferite"
|
||||
"read:clip-favorite": "Vedere Clip preferite"
|
||||
"read:federation": "Vedere la federazione"
|
||||
"write:report-abuse": "Inviare segnalazioni"
|
||||
"write:chat": "Modificare Messaggi Privati"
|
||||
"write:chat": "Gestire la chat"
|
||||
"read:chat": "Visualizzare le chat"
|
||||
_auth:
|
||||
shareAccessTitle: "Permessi dell'applicazione"
|
||||
@@ -2534,19 +2532,19 @@ _widgets:
|
||||
instanceCloud: "Nuvola di federazione"
|
||||
postForm: "Finestra di pubblicazione"
|
||||
slideshow: "Diapositive"
|
||||
button: "Bottone"
|
||||
button: "Pulsante"
|
||||
onlineUsers: "Persone attive adesso"
|
||||
jobQueue: "Coda di lavoro"
|
||||
serverMetric: "Statistiche server"
|
||||
aiscript: "Console AiScript"
|
||||
aiscriptApp: "App AiScript"
|
||||
aichan: "Mascotte Ai"
|
||||
userList: "Lista profili"
|
||||
userList: "Elenco utenti"
|
||||
_userList:
|
||||
chooseList: "Seleziona una lista"
|
||||
clicker: "Cliccheria"
|
||||
birthdayFollowings: "Compleanni del giorno"
|
||||
chat: "Messaggi diretti"
|
||||
chat: "Chatta con questa persona"
|
||||
_widgetOptions:
|
||||
showHeader: "Mostra la testata"
|
||||
transparent: "Sfondo trasparente"
|
||||
@@ -2662,7 +2660,7 @@ _profile:
|
||||
metadataContent: "Contenuto"
|
||||
changeAvatar: "Modifica immagine profilo"
|
||||
changeBanner: "Cambia intestazione"
|
||||
verifiedLinkDescription: "Come avere i collegamenti verificati: inserisci la URL ad una pagina che contiene un collegamento al tuo profilo.\nVedrai una spunta di conferma se, in quella pagina, il collegamento al tuo profilo Misskey ha attributo rel='me'."
|
||||
verifiedLinkDescription: "Puoi verificare il tuo profilo mostrando una icona. Devi inserire la URL alla pagina che contiene un link al tuo profilo.\nPer verificare il profilo tramite la spunta di conferma, devi inserire la url alla pagina che contiene un link al tuo profilo Misskey. Deve avere attributo rel='me'."
|
||||
avatarDecorationMax: "Puoi aggiungere fino a {max} decorazioni."
|
||||
followedMessage: "Messaggio, quando qualcuno ti segue"
|
||||
followedMessageDescription: "Puoi impostare un breve messaggio da mostrare agli altri profili quando ti seguono."
|
||||
@@ -2782,7 +2780,7 @@ _notification:
|
||||
fileUploaded: "File caricato correttamente"
|
||||
youGotMention: "{name} ti ha menzionato"
|
||||
youGotReply: "{name} ti ha risposto"
|
||||
youGotQuote: "{name} ha scritto citando la tua Nota"
|
||||
youGotQuote: "{name} ha citato la tua Nota e ha detto"
|
||||
youRenoted: "{name} ha rinotato"
|
||||
youWereFollowed: "Follower aggiuntivo"
|
||||
youReceivedFollowRequest: "Hai ricevuto una richiesta di follow"
|
||||
@@ -2808,7 +2806,7 @@ _notification:
|
||||
exportOfXCompleted: "Abbiamo completato l'esportazione di {x}"
|
||||
login: "Autenticazione avvenuta"
|
||||
createToken: "È stato creato un token di accesso"
|
||||
createTokenDescription: "Se non ne sai nulla, elimina il token di accesso: {text}."
|
||||
createTokenDescription: "In caso contrario, eliminare il token di accesso tramite ({text})."
|
||||
_types:
|
||||
all: "Tutte"
|
||||
note: "Nuove Note"
|
||||
@@ -3339,7 +3337,7 @@ _watermarkEditor:
|
||||
stripeWidth: "Larghezza della linea"
|
||||
stripeFrequency: "Il numero di linee"
|
||||
polkadot: "A pallini"
|
||||
checker: "Scacchiera"
|
||||
checker: "revisore"
|
||||
polkadotMainDotOpacity: "Opacità del punto principale"
|
||||
polkadotMainDotRadius: "Dimensione del punto principale"
|
||||
polkadotSubDotOpacity: "Opacità del punto secondario"
|
||||
@@ -3368,7 +3366,7 @@ _imageEffector:
|
||||
zoomLines: "Linea di saturazione"
|
||||
stripe: "Strisce"
|
||||
polkadot: "A pallini"
|
||||
checker: "Scacchiera"
|
||||
checker: "revisore"
|
||||
blockNoise: "Attenua rumore"
|
||||
tearing: "Strappa immagine"
|
||||
fill: "Riempimento"
|
||||
@@ -3402,9 +3400,11 @@ _imageEffector:
|
||||
threshold: "Soglia"
|
||||
centerX: "Centro orizzontale"
|
||||
centerY: "Centro verticale"
|
||||
density: "Densità"
|
||||
zoomLinesOutlineThickness: "Spessore del bordo"
|
||||
zoomLinesSmoothing: "Levigatura"
|
||||
zoomLinesSmoothingDescription: "Non si possono usare insieme la levigatura e la larghezza della linea centrale."
|
||||
zoomLinesThreshold: "Limite delle linee zoom"
|
||||
zoomLinesMaskSize: "Ampiezza del diametro"
|
||||
zoomLinesBlack: "Bande nere"
|
||||
circle: "Circolare"
|
||||
drafts: "Bozze"
|
||||
_drafts:
|
||||
|
||||
@@ -1408,7 +1408,6 @@ frame: "フレーム"
|
||||
presets: "プリセット"
|
||||
zeroPadding: "ゼロ埋め"
|
||||
nothingToConfigure: "設定項目はありません"
|
||||
viewRenotedChannel: "リノート先のチャンネルを見る"
|
||||
|
||||
_imageEditing:
|
||||
_vars:
|
||||
@@ -1779,6 +1778,12 @@ _serverSettings:
|
||||
entrancePageStyle: "エントランスページのスタイル"
|
||||
showTimelineForVisitor: "タイムラインを表示する"
|
||||
showActivitiesForVisitor: "アクティビティを表示する"
|
||||
features: "機能"
|
||||
|
||||
_spReactions:
|
||||
enable: "スペシャルリアクションを有効にする"
|
||||
description1: "通常のリアクションより目立つ「スペシャルリアクション」をノートに送れる機能です。"
|
||||
description2: "有効にする場合、ロールポリシーで、毎月送ることのできる最大数を設定してください。"
|
||||
|
||||
_userGeneratedContentsVisibilityForVisitor:
|
||||
all: "全て公開"
|
||||
@@ -2891,6 +2896,7 @@ _notification:
|
||||
renote: "リノート"
|
||||
quote: "引用"
|
||||
reaction: "リアクション"
|
||||
spReaction: "スペシャルリアクション"
|
||||
pollEnded: "アンケートが終了"
|
||||
scheduledNotePosted: "予約投稿が成功した"
|
||||
scheduledNotePostFailed: "予約投稿が失敗した"
|
||||
@@ -3513,9 +3519,11 @@ _imageEffector:
|
||||
threshold: "しきい値"
|
||||
centerX: "中心X"
|
||||
centerY: "中心Y"
|
||||
density: "密度"
|
||||
zoomLinesOutlineThickness: "線の影の太さ"
|
||||
zoomLinesSmoothing: "スムージング"
|
||||
zoomLinesSmoothingDescription: "スムージングと集中線の幅の設定は併用できません。"
|
||||
zoomLinesThreshold: "集中線の幅"
|
||||
zoomLinesMaskSize: "中心径"
|
||||
zoomLinesBlack: "黒色にする"
|
||||
circle: "円形"
|
||||
|
||||
drafts: "下書き"
|
||||
@@ -3553,17 +3561,3 @@ _qr:
|
||||
scanFile: "端末の画像をスキャン"
|
||||
raw: "テキスト"
|
||||
mfm: "MFM"
|
||||
|
||||
_room:
|
||||
snapToGrid: "グリッドにスナップ"
|
||||
gridScale: "グリッドサイズ"
|
||||
thereAreUnsavedChanges: "未保存の変更があります"
|
||||
revertAllChangesConfirmation: "全ての変更を取り消し、部屋を最後に保存した状態まで戻しますか?"
|
||||
graphicsQuality: "グラフィックの品質"
|
||||
frameRate: "フレームレート"
|
||||
resolution: "解像度"
|
||||
yourDeviceNotSupported_title: "お使いのデバイスはMisskeyRoomをサポートしていません。"
|
||||
yourDeviceNotSupported_description: "MisskeyRoomを動作させるには、WebGPUをサポートするデバイスが必要です。"
|
||||
failedToInitialize: "初期化に失敗しました"
|
||||
crushed_description: "バグ、またはデバイスのリソース不足の可能性が考えられます。"
|
||||
antialiasing: "アンチエイリアス"
|
||||
|
||||
@@ -543,7 +543,6 @@ regenerate: "재생성"
|
||||
fontSize: "글자 크기"
|
||||
mediaListWithOneImageAppearance: "이미지가 1개 뿐인 미디어 목록의 높이"
|
||||
limitTo: "{x}로 제한"
|
||||
showMediaListByGridInWideArea: "화면 폭이 넓을 때는 미디어 목록을 가로로 표시하기"
|
||||
noFollowRequests: "처리되지 않은 팔로우 요청이 없습니다"
|
||||
openImageInNewTab: "새 탭에서 이미지 열기"
|
||||
dashboard: "대시보드"
|
||||
@@ -1335,7 +1334,7 @@ markAsSensitiveConfirm: "이 미디어를 민감한 미디어로 설정하시겠
|
||||
unmarkAsSensitiveConfirm: "이 미디어의 민감한 미디어 지정을 해제하시겠습니까?"
|
||||
preferences: "환경설정"
|
||||
accessibility: "접근성"
|
||||
preferencesProfile: "설정 프로파일"
|
||||
preferencesProfile: "설정 프로필"
|
||||
copyPreferenceId: "설정한 ID를 복사"
|
||||
resetToDefaultValue: "기본값으로 되돌리기"
|
||||
overrideByAccount: "계정으로 덮어쓰기"
|
||||
@@ -1348,7 +1347,7 @@ preferenceSyncConflictTitle: "서버에 설정값이 존재합니다."
|
||||
preferenceSyncConflictText: "동기화를 활성화 한 항목의 설정 값은 서버에 저장되지만, 해당 항목은 이미 서버에 설정 값이 저장되어져 있습니다. 어느 쪽의 설정 값을 덮어씌울까요?"
|
||||
preferenceSyncConflictChoiceMerge: "병합"
|
||||
preferenceSyncConflictChoiceServer: "서버 설정값"
|
||||
preferenceSyncConflictChoiceDevice: "장치 설정 값"
|
||||
preferenceSyncConflictChoiceDevice: "장치 설정값"
|
||||
preferenceSyncConflictChoiceCancel: "동기화 취소"
|
||||
paste: "붙여넣기"
|
||||
emojiPalette: "이모지 팔레트"
|
||||
@@ -1408,7 +1407,6 @@ frame: "프레임"
|
||||
presets: "프리셋"
|
||||
zeroPadding: "0으로 채우기"
|
||||
nothingToConfigure: "설정 항목이 없습니다."
|
||||
viewRenotedChannel: "리노트된 채널 보기"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
caption: "파일 설명"
|
||||
@@ -1467,17 +1465,17 @@ _chat:
|
||||
newMessage: "새로운 메시지"
|
||||
individualChat: "개인 대화"
|
||||
individualChat_description: "특정 유저와 일대일 채팅을 할 수 있습니다."
|
||||
roomChat: "그룹 채팅"
|
||||
roomChat: "룸 채팅"
|
||||
roomChat_description: "여러 명이 함께 채팅할 수 있습니다.\n또한, 개인 채팅을 허용하지 않은 유저와도 상대방이 수락하면 채팅을 할 수 있습니다."
|
||||
createRoom: "방 만들기"
|
||||
createRoom: "룸을 생성"
|
||||
inviteUserToChat: "유저를 초대하여 채팅을 시작하세요"
|
||||
yourRooms: "만들어진 방"
|
||||
joiningRooms: "참가 중인 방"
|
||||
yourRooms: "생성한 룸"
|
||||
joiningRooms: "참가 중인 룸"
|
||||
invitations: "초대"
|
||||
noInvitations: "초대장이 없습니다"
|
||||
history: "이력"
|
||||
noHistory: "기록이 없습니다"
|
||||
noRooms: "방이 없습니다"
|
||||
noRooms: "룸이 없습니다"
|
||||
inviteUser: "유저를 초대"
|
||||
sentInvitations: "초대를 보내기"
|
||||
join: "참여"
|
||||
@@ -1488,14 +1486,14 @@ _chat:
|
||||
home: "홈"
|
||||
send: "전송"
|
||||
newline: "줄바꿈"
|
||||
muteThisRoom: "이 방을 뮤트하기"
|
||||
deleteRoom: "방을 삭제하기"
|
||||
muteThisRoom: "이 룸을 뮤트"
|
||||
deleteRoom: "룸을 삭제"
|
||||
chatNotAvailableForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅이 활성화되어 있지 않습니다."
|
||||
chatIsReadOnlyForThisAccountOrServer: "이 서버 또는 이 계정에서 채팅은 읽기 전용입니다. 새로 쓰거나 채팅 룸을 만들거나 참가할 수 없습니다."
|
||||
chatNotAvailableInOtherAccount: "상대방 계정에서 채팅 기능을 사용할 수 없는 상태입니다."
|
||||
cannotChatWithTheUser: "이 유저와 채팅을 시작할 수 없습니다"
|
||||
cannotChatWithTheUser_description: "채팅을 사용할 수 없는 상태이거나 상대방이 채팅을 열지 않은 상태입니다."
|
||||
youAreNotAMemberOfThisRoomButInvited: "이 방의 참가자가 아니지만 초대를 받았습니다. 참가하려면 초대를 수락하세요."
|
||||
youAreNotAMemberOfThisRoomButInvited: "당신은 이 룸의 참가자가 아닙니다만 초대 신청을 받으셨습니다. 참가하려면 초대를 수락해주십시오."
|
||||
doYouAcceptInvitation: "초대를 수락하시겠습니까?"
|
||||
chatWithThisUser: "채팅하기"
|
||||
thisUserAllowsChatOnlyFromFollowers: "이 유저는 팔로워만 채팅을 할 수 있습니다."
|
||||
@@ -1560,11 +1558,11 @@ _settings:
|
||||
showSenderName: "발신자 이름 표시"
|
||||
sendOnEnter: "엔터로 보내기"
|
||||
_preferencesProfile:
|
||||
profileName: "프로파일 이름"
|
||||
profileName: "프로필 이름"
|
||||
profileNameDescription: "이 디바이스를 식별할 이름을 설정해 주세요."
|
||||
profileNameDescription2: "예: '메인PC', '스마트폰' 등"
|
||||
manageProfiles: "프로파일 관리"
|
||||
shareSameProfileBetweenDevicesIsNotRecommended: "여러 장치에서 같은 프로파일을 공유하는 것은 권장하지 않습니다."
|
||||
shareSameProfileBetweenDevicesIsNotRecommended: "여러 장치에서 동일한 프로필을 공유하는 것은 권장하지 않습니다."
|
||||
useSyncBetweenDevicesOptionIfYouWantToSyncSetting: "여러 장치에서 동기화하고 싶은 설정 항목이 있는 경우에는 개별로 '여러 장치에서 동기화' 옵션을 활성화해 주십시오."
|
||||
_preferencesBackup:
|
||||
autoBackup: "자동 백업"
|
||||
@@ -1572,7 +1570,7 @@ _preferencesBackup:
|
||||
noBackupsFoundTitle: "백업을 찾을 수 없습니다"
|
||||
noBackupsFoundDescription: "자동으로 생성된 백업은 찾을 수 없었지만, 수동으로 백업 파일을 저장한 경우 해당 파일을 가져와 복원할 수 있습니다."
|
||||
selectBackupToRestore: "복원할 백업을 선택하세요"
|
||||
youNeedToNameYourProfileToEnableAutoBackup: "자동 백업을 활성화하려면 프로파일 이름을 설정해야 합니다."
|
||||
youNeedToNameYourProfileToEnableAutoBackup: "자동 백업을 활성화하려면 프로필 이름을 설정해야 합니다."
|
||||
autoPreferencesBackupIsNotEnabledForThisDevice: "이 장치에서 설정 자동 백업이 활성화되어 있지 않습니다."
|
||||
backupFound: "설정 백업이 발견되었습니다"
|
||||
forceBackup: "설정 강제 백업"
|
||||
@@ -2545,7 +2543,7 @@ _widgets:
|
||||
_userList:
|
||||
chooseList: "리스트 선택"
|
||||
clicker: "클리커"
|
||||
birthdayFollowings: "곧 생일인 사용자"
|
||||
birthdayFollowings: "오늘이 생일인 유저"
|
||||
chat: "채팅하기"
|
||||
_widgetOptions:
|
||||
showHeader: "해더를 표시"
|
||||
@@ -2793,7 +2791,7 @@ _notification:
|
||||
newNote: "새 게시물"
|
||||
unreadAntennaNote: "안테나 {name}"
|
||||
roleAssigned: "역할이 부여 되었습니다."
|
||||
chatRoomInvitationReceived: "채팅방에 초대되었습니다"
|
||||
chatRoomInvitationReceived: "채팅 룸에 초대받았습니다"
|
||||
emptyPushNotificationMessage: "푸시 알림이 갱신되었습니다"
|
||||
achievementEarned: "도전 과제를 달성했습니다"
|
||||
testNotification: "알림 테스트"
|
||||
@@ -2824,7 +2822,7 @@ _notification:
|
||||
receiveFollowRequest: "팔로우 요청을 받았을 때"
|
||||
followRequestAccepted: "팔로우 요청이 승인되었을 때"
|
||||
roleAssigned: "역할이 부여됨"
|
||||
chatRoomInvitationReceived: "채팅방에 초대됨"
|
||||
chatRoomInvitationReceived: "채팅 룸에 초대받음"
|
||||
achievementEarned: "도전 과제 획득"
|
||||
exportCompleted: "추출을 성공함"
|
||||
login: "로그인"
|
||||
@@ -2859,15 +2857,15 @@ _deck:
|
||||
useSimpleUiForNonRootPages: "루트 이외의 페이지로 접속한 경우 UI 간략화하기"
|
||||
usedAsMinWidthWhenFlexible: "'폭 자동 조정'이 활성화된 경우 최소 폭으로 사용됩니다"
|
||||
flexible: "폭 자동 조정"
|
||||
enableSyncBetweenDevicesForProfiles: "프로파일 정보의 장치 간 동기화를 활성화"
|
||||
enableSyncBetweenDevicesForProfiles: "프로파일 정보의 디바이스 간 동기화를 활성화"
|
||||
showHowToUse: "UI 설명 보기"
|
||||
_howToUse:
|
||||
addColumn_title: "칼럼 추가"
|
||||
addColumn_description: "칼럼의 종류를 선택해 추가할 수 있습니다."
|
||||
settings_title: "UI 설정"
|
||||
settings_description: "덱 UI의 상세 설정을 할 수 있습니다."
|
||||
switchProfile_title: "프로파일 전환"
|
||||
switchProfile_description: "UI의 레이아웃을 프로파일로 저장하고 언제든지 전환할 수 있습니다."
|
||||
switchProfile_title: "프로필 전환"
|
||||
switchProfile_description: "UI의 레이아웃을 프로필로 저장하고, 언제나 전환할 수 있습니다."
|
||||
_columns:
|
||||
main: "메인"
|
||||
widgets: "위젯"
|
||||
@@ -2978,7 +2976,7 @@ _moderationLogTypes:
|
||||
deletePage: "페이지를 삭제"
|
||||
deleteFlash: "Play를 삭제"
|
||||
deleteGalleryPost: "갤러리 게시물을 삭제"
|
||||
deleteChatRoom: "채팅방 삭제하기"
|
||||
deleteChatRoom: "채팅 룸 삭제"
|
||||
updateProxyAccountDescription: "프록시 계정의 설명 업데이트"
|
||||
_fileViewer:
|
||||
title: "파일 상세"
|
||||
@@ -3402,9 +3400,11 @@ _imageEffector:
|
||||
threshold: "한계 값"
|
||||
centerX: "X축 중심"
|
||||
centerY: "Y축 중심"
|
||||
density: "밀도"
|
||||
zoomLinesOutlineThickness: "선 그림자의 굵기"
|
||||
zoomLinesSmoothing: "다듬기"
|
||||
zoomLinesSmoothingDescription: "다듬기와 집중선 폭 설정은 같이 쓸 수 없습니다."
|
||||
zoomLinesThreshold: "집중선 폭"
|
||||
zoomLinesMaskSize: "중앙 값"
|
||||
zoomLinesBlack: "검은색으로 하기"
|
||||
circle: "원형"
|
||||
drafts: "초안"
|
||||
_drafts:
|
||||
|
||||
@@ -5,7 +5,6 @@ introMisskey: "ຍິນດີຕ້ອນຮັບ! Misskey ເປັນຊອ
|
||||
poweredByMisskeyDescription: "{name} ແມ່ນສ່ວນໜຶ່ງຂອງການບໍລິການທີ່ຂັບເຄື່ອນໂດຍແພລດຟອມ open source. <b>Misskey</b> (ເອີ້ນວ່າ \"Misskey instance\")"
|
||||
monthAndDay: "ເດືອນ{month} / ວັນ{day}"
|
||||
search: "ຄົ້ນຫາ"
|
||||
reset: "ຣີເຊັດ"
|
||||
notifications: "ການແຈ້ງເຕືອນ"
|
||||
username: "ຊື່ຜູ້ໃຊ້"
|
||||
password: "ລະຫັດຜ່ານ"
|
||||
|
||||
@@ -3289,7 +3289,11 @@ _imageEffector:
|
||||
threshold: "Limiar"
|
||||
centerX: "Centralizar X"
|
||||
centerY: "Centralizar Y"
|
||||
zoomLinesSmoothing: "Suavização"
|
||||
zoomLinesSmoothingDescription: "Suavização e largura das linhas de zoom não podem ser utilizados simultaneamente."
|
||||
zoomLinesThreshold: "Largura das linhas de zoom"
|
||||
zoomLinesMaskSize: "Diâmetro do centro"
|
||||
zoomLinesBlack: "Linhas pretas"
|
||||
circle: "Circular"
|
||||
drafts: "Rascunhos"
|
||||
_drafts:
|
||||
|
||||
@@ -1231,7 +1231,6 @@ showRepliesToOthersInTimelineAll: "Показывать в ленте ответ
|
||||
hideRepliesToOthersInTimelineAll: "Скрывать в ленте ответы пользователей, на которых вы подписаны"
|
||||
confirmShowRepliesAll: "Это нельзя будет отменить. Показать ответы от всех, на кого вы подписаны?"
|
||||
confirmHideRepliesAll: "Это нельзя будет отменить. Скрыть ответы от всех, на кого вы подписаны?"
|
||||
externalServices: "Интеграции"
|
||||
sourceCode: "Исходный код"
|
||||
sourceCodeIsNotYetProvided: "Исходный код пока не доступен. Свяжитесь с администратором, чтобы исправить эту проблему."
|
||||
repositoryUrl: "Ссылка на репозиторий"
|
||||
|
||||
@@ -83,8 +83,6 @@ files: "ไฟล์"
|
||||
download: "ดาวน์โหลด"
|
||||
driveFileDeleteConfirm: "ต้องการลบไฟล์ “{name}” ใช่ไหม? โน้ตที่แนบมากับไฟล์นี้ก็จะถูกลบไปด้วย"
|
||||
unfollowConfirm: "ต้องการเลิกติดตาม {name} ใช่ไหม?"
|
||||
cancelFollowRequestConfirm: "ยกเลิกคำขอติดตาม {name} ใช่ไหม?"
|
||||
rejectFollowRequestConfirm: "ปฏิเสธคำขอติดตามจาก {name} ใช่ไหม?"
|
||||
exportRequested: "คุณได้ร้องขอการส่งออก อาจใช้เวลาสักครู่ และจะถูกเพิ่มในไดรฟ์ของคุณเมื่อเสร็จสิ้นแล้ว"
|
||||
importRequested: "คุณได้ร้องขอการนำเข้า การดำเนินการนี้อาจใช้เวลาสักครู่"
|
||||
lists: "รายชื่อ"
|
||||
@@ -206,7 +204,7 @@ host: "โฮสต์"
|
||||
selectSelf: "เลือกตัวเอง"
|
||||
selectUser: "เลือกผู้ใช้งาน"
|
||||
recipient: "ผู้รับ"
|
||||
annotation: "ข้อความเกริ่น"
|
||||
annotation: "หมายเหตุประกอบ"
|
||||
federation: "สหพันธ์"
|
||||
instances: "เซิร์ฟเวอร์"
|
||||
registeredAt: "วันที่ลงทะเบียน"
|
||||
@@ -224,7 +222,7 @@ operations: "ดำเนินการ"
|
||||
software: "ซอฟต์แวร์"
|
||||
softwareName: "ชื่อซอฟต์แวร์"
|
||||
version: "เวอร์ชั่น"
|
||||
metadata: "เมทาเดต้า"
|
||||
metadata: "Metadata"
|
||||
withNFiles: "{n} ไฟล์"
|
||||
monitor: "มอนิเตอร์"
|
||||
jobQueue: "คิวงาน"
|
||||
@@ -304,7 +302,6 @@ uploadFromUrlMayTakeTime: "การอัปโหลดอาจใช้เ
|
||||
uploadNFiles: "อัปโหลด {n} ไฟล์"
|
||||
explore: "สำรวจ"
|
||||
messageRead: "อ่านแล้ว"
|
||||
readAllChatMessages: "ทำเครื่องหมายใส่ข้อความทั้งหมดว่าอ่านแล้ว"
|
||||
noMoreHistory: "ไม่มีประวัติเพิ่มเติม"
|
||||
startChat: "เริ่มแชต"
|
||||
nUsersRead: "อ่านโดย {n}"
|
||||
@@ -337,7 +334,6 @@ fileName: "ชื่อไฟล์"
|
||||
selectFile: "เลือกไฟล์"
|
||||
selectFiles: "เลือกไฟล์"
|
||||
selectFolder: "เลือกโฟลเดอร์"
|
||||
unselectFolder: "ยกเลิกการเลือกโฟลเดอร์"
|
||||
selectFolders: "เลือกโฟลเดอร์"
|
||||
fileNotSelected: "ยังไม่ได้เลือกไฟล์"
|
||||
renameFile: "เปลี่ยนชื่อไฟล์"
|
||||
@@ -350,7 +346,6 @@ addFile: "เพิ่มไฟล์"
|
||||
showFile: "แสดงไฟล์"
|
||||
emptyDrive: "ไดรฟ์ของคุณว่างเปล่านะ"
|
||||
emptyFolder: "โฟลเดอร์นี้ว่างเปล่า"
|
||||
dropHereToUpload: "ดรอปไฟล์ลงที่นี่เพื่ออัปโหลด"
|
||||
unableToDelete: "ไม่สามารถลบออกได้"
|
||||
inputNewFileName: "ป้อนชื่อไฟล์ใหม่"
|
||||
inputNewDescription: "กรุณาใส่แคปชั่นใหม่"
|
||||
@@ -433,7 +428,7 @@ antennaKeywordsDescription: "คั่นด้วยเว้นวรรคส
|
||||
notifyAntenna: "แจ้งเตือนเกี่ยวกับโน้ตใหม่"
|
||||
withFileAntenna: "เฉพาะโน้ตที่มีไฟล์"
|
||||
excludeNotesInSensitiveChannel: "ไม่รวมโน้ตจากช่องเนื้อหาละเอียดอ่อน"
|
||||
enableServiceworker: "เปิดใช้งานการแจ้งเตือนแบบพุชไปยังเบราว์เซอร์"
|
||||
enableServiceworker: "เปิดใช้งานการแจ้งเตือนแบบพุชไปยังเบราว์เซอร์ของคุณ"
|
||||
antennaUsersDescription: "ระบุหนึ่งชื่อผู้ใช้ต่อบรรทัด"
|
||||
caseSensitive: "อักษรพิมพ์ใหญ่-พิมพ์เล็กความหมายต่างกัน"
|
||||
withReplies: "รวมตอบกลับ"
|
||||
@@ -543,7 +538,6 @@ regenerate: "สร้างอีกครั้ง"
|
||||
fontSize: "ขนาดตัวอักษร"
|
||||
mediaListWithOneImageAppearance: "ความสูงของรายการสื่อที่มีเพียงรูปเดียว"
|
||||
limitTo: "จำกัดไว้ที่ {x}"
|
||||
showMediaListByGridInWideArea: "เมื่อหน้าจอกว้างยาวขึ้น ให้เรียงรายการสื่อเป็นแนวนอน"
|
||||
noFollowRequests: "คุณไม่มีคำขอติดตามที่รอดำเนินการ"
|
||||
openImageInNewTab: "เปิดรูปภาพในแท็บใหม่"
|
||||
dashboard: "หน้ากระดานหลัก"
|
||||
@@ -618,7 +612,7 @@ uiInspectorDescription: "คุณสามารถตรวจสอบรา
|
||||
output: "เอาท์พุต"
|
||||
script: "สคริปต์"
|
||||
disablePagesScript: "ปิดการใช้งาน AiScript บนเพจ"
|
||||
updateRemoteUser: "อัปเดตข้อมูลผู้ใช้ระยะไกล"
|
||||
updateRemoteUser: "อัปเดตข้อมูลผู้ใช้งานระยะไกล"
|
||||
unsetUserAvatar: "เลิกตั้งไอคอน"
|
||||
unsetUserAvatarConfirm: "ต้องการเลิกตั้งไอคอนประจำตัวหรือไม่?"
|
||||
unsetUserBanner: "เลิกตั้งแบนเนอร์"
|
||||
@@ -779,7 +773,6 @@ lockedAccountInfo: "แม้ว่าการอนุมัติการต
|
||||
alwaysMarkSensitive: "ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อนเป็นค่าเริ่มต้น"
|
||||
loadRawImages: "โหลดภาพต้นฉบับแทนการแสดงภาพขนาดย่อ"
|
||||
disableShowingAnimatedImages: "ไม่ต้องเล่นภาพเคลื่อนไหว"
|
||||
disableShowingAnimatedImages_caption: "หากภาพเคลื่อนไหวไม่เล่นแม่จะปิดตั้งค่านี้ไปแล้ว อาจเป็นกรณีที่การตั้งค่าการช่วยการเข้าถึงหรือการประหยัดพลังงาน ของเบราว์เซอร์/OS เข้าแทรกแซง"
|
||||
highlightSensitiveMedia: "ไฮไลท์สื่อที่มีเนื้อหาละเอียดอ่อน"
|
||||
verificationEmailSent: "ได้ส่งอีเมลยืนยันแล้ว กรุณาเข้าลิงก์ที่ระบุในอีเมลเพื่อทำการตั้งค่าให้เสร็จสิ้น"
|
||||
notSet: "ไม่ได้ตั้งค่า"
|
||||
@@ -894,7 +887,7 @@ low: "ต่ำ"
|
||||
emailNotConfiguredWarning: "ยังไม่ได้ตั้งค่าที่อยู่อีเมล"
|
||||
ratio: "อัตราส่วน"
|
||||
previewNoteText: "แสดงตัวอย่าง"
|
||||
customCss: "CSS แบบกำหนดเอง"
|
||||
customCss: "CSS ที่กำหนดเอง"
|
||||
customCssWarn: "ควรใช้การตั้งค่านี้เฉพาะต่อเมื่อคุณรู้มันใช้ทำอะไร การตั้งค่าที่ไม่เหมาะสมอาจทำให้ไคลเอ็นต์ไม่สามารถใช้งานได้อย่างถูกต้อง"
|
||||
global: "ทั่วโลก"
|
||||
squareAvatars: "แสดงไอคอนประจำตัวเป็นสี่เหลี่ยม"
|
||||
@@ -937,7 +930,7 @@ unmuteThread: "เลิกปิดเสียงเธรด"
|
||||
followingVisibility: "การมองเห็นที่เรากำลังติดตาม"
|
||||
followersVisibility: "การมองเห็นผู้ที่กำลังติดตามเรา"
|
||||
continueThread: "ดูความต่อเนื่องเธรด"
|
||||
deleteAccountConfirm: "บัญชีจะถูกลบ ดำเนินการต่อใช่ไหม?"
|
||||
deleteAccountConfirm: "การดำเนินการนี้จะลบบัญชีของคุณอย่างถาวรเลยนะ แน่ใจหรอดำเนินการ?"
|
||||
incorrectPassword: "รหัสผ่านไม่ถูกต้อง"
|
||||
incorrectTotp: "รหัสยืนยันตัวตนแบบใช้ครั้งเดียวที่ท่านได้ระบุมานั้น ไม่ถูกต้องหรือหมดอายุลงแล้วค่ะ"
|
||||
voteConfirm: "ต้องการโหวต “{choice}” ใช่ไหม?"
|
||||
@@ -998,7 +991,7 @@ pleaseSelect: "ตัวเลือก"
|
||||
reverse: "พลิก"
|
||||
colored: "สี"
|
||||
refreshInterval: "ความถี่ในการอัปเดต"
|
||||
label: "ป้าย"
|
||||
label: "ป้ายชื่อ"
|
||||
type: "รูปแบบ"
|
||||
speed: "ความเร็ว"
|
||||
slow: "ช้า"
|
||||
@@ -1026,9 +1019,6 @@ pushNotificationAlreadySubscribed: "การแจ้งเตือนแบ
|
||||
pushNotificationNotSupported: "เบราว์เซอร์หรือเซิร์ฟเวอร์ไม่รองรับการแจ้งเตือนแบบพุช"
|
||||
sendPushNotificationReadMessage: "ลบการแจ้งเตือนแบบพุชเมื่ออ่านการแจ้งเตือนหรือข้อความที่เกี่ยวข้องแล้ว"
|
||||
sendPushNotificationReadMessageCaption: "อาจทำให้อุปกรณ์ของคุณใช้พลังงานมากขึ้น"
|
||||
pleaseAllowPushNotification: "โปรดอนุญาตการตั้งค่าการแจ้งเตือนของเบราว์เซอร์"
|
||||
browserPushNotificationDisabled: "ขอสิทธิ์ส่งการแจ้งเตือนล้มเหลว"
|
||||
browserPushNotificationDisabledDescription: "ไม่มีสิทธิ์ในการส่งการแจ้งเตือนจาก {serverName} โปรดอนุญาตการแจ้งเตือนในตั้งค่าของเบราว์เซอร์ แล้วลองอีกครั้ง"
|
||||
windowMaximize: "ขยายใหญ่สุด"
|
||||
windowMinimize: "ย่อเล็กที่สุด"
|
||||
windowRestore: "เลิกทำ"
|
||||
@@ -1109,8 +1099,8 @@ license: "ใบอนุญาต"
|
||||
unfavoriteConfirm: "ลบออกจากรายการโปรดแน่ใจหรอ?"
|
||||
myClips: "คลิปของฉัน"
|
||||
drivecleaner: "ทำความสะอาดไดรฟ์"
|
||||
retryAllQueuesNow: "ลองใหม่ทุกคิวทันที"
|
||||
retryAllQueuesConfirmTitle: "ลองใหม่ทันทีเลยไหม?"
|
||||
retryAllQueuesNow: "ลองเรียกใช้คิวทั้งหมดอีกครั้ง"
|
||||
retryAllQueuesConfirmTitle: "ลองใหม่ทั้งหมดจริงๆหรอแน่ใจนะ?"
|
||||
retryAllQueuesConfirmText: "สิ่งนี้จะเพิ่มการโหลดเซิร์ฟเวอร์ชั่วคราวนะ"
|
||||
enableChartsForRemoteUser: "สร้างแผนภูมิข้อมูลผู้ใช้ระยะไกล"
|
||||
enableChartsForFederatedInstances: "สร้างแผนภูมิของเซิร์ฟเวอร์ระยะไกล"
|
||||
@@ -1160,7 +1150,7 @@ initialAccountSetting: "ตั้งค่าโปรไฟล์"
|
||||
youFollowing: "ติดตามแล้ว"
|
||||
preventAiLearning: "ปฏิเสธการเรียนรู้ด้วย generative AI"
|
||||
preventAiLearningDescription: "ส่งคำร้องขอไม่ให้ใช้ ข้อความในโน้ตที่โพสต์, หรือเนื้อหารูปภาพ ฯลฯ ในการเรียนรู้ของเครื่อง(machine learning) / Predictive AI / Generative AI โดยการเพิ่มแฟล็ก “noai” ลง HTML-Response ให้กับเนื้อหาที่เกี่ยวข้อง แต่ทั้งนี้ ไม่ได้ป้องกัน AI จากการเรียนรู้ได้อย่างสมบูรณ์ เนื่องจากมี AI บางตัวเท่านั้นที่จะเคารพคำขอดังกล่าว"
|
||||
options: "ตัวเลือก"
|
||||
options: "ตัวเลือกบทบาท"
|
||||
specifyUser: "ผู้ใช้เฉพาะ"
|
||||
lookupConfirm: "ต้องการเรียกดูข้อมูลใช่ไหม?"
|
||||
openTagPageConfirm: "ต้องการเปิดหน้าแฮชแท็กใช่ไหม?"
|
||||
@@ -1179,7 +1169,6 @@ installed: "ติดตั้งแล้ว"
|
||||
branding: "แบรนดิ้ง"
|
||||
enableServerMachineStats: "เผยแพร่สถานะฮาร์ดแวร์ของเซิร์ฟเวอร์"
|
||||
enableIdenticonGeneration: "เปิดใช้งานผู้ใช้สร้างตัวระบุ"
|
||||
showRoleBadgesOfRemoteUsers: "แสดงตราบทบาทที่มอบให้กับผู้ใช้ระยะไกล"
|
||||
turnOffToImprovePerformance: "การปิดส่วนนี้สามารถเพิ่มประสิทธิภาพได้"
|
||||
createInviteCode: "สร้างรหัสเชิญ"
|
||||
createWithOptions: "สร้างด้วยตัวเลือก"
|
||||
@@ -1258,7 +1247,7 @@ refreshing: "กำลังรีเฟรช..."
|
||||
pullDownToRefresh: "ดึงลงเพื่อรีเฟรช"
|
||||
useGroupedNotifications: "แสดงผลการแจ้งเตือนแบบกลุ่มแล้ว"
|
||||
emailVerificationFailedError: "เกิดปัญหาในขณะตรวจสอบอีเมล อาจเป็นไปได้ว่าลิงก์หมดอายุแล้ว"
|
||||
cwNotationRequired: "หากเปิดใช้งาน “ซ่อนเนื้อหา” จะต้องระบุข้อความเกริ่น"
|
||||
cwNotationRequired: "หากเปิดใช้งาน “ซ่อนเนื้อหา” จะต้องระบุคำอธิบาย"
|
||||
doReaction: "เพิ่มรีแอคชั่น"
|
||||
code: "โค้ด"
|
||||
reloadRequiredToApplySettings: "จำเป็นต้องมีการโหลดซ้ำเพื่อให้การตั้งค่ามีผล"
|
||||
@@ -1362,7 +1351,7 @@ migrateOldSettings: "ย้ายข้อมูลการตั้งค่
|
||||
migrateOldSettings_description: "โดยปกติจะทำโดยอัตโนมัติ แต่หากด้วยเหตุผลบางประการที่ไม่สามารถย้ายได้สำเร็จ สามารถสั่งย้ายด้วยตนเองได้ การตั้งค่าปัจจุบันจะถูกเขียนทับ"
|
||||
compress: "บีบอัด"
|
||||
right: "ขวา"
|
||||
bottom: "ล่าง"
|
||||
bottom: "ภายใต้"
|
||||
top: "บน"
|
||||
embed: "ฝัง"
|
||||
settingsMigrating: "กำลังย้ายการตั้งค่า กรุณารอสักครู่... (สามารถย้ายด้วยตนเองภายหลังได้ที่ การตั้งค่า → อื่นๆ → ย้ายข้อมูลการตั้งค่าเก่า)"
|
||||
@@ -1401,53 +1390,17 @@ scheduledToPostOnX: "มีการกำหนดเวลาให้โพ
|
||||
schedule: "กำหนดเวลา"
|
||||
scheduled: "กำหนดเวลา"
|
||||
widgets: "วิดเจ็ต"
|
||||
deviceInfo: "รายละเอียดอุปกรณ์"
|
||||
deviceInfoDescription: "เมื่อต้องการรับความช่วยเหลือทางเทคนิค กรุณาระบุข้อมูลต่อไปนี้ซึ่งอาจช่วยแก้ไขปัญหาได้"
|
||||
youAreAdmin: "คุณคือผู้ดูแลระบบ"
|
||||
frame: "เฟรม"
|
||||
presets: "พรีเซ็ต"
|
||||
zeroPadding: "ห่างเป็น 0"
|
||||
nothingToConfigure: "ไม่มีอะไรให้ต้ังค่า"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
caption: "แคปชั่นของไฟล์"
|
||||
filename: "ชื่อไฟล์"
|
||||
filename_without_ext: "ชื่อไฟล์ที่ไม่มีนามสกุล"
|
||||
year: "ปีที่ถ่าย"
|
||||
month: "เดือนที่ถ่าย"
|
||||
day: "วันที่ถ่าย"
|
||||
hour: "เวลาที่ถ่าย (ชั่วโมง)"
|
||||
minute: "เวลาที่ถ่าย (นาที)"
|
||||
second: "เวลาที่ถ่าย (วินาที)"
|
||||
camera_model: "ชื่อกล้อง"
|
||||
camera_lens_model: "ชื่อเลนส์"
|
||||
camera_mm: "ความยาวโฟกัส"
|
||||
camera_mm_35: "ทางยาวโฟกัส (เทียบเท่า 35 มม.)"
|
||||
camera_f: "รูรับแสง"
|
||||
camera_s: "ความเร็วชัตเตอร์"
|
||||
camera_iso: "ความไวแสง ISO"
|
||||
gps_lat: "ละติจูด"
|
||||
gps_long: "ลองจิจูด"
|
||||
_imageFrameEditor:
|
||||
title: "แก้ไขเฟรม"
|
||||
tip: "สามารถตกแต่งภาพโดยการเพิ่มป้ายที่มีเฟรมหรือเมทาเดต้าได้"
|
||||
header: "ส่วนหัว"
|
||||
footer: "ท้ายกระดาษ"
|
||||
borderThickness: "ความกว้างขอบ"
|
||||
labelThickness: "ความกว้างป้าย"
|
||||
labelScale: "สเกลของป้าย"
|
||||
centered: "จัดกึ่งกลาง"
|
||||
captionMain: "แคปชั่น (ใหญ่)"
|
||||
captionSub: "แคปชั่น (เล็ก)"
|
||||
availableVariables: "ตัวแปรที่สามารถใช้ได้"
|
||||
withQrCode: "QR โค้ด"
|
||||
backgroundColor: "สีพื้นหลัง"
|
||||
textColor: "สีตัวอักษร"
|
||||
font: "แบบอักษร"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
quitWithoutSaveConfirm: "ต้องการออกโดยไม่บันทึกหรือไม่?"
|
||||
failedToLoadImage: "โหลดภาพล้มเหลว"
|
||||
_compression:
|
||||
_quality:
|
||||
high: "คุณภาพสูง"
|
||||
@@ -1550,11 +1503,6 @@ _settings:
|
||||
showUrlPreview: "แสดงตัวอย่าง URL"
|
||||
showAvailableReactionsFirstInNote: "แสดงรีแอคชั่นที่ใช้ได้ไว้หน้าสุด"
|
||||
showPageTabBarBottom: "แสดงแท็บบาร์ของเพจที่ด้านล่าง"
|
||||
emojiPaletteBanner: "สามารถบันทึกพรีเซ็ตเป็นจานสีเพื่อตรึงไว้ในตัวจิ้มเอโมจิ หรือปรับแต่งวิธีการแสดงผลของตัวจิ้มเอโมจิได้"
|
||||
enableAnimatedImages: "เปิดใช้งานภาพเคลื่อนไหว"
|
||||
settingsPersistence_title: "คงสภาพการตั้งค่า"
|
||||
settingsPersistence_description1: "เมื่อเปิดใช้งานการคงสภาพการตั้งค่า จะช่วยป้องกันไม่ให้ข้อมูลการตั้งค่าสูญหายได้"
|
||||
settingsPersistence_description2: "แต่ในบางสภาพแวดล้อม อาจไม่สามารถเปิดใช้งานได้"
|
||||
_chat:
|
||||
showSenderName: "แสดงชื่อผู้ส่ง"
|
||||
sendOnEnter: "กด Enter เพื่อส่ง"
|
||||
@@ -1563,8 +1511,6 @@ _preferencesProfile:
|
||||
profileNameDescription: "กรุณาตั้งชื่อเพื่อระบุอุปกรณ์นี้"
|
||||
profileNameDescription2: "เช่น: “คอมเครื่องหลัก”, “มือถือ” ฯลฯ"
|
||||
manageProfiles: "จัดการโปรไฟล์"
|
||||
shareSameProfileBetweenDevicesIsNotRecommended: "ไม่แนะนำให้ใช้โปรไฟล์เดียวกันร่วมกันบนหลายอุปกรณ์"
|
||||
useSyncBetweenDevicesOptionIfYouWantToSyncSetting: "หากมีรายการตั้งค่าที่ต้องการซิงก์ระหว่างหลายอุปกรณ์ โปรดเปิดใช้งานตัวเลือก “ซิงก์ระหว่างหลายอุปกรณ์” ในอุปกรณ์นั้นๆ ด้วย"
|
||||
_preferencesBackup:
|
||||
autoBackup: "สำรองโดยอัตโนมัติ"
|
||||
restoreFromBackup: "คืนค่าจากข้อมูลสำรอง"
|
||||
@@ -1572,9 +1518,8 @@ _preferencesBackup:
|
||||
noBackupsFoundDescription: "ไม่พบข้อมูลสำรองที่สร้างโดยอัตโนมัติ แต่หากมีข้อมูลสำรองที่บันทึกด้วยตนเอง สามารถนำเข้ามาเพื่อกู้คืนได้"
|
||||
selectBackupToRestore: "กรุณาเลือกข้อมูลสำรองที่ต้องการกู้คืน"
|
||||
youNeedToNameYourProfileToEnableAutoBackup: "จำเป็นต้องตั้งชื่อโปรไฟล์ก่อนจึงจะเปิดใช้งานการสำรองข้อมูลอัตโนมัติได้"
|
||||
autoPreferencesBackupIsNotEnabledForThisDevice: "ยังไม่ได้เปิดใช้งานการสำรองการตั้งค่าแบบอัตโนมัติบนอุปกรณ์นี้"
|
||||
autoPreferencesBackupIsNotEnabledForThisDevice: "ยังไม่ได้เปิดใช้งานการสำรองข้อมูลอัตโนมัติบนอุปกรณ์นี้"
|
||||
backupFound: "พบข้อมูลสำรองของการตั้งค่าแล้ว"
|
||||
forceBackup: "บังคับสำรองการตั้งค่า"
|
||||
_accountSettings:
|
||||
requireSigninToViewContents: "ต้องเข้าสู่ระบบเพื่อดูเนื้อหา"
|
||||
requireSigninToViewContentsDescription1: "กำหนดให้ต้องเข้าสู่ระบบก่อนจึงจะสามารถดูโน้ตหรือเนื้อหาทั้งหมดที่สร้างไว้ได้ ซึ่งช่วยป้องกันไม่ให้ข้อมูลถูกเก็บโดยบอตหรือ Crawler (โปรแกรมรวบรวมข้อมูล)"
|
||||
@@ -1642,7 +1587,7 @@ _initialAccountSetting:
|
||||
theseSettingsCanEditLater: "คุณสามารถเปลี่ยนการตั้งค่าเหล่านี้ได้ในภายหลังได้ตลอดเวลานะ"
|
||||
youCanEditMoreSettingsInSettingsPageLater: "สามารถตั้งค่าเพิ่มเติมได้ที่หน้า “การตั้งค่า” อย่าลืมไปเยี่ยมชมภายหลังด้วย"
|
||||
followUsers: "ลองติดตามผู้ใช้ที่สนใจเพื่อสร้างไทม์ไลน์ดูสิ"
|
||||
pushNotificationDescription: "เมื่อเปิดใช้งานการแจ้งเตือนแบบพุช จะสามารถรับการแจ้งเตือนจาก {name} บนอุปกรณ์ที่ใช้งานอยู่ได้"
|
||||
pushNotificationDescription: "กำลังเปิดใช้งานการแจ้งเตือนแบบพุชจะช่วยให้คุณได้รับการแจ้งเตือนจาก {name} โดยตรงบนอุปกรณ์ของคุณนะ"
|
||||
initialAccountSettingCompleted: "ตั้งค่าโปรไฟล์เสร็จสมบูรณ์แล้ว!"
|
||||
haveFun: "ขอให้สนุกกับ {name}!"
|
||||
youCanContinueTutorial: "คุณสามารถดำเนินการต่อด้วยบทช่วยสอนเกี่ยวกับวิธีใช้ {name} (Misskey) หรือออกจากบทช่วยสอนแล้วเริ่มใช้งานได้ทันที"
|
||||
@@ -1694,7 +1639,7 @@ _initialTutorial:
|
||||
localOnly: "การโพสต์ด้วย flag นี้จะไม่รวมโน้ตไปยังเซิร์ฟเวอร์อื่น ผู้ใช้บนเซิร์ฟเวอร์อื่นจะไม่สามารถดูโน้ตเหล่านี้ได้โดยตรง โดยไม่คำนึงถึงการตั้งค่าการแสดงผลข้างต้น"
|
||||
_cw:
|
||||
title: "คำเตือนเกี่ยวกับเนื้อหา"
|
||||
description: "เนื้อหาที่เขียนใน “ข้อความเกริ่น” จะแสดงแทนเนื้อหาหลัก ต้องกด “ดูเพิ่มเติม” เพื่อให้เนื้อหาหลักแสดง"
|
||||
description: "เนื้อหาที่เขียนใน “คำอธิบายประกอบ” จะแสดงแทนเนื้อหาหลัก ต้องคลิก “ดูเพิ่มเติม” เพื่อให้เนื้อหาหลักแสดง"
|
||||
_exampleNote:
|
||||
cw: " ห้ามดู ระวังหิว"
|
||||
note: "เพิ่งไปกินโดนัทเคลือบช็อคโกแลตมา 🍩😋"
|
||||
@@ -2046,7 +1991,7 @@ _role:
|
||||
isConditionalRole: "นี่คือบทบาทที่มีเงื่อนไข"
|
||||
isPublic: "ทำให้บทบาทเปิดเผยต่อสาธารณะ"
|
||||
descriptionOfIsPublic: "บทบาทจะปรากฏบนโปรไฟล์ของผู้ใช้และเปิดเผยต่อสาธารณะ (ทุกคนสามารถเห็นได้ว่าผู้ใช้รายนี้มีบทบาทนี้)"
|
||||
options: "ตัวเลือก"
|
||||
options: "ตัวเลือกบทบาท"
|
||||
policies: "นโยบาย"
|
||||
baseRole: "แม่แบบบทบาท"
|
||||
useBaseValue: "ใช้ตามแม่แบบบทบาท"
|
||||
@@ -2080,7 +2025,6 @@ _role:
|
||||
canManageAvatarDecorations: "จัดการตกแต่งอวตาร"
|
||||
driveCapacity: "ความจุของไดรฟ์"
|
||||
maxFileSize: "ขนาดไฟล์สูงสุดที่สามารถอัปโหลดได้"
|
||||
maxFileSize_caption: "รีเวิร์สพร็อกซี, CDN และคอมโพเนนต์หน้าบ้านอื่นๆ อาจมีค่าการตั้งค่าของตนเอง"
|
||||
alwaysMarkNsfw: "ทำเครื่องหมายไฟล์ว่าเป็น NSFW เสมอ"
|
||||
canUpdateBioMedia: "อนุญาตให้เปลี่ยนไอคอนประจำตัวและแบนเนอร์"
|
||||
pinMax: "จํานวนสูงสุดของโน้ตที่ปักหมุดไว้"
|
||||
@@ -2442,7 +2386,7 @@ _permissions:
|
||||
"read:admin:index-stats": "ดูข้อมูลเกี่ยวกับดัชนีฐานข้อมูล"
|
||||
"read:admin:table-stats": "ดูข้อมูลเกี่ยวกับตารางในฐานข้อมูล"
|
||||
"read:admin:user-ips": "ดูที่อยู่ IP ของผู้ใช้"
|
||||
"read:admin:meta": "ดูเมทาเดต้าของอินสแตนซ์"
|
||||
"read:admin:meta": "ดูข้อมูลอภิพันธุ์ของอินสแตนซ์"
|
||||
"write:admin:reset-password": "รีเซ็ตรหัสผ่านของผู้ใช้"
|
||||
"write:admin:resolve-abuse-user-report": "แก้ไขรายงานจากผู้ใช้"
|
||||
"write:admin:send-email": "ส่งอีเมล"
|
||||
@@ -2453,7 +2397,7 @@ _permissions:
|
||||
"write:admin:unset-user-avatar": "ลบอวตารผู้ใช้"
|
||||
"write:admin:unset-user-banner": "ลบแบนเนอร์ผู้ใช้"
|
||||
"write:admin:unsuspend-user": "ยกเลิกการระงับผู้ใช้"
|
||||
"write:admin:meta": "จัดการเมทาเดต้าของอินสแตนซ์"
|
||||
"write:admin:meta": "จัดการข้อมูลอภิพันธุ์ของอินสแตนซ์"
|
||||
"write:admin:user-note": "จัดการโน้ตการกลั่นกรอง"
|
||||
"write:admin:roles": "จัดการบทบาท"
|
||||
"read:admin:roles": "ดูบทบาท"
|
||||
@@ -2499,7 +2443,6 @@ _auth:
|
||||
scopeUser: "กำลังดำเนินการในฐานะผู้ใช้ต่อไปนี้"
|
||||
pleaseLogin: "กรุณาเข้าสู่ระบบเพื่ออนุมัติแอปพลิเคชัน"
|
||||
byClickingYouWillBeRedirectedToThisUrl: "หากอนุญาตการเข้าถึง ระบบจะเปลี่ยนเส้นทางไปยัง URL ด้านล่างโดยอัตโนมัติ"
|
||||
alreadyAuthorized: "แอปพลิเคชันนี้ได้รับอนุญาตให้เข้าถึงแล้ว"
|
||||
_antennaSources:
|
||||
all: "โน้ตทั้งหมด"
|
||||
homeTimeline: "โน้ตจากผู้ใช้ที่ติดตาม"
|
||||
@@ -2548,40 +2491,11 @@ _widgets:
|
||||
chat: "แชตเลย"
|
||||
_widgetOptions:
|
||||
showHeader: "แสดงส่วนหัว"
|
||||
transparent: "ทำพื้นหลังโปรงใส"
|
||||
height: "ความสูง"
|
||||
_button:
|
||||
colored: "สี"
|
||||
_clock:
|
||||
size: "ขนาด"
|
||||
thickness: "ความหนาเข็ม"
|
||||
thicknessThin: "บาง"
|
||||
thicknessMedium: "ปานกลาง"
|
||||
thicknessThick: "หนา"
|
||||
graduations: "ขีดบอกค่าบนหน้าปัด"
|
||||
graduationDots: "จุด"
|
||||
graduationArabic: "เลขอารบิก"
|
||||
fadeGraduations: "เฟดหน้าปัด"
|
||||
sAnimation: "การเคลื่อนไหวของเข็มวินาที"
|
||||
sAnimationElastic: "สมจริง"
|
||||
sAnimationEaseOut: "ลื่นๆ"
|
||||
twentyFour: "ระบบ 24 ชั่วโมง"
|
||||
labelTime: "เวลา"
|
||||
labelTz: "เขตเวลา"
|
||||
labelTimeAndTz: "เวลาและเขตเวลา"
|
||||
timezone: "เขตเวลา"
|
||||
showMs: "แสดงมิลลิวินาที"
|
||||
showLabel: "แสดงป้าย"
|
||||
_jobQueue:
|
||||
sound: "เล่นเสียง"
|
||||
_rss:
|
||||
url: "URL ของฟีด RSS"
|
||||
refreshIntervalSec: "ห้วงอัปเดต (วินาที)"
|
||||
maxEntries: "จำนวนที่แสดงได้สูงสุด"
|
||||
_rssTicker:
|
||||
shuffle: "สุ่มลำดับ"
|
||||
duration: "ความเร็วทิกเกอร์ (วินาที)"
|
||||
reverse: "วิ่งไปอีกทาง"
|
||||
_birthdayFollowings:
|
||||
period: "ระยะเวลา"
|
||||
_cw:
|
||||
@@ -2628,20 +2542,9 @@ _postForm:
|
||||
replyPlaceholder: "ตอบกลับโน้ตนี้..."
|
||||
quotePlaceholder: "อ้างโน้ตนี้..."
|
||||
channelPlaceholder: "โพสต์ลงช่อง..."
|
||||
showHowToUse: "แสดงวิธีใช้ฟอร์ม"
|
||||
_howToUse:
|
||||
content_title: "เนื้อความ"
|
||||
content_description: "ป้อนเนื้อหาที่จะโพสต์"
|
||||
toolbar_title: "แถบเครื่องมือ"
|
||||
toolbar_description: "สามารถแนบไฟล์หรือแบบสอบถาม ตั้งข้อความเกริ่นหรือแฮชแท็ก แทรกเอโมจิหรือการกล่าวถึง เป็นต้น"
|
||||
account_title: "เมนูบัญชี"
|
||||
account_description: "สามารถสลับบัญชีที่ใช้โพสต์ หรือดูรายการฉบับร่างและโพสต์กำหนดเวลาไว้ซึ่งบันทึกไว้ในบัญชีได้"
|
||||
visibility_title: "การมองเห็น"
|
||||
visibility_description: "สามารถตั้งค่าขอบเขตการเผยแพร่โน้ตได้"
|
||||
menu_title: "เมนู"
|
||||
menu_description: "สามารถบันทึกเป็นฉบับร่าง ตั้งเวลาการโพสต์ ตั้งค่ารีแอคชั่น และดำเนินการอื่นๆ ได้"
|
||||
submit_title: "ปุ่มโพสต์"
|
||||
submit_description: "กดปุ่มนั้นเพื่อโพสต์โน้ต หรือกด Ctrl + Enter / Cmd + Return เพื่อโพสต์ก็ได้เช่นกัน"
|
||||
_placeholders:
|
||||
a: "ตอนนี้เป็นยังไงบ้าง?"
|
||||
b: "มีอะไรเกิดขึ้นหรือเปล่า?"
|
||||
@@ -2657,7 +2560,7 @@ _profile:
|
||||
metadata: "ข้อมูลเพิ่มเติม"
|
||||
metadataEdit: "แก้ไขข้อมูลเพิ่มเติม"
|
||||
metadataDescription: "ใช้สิ่งเหล่านี้ คุณสามารถแสดงฟิลด์ข้อมูลเพิ่มเติมในโปรไฟล์ของคุณ"
|
||||
metadataLabel: "ป้าย"
|
||||
metadataLabel: "ป้ายชื่อ"
|
||||
metadataContent: "เนื้อหา"
|
||||
changeAvatar: "เปลี่ยนไอคอนประจำตัว"
|
||||
changeBanner: "เปลี่ยนแบนเนอร์"
|
||||
@@ -2818,8 +2721,6 @@ _notification:
|
||||
quote: "อ้างอิง"
|
||||
reaction: "รีแอคชั่น"
|
||||
pollEnded: "โพลสิ้นสุดแล้ว"
|
||||
scheduledNotePosted: "โพสต์กำหนดเวลาสำเร็จ"
|
||||
scheduledNotePostFailed: "โพสต์กำหนดเวลาล้มเหลว"
|
||||
receiveFollowRequest: "ได้รับคำร้องขอติดตาม"
|
||||
followRequestAccepted: "อนุมัติให้ติดตามแล้ว"
|
||||
roleAssigned: "ให้บทบาท"
|
||||
@@ -2859,14 +2760,6 @@ _deck:
|
||||
usedAsMinWidthWhenFlexible: "ความกว้างขั้นต่ำนั้นจะถูกใช้งานสำหรับสิ่งนี้เมื่อเปิดใช้งานตัวเลือก \"ปรับความกว้างอัตโนมัติ\" หากเลือกเปิดใช้งานแล้ว"
|
||||
flexible: "ปรับความกว้างอัตโนมัติ"
|
||||
enableSyncBetweenDevicesForProfiles: "เปิดใช้งานการซิงค์ข้อมูลโปรไฟล์ระหว่างอุปกรณ์"
|
||||
showHowToUse: "แสดงวิธีใช้ UI"
|
||||
_howToUse:
|
||||
addColumn_title: "เพิ่มคอลัมน์"
|
||||
addColumn_description: "สามารถเลือกประเภทของคอลัมน์แล้วเพิ่มได้"
|
||||
settings_title: "ตั้งค่า UI"
|
||||
settings_description: "สามารถตั้งค่ารายละเอียดของ UI แบบเด็คได้"
|
||||
switchProfile_title: "สลับโปรไฟล์"
|
||||
switchProfile_description: "สามารถบันทึกเลย์เอาต์ของ UI เป็นโปรไฟล์ และสลับใช้งานได้ทุกเมื่อ"
|
||||
_columns:
|
||||
main: "หลัก"
|
||||
widgets: "วิดเจ็ต"
|
||||
@@ -2927,8 +2820,6 @@ _abuseReport:
|
||||
notifiedWebhook: "Webhook ที่ใช้"
|
||||
deleteConfirm: "ต้องการลบปลายทางการแจ้งเตือนใช่ไหม?"
|
||||
_moderationLogTypes:
|
||||
clearQueue: "ล้างคิว"
|
||||
promoteQueue: "ดันงานในคิวอีกครั้ง"
|
||||
createRole: "สร้างบทบาทแล้ว"
|
||||
deleteRole: "ลบบทบาทแล้ว"
|
||||
updateRole: "อัปเดตบทบาทแล้ว"
|
||||
@@ -2987,7 +2878,7 @@ _fileViewer:
|
||||
uploadedAt: "วันที่เข้าร่วม"
|
||||
attachedNotes: "โน้ตที่แนบมาด้วย"
|
||||
usage: "ใช้แล้ว"
|
||||
thisPageCanBeSeenFromTheAuthor: "เฉพาะผู้ใช้ที่อัปโหลดไฟล์นี้เท่านั้นที่สามารถดูหน้าเพจนี้ได้"
|
||||
thisPageCanBeSeenFromTheAuthor: "หน้าเพจนี้จะสามารถปรากฏได้โดยผู้ใช้ที่อัปโหลดไฟล์นี้เท่านั้น"
|
||||
_externalResourceInstaller:
|
||||
title: "ติดตั้งจากไซต์ภายนอก"
|
||||
checkVendorBeforeInstall: "โปรดตรวจสอบให้แน่ใจว่าแหล่งแจกหน่ายมีความน่าเชื่อถือก่อนทำการติดตั้ง"
|
||||
@@ -3172,7 +3063,7 @@ _customEmojisManager:
|
||||
uploadSettingDescription: "สามารถกำหนดพฤติกรรมขณะอัปโหลดเอโมจิจากหน้าจอนี้ได้"
|
||||
directoryToCategoryLabel: "ป้อนชื่อไดเรกทอรีเป็น \"category\""
|
||||
directoryToCategoryCaption: "เมื่อทำการลากและวางไดเรกทอรี ชื่อจะถูกป้อนเป็น \"category\""
|
||||
confirmRegisterEmojisDescription: "จะลงทะเบียนเอโมจิที่แสดงในรายการเป็นเอโมจิแบบกำหนดเองใหม่\nดำเนินการต่อหรือไม่? (เพื่อหลีกเลี่ยงภาระโหลดหนัก ระบบจะสามารถลงทะเบียนเอโมจิได้สูงสุด {count} รายการต่อครั้ง)"
|
||||
confirmRegisterEmojisDescription: "จะลงทะเบียนเอโมจิที่แสดงในรายการเป็นเอโมจิแบบกำหนดเองใหม่\nดำเนินการต่อหรือไม่? (เพื่อหลีกเลี่ยงภาระโหลดหนัก ระบบจะสามารถลงทะเบียนอีโมจิได้สูงสุด {count} รายการต่อครั้ง)"
|
||||
confirmClearEmojisDescription: "ต้องการยกเลิกการแก้ไขและล้างรายการเอโมจิที่แสดงอยู่หรือไม่?"
|
||||
confirmUploadEmojisDescription: "จะอัปโหลดไฟล์ {count} รายการที่ลากและวางไปยังไดรฟ์ ดำเนินการหรือไม่?"
|
||||
_embedCodeGen:
|
||||
@@ -3323,7 +3214,6 @@ _watermarkEditor:
|
||||
title: "แก้ไขลายน้ำ"
|
||||
cover: "ซ้อนทับทั่วทั้งพื้นที่"
|
||||
repeat: "ปูให้เต็มพื้นที่"
|
||||
preserveBoundingRect: "ปรับไม่ให้ล้นขอบเมื่อหมุน"
|
||||
opacity: "ความทึบแสง"
|
||||
scale: "ขนาด"
|
||||
text: "ข้อความ"
|
||||
@@ -3345,12 +3235,10 @@ _watermarkEditor:
|
||||
polkadotSubDotRadius: "ขนาดของจุดรอง"
|
||||
polkadotSubDotDivisions: "จำนวนจุดรอง"
|
||||
leaveBlankToAccountUrl: "เว้นว่างไว้หากต้องการใช้ URL ของบัญชีแทน"
|
||||
failedToLoadImage: "โหลดภาพล้มเหลว"
|
||||
_imageEffector:
|
||||
title: "เอฟเฟกต์"
|
||||
addEffect: "เพิ่มเอฟเฟกต์"
|
||||
discardChangesConfirm: "ต้องการทิ้งการเปลี่ยนแปลงแล้วออกหรือไม่?"
|
||||
failedToLoadImage: "โหลดภาพล้มเหลว"
|
||||
_fxs:
|
||||
chromaticAberration: "ความคลาดสี"
|
||||
glitch: "กลิตช์"
|
||||
@@ -3401,9 +3289,11 @@ _imageEffector:
|
||||
threshold: "เทรชโฮลด์"
|
||||
centerX: "กลาง X"
|
||||
centerY: "กลาง Y"
|
||||
density: "ความหนาทึบ"
|
||||
zoomLinesOutlineThickness: "ความหนาของเงาเส้น"
|
||||
zoomLinesSmoothing: "ทำให้สมูธ"
|
||||
zoomLinesSmoothingDescription: "ตั้งให้สมูธไม่สามารถใช้ร่วมกับตั้งความกว้างเส้นรวมศูนย์ได้"
|
||||
zoomLinesThreshold: "ความกว้างเส้นรวมศูนย์"
|
||||
zoomLinesMaskSize: "ขนาดพื้นที่ตรงกลาง"
|
||||
zoomLinesBlack: "ทำให้ดำ"
|
||||
circle: "ทรงกลม"
|
||||
drafts: "ร่าง"
|
||||
_drafts:
|
||||
|
||||
@@ -83,8 +83,6 @@ files: "Dosyalar"
|
||||
download: "İndir"
|
||||
driveFileDeleteConfirm: "“{name}” dosyasını silmek istediğinden emin misin? Bu dosyaya ekli tüm notlar da silinecek."
|
||||
unfollowConfirm: "{name} kullanıcısını cidden takipden çıkmak istiyor musun?"
|
||||
cancelFollowRequestConfirm: "{name} adlı kişiye gönderdiğiniz takip isteğini iptal etmek ister misiniz?"
|
||||
rejectFollowRequestConfirm: "{name} adlı kullanıcının takip isteğini reddetmek istiyor musunuz?"
|
||||
exportRequested: "Dışa aktarma işlemi talep ettin. Bu işlem biraz zaman alabilir. İşlem tamamlandığında Drive'ına eklenecek."
|
||||
importRequested: "İçe aktarma talebinde bulundun. Bu işlem biraz zaman alabilir."
|
||||
lists: "Listeler"
|
||||
@@ -255,7 +253,6 @@ noteDeleteConfirm: "Bu notu silmek istediğinden emin misin?"
|
||||
pinLimitExceeded: "Artık daha fazla not sabitleyemezsin"
|
||||
done: "Tamam"
|
||||
processing: "İşleniyor..."
|
||||
preprocessing: "Hazırlık aşamasında"
|
||||
preview: "Önizleme"
|
||||
default: "Varsayılan"
|
||||
defaultValueIs: "Varsayılan: {value}"
|
||||
@@ -304,7 +301,6 @@ uploadFromUrlMayTakeTime: "Yükleme işleminin tamamlanması biraz zaman alabili
|
||||
uploadNFiles: "{n} dosya yükle"
|
||||
explore: "Keşfet"
|
||||
messageRead: "Oku"
|
||||
readAllChatMessages: "Tüm mesajları okundu olarak işaretle"
|
||||
noMoreHistory: "Daha fazla geçmiş bilgisi yok."
|
||||
startChat: "Sohbete başla"
|
||||
nUsersRead: "{n} tarafından okundu"
|
||||
@@ -337,7 +333,6 @@ fileName: "Dosya adı"
|
||||
selectFile: "Dosya seçin"
|
||||
selectFiles: "Dosyaları seçin"
|
||||
selectFolder: "Klasör seçin"
|
||||
unselectFolder: "Klasör seçimini kaldır"
|
||||
selectFolders: "Klasörleri seçin"
|
||||
fileNotSelected: "Hiç dosya seçilmedi"
|
||||
renameFile: "Dosyayı yeniden adlandır"
|
||||
@@ -350,7 +345,6 @@ addFile: "Bir dosya ekle"
|
||||
showFile: "Dosyaları göster"
|
||||
emptyDrive: "Drive boş"
|
||||
emptyFolder: "Bu klasör boş"
|
||||
dropHereToUpload: "Yüklemek için dosyalarınızı buraya sürükleyin."
|
||||
unableToDelete: "Silinemiyor"
|
||||
inputNewFileName: "Yeni bir dosya adı girin"
|
||||
inputNewDescription: "Yeni alternatif metin girin"
|
||||
@@ -543,7 +537,6 @@ regenerate: "Yeniden oluştur"
|
||||
fontSize: "Yazı tipi boyutu"
|
||||
mediaListWithOneImageAppearance: "Tek bir resim içeren medya listelerinin yüksekliği"
|
||||
limitTo: "{x} ile sınırlandır"
|
||||
showMediaListByGridInWideArea: "Ekran genişliği geniş olduğunda, medya listesi yatay olarak görüntülenecektir."
|
||||
noFollowRequests: "Bekleyen takip istekleri yok."
|
||||
openImageInNewTab: "Görüntüleri yeni sekmede aç"
|
||||
dashboard: "Gösterge paneli"
|
||||
@@ -779,7 +772,6 @@ lockedAccountInfo: "Notunuzun görünürlüğünü “Yalnızca takipçiler” o
|
||||
alwaysMarkSensitive: "Varsayılan olarak hassas olarak işaretle"
|
||||
loadRawImages: "Küçük resimleri göstermek yerine orijinal resimleri yükle"
|
||||
disableShowingAnimatedImages: "Animasyonlu görüntüleri oynatmayın"
|
||||
disableShowingAnimatedImages_caption: "Bu ayara rağmen animasyonlu görüntüler oynatılmıyorsa, bunun nedeni tarayıcınızın veya işletim sisteminizin erişilebilirlik ayarları veya güç tasarrufu ayarlarından kaynaklanan parazit olabilir."
|
||||
highlightSensitiveMedia: "Hassas medyayı vurgulayın"
|
||||
verificationEmailSent: "Doğrulama e-postası gönderildi. Doğrulamayı tamamlamak için e-postadaki bağlantıyı takip edin."
|
||||
notSet: "Ayarlı değil"
|
||||
@@ -1026,9 +1018,6 @@ pushNotificationAlreadySubscribed: "Push bildirimleri zaten açık"
|
||||
pushNotificationNotSupported: "Push bildirimleri sunucu veya tarayıcı tarafından desteklenmiyor"
|
||||
sendPushNotificationReadMessage: "Okunduktan sonra push bildirimlerini silin"
|
||||
sendPushNotificationReadMessageCaption: "Bu, cihazınızın güç tüketimini artırabilir."
|
||||
pleaseAllowPushNotification: "Lütfen tarayıcı ayarlarınızdan bildirimlere izin verin."
|
||||
browserPushNotificationDisabled: "Bildirim gönderme izni alınamadı."
|
||||
browserPushNotificationDisabledDescription: "{serverName} sunucusundan bildirim gönderme izniniz yok. Lütfen tarayıcı ayarlarınızdan bildirimlere izin verin ve tekrar deneyin."
|
||||
windowMaximize: "Maksimize et"
|
||||
windowMinimize: "Minimize et"
|
||||
windowRestore: "Geri yükle"
|
||||
@@ -1179,7 +1168,6 @@ installed: "Yüklendi"
|
||||
branding: "Markalaşma"
|
||||
enableServerMachineStats: "Sunucu donanım istatistiklerini yayınla"
|
||||
enableIdenticonGeneration: "Kullanıcı identicon oluşturmayı etkinleştir"
|
||||
showRoleBadgesOfRemoteUsers: "Uzaktan kullanıcılara verilen rol rozetlerini görüntüle"
|
||||
turnOffToImprovePerformance: "Devre dışı bırakma, daha yüksek performansa yol açabilir."
|
||||
createInviteCode: "Davet Kodu oluştur"
|
||||
createWithOptions: "Seçeneklerle oluştur"
|
||||
@@ -1328,7 +1316,6 @@ acknowledgeNotesAndEnable: "Önlemleri anladıktan sonra açın."
|
||||
federationSpecified: "Bu sunucu, beyaz liste federasyonunda çalıştırılmaktadır. Yönetici tarafından belirlenen sunucular dışında diğer sunucularla etkileşim kurmak yasaktır."
|
||||
federationDisabled: "Bu sunucuda federasyon devre dışıdır. Diğer sunuculardaki kullanıcılarla etkileşim kuramazsınız."
|
||||
draft: "Taslaklar"
|
||||
draftsAndScheduledNotes: "Taslaklar ve planlanmış gönderiler"
|
||||
confirmOnReact: "Tepki verirken onaylayın"
|
||||
reactAreYouSure: "“{emoji}” tepkisini eklemek ister misin?"
|
||||
markAsSensitiveConfirm: "Bu medyayı hassas olarak ayarlamak ister misin?"
|
||||
@@ -1357,7 +1344,6 @@ textCount: "Karakter sayısı"
|
||||
information: "Hakkında"
|
||||
chat: "Sohbet"
|
||||
directMessage: "Kullanıcıyla sohbet et"
|
||||
directMessage_short: "Mesaj"
|
||||
migrateOldSettings: "Eski istemci ayarlarını taşıma"
|
||||
migrateOldSettings_description: "Bu işlem otomatik olarak yapılmalıdır, ancak herhangi bir nedenle geçiş başarısız olursa, geçiş işlemini manuel olarak kendin başlatabilirsin. Mevcut yapılandırma bilgileri üzerine yazılacaktır."
|
||||
compress: "Sıkıştır"
|
||||
@@ -1385,8 +1371,6 @@ redisplayAllTips: "Tüm “İpucu & Püf Nokta” tekrar göster"
|
||||
hideAllTips: "Tüm “İpucu & Püf Nokta” gizle"
|
||||
defaultImageCompressionLevel: "Varsayılan görüntü sıkıştırma düzeyi"
|
||||
defaultImageCompressionLevel_description: "Düşük seviye görüntü kalitesini korur ancak dosya boyutunu artırır.<br>Yüksek seviye dosya boyutunu azaltır ancak görüntü kalitesini düşürür."
|
||||
defaultCompressionLevel: "Varsayılan sıkıştırma seviyesi"
|
||||
defaultCompressionLevel_description: "Ayarı düşürmek kaliteyi koruyacak ancak dosya boyutunu artıracaktır. <br> Ayarı yükseltmek dosya boyutunu küçültecek ancak kaliteyi düşürecektir."
|
||||
inMinutes: "Dakika(lar)"
|
||||
inDays: "Gün(ler)"
|
||||
safeModeEnabled: "Güvenli mod etkinleştirildi"
|
||||
@@ -1394,74 +1378,21 @@ pluginsAreDisabledBecauseSafeMode: "Güvenli mod etkinleştirildiği için tüm
|
||||
customCssIsDisabledBecauseSafeMode: "Güvenli mod etkin olduğu için özel CSS uygulanmıyor."
|
||||
themeIsDefaultBecauseSafeMode: "Güvenli mod etkinken, varsayılan tema kullanılır. Güvenli modu devre dışı bırakmak bu değişiklikleri geri alır."
|
||||
thankYouForTestingBeta: "Beta sürümünü test ettiğin için teşekkür ederiz!"
|
||||
createUserSpecifiedNote: "Kullanıcı tarafından belirtilen notlar oluşturun"
|
||||
schedulePost: "Bir gönderi planla"
|
||||
scheduleToPostOnX: "{x} için bir gönderi planla"
|
||||
scheduledToPostOnX: "{x} için bir gönderi planlandı."
|
||||
schedule: "rezervasyon"
|
||||
scheduled: "rezervasyon"
|
||||
widgets: "Widget'lar"
|
||||
deviceInfo: "Cihaz Bilgileri"
|
||||
deviceInfoDescription: "Teknik bir sorunuz olduğunda, aşağıdaki bilgileri eklemeniz sorunun çözülmesine yardımcı olabilir."
|
||||
youAreAdmin: "Siz yöneticisiniz."
|
||||
frame: "Çerçeve"
|
||||
presets: "Ön ayar"
|
||||
zeroPadding: "Sıfır doldurma"
|
||||
nothingToConfigure: "Ayarlar seçeneği bulunmamaktadır."
|
||||
_imageEditing:
|
||||
_vars:
|
||||
caption: "Dosya başlığı"
|
||||
filename: "Dosya adı"
|
||||
filename_without_ext: "Uzantısız dosya adları"
|
||||
year: "Çekim yılı"
|
||||
month: "Çekim ayı"
|
||||
day: "Çekim tarihi"
|
||||
hour: "Fotoğrafın çekildiği zaman (saat)"
|
||||
minute: "Çekim süresi (dakika)"
|
||||
second: "Çekim süresi (saniye)"
|
||||
camera_model: "Kamera Adı"
|
||||
camera_lens_model: "Lens adı"
|
||||
camera_mm: "Odak uzaklığı"
|
||||
camera_mm_35: "Genişlik (35mm)"
|
||||
camera_f: "açıklık"
|
||||
camera_s: "Enstantane hızı"
|
||||
camera_iso: "ISO hassasiyeti"
|
||||
gps_lat: "Enlem"
|
||||
gps_long: "Boylam"
|
||||
_imageFrameEditor:
|
||||
title: "Düzenleme kareleri"
|
||||
tip: "Görselleri, meta verileri içeren çerçeveler ve etiketler ekleyerek süsleyebilirsiniz."
|
||||
header: "Başlık"
|
||||
footer: "Alt bilgi"
|
||||
borderThickness: "jantın genişliği"
|
||||
labelThickness: "Etiket genişliği"
|
||||
labelScale: "Etiket ölçeği"
|
||||
centered: "Merkezlenmiş"
|
||||
captionMain: "Altyazı (büyük)"
|
||||
captionSub: "Altyazı (küçük)"
|
||||
availableVariables: "Mevcut değişkenler"
|
||||
withQrCode: "2 boyutlu kod"
|
||||
backgroundColor: "Arka Plan Rengi "
|
||||
textColor: "Metin Rengi "
|
||||
font: "Yazı tipi"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
quitWithoutSaveConfirm: "Kaydedilmemiş değişiklikleri silmek ister misin?"
|
||||
failedToLoadImage: "Görüntü yükleme başarısız oldu "
|
||||
_compression:
|
||||
_quality:
|
||||
high: "Yüksek Kalite "
|
||||
medium: "Orta Kalite"
|
||||
low: "Düşük Kalite "
|
||||
_size:
|
||||
large: "Büyük Boyut"
|
||||
medium: "Orta Boyut"
|
||||
small: "Küçük Boyut"
|
||||
_order:
|
||||
newest: "Önce yeni"
|
||||
oldest: "Önce eski"
|
||||
_chat:
|
||||
messages: "Mesaj"
|
||||
noMessagesYet: "Henüz mesaj yok"
|
||||
newMessage: "Yeni mesaj"
|
||||
individualChat: "Özel Sohbet"
|
||||
@@ -1550,11 +1481,6 @@ _settings:
|
||||
showUrlPreview: "URL önizlemesi"
|
||||
showAvailableReactionsFirstInNote: "Mevcut tepkileri en üstte göster."
|
||||
showPageTabBarBottom: "Sayfa sekme çubuğunu aşağıda göster"
|
||||
emojiPaletteBanner: "Emoji seçiciye kalıcı olarak bir palet olarak görüntülenecek ön ayarları kaydedebilir veya seçicinin nasıl görüntüleneceğini özelleştirebilirsiniz."
|
||||
enableAnimatedImages: "Hareketli görüntüleri etkinleştirin"
|
||||
settingsPersistence_title: "Ayarların kalıcılığı"
|
||||
settingsPersistence_description1: "Ayarların kalıcı olarak saklanmasını etkinleştirmek, yapılandırma bilgilerinin kaybolmasını önler."
|
||||
settingsPersistence_description2: "Ortamınıza bağlı olarak bu özelliği etkinleştirmek mümkün olmayabilir."
|
||||
_chat:
|
||||
showSenderName: "Gönderenin adını göster"
|
||||
sendOnEnter: "Enter tuşuna basarak gönderin"
|
||||
@@ -1563,8 +1489,6 @@ _preferencesProfile:
|
||||
profileNameDescription: "Bu cihazı tanımlayan bir ad belirle."
|
||||
profileNameDescription2: "Örnek: “Ana bilgisayar”, “Akıllı telefon”"
|
||||
manageProfiles: "Profilleri Yönet"
|
||||
shareSameProfileBetweenDevicesIsNotRecommended: "Aynı profili birden fazla cihazda kullanmak önerilmez."
|
||||
useSyncBetweenDevicesOptionIfYouWantToSyncSetting: "Birden fazla cihazda senkronize etmek istediğiniz ayarlarınız varsa, lütfen her bir ayar için \"Birden fazla cihazda senkronize et\" seçeneğini etkinleştirin."
|
||||
_preferencesBackup:
|
||||
autoBackup: "Otomatik yedekleme"
|
||||
restoreFromBackup: "Yedeklemeden geri yükle"
|
||||
@@ -1574,7 +1498,6 @@ _preferencesBackup:
|
||||
youNeedToNameYourProfileToEnableAutoBackup: "Otomatik yedeklemeyi etkinleştirmek için bir profil adı ayarlanmalıdır."
|
||||
autoPreferencesBackupIsNotEnabledForThisDevice: "Bu cihazda ayarların otomatik yedeklemesi etkinleştirilmemiş."
|
||||
backupFound: "Ayarların yedeği bulundu"
|
||||
forceBackup: "Ayarların zorunlu yedeklenmesi"
|
||||
_accountSettings:
|
||||
requireSigninToViewContents: "İçeriği görüntülemek için oturum açmanız gerekir."
|
||||
requireSigninToViewContentsDescription1: "Oluşturduğun tüm notları ve diğer içeriği görüntülemek için oturum açman gerekir. Bu, tarayıcıların bilgilerini toplamasına engel olacaktır."
|
||||
@@ -2080,7 +2003,6 @@ _role:
|
||||
canManageAvatarDecorations: "Avatar süslerini yönet"
|
||||
driveCapacity: "Drive kapasitesi"
|
||||
maxFileSize: "Yükleyebileceğin maksimum dosya boyutu"
|
||||
maxFileSize_caption: "Önceki aşamada ters proxy veya CDN gibi başka yapılandırma ayarları da olabilir."
|
||||
alwaysMarkNsfw: "Dosyaları her zaman NSFW olarak işaretle"
|
||||
canUpdateBioMedia: "Bir simge veya banner görüntüsünü düzenleyebilir"
|
||||
pinMax: "Sabitlenmiş notların maksimum sayısı"
|
||||
@@ -2108,7 +2030,6 @@ _role:
|
||||
uploadableFileTypes_caption: "İzin verilen MIME/dosya türlerini belirtir. Birden fazla MIME türü, yeni bir satırla ayırarak belirtilebilir ve joker karakterler yıldız işareti (*) ile belirtilebilir. (örneğin, image/*)"
|
||||
uploadableFileTypes_caption2: "Bazı dosya türleri algılanamayabilir. Bu tür dosyalara izin vermek için, spesifikasyona {x} ekle."
|
||||
noteDraftLimit: "Sunucu notlarının olası taslak sayısı"
|
||||
scheduledNoteLimit: "Aynı anda oluşturulabilecek planlanmış gönderi sayısı"
|
||||
watermarkAvailable: "Filigran işlevinin kullanılabilirliği"
|
||||
_condition:
|
||||
roleAssignedTo: "Manuel rollere atanmış"
|
||||
@@ -2499,7 +2420,6 @@ _auth:
|
||||
scopeUser: "Aşağıdaki kullanıcı olarak çalıştırın"
|
||||
pleaseLogin: "Uygulamaları yetkilendirmek için lütfen giriş yapın."
|
||||
byClickingYouWillBeRedirectedToThisUrl: "Erişim izni verildiğinde, otomatik olarak aşağıdaki URL'ye yönlendirileceksin."
|
||||
alreadyAuthorized: "Bu uygulamaya zaten erişim izinleri verilmiş durumda."
|
||||
_antennaSources:
|
||||
all: "Tüm notlar"
|
||||
homeTimeline: "Takip edilen kullanıcıların notları"
|
||||
@@ -2548,40 +2468,11 @@ _widgets:
|
||||
chat: "Sohbet"
|
||||
_widgetOptions:
|
||||
showHeader: "Başlığı göster"
|
||||
transparent: "Arka planı şeffaf yapın"
|
||||
height: "Yükseklik"
|
||||
_button:
|
||||
colored: "Renkli"
|
||||
_clock:
|
||||
size: "Boyut"
|
||||
thickness: "İğne kalınlığı"
|
||||
thicknessThin: "İnce"
|
||||
thicknessMedium: "Normal"
|
||||
thicknessThick: "Kalın"
|
||||
graduations: "Kadran ölçeği"
|
||||
graduationDots: "Nokta"
|
||||
graduationArabic: "Arap rakamları"
|
||||
fadeGraduations: "ölçeği soluklaştır"
|
||||
sAnimation: "İkinci el animasyon"
|
||||
sAnimationElastic: "Gerçek"
|
||||
sAnimationEaseOut: "Düz"
|
||||
twentyFour: "24 saat ekran"
|
||||
labelTime: "Zaman"
|
||||
labelTz: "Zaman Dilimi"
|
||||
labelTimeAndTz: "Zaman ve Saat Dilimi"
|
||||
timezone: "Zaman Dilimi "
|
||||
showMs: "Milisaniye cinsinden göster"
|
||||
showLabel: "Etiketi Göster"
|
||||
_jobQueue:
|
||||
sound: "Sesleri Çal"
|
||||
_rss:
|
||||
url: "RSS beslemesi URL'si"
|
||||
refreshIntervalSec: "Güncelleme aralığı (saniye)"
|
||||
maxEntries: "Görüntülenecek maksimum öğe sayısı"
|
||||
_rssTicker:
|
||||
shuffle: "Görüntüleme sırasını karıştır"
|
||||
duration: "Kaydırma yazısı hızı (saniye)"
|
||||
reverse: "Geriye doğru kaydır"
|
||||
_birthdayFollowings:
|
||||
period: "Süre"
|
||||
_cw:
|
||||
@@ -2628,20 +2519,9 @@ _postForm:
|
||||
replyPlaceholder: "Bu notu yanıtla..."
|
||||
quotePlaceholder: "Bu notu alıntı yap..."
|
||||
channelPlaceholder: "Bir kanala gönder..."
|
||||
showHowToUse: "Form açıklamasını göster"
|
||||
_howToUse:
|
||||
content_title: "Metin"
|
||||
content_description: "Yayınlamak istediğiniz içeriği girin."
|
||||
toolbar_title: "Araç Çubuğu"
|
||||
toolbar_description: "Dosya ve anket ekleyebilir, açıklamalar ve etiketler ekleyebilir, emoji ve bahsetme mesajları ekleyebilirsiniz."
|
||||
account_title: "Hesap Menüsü"
|
||||
account_description: "Paylaşım yaptığınız hesabı değiştirebilir ve hesabınıza kaydedilmiş taslak ve planlanmış paylaşımların listesini görüntüleyebilirsiniz."
|
||||
visibility_title: "Görünürlük"
|
||||
visibility_description: "Notlarınıza kimlerin erişebileceğinin kapsamını belirleyebilirsiniz."
|
||||
menu_title: "Menü"
|
||||
menu_description: "Taslak olarak kaydetme, gönderi planlama ve tepki ayarlama gibi diğer işlemleri de gerçekleştirebilirsiniz."
|
||||
submit_title: "Gönder düğmesi"
|
||||
submit_description: "Bir not paylaşacağım. Ctrl + Enter / Cmd + Enter tuşlarını kullanarak da paylaşım yapabilirsiniz."
|
||||
_placeholders:
|
||||
a: "Ne yapıyorsun?"
|
||||
b: "Çevrende neler oluyor?"
|
||||
@@ -2787,8 +2667,6 @@ _notification:
|
||||
youReceivedFollowRequest: "Bir takip isteği aldınız."
|
||||
yourFollowRequestAccepted: "Takip isteğin kabul edildi."
|
||||
pollEnded: "Anket sonuçları açıklandı."
|
||||
scheduledNotePosted: "Rezervasyon defteri yayınlandı."
|
||||
scheduledNotePostFailed: "Rezervasyon defterine gönderilemedi"
|
||||
newNote: "Yeni not"
|
||||
unreadAntennaNote: "{name} anteni"
|
||||
roleAssigned: "Verilen rol"
|
||||
@@ -2818,8 +2696,6 @@ _notification:
|
||||
quote: "Alıntılar"
|
||||
reaction: "Tepki"
|
||||
pollEnded: "Anketler sona eriyor"
|
||||
scheduledNotePosted: "Planlanan gönderi başarılı"
|
||||
scheduledNotePostFailed: "Planlanan gönderi başarısız oldu"
|
||||
receiveFollowRequest: "Takip istekleri alındı"
|
||||
followRequestAccepted: "Kabul edilen takip istekleri"
|
||||
roleAssigned: "Verilen rol"
|
||||
@@ -2859,14 +2735,6 @@ _deck:
|
||||
usedAsMinWidthWhenFlexible: "“Otomatik genişlik ayarı” seçeneği etkinleştirildiğinde, bunun için minimum genişlik kullanılacak."
|
||||
flexible: "Otomatik genişlik ayarı"
|
||||
enableSyncBetweenDevicesForProfiles: "Cihazlar arasında profil bilgilerinin senkronizasyonunu etkinleştir"
|
||||
showHowToUse: "Kullanıcı arayüzü açıklamasını görüntüle"
|
||||
_howToUse:
|
||||
addColumn_title: "Sütun ekle"
|
||||
addColumn_description: "Sütun türlerini seçip ekleyebilirsiniz."
|
||||
settings_title: "Arayüz Yapılandırması"
|
||||
settings_description: "Sekme kullanıcı arayüzünü ayrıntılı olarak yapılandırabilirsiniz."
|
||||
switchProfile_title: "Profili Değiştir"
|
||||
switchProfile_description: "Kullanıcı arayüzü düzenlerini profil olarak kaydedebilir ve istediğiniz zaman bunlar arasında geçiş yapabilirsiniz."
|
||||
_columns:
|
||||
main: "Ana"
|
||||
widgets: "Widget'lar"
|
||||
@@ -2927,8 +2795,6 @@ _abuseReport:
|
||||
notifiedWebhook: "Kullanılacak webhook"
|
||||
deleteConfirm: "Bildirim alıcısını silmek istediğinden emin misin?"
|
||||
_moderationLogTypes:
|
||||
clearQueue: "Kuyruğu temizle"
|
||||
promoteQueue: "Sıraya alınmış işi yeniden deneyin."
|
||||
createRole: "Rol oluşturuldu"
|
||||
deleteRole: "Rol silindi"
|
||||
updateRole: "Rol güncellendi"
|
||||
@@ -3323,13 +3189,10 @@ _watermarkEditor:
|
||||
title: "Filigranı Düzenle"
|
||||
cover: "Her şeyi örtün"
|
||||
repeat: "her yere yayılmış"
|
||||
preserveBoundingRect: "Döndürme sırasında dışarı çıkmayacak şekilde ayarlayın."
|
||||
opacity: "Opaklık"
|
||||
scale: "Boyut"
|
||||
text: "Metin"
|
||||
qr: "2 boyutlu kod"
|
||||
position: "Pozisyon"
|
||||
margin: "Kenar"
|
||||
type: "Tür"
|
||||
image: "Görseller"
|
||||
advanced: "Gelişmiş"
|
||||
@@ -3344,21 +3207,16 @@ _watermarkEditor:
|
||||
polkadotSubDotOpacity: "İkincil noktanın opaklığı"
|
||||
polkadotSubDotRadius: "İkincil noktanın boyutu"
|
||||
polkadotSubDotDivisions: "Alt nokta sayısı."
|
||||
leaveBlankToAccountUrl: "Boş bırakılması durumunda hesap URL'si görüntülenecektir."
|
||||
failedToLoadImage: "Görüntü yükleme başarısız oldu "
|
||||
_imageEffector:
|
||||
title: "Effektler"
|
||||
addEffect: "Efektler Ekle"
|
||||
discardChangesConfirm: "Cidden çıkmak istiyor musun? Kaydedilmemiş değişikliklerin var."
|
||||
failedToLoadImage: "Görüntü yükleme başarısız oldu "
|
||||
_fxs:
|
||||
chromaticAberration: "Renk Sapması"
|
||||
glitch: "Bozulma"
|
||||
mirror: "Ayna"
|
||||
invert: "Renkleri Ters Çevir"
|
||||
grayscale: "Gri tonlama"
|
||||
blur: "Bulanıklık"
|
||||
pixelate: "Mozaik"
|
||||
colorAdjust: "Renk Düzeltme"
|
||||
colorClamp: "Renk Sıkıştırma"
|
||||
colorClampAdvanced: "Renk Sıkıştırma (Gelişmiş)"
|
||||
@@ -3370,13 +3228,10 @@ _imageEffector:
|
||||
checker: "Denetleyici"
|
||||
blockNoise: "Gürültüyü Engelle"
|
||||
tearing: "Yırtılma"
|
||||
fill: "Doldur"
|
||||
_fxProps:
|
||||
angle: "Açı"
|
||||
scale: "Boyut"
|
||||
size: "Boyut"
|
||||
radius: "Yarıçap"
|
||||
samples: "Örnek sayısı"
|
||||
offset: "Pozisyon"
|
||||
color: "Renk"
|
||||
opacity: "Opaklık"
|
||||
@@ -3401,10 +3256,11 @@ _imageEffector:
|
||||
threshold: "Eşik"
|
||||
centerX: "Merkez X"
|
||||
centerY: "Merkez Y"
|
||||
density: "Yoğunluk"
|
||||
zoomLinesOutlineThickness: "çizgi gölge kalınlığı"
|
||||
zoomLinesSmoothing: "Düzeltme"
|
||||
zoomLinesSmoothingDescription: "Düzeltme ve yakınlaştırma çizgi genişliği birlikte kullanılamaz."
|
||||
zoomLinesThreshold: "Zoom çizgi genişliği"
|
||||
zoomLinesMaskSize: "Merkez çapı"
|
||||
circle: "Dairesel"
|
||||
zoomLinesBlack: "Siyah yap"
|
||||
drafts: "Taslaklar"
|
||||
_drafts:
|
||||
select: "Taslak Seç"
|
||||
@@ -3420,22 +3276,6 @@ _drafts:
|
||||
restoreFromDraft: "Taslaktan geri yükle"
|
||||
restore: "Geri yükle"
|
||||
listDrafts: "Taslaklar Listesi"
|
||||
schedule: "Planlanmış Gönderi"
|
||||
listScheduledNotes: "Planlanmış gönderilerin listesi"
|
||||
cancelSchedule: "Rezervasyonu iptal et"
|
||||
qr: "2 boyutlu kod"
|
||||
_qr:
|
||||
showTabTitle: "Ekran"
|
||||
readTabTitle: "Okumak"
|
||||
shareTitle: "{name}{acct}"
|
||||
shareText: "Beni Fediverse'te takip edin!"
|
||||
chooseCamera: "Kamera Seç"
|
||||
cannotToggleFlash: "Işık seçeneği mevcut değil."
|
||||
turnOnFlash: "Işığı açın"
|
||||
turnOffFlash: "Işığı kapatın"
|
||||
startQr: "Özgeçmiş Kodu Okuyucu"
|
||||
stopQr: "Kod okuyucuyu durdurun"
|
||||
noQrCodeFound: "QR kodu bulunamadı"
|
||||
scanFile: "Cihazdaki görüntüyü tarayın"
|
||||
raw: "Metin"
|
||||
mfm: "MFM"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
_lang_: "Tiếng Việt"
|
||||
_lang_: "Tiếng Việt "
|
||||
headlineMisskey: "Mạng xã hội liên hợp"
|
||||
introMisskey: "Xin chào! Misskey là một nền tảng tiểu blog phi tập trung mã nguồn mở.\nViết \"tút\" để chia sẻ những suy nghĩ của bạn 📡\nBằng \"biểu cảm\", bạn có thể bày tỏ nhanh chóng cảm xúc của bạn với các tút 👍\nHãy khám phá một thế giới mới! 🚀"
|
||||
poweredByMisskeyDescription: "{name} là một trong những chủ máy của <b>Misskey</b> là nền tảng mã nguồn mở"
|
||||
@@ -576,7 +576,6 @@ showFixedPostForm: "Hiện khung soạn tút ở phía trên bảng tin"
|
||||
showFixedPostFormInChannel: "Hiển thị mẫu bài đăng ở phía trên bản tin"
|
||||
withRepliesByDefaultForNewlyFollowed: "Mặc định hiển thị trả lời từ những người dùng mới theo dõi trong dòng thời gian"
|
||||
newNoteRecived: "Đã nhận tút mới"
|
||||
newNote: "Ghi chú mới"
|
||||
sounds: "Âm thanh"
|
||||
sound: "Âm thanh"
|
||||
notificationSoundSettings: "Cài đặt âm thanh thông báo"
|
||||
@@ -849,7 +848,7 @@ hideOnlineStatus: "Ẩn trạng thái online"
|
||||
hideOnlineStatusDescription: "Ẩn trạng thái online của bạn làm giảm sự tiện lợi của một số tính năng như tìm kiếm."
|
||||
online: "Online"
|
||||
active: "Hoạt động"
|
||||
offline: "Ngoại tuyến"
|
||||
offline: "Offline"
|
||||
notRecommended: "Không đề xuất"
|
||||
botProtection: "Bảo vệ Bot"
|
||||
instanceBlocking: "Máy chủ đã chặn"
|
||||
@@ -1221,7 +1220,6 @@ information: "Giới thiệu"
|
||||
chat: "Trò chuyện"
|
||||
migrateOldSettings: "Di chuyển cài đặt cũ"
|
||||
migrateOldSettings_description: "Thông thường, quá trình này diễn ra tự động, nhưng nếu vì lý do nào đó mà quá trình di chuyển không thành công, bạn có thể kích hoạt thủ công quy trình di chuyển, quá trình này sẽ ghi đè lên thông tin cấu hình hiện tại của bạn."
|
||||
driveAboutTip: "Trong Drive, danh sách các tệp bạn đã tải lên trước đây sẽ được hiển thị.<br>\nBạn có thể sử dụng lại chúng khi đính kèm vào ghi chú, hoặc tải lên trước các tệp để đăng sau.<br>\n<b>Lưu ý rằng nếu bạn xóa một tệp, tệp đó cũng sẽ biến mất khỏi tất cả những nơi đã sử dụng tệp đó (ghi chú, trang, ảnh đại diện, biểu ngữ, v.v.).</b><br>\nBạn cũng có thể tạo các thư mục để sắp xếp chúng."
|
||||
inMinutes: "phút"
|
||||
inDays: "ngày"
|
||||
widgets: "Tiện ích"
|
||||
|
||||
@@ -164,7 +164,7 @@ selectAntenna: "选择天线"
|
||||
editAntenna: "编辑天线"
|
||||
createAntenna: "创建天线"
|
||||
selectWidget: "选择小工具"
|
||||
editWidgets: "编辑小工具"
|
||||
editWidgets: "编辑部件"
|
||||
editWidgetsExit: "完成编辑"
|
||||
customEmojis: "自定义表情符号"
|
||||
emoji: "表情符号"
|
||||
@@ -543,7 +543,6 @@ regenerate: "重新生成"
|
||||
fontSize: "字体大小"
|
||||
mediaListWithOneImageAppearance: "仅一张图片的媒体列表高度"
|
||||
limitTo: "上限为 {x}"
|
||||
showMediaListByGridInWideArea: "在大屏幕上并排显示媒体列表"
|
||||
noFollowRequests: "没有关注请求"
|
||||
openImageInNewTab: "在新标签页中打开图片"
|
||||
dashboard: "管理面板"
|
||||
@@ -646,7 +645,7 @@ addedRelays: "已添加的中继"
|
||||
serviceworkerInfo: "您需要启用推送通知"
|
||||
deletedNote: "已删除的帖子"
|
||||
invisibleNote: "隐藏的帖子"
|
||||
enableInfiniteScroll: "自动加载更多内容"
|
||||
enableInfiniteScroll: "启用自动滚动页面模式"
|
||||
visibility: "可见性"
|
||||
poll: "投票"
|
||||
useCw: "隐藏内容"
|
||||
@@ -832,7 +831,7 @@ youAreRunningUpToDateClient: "您所使用的客户端已经是最新的。"
|
||||
newVersionOfClientAvailable: "新版本的客户端可用。"
|
||||
usageAmount: "使用量"
|
||||
capacity: "容量"
|
||||
inUse: "已使用"
|
||||
inUse: "使用中"
|
||||
editCode: "编辑代码"
|
||||
apply: "应用"
|
||||
receiveAnnouncementFromInstance: "从服务器接收通知"
|
||||
@@ -1408,7 +1407,6 @@ frame: "边框"
|
||||
presets: "预设值"
|
||||
zeroPadding: "填充 0"
|
||||
nothingToConfigure: "没有项目"
|
||||
viewRenotedChannel: "查看转帖所属频道"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
caption: "文件标题"
|
||||
@@ -2257,7 +2255,7 @@ _menuDisplay:
|
||||
top: "顶部"
|
||||
hide: "隐藏"
|
||||
_wordMute:
|
||||
muteWords: "要折叠的词"
|
||||
muteWords: "要屏蔽的词"
|
||||
muteWordsDescription: "AND 条件用空格分隔,OR 条件用换行符分隔。"
|
||||
muteWordsDescription2: "正则表达式用斜线包裹"
|
||||
_instanceMute:
|
||||
@@ -3402,9 +3400,11 @@ _imageEffector:
|
||||
threshold: "阈值"
|
||||
centerX: "中心 X "
|
||||
centerY: "中心 Y"
|
||||
density: "密度"
|
||||
zoomLinesOutlineThickness: "线条阴影粗细"
|
||||
zoomLinesSmoothing: "平滑"
|
||||
zoomLinesSmoothingDescription: "平滑和集中线宽度设置不能同时使用。"
|
||||
zoomLinesThreshold: "集中线宽度"
|
||||
zoomLinesMaskSize: "中心直径"
|
||||
zoomLinesBlack: "变成黑色"
|
||||
circle: "圆形"
|
||||
drafts: "草稿"
|
||||
_drafts:
|
||||
|
||||
@@ -10,7 +10,7 @@ notifications: "通知"
|
||||
username: "使用者名稱"
|
||||
password: "密碼"
|
||||
initialPasswordForSetup: "啟動初始設定的密碼"
|
||||
initialPasswordIsIncorrect: "啟動初始設定密碼錯誤。"
|
||||
initialPasswordIsIncorrect: "啟動初始設定的密碼錯誤。"
|
||||
initialPasswordForSetupDescription: "如果您自己安裝了 Misskey,請使用您在設定檔中輸入的密碼。\n如果您使用 Misskey 的託管服務之類的服務,請使用提供的密碼。\n如果您尚未設定密碼,請將其留空並繼續。"
|
||||
forgotPassword: "忘記密碼"
|
||||
fetchingAsApObject: "從聯邦宇宙取得中..."
|
||||
@@ -297,7 +297,7 @@ keepOriginalUploading: "保留原圖"
|
||||
keepOriginalUploadingDescription: "上傳圖片時保留原始圖片。關閉時,瀏覽器會在上傳時生成適用於網路傳送的版本。"
|
||||
fromDrive: "從雲端空間中選擇"
|
||||
fromUrl: "從 URL 上傳"
|
||||
uploadFromUrl: "從 URL 上傳"
|
||||
uploadFromUrl: "從網址上傳"
|
||||
uploadFromUrlDescription: "您要上傳的檔案網址"
|
||||
uploadFromUrlRequested: "已請求上傳"
|
||||
uploadFromUrlMayTakeTime: "還需要一些時間才能完成上傳。"
|
||||
@@ -543,7 +543,6 @@ regenerate: "再次生成"
|
||||
fontSize: "字體大小"
|
||||
mediaListWithOneImageAppearance: "只有一張圖片時的檔案列表高度"
|
||||
limitTo: "上限為 {x}"
|
||||
showMediaListByGridInWideArea: "當畫面寬度較寬時,將媒體清單以橫向排列顯示"
|
||||
noFollowRequests: "沒有追隨您的請求"
|
||||
openImageInNewTab: "於新分頁中開啟圖片"
|
||||
dashboard: "儀表板"
|
||||
@@ -825,7 +824,7 @@ saveConfirm: "您要儲存變更嗎?"
|
||||
deleteConfirm: "你確定要刪除嗎?"
|
||||
invalidValue: "輸入值無效。"
|
||||
registry: "登錄表"
|
||||
closeAccount: "刪除帳戶"
|
||||
closeAccount: "停用帳戶"
|
||||
currentVersion: "目前版本"
|
||||
latestVersion: "最新版本"
|
||||
youAreRunningUpToDateClient: "您所使用的客戶端已經是最新的。"
|
||||
@@ -1408,7 +1407,6 @@ frame: "邊框"
|
||||
presets: "預設值"
|
||||
zeroPadding: "補零"
|
||||
nothingToConfigure: "無可設定的項目"
|
||||
viewRenotedChannel: "顯示轉發貼文者的頻道"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
caption: "檔案標題"
|
||||
@@ -2158,7 +2156,7 @@ _accountDelete:
|
||||
accountDelete: "刪除帳戶"
|
||||
mayTakeTime: "刪除帳戶的處理負荷較大,如果帳戶發佈的內容以及上傳的檔案數量較多,則需要一段時間才能完成。"
|
||||
sendEmail: "帳戶刪除完成後,將向其電子郵件地址發送通知。"
|
||||
requestAccountDelete: "請求刪除帳戶"
|
||||
requestAccountDelete: "刪除帳戶請求"
|
||||
started: "已開始刪除作業。"
|
||||
inProgress: "正在刪除"
|
||||
_ad:
|
||||
@@ -2362,7 +2360,7 @@ _timeIn:
|
||||
minutes: "{n}分鐘後"
|
||||
hours: "{n}小時後"
|
||||
days: "{n}天後"
|
||||
weeks: "{n}週後"
|
||||
weeks: "{n}周後"
|
||||
months: "{n}個月後"
|
||||
years: "{n}年後"
|
||||
_time:
|
||||
@@ -2860,14 +2858,14 @@ _deck:
|
||||
usedAsMinWidthWhenFlexible: "如果啟用「自動調整寬度」,此為最小寬度"
|
||||
flexible: "自動調整寬度"
|
||||
enableSyncBetweenDevicesForProfiles: "啟用裝置與裝置之間的設定檔資料同步化"
|
||||
showHowToUse: "檢視使用者介面說明"
|
||||
showHowToUse: "檢視使用者界面說明"
|
||||
_howToUse:
|
||||
addColumn_title: "新增欄位"
|
||||
addColumn_description: "您可以選擇要新增的欄位類型。"
|
||||
settings_title: "使用者介面設定"
|
||||
settings_description: "您可以對多欄模式使用者介面做詳細設定。"
|
||||
settings_title: "使用者界面設定"
|
||||
settings_description: "您可以對多欄模式使用者界面做詳細設定。"
|
||||
switchProfile_title: "切換設定檔"
|
||||
switchProfile_description: "將使用者介面佈局儲存為設定檔,就可以隨時切換使用。"
|
||||
switchProfile_description: "將使用者界面佈局儲存為設定檔,就可以隨時切換使用。"
|
||||
_columns:
|
||||
main: "主列"
|
||||
widgets: "小工具"
|
||||
@@ -3402,9 +3400,11 @@ _imageEffector:
|
||||
threshold: "閾值"
|
||||
centerX: "X中心座標"
|
||||
centerY: "Y中心座標"
|
||||
density: "密度"
|
||||
zoomLinesOutlineThickness: "線條陰影的粗細"
|
||||
zoomLinesSmoothing: "平滑化"
|
||||
zoomLinesSmoothingDescription: "平滑化與集中線寬度設定不能同時使用。"
|
||||
zoomLinesThreshold: "集中線的寬度"
|
||||
zoomLinesMaskSize: "中心直徑"
|
||||
zoomLinesBlack: "變成黑色"
|
||||
circle: "圓形"
|
||||
drafts: "草稿\n"
|
||||
_drafts:
|
||||
|
||||
50
package.json
50
package.json
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"version": "2026.5.0",
|
||||
"version": "2026.1.0-beta.0",
|
||||
"codename": "nasubi",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/misskey-dev/misskey.git"
|
||||
},
|
||||
"packageManager": "pnpm@10.33.0",
|
||||
"packageManager": "pnpm@10.28.2",
|
||||
"workspaces": [
|
||||
"packages/misskey-js",
|
||||
"packages/i18n",
|
||||
@@ -28,9 +28,9 @@
|
||||
"build": "pnpm build-pre && pnpm -r build && pnpm build-assets",
|
||||
"build-storybook": "pnpm --filter frontend build-storybook",
|
||||
"build-misskey-js-with-types": "pnpm build-pre && pnpm --filter backend... --filter=!misskey-js build && pnpm --filter backend generate-api-json --no-build && ncp packages/backend/built/api.json packages/misskey-js/generator/api.json && pnpm --filter misskey-js update-autogen-code && pnpm --filter misskey-js build && pnpm --filter misskey-js api",
|
||||
"start": "cd packages/backend && pnpm compile-config && node ./built/entry.js",
|
||||
"start:inspect": "cd packages/backend && pnpm compile-config && node --inspect ./built/entry.js",
|
||||
"start:test": "ncp ./.github/misskey/test.yml ./.config/test.yml && cd packages/backend && cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./built/entry.js",
|
||||
"start": "cd packages/backend && pnpm compile-config && node ./built/boot/entry.js",
|
||||
"start:inspect": "cd packages/backend && pnpm compile-config && node --inspect ./built/boot/entry.js",
|
||||
"start:test": "ncp ./.github/misskey/test.yml ./.config/test.yml && cd packages/backend && cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./built/boot/entry.js",
|
||||
"cli": "cd packages/backend && pnpm cli",
|
||||
"init": "pnpm migrate",
|
||||
"migrate": "cd packages/backend && pnpm migrate",
|
||||
@@ -44,8 +44,8 @@
|
||||
"cy:run": "pnpm cypress run",
|
||||
"e2e": "pnpm start-server-and-test start:test http://localhost:61812 cy:run",
|
||||
"e2e-dev-container": "ncp ./.config/cypress-devcontainer.yml ./.config/test.yml && pnpm start-server-and-test start:test http://localhost:61812 cy:run",
|
||||
"backend-unit-test": "cd packages/backend && pnpm test",
|
||||
"backend-unit-test-and-coverage": "cd packages/backend && pnpm test-and-coverage",
|
||||
"jest": "cd packages/backend && pnpm jest",
|
||||
"jest-and-coverage": "cd packages/backend && pnpm jest-and-coverage",
|
||||
"test": "pnpm -r test",
|
||||
"test-and-coverage": "pnpm -r test-and-coverage",
|
||||
"clean": "node scripts/clean.mjs",
|
||||
@@ -53,31 +53,31 @@
|
||||
"cleanall": "pnpm clean-all"
|
||||
},
|
||||
"dependencies": {
|
||||
"cssnano": "7.1.5",
|
||||
"esbuild": "0.28.0",
|
||||
"cssnano": "7.1.2",
|
||||
"esbuild": "0.27.2",
|
||||
"execa": "9.6.1",
|
||||
"ignore-walk": "8.0.0",
|
||||
"js-yaml": "4.1.1",
|
||||
"postcss": "8.5.9",
|
||||
"tar": "7.5.13",
|
||||
"terser": "5.46.1"
|
||||
"postcss": "8.5.6",
|
||||
"tar": "7.5.6",
|
||||
"terser": "5.46.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "9.39.4",
|
||||
"@misskey-dev/eslint-plugin": "2.1.0",
|
||||
"@eslint/js": "9.39.2",
|
||||
"@misskey-dev/eslint-plugin": "2.2.0",
|
||||
"@types/js-yaml": "4.0.9",
|
||||
"@types/node": "24.12.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260421.2",
|
||||
"@types/node": "24.10.9",
|
||||
"@typescript-eslint/eslint-plugin": "8.53.0",
|
||||
"@typescript-eslint/parser": "8.53.0",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260116.1",
|
||||
"cross-env": "10.1.0",
|
||||
"cypress": "15.13.1",
|
||||
"eslint": "9.39.4",
|
||||
"globals": "17.5.0",
|
||||
"cypress": "15.9.0",
|
||||
"eslint": "9.39.2",
|
||||
"globals": "16.5.0",
|
||||
"ncp": "2.0.0",
|
||||
"pnpm": "10.33.0",
|
||||
"start-server-and-test": "3.0.2",
|
||||
"typescript": "5.9.3"
|
||||
"pnpm": "10.28.2",
|
||||
"typescript": "5.9.3",
|
||||
"start-server-and-test": "2.1.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@tensorflow/tfjs-core": "4.22.0"
|
||||
@@ -86,7 +86,7 @@
|
||||
"overrides": {
|
||||
"@aiscript-dev/aiscript-languageserver": "-",
|
||||
"chokidar": "5.0.0",
|
||||
"lodash": "4.18.1"
|
||||
"lodash": "4.17.23"
|
||||
},
|
||||
"ignoredBuiltDependencies": [
|
||||
"@sentry-internal/node-cpu-profiler",
|
||||
|
||||
29
packages/backend/.swcrc
Normal file
29
packages/backend/.swcrc
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "https://swc.rs/schema.json",
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "typescript",
|
||||
"jsx": true,
|
||||
"dynamicImport": true,
|
||||
"decorators": true
|
||||
},
|
||||
"transform": {
|
||||
"legacyDecorator": true,
|
||||
"decoratorMetadata": true,
|
||||
"react": {
|
||||
"runtime": "automatic",
|
||||
"importSource": "@kitajs/html"
|
||||
}
|
||||
},
|
||||
"experimental": {
|
||||
"keepImportAssertions": true
|
||||
},
|
||||
"baseUrl": "src",
|
||||
"paths": {
|
||||
"@/*": ["*"]
|
||||
},
|
||||
"target": "es2022"
|
||||
},
|
||||
"minify": false,
|
||||
"sourceMaps": "inline"
|
||||
}
|
||||
20
packages/backend/assets/api-doc.html
Normal file
20
packages/backend/assets/api-doc.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Misskey API</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<script
|
||||
id="api-reference"
|
||||
data-url="/api.json"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
packages/backend/assets/api-doc.png
Normal file
BIN
packages/backend/assets/api-doc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
4
packages/backend/assets/robots.txt
Normal file
4
packages/backend/assets/robots.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
user-agent: *
|
||||
allow: /
|
||||
|
||||
# todo: sitemap
|
||||
121
packages/backend/build.js
Normal file
121
packages/backend/build.js
Normal file
@@ -0,0 +1,121 @@
|
||||
import fs from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { build } from 'esbuild';
|
||||
import { swcPlugin } from 'esbuild-plugin-swc';
|
||||
|
||||
const _filename = fileURLToPath(import.meta.url);
|
||||
const _dirname = dirname(_filename);
|
||||
const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8'));
|
||||
|
||||
const resolveTsPathsPlugin = {
|
||||
name: 'resolve-ts-paths',
|
||||
setup(build) {
|
||||
build.onResolve({ filter: /^\.{1,2}\/.*\.js$/ }, (args) => {
|
||||
if (args.importer) {
|
||||
const absPath = join(args.resolveDir, args.path);
|
||||
const tsPath = absPath.slice(0, -3) + '.ts';
|
||||
if (fs.existsSync(tsPath)) return { path: tsPath };
|
||||
const tsxPath = absPath.slice(0, -3) + '.tsx';
|
||||
if (fs.existsSync(tsxPath)) return { path: tsxPath };
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const externalIpaddrPlugin = {
|
||||
name: 'external-ipaddr',
|
||||
setup(build) {
|
||||
build.onResolve({ filter: /^ipaddr\.js$/ }, (args) => {
|
||||
return { path: args.path, external: true };
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/** @type {import('esbuild').BuildOptions} */
|
||||
const options = {
|
||||
entryPoints: ['./src/boot/entry.ts'],
|
||||
minify: true,
|
||||
keepNames: true,
|
||||
bundle: true,
|
||||
outdir: './built/boot',
|
||||
target: 'node22',
|
||||
platform: 'node',
|
||||
format: 'esm',
|
||||
sourcemap: 'linked',
|
||||
packages: 'external',
|
||||
banner: {
|
||||
js: 'import { createRequire as topLevelCreateRequire } from "module";' +
|
||||
'import ___url___ from "url";' +
|
||||
'const require = topLevelCreateRequire(import.meta.url);' +
|
||||
'const __filename = ___url___.fileURLToPath(import.meta.url);' +
|
||||
'const __dirname = ___url___.fileURLToPath(new URL(".", import.meta.url));',
|
||||
},
|
||||
plugins: [
|
||||
externalIpaddrPlugin,
|
||||
resolveTsPathsPlugin,
|
||||
swcPlugin({
|
||||
jsc: {
|
||||
parser: {
|
||||
syntax: 'typescript',
|
||||
decorators: true,
|
||||
dynamicImport: true,
|
||||
},
|
||||
transform: {
|
||||
legacyDecorator: true,
|
||||
decoratorMetadata: true,
|
||||
},
|
||||
experimental: {
|
||||
keepImportAssertions: true,
|
||||
},
|
||||
baseUrl: join(_dirname, 'src'),
|
||||
paths: {
|
||||
'@/*': ['*'],
|
||||
},
|
||||
target: 'esnext',
|
||||
keepClassNames: true,
|
||||
},
|
||||
}),
|
||||
externalIpaddrPlugin,
|
||||
],
|
||||
// external: [
|
||||
// 'slacc-*',
|
||||
// 'class-transformer',
|
||||
// 'class-validator',
|
||||
// '@sentry/*',
|
||||
// '@nestjs/websockets/socket-module',
|
||||
// '@nestjs/microservices/microservices-module',
|
||||
// '@nestjs/microservices',
|
||||
// '@napi-rs/canvas-win32-x64-msvc',
|
||||
// 'mock-aws-s3',
|
||||
// 'aws-sdk',
|
||||
// 'nock',
|
||||
// 'sharp',
|
||||
// 'jsdom',
|
||||
// 're2',
|
||||
// '@napi-rs/canvas',
|
||||
// ],
|
||||
};
|
||||
|
||||
const args = process.argv.slice(2).map(arg => arg.toLowerCase());
|
||||
|
||||
if (!args.includes('--no-clean')) {
|
||||
fs.rmSync('./built', { recursive: true, force: true });
|
||||
}
|
||||
|
||||
await buildSrc();
|
||||
|
||||
async function buildSrc() {
|
||||
console.log(`[${_package.name}] start building...`);
|
||||
|
||||
await build(options)
|
||||
.then(() => {
|
||||
console.log(`[${_package.name}] build succeeded.`);
|
||||
})
|
||||
.catch((err) => {
|
||||
process.stderr.write(err.stderr || err.message || err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
console.log(`[${_package.name}] finish building.`);
|
||||
}
|
||||
220
packages/backend/jest.config.cjs
Normal file
220
packages/backend/jest.config.cjs
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* For a detailed explanation regarding each configuration property and type check, visit:
|
||||
* https://jestjs.io/docs/en/configuration.html
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
// All imported modules in your tests should be mocked automatically
|
||||
// automock: false,
|
||||
|
||||
// Stop running tests after `n` failures
|
||||
// bail: 0,
|
||||
|
||||
// The directory where Jest should store its cached dependency information
|
||||
// cacheDirectory: "C:\\Users\\ai\\AppData\\Local\\Temp\\jest",
|
||||
|
||||
// Automatically clear mock calls and instances between every test
|
||||
// clearMocks: false,
|
||||
|
||||
// Indicates whether the coverage information should be collected while executing the test
|
||||
// collectCoverage: false,
|
||||
|
||||
// An array of glob patterns indicating a set of files for which coverage information should be collected
|
||||
collectCoverageFrom: ['src/**/*.ts', '!src/**/*.test.ts'],
|
||||
|
||||
// The directory where Jest should output its coverage files
|
||||
coverageDirectory: "coverage",
|
||||
|
||||
// An array of regexp pattern strings used to skip coverage collection
|
||||
// coveragePathIgnorePatterns: [
|
||||
// "\\\\node_modules\\\\"
|
||||
// ],
|
||||
|
||||
// Indicates which provider should be used to instrument code for coverage
|
||||
coverageProvider: "v8",
|
||||
|
||||
// A list of reporter names that Jest uses when writing coverage reports
|
||||
// coverageReporters: [
|
||||
// "json",
|
||||
// "text",
|
||||
// "lcov",
|
||||
// "clover"
|
||||
// ],
|
||||
|
||||
// An object that configures minimum threshold enforcement for coverage results
|
||||
// coverageThreshold: undefined,
|
||||
|
||||
// A path to a custom dependency extractor
|
||||
// dependencyExtractor: undefined,
|
||||
|
||||
// Make calling deprecated APIs throw helpful error messages
|
||||
// errorOnDeprecated: false,
|
||||
|
||||
// Force coverage collection from ignored files using an array of glob patterns
|
||||
// forceCoverageMatch: [],
|
||||
|
||||
// A path to a module which exports an async function that is triggered once before all test suites
|
||||
// globalSetup: undefined,
|
||||
|
||||
// A path to a module which exports an async function that is triggered once after all test suites
|
||||
// globalTeardown: undefined,
|
||||
|
||||
// A set of global variables that need to be available in all test environments
|
||||
globals: {
|
||||
},
|
||||
|
||||
// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
|
||||
// maxWorkers: "50%",
|
||||
|
||||
// An array of directory names to be searched recursively up from the requiring module's location
|
||||
// moduleDirectories: [
|
||||
// "node_modules"
|
||||
// ],
|
||||
|
||||
// An array of file extensions your modules use
|
||||
// moduleFileExtensions: [
|
||||
// "js",
|
||||
// "json",
|
||||
// "jsx",
|
||||
// "ts",
|
||||
// "tsx",
|
||||
// "node"
|
||||
// ],
|
||||
|
||||
// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
|
||||
moduleNameMapper: {
|
||||
// Do not resolve .wasm.js to .wasm by the rule below
|
||||
'^(.+)\\.wasm\\.js$': '$1.wasm.js',
|
||||
// SWC converts @/foo/bar.js to `../../src/foo/bar.js`, and then this rule
|
||||
// converts it again to `../../src/foo/bar` which then can be resolved to
|
||||
// `.ts` files.
|
||||
// See https://github.com/swc-project/jest/issues/64#issuecomment-1029753225
|
||||
// TODO: Use `--allowImportingTsExtensions` on TypeScript 5.0 so that we can
|
||||
// directly import `.ts` files without this hack.
|
||||
'^((?:\\.{1,2}|[A-Z:])*/.*)\\.js$': '$1',
|
||||
},
|
||||
|
||||
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
|
||||
// modulePathIgnorePatterns: [],
|
||||
|
||||
// Activates notifications for test results
|
||||
// notify: false,
|
||||
|
||||
// An enum that specifies notification mode. Requires { notify: true }
|
||||
// notifyMode: "failure-change",
|
||||
|
||||
// A preset that is used as a base for Jest's configuration
|
||||
//preset: "ts-jest/presets/js-with-ts-esm",
|
||||
|
||||
// Run tests from one or more projects
|
||||
// projects: undefined,
|
||||
|
||||
// Use this configuration option to add custom reporters to Jest
|
||||
// reporters: undefined,
|
||||
|
||||
// Automatically reset mock state between every test
|
||||
// resetMocks: false,
|
||||
|
||||
// Reset the module registry before running each individual test
|
||||
// resetModules: false,
|
||||
|
||||
// A path to a custom resolver
|
||||
// resolver: './jest-resolver.cjs',
|
||||
|
||||
// Automatically restore mock state between every test
|
||||
restoreMocks: true,
|
||||
|
||||
// The root directory that Jest should scan for tests and modules within
|
||||
// rootDir: undefined,
|
||||
|
||||
// A list of paths to directories that Jest should use to search for files in
|
||||
roots: [
|
||||
"<rootDir>"
|
||||
],
|
||||
|
||||
// Allows you to use a custom runner instead of Jest's default test runner
|
||||
// runner: "jest-runner",
|
||||
|
||||
// The paths to modules that run some code to configure or set up the testing environment before each test
|
||||
// setupFiles: [],
|
||||
|
||||
// A list of paths to modules that run some code to configure or set up the testing framework before each test
|
||||
// setupFilesAfterEnv: [],
|
||||
|
||||
// The number of seconds after which a test is considered as slow and reported as such in the results.
|
||||
// slowTestThreshold: 5,
|
||||
|
||||
// A list of paths to snapshot serializer modules Jest should use for snapshot testing
|
||||
// snapshotSerializers: [],
|
||||
|
||||
// The test environment that will be used for testing
|
||||
testEnvironment: "node",
|
||||
|
||||
// Options that will be passed to the testEnvironment
|
||||
// testEnvironmentOptions: {},
|
||||
|
||||
// Adds a location field to test results
|
||||
// testLocationInResults: false,
|
||||
|
||||
// The glob patterns Jest uses to detect test files
|
||||
testMatch: [
|
||||
"<rootDir>/test/unit/**/*.ts",
|
||||
"<rootDir>/src/**/*.test.ts",
|
||||
],
|
||||
|
||||
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
|
||||
// testPathIgnorePatterns: [
|
||||
// "\\\\node_modules\\\\"
|
||||
// ],
|
||||
|
||||
// The regexp pattern or array of patterns that Jest uses to detect test files
|
||||
// testRegex: [],
|
||||
|
||||
// This option allows the use of a custom results processor
|
||||
// testResultsProcessor: undefined,
|
||||
|
||||
// This option allows use of a custom test runner
|
||||
// testRunner: "jasmine2",
|
||||
|
||||
// This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
|
||||
// testURL: "http://localhost",
|
||||
|
||||
// Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
|
||||
// timers: "real",
|
||||
|
||||
// A map from regular expressions to paths to transformers
|
||||
transform: {
|
||||
"^.+\\.(t|j)sx?$": ["@swc/jest"],
|
||||
},
|
||||
|
||||
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
|
||||
// transformIgnorePatterns: [
|
||||
// "\\\\node_modules\\\\",
|
||||
// "\\.pnp\\.[^\\\\]+$"
|
||||
// ],
|
||||
|
||||
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
|
||||
// unmockedModulePathPatterns: undefined,
|
||||
|
||||
// Indicates whether each individual test should be reported during the run
|
||||
// verbose: undefined,
|
||||
|
||||
// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
|
||||
// watchPathIgnorePatterns: [],
|
||||
|
||||
// Whether to use watchman for file crawling
|
||||
// watchman: true,
|
||||
|
||||
extensionsToTreatAsEsm: ['.ts', '.tsx'],
|
||||
|
||||
testTimeout: 60000,
|
||||
|
||||
// Let Jest kill the test worker whenever it grows too much
|
||||
// (It seems there's a known memory leak issue in Node.js' vm.Script used by Jest)
|
||||
// https://github.com/facebook/jest/issues/11956
|
||||
maxWorkers: 1, // Make it use worker (that can be killed and restarted)
|
||||
logHeapUsage: true, // To debug when out-of-memory happens on CI
|
||||
workerIdleMemoryLimit: '1GiB', // Limit the worker to 1GB (GitHub Workflows dies at 2GB)
|
||||
|
||||
maxConcurrency: 32,
|
||||
};
|
||||
15
packages/backend/jest.config.e2e.cjs
Normal file
15
packages/backend/jest.config.e2e.cjs
Normal 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",
|
||||
],
|
||||
};
|
||||
13
packages/backend/jest.config.fed.cjs
Normal file
13
packages/backend/jest.config.fed.cjs
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* For a detailed explanation regarding each configuration property and type check, visit:
|
||||
* https://jestjs.io/docs/en/configuration.html
|
||||
*/
|
||||
|
||||
const base = require('./jest.config.cjs');
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
testMatch: [
|
||||
'<rootDir>/test-federation/test/**/*.test.ts',
|
||||
],
|
||||
};
|
||||
15
packages/backend/jest.config.unit.cjs
Normal file
15
packages/backend/jest.config.unit.cjs
Normal 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>/test/jest.setup.unit.cjs",
|
||||
testMatch: [
|
||||
"<rootDir>/test/unit/**/*.ts",
|
||||
"<rootDir>/src/**/*.test.ts",
|
||||
],
|
||||
};
|
||||
31
packages/backend/jest.js
Normal file
31
packages/backend/jest.js
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env node
|
||||
import child_process from 'node:child_process';
|
||||
import path from 'node:path';
|
||||
import url from 'node:url';
|
||||
|
||||
import semver from 'semver';
|
||||
|
||||
const __filename = url.fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const args = [];
|
||||
args.push(...[
|
||||
...semver.satisfies(process.version, '^20.17.0 || ^22.0.0 || ^24.10.0') ? ['--no-experimental-require-module'] : [],
|
||||
'--experimental-vm-modules',
|
||||
'--experimental-import-meta-resolve',
|
||||
path.join(__dirname, 'node_modules/jest/bin/jest.js'),
|
||||
...process.argv.slice(2),
|
||||
]);
|
||||
|
||||
const child = child_process.spawn(process.execPath, args, { stdio: 'inherit' });
|
||||
child.on('error', (err) => {
|
||||
console.error('Failed to start Jest:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
child.on('exit', (code, signal) => {
|
||||
if (code === null) {
|
||||
process.exit(128 + signal);
|
||||
} else {
|
||||
process.exit(code);
|
||||
}
|
||||
});
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export class AddCategoryToAvatarDecorations1766652173085 {
|
||||
name = 'AddCategoryToAvatarDecorations1766652173085';
|
||||
|
||||
/**
|
||||
* @param {QueryRunner} queryRunner
|
||||
*/
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query('ALTER TABLE "avatar_decoration" ADD "category" character varying(128)');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {QueryRunner} queryRunner
|
||||
*/
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query('ALTER TABLE "avatar_decoration" DROP COLUMN "category"');
|
||||
}
|
||||
};
|
||||
36
packages/backend/migration/1769664628306-sp-reactions.js
Normal file
36
packages/backend/migration/1769664628306-sp-reactions.js
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export class SpReactions1769664628306 {
|
||||
name = 'SpReactions1769664628306'
|
||||
|
||||
/**
|
||||
* @param {QueryRunner} queryRunner
|
||||
*/
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`CREATE TABLE "note_sp_reaction" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "noteId" character varying(32) NOT NULL, "reaction" character varying(260) NOT NULL, "noteUserId" character varying(32) NOT NULL, CONSTRAINT "PK_11fd5ecdd9bb91517edfcf890d9" PRIMARY KEY ("id")); COMMENT ON COLUMN "note_sp_reaction"."noteUserId" IS '[Denormalized]'`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_3463a48b09fa41e1826ebd9f58" ON "note_sp_reaction" ("userId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_bfe4caa46cc0526bc2932d6dbe" ON "note_sp_reaction" ("noteId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_8be6eb3f4edc9940a3f8142669" ON "note_sp_reaction" ("noteUserId") `);
|
||||
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_b5f210b20bd987fe8584c85d33" ON "note_sp_reaction" ("userId", "noteId") `);
|
||||
await queryRunner.query(`ALTER TABLE "meta" ADD "enableSpReaction" boolean NOT NULL DEFAULT false`);
|
||||
await queryRunner.query(`ALTER TABLE "note_sp_reaction" ADD CONSTRAINT "FK_3463a48b09fa41e1826ebd9f585" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "note_sp_reaction" ADD CONSTRAINT "FK_bfe4caa46cc0526bc2932d6dbed" FOREIGN KEY ("noteId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {QueryRunner} queryRunner
|
||||
*/
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "note_sp_reaction" DROP CONSTRAINT "FK_bfe4caa46cc0526bc2932d6dbed"`);
|
||||
await queryRunner.query(`ALTER TABLE "note_sp_reaction" DROP CONSTRAINT "FK_3463a48b09fa41e1826ebd9f585"`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableSpReaction"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_b5f210b20bd987fe8584c85d33"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_8be6eb3f4edc9940a3f8142669"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_bfe4caa46cc0526bc2932d6dbe"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_3463a48b09fa41e1826ebd9f58"`);
|
||||
await queryRunner.query(`DROP TABLE "note_sp_reaction"`);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
import { loadConfig } from './built/config.js';
|
||||
import { entities } from './built/postgres.js';
|
||||
import { loadConfig } from './src-js/config.js';
|
||||
import { entities } from './src-js/postgres.js';
|
||||
|
||||
const isConcurrentIndexMigrationEnabled = process.env.MISSKEY_MIGRATION_CREATE_INDEX_CONCURRENTLY === '1';
|
||||
|
||||
|
||||
@@ -7,33 +7,51 @@
|
||||
"node": "^22.15.0 || ^24.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "pnpm compile-config && node ./built/entry.js",
|
||||
"start:inspect": "pnpm compile-config && node --inspect ./built/entry.js",
|
||||
"start:test": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./built/entry.js",
|
||||
"start": "pnpm compile-config && node ./built/boot/entry.js",
|
||||
"start:inspect": "pnpm compile-config && node --inspect ./built/boot/entry.js",
|
||||
"start:test": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./built/boot/entry.js",
|
||||
"migrate": "pnpm compile-config && pnpm typeorm migration:run -d ormconfig.js",
|
||||
"revert": "pnpm compile-config && pnpm typeorm migration:revert -d ormconfig.js",
|
||||
"cli": "pnpm compile-config && node ./built/cli.js",
|
||||
"cli": "pnpm compile-config && node ./src-js/boot/cli.js",
|
||||
"check:connect": "pnpm compile-config && node ./scripts/check_connect.js",
|
||||
"compile-config": "node ./scripts/compile_config.js",
|
||||
"build": "rolldown -c",
|
||||
"build:unit": "rolldown -c --sourcemap",
|
||||
"build:e2e": "rolldown -c --e2e",
|
||||
"build": "swc src -d src-js -D --strip-leading-paths && node ./build.js",
|
||||
"build:test": "swc test-server -d built-test -D --config-file test-server/.swcrc --strip-leading-paths",
|
||||
"watch:swc": "swc src -d built -D -w --strip-leading-paths",
|
||||
"build:tsc": "tsgo -p tsconfig.json && tsc-alias -p tsconfig.json",
|
||||
"watch": "pnpm compile-config && node ./scripts/watch.mjs",
|
||||
"restart": "pnpm build && pnpm start",
|
||||
"dev": "pnpm compile-config && rolldown -c --watch",
|
||||
"dev": "pnpm compile-config && node ./scripts/dev.mjs",
|
||||
"typecheck": "tsgo --noEmit && tsgo -p test --noEmit && tsgo -p test-federation --noEmit",
|
||||
"eslint": "eslint --quiet \"{src,test-federation}/**/*.ts\"",
|
||||
"lint": "pnpm typecheck && pnpm eslint",
|
||||
"test": "pnpm build:unit && cross-env NODE_ENV=test pnpm compile-config && vitest --config vitest.config.unit.ts",
|
||||
"test:e2e": "pnpm build:e2e && cross-env NODE_ENV=test pnpm compile-config && vitest --config vitest.config.e2e.ts",
|
||||
"test:fed": "cross-env NODE_ENV=test pnpm compile-config && vitest --config vitest.config.fed.ts",
|
||||
"test-and-coverage": "pnpm build:unit && cross-env NODE_ENV=test pnpm compile-config && vitest --coverage --config vitest.config.unit.ts",
|
||||
"test-and-coverage:e2e": "pnpm build:e2e && cross-env NODE_ENV=test pnpm compile-config && vitest --coverage --config vitest.config.e2e.ts",
|
||||
"jest": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./jest.js --forceExit --config jest.config.unit.cjs",
|
||||
"jest:e2e": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./jest.js --forceExit --config jest.config.e2e.cjs",
|
||||
"jest:fed": "pnpm compile-config && node ./jest.js --forceExit --config jest.config.fed.cjs",
|
||||
"jest-and-coverage": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./jest.js --coverage --forceExit --config jest.config.unit.cjs",
|
||||
"jest-and-coverage:e2e": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./jest.js --coverage --forceExit --config jest.config.e2e.cjs",
|
||||
"jest-clear": "cross-env NODE_ENV=test pnpm compile-config && cross-env NODE_ENV=test node ./jest.js --clearCache",
|
||||
"test": "pnpm jest",
|
||||
"test:e2e": "pnpm build && pnpm build:test && pnpm jest:e2e",
|
||||
"test:fed": "pnpm jest:fed",
|
||||
"test-and-coverage": "pnpm jest-and-coverage",
|
||||
"test-and-coverage:e2e": "pnpm build && pnpm build:test && pnpm jest-and-coverage:e2e",
|
||||
"check-migrations": "node scripts/check_migrations_clean.js",
|
||||
"generate-api-json": "pnpm compile-config && node ./scripts/generate_api_json.js"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-android-arm64": "1.3.11",
|
||||
"@swc/core-darwin-arm64": "1.15.8",
|
||||
"@swc/core-darwin-x64": "1.15.8",
|
||||
"@swc/core-freebsd-x64": "1.3.11",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.15.8",
|
||||
"@swc/core-linux-arm64-gnu": "1.15.8",
|
||||
"@swc/core-linux-arm64-musl": "1.15.8",
|
||||
"@swc/core-linux-x64-gnu": "1.15.8",
|
||||
"@swc/core-linux-x64-musl": "1.15.8",
|
||||
"@swc/core-win32-arm64-msvc": "1.15.8",
|
||||
"@swc/core-win32-ia32-msvc": "1.15.8",
|
||||
"@swc/core-win32-x64-msvc": "1.15.8",
|
||||
"@tensorflow/tfjs": "4.22.0",
|
||||
"@tensorflow/tfjs-node": "4.22.0",
|
||||
"bufferutil": "4.1.0",
|
||||
@@ -53,99 +71,100 @@
|
||||
"utf-8-validate": "6.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.1030.0",
|
||||
"@aws-sdk/lib-storage": "3.1030.0",
|
||||
"@aws-sdk/client-s3": "3.970.0",
|
||||
"@aws-sdk/lib-storage": "3.970.0",
|
||||
"@discordapp/twemoji": "16.0.1",
|
||||
"@fastify/accepts": "5.0.4",
|
||||
"@fastify/cors": "11.2.0",
|
||||
"@fastify/express": "4.0.5",
|
||||
"@fastify/http-proxy": "11.4.4",
|
||||
"@fastify/multipart": "10.0.0",
|
||||
"@fastify/static": "9.1.3",
|
||||
"@kitajs/html": "4.2.13",
|
||||
"@fastify/express": "4.0.4",
|
||||
"@fastify/http-proxy": "11.4.1",
|
||||
"@fastify/multipart": "9.3.0",
|
||||
"@fastify/static": "8.3.0",
|
||||
"@kitajs/html": "4.2.11",
|
||||
"@misskey-dev/sharp-read-bmp": "1.2.0",
|
||||
"@misskey-dev/summaly": "5.2.5",
|
||||
"@napi-rs/canvas": "0.1.97",
|
||||
"@nestjs/common": "11.1.19",
|
||||
"@nestjs/core": "11.1.19",
|
||||
"@nestjs/testing": "11.1.19",
|
||||
"@oxc-project/runtime": "0.125.0",
|
||||
"@napi-rs/canvas": "0.1.88",
|
||||
"@nestjs/common": "11.1.12",
|
||||
"@nestjs/core": "11.1.12",
|
||||
"@nestjs/testing": "11.1.12",
|
||||
"@peertube/http-signature": "1.7.0",
|
||||
"@sentry/node": "10.48.0",
|
||||
"@sentry/profiling-node": "10.48.0",
|
||||
"@simplewebauthn/server": "13.3.0",
|
||||
"@sinonjs/fake-timers": "15.3.2",
|
||||
"@smithy/node-http-handler": "4.5.2",
|
||||
"@sentry/node": "10.34.0",
|
||||
"@sentry/profiling-node": "10.34.0",
|
||||
"@simplewebauthn/server": "13.2.2",
|
||||
"@sinonjs/fake-timers": "15.1.0",
|
||||
"@smithy/node-http-handler": "4.4.8",
|
||||
"@swc/cli": "0.7.10",
|
||||
"@swc/core": "1.15.8",
|
||||
"@twemoji/parser": "16.0.0",
|
||||
"accepts": "1.3.8",
|
||||
"ajv": "8.18.0",
|
||||
"ajv": "8.17.1",
|
||||
"archiver": "7.0.1",
|
||||
"async-mutex": "0.5.0",
|
||||
"bcryptjs": "3.0.3",
|
||||
"blurhash": "2.0.5",
|
||||
"body-parser": "2.2.2",
|
||||
"bullmq": "5.73.5",
|
||||
"bullmq": "5.66.5",
|
||||
"cacheable-lookup": "7.0.0",
|
||||
"chalk": "5.6.2",
|
||||
"chalk-template": "1.1.2",
|
||||
"chokidar": "5.0.0",
|
||||
"color-convert": "3.1.3",
|
||||
"content-disposition": "1.1.0",
|
||||
"content-disposition": "1.0.1",
|
||||
"date-fns": "4.1.0",
|
||||
"deep-email-validator": "0.1.21",
|
||||
"fastify": "5.8.5",
|
||||
"fastify": "5.7.1",
|
||||
"fastify-raw-body": "5.0.0",
|
||||
"feed": "5.2.0",
|
||||
"file-type": "22.0.1",
|
||||
"file-type": "21.3.0",
|
||||
"fluent-ffmpeg": "2.1.3",
|
||||
"form-data": "4.0.5",
|
||||
"got": "14.6.6",
|
||||
"hpagent": "1.2.0",
|
||||
"http-link-header": "1.1.3",
|
||||
"i18n": "workspace:*",
|
||||
"ioredis": "5.10.1",
|
||||
"ioredis": "5.9.2",
|
||||
"ip-cidr": "4.0.2",
|
||||
"ipaddr.js": "2.3.0",
|
||||
"is-svg": "6.1.0",
|
||||
"json5": "2.2.3",
|
||||
"jsonld": "9.0.0",
|
||||
"juice": "11.1.1",
|
||||
"meilisearch": "0.57.0",
|
||||
"juice": "11.1.0",
|
||||
"meilisearch": "0.55.0",
|
||||
"mfm-js": "0.25.0",
|
||||
"mime-types": "3.0.2",
|
||||
"misskey-js": "workspace:*",
|
||||
"misskey-reversi": "workspace:*",
|
||||
"ms": "3.0.0-canary.202508261828",
|
||||
"nanoid": "5.1.7",
|
||||
"nanoid": "5.1.6",
|
||||
"nested-property": "4.0.0",
|
||||
"node-fetch": "3.3.2",
|
||||
"node-html-parser": "7.1.0",
|
||||
"nodemailer": "8.0.5",
|
||||
"nsfwjs": "4.3.0",
|
||||
"node-html-parser": "7.0.2",
|
||||
"nodemailer": "7.0.12",
|
||||
"nsfwjs": "4.2.0",
|
||||
"oauth2orize": "1.12.0",
|
||||
"oauth2orize-pkce": "0.1.2",
|
||||
"os-utils": "0.0.14",
|
||||
"otpauth": "9.5.0",
|
||||
"pg": "8.20.0",
|
||||
"pkce-challenge": "6.0.0",
|
||||
"otpauth": "9.4.1",
|
||||
"pg": "8.17.1",
|
||||
"pkce-challenge": "5.0.1",
|
||||
"probe-image-size": "7.2.3",
|
||||
"promise-limit": "2.7.0",
|
||||
"qrcode": "1.5.4",
|
||||
"random-seed": "0.3.0",
|
||||
"ratelimiter": "3.4.1",
|
||||
"re2": "1.24.0",
|
||||
"re2": "1.23.0",
|
||||
"reflect-metadata": "0.2.2",
|
||||
"rename": "1.0.4",
|
||||
"rss-parser": "3.13.0",
|
||||
"rxjs": "7.8.2",
|
||||
"sanitize-html": "2.17.3",
|
||||
"sanitize-html": "2.17.0",
|
||||
"secure-json-parse": "4.1.0",
|
||||
"semver": "7.7.4",
|
||||
"semver": "7.7.3",
|
||||
"sharp": "0.33.5",
|
||||
"slacc": "0.0.10",
|
||||
"strict-event-emitter-types": "2.0.0",
|
||||
"stringz": "2.1.0",
|
||||
"systeminformation": "5.31.5",
|
||||
"systeminformation": "5.30.5",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tmp": "0.2.5",
|
||||
"tsc-alias": "1.8.16",
|
||||
@@ -153,61 +172,62 @@
|
||||
"ulid": "3.0.2",
|
||||
"vary": "1.1.2",
|
||||
"web-push": "3.6.7",
|
||||
"ws": "8.20.0",
|
||||
"ws": "8.19.0",
|
||||
"xev": "3.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kitajs/ts-html-plugin": "4.1.4",
|
||||
"@nestjs/platform-express": "11.1.19",
|
||||
"@rollup/plugin-esm-shim": "0.1.8",
|
||||
"@sentry/vue": "10.48.0",
|
||||
"@jest/globals": "29.7.0",
|
||||
"@kitajs/ts-html-plugin": "4.1.3",
|
||||
"@nestjs/platform-express": "11.1.12",
|
||||
"@sentry/vue": "10.34.0",
|
||||
"@simplewebauthn/types": "12.0.0",
|
||||
"@swc/jest": "0.2.39",
|
||||
"@types/accepts": "1.3.7",
|
||||
"@types/archiver": "7.0.0",
|
||||
"@types/body-parser": "1.19.6",
|
||||
"@types/color-convert": "3.0.1",
|
||||
"@types/color-convert": "2.0.4",
|
||||
"@types/content-disposition": "0.5.9",
|
||||
"@types/fluent-ffmpeg": "2.1.28",
|
||||
"@types/http-link-header": "1.0.7",
|
||||
"@types/js-yaml": "4.0.9",
|
||||
"@types/jest": "29.5.14",
|
||||
"@types/jsonld": "1.5.15",
|
||||
"@types/mime-types": "3.0.1",
|
||||
"@types/ms": "2.1.0",
|
||||
"@types/node": "24.12.2",
|
||||
"@types/nodemailer": "8.0.0",
|
||||
"@types/node": "24.10.9",
|
||||
"@types/nodemailer": "7.0.5",
|
||||
"@types/oauth2orize": "1.11.5",
|
||||
"@types/oauth2orize-pkce": "0.1.2",
|
||||
"@types/pg": "8.20.0",
|
||||
"@types/pg": "8.16.0",
|
||||
"@types/qrcode": "1.5.6",
|
||||
"@types/random-seed": "0.3.5",
|
||||
"@types/ratelimiter": "3.4.6",
|
||||
"@types/rename": "1.0.7",
|
||||
"@types/sanitize-html": "2.16.1",
|
||||
"@types/sanitize-html": "2.16.0",
|
||||
"@types/semver": "7.7.1",
|
||||
"@types/simple-oauth2": "5.0.8",
|
||||
"@types/sinonjs__fake-timers": "15.0.1",
|
||||
"@types/supertest": "7.2.0",
|
||||
"@types/supertest": "6.0.3",
|
||||
"@types/tinycolor2": "1.4.6",
|
||||
"@types/tmp": "0.2.6",
|
||||
"@types/vary": "1.1.3",
|
||||
"@types/web-push": "3.6.4",
|
||||
"@types/ws": "8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.58.2",
|
||||
"@typescript-eslint/parser": "8.58.2",
|
||||
"@vitest/coverage-v8": "4.1.4",
|
||||
"@typescript-eslint/eslint-plugin": "8.53.0",
|
||||
"@typescript-eslint/parser": "8.53.0",
|
||||
"aws-sdk-client-mock": "4.1.0",
|
||||
"cbor": "10.0.12",
|
||||
"cbor": "10.0.11",
|
||||
"cross-env": "10.1.0",
|
||||
"esbuild-plugin-swc": "1.0.1",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"execa": "9.6.1",
|
||||
"fkill": "10.0.3",
|
||||
"jest": "29.7.0",
|
||||
"jest-mock": "29.7.0",
|
||||
"js-yaml": "4.1.1",
|
||||
"pid-port": "2.1.1",
|
||||
"rolldown": "1.0.0-rc.15",
|
||||
"nodemon": "3.1.11",
|
||||
"pid-port": "2.0.1",
|
||||
"simple-oauth2": "5.1.0",
|
||||
"supertest": "7.2.2",
|
||||
"vite": "8.0.8",
|
||||
"vitest": "4.1.4",
|
||||
"vitest-mock-extended": "4.0.0"
|
||||
"vite": "7.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
import { defineConfig } from 'rolldown';
|
||||
import type { Plugin, ExternalOption } from 'rolldown';
|
||||
import { execa, execaNode } from 'execa';
|
||||
import type { ResultPromise } from 'execa';
|
||||
import esmShim from '@rollup/plugin-esm-shim';
|
||||
|
||||
/**
|
||||
* Watchモード時にバックエンドの起動・停止制御を行うプラグイン
|
||||
*/
|
||||
function backendDevServerPlugin(): Plugin {
|
||||
let backendProcess: ResultPromise | null = null;
|
||||
|
||||
async function runBuildAssets() {
|
||||
await execa('pnpm', ['run', 'build-assets'], {
|
||||
cwd: '../../',
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
});
|
||||
}
|
||||
|
||||
async function killBackendProcess() {
|
||||
if (backendProcess) {
|
||||
backendProcess.catch(() => {}); // backendProcess.kill()によって発生する例外を無視するためにcatch()を呼び出す
|
||||
backendProcess.kill();
|
||||
await new Promise(resolve => backendProcess!.on('exit', resolve));
|
||||
backendProcess = null;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'backend-dev-server',
|
||||
async closeBundle() {
|
||||
await runBuildAssets();
|
||||
if (backendProcess) {
|
||||
await killBackendProcess();
|
||||
}
|
||||
backendProcess = execaNode('./built/entry.js', [], {
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
env: {
|
||||
NODE_ENV: 'development',
|
||||
},
|
||||
});
|
||||
},
|
||||
async watchChange() {
|
||||
if (backendProcess) {
|
||||
await killBackendProcess();
|
||||
await runBuildAssets();
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default defineConfig((args) => {
|
||||
const isWatchMode = args.watch != null && args.watch !== 'false';
|
||||
const isE2E = args.e2e != null && args.e2e !== 'false';
|
||||
|
||||
// 通常のビルド時にexternalとするモジュール
|
||||
const externalModules: ExternalOption = [
|
||||
/^slacc-.*/,
|
||||
'class-transformer',
|
||||
'class-validator',
|
||||
/^@sentry\/.*/,
|
||||
/^@sentry-internal\/.*/,
|
||||
'@nestjs/websockets/socket-module',
|
||||
'@nestjs/microservices/microservices-module',
|
||||
'@nestjs/microservices',
|
||||
/^@napi-rs\/.*/,
|
||||
'mock-aws-s3',
|
||||
'aws-sdk',
|
||||
'nock',
|
||||
'sharp',
|
||||
'jsdom',
|
||||
're2',
|
||||
'ipaddr.js',
|
||||
'oauth2orize',
|
||||
'file-type',
|
||||
];
|
||||
|
||||
if (isE2E) {
|
||||
return {
|
||||
input: './test-server/entry.ts',
|
||||
platform: 'node',
|
||||
tsconfig: './test-server/tsconfig.json',
|
||||
plugins: [
|
||||
esmShim(),
|
||||
],
|
||||
output: {
|
||||
keepNames: true,
|
||||
sourcemap: true,
|
||||
dir: './built-test',
|
||||
cleanDir: true,
|
||||
format: 'esm',
|
||||
},
|
||||
external: externalModules,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
input: [
|
||||
'./src/boot/entry.ts',
|
||||
'./src/boot/cli.ts',
|
||||
'./src/config.ts',
|
||||
'./src/postgres.ts',
|
||||
'./src/server/api/openapi/gen-spec.ts',
|
||||
],
|
||||
platform: 'node',
|
||||
tsconfig: true,
|
||||
plugins: [
|
||||
esmShim(),
|
||||
(isWatchMode ? backendDevServerPlugin() : undefined),
|
||||
],
|
||||
output: {
|
||||
keepNames: true,
|
||||
minify: !isWatchMode,
|
||||
sourcemap: isWatchMode,
|
||||
dir: './built',
|
||||
cleanDir: !isWatchMode,
|
||||
format: 'esm',
|
||||
},
|
||||
watch: {
|
||||
include: ['src/**/*.{ts,js,mjs,cjs,tsx,json}'],
|
||||
clearScreen: false,
|
||||
},
|
||||
// ビルドの高速化のために、watchモードのときは外部モジュールは全てバンドルしないようにする
|
||||
external: isWatchMode ? /^(?!@\/)[^.\/](?!:[\/\\])/ : externalModules,
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
|
||||
import Redis from 'ioredis';
|
||||
import { loadConfig } from '../built/config.js';
|
||||
import { createPostgresDataSource } from '../built/postgres.js';
|
||||
import { loadConfig } from '../src-js/config.js';
|
||||
import { createPostgresDataSource } from '../src-js/postgres.js';
|
||||
|
||||
const config = loadConfig();
|
||||
|
||||
|
||||
63
packages/backend/scripts/dev.mjs
Normal file
63
packages/backend/scripts/dev.mjs
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { execa, execaNode } from 'execa';
|
||||
|
||||
/** @type {import('execa').ExecaChildProcess | undefined} */
|
||||
let backendProcess;
|
||||
|
||||
async function execBuildAssets() {
|
||||
await execa('pnpm', ['run', 'build-assets'], {
|
||||
cwd: '../../',
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
})
|
||||
}
|
||||
|
||||
function execStart() {
|
||||
// pnpm run start を呼び出したいが、windowsだとプロセスグループ単位でのkillが出来ずゾンビプロセス化するので
|
||||
// 上記と同等の動きをするコマンドで子・孫プロセスを作らないようにしたい
|
||||
backendProcess = execaNode('./built/boot/entry.js', [], {
|
||||
stdout: process.stdout,
|
||||
stderr: process.stderr,
|
||||
env: {
|
||||
'NODE_ENV': 'development',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function killProc() {
|
||||
if (backendProcess) {
|
||||
backendProcess.catch(() => {}); // backendProcess.kill()によって発生する例外を無視するためにcatch()を呼び出す
|
||||
backendProcess.kill();
|
||||
await new Promise(resolve => backendProcess.on('exit', resolve));
|
||||
backendProcess = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
execaNode(
|
||||
'./node_modules/nodemon/bin/nodemon.js',
|
||||
[
|
||||
'-w', 'src',
|
||||
'-e', 'ts,js,mjs,cjs,tsx,json,pug',
|
||||
'--exec', 'pnpm', 'run', 'build',
|
||||
],
|
||||
{
|
||||
stdio: [process.stdin, process.stdout, process.stderr, 'ipc'],
|
||||
serialization: "json",
|
||||
})
|
||||
.on('message', async (message) => {
|
||||
if (message.type === 'exit') {
|
||||
// かならずbuild->build-assetsの順番で呼び出したいので、
|
||||
// 少々トリッキーだがnodemonからのexitイベントを利用してbuild-assets->startを行う。
|
||||
// pnpm restartをbuildが終わる前にbuild-assetsが動いてしまうので、バラバラに呼び出す必要がある
|
||||
|
||||
await killProc();
|
||||
await execBuildAssets();
|
||||
execStart();
|
||||
}
|
||||
})
|
||||
})();
|
||||
@@ -19,10 +19,10 @@ async function main() {
|
||||
}
|
||||
|
||||
/** @type {import('../src/config.js')} */
|
||||
const { loadConfig } = await import('../built/config.js');
|
||||
const { loadConfig } = await import('../src-js/config.js');
|
||||
|
||||
/** @type {import('../src/server/api/openapi/gen-spec.js')} */
|
||||
const { genOpenapiSpec } = await import('../built/gen-spec.js');
|
||||
const { genOpenapiSpec } = await import('../src-js/server/api/openapi/gen-spec.js');
|
||||
|
||||
const config = loadConfig();
|
||||
const spec = genOpenapiSpec(config, true);
|
||||
|
||||
@@ -55,7 +55,7 @@ async function getMemoryUsage(pid) {
|
||||
|
||||
async function measureMemory() {
|
||||
// Start the Misskey backend server using fork to enable IPC
|
||||
const serverProcess = fork(join(__dirname, '../built/entry.js'), ['expose-gc'], {
|
||||
const serverProcess = fork(join(__dirname, '../built/boot/entry.js'), ['expose-gc'], {
|
||||
cwd: join(__dirname, '..'),
|
||||
env: {
|
||||
...process.env,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Global, Inject, Module } from '@nestjs/common';
|
||||
import * as Redis from 'ioredis';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { Meilisearch } from 'meilisearch';
|
||||
import { MeiliSearch } from 'meilisearch';
|
||||
import { MiMeta } from '@/models/Meta.js';
|
||||
import { DI } from './di-symbols.js';
|
||||
import { Config, loadConfig } from './config.js';
|
||||
@@ -40,10 +40,10 @@ const $meilisearch: Provider = {
|
||||
useFactory: (config: Config) => {
|
||||
if (config.fulltextSearch?.provider === 'meilisearch') {
|
||||
if (!config.meilisearch) {
|
||||
throw new Error('Meilisearch is enabled but no configuration is provided');
|
||||
throw new Error('MeiliSearch is enabled but no configuration is provided');
|
||||
}
|
||||
|
||||
return new Meilisearch({
|
||||
return new MeiliSearch({
|
||||
host: `${config.meilisearch.ssl ? 'https' : 'http'}://${config.meilisearch.host}:${config.meilisearch.port}`,
|
||||
apiKey: config.meilisearch.apiKey,
|
||||
});
|
||||
|
||||
@@ -4,12 +4,16 @@
|
||||
*/
|
||||
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { ChartManagementService } from '@/core/chart/ChartManagementService.js';
|
||||
import { QueueProcessorService } from '@/queue/QueueProcessorService.js';
|
||||
import { NestLogger } from '@/NestLogger.js';
|
||||
import { QueueProcessorModule } from '@/queue/QueueProcessorModule.js';
|
||||
import { QueueStatsService } from '@/daemons/QueueStatsService.js';
|
||||
import { ServerStatsService } from '@/daemons/ServerStatsService.js';
|
||||
import { ServerService } from '@/server/ServerService.js';
|
||||
import { MainModule } from '@/MainModule.js';
|
||||
|
||||
export async function server() {
|
||||
const { MainModule } = await import('../MainModule.js');
|
||||
const { ServerService } = await import('../server/ServerService.js');
|
||||
|
||||
const app = await NestFactory.createApplicationContext(MainModule, {
|
||||
logger: new NestLogger(),
|
||||
});
|
||||
@@ -18,10 +22,6 @@ export async function server() {
|
||||
await serverService.launch();
|
||||
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
const { ChartManagementService } = await import('../core/chart/ChartManagementService.js');
|
||||
const { QueueStatsService } = await import('../daemons/QueueStatsService.js');
|
||||
const { ServerStatsService } = await import('../daemons/ServerStatsService.js');
|
||||
|
||||
app.get(ChartManagementService).start();
|
||||
app.get(QueueStatsService).start();
|
||||
app.get(ServerStatsService).start();
|
||||
@@ -31,10 +31,6 @@ export async function server() {
|
||||
}
|
||||
|
||||
export async function jobQueue() {
|
||||
const { QueueProcessorModule } = await import('../queue/QueueProcessorModule.js');
|
||||
const { QueueProcessorService } = await import('../queue/QueueProcessorService.js');
|
||||
const { ChartManagementService } = await import('../core/chart/ChartManagementService.js');
|
||||
|
||||
const jobQueue = await NestFactory.createApplicationContext(QueueProcessorModule, {
|
||||
logger: new NestLogger(),
|
||||
});
|
||||
|
||||
@@ -13,6 +13,8 @@ import chalk from 'chalk';
|
||||
import Xev from 'xev';
|
||||
import Logger from '@/logger.js';
|
||||
import { envOption } from '../env.js';
|
||||
import { masterMain } from './master.js';
|
||||
import { workerMain } from './worker.js';
|
||||
import { readyRef } from './ready.js';
|
||||
|
||||
import 'reflect-metadata';
|
||||
@@ -69,12 +71,10 @@ process.on('exit', code => {
|
||||
if (!envOption.disableClustering) {
|
||||
if (cluster.isPrimary) {
|
||||
logger.info(`Start main process... pid: ${process.pid}`);
|
||||
const { masterMain } = await import('./master.js');
|
||||
await masterMain();
|
||||
ev.mount();
|
||||
} else if (cluster.isWorker) {
|
||||
logger.info(`Start worker process... pid: ${process.pid}`);
|
||||
const { workerMain } = await import('./worker.js');
|
||||
await workerMain();
|
||||
} else {
|
||||
throw new Error('Unknown process type');
|
||||
@@ -82,7 +82,6 @@ if (!envOption.disableClustering) {
|
||||
} else {
|
||||
// 非clusterの場合はMasterのみが起動するため、Workerの処理は行わない(cluster.isWorker === trueの状態でこのブロックに来ることはない)
|
||||
logger.info(`Start main process... pid: ${process.pid}`);
|
||||
const { masterMain } = await import('./master.js');
|
||||
await masterMain();
|
||||
ev.mount();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { type FastifyServerOptions } from 'fastify';
|
||||
import type * as Sentry from '@sentry/node';
|
||||
import type * as SentryVue from '@sentry/vue';
|
||||
import type { RedisOptions } from 'ioredis';
|
||||
import type { ManifestChunk } from 'vite';
|
||||
|
||||
type RedisOptionsSource = Partial<RedisOptions> & {
|
||||
host: string;
|
||||
@@ -188,9 +189,10 @@ export type Config = {
|
||||
authUrl: string;
|
||||
driveUrl: string;
|
||||
userAgent: string;
|
||||
frontendEntry: ManifestChunk;
|
||||
frontendManifestExists: boolean;
|
||||
frontendEmbedEntry: ManifestChunk;
|
||||
frontendEmbedManifestExists: boolean;
|
||||
rootDir: string;
|
||||
mediaProxy: string;
|
||||
externalMediaProxyEnabled: boolean;
|
||||
videoThumbnailGenerator: string | null;
|
||||
@@ -248,6 +250,12 @@ export function loadConfig(): Config {
|
||||
|
||||
const frontendManifestExists = fs.existsSync(resolve(projectBuiltDir, '_frontend_vite_/manifest.json'));
|
||||
const frontendEmbedManifestExists = fs.existsSync(resolve(projectBuiltDir, '_frontend_embed_vite_/manifest.json'));
|
||||
const frontendManifest = frontendManifestExists ?
|
||||
JSON.parse(fs.readFileSync(resolve(projectBuiltDir, '_frontend_vite_/manifest.json'), 'utf-8'))
|
||||
: { 'src/_boot_.ts': { file: null } };
|
||||
const frontendEmbedManifest = frontendEmbedManifestExists ?
|
||||
JSON.parse(fs.readFileSync(resolve(projectBuiltDir, '_frontend_embed_vite_/manifest.json'), 'utf-8'))
|
||||
: { 'src/boot.ts': { file: null } };
|
||||
|
||||
const config = JSON.parse(fs.readFileSync(compiledConfigFilePath, 'utf-8')) as Source;
|
||||
|
||||
@@ -329,9 +337,10 @@ export function loadConfig(): Config {
|
||||
config.videoThumbnailGenerator.endsWith('/') ? config.videoThumbnailGenerator.substring(0, config.videoThumbnailGenerator.length - 1) : config.videoThumbnailGenerator
|
||||
: null,
|
||||
userAgent: `Misskey/${version} (${config.url})`,
|
||||
frontendEntry: frontendManifest['src/_boot_.ts'],
|
||||
frontendManifestExists: frontendManifestExists,
|
||||
frontendEmbedEntry: frontendEmbedManifest['src/boot.ts'],
|
||||
frontendEmbedManifestExists: frontendEmbedManifestExists,
|
||||
rootDir,
|
||||
perChannelMaxNoteCacheCount: config.perChannelMaxNoteCacheCount ?? 1000,
|
||||
perUserNotificationsMaxCount: config.perUserNotificationsMaxCount ?? 500,
|
||||
deactivateAntennaThreshold: config.deactivateAntennaThreshold ?? (1000 * 60 * 60 * 24 * 7),
|
||||
|
||||
@@ -4,31 +4,27 @@
|
||||
*/
|
||||
|
||||
import * as fs from 'node:fs';
|
||||
import { pathToFileURL } from 'node:url';
|
||||
import { resolve } from 'node:path';
|
||||
import { Injectable, Inject } from '@nestjs/common';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname } from 'node:path';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Mutex } from 'async-mutex';
|
||||
import fetch from 'node-fetch';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import type { NSFWJS, PredictionType } from 'nsfwjs/core';
|
||||
import type { NSFWJS, PredictionType } from 'nsfwjs';
|
||||
|
||||
const _filename = fileURLToPath(import.meta.url);
|
||||
const _dirname = dirname(_filename);
|
||||
|
||||
const REQUIRED_CPU_FLAGS_X64 = ['avx2', 'fma'];
|
||||
let isSupportedCpu: undefined | boolean = undefined;
|
||||
|
||||
@Injectable()
|
||||
export class AiService {
|
||||
private readonly modelDir: string;
|
||||
private model: NSFWJS;
|
||||
private modelLoadMutex: Mutex = new Mutex();
|
||||
|
||||
constructor(
|
||||
@Inject(DI.config)
|
||||
private config: Config,
|
||||
) {
|
||||
const md = resolve(this.config.rootDir, 'packages/backend/nsfw-model');
|
||||
this.modelDir = md.endsWith('/') ? md : md + '/';
|
||||
}
|
||||
|
||||
@bindThis
|
||||
@@ -47,10 +43,10 @@ export class AiService {
|
||||
tf.env().global.fetch = fetch;
|
||||
|
||||
if (this.model == null) {
|
||||
const nsfw = await import('nsfwjs/core');
|
||||
const nsfw = await import('nsfwjs');
|
||||
await this.modelLoadMutex.runExclusive(async () => {
|
||||
if (this.model == null) {
|
||||
this.model = await nsfw.load(pathToFileURL(this.modelDir).toString(), { size: 299 });
|
||||
this.model = await nsfw.load(`file://${_dirname}/../../nsfw-model/`, { size: 299 });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -129,9 +129,6 @@ export interface NoteEventTypes {
|
||||
type NoteStreamEventTypes = {
|
||||
[key in keyof NoteEventTypes]: {
|
||||
id: MiNote['id'];
|
||||
userId: MiNote['userId'];
|
||||
visibility: MiNote['visibility'];
|
||||
visibleUserIds: MiNote['visibleUserIds'];
|
||||
body: NoteEventTypes[key];
|
||||
};
|
||||
};
|
||||
@@ -381,12 +378,9 @@ export class GlobalEventService {
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public publishNoteStream<K extends keyof NoteEventTypes>(note: MiNote, type: K, value?: NoteEventTypes[K]): void {
|
||||
this.publish(`noteStream:${note.id}`, type, {
|
||||
id: note.id,
|
||||
userId: note.userId,
|
||||
visibility: note.visibility,
|
||||
visibleUserIds: note.visibleUserIds,
|
||||
public publishNoteStream<K extends keyof NoteEventTypes>(noteId: MiNote['id'], type: K, value?: NoteEventTypes[K]): void {
|
||||
this.publish(`noteStream:${noteId}`, type, {
|
||||
id: noteId,
|
||||
body: value,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,25 +5,29 @@
|
||||
|
||||
import * as fs from 'node:fs';
|
||||
import * as Path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname } from 'node:path';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { Config } from '@/config.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
|
||||
const _filename = fileURLToPath(import.meta.url);
|
||||
const _dirname = dirname(_filename);
|
||||
|
||||
const path = Path.resolve(_dirname, '../../../../files');
|
||||
|
||||
@Injectable()
|
||||
export class InternalStorageService {
|
||||
private readonly path: string;
|
||||
|
||||
constructor(
|
||||
@Inject(DI.config)
|
||||
private config: Config,
|
||||
) {
|
||||
this.path = Path.resolve(this.config.rootDir, 'files');
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public resolvePath(key: string) {
|
||||
return Path.resolve(this.path, key);
|
||||
return Path.resolve(path, key);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
@@ -33,14 +37,14 @@ export class InternalStorageService {
|
||||
|
||||
@bindThis
|
||||
public saveFromPath(key: string, srcPath: string) {
|
||||
fs.mkdirSync(this.path, { recursive: true });
|
||||
fs.mkdirSync(path, { recursive: true });
|
||||
fs.copyFileSync(srcPath, this.resolvePath(key));
|
||||
return `${this.config.url}/files/${key}`;
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public saveFromBuffer(key: string, data: Buffer) {
|
||||
fs.mkdirSync(this.path, { recursive: true });
|
||||
fs.mkdirSync(path, { recursive: true });
|
||||
fs.writeFileSync(this.resolvePath(key), data);
|
||||
return `${this.config.url}/files/${key}`;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import Logger from '@/logger.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { Keyword } from 'color-convert';
|
||||
import type { KEYWORD } from 'color-convert/conversions.js';
|
||||
|
||||
@Injectable()
|
||||
export class LoggerService {
|
||||
@@ -15,7 +15,7 @@ export class LoggerService {
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public getLogger(domain: string, color?: Keyword | undefined) {
|
||||
public getLogger(domain: string, color?: KEYWORD | undefined) {
|
||||
return new Logger(domain, color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,21 +63,20 @@ type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
|
||||
class NotificationManager {
|
||||
private notifier: { id: MiUser['id']; };
|
||||
private note: MiNote;
|
||||
private queue: Map<MiLocalUser['id'], {
|
||||
private queue: {
|
||||
target: MiLocalUser['id'];
|
||||
reason: NotificationType;
|
||||
}>;
|
||||
}[];
|
||||
|
||||
constructor(
|
||||
private mutingsRepository: MutingsRepository,
|
||||
private notificationService: NotificationService,
|
||||
private followingsRepository: FollowingsRepository,
|
||||
notifier: { id: MiUser['id']; },
|
||||
note: MiNote,
|
||||
) {
|
||||
this.notifier = notifier;
|
||||
this.note = note;
|
||||
this.queue = new Map();
|
||||
this.queue = [];
|
||||
}
|
||||
|
||||
@bindThis
|
||||
@@ -85,7 +84,7 @@ class NotificationManager {
|
||||
// 自分自身へは通知しない
|
||||
if (this.notifier.id === notifiee) return;
|
||||
|
||||
const exist = this.queue.get(notifiee);
|
||||
const exist = this.queue.find(x => x.target === notifiee);
|
||||
|
||||
if (exist) {
|
||||
// 「メンションされているかつ返信されている」場合は、メンションとしての通知ではなく返信としての通知にする
|
||||
@@ -93,7 +92,7 @@ class NotificationManager {
|
||||
exist.reason = reason;
|
||||
}
|
||||
} else {
|
||||
this.queue.set(notifiee, {
|
||||
this.queue.push({
|
||||
reason: reason,
|
||||
target: notifiee,
|
||||
});
|
||||
@@ -102,49 +101,7 @@ class NotificationManager {
|
||||
|
||||
@bindThis
|
||||
public async notify() {
|
||||
if (this.queue.size === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let visibleUserIds: Set<MiUser['id']> | null;
|
||||
|
||||
switch (this.note.visibility) {
|
||||
case 'public':
|
||||
case 'home':
|
||||
visibleUserIds = null;
|
||||
break;
|
||||
|
||||
case 'specified':
|
||||
visibleUserIds = new Set(this.note.visibleUserIds);
|
||||
break;
|
||||
|
||||
// TODO: フォロワー限定ノートにフォロワーではない人がメンションされた場合通知されるのが正しい挙動なのか確認(一部に挙動の不一致がありそう)。現状は通知されるためフィルタしない
|
||||
// case 'followers': {
|
||||
// const targetUserIds = this.queue.map(x => x.target);
|
||||
// const followers = await this.followingsRepository.find({
|
||||
// where: {
|
||||
// followeeId: this.note.userId,
|
||||
// followerId: In(targetUserIds),
|
||||
// isFollowerHibernated: false,
|
||||
// },
|
||||
// select: ['followerId'],
|
||||
// });
|
||||
// visibleUserIds = new Set(followers.map(f => f.followerId));
|
||||
// break;
|
||||
// }
|
||||
|
||||
default:
|
||||
visibleUserIds = new Set();
|
||||
break;
|
||||
}
|
||||
|
||||
for (const x of this.queue.values()) {
|
||||
const isVisibleToTarget = visibleUserIds === null || visibleUserIds.has(x.target);
|
||||
|
||||
if (!isVisibleToTarget) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const x of this.queue) {
|
||||
if (x.reason === 'renote') {
|
||||
this.notificationService.createNotification(x.target, 'renote', {
|
||||
noteId: this.note.id,
|
||||
@@ -815,7 +772,7 @@ export class NoteCreateService implements OnApplicationShutdown {
|
||||
|
||||
this.webhookService.enqueueUserWebhook(user.id, 'note', { note: noteObj });
|
||||
|
||||
const nm = new NotificationManager(this.mutingsRepository, this.notificationService, this.followingsRepository, user, note);
|
||||
const nm = new NotificationManager(this.mutingsRepository, this.notificationService, user, note);
|
||||
|
||||
await this.createMentionedEvents(mentionedUsers, note, nm);
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ export class NoteDeleteService {
|
||||
}
|
||||
|
||||
if (!quiet) {
|
||||
this.globalEventService.publishNoteStream(note, 'deleted', {
|
||||
this.globalEventService.publishNoteStream(note.id, 'deleted', {
|
||||
deletedAt: deletedAt,
|
||||
});
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ export class PollService {
|
||||
const index = choice + 1; // In SQL, array index is 1 based
|
||||
await this.pollsRepository.query(`UPDATE poll SET votes[${index}] = votes[${index}] + 1 WHERE "noteId" = '${poll.noteId}'`);
|
||||
|
||||
this.globalEventService.publishNoteStream(note, 'pollVoted', {
|
||||
this.globalEventService.publishNoteStream(note.id, 'pollVoted', {
|
||||
choice: choice,
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
@@ -259,7 +259,7 @@ export class QueryService {
|
||||
|
||||
@bindThis
|
||||
public generateVisibilityQuery(q: SelectQueryBuilder<any>, me?: { id: MiUser['id'] } | null): void {
|
||||
// This code must always be synchronized with the checks in NoteEntityService.isVisibleForMe and Stream abstract class Channel.isNoteVisibleForMe.
|
||||
// This code must always be synchronized with the checks in Notes.isVisibleForMe.
|
||||
if (me == null) {
|
||||
q.andWhere(new Brackets(qb => {
|
||||
qb
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
*/
|
||||
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import * as Redis from 'ioredis';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
import type { EmojisRepository, NoteReactionsRepository, UsersRepository, NotesRepository, MiMeta } from '@/models/_.js';
|
||||
import type { EmojisRepository, NoteReactionsRepository, UsersRepository, NotesRepository, MiMeta, MiNoteSpReaction, NoteSpReactionsRepository } from '@/models/_.js';
|
||||
import { IdentifiableError } from '@/misc/identifiable-error.js';
|
||||
import type { MiRemoteUser, MiUser } from '@/models/User.js';
|
||||
import type { MiNote } from '@/models/Note.js';
|
||||
@@ -73,6 +74,9 @@ export class ReactionService {
|
||||
@Inject(DI.meta)
|
||||
private meta: MiMeta,
|
||||
|
||||
@Inject(DI.redis)
|
||||
private redisClient: Redis.Redis,
|
||||
|
||||
@Inject(DI.usersRepository)
|
||||
private usersRepository: UsersRepository,
|
||||
|
||||
@@ -82,6 +86,9 @@ export class ReactionService {
|
||||
@Inject(DI.noteReactionsRepository)
|
||||
private noteReactionsRepository: NoteReactionsRepository,
|
||||
|
||||
@Inject(DI.noteSpReactionsRepository)
|
||||
private noteSpReactionsRepository: NoteSpReactionsRepository,
|
||||
|
||||
@Inject(DI.emojisRepository)
|
||||
private emojisRepository: EmojisRepository,
|
||||
|
||||
@@ -244,7 +251,7 @@ export class ReactionService {
|
||||
},
|
||||
});
|
||||
|
||||
this.globalEventService.publishNoteStream(note, 'reacted', {
|
||||
this.globalEventService.publishNoteStream(note.id, 'reacted', {
|
||||
reaction: decodedReaction.reaction,
|
||||
emoji: customEmoji != null ? {
|
||||
name: customEmoji.host ? `${customEmoji.name}@${customEmoji.host}` : `${customEmoji.name}@.`,
|
||||
@@ -318,7 +325,7 @@ export class ReactionService {
|
||||
.execute();
|
||||
}
|
||||
|
||||
this.globalEventService.publishNoteStream(note, 'unreacted', {
|
||||
this.globalEventService.publishNoteStream(note.id, 'unreacted', {
|
||||
reaction: this.decodeReaction(exist.reaction).reaction,
|
||||
userId: user.id,
|
||||
});
|
||||
@@ -337,6 +344,118 @@ export class ReactionService {
|
||||
//#endregion
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async createSp(user: { id: MiUser['id']; isBot: MiUser['isBot'] }, note: MiNote, reaction: string) {
|
||||
if (!this.meta.enableSpReaction) {
|
||||
throw new IdentifiableError('52c432ea-b166-491c-a73b-5dd703221b20');
|
||||
}
|
||||
|
||||
if (note.userId === user.id) {
|
||||
throw new IdentifiableError('afa694bf-6661-4d72-b8f7-bfb86a7545a1');
|
||||
}
|
||||
|
||||
if (note.userHost !== null) {
|
||||
throw new IdentifiableError('b59abda2-0d81-49e3-8148-80cf35ac4402');
|
||||
}
|
||||
|
||||
if (note.reactionAcceptance === 'likeOnly') {
|
||||
throw new IdentifiableError('1b168811-a1aa-470a-9b61-7fcf807cf9c1');
|
||||
}
|
||||
|
||||
if (!await this.noteEntityService.isVisibleForMe(note, user.id)) {
|
||||
throw new IdentifiableError('3ce0e3bc-7d48-4e87-a902-578c6ffd369e', 'Note not accessible for you.');
|
||||
}
|
||||
|
||||
// monthly limit
|
||||
const policies = await this.roleService.getUserPolicies(user.id);
|
||||
if (policies.spReactionsMonthlyLimit === 0) {
|
||||
throw new IdentifiableError('e371be02-9478-4133-90ef-8401ee38e474');
|
||||
}
|
||||
const month = new Date().getUTCMonth() + 1;
|
||||
const monthlySpReactionsCountMapKey = `monthlySpReactionsCountMap:${user.id}:${month}`;
|
||||
const count = await this.redisClient.get(monthlySpReactionsCountMapKey);
|
||||
if (count != null && parseInt(count, 10) >= policies.spReactionsMonthlyLimit) {
|
||||
throw new IdentifiableError('82e1a10c-52a8-4ccb-8ff7-3678bff68444');
|
||||
}
|
||||
|
||||
const blocked = await this.userBlockingService.checkBlocked(note.userId, user.id);
|
||||
if (blocked) {
|
||||
throw new IdentifiableError('388ee683-8720-4aea-9ac8-b8c92d260815');
|
||||
}
|
||||
|
||||
const custom = reaction.match(isCustomEmojiRegexp);
|
||||
if (custom) {
|
||||
const name = custom[1];
|
||||
const emoji = (await this.customEmojiService.localEmojisCache.fetch()).get(name);
|
||||
|
||||
if (emoji == null) {
|
||||
throw new IdentifiableError('47c098e2-d0b6-4197-8d00-5a68bbb156be');
|
||||
}
|
||||
|
||||
// センシティブ
|
||||
if ((note.reactionAcceptance === 'nonSensitiveOnly' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote') && emoji.isSensitive) {
|
||||
throw new IdentifiableError('7fc2efbd-2652-4a60-975b-6eb65f60c7b3');
|
||||
}
|
||||
|
||||
if (emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length > 0 && !(await this.roleService.getUserRoles(user.id)).some(r => emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.includes(r.id))) {
|
||||
// リアクションとして使う権限がない
|
||||
throw new IdentifiableError('63288e20-4251-4c62-a9d5-9da4e0bdd41e');
|
||||
}
|
||||
|
||||
reaction = `:${name}:`;
|
||||
} else {
|
||||
reaction = this.normalize(reaction);
|
||||
}
|
||||
|
||||
const record: MiNoteSpReaction = {
|
||||
id: this.idService.gen(),
|
||||
noteId: note.id,
|
||||
userId: user.id,
|
||||
reaction,
|
||||
noteUserId: note.userId,
|
||||
};
|
||||
|
||||
try {
|
||||
await this.noteSpReactionsRepository.insert(record);
|
||||
} catch (e) {
|
||||
if (isDuplicateKeyValueError(e)) {
|
||||
throw new IdentifiableError('c9e8b0d0-d532-4453-8cc1-5cf8e95ba764');
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// increment monthly reactions count
|
||||
const redisPipeline = this.redisClient.pipeline();
|
||||
redisPipeline.incr(monthlySpReactionsCountMapKey);
|
||||
redisPipeline.expireat(monthlySpReactionsCountMapKey,
|
||||
(Date.now() / 1000) + (60 * 60 * 24 * 40), // TTLは最低でも一か月存続しさえすれば厳密でなくていい
|
||||
'NX',
|
||||
);
|
||||
redisPipeline.exec();
|
||||
|
||||
// 3日以内に投稿されたノートの場合ハイライト用ランキング更新
|
||||
if (
|
||||
(Date.now() - this.idService.parse(note.id).date.getTime()) < 1000 * 60 * 60 * 24 * 3
|
||||
) {
|
||||
if (note.channelId != null) {
|
||||
if (note.replyId == null) {
|
||||
this.featuredService.updateInChannelNotesRanking(note.channelId, note.id, 1);
|
||||
}
|
||||
} else {
|
||||
if (note.visibility === 'public' && note.replyId == null) {
|
||||
this.featuredService.updateGlobalNotesRanking(note.id, 1);
|
||||
this.featuredService.updatePerUserNotesRanking(note.userId, note.id, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.notificationService.createNotification(note.userId, 'spReaction', {
|
||||
noteId: note.id,
|
||||
reaction: reaction,
|
||||
}, user.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* - 文字列タイプのレガシーな形式のリアクションを現在の形式に変換する
|
||||
* - ローカルのリアクションのホストを `@.` にする(`decodeReaction()`の効果)
|
||||
|
||||
@@ -91,27 +91,13 @@ export class RelayService {
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
private getAcceptedRelays(): Promise<MiRelay[]> {
|
||||
return this.relaysCache.fetch(() => this.relaysRepository.findBy({
|
||||
status: 'accepted',
|
||||
}));
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async isRelayActor(actor: { inbox: string | null; sharedInbox: string | null }): Promise<boolean> {
|
||||
const relays = await this.getAcceptedRelays();
|
||||
return relays.some(relay =>
|
||||
(actor.inbox != null && relay.inbox === actor.inbox)
|
||||
|| (actor.sharedInbox != null && relay.inbox === actor.sharedInbox),
|
||||
);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async deliverToRelays(user: { id: MiUser['id']; host: null; }, activity: any): Promise<void> {
|
||||
if (activity == null) return;
|
||||
|
||||
const relays = await this.getAcceptedRelays();
|
||||
const relays = await this.relaysCache.fetch(() => this.relaysRepository.findBy({
|
||||
status: 'accepted',
|
||||
}));
|
||||
if (relays.length === 0) return;
|
||||
|
||||
const copy = deepClone(activity);
|
||||
|
||||
@@ -71,6 +71,7 @@ export type RolePolicies = {
|
||||
noteDraftLimit: number;
|
||||
scheduledNoteLimit: number;
|
||||
watermarkAvailable: boolean;
|
||||
spReactionsMonthlyLimit: number;
|
||||
};
|
||||
|
||||
export const DEFAULT_POLICIES: RolePolicies = {
|
||||
@@ -118,6 +119,7 @@ export const DEFAULT_POLICIES: RolePolicies = {
|
||||
noteDraftLimit: 10,
|
||||
scheduledNoteLimit: 1,
|
||||
watermarkAvailable: true,
|
||||
spReactionsMonthlyLimit: 0,
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
@@ -533,8 +535,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
|
||||
roleId: In(administratorRoles.map(r => r.id)),
|
||||
}) : [];
|
||||
// TODO: isRootなアカウントも含める
|
||||
// Setを経由して重複を除去(ユーザIDは重複する可能性があるので)
|
||||
return [...new Set(assigns.map(a => a.userId))].sort((x, y) => x.localeCompare(y));
|
||||
return assigns.map(a => a.userId);
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
||||
@@ -17,7 +17,7 @@ import { CacheService } from '@/core/CacheService.js';
|
||||
import { QueryService } from '@/core/QueryService.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { LoggerService } from '@/core/LoggerService.js';
|
||||
import type { Index, Meilisearch } from 'meilisearch';
|
||||
import type { Index, MeiliSearch } from 'meilisearch';
|
||||
|
||||
type K = string;
|
||||
type V = string | number | boolean;
|
||||
@@ -85,7 +85,7 @@ export class SearchService {
|
||||
private config: Config,
|
||||
|
||||
@Inject(DI.meilisearch)
|
||||
private meilisearch: Meilisearch | null,
|
||||
private meilisearch: MeiliSearch | null,
|
||||
|
||||
@Inject(DI.notesRepository)
|
||||
private notesRepository: NotesRepository,
|
||||
@@ -187,7 +187,7 @@ export class SearchService {
|
||||
return this.searchNoteByLike(q, me, opts, pagination);
|
||||
}
|
||||
case 'meilisearch': {
|
||||
return this.searchNoteByMeilisearch(q, me, opts, pagination);
|
||||
return this.searchNoteByMeiliSearch(q, me, opts, pagination);
|
||||
}
|
||||
default: {
|
||||
const _: never = this.provider;
|
||||
@@ -239,14 +239,14 @@ export class SearchService {
|
||||
}
|
||||
|
||||
@bindThis
|
||||
private async searchNoteByMeilisearch(
|
||||
private async searchNoteByMeiliSearch(
|
||||
q: string,
|
||||
me: MiUser | null,
|
||||
opts: SearchOpts,
|
||||
pagination: SearchPagination,
|
||||
): Promise<MiNote[]> {
|
||||
if (!this.meilisearch || !this.meilisearchNoteIndex) {
|
||||
throw new Error('Meilisearch is not available');
|
||||
throw new Error('MeiliSearch is not available');
|
||||
}
|
||||
|
||||
const filter: Q = {
|
||||
|
||||
@@ -164,3 +164,4 @@ export class SignupService {
|
||||
return { account, secret };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ export class ApInboxService {
|
||||
|
||||
@bindThis
|
||||
private async add(actor: MiRemoteUser, activity: IAdd, resolver?: Resolver): Promise<string | void> {
|
||||
if (actor.uri !== getApId(activity.actor)) {
|
||||
if (actor.uri !== activity.actor) {
|
||||
return 'invalid actor';
|
||||
}
|
||||
|
||||
@@ -302,14 +302,12 @@ export class ApInboxService {
|
||||
|
||||
@bindThis
|
||||
private async announceNote(actor: MiRemoteUser, activity: IAnnounce, target: IPost, resolver?: Resolver): Promise<string | void> {
|
||||
const uri = getApId(activity);
|
||||
|
||||
if (actor.isSuspended) {
|
||||
return;
|
||||
}
|
||||
|
||||
// リレーからのAnnounceかチェック
|
||||
const fromRelay = await this.relayService.isRelayActor(actor);
|
||||
const uri = getApId(fromRelay ? target : activity);
|
||||
|
||||
// アナウンス先が許可されているかチェック
|
||||
if (!this.utilityService.isFederationAllowedUri(uri)) return;
|
||||
|
||||
@@ -338,14 +336,6 @@ export class ApInboxService {
|
||||
throw err;
|
||||
}
|
||||
|
||||
// リレーからのAnnounceはリノートを作成せず、ノートを直接公開する
|
||||
if (fromRelay) {
|
||||
this.logger.info(`Publishing relay-delivered note: ${uri}`);
|
||||
const noteObj = await this.noteEntityService.pack(renote, null, { skipHide: true, withReactionAndUserPairCache: true });
|
||||
this.globalEventService.publishNotesStream(noteObj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await this.noteEntityService.isVisibleForMe(renote, actor.id)) {
|
||||
return 'skip: invalid actor for this activity';
|
||||
}
|
||||
@@ -469,7 +459,7 @@ export class ApInboxService {
|
||||
|
||||
@bindThis
|
||||
private async delete(actor: MiRemoteUser, activity: IDelete): Promise<string> {
|
||||
if (actor.uri !== getApId(activity.actor)) {
|
||||
if (actor.uri !== activity.actor) {
|
||||
return 'invalid actor';
|
||||
}
|
||||
|
||||
@@ -623,7 +613,7 @@ export class ApInboxService {
|
||||
|
||||
@bindThis
|
||||
private async remove(actor: MiRemoteUser, activity: IRemove, resolver?: Resolver): Promise<string | void> {
|
||||
if (actor.uri !== getApId(activity.actor)) {
|
||||
if (actor.uri !== activity.actor) {
|
||||
return 'invalid actor';
|
||||
}
|
||||
|
||||
@@ -643,7 +633,7 @@ export class ApInboxService {
|
||||
|
||||
@bindThis
|
||||
private async undo(actor: MiRemoteUser, activity: IUndo, resolver?: Resolver): Promise<string> {
|
||||
if (actor.uri !== getApId(activity.actor)) {
|
||||
if (actor.uri !== activity.actor) {
|
||||
return 'invalid actor';
|
||||
}
|
||||
|
||||
@@ -777,7 +767,7 @@ export class ApInboxService {
|
||||
|
||||
@bindThis
|
||||
private async update(actor: MiRemoteUser, activity: IUpdate, resolver?: Resolver): Promise<string> {
|
||||
if (actor.uri !== getApId(activity.actor)) {
|
||||
if (actor.uri !== activity.actor) {
|
||||
return 'skip: invalid actor';
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ export class ApRequestCreator {
|
||||
}, args.additionalHeaders),
|
||||
};
|
||||
|
||||
const result = this.#signToRequest(request, args.key, ['(request-target)', 'date', 'host']);
|
||||
const result = this.#signToRequest(request, args.key, ['(request-target)', 'date', 'host', 'accept']);
|
||||
|
||||
return {
|
||||
request,
|
||||
|
||||
@@ -376,7 +376,7 @@ export class ApPersonService implements OnModuleInit {
|
||||
isLocked: person.manuallyApprovesFollowers,
|
||||
movedToUri: person.movedTo,
|
||||
movedAt: person.movedTo ? new Date() : null,
|
||||
alsoKnownAs: toArray(person.alsoKnownAs),
|
||||
alsoKnownAs: person.alsoKnownAs,
|
||||
isExplorable: person.discoverable,
|
||||
username: person.preferredUsername,
|
||||
usernameLower: person.preferredUsername?.toLowerCase(),
|
||||
@@ -568,7 +568,7 @@ export class ApPersonService implements OnModuleInit {
|
||||
isCat: (person as any).isCat === true,
|
||||
isLocked: person.manuallyApprovesFollowers,
|
||||
movedToUri: person.movedTo ?? null,
|
||||
alsoKnownAs: person.alsoKnownAs ? toArray(person.alsoKnownAs) : null,
|
||||
alsoKnownAs: person.alsoKnownAs ?? null,
|
||||
isExplorable: person.discoverable,
|
||||
...(await this.resolveAvatarAndBanner(exist, person.icon, person.image).catch(() => ({}))),
|
||||
} as Partial<MiRemoteUser> & Pick<MiRemoteUser, 'isBot' | 'isCat' | 'isLocked' | 'movedToUri' | 'alsoKnownAs' | 'isExplorable'>;
|
||||
|
||||
@@ -132,7 +132,7 @@ export class MetaEntityService {
|
||||
sentryForFrontend: this.config.sentryForFrontend ?? null,
|
||||
mediaProxy: this.config.mediaProxy,
|
||||
enableUrlPreview: instance.urlPreviewEnabled,
|
||||
noteSearchableScope: (this.config.fulltextSearch?.provider === 'meilisearch' && this.config.meilisearch?.scope === 'local') ? 'local' : 'global',
|
||||
noteSearchableScope: (this.config.meilisearch == null || this.config.meilisearch.scope !== 'local') ? 'global' : 'local',
|
||||
maxFileSize: this.config.maxFileSize,
|
||||
federation: this.meta.federation,
|
||||
};
|
||||
|
||||
@@ -17,7 +17,6 @@ import { DebounceLoader } from '@/misc/loader.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { shouldHideNoteByTime } from '@/misc/should-hide-note-by-time.js';
|
||||
import { ReactionsBufferingService } from '@/core/ReactionsBufferingService.js';
|
||||
import { CacheService } from '@/core/CacheService.js';
|
||||
import type { OnModuleInit } from '@nestjs/common';
|
||||
import type { CustomEmojiService } from '../CustomEmojiService.js';
|
||||
import type { ReactionService } from '../ReactionService.js';
|
||||
@@ -67,7 +66,6 @@ export class NoteEntityService implements OnModuleInit {
|
||||
private reactionService: ReactionService;
|
||||
private reactionsBufferingService: ReactionsBufferingService;
|
||||
private idService: IdService;
|
||||
private cacheService: CacheService;
|
||||
private noteLoader = new DebounceLoader(this.findNoteOrFail);
|
||||
|
||||
constructor(
|
||||
@@ -103,7 +101,6 @@ export class NoteEntityService implements OnModuleInit {
|
||||
//private reactionService: ReactionService,
|
||||
//private reactionsBufferingService: ReactionsBufferingService,
|
||||
//private idService: IdService,
|
||||
//private cacheService: CacheService,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -114,7 +111,6 @@ export class NoteEntityService implements OnModuleInit {
|
||||
this.reactionService = this.moduleRef.get('ReactionService');
|
||||
this.reactionsBufferingService = this.moduleRef.get('ReactionsBufferingService');
|
||||
this.idService = this.moduleRef.get('IdService');
|
||||
this.cacheService = this.moduleRef.get('CacheService');
|
||||
}
|
||||
|
||||
@bindThis
|
||||
@@ -129,65 +125,75 @@ export class NoteEntityService implements OnModuleInit {
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public async shouldHideNote(packedNote: Packed<'Note'>, meId: MiUser['id'] | null): Promise<boolean> {
|
||||
if (meId === packedNote.userId) return false;
|
||||
private async hideNote(packedNote: Packed<'Note'>, meId: MiUser['id'] | null): Promise<void> {
|
||||
if (meId === packedNote.userId) return;
|
||||
|
||||
// TODO: isVisibleForMe を使うようにしても良さそう(型違うけど)
|
||||
let hide = false;
|
||||
|
||||
if (packedNote.user.requireSigninToViewContents && meId == null) {
|
||||
return true;
|
||||
hide = true;
|
||||
}
|
||||
|
||||
const hiddenBefore = packedNote.user.makeNotesHiddenBefore;
|
||||
if (shouldHideNoteByTime(hiddenBefore, packedNote.createdAt)) {
|
||||
return true;
|
||||
if (!hide) {
|
||||
const hiddenBefore = packedNote.user.makeNotesHiddenBefore;
|
||||
if (shouldHideNoteByTime(hiddenBefore, packedNote.createdAt)) {
|
||||
hide = true;
|
||||
}
|
||||
}
|
||||
|
||||
// visibility が specified かつ自分が指定されていなかったら非表示
|
||||
if (packedNote.visibility === 'specified') {
|
||||
if (meId == null) {
|
||||
return true;
|
||||
} else {
|
||||
// 指定されているかどうか
|
||||
const specified = packedNote.visibleUserIds!.some(id => meId === id);
|
||||
if (!hide) {
|
||||
if (packedNote.visibility === 'specified') {
|
||||
if (meId == null) {
|
||||
hide = true;
|
||||
} else {
|
||||
// 指定されているかどうか
|
||||
const specified = packedNote.visibleUserIds!.some(id => meId === id);
|
||||
|
||||
if (!specified) {
|
||||
return true;
|
||||
if (!specified) {
|
||||
hide = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// visibility が followers かつ自分が投稿者のフォロワーでなかったら非表示
|
||||
if (packedNote.visibility === 'followers') {
|
||||
if (meId == null) {
|
||||
return true;
|
||||
} else if (packedNote.reply && (meId === packedNote.reply.userId)) {
|
||||
// 自分の投稿に対するリプライ
|
||||
return false;
|
||||
} else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) {
|
||||
// 自分へのメンション
|
||||
return false;
|
||||
} else {
|
||||
// フォロワーかどうか
|
||||
const followings = await this.cacheService.userFollowingsCache.fetch(meId);
|
||||
if (!Object.hasOwn(followings, packedNote.userId)) {
|
||||
return true;
|
||||
if (!hide) {
|
||||
if (packedNote.visibility === 'followers') {
|
||||
if (meId == null) {
|
||||
hide = true;
|
||||
} else if (packedNote.reply && (meId === packedNote.reply.userId)) {
|
||||
// 自分の投稿に対するリプライ
|
||||
hide = false;
|
||||
} else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) {
|
||||
// 自分へのメンション
|
||||
hide = false;
|
||||
} else {
|
||||
// フォロワーかどうか
|
||||
// TODO: 当関数呼び出しごとにクエリが走るのは重そうだからなんとかする
|
||||
const isFollowing = await this.followingsRepository.exists({
|
||||
where: {
|
||||
followeeId: packedNote.userId,
|
||||
followerId: meId,
|
||||
},
|
||||
});
|
||||
|
||||
hide = !isFollowing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public hideNote(packedNote: Packed<'Note'>): void {
|
||||
packedNote.visibleUserIds = undefined;
|
||||
packedNote.fileIds = [];
|
||||
packedNote.files = [];
|
||||
packedNote.text = null;
|
||||
packedNote.poll = undefined;
|
||||
packedNote.cw = null;
|
||||
packedNote.isHidden = true;
|
||||
// TODO: hiddenReason みたいなのを提供しても良さそう
|
||||
if (hide) {
|
||||
packedNote.visibleUserIds = undefined;
|
||||
packedNote.fileIds = [];
|
||||
packedNote.files = [];
|
||||
packedNote.text = null;
|
||||
packedNote.poll = undefined;
|
||||
packedNote.cw = null;
|
||||
packedNote.isHidden = true;
|
||||
// TODO: hiddenReason みたいなのを提供しても良さそう
|
||||
}
|
||||
}
|
||||
|
||||
@bindThis
|
||||
@@ -272,7 +278,7 @@ export class NoteEntityService implements OnModuleInit {
|
||||
|
||||
@bindThis
|
||||
public async isVisibleForMe(note: MiNote, meId: MiUser['id'] | null): Promise<boolean> {
|
||||
// This code must always be synchronized with the checks in QueryService.generateVisibilityQuery.
|
||||
// This code must always be synchronized with the checks in generateVisibilityQuery.
|
||||
// visibility が specified かつ自分が指定されていなかったら非表示
|
||||
if (note.visibility === 'specified') {
|
||||
if (meId == null) {
|
||||
@@ -462,8 +468,8 @@ export class NoteEntityService implements OnModuleInit {
|
||||
|
||||
this.treatVisibility(packed);
|
||||
|
||||
if (!opts.skipHide && await this.shouldHideNote(packed, meId)) {
|
||||
this.hideNote(packed);
|
||||
if (!opts.skipHide) {
|
||||
await this.hideNote(packed, meId);
|
||||
}
|
||||
|
||||
return packed;
|
||||
|
||||
@@ -29,6 +29,7 @@ const NOTE_REQUIRED_NOTIFICATION_TYPES = new Set([
|
||||
'renote:grouped',
|
||||
'quote',
|
||||
'reaction',
|
||||
'spReaction',
|
||||
'reaction:grouped',
|
||||
'pollEnded',
|
||||
'scheduledNotePosted',
|
||||
|
||||
@@ -51,7 +51,6 @@ import { ChatService } from '@/core/ChatService.js';
|
||||
import type { OnModuleInit } from '@nestjs/common';
|
||||
import type { NoteEntityService } from './NoteEntityService.js';
|
||||
import type { PageEntityService } from './PageEntityService.js';
|
||||
import { toArray } from '@/misc/prelude/array.js';
|
||||
|
||||
const Ajv = _Ajv.default;
|
||||
const ajv = new Ajv();
|
||||
@@ -528,10 +527,10 @@ export class UserEntityService implements OnModuleInit {
|
||||
url: profile!.url,
|
||||
uri: user.uri,
|
||||
movedTo: user.movedToUri ? this.apPersonService.resolvePerson(user.movedToUri).then(user => user.id).catch(() => null) : null,
|
||||
alsoKnownAs: user.alsoKnownAs ?
|
||||
Promise.all(toArray(user.alsoKnownAs).map(uri => this.apPersonService.fetchPerson(uri).then(user => user?.id).catch(() => null)))
|
||||
.then(xs => xs.length === 0 ? null : xs.filter(x => x != null))
|
||||
: null,
|
||||
alsoKnownAs: user.alsoKnownAs
|
||||
? Promise.all(user.alsoKnownAs.map(uri => this.apPersonService.fetchPerson(uri).then(user => user?.id).catch(() => null)))
|
||||
.then(xs => xs.length === 0 ? null : xs.filter(x => x != null))
|
||||
: null,
|
||||
createdAt: this.idService.parse(user.id).date.toISOString(),
|
||||
updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null,
|
||||
lastFetchedAt: user.lastFetchedAt ? user.lastFetchedAt.toISOString() : null,
|
||||
|
||||
@@ -24,6 +24,7 @@ export const DI = {
|
||||
noteFavoritesRepository: Symbol('noteFavoritesRepository'),
|
||||
noteThreadMutingsRepository: Symbol('noteThreadMutingsRepository'),
|
||||
noteReactionsRepository: Symbol('noteReactionsRepository'),
|
||||
noteSpReactionsRepository: Symbol('noteSpReactionsRepository'),
|
||||
pollsRepository: Symbol('pollsRepository'),
|
||||
pollVotesRepository: Symbol('pollVotesRepository'),
|
||||
userProfilesRepository: Symbol('userProfilesRepository'),
|
||||
|
||||
@@ -9,11 +9,11 @@ import { default as convertColor } from 'color-convert';
|
||||
import { format as dateFormat } from 'date-fns';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { envOption } from './env.js';
|
||||
import type { Keyword } from 'color-convert';
|
||||
import type { KEYWORD } from 'color-convert/conversions.js';
|
||||
|
||||
type Context = {
|
||||
name: string;
|
||||
color?: Keyword;
|
||||
color?: KEYWORD;
|
||||
};
|
||||
|
||||
type Level = 'error' | 'success' | 'warning' | 'debug' | 'info';
|
||||
@@ -23,7 +23,7 @@ export default class Logger {
|
||||
private context: Context;
|
||||
private parentLogger: Logger | null = null;
|
||||
|
||||
constructor(context: string, color?: Keyword) {
|
||||
constructor(context: string, color?: KEYWORD) {
|
||||
this.context = {
|
||||
name: context,
|
||||
color: color,
|
||||
@@ -31,7 +31,7 @@ export default class Logger {
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public createSubLogger(context: string, color?: Keyword): Logger {
|
||||
public createSubLogger(context: string, color?: KEYWORD): Logger {
|
||||
const logger = new Logger(context, color);
|
||||
logger.parentLogger = this;
|
||||
return logger;
|
||||
|
||||
@@ -5,19 +5,12 @@
|
||||
|
||||
// Crockford's Base32
|
||||
// https://github.com/ulid/spec#encoding
|
||||
import { parseBigInt32 } from '@/misc/bigint.js';
|
||||
|
||||
const CHARS = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
||||
|
||||
export const ulidRegExp = /^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$/;
|
||||
|
||||
function parseBigIntCrockford(str: string): bigint {
|
||||
let result = 0n;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
result = result * 32n + BigInt(CHARS.indexOf(str[i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseBase32(timestamp: string) {
|
||||
let time = 0;
|
||||
for (let i = 0; i < timestamp.length; i++) {
|
||||
@@ -33,6 +26,6 @@ export function parseUlid(id: string): { date: Date; } {
|
||||
export function parseUlidFull(id: string): { date: number; additional: bigint; } {
|
||||
return {
|
||||
date: parseBase32(id.slice(0, 10)),
|
||||
additional: parseBigIntCrockford(id.slice(10, 26)),
|
||||
additional: parseBigInt32(id.slice(10, 26)),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -36,9 +36,4 @@ export class MiAvatarDecoration {
|
||||
array: true, length: 128, default: '{}',
|
||||
})
|
||||
public roleIdsThatCanBeUsedThisDecoration: string[];
|
||||
|
||||
@Column('varchar', {
|
||||
length: 128, nullable: true,
|
||||
})
|
||||
public category: string | null;
|
||||
}
|
||||
|
||||
@@ -722,6 +722,11 @@ export class MiMeta {
|
||||
})
|
||||
public showRoleBadgesOfRemoteUsers: boolean;
|
||||
|
||||
@Column('boolean', {
|
||||
default: false,
|
||||
})
|
||||
public enableSpReaction: boolean;
|
||||
|
||||
@Column('jsonb', {
|
||||
default: { },
|
||||
})
|
||||
|
||||
50
packages/backend/src/models/NoteSpReaction.ts
Normal file
50
packages/backend/src/models/NoteSpReaction.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
|
||||
import { id } from './util/id.js';
|
||||
import { MiUser } from './User.js';
|
||||
import { MiNote } from './Note.js';
|
||||
|
||||
@Entity('note_sp_reaction')
|
||||
@Index(['userId', 'noteId'], { unique: true })
|
||||
export class MiNoteSpReaction {
|
||||
@PrimaryColumn(id())
|
||||
public id: string;
|
||||
|
||||
@Index()
|
||||
@Column(id())
|
||||
public userId: MiUser['id'];
|
||||
|
||||
@ManyToOne(() => MiUser, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
public user?: MiUser | null;
|
||||
|
||||
@Index()
|
||||
@Column(id())
|
||||
public noteId: MiNote['id'];
|
||||
|
||||
@ManyToOne(() => MiNote, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn()
|
||||
public note?: MiNote | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 260,
|
||||
})
|
||||
public reaction: string;
|
||||
|
||||
//#region Denormalized fields
|
||||
@Index()
|
||||
@Column({
|
||||
...id(),
|
||||
comment: '[Denormalized]',
|
||||
})
|
||||
public noteUserId: MiUser['id'];
|
||||
//#endregion
|
||||
}
|
||||
@@ -55,6 +55,13 @@ export type MiNotification = {
|
||||
notifierId: MiUser['id'];
|
||||
noteId: MiNote['id'];
|
||||
reaction: string;
|
||||
} | {
|
||||
type: 'spReaction';
|
||||
id: string;
|
||||
createdAt: string;
|
||||
notifierId: MiUser['id'];
|
||||
noteId: MiNote['id'];
|
||||
reaction: string;
|
||||
} | {
|
||||
type: 'pollEnded';
|
||||
id: string;
|
||||
|
||||
@@ -42,6 +42,7 @@ import {
|
||||
MiNote,
|
||||
MiNoteFavorite,
|
||||
MiNoteReaction,
|
||||
MiNoteSpReaction,
|
||||
MiNoteThreadMuting,
|
||||
MiNoteDraft,
|
||||
MiPage,
|
||||
@@ -142,6 +143,12 @@ const $noteReactionsRepository: Provider = {
|
||||
inject: [DI.db],
|
||||
};
|
||||
|
||||
const $noteSpReactionsRepository: Provider = {
|
||||
provide: DI.noteSpReactionsRepository,
|
||||
useFactory: (db: DataSource) => db.getRepository(MiNoteSpReaction).extend(miRepository as MiRepository<MiNoteSpReaction>),
|
||||
inject: [DI.db],
|
||||
};
|
||||
|
||||
const $noteDraftsRepository: Provider = {
|
||||
provide: DI.noteDraftsRepository,
|
||||
useFactory: (db: DataSource) => db.getRepository(MiNoteDraft).extend(miRepository as MiRepository<MiNoteDraft>),
|
||||
@@ -556,6 +563,7 @@ const $reversiGamesRepository: Provider = {
|
||||
$noteFavoritesRepository,
|
||||
$noteThreadMutingsRepository,
|
||||
$noteReactionsRepository,
|
||||
$noteSpReactionsRepository,
|
||||
$noteDraftsRepository,
|
||||
$pollsRepository,
|
||||
$pollVotesRepository,
|
||||
@@ -634,6 +642,7 @@ const $reversiGamesRepository: Provider = {
|
||||
$noteFavoritesRepository,
|
||||
$noteThreadMutingsRepository,
|
||||
$noteReactionsRepository,
|
||||
$noteSpReactionsRepository,
|
||||
$noteDraftsRepository,
|
||||
$pollsRepository,
|
||||
$pollVotesRepository,
|
||||
|
||||
@@ -23,7 +23,7 @@ import { MiBubbleGameRecord } from '@/models/BubbleGameRecord.js';
|
||||
import { MiChannel } from '@/models/Channel.js';
|
||||
import { MiChannelFavorite } from '@/models/ChannelFavorite.js';
|
||||
import { MiChannelFollowing } from '@/models/ChannelFollowing.js';
|
||||
import { MiChannelMuting } from "@/models/ChannelMuting.js";
|
||||
import { MiChannelMuting } from '@/models/ChannelMuting.js';
|
||||
import { MiChatApproval } from '@/models/ChatApproval.js';
|
||||
import { MiChatMessage } from '@/models/ChatMessage.js';
|
||||
import { MiChatRoom } from '@/models/ChatRoom.js';
|
||||
@@ -50,6 +50,7 @@ import { MiNote } from '@/models/Note.js';
|
||||
import { MiNoteDraft } from '@/models/NoteDraft.js';
|
||||
import { MiNoteFavorite } from '@/models/NoteFavorite.js';
|
||||
import { MiNoteReaction } from '@/models/NoteReaction.js';
|
||||
import { MiNoteSpReaction } from '@/models/NoteSpReaction.js';
|
||||
import { MiNoteThreadMuting } from '@/models/NoteThreadMuting.js';
|
||||
import { MiPage } from '@/models/Page.js';
|
||||
import { MiPageLike } from '@/models/PageLike.js';
|
||||
@@ -131,6 +132,7 @@ export {
|
||||
MiNoteDraft,
|
||||
MiNoteFavorite,
|
||||
MiNoteReaction,
|
||||
MiNoteSpReaction,
|
||||
MiNoteThreadMuting,
|
||||
MiPage,
|
||||
MiPageLike,
|
||||
@@ -211,6 +213,7 @@ export type NotesRepository = Repository<MiNote> & MiRepository<MiNote>;
|
||||
export type NoteDraftsRepository = Repository<MiNoteDraft> & MiRepository<MiNoteDraft>;
|
||||
export type NoteFavoritesRepository = Repository<MiNoteFavorite> & MiRepository<MiNoteFavorite>;
|
||||
export type NoteReactionsRepository = Repository<MiNoteReaction> & MiRepository<MiNoteReaction>;
|
||||
export type NoteSpReactionsRepository = Repository<MiNoteSpReaction> & MiRepository<MiNoteSpReaction>;
|
||||
export type NoteThreadMutingsRepository = Repository<MiNoteThreadMuting> & MiRepository<MiNoteThreadMuting>;
|
||||
export type PagesRepository = Repository<MiPage> & MiRepository<MiPage>;
|
||||
export type PageLikesRepository = Repository<MiPageLike> & MiRepository<MiPageLike>;
|
||||
|
||||
@@ -182,6 +182,35 @@ export const packedNotificationSchema = {
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
type: 'object',
|
||||
properties: {
|
||||
...baseSchema.properties,
|
||||
type: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
enum: ['spReaction'],
|
||||
},
|
||||
user: {
|
||||
type: 'object',
|
||||
ref: 'UserLite',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
userId: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
format: 'id',
|
||||
},
|
||||
note: {
|
||||
type: 'object',
|
||||
ref: 'Note',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
reaction: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
type: 'object',
|
||||
properties: {
|
||||
|
||||
@@ -608,6 +608,7 @@ export const packedMeDetailedOnlySchema = {
|
||||
renote: { optional: true, ...notificationRecieveConfig },
|
||||
quote: { optional: true, ...notificationRecieveConfig },
|
||||
reaction: { optional: true, ...notificationRecieveConfig },
|
||||
spReaction: { optional: true, ...notificationRecieveConfig },
|
||||
pollEnded: { optional: true, ...notificationRecieveConfig },
|
||||
scheduledNotePosted: { optional: true, ...notificationRecieveConfig },
|
||||
scheduledNotePostFailed: { optional: true, ...notificationRecieveConfig },
|
||||
|
||||
@@ -44,6 +44,7 @@ import { MiRenoteMuting } from '@/models/RenoteMuting.js';
|
||||
import { MiNote } from '@/models/Note.js';
|
||||
import { MiNoteFavorite } from '@/models/NoteFavorite.js';
|
||||
import { MiNoteReaction } from '@/models/NoteReaction.js';
|
||||
import { MiNoteSpReaction } from '@/models/NoteSpReaction.js';
|
||||
import { MiNoteThreadMuting } from '@/models/NoteThreadMuting.js';
|
||||
import { MiNoteDraft } from '@/models/NoteDraft.js';
|
||||
import { MiPage } from '@/models/Page.js';
|
||||
@@ -204,6 +205,7 @@ export const entities = [
|
||||
MiNote,
|
||||
MiNoteFavorite,
|
||||
MiNoteReaction,
|
||||
MiNoteSpReaction,
|
||||
MiNoteThreadMuting,
|
||||
MiNoteDraft,
|
||||
MiPage,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user