From 316ffcea54eb7f1f4b04c8b9937b390c629d088c Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Sun, 24 Dec 2023 14:20:43 +0900 Subject: [PATCH 01/32] =?UTF-8?q?ci:=20Get=20api.json=20from=20Misskey?= =?UTF-8?q?=E3=81=A7upload-artifact@v4=E3=81=A7=E5=90=8C=E5=90=8Dartifact?= =?UTF-8?q?=E3=81=A7=E3=82=A8=E3=83=A9=E3=83=BC=E3=81=AB=E3=81=AA=E3=82=8B?= =?UTF-8?q?=E3=81=AE=E3=82=92=E4=BF=AE=E6=AD=A3=20(#12770)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci: upload-artifact@v4で同名artifactでエラーになるのを修正 Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com> * report-api-diff.ymlの最中にエラーが発生したときに分かりづらいので、PRにコメントを残すようにする * 古いget-api-diffを使ってるactionとの互換性をもたせる --------- Co-authored-by: おさむのひと <46447427+samunohito@users.noreply.github.com> --- .github/workflows/get-api-diff.yml | 4 +-- .github/workflows/report-api-diff.yml | 36 ++++++++++++++++++--------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/.github/workflows/get-api-diff.yml b/.github/workflows/get-api-diff.yml index d604f9b16..bf92e701b 100644 --- a/.github/workflows/get-api-diff.yml +++ b/.github/workflows/get-api-diff.yml @@ -56,7 +56,7 @@ jobs: - name: Upload Artifact uses: actions/upload-artifact@v4 with: - name: api-artifact + name: api-artifact-${{ matrix.api-json-name }} path: ${{ matrix.api-json-name }} save-pr-number: @@ -69,5 +69,5 @@ jobs: echo "$PR_NUMBER" > ./pr_number - uses: actions/upload-artifact@v4 with: - name: api-artifact + name: api-artifact-pr-number path: pr_number diff --git a/.github/workflows/report-api-diff.yml b/.github/workflows/report-api-diff.yml index 309516772..54da8b4a8 100644 --- a/.github/workflows/report-api-diff.yml +++ b/.github/workflows/report-api-diff.yml @@ -19,24 +19,28 @@ jobs: uses: actions/github-script@v7 with: script: | + const fs = require('fs'); let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ owner: context.repo.owner, repo: context.repo.repo, run_id: context.payload.workflow_run.id, }); - let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { - return artifact.name == "api-artifact" - })[0]; - let download = await github.rest.actions.downloadArtifact({ - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: matchArtifact.id, - archive_format: 'zip', + let matchArtifacts = allArtifacts.data.artifacts.filter((artifact) => { + return artifact.name.startsWith("api-artifact-") || artifact.name == "api-artifact" }); - let fs = require('fs'); - fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/api-artifact.zip`, Buffer.from(download.data)); - - name: Extract artifact - run: unzip api-artifact.zip -d artifacts + await Promise.all(matchArtifacts.map(async (artifact) => { + let download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: artifact.id, + archive_format: 'zip', + }); + await fs.promises.writeFile(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data)); + })); + - name: Extract all artifacts + run: | + find . -mindepth 1 -maxdepth 1 -type f -name '*.zip' -exec unzip {} -d artifacts ';' + ls -la - name: Load PR Number id: load-pr-num run: echo "pr-number=$(cat artifacts/pr_number)" >> "$GITHUB_OUTPUT" @@ -83,3 +87,11 @@ jobs: pr_number: ${{ steps.load-pr-num.outputs.pr-number }} comment_tag: show_diff filePath: ./output.md + - name: Tell error to PR + uses: thollander/actions-comment-pull-request@v2 + if: failure() && steps.load-pr-num.outputs.pr-number + with: + pr_number: ${{ steps.load-pr-num.outputs.pr-number }} + comment_tag: show_diff_error + message: | + api.jsonの差分作成中にエラーが発生しました。詳細は[Workflowのログ](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})を確認してください。 From 6fce36374d8756f47f96c7a04cd388c994bd047f Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 24 Dec 2023 15:23:56 +0900 Subject: [PATCH 02/32] =?UTF-8?q?enhance(backend):=20=E3=82=BB=E3=83=B3?= =?UTF-8?q?=E3=82=B7=E3=83=86=E3=82=A3=E3=83=96=E3=83=AF=E3=83=BC=E3=83=89?= =?UTF-8?q?=E3=81=AE=E8=A8=AD=E5=AE=9A=E3=81=8C=E3=83=8F=E3=83=83=E3=82=B7?= =?UTF-8?q?=E3=83=A5=E3=82=BF=E3=82=B0=E3=83=88=E3=83=AC=E3=83=B3=E3=83=89?= =?UTF-8?q?=E3=81=AB=E3=82=82=E9=81=A9=E7=94=A8=E3=81=95=E3=82=8C=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 11 ++++++++ packages/backend/src/core/HashtagService.ts | 3 ++ .../backend/src/core/NoteCreateService.ts | 27 +----------------- packages/backend/src/core/UtilityService.ts | 28 +++++++++++++++++++ 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac31bc0d2..af2aea799 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,17 @@ --> +## 2023.12.1 + +### General +- + +### Client +- + +### Server +- Enhance: センシティブワードの設定がハッシュタグトレンドにも適用されるようになりました + ## 2023.12.0 ### Note diff --git a/packages/backend/src/core/HashtagService.ts b/packages/backend/src/core/HashtagService.ts index d37899990..5a2417c9c 100644 --- a/packages/backend/src/core/HashtagService.ts +++ b/packages/backend/src/core/HashtagService.ts @@ -15,6 +15,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { bindThis } from '@/decorators.js'; import { FeaturedService } from '@/core/FeaturedService.js'; import { MetaService } from '@/core/MetaService.js'; +import { UtilityService } from '@/core/UtilityService.js'; @Injectable() export class HashtagService { @@ -29,6 +30,7 @@ export class HashtagService { private featuredService: FeaturedService, private idService: IdService, private metaService: MetaService, + private utilityService: UtilityService, ) { } @@ -161,6 +163,7 @@ export class HashtagService { const instance = await this.metaService.fetch(); const hiddenTags = instance.hiddenTags.map(t => normalizeForSearch(t)); if (hiddenTags.includes(hashtag)) return; + if (this.utilityService.isSensitiveWordIncluded(hashtag, instance.sensitiveWords)) return; // YYYYMMDDHHmm (10分間隔) const now = new Date(); diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 2bdff872a..35baa1447 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -253,7 +253,7 @@ export class NoteCreateService implements OnApplicationShutdown { if (data.visibility === 'public' && data.channel == null) { const sensitiveWords = meta.sensitiveWords; - if (this.isSensitive(data, sensitiveWords)) { + if (this.utilityService.isSensitiveWordIncluded(data.cw ?? data.text ?? '', sensitiveWords)) { data.visibility = 'home'; } else if ((await this.roleService.getUserPolicies(user.id)).canPublicNote === false) { data.visibility = 'home'; @@ -704,31 +704,6 @@ export class NoteCreateService implements OnApplicationShutdown { this.index(note); } - @bindThis - private isSensitive(note: Option, sensitiveWord: string[]): boolean { - if (sensitiveWord.length > 0) { - const text = note.cw ?? note.text ?? ''; - if (text === '') return false; - const matched = sensitiveWord.some(filter => { - // represents RegExp - const regexp = filter.match(/^\/(.+)\/(.*)$/); - // This should never happen due to input sanitisation. - if (!regexp) { - const words = filter.split(' '); - return words.every(keyword => text.includes(keyword)); - } - try { - return new RE2(regexp[1], regexp[2]).test(text); - } catch (err) { - // This should never happen due to input sanitisation. - return false; - } - }); - if (matched) return true; - } - return false; - } - @bindThis private isQuote(note: Option): note is Option & { renote: MiNote } { // sync with misc/is-quote.ts diff --git a/packages/backend/src/core/UtilityService.ts b/packages/backend/src/core/UtilityService.ts index b95e41167..5dec36c89 100644 --- a/packages/backend/src/core/UtilityService.ts +++ b/packages/backend/src/core/UtilityService.ts @@ -6,6 +6,7 @@ import { URL } from 'node:url'; import { toASCII } from 'punycode'; import { Inject, Injectable } from '@nestjs/common'; +import RE2 from 're2'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; import { bindThis } from '@/decorators.js'; @@ -41,6 +42,33 @@ export class UtilityService { return silencedHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`)); } + @bindThis + public isSensitiveWordIncluded(text: string, sensitiveWords: string[]): boolean { + if (sensitiveWords.length === 0) return false; + if (text === '') return false; + + const regexpregexp = /^\/(.+)\/(.*)$/; + + const matched = sensitiveWords.some(filter => { + // represents RegExp + const regexp = filter.match(regexpregexp); + // This should never happen due to input sanitisation. + if (!regexp) { + const words = filter.split(' '); + return words.every(keyword => text.includes(keyword)); + } + try { + // TODO: RE2インスタンスをキャッシュ + return new RE2(regexp[1], regexp[2]).test(text); + } catch (err) { + // This should never happen due to input sanitisation. + return false; + } + }); + + return matched; + } + @bindThis public extractDbHost(uri: string): string { const url = new URL(uri); From 36701f8a7c867a68bcce814bfc4548624f43916b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8A=E3=81=95=E3=82=80=E3=81=AE=E3=81=B2=E3=81=A8?= <46447427+samunohito@users.noreply.github.com> Date: Sun, 24 Dec 2023 15:24:26 +0900 Subject: [PATCH 03/32] =?UTF-8?q?fix(backend):=201702718871541-ffVisibilit?= =?UTF-8?q?y.js=E3=81=AEdown=E3=81=8C=E5=A3=8A=E3=82=8C=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=82=8B=20(#12767)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/migration/1702718871541-ffVisibility.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/backend/migration/1702718871541-ffVisibility.js b/packages/backend/migration/1702718871541-ffVisibility.js index 24b187313..e9e820c89 100644 --- a/packages/backend/migration/1702718871541-ffVisibility.js +++ b/packages/backend/migration/1702718871541-ffVisibility.js @@ -24,9 +24,11 @@ export class ffVisibility1702718871541 { async down(queryRunner) { await queryRunner.query(`CREATE TYPE "public"."user_profile_ffvisibility_enum" AS ENUM('public', 'followers', 'private')`); await queryRunner.query(`ALTER TABLE "user_profile" ADD "ffVisibility" "public"."user_profile_ffvisibility_enum" NOT NULL DEFAULT 'public'`); + await queryRunner.query(`CREATE CAST ("public"."user_profile_followingvisibility_enum" AS "public"."user_profile_ffvisibility_enum") WITH INOUT AS ASSIGNMENT`); - await queryRunner.query(`UPDATE "user_profile" SET ffVisibility = "user_profile"."followingVisibility"`); + await queryRunner.query(`UPDATE "user_profile" SET "ffVisibility" = "followingVisibility"`); await queryRunner.query(`DROP CAST ("public"."user_profile_followingvisibility_enum" AS "public"."user_profile_ffvisibility_enum")`); + await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "followersVisibility"`); await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "followingVisibility"`); await queryRunner.query(`DROP TYPE "public"."user_profile_followersVisibility_enum"`); From cae40e68e4c84693fbeaf0e801e705ccb876e2c0 Mon Sep 17 00:00:00 2001 From: Nya Candy Date: Sun, 24 Dec 2023 14:24:51 +0800 Subject: [PATCH 04/32] fix: lint (#12761) --- packages/backend/src/core/EmailService.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/EmailService.ts b/packages/backend/src/core/EmailService.ts index 3a61e353f..7fc780078 100644 --- a/packages/backend/src/core/EmailService.ts +++ b/packages/backend/src/core/EmailService.ts @@ -7,7 +7,6 @@ import { URLSearchParams } from 'node:url'; import * as nodemailer from 'nodemailer'; import { Inject, Injectable } from '@nestjs/common'; import { validate as validateEmail } from 'deep-email-validator'; -import { SubOutputFormat } from 'deep-email-validator/dist/output/output.js'; import { MetaService } from '@/core/MetaService.js'; import { UtilityService } from '@/core/UtilityService.js'; import { DI } from '@/di-symbols.js'; @@ -166,7 +165,10 @@ export class EmailService { email: emailAddress, }); - let validated; + let validated: { + valid: boolean, + reason?: string | null, + }; if (meta.enableActiveEmailValidation) { if (meta.enableVerifymailApi && meta.verifymailAuthKey != null) { From 0393d8f53cb8607ff9448208e125c7b9900ab422 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 24 Dec 2023 15:25:13 +0900 Subject: [PATCH 05/32] New Crowdin updates (#12759) * New translations ja-jp.yml (Spanish) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Korean) --- locales/es-ES.yml | 78 +++++++++++++++++++++++++++++++++++++++++++++++ locales/ko-KR.yml | 5 +-- locales/zh-TW.yml | 15 ++++----- 3 files changed, 89 insertions(+), 9 deletions(-) diff --git a/locales/es-ES.yml b/locales/es-ES.yml index a079cf01f..80cf905f7 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -121,6 +121,12 @@ sensitive: "Marcado como sensible" add: "Agregar" reaction: "Reacción" reactions: "Reacción" +emojiPicker: "Selector de emojis" +pinnedEmojisForReactionSettingDescription: "Puedes seleccionar reacciones para fijarlos en el selector" +pinnedEmojisSettingDescription: "Puedes seleccionar emojis para fijarlos en el selector" +emojiPickerDisplay: "Mostrar el selector de emojis" +overwriteFromPinnedEmojisForReaction: "Sobreescribir las reacciones fijadas" +overwriteFromPinnedEmojis: "Sobreescribir los emojis fijados" reactionSettingDescription2: "Arrastre para reordenar, click para borrar, apriete la tecla + para añadir." rememberNoteVisibility: "Recordar visibilidad" attachCancel: "Quitar adjunto" @@ -260,6 +266,7 @@ removed: "Borrado" removeAreYouSure: "¿Desea borrar \"{x}\"?" deleteAreYouSure: "¿Desea borrar \"{x}\"?" resetAreYouSure: "¿Desea reestablecer?" +areYouSure: "¿Estás conforme?" saved: "Guardado" messaging: "Chat" upload: "Subir" @@ -640,6 +647,7 @@ smtpSecure: "Usar SSL/TLS implícito en la conexión SMTP" smtpSecureInfo: "Apagar cuando se use STARTTLS" testEmail: "Prueba de envío" wordMute: "Silenciar palabras" +hardWordMute: "Filtro de palabra fuerte" regexpError: "Error de la expresión regular" regexpErrorDescription: "Ocurrió un error en la expresión regular en la linea {line} de las palabras muteadas {tab}" instanceMute: "Instancias silenciadas" @@ -873,6 +881,8 @@ makeReactionsPublicDescription: "Todas las reacciones que hayas hecho serán pú classic: "Clásico" muteThread: "Silenciar hilo" unmuteThread: "Mostrar hilo" +followingVisibility: "Visibilidad de seguidos" +followersVisibility: "Visibilidad de seguidores" continueThread: "Ver la continuación del hilo" deleteAccountConfirm: "La cuenta será borrada. ¿Está seguro?" incorrectPassword: "La contraseña es incorrecta" @@ -1024,6 +1034,7 @@ sensitiveWords: "Palabras sensibles" sensitiveWordsDescription: "La visibilidad de todas las notas que contienen cualquiera de las palabras configuradas serán puestas en \"Inicio\" automáticamente. Puedes enumerás varias separándolas con saltos de línea" sensitiveWordsDescription2: "Si se usan espacios se crearán expresiones AND y las palabras subsecuentes con barras inclinadas se convertirán en expresiones regulares." hiddenTags: "Hashtags ocultos" +hiddenTagsDescription: "Selecciona las etiquetas que no se mostrarán en tendencias. Una etiqueta por línea." notesSearchNotAvailable: "No se puede buscar una nota" license: "Licencia" unfavoriteConfirm: "¿Desea quitar de favoritos?" @@ -1152,6 +1163,7 @@ tosAndPrivacyPolicy: "Condiciones de Uso y Política de Privacidad" avatarDecorations: "Decoraciones de avatar" attach: "Acoplar" detach: "Quitar" +detachAll: "Quitar todo" angle: "Ángulo" flip: "Echar de un capirotazo" showAvatarDecorations: "Mostrar decoraciones de avatar" @@ -1165,6 +1177,10 @@ cwNotationRequired: "Si se ha activado \"ocultar contenido\", es necesario propo doReaction: "Añadir reacción" code: "Código" reloadRequiredToApplySettings: "Es necesario recargar para que se aplique la configuración." +remainingN: "Faltan: {n}" +overwriteContentConfirm: "¿Quieres sustituir todo el contenido actual?" +seasonalScreenEffect: "Efectos de pantalla asociados a estaciones" +decorate: "Decorar" _announcement: forExistingUsers: "Solo para usuarios registrados" forExistingUsersDescription: "Este anuncio solo se mostrará a aquellos usuarios registrados en el momento de su publicación. Si se deshabilita esta opción, aquellos usuarios que se registren tras su publicación también lo verán." @@ -1222,6 +1238,45 @@ _initialTutorial: home: "Puedes ver los posts de las cuentas que sigues." local: "Puedes ver los posts de todos los usuarios de este servidor." social: "Se ven los posts de la línea de tiempo de inicio junto con los de la línea de tiempo local." + global: "Puedes ver notas de todos los servidores conectados." + description2: "Puedes cambiar la línea de tiempo en la parte superior de la pantalla cuando quieras." + description3: "Además, hay listas de líneas de tiempo y listas de canales. Para más detalle, por favor visita este enlace: {link}" + _postNote: + title: "Ajustes de publicación de nota" + description1: "Cuando publicas una nota en Misskey, hay varias opciones disponibles. El formulario tiene este aspecto." + _visibility: + description: "Puedes limitar quién puede ver tu nota." + public: "Tu nota será visible para todos los usuarios." + home: "Publicar solo en la línea de tiempo de Inicio. La nota se verá en tu perfil, la verán tus seguidores y también cuando sea renotada." + followers: "Visible solo para seguidores. Sólo tus seguidores podrán ver la nota, y no podrá ser renotada por otras personas." + direct: "Visible sólo para usuarios específicos, y el destinatario será notificado. Puede usarse como alternativa a la mensajería directa." + doNotSendConfidencialOnDirect1: "¡Ten cuidado cuando vayas a enviar información sensible!" + doNotSendConfidencialOnDirect2: "Los administradores del servidor pueden leer lo que escribes. Ten cuidado cuando envíes información sensible en notas directas en servidores no confiables." + localOnly: "Publicando con esta opción seleccionada, la nota no se federará hacia otros servidores. Los usuarios de otros servidores no podrán ver estas notas directamente, sin importar los ajustes seleccionados más arriba." + _cw: + title: "Alerta de contenido (CW)" + description: "En lugar de mostrarse el contenido de la nota, se mostrará lo que escribas en el campo \"comentarios\". Pulsando en \"leer más\" desplegará el contenido de la nota." + _exampleNote: + cw: "¡Esto te hará tener hambre!" + note: "Acabo de comerme un donut de chocolate glaseado 🍩😋" + useCases: "Esto se usa cuando las normas del servidor lo requieren, o para ocultar spoilers o contenido sensible." + _howToMakeAttachmentsSensitive: + title: "¿Cómo puedo marcar adjuntos como contenido sensible?" + description: "Cuando las normas del servidor lo requieran, o el contenido lo requiera, marca la opción de \"contenido sensible\" para el adjunto." + tryThisFile: "¡Prueba a marcar la imagen adjunta como contenido sensible!" + _exampleNote: + note: "Ups, la he liado al abrir la tapa del natto..." + method: "Para marcar un adjunto como sensible, haz clic en la miniatura, abre el menú, y haz clic en \"Marcar como sensible\"." + sensitiveSucceeded: "Cuando adjuntes archivos, por favor, ten en cuenta las normas del servidor para marcarlos como contenido sensible." + doItToContinue: "Marca el archivo adjunto como sensible para continuar." + _done: + title: "¡Has completado el tutorial! 🎉" + description: "Las funciones que mostramos aquí son sólo una pequeña parte. Para más detalles sobre el funcionamiento de Misskey, pulsa en este enlace: {link}" +_timelineDescription: + home: "En la línea de tiempo de Inicio puedes ver las notas de las cuentas a las que sigues." + local: "En la línea de tiempo Local puedes ver las notas de todos los usuarios del servidor." + social: "En la línea de tiempo Social verás las notas de Inicio y Local a la vez." + global: "En la línea de tiempo Global verás las notas de todos los servidores conectados." _serverRules: description: "Un conjunto de reglas que serán mostradas antes del registro. Configurar un sumario de términos de servicio es recomendado." _serverSettings: @@ -1233,6 +1288,7 @@ _serverSettings: manifestJsonOverride: "Sobreescribir manifest.json" shortName: "Nombre corto" shortNameDescription: "Forma corta del nombre de la instancia que puede mostrarse si el nombre completo es demasiado largo." + fanoutTimelineDescription: "Incrementa el rendimiento de forma significativa cuando se obtienen las líneas de tiempo y reduce la carga en la base de datos. A cambio, el uso de la memoria en Redis incrementará. Considera desactivar esta opción en caso de que tu servidor tenga poca memoria o detectes inestabilidad." _accountMigration: moveFrom: "Trasladar de otra cuenta a ésta" moveFromSub: "Crear un alias para otra cuenta." @@ -1490,6 +1546,9 @@ _achievements: _smashTestNotificationButton: title: "Sobrecarga de pruebas" description: "Envía muchas notificaciones de prueba en un corto espacio de tiempo" + _tutorialCompleted: + title: "Diploma del Curso Básico de Misskey" + description: "Tutorial completado" _role: new: "Crear rol" edit: "Editar rol" @@ -1500,7 +1559,9 @@ _role: assignTarget: "Asignar objetivo" descriptionOfAssignTarget: "Manual Para cambiar manualmente lo que se incluye en este rol.\nCondicional configura una condición, y los usuarios que cumplan la condición serán incluídos automáticamente." manual: "manual" + manualRoles: "Roles manuales" conditional: "condicional" + conditionalRoles: "Roles condicionales" condition: "condición" isConditionalRole: "Esto es un rol condicional" isPublic: "Publicar rol" @@ -1549,6 +1610,7 @@ _role: canHideAds: "Puede ocultar anuncios" canSearchNotes: "Uso de la búsqueda de notas" canUseTranslator: "Uso de traductor" + avatarDecorationLimit: "Número máximo de decoraciones de avatar" _condition: isLocal: "Usuario local" isRemote: "Usuario remoto" @@ -1577,6 +1639,7 @@ _emailUnavailable: disposable: "No es un correo reutilizable" mx: "Servidor de correo inválido" smtp: "Servidor de correo no disponible" + banned: "Email no disponible" _ffVisibility: public: "Publicar" followers: "Visible solo para seguidores" @@ -1653,6 +1716,7 @@ _aboutMisskey: donate: "Donar a Misskey" morePatrons: "Muchas más personas nos apoyan. Muchas gracias🥰" patrons: "Patrocinadores" + projectMembers: "Miembros del proyecto" _displayOfSensitiveMedia: respect: "Esconder medios marcados como sensibles" ignore: "Mostrar medios marcados como sensibles" @@ -1677,6 +1741,7 @@ _channel: notesCount: "{n} notas" nameAndDescription: "Nombre y descripción" nameOnly: "Sólo nombre" + allowRenoteToExternal: "Permitir renotas y menciones fuera del canal" _menuDisplay: sideFull: "Horizontal" sideIcon: "Horizontal (ícono)" @@ -1780,6 +1845,12 @@ _ago: yearsAgo: "Hace {n} años" invalid: "No hay nada que ver aqui" _timeIn: + seconds: "En {n} segundos" + minutes: "En {n}m" + hours: "En {n}h" + days: "En {n}d" + weeks: "En {n}sem." + months: "En {n}M" years: "En {n} años" _time: second: "Segundos" @@ -1906,6 +1977,7 @@ _widgets: _userList: chooseList: "Seleccione una lista" clicker: "Cliqueador" + birthdayFollowings: "Hoy cumplen años" _cw: hide: "Ocultar" show: "Ver más" @@ -1968,6 +2040,7 @@ _profile: changeAvatar: "Cambiar avatar" changeBanner: "Cambiar banner" verifiedLinkDescription: "Introduciendo una URL que contiene un enlace a tu perfil, se puede mostrar un icono de verificación de propiedad al lado del campo." + avatarDecorationMax: "Puedes añadir un máximo de {max} decoraciones de avatar." _exportOrImport: allNotes: "Todas las notas" favoritedNotes: "Notas favoritas" @@ -2089,6 +2162,7 @@ _notification: pollEnded: "Estan disponibles los resultados de la encuesta" newNote: "Nueva nota" unreadAntennaNote: "Antena {name}" + roleAssigned: "Rol asignado" emptyPushNotificationMessage: "Se han actualizado las notificaciones push" achievementEarned: "Logro desbloqueado" testNotification: "Notificación de prueba" @@ -2110,6 +2184,7 @@ _notification: pollEnded: "La encuesta terminó" receiveFollowRequest: "Recibió una solicitud de seguimiento" followRequestAccepted: "El seguimiento fue aceptado" + roleAssigned: "Rol asignado" achievementEarned: "Logro desbloqueado" app: "Notificaciones desde aplicaciones" _actions: @@ -2255,3 +2330,6 @@ _externalResourceInstaller: _themeInstallFailed: title: "Instalación de tema fallida" description: "Ha ocurrido un problema al instalar el tema. Por favor, inténtalo de nuevo. Se pueden ver más detalles del error en la consola de Javascript." +_dataSaver: + _media: + title: "Cargando Multimedia" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 6cdcc2c24..63d0812e9 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -114,7 +114,7 @@ quote: "인용" inChannelRenote: "채널 내 리노트" inChannelQuote: "채널 내 인용" pinnedNote: "고정된 노트" -pinned: "프로필에 고정" +pinned: "고정하기" you: "나" clickToShow: "클릭하여 보기" sensitive: "열람 주의" @@ -1179,7 +1179,7 @@ code: "문자열" reloadRequiredToApplySettings: "설정을 적용하려면 새로고침을 해야 합니다." remainingN: "나머지: {n}" overwriteContentConfirm: "현재 내용을 덮어쓰기 합니다. 계속 진행하시겠습니까?" -seasonalScreenEffect: "철에 맞는 화면으로 꾸미기" +seasonalScreenEffect: "계절에 따른 효과 보이기" decorate: "장식하기" _announcement: forExistingUsers: "기존 유저에게만 알림" @@ -1641,6 +1641,7 @@ _emailUnavailable: disposable: "임시 이메일 주소는 사용할 수 없습니다" mx: "메일 서버가 올바르지 않습니다" smtp: "메일 서버가 응답하지 않습니다" + banned: "이 메일 주소는 사용할 수 없습니다" _ffVisibility: public: "공개" followers: "팔로워에게만 공개" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 51ba42e66..782f871b1 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -632,11 +632,11 @@ tokenRequested: "允許存取帳戶" pluginTokenRequestedDescription: "此外掛將擁有在此設定的權限。" notificationType: "通知形式" edit: "編輯" -emailServer: "電郵伺服器" -enableEmail: "啟用發送電郵功能" -emailConfigInfo: "用於確認電郵地址及密碼重置" +emailServer: "電子郵件伺服器" +enableEmail: "啟用發送電子郵件功能" +emailConfigInfo: "用於確認電子郵件地址及密碼重置" email: "電子郵件" -emailAddress: "電郵地址" +emailAddress: "電子郵件位址" smtpConfig: "SMTP 伺服器設定" smtpHost: "主機" smtpPort: "埠" @@ -731,7 +731,7 @@ disableShowingAnimatedImages: "不播放動態圖檔" highlightSensitiveMedia: "強調敏感標記" verificationEmailSent: "已發送驗證電子郵件。請點擊進入電子郵件中的鏈接完成驗證。" notSet: "未設定" -emailVerified: "已成功驗證您的電郵" +emailVerified: "已成功驗證您的電子郵件地址" noteFavoritesCount: "我的最愛貼文的數目" pageLikesCount: "頁面被按讚次數" pageLikedCount: "頁面被按讚次數" @@ -783,7 +783,7 @@ capacity: "容量" inUse: "已使用" editCode: "編輯代碼" apply: "套用" -receiveAnnouncementFromInstance: "接收由本實例發出的電郵通知" +receiveAnnouncementFromInstance: "接收來自伺服器的通知" emailNotification: "郵件通知" publish: "發布" inChannelSearch: "頻道内搜尋" @@ -955,7 +955,7 @@ cannotUploadBecauseExceedsFileSizeLimit: "由於超過了檔案大小的限制 beta: "測試版" enableAutoSensitive: "自動 NSFW 判定" enableAutoSensitiveDescription: "如果可用,它將使用機器學習技術判斷檔案是否需要標記為敏感。即使關閉此功能,也可能會依實例規則而自動啟用。" -activeEmailValidationDescription: "積極驗證使用者的電郵地址,以判斷它是否可以通訊。關閉此選項代表只會檢查地址是否符合格式。" +activeEmailValidationDescription: "主動地驗證使用者的電子郵件地址,以確定是否是一次性地址以及是否可以真正與其進行通訊。關閉時,僅檢查格式是否正確。" navbar: "導覽列" shuffle: "隨機" account: "帳戶" @@ -1641,6 +1641,7 @@ _emailUnavailable: disposable: "不是永久可用的地址" mx: "郵件伺服器不正確" smtp: "郵件伺服器沒有應答" + banned: "無法使用此電子郵件地址註冊" _ffVisibility: public: "公開" followers: "只有關注您的使用者能看到" From 7167bb397e6a40fa715254e2aa7f901956275975 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 24 Dec 2023 15:31:48 +0900 Subject: [PATCH 06/32] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af2aea799..4751fff65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -110,6 +110,7 @@ - Enhance: MFM `$[ruby ]` が他ソフトウェアと連合されるように - Enhance: Meilisearchを有効にした検索で、ユーザーのミュートやブロックを考慮するように - Enhance: カスタム絵文字のインポート時の動作を改善 +- Enhance: json-schema(OpenAPIの戻り値として使用されるスキーマ定義)を出来る限り最新化 #12311 - Fix: 時間経過により無効化されたアンテナを再有効化したとき、サーバ再起動までその状況が反映されないのを修正 #12303 - Fix: ロールタイムラインが保存されない問題を修正 - Fix: api.jsonの生成ロジックを改善 #12402 @@ -137,7 +138,6 @@ - Feat: 管理者がコントロールパネルからメールアドレスの照会を行えるようになりました - Enhance: ローカリゼーションの更新 - Enhance: 依存関係の更新 -- Enhance: json-schema(OpenAPIの戻り値として使用されるスキーマ定義)を出来る限り最新化 #12311 ### Client - Enhance: MFMでルビを振れるように From bf45c2309845640de9a0d0472bb4480b2a9dc8af Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 24 Dec 2023 15:38:03 +0900 Subject: [PATCH 07/32] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4751fff65..432b39afb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,13 +15,14 @@ ## 2023.12.1 ### General -- +- Enhance: ローカリゼーションの更新 ### Client - ### Server - Enhance: センシティブワードの設定がハッシュタグトレンドにも適用されるようになりました +- Fix: 1702718871541-ffVisibility.jsのdownが壊れている ## 2023.12.0 From 0009aa332bec1bb52ee5600d528419c0455576d2 Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Sun, 24 Dec 2023 16:16:58 +0900 Subject: [PATCH 08/32] =?UTF-8?q?refactor(frontend):=20import=E5=AE=A3?= =?UTF-8?q?=E8=A8=80=E5=91=A8=E3=82=8A=E3=81=AE=E3=82=A8=E3=83=A9=E3=83=BC?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3=20(#12773)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...lugin-unwind-css-module-class-name.test.ts | 2 +- .../components/MkAbuseReport.stories.impl.ts | 4 ++-- .../MkAbuseReportWindow.stories.impl.ts | 4 ++-- .../components/MkAccountMoved.stories.impl.ts | 2 +- .../components/MkAchievements.stories.impl.ts | 4 ++-- .../components/MkAutocomplete.stories.impl.ts | 4 ++-- .../src/components/MkAvatars.stories.impl.ts | 4 ++-- .../frontend/src/components/MkContextMenu.vue | 2 +- .../src/components/MkDateSeparatedList.vue | 4 ++-- .../MkGalleryPostPreview.stories.impl.ts | 2 +- .../components/MkInviteCode.stories.impl.ts | 4 ++-- .../frontend/src/components/MkMediaList.vue | 2 +- packages/frontend/src/components/MkMenu.vue | 2 +- .../frontend/src/components/MkPageWindow.vue | 2 +- .../frontend/src/components/MkPagination.vue | 2 +- .../MkUserSetupDialog.Follow.stories.impl.ts | 4 ++-- .../MkUserSetupDialog.User.stories.impl.ts | 2 +- .../MkUserSetupDialog.stories.impl.ts | 4 ++-- .../frontend/src/components/MkWidgets.vue | 2 +- .../components/global/MkAcct.stories.impl.ts | 2 +- .../global/MkAvatar.stories.impl.ts | 2 +- .../MkMisskeyFlavoredMarkdown.stories.impl.ts | 2 +- .../components/global/MkStickyContainer.vue | 2 +- .../components/global/MkUrl.stories.impl.ts | 2 +- .../global/MkUserName.stories.impl.ts | 2 +- .../src/components/global/RouterView.vue | 2 +- .../src/components/page/page.block.vue | 2 +- .../src/components/page/page.image.vue | 2 +- .../src/components/page/page.note.vue | 2 +- .../src/components/page/page.section.vue | 2 +- .../src/components/page/page.text.vue | 2 +- packages/frontend/src/directives/hotkey.ts | 2 +- packages/frontend/src/directives/index.ts | 22 +++++++++---------- .../frontend/src/pages/admin/_header_.vue | 2 +- .../frontend/src/pages/admin/roles.edit.vue | 2 +- packages/frontend/src/pages/admin/roles.vue | 2 +- packages/frontend/src/pages/clip.vue | 2 +- .../frontend/src/pages/my-antennas/edit.vue | 2 +- .../frontend/src/pages/my-antennas/index.vue | 2 +- .../frontend/src/pages/my-clips/index.vue | 2 +- .../frontend/src/pages/my-lists/index.vue | 2 +- .../frontend/src/pages/settings/navbar.vue | 2 +- .../src/pages/settings/theme.manage.vue | 2 +- .../frontend/src/pages/settings/theme.vue | 2 +- packages/frontend/src/pages/theme-editor.vue | 2 +- .../src/pages/user/home.stories.impl.ts | 4 ++-- .../src/scripts/upload/compress-config.ts | 2 +- packages/frontend/src/ui/_common_/common.vue | 4 ++-- .../src/ui/_common_/navbar-for-mobile.vue | 4 ++-- packages/frontend/src/ui/classic.header.vue | 4 ++-- packages/frontend/src/ui/deck/column.vue | 2 +- packages/frontend/src/ui/deck/list-column.vue | 2 +- packages/frontend/src/ui/deck/main-column.vue | 2 +- .../src/widgets/server-metric/index.vue | 2 +- packages/frontend/test/init.ts | 4 ++-- packages/frontend/vite.config.local-dev.ts | 2 +- packages/frontend/vite.config.ts | 7 +++--- 57 files changed, 84 insertions(+), 83 deletions(-) diff --git a/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts b/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts index 550e08d7f..535adc9c8 100644 --- a/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts +++ b/packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts @@ -6,7 +6,7 @@ import { parse } from 'acorn'; import { generate } from 'astring'; import { describe, expect, it } from 'vitest'; -import { normalizeClass, unwindCssModuleClassName } from './rollup-plugin-unwind-css-module-class-name'; +import { normalizeClass, unwindCssModuleClassName } from './rollup-plugin-unwind-css-module-class-name.js'; import type * as estree from 'estree'; function parseExpression(code: string): estree.Expression { diff --git a/packages/frontend/src/components/MkAbuseReport.stories.impl.ts b/packages/frontend/src/components/MkAbuseReport.stories.impl.ts index 3b6452962..77e7c84d5 100644 --- a/packages/frontend/src/components/MkAbuseReport.stories.impl.ts +++ b/packages/frontend/src/components/MkAbuseReport.stories.impl.ts @@ -7,8 +7,8 @@ import { action } from '@storybook/addon-actions'; import { StoryObj } from '@storybook/vue3'; import { rest } from 'msw'; -import { abuseUserReport } from '../../.storybook/fakes'; -import { commonHandlers } from '../../.storybook/mocks'; +import { abuseUserReport } from '../../.storybook/fakes.js'; +import { commonHandlers } from '../../.storybook/mocks.js'; import MkAbuseReport from './MkAbuseReport.vue'; export const Default = { render(args) { diff --git a/packages/frontend/src/components/MkAbuseReportWindow.stories.impl.ts b/packages/frontend/src/components/MkAbuseReportWindow.stories.impl.ts index b45d54679..dc842b3d1 100644 --- a/packages/frontend/src/components/MkAbuseReportWindow.stories.impl.ts +++ b/packages/frontend/src/components/MkAbuseReportWindow.stories.impl.ts @@ -7,8 +7,8 @@ import { action } from '@storybook/addon-actions'; import { StoryObj } from '@storybook/vue3'; import { rest } from 'msw'; -import { userDetailed } from '../../.storybook/fakes'; -import { commonHandlers } from '../../.storybook/mocks'; +import { userDetailed } from '../../.storybook/fakes.js'; +import { commonHandlers } from '../../.storybook/mocks.js'; import MkAbuseReportWindow from './MkAbuseReportWindow.vue'; export const Default = { render(args) { diff --git a/packages/frontend/src/components/MkAccountMoved.stories.impl.ts b/packages/frontend/src/components/MkAccountMoved.stories.impl.ts index a6d4d18c1..33c6c2463 100644 --- a/packages/frontend/src/components/MkAccountMoved.stories.impl.ts +++ b/packages/frontend/src/components/MkAccountMoved.stories.impl.ts @@ -5,7 +5,7 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ import { StoryObj } from '@storybook/vue3'; -import { userDetailed } from '../../.storybook/fakes'; +import { userDetailed } from '../../.storybook/fakes.js'; import MkAccountMoved from './MkAccountMoved.vue'; export const Default = { render(args) { diff --git a/packages/frontend/src/components/MkAchievements.stories.impl.ts b/packages/frontend/src/components/MkAchievements.stories.impl.ts index a67e1def1..6d972467b 100644 --- a/packages/frontend/src/components/MkAchievements.stories.impl.ts +++ b/packages/frontend/src/components/MkAchievements.stories.impl.ts @@ -6,8 +6,8 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ import { StoryObj } from '@storybook/vue3'; import { rest } from 'msw'; -import { userDetailed } from '../../.storybook/fakes'; -import { commonHandlers } from '../../.storybook/mocks'; +import { userDetailed } from '../../.storybook/fakes.js'; +import { commonHandlers } from '../../.storybook/mocks.js'; import MkAchievements from './MkAchievements.vue'; import { ACHIEVEMENT_TYPES } from '@/scripts/achievements.js'; export const Empty = { diff --git a/packages/frontend/src/components/MkAutocomplete.stories.impl.ts b/packages/frontend/src/components/MkAutocomplete.stories.impl.ts index 8232759ba..969519386 100644 --- a/packages/frontend/src/components/MkAutocomplete.stories.impl.ts +++ b/packages/frontend/src/components/MkAutocomplete.stories.impl.ts @@ -9,8 +9,8 @@ import { expect } from '@storybook/jest'; import { userEvent, waitFor, within } from '@storybook/testing-library'; import { StoryObj } from '@storybook/vue3'; import { rest } from 'msw'; -import { userDetailed } from '../../.storybook/fakes'; -import { commonHandlers } from '../../.storybook/mocks'; +import { userDetailed } from '../../.storybook/fakes.js'; +import { commonHandlers } from '../../.storybook/mocks.js'; import MkAutocomplete from './MkAutocomplete.vue'; import MkInput from './MkInput.vue'; import { tick } from '@/scripts/test-utils.js'; diff --git a/packages/frontend/src/components/MkAvatars.stories.impl.ts b/packages/frontend/src/components/MkAvatars.stories.impl.ts index 659c0eebd..d41b64695 100644 --- a/packages/frontend/src/components/MkAvatars.stories.impl.ts +++ b/packages/frontend/src/components/MkAvatars.stories.impl.ts @@ -6,8 +6,8 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ import { StoryObj } from '@storybook/vue3'; import { rest } from 'msw'; -import { userDetailed } from '../../.storybook/fakes'; -import { commonHandlers } from '../../.storybook/mocks'; +import { userDetailed } from '../../.storybook/fakes.js'; +import { commonHandlers } from '../../.storybook/mocks.js'; import MkAvatars from './MkAvatars.vue'; export const Default = { render(args) { diff --git a/packages/frontend/src/components/MkContextMenu.vue b/packages/frontend/src/components/MkContextMenu.vue index b78252be8..e29cf472f 100644 --- a/packages/frontend/src/components/MkContextMenu.vue +++ b/packages/frontend/src/components/MkContextMenu.vue @@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index 33a6786d0..f1bcdec7f 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -224,7 +224,7 @@ import { claimAchievement } from '@/scripts/achievements.js'; import MkRippleEffect from '@/components/MkRippleEffect.vue'; import { showMovedDialog } from '@/scripts/show-moved-dialog.js'; import MkUserCardMini from '@/components/MkUserCardMini.vue'; -import MkPagination from '@/components/MkPagination.vue'; +import MkPagination, { Paging } from '@/components/MkPagination.vue'; import MkReactionIcon from '@/components/MkReactionIcon.vue'; import MkButton from '@/components/MkButton.vue'; @@ -307,7 +307,7 @@ const renotesPagination = computed(() => ({ params: { noteId: appearNote.value.id, }, -})); +} satisfies Paging)); const reactionsPagination = computed(() => ({ endpoint: 'notes/reactions', @@ -316,7 +316,7 @@ const reactionsPagination = computed(() => ({ noteId: appearNote.value.id, type: reactionTabType.value, }, -})); +} satisfies Paging)); useNoteCapture({ rootEl: el, diff --git a/packages/frontend/src/components/MkUserSetupDialog.Follow.vue b/packages/frontend/src/components/MkUserSetupDialog.Follow.vue index 5f3f5b81d..d924a54ff 100644 --- a/packages/frontend/src/components/MkUserSetupDialog.Follow.vue +++ b/packages/frontend/src/components/MkUserSetupDialog.Follow.vue @@ -37,15 +37,15 @@ SPDX-License-Identifier: AGPL-3.0-only import { i18n } from '@/i18n.js'; import MkFolder from '@/components/MkFolder.vue'; import XUser from '@/components/MkUserSetupDialog.User.vue'; -import MkPagination from '@/components/MkPagination.vue'; +import MkPagination, { Paging } from '@/components/MkPagination.vue'; -const pinnedUsers = { endpoint: 'pinned-users', noPaging: true }; +const pinnedUsers = { endpoint: 'pinned-users', noPaging: true } satisfies Paging; const popularUsers = { endpoint: 'users', limit: 10, noPaging: true, params: { state: 'alive', origin: 'local', sort: '+follower', -} }; +} } satisfies Paging;