From 9a70ce8f5ea9df00001894809f5ce7bc69b14c8a Mon Sep 17 00:00:00 2001 From: tamaina Date: Sat, 17 Feb 2024 12:41:19 +0900 Subject: [PATCH 01/10] Merge pull request from GHSA-qqrm-9grj-6v32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * maybe ok * fix * test wip * :v: * fix * if (res.ok) * validateContentTypeSetAsJsonLD * 条件を考慮し直す * その他の+json接尾辞が付いているメディアタイプも受け容れる * https://github.com/misskey-dev/misskey-ghsa-qqrm-9grj-6v32/pull/1#discussion_r1490999009 * add `; profile="https://www.w3.org/ns/activitystreams"` * application/ld+json; --- .../backend/src/core/HttpRequestService.ts | 55 +++++++++++++++---- .../src/core/activitypub/ApRequestService.ts | 6 +- .../src/core/activitypub/ApResolverService.ts | 2 +- .../core/activitypub/LdSignatureService.ts | 6 +- .../src/core/activitypub/misc/validator.ts | 39 +++++++++++++ .../test/e2e/fetch-validate-ap-deny.ts | 40 ++++++++++++++ packages/backend/test/unit/activitypub.ts | 2 +- packages/backend/test/utils.ts | 36 +++++++----- 8 files changed, 157 insertions(+), 29 deletions(-) create mode 100644 packages/backend/src/core/activitypub/misc/validator.ts create mode 100644 packages/backend/test/e2e/fetch-validate-ap-deny.ts diff --git a/packages/backend/src/core/HttpRequestService.ts b/packages/backend/src/core/HttpRequestService.ts index b36b9f6e3c76..7f3cac7c5807 100644 --- a/packages/backend/src/core/HttpRequestService.ts +++ b/packages/backend/src/core/HttpRequestService.ts @@ -14,9 +14,16 @@ import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { StatusError } from '@/misc/status-error.js'; import { bindThis } from '@/decorators.js'; +import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js'; +import type { IObject } from '@/core/activitypub/type.js'; import type { Response } from 'node-fetch'; import type { URL } from 'node:url'; +export type HttpRequestSendOptions = { + throwErrorWhenResponseNotOk: boolean; + validators?: ((res: Response) => void)[]; +}; + @Injectable() export class HttpRequestService { /** @@ -104,6 +111,23 @@ export class HttpRequestService { } } + @bindThis + public async getActivityJson(url: string): Promise { + const res = await this.send(url, { + method: 'GET', + headers: { + Accept: 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"', + }, + timeout: 5000, + size: 1024 * 256, + }, { + throwErrorWhenResponseNotOk: true, + validators: [validateContentTypeSetAsActivityPub], + }); + + return await res.json() as IObject; + } + @bindThis public async getJson(url: string, accept = 'application/json, */*', headers?: Record): Promise { const res = await this.send(url, { @@ -132,17 +156,20 @@ export class HttpRequestService { } @bindThis - public async send(url: string, args: { - method?: string, - body?: string, - headers?: Record, - timeout?: number, - size?: number, - } = {}, extra: { - throwErrorWhenResponseNotOk: boolean; - } = { - throwErrorWhenResponseNotOk: true, - }): Promise { + public async send( + url: string, + args: { + method?: string, + body?: string, + headers?: Record, + timeout?: number, + size?: number, + } = {}, + extra: HttpRequestSendOptions = { + throwErrorWhenResponseNotOk: true, + validators: [], + }, + ): Promise { const timeout = args.timeout ?? 5000; const controller = new AbortController(); @@ -166,6 +193,12 @@ export class HttpRequestService { throw new StatusError(`${res.status} ${res.statusText}`, res.status, res.statusText); } + if (res.ok) { + for (const validator of (extra.validators ?? [])) { + validator(res); + } + } + return res; } } diff --git a/packages/backend/src/core/activitypub/ApRequestService.ts b/packages/backend/src/core/activitypub/ApRequestService.ts index 202e07814ecc..93ac8ce9a74b 100644 --- a/packages/backend/src/core/activitypub/ApRequestService.ts +++ b/packages/backend/src/core/activitypub/ApRequestService.ts @@ -14,6 +14,7 @@ import { HttpRequestService } from '@/core/HttpRequestService.js'; import { LoggerService } from '@/core/LoggerService.js'; import { bindThis } from '@/decorators.js'; import type Logger from '@/logger.js'; +import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js'; type Request = { url: string; @@ -70,7 +71,7 @@ export class ApRequestCreator { url: u.href, method: 'GET', headers: this.#objectAssignWithLcKey({ - 'Accept': 'application/activity+json, application/ld+json', + 'Accept': 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"', 'Date': new Date().toUTCString(), 'Host': new URL(args.url).host, }, args.additionalHeaders), @@ -195,6 +196,9 @@ export class ApRequestService { const res = await this.httpRequestService.send(url, { method: req.request.method, headers: req.request.headers, + }, { + throwErrorWhenResponseNotOk: true, + validators: [validateContentTypeSetAsActivityPub], }); return await res.json(); diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts index db44c042e77b..bb3c40f0939b 100644 --- a/packages/backend/src/core/activitypub/ApResolverService.ts +++ b/packages/backend/src/core/activitypub/ApResolverService.ts @@ -105,7 +105,7 @@ export class Resolver { const object = (this.user ? await this.apRequestService.signedGet(value, this.user) as IObject - : await this.httpRequestService.getJson(value, 'application/activity+json, application/ld+json')) as IObject; + : await this.httpRequestService.getActivityJson(value)) as IObject; if ( Array.isArray(object['@context']) ? diff --git a/packages/backend/src/core/activitypub/LdSignatureService.ts b/packages/backend/src/core/activitypub/LdSignatureService.ts index f958e9d16ec2..9de184336f0f 100644 --- a/packages/backend/src/core/activitypub/LdSignatureService.ts +++ b/packages/backend/src/core/activitypub/LdSignatureService.ts @@ -8,6 +8,7 @@ import { Injectable } from '@nestjs/common'; import { HttpRequestService } from '@/core/HttpRequestService.js'; import { bindThis } from '@/decorators.js'; import { CONTEXTS } from './misc/contexts.js'; +import { validateContentTypeSetAsJsonLD } from './misc/validator.js'; import type { JsonLdDocument } from 'jsonld'; import type { JsonLd, RemoteDocument } from 'jsonld/jsonld-spec.js'; @@ -133,7 +134,10 @@ class LdSignature { }, timeout: this.loderTimeout, }, - { throwErrorWhenResponseNotOk: false }, + { + throwErrorWhenResponseNotOk: false, + validators: [validateContentTypeSetAsJsonLD], + }, ).then(res => { if (!res.ok) { throw new Error(`${res.status} ${res.statusText}`); diff --git a/packages/backend/src/core/activitypub/misc/validator.ts b/packages/backend/src/core/activitypub/misc/validator.ts new file mode 100644 index 000000000000..6ba14a222fe5 --- /dev/null +++ b/packages/backend/src/core/activitypub/misc/validator.ts @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import type { Response } from 'node-fetch'; + +export function validateContentTypeSetAsActivityPub(response: Response): void { + const contentType = (response.headers.get('content-type') ?? '').toLowerCase(); + + if (contentType === '') { + throw new Error('Validate content type of AP response: No content-type header'); + } + if ( + contentType.startsWith('application/activity+json') || + (contentType.startsWith('application/ld+json;') && contentType.includes('https://www.w3.org/ns/activitystreams')) + ) { + return; + } + throw new Error('Validate content type of AP response: Content type is not application/activity+json or application/ld+json'); +} + +const plusJsonSuffixRegex = /(application|text)\/[a-zA-Z0-9\.\-\+]+\+json/; + +export function validateContentTypeSetAsJsonLD(response: Response): void { + const contentType = (response.headers.get('content-type') ?? '').toLowerCase(); + + if (contentType === '') { + throw new Error('Validate content type of JSON LD: No content-type header'); + } + if ( + contentType.startsWith('application/ld+json') || + contentType.startsWith('application/json') || + plusJsonSuffixRegex.test(contentType) + ) { + return; + } + throw new Error('Validate content type of JSON LD: Content type is not application/ld+json or application/json'); +} diff --git a/packages/backend/test/e2e/fetch-validate-ap-deny.ts b/packages/backend/test/e2e/fetch-validate-ap-deny.ts new file mode 100644 index 000000000000..434a9fe209b5 --- /dev/null +++ b/packages/backend/test/e2e/fetch-validate-ap-deny.ts @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +process.env.NODE_ENV = 'test'; + +import { validateContentTypeSetAsActivityPub, validateContentTypeSetAsJsonLD } from '@/core/activitypub/misc/validator.js'; +import { signup, uploadFile, relativeFetch } from '../utils.js'; +import type * as misskey from 'misskey-js'; + +describe('validateContentTypeSetAsActivityPub/JsonLD (deny case)', () => { + let alice: misskey.entities.SignupResponse; + let aliceUploadedFile: any; + + beforeAll(async () => { + alice = await signup({ username: 'alice' }); + aliceUploadedFile = await uploadFile(alice); + }, 1000 * 60 * 2); + + test('ActivityStreams: ファイルはエラーになる', async () => { + const res = await relativeFetch(aliceUploadedFile.webpublicUrl); + + function doValidate() { + validateContentTypeSetAsActivityPub(res); + } + + expect(doValidate).toThrow('Content type is not'); + }); + + test('JSON-LD: ファイルはエラーになる', async () => { + const res = await relativeFetch(aliceUploadedFile.webpublicUrl); + + function doValidate() { + validateContentTypeSetAsJsonLD(res); + } + + expect(doValidate).toThrow('Content type is not'); + }); +}); diff --git a/packages/backend/test/unit/activitypub.ts b/packages/backend/test/unit/activitypub.ts index 88ff49b11900..b4b06b06bd05 100644 --- a/packages/backend/test/unit/activitypub.ts +++ b/packages/backend/test/unit/activitypub.ts @@ -203,7 +203,7 @@ describe('ActivityPub', () => { describe('Renderer', () => { test('Render an announce with visibility: followers', () => { - rendererService.renderAnnounce(null, { + rendererService.renderAnnounce('https://example.com/notes/00example', { id: genAidx(Date.now()), visibility: 'followers', } as MiNote); diff --git a/packages/backend/test/utils.ts b/packages/backend/test/utils.ts index d5da8e02265d..a2220ffae656 100644 --- a/packages/backend/test/utils.ts +++ b/packages/backend/test/utils.ts @@ -13,10 +13,11 @@ import fetch, { File, RequestInit } from 'node-fetch'; import { DataSource } from 'typeorm'; import { JSDOM } from 'jsdom'; import { DEFAULT_POLICIES } from '@/core/RoleService.js'; +import { Packed } from '@/misc/json-schema.js'; +import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js'; import { entities } from '../src/postgres.js'; import { loadConfig } from '../src/config.js'; import type * as misskey from 'misskey-js'; -import { Packed } from '@/misc/json-schema.js'; export { server as startServer, jobQueue as startJobQueue } from '@/boot/common.js'; @@ -123,9 +124,9 @@ export function randomString(chars = 'abcdefghijklmnopqrstuvwxyz0123456789', len function timeoutPromise(p: Promise, timeout: number): Promise { return Promise.race([ p, - new Promise((reject) =>{ - setTimeout(() => { reject(new Error('timed out')); }, timeout) - }) as never + new Promise((reject) => { + setTimeout(() => { reject(new Error('timed out')); }, timeout); + }) as never, ]); } @@ -327,7 +328,6 @@ export const uploadFile = async (user?: UserToken, { path, name, blob }: UploadO }); const body = res.status !== 204 ? await res.json() as misskey.Endpoints['drive/files/create']['res'] : null; - return { status: res.status, headers: res.headers, @@ -343,7 +343,7 @@ export const uploadUrl = async (user: UserToken, url: string): Promise msg.type === 'urlUploadFinished' && msg.body.marker === marker, (msg) => msg.body.file as Packed<'DriveFile'>, - 60 * 1000 + 60 * 1000, ); await api('drive/files/upload-from-url', { @@ -434,20 +434,20 @@ export const waitFire = async (user: UserToken, channel: string, trgr: () => any * @returns 時間内に正常に処理できた場合に通知からextractorを通した値を得る */ export function makeStreamCatcher( - user: UserToken, - channel: string, - cond: (message: Record) => boolean, - extractor: (message: Record) => T, - timeout = 60 * 1000): Promise { - let ws: WebSocket + user: UserToken, + channel: string, + cond: (message: Record) => boolean, + extractor: (message: Record) => T, + timeout = 60 * 1000): Promise { + let ws: WebSocket; const p = new Promise(async (resolve) => { ws = await connectStream(user, channel, (msg) => { if (cond(msg)) { - resolve(extractor(msg)) + resolve(extractor(msg)); } }); }).finally(() => { - ws?.close(); + ws.close(); }); return timeoutPromise(p, timeout); @@ -476,6 +476,14 @@ export const simpleGet = async (path: string, accept = '*/*', cookie: any = unde 'text/html; charset=utf-8', ]; + if (res.ok && ( + accept.startsWith('application/activity+json') || + (accept.startsWith('application/ld+json') && accept.includes('https://www.w3.org/ns/activitystreams')) + )) { + // validateContentTypeSetAsActivityPubのテストを兼ねる + validateContentTypeSetAsActivityPub(res); + } + const body = jsonTypes.includes(res.headers.get('content-type') ?? '') ? await res.json() : htmlTypes.includes(res.headers.get('content-type') ?? '') ? new JSDOM(await res.text()) : From fa243276c5d9acd2c3e49f06170c0187ad3e6dc0 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Sat, 17 Feb 2024 12:43:39 +0900 Subject: [PATCH 02/10] feat: add link to local note in initial comment of abuse note (#13347) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add link to local note in initial comment of abuse note * docs(changelog): ノートの通報時にリモートのノートであっても自インスタンスにおけるノートのリンクを含むように --- CHANGELOG.md | 1 + packages/frontend/src/scripts/get-note-menu.ts | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a6ff02db63c..b6db0b61ef38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ - センシティブなリアクションを認めていないユーザーにセンシティブなカスタム絵文字をリアクションしようとした場合 - ロールが必要な絵文字をリアクションしようとした場合 - Enhance: ページ遷移時にPlayerを閉じるように +- Enhance: ノートの通報時にリモートのノートであっても自インスタンスにおけるノートのリンクを含むように - Fix: ネイティブモードの絵文字がモノクロにならないように - Fix: v2023.12.0で追加された「モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能」が管理画面上で正しく表示されていない問題を修正 - Fix: AiScriptの`readline`関数が不正な値を返すことがある問題のv2023.12.0時点での修正がPlay以外に適用されていないのを修正 diff --git a/packages/frontend/src/scripts/get-note-menu.ts b/packages/frontend/src/scripts/get-note-menu.ts index ad46e5dfe75e..b273bd36f398 100644 --- a/packages/frontend/src/scripts/get-note-menu.ts +++ b/packages/frontend/src/scripts/get-note-menu.ts @@ -102,10 +102,13 @@ export function getAbuseNoteMenu(note: Misskey.entities.Note, text: string): Men icon: 'ti ti-exclamation-circle', text, action: (): void => { - const u = note.url ?? note.uri ?? `${url}/notes/${note.id}`; + const localUrl = `${url}/notes/${note.id}`; + let noteInfo = ''; + if (note.url ?? note.uri != null) noteInfo = `Note: ${note.url ?? note.uri}\n`; + noteInfo += `Local Note: ${localUrl}\n`; os.popup(defineAsyncComponent(() => import('@/components/MkAbuseReportWindow.vue')), { user: note.user, - initialComment: `Note: ${u}\n-----\n`, + initialComment: `${noteInfo}-----\n`, }, {}, 'closed'); }, }; From acba96c1d34572ed7bd454462c2462d2a32369f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Sat, 17 Feb 2024 13:34:50 +0900 Subject: [PATCH 03/10] feat: license violation protection (#13285) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * spec(frontend): aboutページにリポジトリ・フィードバックのURLを表示させる Cherry-picked from MisskeyIO#441 Cherry-picked from MisskeyIO#438 * feat: license violation protection * build: fix typo * build: fix typo * fix: farewell to the static type land * fix: key typo * fix: import typo * fix: properly interpret `prominently` * docs: add disclaimer * docs: update CHANGELOG * chore: add gap --------- Co-authored-by: まっちゃとーにゅ <17376330+u1-liquid@users.noreply.github.com> Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- .config/example.yml | 61 +++++++++- CHANGELOG.md | 3 + locales/index.d.ts | 40 +++++++ locales/ja-JP.yml | 10 ++ ...1707808106310-MakeRepositoryUrlNullable.js | 16 +++ packages/backend/src/config.ts | 4 + packages/backend/src/models/Meta.ts | 4 +- .../src/server/api/endpoints/admin/meta.ts | 2 +- .../server/api/endpoints/admin/update-meta.ts | 6 +- .../backend/src/server/api/endpoints/meta.ts | 9 +- packages/frontend/src/boot/main-boot.ts | 8 ++ .../components/MkSourceCodeAvailablePopup.vue | 112 ++++++++++++++++++ packages/frontend/src/local-storage.ts | 1 + packages/frontend/src/pages/about-misskey.vue | 24 +++- packages/frontend/src/pages/about.vue | 40 +++++-- .../frontend/src/pages/admin/branding.vue | 16 +++ .../frontend/src/pages/admin/settings.vue | 15 ++- packages/misskey-js/src/autogen/types.ts | 11 +- scripts/build-assets.mjs | 15 ++- 19 files changed, 371 insertions(+), 26 deletions(-) create mode 100644 packages/backend/migration/1707808106310-MakeRepositoryUrlNullable.js create mode 100644 packages/frontend/src/components/MkSourceCodeAvailablePopup.vue diff --git a/.config/example.yml b/.config/example.yml index 3c9c3bc0d74b..7fea9293746e 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -2,6 +2,63 @@ # Misskey configuration #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# ┌──────────────────────────────┐ +#───┘ a boring but important thing └──────────────────────────── + +# +# First of all, let me tell you a story that may possibly be +# boring to you and possibly important to you. +# +# Misskey is licensed under the AGPLv3 license. This license is +# known to be often misunderstood. Please read the following +# instructions carefully and select the appropriate option so +# that you do not negligently cause a license violation. +# + +# -------- +# Option 1: If you host Misskey AS-IS (without any changes to +# the source code. forks are not included). +# +# Step 1: Congratulations! You don't need to do anything. + +# -------- +# Option 2: If you have made changes to the source code (forks +# are included) and publish a Git repository of source +# code. There should be no access restrictions on +# this repository. Strictly speaking, it doesn't have +# to be a Git repository, but you'll probably use Git! +# +# Step 1: Build and run the Misskey server first. +# Step 2: Open in +# your browser with the administrator account. +# Step 3: Enter the URL of your Git repository in the +# "Repository URL" field. + +# -------- +# Option 3: If neither of the above applies to you. +# (In this case, the source code should be published +# on the Misskey interface. IT IS NOT ENOUGH TO +# DISCLOSE THE SOURCE CODE WEHN A USER REQUESTS IT BY +# E-MAIL OR OTHER MEANS. If you are not satisfied +# with this, it is recommended that you read the +# license again carefully. Anyway, enabling this +# option will automatically generate and publish a +# tarball at build time, protecting you from +# inadvertent license violations. (There is no legal +# guarantee, of course.) The tarball will generated +# from the root directory of your codebase. So it is +# also recommended to check directory +# once after building and before activating the server +# to avoid ACCIDENTAL LEAKING OF SENSITIVE INFORMATION. +# To prevent certain files from being included in the +# tarball, add a glob pattern after line 15 in +# . DO NOT FORGET TO BUILD AFTER +# ENABLING THIS OPTION!) +# +# Step 1: Uncomment the following line. +# +# publishTarballInsteadOfProvideRepositoryUrl: true + # ┌─────┐ #───┘ URL └───────────────────────────────────────────────────── @@ -118,7 +175,7 @@ redis: # ┌───────────────────────────┐ #───┘ MeiliSearch configuration └───────────────────────────── -# You can set scope to local (default value) or global +# You can set scope to local (default value) or global # (include notes from remote). #meilisearch: @@ -214,7 +271,7 @@ proxyRemoteFiles: true signToActivityPubGet: true # For security reasons, uploading attachments from the intranet is prohibited, -# but exceptions can be made from the following settings. Default value is "undefined". +# but exceptions can be made from the following settings. Default value is "undefined". # Read changelog to learn more (Improvements of 12.90.0 (2021/09/04)). #allowedPrivateNetworks: [ # '127.0.0.1/32' diff --git a/CHANGELOG.md b/CHANGELOG.md index b6db0b61ef38..e70a3e34134b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,9 @@ ### General - Feat: [mCaptcha](https://github.com/mCaptcha/mCaptcha)のサポートを追加 - Feat: Add support for TrueMail +- Feat: AGPLv3ライセンスに誤って違反するのを防止する機能を追加 + - 管理者がrepositoryUrlを変更したり、またはソースコードを直接頒布することを選択できるようになります + - 本体のソースコードに改変を加えた際に、ライセンスに基づく適切な案内を表示します - Enhance: モデレーターはすべてのユーザーのリアクション一覧を見られるように - Fix: リストライムラインの「リノートを表示」が正しく機能しない問題を修正 - Fix: リモートユーザーのリアクション一覧がすべて見えてしまうのを修正 diff --git a/locales/index.d.ts b/locales/index.d.ts index 8f4c9d18e4b5..1bc99ab84904 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -3980,6 +3980,10 @@ export interface Locale extends ILocale { * Misskeyは{host}が使用している無料のソフトウェアです。これからも開発を続けられるように、ぜひ寄付をお願いします! */ "pleaseDonate": ParameterizedString<"host">; + /** + * 対応するソースコードは{anchor}から利用可能です。 + */ + "correspondingSourceIsAvailable": ParameterizedString<"anchor">; /** * ロール */ @@ -4684,6 +4688,34 @@ export interface Locale extends ILocale { * 外部サービス */ "externalServices": string; + /** + * ソースコード + */ + "sourceCode": string; + /** + * ソースコードはまだ提供されていません。この問題の修正について管理者に問い合わせてください。 + */ + "sourceCodeIsNotYetProvided": string; + /** + * リポジトリURL + */ + "repositoryUrl": string; + /** + * ソースコードが公開されているリポジトリがある場合、そのURLを記入します。Misskeyを現状のまま(ソースコードにいかなる変更も加えずに)使用している場合は https://github.com/misskey-dev/misskey と記入します。 + */ + "repositoryUrlDescription": string; + /** + * リポジトリを公開していない場合、代わりにtarballを提供する必要があります。詳細は.config/example.ymlを参照してください。 + */ + "repositoryUrlOrTarballRequired": string; + /** + * フィードバック + */ + "feedback": string; + /** + * フィードバックURL + */ + "feedbackUrl": string; /** * 運営者情報 */ @@ -6813,6 +6845,14 @@ export interface Locale extends ILocale { * ソースコード */ "source": string; + /** + * オリジナル + */ + "original": string; + /** + * {name}はオリジナルのMisskeyを改変したバージョンを使用しています。 + */ + "thisIsModifiedVersion": ParameterizedString<"name">; /** * Misskeyを翻訳 */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 534850242535..5993ec80d0ce 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -991,6 +991,7 @@ neverShow: "今後表示しない" remindMeLater: "また後で" didYouLikeMisskey: "Misskeyを気に入っていただけましたか?" pleaseDonate: "Misskeyは{host}が使用している無料のソフトウェアです。これからも開発を続けられるように、ぜひ寄付をお願いします!" +correspondingSourceIsAvailable: "対応するソースコードは{anchor}から利用可能です。" roles: "ロール" role: "ロール" noRole: "ロールはありません" @@ -1167,6 +1168,13 @@ hideRepliesToOthersInTimelineAll: "TLに現在フォロー中の人全員の返 confirmShowRepliesAll: "この操作は元に戻せません。本当にTLに現在フォロー中の人全員の返信を含めるようにしますか?" confirmHideRepliesAll: "この操作は元に戻せません。本当にTLに現在フォロー中の人全員の返信を含めないようにしますか?" externalServices: "外部サービス" +sourceCode: "ソースコード" +sourceCodeIsNotYetProvided: "ソースコードはまだ提供されていません。この問題の修正について管理者に問い合わせてください。" +repositoryUrl: "リポジトリURL" +repositoryUrlDescription: "ソースコードが公開されているリポジトリがある場合、そのURLを記入します。Misskeyを現状のまま(ソースコードにいかなる変更も加えずに)使用している場合は https://github.com/misskey-dev/misskey と記入します。" +repositoryUrlOrTarballRequired: "リポジトリを公開していない場合、代わりにtarballを提供する必要があります。詳細は.config/example.ymlを参照してください。" +feedback: "フィードバック" +feedbackUrl: "フィードバックURL" impressum: "運営者情報" impressumUrl: "運営者情報URL" impressumDescription: "ドイツなどの一部の国と地域では表示が義務付けられています(Impressum)。" @@ -1778,6 +1786,8 @@ _aboutMisskey: contributors: "コントリビューター" allContributors: "全てのコントリビューター" source: "ソースコード" + original: "オリジナル" + thisIsModifiedVersion: "{name}はオリジナルのMisskeyを改変したバージョンを使用しています。" translation: "Misskeyを翻訳" donate: "Misskeyに寄付" morePatrons: "他にも多くの方が支援してくれています。ありがとうございます🥰" diff --git a/packages/backend/migration/1707808106310-MakeRepositoryUrlNullable.js b/packages/backend/migration/1707808106310-MakeRepositoryUrlNullable.js new file mode 100644 index 000000000000..335b14976c34 --- /dev/null +++ b/packages/backend/migration/1707808106310-MakeRepositoryUrlNullable.js @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class MakeRepositoryUrlNullable1707808106310 { + name = 'MakeRepositoryUrlNullable1707808106310' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "repositoryUrl" DROP NOT NULL`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "repositoryUrl" SET NOT NULL`); + } +} diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 308da4481b44..0ca1fa55c1f8 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -57,6 +57,8 @@ type Source = { scope?: 'local' | 'global' | string[]; }; + publishTarballInsteadOfProvideRepositoryUrl?: boolean; + proxy?: string; proxySmtp?: string; proxyBypassHosts?: string[]; @@ -145,6 +147,7 @@ export type Config = { signToActivityPubGet: boolean | undefined; version: string; + publishTarballInsteadOfProvideRepositoryUrl: boolean; host: string; hostname: string; scheme: string; @@ -209,6 +212,7 @@ export function loadConfig(): Config { return { version, + publishTarballInsteadOfProvideRepositoryUrl: !!config.publishTarballInsteadOfProvideRepositoryUrl, url: url.origin, port: config.port ?? parseInt(process.env.PORT ?? '', 10), socket: config.socket, diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts index 63503fbe0659..6ed0ec6ce50d 100644 --- a/packages/backend/src/models/Meta.ts +++ b/packages/backend/src/models/Meta.ts @@ -357,9 +357,9 @@ export class MiMeta { @Column('varchar', { length: 1024, default: 'https://github.com/misskey-dev/misskey', - nullable: false, + nullable: true, }) - public repositoryUrl: string; + public repositoryUrl: string | null; @Column('varchar', { length: 1024, diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index ef569722e044..88c5907bcc80 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -429,7 +429,7 @@ export const meta = { }, repositoryUrl: { type: 'string', - optional: false, nullable: false, + optional: false, nullable: true, }, summalyProxy: { type: 'string', diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index 51075ed3c646..bffceef8151d 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -104,8 +104,8 @@ export const paramDef = { swPublicKey: { type: 'string', nullable: true }, swPrivateKey: { type: 'string', nullable: true }, tosUrl: { type: 'string', nullable: true }, - repositoryUrl: { type: 'string' }, - feedbackUrl: { type: 'string' }, + repositoryUrl: { type: 'string', nullable: true }, + feedbackUrl: { type: 'string', nullable: true }, impressumUrl: { type: 'string', nullable: true }, privacyPolicyUrl: { type: 'string', nullable: true }, useObjectStorage: { type: 'boolean' }, @@ -402,7 +402,7 @@ export default class extends Endpoint { // eslint- } if (ps.repositoryUrl !== undefined) { - set.repositoryUrl = ps.repositoryUrl; + set.repositoryUrl = URL.canParse(ps.repositoryUrl!) ? ps.repositoryUrl : null; } if (ps.feedbackUrl !== undefined) { diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 6bcd7f6b1f3d..834158baf41a 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -37,6 +37,10 @@ export const meta = { type: 'string', optional: false, nullable: false, }, + providesTarball: { + type: 'boolean', + optional: false, nullable: false, + }, name: { type: 'string', optional: false, nullable: false, @@ -69,12 +73,12 @@ export const meta = { }, repositoryUrl: { type: 'string', - optional: false, nullable: false, + optional: false, nullable: true, default: 'https://github.com/misskey-dev/misskey', }, feedbackUrl: { type: 'string', - optional: false, nullable: false, + optional: false, nullable: true, default: 'https://github.com/misskey-dev/misskey/issues/new', }, defaultDarkTheme: { @@ -352,6 +356,7 @@ export default class extends Endpoint { // eslint- maintainerEmail: instance.maintainerEmail, version: this.config.version, + providesTarball: this.config.publishTarballInsteadOfProvideRepositoryUrl, name: instance.name, shortName: instance.shortName, diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index afe8e2ac1b37..b19d45a35e87 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -11,6 +11,7 @@ import { alert, confirm, popup, post, toast } from '@/os.js'; import { useStream } from '@/stream.js'; import * as sound from '@/scripts/sound.js'; import { $i, signout, updateAccount } from '@/account.js'; +import { fetchInstance, instance } from '@/instance.js'; import { ColdDeviceStorage, defaultStore } from '@/store.js'; import { makeHotkey } from '@/scripts/hotkey.js'; import { reactionPicker } from '@/scripts/reaction-picker.js'; @@ -234,6 +235,13 @@ export async function mainBoot() { } } + fetchInstance().then(() => { + const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read'); + if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') { + popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {}, 'closed'); + } + }); + if ('Notification' in window) { // 許可を得ていなかったらリクエスト if (Notification.permission === 'default') { diff --git a/packages/frontend/src/components/MkSourceCodeAvailablePopup.vue b/packages/frontend/src/components/MkSourceCodeAvailablePopup.vue new file mode 100644 index 000000000000..80f3a6709c5e --- /dev/null +++ b/packages/frontend/src/components/MkSourceCodeAvailablePopup.vue @@ -0,0 +1,112 @@ + + + + + + + diff --git a/packages/frontend/src/local-storage.ts b/packages/frontend/src/local-storage.ts index 355715bcc693..3de81c9bb9dc 100644 --- a/packages/frontend/src/local-storage.ts +++ b/packages/frontend/src/local-storage.ts @@ -12,6 +12,7 @@ type Keys = 'latestDonationInfoShownAt' | 'neverShowDonationInfo' | 'neverShowLocalOnlyInfo' | + 'modifiedVersionMustProminentlyOfferInAgplV3Section13Read' | 'lastUsed' | 'lang' | 'drafts' | diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue index a2ecae3b80bc..fd97ab97b919 100644 --- a/packages/frontend/src/pages/about-misskey.vue +++ b/packages/frontend/src/pages/about-misskey.vue @@ -31,7 +31,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ i18n.ts._aboutMisskey.source }} + {{ i18n.ts._aboutMisskey.source }} ({{ i18n.ts._aboutMisskey.original }}) @@ -46,6 +46,25 @@ SPDX-License-Identifier: AGPL-3.0-only
+ +
+ + {{ i18n.tsx._aboutMisskey.thisIsModifiedVersion({ name: instance.name }) }} + + + + {{ i18n.ts._aboutMisskey.source }} + + + + {{ i18n.ts._aboutMisskey.source }} + + + + {{ i18n.ts.sourceCodeIsNotYetProvided }} + +
+
@@ -118,9 +137,10 @@ import { version } from '@/config.js'; import FormLink from '@/components/form/link.vue'; import FormSection from '@/components/form/section.vue'; import MkButton from '@/components/MkButton.vue'; -import MkLink from '@/components/MkLink.vue'; +import MkInfo from '@/components/MkInfo.vue'; import { physics } from '@/scripts/physics.js'; import { i18n } from '@/i18n.js'; +import { instance } from '@/instance.js'; import { defaultStore } from '@/store.js'; import * as os from '@/os.js'; import { definePageMetadata } from '@/scripts/page-metadata.js'; diff --git a/packages/frontend/src/pages/about.vue b/packages/frontend/src/pages/about.vue index f99eb9c57777..324d1c11defe 100644 --- a/packages/frontend/src/pages/about.vue +++ b/packages/frontend/src/pages/about.vue @@ -31,7 +31,17 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ i18n.ts.aboutMisskey }} + + + {{ i18n.ts.aboutMisskey }} + + + + {{ i18n.ts.sourceCode }} + + + {{ i18n.ts.sourceCodeIsNotYetProvided }} +
@@ -47,17 +57,33 @@ SPDX-License-Identifier: AGPL-3.0-only - {{ i18n.ts.impressum }} + + + {{ i18n.ts.impressum }} +
- +
    -
  1. +
- {{ i18n.ts.termsOfService }} - {{ i18n.ts.privacyPolicy }} + + + {{ i18n.ts.termsOfService }} + + + + {{ i18n.ts.privacyPolicy }} + + + + {{ i18n.ts.feedback }} +
@@ -86,7 +112,6 @@ SPDX-License-Identifier: AGPL-3.0-only nodeinfo robots.txt manifest.json - source code @@ -116,6 +141,7 @@ import FormSuspense from '@/components/form/suspense.vue'; import FormSplit from '@/components/form/split.vue'; import MkFolder from '@/components/MkFolder.vue'; import MkKeyValue from '@/components/MkKeyValue.vue'; +import MkInfo from '@/components/MkInfo.vue'; import MkInstanceStats from '@/components/MkInstanceStats.vue'; import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue'; import { misskeyApi } from '@/scripts/misskey-api.js'; diff --git a/packages/frontend/src/pages/admin/branding.vue b/packages/frontend/src/pages/admin/branding.vue index 4ac2011aafb3..2b559f92c9bd 100644 --- a/packages/frontend/src/pages/admin/branding.vue +++ b/packages/frontend/src/pages/admin/branding.vue @@ -76,6 +76,16 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + + + + + + + @@ -120,6 +130,8 @@ const defaultDarkTheme = ref(null); const serverErrorImageUrl = ref(null); const infoImageUrl = ref(null); const notFoundImageUrl = ref(null); +const repositoryUrl = ref(null); +const feedbackUrl = ref(null); const manifestJsonOverride = ref('{}'); async function init() { @@ -135,6 +147,8 @@ async function init() { serverErrorImageUrl.value = meta.serverErrorImageUrl; infoImageUrl.value = meta.infoImageUrl; notFoundImageUrl.value = meta.notFoundImageUrl; + repositoryUrl.value = meta.repositoryUrl; + feedbackUrl.value = meta.feedbackUrl; manifestJsonOverride.value = meta.manifestJsonOverride === '' ? '{}' : JSON.stringify(JSON.parse(meta.manifestJsonOverride), null, '\t'); } @@ -151,6 +165,8 @@ function save() { infoImageUrl: infoImageUrl.value === '' ? null : infoImageUrl.value, notFoundImageUrl: notFoundImageUrl.value === '' ? null : notFoundImageUrl.value, serverErrorImageUrl: serverErrorImageUrl.value === '' ? null : serverErrorImageUrl.value, + repositoryUrl: repositoryUrl.value === '' ? null : repositoryUrl.value, + feedbackUrl: feedbackUrl.value === '' ? null : feedbackUrl.value, manifestJsonOverride: manifestJsonOverride.value === '' ? '{}' : JSON.stringify(JSON5.parse(manifestJsonOverride.value)), }).then(() => { fetchInstance(); diff --git a/packages/frontend/src/pages/admin/settings.vue b/packages/frontend/src/pages/admin/settings.vue index 8af9deae6250..c505d70aa980 100644 --- a/packages/frontend/src/pages/admin/settings.vue +++ b/packages/frontend/src/pages/admin/settings.vue @@ -34,6 +34,16 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + + + + + {{ i18n.ts.repositoryUrlOrTarballRequired }} + + @@ -159,7 +169,7 @@ import FormSplit from '@/components/form/split.vue'; import FormSuspense from '@/components/form/suspense.vue'; import * as os from '@/os.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; -import { fetchInstance } from '@/instance.js'; +import { fetchInstance, instance } from '@/instance.js'; import { i18n } from '@/i18n.js'; import { definePageMetadata } from '@/scripts/page-metadata.js'; import MkButton from '@/components/MkButton.vue'; @@ -169,6 +179,7 @@ const shortName = ref(null); const description = ref(null); const maintainerName = ref(null); const maintainerEmail = ref(null); +const repositoryUrl = ref(null); const impressumUrl = ref(null); const pinnedUsers = ref(''); const cacheRemoteFiles = ref(false); @@ -191,6 +202,7 @@ async function init(): Promise { description.value = meta.description; maintainerName.value = meta.maintainerName; maintainerEmail.value = meta.maintainerEmail; + repositoryUrl.value = meta.repositoryUrl; impressumUrl.value = meta.impressumUrl; pinnedUsers.value = meta.pinnedUsers.join('\n'); cacheRemoteFiles.value = meta.cacheRemoteFiles; @@ -214,6 +226,7 @@ async function save(): void { description: description.value, maintainerName: maintainerName.value, maintainerEmail: maintainerEmail.value, + repositoryUrl: repositoryUrl.value, impressumUrl: impressumUrl.value, pinnedUsers: pinnedUsers.value.split('\n'), cacheRemoteFiles: cacheRemoteFiles.value, diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index ad3a9a7c661b..d0d8573b407c 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -4845,7 +4845,7 @@ export type operations = { shortName: string | null; objectStorageS3ForcePathStyle: boolean; privacyPolicyUrl: string | null; - repositoryUrl: string; + repositoryUrl: string | null; summalyProxy: string | null; themeColor: string | null; tosUrl: string | null; @@ -8757,8 +8757,8 @@ export type operations = { swPublicKey?: string | null; swPrivateKey?: string | null; tosUrl?: string | null; - repositoryUrl?: string; - feedbackUrl?: string; + repositoryUrl?: string | null; + feedbackUrl?: string | null; impressumUrl?: string | null; privacyPolicyUrl?: string | null; useObjectStorage?: boolean; @@ -19450,6 +19450,7 @@ export type operations = { maintainerName: string | null; maintainerEmail: string | null; version: string; + providesTarball: boolean; name: string; shortName: string | null; /** @@ -19461,9 +19462,9 @@ export type operations = { langs: string[]; tosUrl: string | null; /** @default https://github.com/misskey-dev/misskey */ - repositoryUrl: string; + repositoryUrl: string | null; /** @default https://github.com/misskey-dev/misskey/issues/new */ - feedbackUrl: string; + feedbackUrl: string | null; defaultDarkTheme: string | null; defaultLightTheme: string | null; disableRegistration: boolean; diff --git a/scripts/build-assets.mjs b/scripts/build-assets.mjs index bafb1da5d975..e7684d7cc9e4 100644 --- a/scripts/build-assets.mjs +++ b/scripts/build-assets.mjs @@ -5,7 +5,9 @@ import * as fs from 'node:fs/promises'; import * as path from 'node:path'; +import { fileURLToPath } from 'node:url'; import cssnano from 'cssnano'; +import * as yaml from 'js-yaml'; import postcss from 'postcss'; import * as terser from 'terser'; @@ -14,8 +16,19 @@ import generateDTS from '../locales/generateDTS.js'; import meta from '../package.json' assert { type: "json" }; import buildTarball from './tarball.mjs'; +const configDir = fileURLToPath(new URL('../.config', import.meta.url)); +const configPath = process.env.MISSKEY_CONFIG_YML + ? path.resolve(configDir, process.env.MISSKEY_CONFIG_YML) + : process.env.NODE_ENV === 'test' + ? path.resolve(configDir, 'test.yml') + : path.resolve(configDir, 'default.yml'); + let locales = buildLocales(); +async function loadConfig() { + return fs.readFile(configPath, 'utf-8').then(data => yaml.load(data)).catch(() => null); +} + async function copyFrontendFonts() { await fs.cp('./packages/frontend/node_modules/three/examples/fonts', './built/_frontend_dist_/fonts', { dereference: true, recursive: true }); } @@ -78,7 +91,7 @@ async function build() { copyBackendViews(), buildBackendScript(), buildBackendStyle(), - buildTarball(), + loadConfig().then(config => config?.publishTarballInsteadOfProvideRepositoryUrl && buildTarball()), ]); } From d961ed830fe42477a3e2d7f99078df4e1fdf726f Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 17 Feb 2024 13:36:39 +0900 Subject: [PATCH 04/10] Update CHANGELOG.md --- CHANGELOG.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6db0b61ef38..43746dbfbf6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ - ロールが必要な絵文字をリアクションしようとした場合 - Enhance: ページ遷移時にPlayerを閉じるように - Enhance: ノートの通報時にリモートのノートであっても自インスタンスにおけるノートのリンクを含むように +- Enhance: オフライン表示のデザインを改善・多言語対応 - Fix: ネイティブモードの絵文字がモノクロにならないように - Fix: v2023.12.0で追加された「モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能」が管理画面上で正しく表示されていない問題を修正 - Fix: AiScriptの`readline`関数が不正な値を返すことがある問題のv2023.12.0時点での修正がPlay以外に適用されていないのを修正 @@ -95,9 +96,6 @@ - Fix: コントロールパネル->モデレーション->「誰でも新規登録できるようにする」の初期値をONからOFFに変更 #13122 - Fix: リモートユーザーが復活してもキャッシュにより該当ユーザーのActivityが受け入れられないのを修正 #13273 -### Service Worker -- Enhance: オフライン表示のデザインを改善・多言語対応 - ## 2023.12.2 ### General From 0b5d3315bcf5682e519a32a1ff4d98bbaf845502 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 17 Feb 2024 13:41:24 +0900 Subject: [PATCH 05/10] 2024.2.0 --- CHANGELOG.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e35d9e2b663..b6c282259073 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ --> -## 202x.x.x (Unreleased) +## 2024.2.0 ### Note - 外部サイトからプラグインをインストールする場合のパスが`/install-extentions`から`/install-extensions`に変わります。以前のパスからは自動でリダイレクトされるようになっていますが、新しいパスに変更することをお勧めします。 diff --git a/package.json b/package.json index f8dd5aeadc91..3f94448db7ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2024.2.0-beta.13", + "version": "2024.2.0", "codename": "nasubi", "repository": { "type": "git", From 875069c6b08d4d2bdb8661120c23ee2b228961b5 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 17 Feb 2024 13:43:04 +0900 Subject: [PATCH 06/10] Update package.json --- packages/misskey-js/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index 094a6e721401..051c63cbe179 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "misskey-js", - "version": "2024.2.0-beta.13", + "version": "2024.2.0", "description": "Misskey SDK for JavaScript", "types": "./built/dts/index.d.ts", "exports": { From 01de1519dda0188121d4d1558310beaa24dbe8af Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 17 Feb 2024 14:26:48 +0900 Subject: [PATCH 07/10] fix of 9a70ce8f5ea9df00001894809f5ce7bc69b14c8a Co-Authored-By: RyotaK <49341894+Ry0taK@users.noreply.github.com> --- packages/backend/src/core/activitypub/misc/validator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/core/activitypub/misc/validator.ts b/packages/backend/src/core/activitypub/misc/validator.ts index 6ba14a222fe5..690beeffef5d 100644 --- a/packages/backend/src/core/activitypub/misc/validator.ts +++ b/packages/backend/src/core/activitypub/misc/validator.ts @@ -20,7 +20,7 @@ export function validateContentTypeSetAsActivityPub(response: Response): void { throw new Error('Validate content type of AP response: Content type is not application/activity+json or application/ld+json'); } -const plusJsonSuffixRegex = /(application|text)\/[a-zA-Z0-9\.\-\+]+\+json/; +const plusJsonSuffixRegex = /^\s*(application|text)\/[a-zA-Z0-9\.\-\+]+\+json\s*(;|$)/; export function validateContentTypeSetAsJsonLD(response: Response): void { const contentType = (response.headers.get('content-type') ?? '').toLowerCase(); From d4a5e31c8da6307994d35f6a79a7c282e20b1bc0 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sat, 17 Feb 2024 14:27:42 +0900 Subject: [PATCH 08/10] New Crowdin updates (#13341) * New translations ja-jp.yml (Indonesian) * New translations ja-jp.yml (Indonesian) * New translations ja-jp.yml (Catalan) * New translations ja-jp.yml (German) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Chinese Simplified) * New translations ja-jp.yml (French) * New translations ja-jp.yml (Spanish) * New translations ja-jp.yml (Arabic) * New translations ja-jp.yml (Czech) * New translations ja-jp.yml (Italian) * New translations ja-jp.yml (Polish) * New translations ja-jp.yml (Russian) * New translations ja-jp.yml (Slovak) * New translations ja-jp.yml (Ukrainian) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (English) * New translations ja-jp.yml (Vietnamese) * New translations ja-jp.yml (Indonesian) * New translations ja-jp.yml (Bengali) * New translations ja-jp.yml (Thai) * New translations ja-jp.yml (Japanese, Kansai) --- locales/ar-SA.yml | 1 + locales/bn-BD.yml | 1 + locales/ca-ES.yml | 1 + locales/cs-CZ.yml | 1 + locales/de-DE.yml | 1 + locales/en-US.yml | 1 + locales/es-ES.yml | 1 + locales/fr-FR.yml | 1 + locales/id-ID.yml | 107 +++++++++++++++++++++++++++++++++++++++++++++- locales/it-IT.yml | 1 + locales/ja-KS.yml | 1 + locales/ko-KR.yml | 1 + locales/pl-PL.yml | 1 + locales/ru-RU.yml | 1 + locales/sk-SK.yml | 1 + locales/th-TH.yml | 1 + locales/uk-UA.yml | 1 + locales/vi-VN.yml | 1 + locales/zh-CN.yml | 1 + locales/zh-TW.yml | 1 + 20 files changed, 125 insertions(+), 1 deletion(-) diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml index 47f131032a37..b0f7408587e3 100644 --- a/locales/ar-SA.yml +++ b/locales/ar-SA.yml @@ -1011,6 +1011,7 @@ expired: "منتهية صلاحيته" icon: "الصورة الرمزية" replies: "رد" renotes: "أعد النشر" +sourceCode: "الشفرة المصدرية" flip: "اقلب" lastNDays: "آخر {n} أيام" _initialAccountSetting: diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml index 42edad1fd0b6..2a23cda06bda 100644 --- a/locales/bn-BD.yml +++ b/locales/bn-BD.yml @@ -855,6 +855,7 @@ youFollowing: "অনুসরণ করা হচ্ছে" icon: "প্রোফাইল ছবি" replies: "জবাব" renotes: "রিনোট" +sourceCode: "সোর্স কোড" flip: "উল্টান" _role: priority: "অগ্রাধিকার" diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 656afb76107d..af5329dc7e9b 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -1167,6 +1167,7 @@ hideRepliesToOthersInTimelineAll: "Ocultar les teves respostes a tots els usuari confirmShowRepliesAll: "Aquesta opció no té marxa enrere. Vols mostrar les teves respostes a tots els que segueixes a la teva línia de temps?" confirmHideRepliesAll: "Aquesta opció no té marxa enrere. Vols ocultar les teves respostes a tots els usuaris que segueixes a la línia de temps?" externalServices: "Serveis externs" +sourceCode: "Codi font" impressum: "Impressum" impressumUrl: "Adreça URL impressum" impressumDescription: "A països, com Alemanya, la inclusió de la informació de contacte de l'operador (un Impressum) és requereix de manera legal per llocs comercials." diff --git a/locales/cs-CZ.yml b/locales/cs-CZ.yml index 7da9461af10e..3161ff275a57 100644 --- a/locales/cs-CZ.yml +++ b/locales/cs-CZ.yml @@ -1095,6 +1095,7 @@ iHaveReadXCarefullyAndAgree: "Přečetl jsem si text \"{x}\" a souhlasím s ním icon: "Avatar" replies: "Odpovědět" renotes: "Přeposlat" +sourceCode: "Zdrojový kód" flip: "Otočit" lastNDays: "Posledních {n} dnů" _initialAccountSetting: diff --git a/locales/de-DE.yml b/locales/de-DE.yml index a4412395f64f..f733fa1ee90d 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -1158,6 +1158,7 @@ hideRepliesToOthersInTimelineAll: "Antworten von allen momentan gefolgten Benutz confirmShowRepliesAll: "Dies ist eine unwiderrufliche Aktion. Wirklich Antworten von allen momentan gefolgten Benutzern in der Chronik anzeigen?" confirmHideRepliesAll: "Dies ist eine unwiderrufliche Aktion. Wirklich Antworten von allen momentan gefolgten Benutzern nicht in der Chronik anzeigen?" externalServices: "Externe Dienste" +sourceCode: "Quellcode" impressum: "Impressum" impressumUrl: "Impressums-URL" impressumDescription: "In manchen Ländern, wie Deutschland und dessen Umgebung, ist die Angabe von Betreiberinformationen (ein Impressum) bei kommerziellem Betrieb zwingend." diff --git a/locales/en-US.yml b/locales/en-US.yml index 16b7558456e8..084f6b23b94b 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1165,6 +1165,7 @@ hideRepliesToOthersInTimelineAll: "Hide replies to others from everyone you foll confirmShowRepliesAll: "This operation is irreversible. Would you really like to show replies to others from everyone you follow in your timeline?" confirmHideRepliesAll: "This operation is irreversible. Would you really like to hide replies to others from everyone you follow in your timeline?" externalServices: "External Services" +sourceCode: "Source code" impressum: "Impressum" impressumUrl: "Impressum URL" impressumDescription: "In some countries, like germany, the inclusion of operator contact information (an Impressum) is legally required for commercial websites." diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 89961b24cb80..2952e89f8396 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -1166,6 +1166,7 @@ hideRepliesToOthersInTimelineAll: "Ocultar tus respuestas a otros usuarios que s confirmShowRepliesAll: "Esta operación es irreversible. ¿Confirmas que quieres mostrar tus respuestas a otros usuarios que sigues en tu línea de tiempo?" confirmHideRepliesAll: "Esta operación es irreversible. ¿Confirmas que quieres ocultar tus respuestas a otros usuarios que sigues en tu línea de tiempo?" externalServices: "Servicios Externos" +sourceCode: "Código fuente" impressum: "Impressum" impressumUrl: "Impressum URL" impressumDescription: "En algunos países, como Alemania, la inclusión del operador de datos (el Impressum) es requerido legalmente para sitios web comerciales." diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 8527ddd0eab7..35fac49cddde 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -1136,6 +1136,7 @@ hideRepliesToOthersInTimelineAll: "Masquer les réponses de toutes les personnes confirmShowRepliesAll: "Cette opération est irréversible. Voulez-vous vraiment afficher les réponses de toutes les personnes que vous suivez dans le fil ?" confirmHideRepliesAll: "Cette opération est irréversible. Voulez-vous vraiment masquer les réponses de toutes les personnes que vous suivez dans le fil ?" externalServices: "Services externes" +sourceCode: "Code source" impressum: "Impressum" impressumUrl: "URL de l'impressum" impressumDescription: "Dans certains pays comme l'Allemagne, il est obligatoire d'afficher les informations sur l'opérateur d'un site (un impressum)." diff --git a/locales/id-ID.yml b/locales/id-ID.yml index b38e95596bd7..58a248996b95 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -81,7 +81,7 @@ exportRequested: "Kamu telah meminta ekspor. Ini akan memakan waktu sesaat. Sete importRequested: "Kamu telah meminta impor. Ini akan memakan waktu sesaat." lists: "Daftar" noLists: "Kamu tidak memiliki daftar apapun" -note: "Catat" +note: "Catatan" notes: "Catatan" following: "Ikuti" followers: "Pengikut" @@ -381,8 +381,10 @@ enableHcaptcha: "Nyalakan hCaptcha" hcaptchaSiteKey: "Site Key" hcaptchaSecretKey: "Secret Key" mcaptcha: "mCaptcha" +enableMcaptcha: "Nyalakan mCaptcha" mcaptchaSiteKey: "Site key" mcaptchaSecretKey: "Secret Key" +mcaptchaInstanceUrl: "URL instansi mCaptcha" recaptcha: "reCAPTCHA" enableRecaptcha: "Nyalakan reCAPTCHA" recaptchaSiteKey: "Site key" @@ -630,6 +632,7 @@ medium: "Sedang" small: "Kecil" generateAccessToken: "Buat token akses" permission: "Izin" +adminPermission: "Wewenang Izin Admin" enableAll: "Aktifkan semua" disableAll: "Nonaktifkan semua" tokenRequested: "Berikan ijin akses ke akun" @@ -1038,6 +1041,7 @@ resetPasswordConfirm: "Yakin untuk mereset kata sandimu?" sensitiveWords: "Kata sensitif" sensitiveWordsDescription: "Visibilitas dari semua catatan mengandung kata yang telah diatur akan dijadikan \"Beranda\" secara otomatis. Kamu dapat mendaftarkan kata tersebut lebih dari satu dengan menuliskannya di baris baru." sensitiveWordsDescription2: "Menggunakan spasi akan membuat ekspresi AND dan kata kunci disekitarnya dengan garis miring akan mengubahnya menjadi ekspresi reguler." +prohibitedWords: "Kata yang dilarang" prohibitedWordsDescription2: "Menggunakan spasi akan membuat ekspresi AND dan kata kunci disekitarnya dengan garis miring akan mengubahnya menjadi ekspresi reguler." hiddenTags: "Tagar tersembunyi" hiddenTagsDescription: "Pilih tanda yang mana akan tidak diperlihatkan dalam daftar tren.\nTanda lebih dari satu dapat didaftarkan dengan tiap baris." @@ -1057,6 +1061,8 @@ limitWidthOfReaction: "Batasi lebar maksimum reaksi dan tampilkan dalam ukuran t noteIdOrUrl: "ID catatan atau URL" video: "Video" videos: "Video" +audio: "Suara" +audioFiles: "Berkas Suara" dataSaver: "Penghemat data" accountMigration: "Pemindahan akun" accountMoved: "Pengguna ini telah berpindah ke akun baru:" @@ -1160,6 +1166,7 @@ hideRepliesToOthersInTimelineAll: "Sembuyikan balasan ke lainnya dari semua oran confirmShowRepliesAll: "Operasi ini tidak dapat diubah. Apakah kamu yakin untuk menampilkan balasan ke lainnya dari semua orang yang kamu ikuti di lini masa?" confirmHideRepliesAll: "Operasi ini tidak dapat diubah. Apakah kamu yakin untuk menyembunyikan balasan ke lainnya dari semua orang yang kamu ikuti di lini masa?" externalServices: "Layanan eksternal" +sourceCode: "Sumber kode" impressum: "Impressum" impressumUrl: "Tautan Impressum" impressumDescription: "Pada beberapa negara seperti Jerman, inklusi dari informasi kontak operator (sebuah Impressum) diperlukan secara legal untuk situs web komersil." @@ -1191,10 +1198,21 @@ addMfmFunction: "Tambahkan dekorasi" enableQuickAddMfmFunction: "Tampilkan pemilih MFM tingkat lanjut" bubbleGame: "Bubble Game" sfx: "Efek Suara" +soundWillBePlayed: "Suara yang akan dimainkan" +showReplay: "Lihat tayangan ulang" +replay: "Tayangan ulang" +replaying: "Menayangkan Ulang" +ranking: "Peringkat" lastNDays: "{n} hari terakhir" backToTitle: "Ke Judul" +hemisphere: "Letak kamu tinggal" +withSensitive: "Lampirkan catatan dengan berkas sensitif" +userSaysSomethingSensitive: "Postingan oleh {name} mengandung konten sensitif" +enableHorizontalSwipe: "Geser untuk mengganti tab" _bubbleGame: howToPlay: "Cara bermain" + _howToPlay: + section1: "Atur posisi dan jatuhkan obyek ke dalam kotak." _announcement: forExistingUsers: "Hanya pengguna yang telah ada" forExistingUsersDescription: "Pengumuman ini akan dimunculkan ke pengguna yang sudah ada dari titik waktu publikasi jika dinyalakan. Apabila dimatikan, mereka yang baru mendaftar setelah publikasi ini akan juga melihatnya." @@ -1256,6 +1274,8 @@ _initialTutorial: note: "Baru aja makan donat berlapis coklat 🍩😋" _howToMakeAttachmentsSensitive: title: "Bagaimana menandai lampiran sebagai sensitif?" + _done: + title: "Kamu telah menyelesaikan tutorial! 🎉" _serverRules: description: "Daftar peraturan akan ditampilkan sebelum pendaftaran. Mengatur ringkasan dari Syarat dan Ketentuan sangat direkomendasikan." _serverSettings: @@ -1900,6 +1920,55 @@ _permissions: "write:flash": "Sunting Play" "read:flash-likes": "Lihat daftar Play yang disukai" "write:flash-likes": "Sunting daftar Play yang disukai" + "read:admin:abuse-user-reports": "Lihat laporan pengguna" + "write:admin:delete-account": "Hapus akun pengguna" + "write:admin:delete-all-files-of-a-user": "Hapus semua berkas dari seorang pengguna" + "read:admin:index-stats": "Lihat statistik indeks basis data" + "read:admin:table-stats": "Lihat statistik tabel basis data" + "read:admin:user-ips": "Lihat alamat IP pengguna" + "read:admin:meta": "Lihat metadata instansi" + "write:admin:reset-password": "Atur ulang kata sandi pengguna" + "write:admin:resolve-abuse-user-report": "Selesaikan laporan pengguna" + "write:admin:send-email": "Mengirim surel" + "read:admin:server-info": "Lihat informasi peladen" + "read:admin:show-moderation-log": "Lihat log moderasi" + "read:admin:show-user": "Lihat informasi pengguna privat" + "read:admin:show-users": "Lihat informasi pengguna privat" + "write:admin:suspend-user": "Tangguhkan pengguna" + "write:admin:unset-user-avatar": "Hapus avatar pengguna" + "write:admin:unset-user-banner": "Hapus banner pengguna" + "write:admin:unsuspend-user": "Batalkan penangguhan pengguna" + "write:admin:meta": "Kelola metadata instansi" + "write:admin:user-note": "Kelola moderasi catatan" + "write:admin:roles": "Kelola peran" + "read:admin:roles": "Lihat peran" + "write:admin:relays": "Kelola relay" + "read:admin:relays": "Lihat relay" + "write:admin:invite-codes": "Kelola kode undangan" + "read:admin:invite-codes": "Lihat kode undangan" + "write:admin:announcements": "Kelola pengumuman" + "read:admin:announcements": "Lihat Pengumuman" + "write:admin:avatar-decorations": "Kelola dekorasi avatar" + "read:admin:avatar-decorations": "Lihat dekorasi avatar" + "write:admin:federation": "Kelola data federasi" + "write:admin:account": "Kelola akun pengguna" + "read:admin:account": "Lihat akun pengguna" + "write:admin:emoji": "Kelola emoji" + "read:admin:emoji": "Lihat emoji" + "write:admin:queue": "Kelola antrian kerja" + "read:admin:queue": "Lihat informasi antrian kerja" + "write:admin:promo": "Kelola catatan promosi" + "write:admin:drive": "Kelola drive pengguna" + "read:admin:drive": "Kelola informasi drive pengguna" + "read:admin:stream": "Gunakan API WebSocket untuk Admin" + "write:admin:ad": "Kelola iklan" + "read:admin:ad": "Lihat iklan" + "write:invite-codes": "Membuat kode undangan" + "read:invite-codes": "Mendapatkan kode undangan" + "write:clip-favorite": "Kelola klip yang difavoritkan" + "read:clip-favorite": "Lihat klip yang difavoritkan" + "read:federation": "Mendapatkan data federasi" + "write:report-abuse": "Melaporkan pelanggaran" _auth: shareAccessTitle: "Mendapatkan ijin akses aplikasi" shareAccess: "Apakah kamu ingin mengijinkan \"{name}\" untuk mengakses akun ini?" @@ -1954,6 +2023,7 @@ _widgets: _userList: chooseList: "Pilih daftar" clicker: "Pengeklik" + birthdayFollowings: "Pengguna yang merayakan hari ulang tahunnya hari ini" _cw: hide: "Sembunyikan" show: "Lihat konten" @@ -2320,6 +2390,41 @@ _dataSaver: _code: title: "Penyorotan kode" description: "Jika notasi penyorotan kode digunakan di MFM, dll. Fungsi tersebut tidak akan dimuat apabila tidak diketuk. Penyorotan sintaks membutuhkan pengunduhan berkas definisi penyorotan untuk setiap bahasa pemrograman. Oleh sebab itu, menonaktifkan pemuatan otomatis dari berkas ini dilakukan untuk mengurangi jumlah komunikasi data." +_hemisphere: + N: "Bumi belahan utara" + S: "Bumi belahan selatan" + caption: "Digunakan dalam beberapa pengaturan klien untuk menentukan musim." _reversi: + reversi: "Reversi" + gameSettings: "Pengaturan permainan" + chooseBoard: "Pilih papan" + blackOrWhite: "Hitam/Putih" + blackIs: "{name} bermain sebagai Hitam" + rules: "Aturan" + thisGameIsStartedSoon: "Permainan akan segera dimulai" + waitingForOther: "Menunggu langkah giliran dari lawan" + waitingForMe: "Menungguh langkah giliran dari kamu" + waitingBoth: "Bersiap" + ready: "Siap" + cancelReady: "Belum siap" + opponentTurn: "Giliran lawan" + myTurn: "Giliran kamu" + turnOf: "Giliran {name}" + pastTurnOf: "Giliran {name}" + surrender: "Menyerah" + surrendered: "Telah menyerah" + timeout: "Waktu habis" + drawn: "Seri" + won: "{name} menang" + black: "Hitam" + white: "Putih" total: "Jumlah" + turnCount: "Langkah ke {count}" + myGames: "Rondeku" + allGames: "Semua ronde" + ended: "Selesai" + playing: "Sedang bermain" + isLlotheo: "Pemain dengan batu yang sedikit menang (Llotheo)" + loopedMap: "Peta melingkar" + canPutEverywhere: "Keping dapat ditaruh dimana saja" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index f344ca39ef7f..378036af6df5 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -1167,6 +1167,7 @@ hideRepliesToOthersInTimelineAll: "Nascondi le risposte dei tuoi follow nella TL confirmShowRepliesAll: "Questa è una attività irreversibile. Vuoi davvero includere tutte le risposte dei following in TL?" confirmHideRepliesAll: "Questa è una attività irreversibile. Vuoi davvero escludere tutte le risposte dei following in TL?" externalServices: "Servizi esterni" +sourceCode: "Codice sorgente" impressum: "Dichiarazione di proprietà" impressumUrl: "URL della dichiarazione di proprietà" impressumDescription: "La dichiarazione di proprietà, è obbligatoria in alcuni paesi come la Germania (Impressum)." diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index c676bf4fdb73..4b5f98e803dc 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -1165,6 +1165,7 @@ hideRepliesToOthersInTimelineAll: "タイムラインに今フォローしとる confirmShowRepliesAll: "これは元に戻せへんから慎重に決めてや。本当にタイムラインに今フォローしとる全員の返信を入れるか?" confirmHideRepliesAll: "これは元に戻せへんから慎重に決めてや。本当にタイムラインに今フォローしとる全員の返信を入れへんのか?" externalServices: "他のサイトのサービス" +sourceCode: "ソースコード" impressum: "運営者の情報" impressumUrl: "運営者の情報URL" impressumDescription: "ドイツとかの一部んところではな、表示が義務付けられてんねん(Impressum)。" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index ab0ac9d27f62..c4646b6a863b 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -1167,6 +1167,7 @@ hideRepliesToOthersInTimelineAll: "타임라인에 현재 팔로우 중인 사 confirmShowRepliesAll: "이 조작은 되돌릴 수 없습니다. 정말로 타임라인에 현재 팔로우 중인 사람 전원의 답글이 나오게 하시겠습니까?" confirmHideRepliesAll: "이 조작은 되돌릴 수 없습니다. 정말로 타임라인에 현재 팔로우 중인 사람 전원의 답글이 나오지 않게 하시겠습니까?" externalServices: "외부 서비스" +sourceCode: "소스 코드" impressum: "운영자 정보" impressumUrl: "운영자 정보 URL" impressumDescription: "독일 등의 일부 나라와 지역에서는 꼭 표시해야 합니다(Impressum)." diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index 9de413eb3ba6..99eb1f302800 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -871,6 +871,7 @@ youFollowing: "Śledzeni" icon: "Awatar" replies: "Odpowiedz" renotes: "Udostępnij" +sourceCode: "Kod źródłowy" flip: "Odwróć" _role: priority: "Priorytet" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index d014b7fc259e..6141eba5f0aa 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -1082,6 +1082,7 @@ icon: "Аватар" replies: "Ответы" renotes: "Репост" loadReplies: "Показать ответы" +sourceCode: "Исходный код" flip: "Переворот" lastNDays: "Последние {n} сут" _initialAccountSetting: diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml index 7856809bf87a..251496b10b68 100644 --- a/locales/sk-SK.yml +++ b/locales/sk-SK.yml @@ -919,6 +919,7 @@ youFollowing: "Sledované" icon: "Avatar" replies: "Odpovedať" renotes: "Preposlať" +sourceCode: "Zdrojový kód" flip: "Preklopiť" lastNDays: "Posledných {n} dní" _role: diff --git a/locales/th-TH.yml b/locales/th-TH.yml index 3ae18e7d89c9..b5a54a39eca3 100644 --- a/locales/th-TH.yml +++ b/locales/th-TH.yml @@ -1167,6 +1167,7 @@ hideRepliesToOthersInTimelineAll: "ซ่อนตอบกลับจากท confirmShowRepliesAll: "การดำเนินการนี้ไม่สามารถย้อนกลับได้ คุณต้องการแสดงการตอบกลับผู้อื่นจากผู้ใช้ทุกคนที่คุณติดตามอยู่ในไทม์ไลน์ของคุณหรือไม่?" confirmHideRepliesAll: "การดำเนินการนี้ไม่สามารถย้อนกลับได้ คุณต้องการซ่อนการตอบกลับผู้อื่นจากผู้ใช้ทุกคนที่คุณติดตามอยู่ในไทม์ไลน์ของคุณหรือไม่?" externalServices: "บริการภายนอก" +sourceCode: "ซอร์สโค้ด" impressum: "อิมเพรสชั่น" impressumUrl: "URL อิมเพรสชั่น" impressumDescription: "การติดป้ายกำกับ (Impressum) มีผลบังคับใช้ในบางประเทศและภูมิภาค เช่น ประเทศเยอรมนี" diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index 7679ad56d7ad..df36f43c06c9 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -911,6 +911,7 @@ youFollowing: "Підписки" icon: "Аватар" replies: "Відповісти" renotes: "Поширити" +sourceCode: "Вихідний код" flip: "Перевернути" lastNDays: "Останні {n} днів" _achievements: diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml index 6de15fc11fb1..7cfdde320474 100644 --- a/locales/vi-VN.yml +++ b/locales/vi-VN.yml @@ -1045,6 +1045,7 @@ loadReplies: "Hiển thị các trả lời" pinnedList: "Các mục đã được ghim" keepScreenOn: "Giữ màn hình luôn bật" verifiedLink: "Chúng tôi đã xác nhận bạn là chủ sở hữu của đường dẫn này" +sourceCode: "Mã nguồn" flip: "Lật" lastNDays: "{n} ngày trước" _announcement: diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index ec21de62ff59..d0891f0678c2 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -1166,6 +1166,7 @@ hideRepliesToOthersInTimelineAll: "在时间线中隐藏现在关注的所有人 confirmShowRepliesAll: "此操作不可撤销。确认要在时间线中包含现在关注的所有人的回复吗?" confirmHideRepliesAll: "此操作不可撤销。确认要在时间线中隐藏现在关注的所有人的回复吗?" externalServices: "外部服务" +sourceCode: "源代码" impressum: "运营商信息" impressumUrl: "运营商信息地址" impressumDescription: "德国等国家和地区有义务展示此类信息(Impressum)。" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 73b78c9d338e..2762a612f559 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -1167,6 +1167,7 @@ hideRepliesToOthersInTimelineAll: "在時間軸不包含追隨中所有人的回 confirmShowRepliesAll: "進行此操作後無法復原。您真的希望時間軸「包含」您目前追隨的所有人的回覆嗎?" confirmHideRepliesAll: "進行此操作後無法復原。您真的希望時間軸「不包含」您目前追隨的所有人的回覆嗎?" externalServices: "外部服務" +sourceCode: "原始碼" impressum: "營運者資訊" impressumUrl: "營運者資訊網址" impressumDescription: "在德國與部份地區必須要明確顯示營運者資訊。" From b3aa793f429df5a26b7ac537813b87e9a50b99c2 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Sat, 17 Feb 2024 14:28:34 +0900 Subject: [PATCH 09/10] =?UTF-8?q?chore:=20=E9=80=9A=E5=A0=B1=E3=83=9A?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=81=AE=E3=83=A6=E3=83=BC=E3=82=B6=E3=82=92?= =?UTF-8?q?=E3=82=AF=E3=83=AA=E3=83=83=E3=82=AF=E3=81=97=E3=81=9F=E9=9A=9B?= =?UTF-8?q?=E3=81=AB=E3=83=A6=E3=83=BC=E3=82=B6=E3=82=92=E3=82=A6=E3=82=A3?= =?UTF-8?q?=E3=83=B3=E3=83=89=E3=82=A6=E3=81=A7=E9=96=8B=E3=81=8F=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=20(#13348)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 通報ページのユーザをクリックした際にユーザをウィンドウで開くように * docs(changelog): 通報ページのユーザをクリックした際にユーザをウィンドウで開くように --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- CHANGELOG.md | 1 + packages/frontend/src/components/MkAbuseReport.vue | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6c282259073..32c9bd0aec9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ - センシティブなリアクションを認めていないユーザーにセンシティブなカスタム絵文字をリアクションしようとした場合 - ロールが必要な絵文字をリアクションしようとした場合 - Enhance: ページ遷移時にPlayerを閉じるように +- Enhance: 通報ページのユーザをクリックした際にユーザをウィンドウで開くように - Enhance: ノートの通報時にリモートのノートであっても自インスタンスにおけるノートのリンクを含むように - Enhance: オフライン表示のデザインを改善・多言語対応 - Fix: ネイティブモードの絵文字がモノクロにならないように diff --git a/packages/frontend/src/components/MkAbuseReport.vue b/packages/frontend/src/components/MkAbuseReport.vue index 733796ec21c6..271b94feaada 100644 --- a/packages/frontend/src/components/MkAbuseReport.vue +++ b/packages/frontend/src/components/MkAbuseReport.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only