forked from naskya/firefish
Firefish v1.0.4-beta
This commit is contained in:
parent
f58683e142
commit
52e3595da2
49 changed files with 2329 additions and 853 deletions
|
@ -34,7 +34,7 @@ port: 3000
|
||||||
#───┘ PostgreSQL configuration └────────────────────────────────
|
#───┘ PostgreSQL configuration └────────────────────────────────
|
||||||
|
|
||||||
db:
|
db:
|
||||||
host: database
|
host: postgres
|
||||||
port: 5432
|
port: 5432
|
||||||
|
|
||||||
# Database name
|
# Database name
|
||||||
|
|
|
@ -29,7 +29,7 @@ url: https://example.com/
|
||||||
# The port that your Firefish server should listen on.
|
# The port that your Firefish server should listen on.
|
||||||
port: 3000
|
port: 3000
|
||||||
|
|
||||||
# The bind host your Calckey server should listen on.
|
# The bind host your Firefish server should listen on.
|
||||||
# If unspecified, the wildcard address will be used.
|
# If unspecified, the wildcard address will be used.
|
||||||
#bind: 127.0.0.1
|
#bind: 127.0.0.1
|
||||||
|
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,7 @@
|
||||||
# Visual Studio Code
|
# Visual Studio Code
|
||||||
/.vscode
|
/.vscode
|
||||||
!/.vscode/extensions.json
|
!/.vscode/extensions.json
|
||||||
|
!/.vscode/launch.json
|
||||||
|
|
||||||
# Intelij-IDEA
|
# Intelij-IDEA
|
||||||
/.idea
|
/.idea
|
||||||
|
|
1952
CHANGELOG.md
1952
CHANGELOG.md
File diff suppressed because it is too large
Load diff
|
@ -12,9 +12,6 @@ You can contribute without knowing how to code by helping translate here:
|
||||||
|
|
||||||
[![Translation bars](https://hosted.weblate.org/widgets/firefish/-/multi-auto.svg)](https://hosted.weblate.org/engage/firefish/)
|
[![Translation bars](https://hosted.weblate.org/widgets/firefish/-/multi-auto.svg)](https://hosted.weblate.org/engage/firefish/)
|
||||||
|
|
||||||
## Roadmap
|
|
||||||
See [FIREFISH.md](./FIREFISH.md)
|
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
Before creating an issue, please check the following:
|
Before creating an issue, please check the following:
|
||||||
- To avoid duplication, please search for similar issues before creating a new issue.
|
- To avoid duplication, please search for similar issues before creating a new issue.
|
||||||
|
|
|
@ -2177,5 +2177,5 @@ deletePasskeys: Suprimeix les contrasenyes
|
||||||
deletePasskeysConfirm: Això suprimirà de manera irreversible totes les contrasenyes
|
deletePasskeysConfirm: Això suprimirà de manera irreversible totes les contrasenyes
|
||||||
i claus de seguretat d'aquest compte. Procedir?
|
i claus de seguretat d'aquest compte. Procedir?
|
||||||
inputNotMatch: L'entrada no coincideix
|
inputNotMatch: L'entrada no coincideix
|
||||||
delete2fa: Suprimeix 2FA
|
delete2fa: Desactivar 2FA
|
||||||
delete2faConfirm: Això suprimirà irreversiblement 2FA en aquest compte. Procedir?
|
delete2faConfirm: Això suprimirà irreversiblement 2FA en aquest compte. Procedir?
|
||||||
|
|
|
@ -853,7 +853,7 @@ gallery: "Bilder-Galerie"
|
||||||
recentPosts: "Neue Beiträge"
|
recentPosts: "Neue Beiträge"
|
||||||
popularPosts: "Beliebte Beiträge"
|
popularPosts: "Beliebte Beiträge"
|
||||||
shareWithNote: "Mit Beitrag teilen"
|
shareWithNote: "Mit Beitrag teilen"
|
||||||
ads: "Werbeanzeigen"
|
ads: "Community-Banner"
|
||||||
expiration: "Frist"
|
expiration: "Frist"
|
||||||
memo: "Merkzettel"
|
memo: "Merkzettel"
|
||||||
priority: "Priorität"
|
priority: "Priorität"
|
||||||
|
@ -953,9 +953,9 @@ driveCapOverrideCaption: "Gib einen Wert von 0 oder weniger ein, um die Kapazit
|
||||||
auf den Standard zurückzusetzen."
|
auf den Standard zurückzusetzen."
|
||||||
requireAdminForView: "Du musst dich mit einem Administratorkonto anmelden um dies
|
requireAdminForView: "Du musst dich mit einem Administratorkonto anmelden um dies
|
||||||
zu sehen."
|
zu sehen."
|
||||||
isSystemAccount: "Dieses Konto wird vom System erstellt und automatisch verwaltet.
|
isSystemAccount: "Ein Nutzerkonto, dass durch das System erstellt und automatisch
|
||||||
Bitte moderieren, bearbeiten, löschen oder manipulieren Sie dieses Konto nicht,
|
kontrolliert wird. Jede Anpassung, Veränderung oder Löschung dieses Nutzerkontos,
|
||||||
da es sonst zu einem Server-Absturz kommen könnte."
|
kann zu schwerwiegenden Fehlern auf diesem Server führen."
|
||||||
typeToConfirm: "Bitte gib zur Bestätigung {x} ein"
|
typeToConfirm: "Bitte gib zur Bestätigung {x} ein"
|
||||||
deleteAccount: "Nutzerkonto löschen"
|
deleteAccount: "Nutzerkonto löschen"
|
||||||
document: "Dokumentation"
|
document: "Dokumentation"
|
||||||
|
@ -966,7 +966,7 @@ logoutConfirm: "Wirklich abmelden?"
|
||||||
lastActiveDate: "Zuletzt verwendet am"
|
lastActiveDate: "Zuletzt verwendet am"
|
||||||
statusbar: "Statusleiste"
|
statusbar: "Statusleiste"
|
||||||
pleaseSelect: "Wähle eine Option"
|
pleaseSelect: "Wähle eine Option"
|
||||||
reverse: "Umkehren"
|
reverse: "Rückgängig machen"
|
||||||
colored: "Farbig"
|
colored: "Farbig"
|
||||||
refreshInterval: "Aktualisierungsintervall "
|
refreshInterval: "Aktualisierungsintervall "
|
||||||
label: "Beschriftung"
|
label: "Beschriftung"
|
||||||
|
@ -1128,7 +1128,7 @@ _mfm:
|
||||||
bold: "Fett"
|
bold: "Fett"
|
||||||
boldDescription: "Zeichen zur Betonung dicker erscheinen lassen."
|
boldDescription: "Zeichen zur Betonung dicker erscheinen lassen."
|
||||||
small: "Klein"
|
small: "Klein"
|
||||||
smallDescription: "Inhalt klein und dünn erscheinen lassen."
|
smallDescription: "Inhalt klein und dünn anzeigen."
|
||||||
center: "Zentrieren"
|
center: "Zentrieren"
|
||||||
centerDescription: "Inhalt zentriert anzeigen."
|
centerDescription: "Inhalt zentriert anzeigen."
|
||||||
inlineCode: "Code (Eingebettet)"
|
inlineCode: "Code (Eingebettet)"
|
||||||
|
@ -2053,7 +2053,7 @@ userSaysSomethingReasonReply: '{name} hat auf einen Beitrag geantwortet der {rea
|
||||||
userSaysSomethingReasonRenote: '{name} hat einen Beitrag geteilt der {reason} beinhaltet'
|
userSaysSomethingReasonRenote: '{name} hat einen Beitrag geteilt der {reason} beinhaltet'
|
||||||
userSaysSomethingReasonQuote: '{name} hat einen Beitrag zitiert der {reason} beinhaltet'
|
userSaysSomethingReasonQuote: '{name} hat einen Beitrag zitiert der {reason} beinhaltet'
|
||||||
seperateRenoteQuote: Getrennte Boost- und Zitat-Schaltflächen
|
seperateRenoteQuote: Getrennte Boost- und Zitat-Schaltflächen
|
||||||
showAds: Anzeigen anzeigen
|
showAds: Community-Banner anzeigen
|
||||||
splash: Begrüßungsbildschirm
|
splash: Begrüßungsbildschirm
|
||||||
customSplashIconsDescription: URLs für benutzerdefinierte Splash-Screen-Symbole, die
|
customSplashIconsDescription: URLs für benutzerdefinierte Splash-Screen-Symbole, die
|
||||||
durch Zeilenumbrüche getrennt sind und nach dem Zufallsprinzip jedes Mal angezeigt
|
durch Zeilenumbrüche getrennt sind und nach dem Zufallsprinzip jedes Mal angezeigt
|
||||||
|
@ -2191,3 +2191,13 @@ _skinTones:
|
||||||
showPopup: Benutzer mit Popup benachrichtigen
|
showPopup: Benutzer mit Popup benachrichtigen
|
||||||
showWithSparkles: Mit Glitzer anzeigen
|
showWithSparkles: Mit Glitzer anzeigen
|
||||||
removeQuote: Zitat entfernen
|
removeQuote: Zitat entfernen
|
||||||
|
objectStorageS3ForcePathStyle: Verwende pfadbasierte Endpunkt-URLs
|
||||||
|
objectStorageS3ForcePathStyleDesc: Wenn aktiviert, werden Endpunkt-URLs im Format
|
||||||
|
's3.amazonaws.com/<bucket>/' statt '<bucket>.s3.amazonaws.com' erstellt.
|
||||||
|
origin: Herkunft
|
||||||
|
delete2fa: 2FA deaktivieren
|
||||||
|
deletePasskeys: Passkeys löschen
|
||||||
|
delete2faConfirm: Passkeys werden unwiderruflich von diesem Account gelöscht. Fortfahren?
|
||||||
|
deletePasskeysConfirm: Alle Passkeys und Security-Keys werden unwiderruflich von diesem
|
||||||
|
Account gelöscht. Fortfahren?
|
||||||
|
inputNotMatch: Eingabe stimmt nicht überein
|
||||||
|
|
|
@ -1135,7 +1135,6 @@ hideFollowButtons: "Hide follow buttons in notifications and user pages"
|
||||||
forMobile: "Mobile"
|
forMobile: "Mobile"
|
||||||
replaceChatButtonWithAccountButton: "Replace chat button at the bottom with account switch button"
|
replaceChatButtonWithAccountButton: "Replace chat button at the bottom with account switch button"
|
||||||
replaceWidgetsButtonWithReloadButton: "Replace widgets button at the bottom with reload button"
|
replaceWidgetsButtonWithReloadButton: "Replace widgets button at the bottom with reload button"
|
||||||
addRe: "Add \"re:\" at the beginning of comment in reply to CW'd post"
|
|
||||||
origin: "Origin"
|
origin: "Origin"
|
||||||
delete2fa: "Disable 2FA"
|
delete2fa: "Disable 2FA"
|
||||||
deletePasskeys: "Delete passkeys"
|
deletePasskeys: "Delete passkeys"
|
||||||
|
@ -1144,6 +1143,7 @@ deletePasskeysConfirm: "This will irreversibly delete all passkeys and security
|
||||||
inputNotMatch: "Input does not match"
|
inputNotMatch: "Input does not match"
|
||||||
detectPostLanguage: "Automatically detect the language and show a translate button for non-English posts"
|
detectPostLanguage: "Automatically detect the language and show a translate button for non-English posts"
|
||||||
languageForTranslation: "Language used for post translation"
|
languageForTranslation: "Language used for post translation"
|
||||||
|
addRe: "Add \"re:\" at the beginning of comment in reply to a post with a content warning"
|
||||||
|
|
||||||
_sensitiveMediaDetection:
|
_sensitiveMediaDetection:
|
||||||
description: "Reduces the effort of server moderation through automatically recognizing
|
description: "Reduces the effort of server moderation through automatically recognizing
|
||||||
|
@ -1239,7 +1239,7 @@ _aboutFirefish:
|
||||||
development since 2022."
|
development since 2022."
|
||||||
contributors: "Main contributors"
|
contributors: "Main contributors"
|
||||||
allContributors: "All contributors"
|
allContributors: "All contributors"
|
||||||
originalMisskeyContributors: "Original Misskey main contributors"
|
misskeyContributors: "Misskey main contributors"
|
||||||
source: "Source code"
|
source: "Source code"
|
||||||
translation: "Translate Firefish"
|
translation: "Translate Firefish"
|
||||||
donate: "Donate to Firefish"
|
donate: "Donate to Firefish"
|
||||||
|
|
|
@ -161,7 +161,7 @@ autoAcceptFollowed: "Aceptar automáticamente las solicitudes de seguimiento de
|
||||||
usuarios que sigues"
|
usuarios que sigues"
|
||||||
addAccount: "Agregar Cuenta"
|
addAccount: "Agregar Cuenta"
|
||||||
loginFailed: "Error al iniciar sesión"
|
loginFailed: "Error al iniciar sesión"
|
||||||
showOnRemote: "Ver en servidor remoto"
|
showOnRemote: "Abrir página original"
|
||||||
general: "General"
|
general: "General"
|
||||||
wallpaper: "Fondo de pantalla"
|
wallpaper: "Fondo de pantalla"
|
||||||
setWallpaper: "Establecer fondo de pantalla"
|
setWallpaper: "Establecer fondo de pantalla"
|
||||||
|
@ -540,7 +540,7 @@ objectStorageSetPublicRead: "Seleccionar \"public-read\" al subir "
|
||||||
serverLogs: "Registros del servidor"
|
serverLogs: "Registros del servidor"
|
||||||
deleteAll: "Eliminar todos"
|
deleteAll: "Eliminar todos"
|
||||||
showFixedPostForm: "Mostrar el formulario de las entradas encima de la línea de tiempo"
|
showFixedPostForm: "Mostrar el formulario de las entradas encima de la línea de tiempo"
|
||||||
newNoteRecived: "Tienes unas publicaciones nuevas"
|
newNoteRecived: "Hay publicaciones nuevas"
|
||||||
sounds: "Sonidos"
|
sounds: "Sonidos"
|
||||||
listen: "Escuchar"
|
listen: "Escuchar"
|
||||||
none: "Ninguna"
|
none: "Ninguna"
|
||||||
|
@ -690,7 +690,7 @@ instanceTicker: "Información de publicaciones de el servidor"
|
||||||
waitingFor: "Esperando a {x}"
|
waitingFor: "Esperando a {x}"
|
||||||
random: "Aleatorio"
|
random: "Aleatorio"
|
||||||
system: "Sistema"
|
system: "Sistema"
|
||||||
switchUi: "Cambiar interfaz de usuario"
|
switchUi: "Interfaz"
|
||||||
desktop: "Escritorio"
|
desktop: "Escritorio"
|
||||||
clip: "Clip"
|
clip: "Clip"
|
||||||
createNew: "Crear"
|
createNew: "Crear"
|
||||||
|
@ -700,15 +700,15 @@ unclip: "Quitar clip"
|
||||||
confirmToUnclipAlreadyClippedNote: "Esta publicación ya está incluida en el clip \"\
|
confirmToUnclipAlreadyClippedNote: "Esta publicación ya está incluida en el clip \"\
|
||||||
{name}\". ¿Quiere quitar la nota del clip?"
|
{name}\". ¿Quiere quitar la nota del clip?"
|
||||||
public: "Público"
|
public: "Público"
|
||||||
i18nInfo: "Firefish está siendo traducido a varios idiomas gracias a voluntarios. Se
|
i18nInfo: "Firefish está siendo traducido a varios idiomas gracias a voluntarios.
|
||||||
puede colaborar traduciendo en {link}"
|
Se puede colaborar traduciendo en {link}"
|
||||||
manageAccessTokens: "Administrar tokens de acceso"
|
manageAccessTokens: "Administrar tokens de acceso"
|
||||||
accountInfo: "Información de la Cuenta"
|
accountInfo: "Información de la Cuenta"
|
||||||
notesCount: "Cantidad de publicaciones"
|
notesCount: "Cantidad de publicaciones"
|
||||||
repliesCount: "Cantidad de respuestas hechas"
|
repliesCount: "Cantidad de respuestas hechas"
|
||||||
renotesCount: "Cantidad de renotas hechas"
|
renotesCount: "Número de impulsos enviados"
|
||||||
repliedCount: "Cantidad de respuestas recibidas"
|
repliedCount: "Cantidad de respuestas recibidas"
|
||||||
renotedCount: "Cantidad de renotas recibidas"
|
renotedCount: "Cantidad de impulsos recibidos"
|
||||||
followingCount: "Cantidad de seguidos"
|
followingCount: "Cantidad de seguidos"
|
||||||
followersCount: "Cantidad de seguidores"
|
followersCount: "Cantidad de seguidores"
|
||||||
sentReactionsCount: "Cantidad de reacciones hechas"
|
sentReactionsCount: "Cantidad de reacciones hechas"
|
||||||
|
@ -722,9 +722,9 @@ driveUsage: "Uso del drive"
|
||||||
noCrawle: "Rechazar indexación del crawler"
|
noCrawle: "Rechazar indexación del crawler"
|
||||||
noCrawleDescription: "Pedir a los motores de búsqueda que no indexen tu perfil, publicaciones,
|
noCrawleDescription: "Pedir a los motores de búsqueda que no indexen tu perfil, publicaciones,
|
||||||
páginas, etc."
|
páginas, etc."
|
||||||
lockedAccountInfo: "A menos que configures la visibilidad de tus notas como \"Sólo
|
lockedAccountInfo: "A menos que configures la visibilidad de tus publicaciones como
|
||||||
seguidores\", tus notas serán visibles para cualquiera, incluso si requieres que
|
\"Sólo seguidores\", tus publicaciones serán visibles para cualquiera, incluso si
|
||||||
los seguidores sean aprobados manualmente."
|
requieres que los seguidores sean aprobados manualmente."
|
||||||
alwaysMarkSensitive: "Marcar los medios de comunicación como contenido sensible por
|
alwaysMarkSensitive: "Marcar los medios de comunicación como contenido sensible por
|
||||||
defecto"
|
defecto"
|
||||||
loadRawImages: "Cargar las imágenes originales en lugar de mostrar las miniaturas"
|
loadRawImages: "Cargar las imágenes originales en lugar de mostrar las miniaturas"
|
||||||
|
@ -758,7 +758,7 @@ showTitlebar: "Mostrar la barra de título"
|
||||||
clearCache: "Limpiar caché"
|
clearCache: "Limpiar caché"
|
||||||
onlineUsersCount: "{n} usuarios en línea"
|
onlineUsersCount: "{n} usuarios en línea"
|
||||||
nUsers: "{n} Usuarios"
|
nUsers: "{n} Usuarios"
|
||||||
nNotes: "{n} Notas"
|
nNotes: "{n} Publicaciones"
|
||||||
sendErrorReports: "Envíar informe de errores"
|
sendErrorReports: "Envíar informe de errores"
|
||||||
sendErrorReportsDescription: "Si habilita esta opción, los detalles de los errores
|
sendErrorReportsDescription: "Si habilita esta opción, los detalles de los errores
|
||||||
serán compartidos con Firefish cuando ocurra un problema, lo que ayudará a mejorar
|
serán compartidos con Firefish cuando ocurra un problema, lo que ayudará a mejorar
|
||||||
|
@ -788,7 +788,7 @@ capacity: "Capacidad"
|
||||||
inUse: "Usado"
|
inUse: "Usado"
|
||||||
editCode: "Editar código"
|
editCode: "Editar código"
|
||||||
apply: "Aplicar"
|
apply: "Aplicar"
|
||||||
receiveAnnouncementFromInstance: "Recibir notificaciones de la instancia"
|
receiveAnnouncementFromInstance: "Recibir notificaciones de este servidor"
|
||||||
emailNotification: "Notificaciones por correo electrónico"
|
emailNotification: "Notificaciones por correo electrónico"
|
||||||
publish: "Publicar"
|
publish: "Publicar"
|
||||||
inChannelSearch: "Buscar en el canal"
|
inChannelSearch: "Buscar en el canal"
|
||||||
|
@ -804,9 +804,10 @@ unlikeConfirm: "¿Quitar como favorito?"
|
||||||
fullView: "Vista completa"
|
fullView: "Vista completa"
|
||||||
quitFullView: "quitar vista completa"
|
quitFullView: "quitar vista completa"
|
||||||
addDescription: "Agregar descripción"
|
addDescription: "Agregar descripción"
|
||||||
userPagePinTip: "Puede mantener sus notas visibles aquí seleccionando Pin en el menú
|
userPagePinTip: "Puede mantener tus publicaciones visibles aquí seleccionando Pin
|
||||||
de notas individuales"
|
en el menú de notas individuales."
|
||||||
notSpecifiedMentionWarning: "Algunas menciones no están incluidas en el destino"
|
notSpecifiedMentionWarning: "Esta publicacion contiene menciones a usuarios no incluídos
|
||||||
|
como destinatarios"
|
||||||
info: "Información"
|
info: "Información"
|
||||||
userInfo: "Información del usuario"
|
userInfo: "Información del usuario"
|
||||||
unknown: "Desconocido"
|
unknown: "Desconocido"
|
||||||
|
@ -819,7 +820,7 @@ active: "Activo"
|
||||||
offline: "Sin conexión"
|
offline: "Sin conexión"
|
||||||
notRecommended: "obsoleto"
|
notRecommended: "obsoleto"
|
||||||
botProtection: "Protección contra bots"
|
botProtection: "Protección contra bots"
|
||||||
instanceBlocking: "Instancias bloqueadas"
|
instanceBlocking: "Gestión de la Federación"
|
||||||
selectAccount: "Elija una cuenta"
|
selectAccount: "Elija una cuenta"
|
||||||
switchAccount: "Cambiar de cuenta"
|
switchAccount: "Cambiar de cuenta"
|
||||||
enabled: "Activado"
|
enabled: "Activado"
|
||||||
|
@ -836,8 +837,8 @@ postToGallery: "Crear una nueva publicación en la galería"
|
||||||
gallery: "Galería"
|
gallery: "Galería"
|
||||||
recentPosts: "Posts recientes"
|
recentPosts: "Posts recientes"
|
||||||
popularPosts: "Más vistos"
|
popularPosts: "Más vistos"
|
||||||
shareWithNote: "Compartir con una nota"
|
shareWithNote: "Compartir con una publicación"
|
||||||
ads: "Anuncios"
|
ads: "Banners"
|
||||||
expiration: "Termina el"
|
expiration: "Termina el"
|
||||||
memo: "Notas"
|
memo: "Notas"
|
||||||
priority: "Prioridad"
|
priority: "Prioridad"
|
||||||
|
@ -885,14 +886,14 @@ manageAccounts: "Administrar cuenta"
|
||||||
makeReactionsPublic: "Hacer el historial de reacciones público"
|
makeReactionsPublic: "Hacer el historial de reacciones público"
|
||||||
makeReactionsPublicDescription: "Todas las reacciones que hayas hecho serán públicamente
|
makeReactionsPublicDescription: "Todas las reacciones que hayas hecho serán públicamente
|
||||||
visibles."
|
visibles."
|
||||||
classic: "Clásico"
|
classic: "Centrado"
|
||||||
muteThread: "Ocultar hilo"
|
muteThread: "Ocultar hilo"
|
||||||
unmuteThread: "Mostrar hilo"
|
unmuteThread: "Mostrar hilo"
|
||||||
ffVisibility: "Visibilidad de seguidores y seguidos"
|
ffVisibility: "Visibilidad de seguidores y seguidos"
|
||||||
ffVisibilityDescription: "Puedes configurar quien puede ver a quienes sigues y quienes
|
ffVisibilityDescription: "Puedes configurar quien puede ver a quienes sigues y quienes
|
||||||
te siguen"
|
te siguen"
|
||||||
continueThread: "Ver la continuación del hilo"
|
continueThread: "Ver la continuación del hilo"
|
||||||
deleteAccountConfirm: "La cuenta será borrada. ¿Está seguro?"
|
deleteAccountConfirm: "La cuenta será borrada irreversiblemente. ¿Está seguro?"
|
||||||
incorrectPassword: "La contraseña es incorrecta"
|
incorrectPassword: "La contraseña es incorrecta"
|
||||||
voteConfirm: "¿Confirma su voto a {choice}?"
|
voteConfirm: "¿Confirma su voto a {choice}?"
|
||||||
hide: "Ocultar"
|
hide: "Ocultar"
|
||||||
|
@ -934,7 +935,9 @@ driveCapOverrideLabel: "Cambiar la capacidad de la unidad para este usuario"
|
||||||
driveCapOverrideCaption: "Restablecer la capacidad a su predeterminado ingresando
|
driveCapOverrideCaption: "Restablecer la capacidad a su predeterminado ingresando
|
||||||
un valor de 0 o menos"
|
un valor de 0 o menos"
|
||||||
requireAdminForView: "Necesitas iniciar sesión como administrador para ver esto."
|
requireAdminForView: "Necesitas iniciar sesión como administrador para ver esto."
|
||||||
isSystemAccount: "Cuenta creada y operada automáticamente por el sistema"
|
isSystemAccount: "Esta cuenta es creada y operada automaticamente por el sistema.
|
||||||
|
Porfavor no moderar, editar, borrar o manipular de ninguna forma esta cuenta, o
|
||||||
|
podría romper tu servidor."
|
||||||
typeToConfirm: "Ingrese {x} para confirmar"
|
typeToConfirm: "Ingrese {x} para confirmar"
|
||||||
deleteAccount: "Borrar cuenta"
|
deleteAccount: "Borrar cuenta"
|
||||||
document: "Documento"
|
document: "Documento"
|
||||||
|
@ -1019,8 +1022,9 @@ _forgotPassword:
|
||||||
enterEmail: "Ingrese el correo usado para registrar la cuenta. Se enviará un link
|
enterEmail: "Ingrese el correo usado para registrar la cuenta. Se enviará un link
|
||||||
para resetear la contraseña."
|
para resetear la contraseña."
|
||||||
ifNoEmail: "Si no utilizó un correo para crear la cuenta, contáctese con el administrador."
|
ifNoEmail: "Si no utilizó un correo para crear la cuenta, contáctese con el administrador."
|
||||||
contactAdmin: "Esta instancia no admite el uso de direcciones de correo electrónico,
|
contactAdmin: "Este servidor no admite el uso de direcciones de correo electrónico,
|
||||||
póngase en contacto con el administrador de la instancia para restablecer su contraseña"
|
póngase en contacto con la persona que administra el servidor para restablecer
|
||||||
|
su contraseña."
|
||||||
_gallery:
|
_gallery:
|
||||||
my: "Mi galería"
|
my: "Mi galería"
|
||||||
liked: "Publicaciones que me gustan"
|
liked: "Publicaciones que me gustan"
|
||||||
|
@ -1073,6 +1077,14 @@ _aboutFirefish:
|
||||||
morePatrons: "También apreciamos el apoyo de muchos más que no están enlistados
|
morePatrons: "También apreciamos el apoyo de muchos más que no están enlistados
|
||||||
aquí. ¡Gracias! 🥰"
|
aquí. ¡Gracias! 🥰"
|
||||||
patrons: "Mecenas de Firefish"
|
patrons: "Mecenas de Firefish"
|
||||||
|
pleaseDonateToFirefish: Por favor considera donar a Firefish para apollar su desarrollo.
|
||||||
|
donateHost: Dona a {host}
|
||||||
|
patronsList: Listados cronológicamente no por monto de la donación. ¡Dona con el
|
||||||
|
vínculo de arriba para que tu nombre aparezca aquí!
|
||||||
|
donateTitle: ¿Te gusta Firefish?
|
||||||
|
pleaseDonateToHost: También considera donar a tu propio servidor , {host}, para
|
||||||
|
ayudar con los costos de operación.
|
||||||
|
sponsors: Patrocinadores de Firefish
|
||||||
_nsfw:
|
_nsfw:
|
||||||
respect: "Ocultar medios NSFW"
|
respect: "Ocultar medios NSFW"
|
||||||
ignore: "No esconder medios NSFW "
|
ignore: "No esconder medios NSFW "
|
||||||
|
@ -1080,8 +1092,8 @@ _nsfw:
|
||||||
_mfm:
|
_mfm:
|
||||||
cheatSheet: "Hoja de referencia de MFM"
|
cheatSheet: "Hoja de referencia de MFM"
|
||||||
intro: "MFM es un lenguaje de marcado dedicado que se puede usar en varios lugares
|
intro: "MFM es un lenguaje de marcado dedicado que se puede usar en varios lugares
|
||||||
dentro de Misskey, Firefish, Akkoma, y mucho más. Aquí puede ver una lista de sintaxis
|
dentro de Misskey, Firefish, Akkoma, y mucho más. Aquí puede ver una lista de
|
||||||
disponibles en MFM."
|
sintaxis disponibles en MFM."
|
||||||
dummy: "Firefish expande el mundo de la Fediverso"
|
dummy: "Firefish expande el mundo de la Fediverso"
|
||||||
mention: "Menciones"
|
mention: "Menciones"
|
||||||
mentionDescription: "El signo @ seguido de un nombre de usuario se puede utilizar
|
mentionDescription: "El signo @ seguido de un nombre de usuario se puede utilizar
|
||||||
|
@ -1106,7 +1118,7 @@ _mfm:
|
||||||
inlineMath: "Fórmula (insertado)"
|
inlineMath: "Fórmula (insertado)"
|
||||||
inlineMathDescription: "Muestra fórmulas (KaTeX) insertadas"
|
inlineMathDescription: "Muestra fórmulas (KaTeX) insertadas"
|
||||||
blockMath: "Fórmula (bloque)"
|
blockMath: "Fórmula (bloque)"
|
||||||
blockMathDescription: "Muestra fórmulas (KaTeX) de varias líneas en un bloque"
|
blockMathDescription: "Muestra fórmulas matemáticas (KaTeX) en un bloque"
|
||||||
quote: "Citar"
|
quote: "Citar"
|
||||||
quoteDescription: "Muestra el contenido como una cita"
|
quoteDescription: "Muestra el contenido como una cita"
|
||||||
emoji: "Emojis personalizados"
|
emoji: "Emojis personalizados"
|
||||||
|
@ -1151,6 +1163,22 @@ _mfm:
|
||||||
plainDescription: "Desactiva los efectos de todo el contenido MFM con este efecto
|
plainDescription: "Desactiva los efectos de todo el contenido MFM con este efecto
|
||||||
MFM."
|
MFM."
|
||||||
position: Posición
|
position: Posición
|
||||||
|
warn: MFM podría contener movimientos rápidos o animaciones destellantes
|
||||||
|
advancedDescription: Si está desactivado, solo permitir markup básico, excepto cuando
|
||||||
|
un MFM animado se reproduce
|
||||||
|
scale: Escalar
|
||||||
|
foreground: Color en primer plano
|
||||||
|
scaleDescription: Ajustar el contenido según un valor especificado.
|
||||||
|
stop: Detener MFM
|
||||||
|
crop: Recortar
|
||||||
|
cropDescription: Recortar contenido.
|
||||||
|
backgroundDescription: Cambiar el color de fondo del texto.
|
||||||
|
alwaysPlay: Siempre reproducir todos los MFM animados
|
||||||
|
fade: Fundido
|
||||||
|
advanced: MFM avanzado
|
||||||
|
play: Reproducir MFM
|
||||||
|
foregroundDescription: Cambiar el color en primer plano del texto.
|
||||||
|
background: Color de fondo
|
||||||
_instanceTicker:
|
_instanceTicker:
|
||||||
none: "No mostrar"
|
none: "No mostrar"
|
||||||
remote: "Mostrar a usuarios remotos"
|
remote: "Mostrar a usuarios remotos"
|
||||||
|
@ -1169,7 +1197,7 @@ _channel:
|
||||||
owned: "Dueño"
|
owned: "Dueño"
|
||||||
following: "Siguiendo"
|
following: "Siguiendo"
|
||||||
usersCount: "{n} participantes"
|
usersCount: "{n} participantes"
|
||||||
notesCount: "{n} notas"
|
notesCount: "{n} publicaciones"
|
||||||
nameOnly: Nombre solamente
|
nameOnly: Nombre solamente
|
||||||
nameAndDescription: Nombre y descripción
|
nameAndDescription: Nombre y descripción
|
||||||
_menuDisplay:
|
_menuDisplay:
|
||||||
|
@ -1183,18 +1211,20 @@ _wordMute:
|
||||||
con lineas nuevas indica una declaracion Or。"
|
con lineas nuevas indica una declaracion Or。"
|
||||||
muteWordsDescription2: "Encerrar las palabras clave entre numerales para usar expresiones
|
muteWordsDescription2: "Encerrar las palabras clave entre numerales para usar expresiones
|
||||||
regulares"
|
regulares"
|
||||||
softDescription: "Ocultar en la linea de tiempo las notas que cumplen las condiciones"
|
softDescription: "Ocultar en la linea de tiempo las publicaciones que cumplen las
|
||||||
hardDescription: "Evitar que se agreguen a la linea de tiempo las notas que cumplen
|
condiciones"
|
||||||
las condiciones. Las notas no agregadas seguirán quitadas aunque cambien las condiciones."
|
hardDescription: "Evitar que se agreguen a la linea de tiempo las publicaciones
|
||||||
|
que cumplen las condiciones, estas no serán agregadas a la linea de tiempo incluso
|
||||||
|
si cambian las condiciones."
|
||||||
soft: "Suave"
|
soft: "Suave"
|
||||||
hard: "Duro"
|
hard: "Duro"
|
||||||
mutedNotes: "Notas silenciadas"
|
mutedNotes: "Publicaciones silenciadas"
|
||||||
_instanceMute:
|
_instanceMute:
|
||||||
instanceMuteDescription: "Silencia todas las notas y reposts de la instancias seleccionadas,
|
instanceMuteDescription: "Silencia todas las publicaciones e impusos de los servidores
|
||||||
incluyendo respuestas a los usuarios de las mismas"
|
seleccionados, incluyendo respuestas a los usuarios de las mismas."
|
||||||
instanceMuteDescription2: "Separar por líneas"
|
instanceMuteDescription2: "Separar por líneas"
|
||||||
title: "Oculta las notas de las instancias listadas."
|
title: "Oculta las publicaciones de los servidores listados."
|
||||||
heading: "Instancias a silenciar"
|
heading: "Servidores a silenciar"
|
||||||
_theme:
|
_theme:
|
||||||
explore: "Explorar temas"
|
explore: "Explorar temas"
|
||||||
install: "Instalar tema"
|
install: "Instalar tema"
|
||||||
|
@ -1243,7 +1273,7 @@ _theme:
|
||||||
hashtag: "Hashtag"
|
hashtag: "Hashtag"
|
||||||
mention: "Menciones"
|
mention: "Menciones"
|
||||||
mentionMe: "Menciones (yo)"
|
mentionMe: "Menciones (yo)"
|
||||||
renote: "Renotar"
|
renote: "Impulsar"
|
||||||
modalBg: "Fondo modal"
|
modalBg: "Fondo modal"
|
||||||
divider: "Divisor"
|
divider: "Divisor"
|
||||||
scrollbarHandle: "Cuadro de la barra de desplazamiento"
|
scrollbarHandle: "Cuadro de la barra de desplazamiento"
|
||||||
|
@ -1270,23 +1300,23 @@ _theme:
|
||||||
accentLighten: "Acento (claro)"
|
accentLighten: "Acento (claro)"
|
||||||
fgHighlighted: "Texto resaltado"
|
fgHighlighted: "Texto resaltado"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "Notas"
|
note: "Nueva publicación"
|
||||||
noteMy: "Nota (a mí mismo)"
|
noteMy: "Nota (a mí mismo)"
|
||||||
notification: "Notificaciones"
|
notification: "Notificaciones"
|
||||||
chat: "Chat"
|
chat: "Chat"
|
||||||
chatBg: "Chat (Fondo)"
|
chatBg: "Chat (Fondo)"
|
||||||
antenna: "Antena receptora"
|
antenna: "Antenas"
|
||||||
channel: "Notificaciones del canal"
|
channel: "Notificaciones del canal"
|
||||||
_ago:
|
_ago:
|
||||||
future: "Futuro"
|
future: "Futuro"
|
||||||
justNow: "Recién ahora"
|
justNow: "Recién ahora"
|
||||||
secondsAgo: "Hace {n} segundos"
|
secondsAgo: "Hace {n} segundo(s)"
|
||||||
minutesAgo: "Hace {n} minutos"
|
minutesAgo: "Hace {n} minuto(s)"
|
||||||
hoursAgo: "Hace {n} horas"
|
hoursAgo: "Hace {n} hora(s)"
|
||||||
daysAgo: "Hace {n} días"
|
daysAgo: "Hace {n} día(s)"
|
||||||
weeksAgo: "Hace {n} semanas"
|
weeksAgo: "Hace {n} semana(s)"
|
||||||
monthsAgo: "Hace {n} meses"
|
monthsAgo: "Hace {n} mes(es)"
|
||||||
yearsAgo: "Hace {n} años"
|
yearsAgo: "Hace {n} año(s)"
|
||||||
_time:
|
_time:
|
||||||
second: "Segundos"
|
second: "Segundos"
|
||||||
minute: "Minutos"
|
minute: "Minutos"
|
||||||
|
@ -1298,16 +1328,16 @@ _tutorial:
|
||||||
step1_2: "Vamos a configurarte. ¡Estarás listo y funcionando en poco tiempo!"
|
step1_2: "Vamos a configurarte. ¡Estarás listo y funcionando en poco tiempo!"
|
||||||
step2_1: "En primer lugar, rellena tu perfil"
|
step2_1: "En primer lugar, rellena tu perfil"
|
||||||
step2_2: "Proporcionar algo de información sobre quién eres hará que sea más fácil
|
step2_2: "Proporcionar algo de información sobre quién eres hará que sea más fácil
|
||||||
para los demás saber si quieren ver tus notas o seguirte."
|
para los demás saber si quieren ver tus publicaciones o seguirte."
|
||||||
step3_1: "¡Ahora es el momento de seguir a algunas personas!"
|
step3_1: "¡Ahora es el momento de seguir a algunas personas!"
|
||||||
step3_2: "Tu página de inicio y tus líneas de tiempo sociales se basan en quién
|
step3_2: "Tu página de inicio y tus líneas de tiempo sociales se basan en quién
|
||||||
sigues, así que intenta seguir un par de cuentas para empezar.\nHaz clic en el
|
sigues, así que intenta seguir un par de cuentas para empezar.\nHaz clic en el
|
||||||
círculo más en la parte superior derecha de un perfil para seguirlos."
|
círculo más en la parte superior derecha de un perfil para seguirlos."
|
||||||
step4_1: "Vamos a salir a la calle"
|
step4_1: "Vamos a salir a la calle"
|
||||||
step4_2: "Para tu primer post, a algunas personas les gusta hacer un post de {introduction}
|
step4_2: "Para tu primer publicación, a algunas personas les gusta escribir una
|
||||||
o un simple \"¡Hola mundo!\""
|
{introduction} o un simple \"¡Hola mundo!\""
|
||||||
step5_1: "¡Líneas de tiempo, líneas de tiempo por todas partes!"
|
step5_1: "¡Líneas de tiempo, líneas de tiempo por todas partes!"
|
||||||
step5_2: "Su instancia tiene {timelines} diferentes líneas de tiempo habilitadas"
|
step5_2: "Tu servidor tiene {timelines} diferentes líneas de tiempo habilitadas."
|
||||||
step5_3: "La línea de tiempo Inicio {icon} es donde puedes ver las publicaciones
|
step5_3: "La línea de tiempo Inicio {icon} es donde puedes ver las publicaciones
|
||||||
de tus seguidores."
|
de tus seguidores."
|
||||||
step5_4: "La línea de tiempo Local {icon} es donde puedes ver las publicaciones
|
step5_4: "La línea de tiempo Local {icon} es donde puedes ver las publicaciones
|
||||||
|
@ -1475,7 +1505,8 @@ _profile:
|
||||||
youCanIncludeHashtags: "Puedes añadir hashtags"
|
youCanIncludeHashtags: "Puedes añadir hashtags"
|
||||||
metadata: "información adicional"
|
metadata: "información adicional"
|
||||||
metadataEdit: "Editar información adicional"
|
metadataEdit: "Editar información adicional"
|
||||||
metadataDescription: "Muestra la información adicional en el perfil. ¡Puede agregar una etiqueta {a} o una etiqueta {l} con {rel} para verificar el enlace en su perfil!"
|
metadataDescription: "Muestra la información adicional en el perfil. ¡Puede agregar
|
||||||
|
una etiqueta {a} o una etiqueta {l} con {rel} para verificar el enlace en su perfil!"
|
||||||
metadataLabel: "Etiqueta"
|
metadataLabel: "Etiqueta"
|
||||||
metadataContent: "Contenido"
|
metadataContent: "Contenido"
|
||||||
changeAvatar: "Cambiar avatar"
|
changeAvatar: "Cambiar avatar"
|
||||||
|
@ -1887,7 +1918,7 @@ renoteUnmute: Dejar de silenciar impulsos
|
||||||
flagSpeakAsCat: Habla como un gato
|
flagSpeakAsCat: Habla como un gato
|
||||||
selectInstance: Selecciona un servidor
|
selectInstance: Selecciona un servidor
|
||||||
flagSpeakAsCatDescription: Tu publicación se "nyanified" cuando esté en modo gato
|
flagSpeakAsCatDescription: Tu publicación se "nyanified" cuando esté en modo gato
|
||||||
allowedInstances: Instancias en la lista blanca
|
allowedInstances: Servidores autorizados
|
||||||
breakFollowConfirm: ¿Estás seguro de que quieres eliminar el seguidor?
|
breakFollowConfirm: ¿Estás seguro de que quieres eliminar el seguidor?
|
||||||
subscribePushNotification: Habilitar notificaciones
|
subscribePushNotification: Habilitar notificaciones
|
||||||
unsubscribePushNotification: Desactivar notificaciones
|
unsubscribePushNotification: Desactivar notificaciones
|
||||||
|
@ -1904,12 +1935,12 @@ hiddenTags: Etiquetas Ocultas
|
||||||
noInstances: No hay servidores
|
noInstances: No hay servidores
|
||||||
accountMoved: 'Usuario ha movido a una cuenta nueva:'
|
accountMoved: 'Usuario ha movido a una cuenta nueva:'
|
||||||
caption: Auto Subtítulos
|
caption: Auto Subtítulos
|
||||||
showAds: Mostrar Anuncios
|
showAds: Mostrar banners
|
||||||
enterSendsMessage: Presione "RETORNO" en los mensajes para enviar el mensaje (para
|
enterSendsMessage: Presione "RETORNO" en los mensajes para enviar el mensaje (para
|
||||||
apagarlo es Ctrl + RETORNO)
|
apagarlo es Ctrl + RETORNO)
|
||||||
recommendedInstances: Instancias Recomendadas
|
recommendedInstances: Instancias Recomendadas
|
||||||
instanceSecurity: Seguridad de la instancia
|
instanceSecurity: Seguridad del servidor
|
||||||
seperateRenoteQuote: Separar impulsados y Citar botones
|
seperateRenoteQuote: Separar botones de Impulsar y Citar
|
||||||
_messaging:
|
_messaging:
|
||||||
groups: Grupos
|
groups: Grupos
|
||||||
dms: Privado
|
dms: Privado
|
||||||
|
@ -1941,3 +1972,53 @@ hiddenTagsDescription: 'Escriba los hashtags (sin el #) que desea ocultar de las
|
||||||
jumpToPrevious: Ver anterior
|
jumpToPrevious: Ver anterior
|
||||||
enableEmojiReactions: Habilitar reacciones de emoji
|
enableEmojiReactions: Habilitar reacciones de emoji
|
||||||
cw: Aviso de contenido
|
cw: Aviso de contenido
|
||||||
|
sendPushNotificationReadMessage: Eliminar notificaciones una vez que la notificación
|
||||||
|
o mensaje ha sido leído
|
||||||
|
sendPushNotificationReadMessageCaption: Una notificación con el texto "{emptyPushNotificationMessage}"
|
||||||
|
será mostrada por un breve período. Esto podría aumentar el uso de batería de tu
|
||||||
|
dispositivo.
|
||||||
|
enableServerMachineStats: Permitir estadísticas del hardware del servidor
|
||||||
|
customMOTD: Mensaje del día personalizado (mensajes de la pantalla de presentación)
|
||||||
|
antennasDesc: "Las Antennas muestran nuevas publicaciones que conciden con los criterios
|
||||||
|
que estableciste.\nPueden ser accedidas desde la sección de Lineas de tiempo."
|
||||||
|
antennaInstancesDescription: Escribe un servidor por cada linea
|
||||||
|
expandOnNoteClickDesc: Si está desactivado, puedes abrir publicaciones usando el menú
|
||||||
|
del botón derecho del ratón o presionando sobre la fecha.
|
||||||
|
channelFederationWarn: Los Canales aún no federan con otras instancias
|
||||||
|
clipsDesc: Los clips como marcadores categorizados que pueden ser compartidos. Puedes
|
||||||
|
crear clips desde el menú de publicaciones.
|
||||||
|
verifiedLink: Vínculo verificado
|
||||||
|
cannotUploadBecauseExceedsFileSizeLimit: Este archivo no pudo ser cargado porque excede
|
||||||
|
el tamaño máximo permitido.
|
||||||
|
accessibility: Accesibilidad
|
||||||
|
_filters:
|
||||||
|
fromUser: Del usuario
|
||||||
|
fromDomain: Desde el dominio
|
||||||
|
notesAfter: Publicaciones posteriores
|
||||||
|
userSaysSomethingReasonReply: '{name} respondió a una publicación que contiene {reason}'
|
||||||
|
userSaysSomethingReasonQuote: '{name} citó una publicación que contiene {reason}'
|
||||||
|
privateModeInfo: Al activar, solo servidores autorizados podrán federar con tu servidor.
|
||||||
|
Todas las publicaiones estáran ocultas del público.
|
||||||
|
customMOTDDescription: Mensajes del día personalizados (MOTD) de la pantalla de presentación,
|
||||||
|
separados cada salto de linea. Para ser mostrados aleatoriamente cada vez que un
|
||||||
|
usuario carga/recarga una página.
|
||||||
|
customSplashIcons: Icono personalizado de la pantalla de presentación (url)
|
||||||
|
donationLink: Vinculo a página de donación
|
||||||
|
delete2fa: Desactivar autentificación en dos pasos
|
||||||
|
delete2faConfirm: Esto eliminara irreversiblemente la autentificación en dos pasos
|
||||||
|
de esta cuenta. ¿Quieres continuar?
|
||||||
|
allowedInstancesDescription: Host de los servidores autorizados para federar, cada
|
||||||
|
uno separado por una nueva linea (solo aplica en modo pivado).
|
||||||
|
adminCustomCssWarn: Está configuración solo debería ser utilizado si sabes lo que
|
||||||
|
hace. Ingresar valores erroneos podría causar que TODOS los clientes dejaran de
|
||||||
|
funcionar normalmente. Porfavor asegurate que tus CSS funcionan adecuadamente al
|
||||||
|
probar los en tus configuraciones de usuario.
|
||||||
|
image: Imagen
|
||||||
|
showPopup: Notificar a los usuarios con una ventana emergente
|
||||||
|
showWithSparkles: Mostrar con destellos
|
||||||
|
youHaveUnreadAnnouncements: Tienes anuncios sin leer
|
||||||
|
neverShow: No mostrar nuevamente
|
||||||
|
remindMeLater: Recordar nuevamente
|
||||||
|
removeQuote: Eliminar cita
|
||||||
|
removeRecipient: Eliminar destinatario
|
||||||
|
removeMember: Eliminar miembro
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
_lang_: "Français"
|
_lang_: "Français"
|
||||||
headlineFirefish: "Réseau relié par des notes"
|
headlineFirefish: "Une plateforme de réseaux sociaux décentralisé, open source qui
|
||||||
|
est gratuit pour toujours ! 🚀"
|
||||||
introFirefish: "Bienvenue ! Firefish est une plateforme de réseau social décentralisé
|
introFirefish: "Bienvenue ! Firefish est une plateforme de réseau social décentralisé
|
||||||
et open source qui est gratuite pour toujours ! 🚀"
|
et open source qui est gratuite pour toujours ! 🚀"
|
||||||
monthAndDay: "{day}/{month}"
|
monthAndDay: "{day}/{month}"
|
||||||
|
@ -13,8 +14,8 @@ ok: "OK"
|
||||||
gotIt: "J’ai compris !"
|
gotIt: "J’ai compris !"
|
||||||
cancel: "Annuler"
|
cancel: "Annuler"
|
||||||
enterUsername: "Entrer un nom d’utilisateur·rice"
|
enterUsername: "Entrer un nom d’utilisateur·rice"
|
||||||
renotedBy: "Renoté par {user}"
|
renotedBy: "Boosté par {user}"
|
||||||
noNotes: "Aucune note"
|
noNotes: "Aucun post"
|
||||||
noNotifications: "Aucune notification"
|
noNotifications: "Aucune notification"
|
||||||
instance: "Serveur"
|
instance: "Serveur"
|
||||||
settings: "Paramètres"
|
settings: "Paramètres"
|
||||||
|
@ -45,8 +46,8 @@ copyContent: "Copier le contenu"
|
||||||
copyLink: "Copier le lien"
|
copyLink: "Copier le lien"
|
||||||
delete: "Supprimer"
|
delete: "Supprimer"
|
||||||
deleteAndEdit: "Supprimer et réécrire"
|
deleteAndEdit: "Supprimer et réécrire"
|
||||||
deleteAndEditConfirm: "Êtes-vous sûr·e de vouloir supprimer cette note et la reformuler
|
deleteAndEditConfirm: "Êtes-vous sûr·e de vouloir supprimer ce post et le reformuler
|
||||||
? Vous perdrez toutes les réactions, renotes et réponses y afférentes."
|
? Vous perdrez toutes les réactions, boosts et réponses liées."
|
||||||
addToList: "Ajouter à une liste"
|
addToList: "Ajouter à une liste"
|
||||||
sendMessage: "Envoyer un message"
|
sendMessage: "Envoyer un message"
|
||||||
copyUsername: "Copier le nom d’utilisateur·rice"
|
copyUsername: "Copier le nom d’utilisateur·rice"
|
||||||
|
@ -60,14 +61,14 @@ receiveFollowRequest: "Demande d’abonnement reçue"
|
||||||
followRequestAccepted: "La demande d’abonnement a été acceptée"
|
followRequestAccepted: "La demande d’abonnement a été acceptée"
|
||||||
mention: "Mentionner"
|
mention: "Mentionner"
|
||||||
mentions: "Mentions"
|
mentions: "Mentions"
|
||||||
directNotes: "Notes directes"
|
directNotes: "Messages directs"
|
||||||
importAndExport: "Import et export"
|
importAndExport: "Import et export"
|
||||||
import: "Importer"
|
import: "Importer"
|
||||||
export: "Exporter"
|
export: "Exporter"
|
||||||
files: "Fichiers"
|
files: "Fichiers"
|
||||||
download: "Télécharger"
|
download: "Télécharger"
|
||||||
driveFileDeleteConfirm: "Êtes-vous sûr·e de vouloir supprimer le fichier \"{name}\"\
|
driveFileDeleteConfirm: "Êtes-vous sûr·e de vouloir supprimer le fichier \"{name}\"\
|
||||||
\ ? Il sera retiré de toutes ses notes liées."
|
\ ? Il sera retiré de tous ses posts liées."
|
||||||
unfollowConfirm: "Désirez-vous vous désabonner de {name} ?"
|
unfollowConfirm: "Désirez-vous vous désabonner de {name} ?"
|
||||||
exportRequested: "Vous avez demandé une exportation. L’opération pourrait prendre
|
exportRequested: "Vous avez demandé une exportation. L’opération pourrait prendre
|
||||||
un peu de temps. Une terminée, le fichier résultant sera ajouté au Drive."
|
un peu de temps. Une terminée, le fichier résultant sera ajouté au Drive."
|
||||||
|
@ -94,18 +95,18 @@ youShouldUpgradeClient: "Si la page ne s'affiche pas correctement, rechargez-la
|
||||||
enterListName: "Nom de la liste"
|
enterListName: "Nom de la liste"
|
||||||
privacy: "Confidentialité"
|
privacy: "Confidentialité"
|
||||||
makeFollowManuallyApprove: "Accepter manuellement les demandes d’abonnement"
|
makeFollowManuallyApprove: "Accepter manuellement les demandes d’abonnement"
|
||||||
defaultNoteVisibility: "Visibilité des notes par défaut"
|
defaultNoteVisibility: "Visibilité des posts par défaut"
|
||||||
follow: "S’abonner"
|
follow: "S’abonner"
|
||||||
followRequest: "Demande d’abonnement"
|
followRequest: "Demande d’abonnement"
|
||||||
followRequests: "Demandes d’abonnement"
|
followRequests: "Demandes d’abonnement"
|
||||||
unfollow: "Se désabonner"
|
unfollow: "Se désabonner"
|
||||||
followRequestPending: "Demande d'abonnement en attente de confirmation"
|
followRequestPending: "Demande d'abonnement en attente de confirmation"
|
||||||
enterEmoji: "Insérer un émoji"
|
enterEmoji: "Insérer un émoji"
|
||||||
renote: "Renoter"
|
renote: "Booster"
|
||||||
unrenote: "Annuler la Renote"
|
unrenote: "Annuler le boost"
|
||||||
renoted: "Renoté."
|
renoted: "Boosté."
|
||||||
cantRenote: "Ce message ne peut pas être renoté."
|
cantRenote: "Ce message ne peut pas être boosté."
|
||||||
cantReRenote: "Impossible de renoter une Renote."
|
cantReRenote: "Impossible de partager ce boost."
|
||||||
quote: "Citer"
|
quote: "Citer"
|
||||||
pinnedNote: "Note épinglée"
|
pinnedNote: "Note épinglée"
|
||||||
pinned: "Épingler sur le profil"
|
pinned: "Épingler sur le profil"
|
||||||
|
@ -117,9 +118,9 @@ reaction: "Réactions"
|
||||||
reactionSetting: "Réactions à afficher dans le sélecteur de réactions"
|
reactionSetting: "Réactions à afficher dans le sélecteur de réactions"
|
||||||
reactionSettingDescription2: "Déplacer pour réorganiser, cliquer pour effacer, utiliser
|
reactionSettingDescription2: "Déplacer pour réorganiser, cliquer pour effacer, utiliser
|
||||||
« + » pour ajouter."
|
« + » pour ajouter."
|
||||||
rememberNoteVisibility: "Activer l'option \" se souvenir de la visibilité des notes
|
rememberNoteVisibility: "Activer l'option \" se souvenir de la visibilité des posts
|
||||||
\" vous permet de réutiliser automatiquement la visibilité utilisée lors de la publication
|
\" vous permet de réutiliser automatiquement la visibilité utilisée lors de la publication
|
||||||
de votre note précédente."
|
de votre post précédent."
|
||||||
attachCancel: "Supprimer le fichier attaché"
|
attachCancel: "Supprimer le fichier attaché"
|
||||||
markAsSensitive: "Marquer comme sensible"
|
markAsSensitive: "Marquer comme sensible"
|
||||||
unmarkAsSensitive: "Supprimer le marquage comme sensible"
|
unmarkAsSensitive: "Supprimer le marquage comme sensible"
|
||||||
|
@ -175,9 +176,9 @@ proxyAccount: "Compte proxy"
|
||||||
proxyAccountDescription: "Un compte proxy se comporte, dans certaines conditions,
|
proxyAccountDescription: "Un compte proxy se comporte, dans certaines conditions,
|
||||||
comme un·e abonné·e distant·e pour les utilisateur·rice·s d'autres serveurs. Par
|
comme un·e abonné·e distant·e pour les utilisateur·rice·s d'autres serveurs. Par
|
||||||
exemple, quand un·e utilisateur·rice local ajoute un·e utilisateur·rice distant·e
|
exemple, quand un·e utilisateur·rice local ajoute un·e utilisateur·rice distant·e
|
||||||
à une liste, ses notes ne seront pas visibles sur le serveur si personne ne suit
|
à une liste, ses posts ne seront pas visibles sur le serveur si personne ne suit
|
||||||
cet·te utilisateur·rice. Le compte proxy va donc suivre cet·te utilisateur·rice
|
cet·te utilisateur·rice. Le compte proxy va donc suivre cet·te utilisateur·rice
|
||||||
pour que ses notes soient acheminées."
|
pour que ses posts soient acheminées."
|
||||||
host: "Serveur distant"
|
host: "Serveur distant"
|
||||||
selectUser: "Sélectionner un·e utilisateur·rice"
|
selectUser: "Sélectionner un·e utilisateur·rice"
|
||||||
recipient: "Destinataire"
|
recipient: "Destinataire"
|
||||||
|
@ -207,7 +208,7 @@ instanceInfo: "Informations du serveur"
|
||||||
statistics: "Statistiques"
|
statistics: "Statistiques"
|
||||||
clearQueue: "Vider la file d’attente"
|
clearQueue: "Vider la file d’attente"
|
||||||
clearQueueConfirmTitle: "Êtes-vous sûr·e de vouloir vider la file d’attente ?"
|
clearQueueConfirmTitle: "Êtes-vous sûr·e de vouloir vider la file d’attente ?"
|
||||||
clearQueueConfirmText: "Les notes non distribuées ne seront pas délivrées. Normalement,
|
clearQueueConfirmText: "Les posts non distribués ne seront pas délivrés. Normalement,
|
||||||
vous n'avez pas besoin d'effectuer cette opération."
|
vous n'avez pas besoin d'effectuer cette opération."
|
||||||
clearCachedFiles: "Vider le cache"
|
clearCachedFiles: "Vider le cache"
|
||||||
clearCachedFilesConfirm: "Êtes-vous sûr·e de vouloir vider tout le cache de fichiers
|
clearCachedFilesConfirm: "Êtes-vous sûr·e de vouloir vider tout le cache de fichiers
|
||||||
|
@ -220,8 +221,8 @@ mutedUsers: "Utilisateur·rice·s en sourdine"
|
||||||
blockedUsers: "Utilisateur·rice·s bloqué·e·s"
|
blockedUsers: "Utilisateur·rice·s bloqué·e·s"
|
||||||
noUsers: "Il n’y a pas d’utilisateur·rice·s"
|
noUsers: "Il n’y a pas d’utilisateur·rice·s"
|
||||||
editProfile: "Modifier votre profil"
|
editProfile: "Modifier votre profil"
|
||||||
noteDeleteConfirm: "Êtes-vous sûr·e de vouloir supprimer cette note ?"
|
noteDeleteConfirm: "Êtes-vous sûr·e de vouloir supprimer ce post ?"
|
||||||
pinLimitExceeded: "Vous ne pouvez pas épingler plus de notes"
|
pinLimitExceeded: "Vous ne pouvez pas épingler plus de posts"
|
||||||
intro: "L’installation de Firefish est terminée ! Veuillez créer un compte administrateur."
|
intro: "L’installation de Firefish est terminée ! Veuillez créer un compte administrateur."
|
||||||
done: "Terminé"
|
done: "Terminé"
|
||||||
processing: "Traitement en cours"
|
processing: "Traitement en cours"
|
||||||
|
@ -366,7 +367,7 @@ pinnedPages: "Pages épinglées"
|
||||||
pinnedPagesDescription: "Inscrivez le chemin des Pages que vous souhaitez épingler
|
pinnedPagesDescription: "Inscrivez le chemin des Pages que vous souhaitez épingler
|
||||||
en haut de la page du serveur. Séparez les d'un retour à la ligne."
|
en haut de la page du serveur. Séparez les d'un retour à la ligne."
|
||||||
pinnedClipId: "Identifiant du clip épinglé"
|
pinnedClipId: "Identifiant du clip épinglé"
|
||||||
pinnedNotes: "Note épinglée"
|
pinnedNotes: "Posts épinglée"
|
||||||
hcaptcha: "hCaptcha"
|
hcaptcha: "hCaptcha"
|
||||||
enableHcaptcha: "Activer hCaptcha"
|
enableHcaptcha: "Activer hCaptcha"
|
||||||
hcaptchaSiteKey: "Clé du site"
|
hcaptchaSiteKey: "Clé du site"
|
||||||
|
@ -386,14 +387,14 @@ antennaKeywords: "Mots clés à recevoir"
|
||||||
antennaExcludeKeywords: "Mots clés à exclure"
|
antennaExcludeKeywords: "Mots clés à exclure"
|
||||||
antennaKeywordsDescription: "Séparer avec des espaces pour la condition AND. Séparer
|
antennaKeywordsDescription: "Séparer avec des espaces pour la condition AND. Séparer
|
||||||
avec un saut de ligne pour une condition OR."
|
avec un saut de ligne pour une condition OR."
|
||||||
notifyAntenna: "Je souhaite recevoir les notifications des nouvelles notes"
|
notifyAntenna: "Je souhaite recevoir les notifications des nouveaux posts"
|
||||||
withFileAntenna: "Notes ayant des attachements uniquement"
|
withFileAntenna: "Posts ayant des attachements uniquement"
|
||||||
enableServiceworker: "Activer ServiceWorker"
|
enableServiceworker: "Activer ServiceWorker"
|
||||||
antennaUsersDescription: "Saisissez un seul nom d’utilisateur·rice par ligne"
|
antennaUsersDescription: "Saisissez un seul nom d’utilisateur·rice par ligne"
|
||||||
caseSensitive: "Sensible à la casse"
|
caseSensitive: "Sensible à la casse"
|
||||||
withReplies: "Inclure les réponses"
|
withReplies: "Inclure les réponses"
|
||||||
connectedTo: "Vous êtes connectés aux services suivants"
|
connectedTo: "Vous êtes connectés aux services suivants"
|
||||||
notesAndReplies: "Notes et Réponses"
|
notesAndReplies: "Posts et Réponses"
|
||||||
withFiles: "Avec fichiers joints"
|
withFiles: "Avec fichiers joints"
|
||||||
silence: "Mettre en sourdine"
|
silence: "Mettre en sourdine"
|
||||||
silenceConfirm: "Êtes-vous sûr·e de vouloir mettre l’utilisateur·rice en sourdine
|
silenceConfirm: "Êtes-vous sûr·e de vouloir mettre l’utilisateur·rice en sourdine
|
||||||
|
@ -431,7 +432,7 @@ notFoundDescription: "Aucune page ne correspond à l’URL spécifiée."
|
||||||
uploadFolder: "Emplacement de téléversement par défaut"
|
uploadFolder: "Emplacement de téléversement par défaut"
|
||||||
cacheClear: "Vider le cache"
|
cacheClear: "Vider le cache"
|
||||||
markAsReadAllNotifications: "Marquer toutes les notifications comme lues"
|
markAsReadAllNotifications: "Marquer toutes les notifications comme lues"
|
||||||
markAsReadAllUnreadNotes: "Marquer toutes les notes comme lues"
|
markAsReadAllUnreadNotes: "Marquer tous les posts comme lus"
|
||||||
markAsReadAllTalkMessages: "Marquer toutes les discussions comme lues"
|
markAsReadAllTalkMessages: "Marquer toutes les discussions comme lues"
|
||||||
help: "Aide"
|
help: "Aide"
|
||||||
inputMessageHere: "Écrivez votre message ici"
|
inputMessageHere: "Écrivez votre message ici"
|
||||||
|
@ -452,7 +453,7 @@ text: "Texte"
|
||||||
enable: "Activer"
|
enable: "Activer"
|
||||||
next: "Suivant"
|
next: "Suivant"
|
||||||
retype: "Confirmation"
|
retype: "Confirmation"
|
||||||
noteOf: "Notes de {user}"
|
noteOf: "Posts de {user}"
|
||||||
inviteToGroup: "Inviter dans un groupe"
|
inviteToGroup: "Inviter dans un groupe"
|
||||||
quoteAttached: "Avec citation"
|
quoteAttached: "Avec citation"
|
||||||
quoteQuestion: "Souhaitez-vous ajouter une citation ?"
|
quoteQuestion: "Souhaitez-vous ajouter une citation ?"
|
||||||
|
@ -512,8 +513,8 @@ accountSettings: "Paramètres du compte"
|
||||||
promotion: "Promu"
|
promotion: "Promu"
|
||||||
promote: "Promouvoir"
|
promote: "Promouvoir"
|
||||||
numberOfDays: "Nombre de jours"
|
numberOfDays: "Nombre de jours"
|
||||||
hideThisNote: "Masquer cette note"
|
hideThisNote: "Masquer ce post"
|
||||||
showFeaturedNotesInTimeline: "Afficher les notes des Tendances dans le fil d'actualité"
|
showFeaturedNotesInTimeline: "Afficher les posts des Tendances dans le fil d'actualité"
|
||||||
objectStorage: "Stockage d'objets"
|
objectStorage: "Stockage d'objets"
|
||||||
useObjectStorage: "Utiliser le stockage d'objets"
|
useObjectStorage: "Utiliser le stockage d'objets"
|
||||||
objectStorageBaseUrl: "Base URL"
|
objectStorageBaseUrl: "Base URL"
|
||||||
|
@ -544,7 +545,7 @@ objectStorageSetPublicRead: "Régler sur « public » lors de l'envoi"
|
||||||
serverLogs: "Journal du serveur"
|
serverLogs: "Journal du serveur"
|
||||||
deleteAll: "Supprimer tout"
|
deleteAll: "Supprimer tout"
|
||||||
showFixedPostForm: "Afficher le formulaire de publication en haut du fil d'actualité"
|
showFixedPostForm: "Afficher le formulaire de publication en haut du fil d'actualité"
|
||||||
newNoteRecived: "Voir les nouvelles notes"
|
newNoteRecived: "Voir les nouveaux posts"
|
||||||
sounds: "Sons"
|
sounds: "Sons"
|
||||||
listen: "Écouter"
|
listen: "Écouter"
|
||||||
none: "Rien"
|
none: "Rien"
|
||||||
|
@ -594,8 +595,8 @@ addRelay: "Ajouter un relais"
|
||||||
inboxUrl: "Inbox URL"
|
inboxUrl: "Inbox URL"
|
||||||
addedRelays: "Relais ajoutés"
|
addedRelays: "Relais ajoutés"
|
||||||
serviceworkerInfo: "Devrait être activé pour les notifications push."
|
serviceworkerInfo: "Devrait être activé pour les notifications push."
|
||||||
deletedNote: "Note supprimée"
|
deletedNote: "Post supprimé"
|
||||||
invisibleNote: "Note invisible"
|
invisibleNote: "Post invisible"
|
||||||
enableInfiniteScroll: "Activer le défilement infini"
|
enableInfiniteScroll: "Activer le défilement infini"
|
||||||
visibility: "Visibilité"
|
visibility: "Visibilité"
|
||||||
poll: "Sondage"
|
poll: "Sondage"
|
||||||
|
@ -680,7 +681,7 @@ abuseReports: "Signalements"
|
||||||
reportAbuse: "Signaler"
|
reportAbuse: "Signaler"
|
||||||
reportAbuseOf: "Signaler {name}"
|
reportAbuseOf: "Signaler {name}"
|
||||||
fillAbuseReportDescription: "Veuillez expliquer les raisons du signalement. S'il s'agit
|
fillAbuseReportDescription: "Veuillez expliquer les raisons du signalement. S'il s'agit
|
||||||
d'une note particulière, veuillez inclure le lien."
|
d'un post particulier, veuillez inclure le lien."
|
||||||
abuseReported: "Le rapport est envoyé. Merci."
|
abuseReported: "Le rapport est envoyé. Merci."
|
||||||
reporter: "Signalé par"
|
reporter: "Signalé par"
|
||||||
reporteeOrigin: "Origine du signalement"
|
reporteeOrigin: "Origine du signalement"
|
||||||
|
@ -693,7 +694,7 @@ openInSideView: "Ouvrir en vue latérale"
|
||||||
defaultNavigationBehaviour: "Navigation par défaut"
|
defaultNavigationBehaviour: "Navigation par défaut"
|
||||||
editTheseSettingsMayBreakAccount: "La modification de ces paramètres peut endommager
|
editTheseSettingsMayBreakAccount: "La modification de ces paramètres peut endommager
|
||||||
votre compte."
|
votre compte."
|
||||||
instanceTicker: "Nom du serveur d'origine des notes"
|
instanceTicker: "Nom du serveur d'origine des posts"
|
||||||
waitingFor: "En attente de {x}"
|
waitingFor: "En attente de {x}"
|
||||||
random: "Aléatoire"
|
random: "Aléatoire"
|
||||||
system: "Système"
|
system: "Système"
|
||||||
|
@ -708,11 +709,11 @@ i18nInfo: "Firefish est traduit dans différentes langues par des bénévoles. V
|
||||||
contribuer à {link}."
|
contribuer à {link}."
|
||||||
manageAccessTokens: "Gérer les jetons d'accès"
|
manageAccessTokens: "Gérer les jetons d'accès"
|
||||||
accountInfo: " Informations du compte "
|
accountInfo: " Informations du compte "
|
||||||
notesCount: "Nombre de notes"
|
notesCount: "Nombre de posts"
|
||||||
repliesCount: "Nombre de réponses envoyées"
|
repliesCount: "Nombre de réponses envoyées"
|
||||||
renotesCount: "Nombre de notes que vous avez renotées"
|
renotesCount: "Nombre de boosts que vous avez envoyé"
|
||||||
repliedCount: "Nombre de réponses reçues"
|
repliedCount: "Nombre de réponses reçues"
|
||||||
renotedCount: "Nombre de vos notes renotées"
|
renotedCount: "Nombre de vos posts boostés"
|
||||||
followingCount: "Nombre de comptes suivis"
|
followingCount: "Nombre de comptes suivis"
|
||||||
followersCount: "Nombre d'abonnés"
|
followersCount: "Nombre d'abonnés"
|
||||||
sentReactionsCount: "Nombre de réactions envoyées"
|
sentReactionsCount: "Nombre de réactions envoyées"
|
||||||
|
@ -725,9 +726,9 @@ driveFilesCount: "Nombre de fichiers dans le Drive"
|
||||||
driveUsage: "Utilisation du Drive"
|
driveUsage: "Utilisation du Drive"
|
||||||
noCrawle: "Refuser l'indexation par les robots"
|
noCrawle: "Refuser l'indexation par les robots"
|
||||||
noCrawleDescription: "Demandez aux moteurs de recherche de ne pas indexer votre page
|
noCrawleDescription: "Demandez aux moteurs de recherche de ne pas indexer votre page
|
||||||
de profil, vos notes, vos pages, etc."
|
de profil, vos posts, vos pages, etc."
|
||||||
lockedAccountInfo: "À moins que vous ne définissiez la visibilité de votre note sur
|
lockedAccountInfo: "À moins que vous ne définissiez la visibilité de votre post sur
|
||||||
\"Abonné-e-s\", vos notes sont visibles par tous, même si vous exigez que les demandes
|
\"Abonné-e-s\", vos posts sont visibles par tous, même si vous exigez que les demandes
|
||||||
d'abonnement soient approuvées manuellement."
|
d'abonnement soient approuvées manuellement."
|
||||||
alwaysMarkSensitive: "Marquer les médias comme contenu sensible par défaut"
|
alwaysMarkSensitive: "Marquer les médias comme contenu sensible par défaut"
|
||||||
loadRawImages: "Affichage complet des images jointes au lieu des vignettes"
|
loadRawImages: "Affichage complet des images jointes au lieu des vignettes"
|
||||||
|
@ -736,7 +737,7 @@ verificationEmailSent: "Un e-mail de vérification a été envoyé. Veuillez acc
|
||||||
lien pour compléter la vérification."
|
lien pour compléter la vérification."
|
||||||
notSet: "Non défini"
|
notSet: "Non défini"
|
||||||
emailVerified: "Votre adresse e-mail a été vérifiée."
|
emailVerified: "Votre adresse e-mail a été vérifiée."
|
||||||
noteFavoritesCount: "Nombre de notes dans les favoris"
|
noteFavoritesCount: "Nombre de posts dans les favoris"
|
||||||
pageLikesCount: "Nombre de pages aimées"
|
pageLikesCount: "Nombre de pages aimées"
|
||||||
pageLikedCount: "Nombre de vos pages aimées"
|
pageLikedCount: "Nombre de vos pages aimées"
|
||||||
contact: "Contact"
|
contact: "Contact"
|
||||||
|
@ -747,7 +748,7 @@ developer: "Développeur"
|
||||||
makeExplorable: "Rendre le compte visible sur la page \"Découvrir\"."
|
makeExplorable: "Rendre le compte visible sur la page \"Découvrir\"."
|
||||||
makeExplorableDescription: "Si vous désactivez cette option, votre compte n'apparaîtra
|
makeExplorableDescription: "Si vous désactivez cette option, votre compte n'apparaîtra
|
||||||
pas sur la page \"Découvrir\"."
|
pas sur la page \"Découvrir\"."
|
||||||
showGapBetweenNotesInTimeline: "Afficher un écart entre les notes du fil d’actualité"
|
showGapBetweenNotesInTimeline: "Afficher un écart entre les posts du fil d’actualité"
|
||||||
duplicate: "Duliquer"
|
duplicate: "Duliquer"
|
||||||
left: "Gauche"
|
left: "Gauche"
|
||||||
center: "Centrer"
|
center: "Centrer"
|
||||||
|
@ -760,7 +761,7 @@ showTitlebar: "Afficher la barre de titre"
|
||||||
clearCache: "Vider le cache"
|
clearCache: "Vider le cache"
|
||||||
onlineUsersCount: "{n} utilisateur(s) en ligne"
|
onlineUsersCount: "{n} utilisateur(s) en ligne"
|
||||||
nUsers: "{n} utilisateur·rice·s"
|
nUsers: "{n} utilisateur·rice·s"
|
||||||
nNotes: "{n} Notes"
|
nNotes: "{n} Posts"
|
||||||
sendErrorReports: "Envoyer les rapports d’erreur"
|
sendErrorReports: "Envoyer les rapports d’erreur"
|
||||||
sendErrorReportsDescription: "Si vous activez l'envoi des rapports d'erreur, vous
|
sendErrorReportsDescription: "Si vous activez l'envoi des rapports d'erreur, vous
|
||||||
contribuerez à améliorer la qualité de Firefish grâce au partage d'informations
|
contribuerez à améliorer la qualité de Firefish grâce au partage d'informations
|
||||||
|
@ -805,8 +806,8 @@ unlikeConfirm: "Êtes-vous sûr·e de ne plus vouloir aimer cette publication ?"
|
||||||
fullView: "Plein écran"
|
fullView: "Plein écran"
|
||||||
quitFullView: "Quitter le plein écran"
|
quitFullView: "Quitter le plein écran"
|
||||||
addDescription: "Ajouter une description"
|
addDescription: "Ajouter une description"
|
||||||
userPagePinTip: "Vous pouvez afficher des notes ici en sélectionnant l'option « Épingler
|
userPagePinTip: "Vous pouvez afficher des posts ici en sélectionnant l'option « Épingler
|
||||||
au profil » dans le menu de chaque note."
|
au profil » dans le menu de chaque post."
|
||||||
notSpecifiedMentionWarning: "Vous avez mentionné des utilisateur·rice·s qui ne font
|
notSpecifiedMentionWarning: "Vous avez mentionné des utilisateur·rice·s qui ne font
|
||||||
pas partie de la liste des destinataires"
|
pas partie de la liste des destinataires"
|
||||||
info: "Informations"
|
info: "Informations"
|
||||||
|
@ -838,7 +839,7 @@ postToGallery: "Publier dans la galerie"
|
||||||
gallery: "Galerie"
|
gallery: "Galerie"
|
||||||
recentPosts: "Les plus récentes"
|
recentPosts: "Les plus récentes"
|
||||||
popularPosts: "Les plus consultées"
|
popularPosts: "Les plus consultées"
|
||||||
shareWithNote: "Partager dans une note"
|
shareWithNote: "Partager dans un post"
|
||||||
ads: "Bannière communautaire"
|
ads: "Bannière communautaire"
|
||||||
expiration: "Échéance"
|
expiration: "Échéance"
|
||||||
memo: "Pense-bête"
|
memo: "Pense-bête"
|
||||||
|
@ -1121,7 +1122,7 @@ _channel:
|
||||||
owned: "Mes canaux"
|
owned: "Mes canaux"
|
||||||
following: "Abonné·e"
|
following: "Abonné·e"
|
||||||
usersCount: "{n} Participant·e·s"
|
usersCount: "{n} Participant·e·s"
|
||||||
notesCount: "{n} Notes"
|
notesCount: "{n} Posts"
|
||||||
nameAndDescription: Nom et description
|
nameAndDescription: Nom et description
|
||||||
nameOnly: Nom uniquement
|
nameOnly: Nom uniquement
|
||||||
_menuDisplay:
|
_menuDisplay:
|
||||||
|
@ -1135,20 +1136,20 @@ _wordMute:
|
||||||
un saut de ligne pour une condition OR."
|
un saut de ligne pour une condition OR."
|
||||||
muteWordsDescription2: "Pour utiliser des expressions régulières (regex), mettez
|
muteWordsDescription2: "Pour utiliser des expressions régulières (regex), mettez
|
||||||
les mots-clés entre barres obliques."
|
les mots-clés entre barres obliques."
|
||||||
softDescription: "Masquez de votre fil d’actualité les notes qui répondent aux conditions
|
softDescription: "Masquez de votre fil d’actualité les posts qui répondent aux conditions
|
||||||
définies."
|
définies."
|
||||||
hardDescription: "Empêche les notes qui remplissent les conditions définies d'être
|
hardDescription: "Empêche les posts qui remplissent les conditions définies d'être
|
||||||
ajoutées au fil d'actualité. Cette action est irréversible : si vous modifiez
|
ajoutées au fil d'actualité. Cette action est irréversible : si vous modifiez
|
||||||
ces conditions plus tard, les notes précédemment filtrées ne seront pas récupérées."
|
ces conditions plus tard, les posts précédemment filtrées ne seront pas récupérées."
|
||||||
soft: "Doux"
|
soft: "Doux"
|
||||||
hard: "Strict"
|
hard: "Strict"
|
||||||
mutedNotes: "Notes filtrées"
|
mutedNotes: "Posts filtrés"
|
||||||
_instanceMute:
|
_instanceMute:
|
||||||
instanceMuteDescription2: "Séparer avec des sauts de lignes"
|
instanceMuteDescription2: "Séparer avec des sauts de lignes"
|
||||||
title: "Masque les notes venant des serveurs listés."
|
title: "Masque les posts provenant des serveurs listés."
|
||||||
heading: "Serveurs à mettre en sourdine/masquer"
|
heading: "Serveurs à mettre en sourdine/masquer"
|
||||||
instanceMuteDescription: Ceci va masquer toute publication ou partage de serveurs
|
instanceMuteDescription: Ceci va masquer toute posts ou boosts de serveurs listés,
|
||||||
listés, incluant celles des personnes répondant à des personnes des serveurs masqués.
|
incluant celles des personnes répondant à des personnes des serveurs masqués.
|
||||||
_theme:
|
_theme:
|
||||||
explore: "Explorer les thèmes"
|
explore: "Explorer les thèmes"
|
||||||
install: "Installer un thème"
|
install: "Installer un thème"
|
||||||
|
@ -1199,7 +1200,7 @@ _theme:
|
||||||
hashtag: "Hashtags"
|
hashtag: "Hashtags"
|
||||||
mention: "Mentionner"
|
mention: "Mentionner"
|
||||||
mentionMe: "Mentions (Moi)"
|
mentionMe: "Mentions (Moi)"
|
||||||
renote: "Renoter"
|
renote: "Booster"
|
||||||
modalBg: "Modal d'arrière-plan"
|
modalBg: "Modal d'arrière-plan"
|
||||||
divider: "Séparateur"
|
divider: "Séparateur"
|
||||||
scrollbarHandle: "Poignée de la barre de navigation"
|
scrollbarHandle: "Poignée de la barre de navigation"
|
||||||
|
@ -1226,8 +1227,8 @@ _theme:
|
||||||
accentLighten: "Plus clair"
|
accentLighten: "Plus clair"
|
||||||
fgHighlighted: "Texte mis en évidence"
|
fgHighlighted: "Texte mis en évidence"
|
||||||
_sfx:
|
_sfx:
|
||||||
note: "Nouvelle note"
|
note: "Nouveau post"
|
||||||
noteMy: "Ma note"
|
noteMy: "Mon post"
|
||||||
notification: "Notifications"
|
notification: "Notifications"
|
||||||
chat: "Discuter"
|
chat: "Discuter"
|
||||||
chatBg: "Discussion (arrière-plan)"
|
chatBg: "Discussion (arrière-plan)"
|
||||||
|
@ -1254,14 +1255,14 @@ _tutorial:
|
||||||
step1_2: "On va vous installer. Vous serez opérationnel en un rien de temps"
|
step1_2: "On va vous installer. Vous serez opérationnel en un rien de temps"
|
||||||
step2_1: "Tout d'abord, remplissez votre profil"
|
step2_1: "Tout d'abord, remplissez votre profil"
|
||||||
step2_2: "En fournissant quelques informations sur qui vous êtes, il sera plus facile
|
step2_2: "En fournissant quelques informations sur qui vous êtes, il sera plus facile
|
||||||
pour les autres de savoir s'ils veulent voir vos notes ou vous suivre."
|
pour les autres de savoir s'ils veulent voir vos posts ou vous suivre."
|
||||||
step3_1: "Maintenant il est temps de suivre des gens !"
|
step3_1: "Maintenant il est temps de suivre des gens !"
|
||||||
step3_2: "Vos fil d’actualité Principal et Social sont basés sur les personnes que
|
step3_2: "Vos fil d’actualité Principal et Social sont basés sur les personnes que
|
||||||
vous suivez, alors essayez de suivre quelques comptes pour commencer.\nCliquez
|
vous suivez, alors essayez de suivre quelques comptes pour commencer.\nCliquez
|
||||||
sur le cercle plus en haut à droite d'un profil pour le suivre."
|
sur le cercle plus en haut à droite d'un profil pour le suivre."
|
||||||
step4_1: "On y va."
|
step4_1: "On y va."
|
||||||
step4_2: "Pour votre première note, certaines personnes aiment faire une note {introduction}
|
step4_2: "Pour votre premier post, certaines personnes aiment faire un post {introduction}
|
||||||
ou une simple note 'Bonjours tout le monde !'."
|
ou un simple 'Bonjours tout le monde !'"
|
||||||
step5_1: "Des fils, des fils d’actualité partout !"
|
step5_1: "Des fils, des fils d’actualité partout !"
|
||||||
step5_2: "Votre serveur a {timelines} fils différents disponibles !"
|
step5_2: "Votre serveur a {timelines} fils différents disponibles !"
|
||||||
step5_3: "Le fil {icon} Principal est l'endroit où vous pouvez voir les publications
|
step5_3: "Le fil {icon} Principal est l'endroit où vous pouvez voir les publications
|
||||||
|
@ -1334,7 +1335,7 @@ _permissions:
|
||||||
"write:messaging": "Gérer les discussions"
|
"write:messaging": "Gérer les discussions"
|
||||||
"read:mutes": "Voir les comptes masqués"
|
"read:mutes": "Voir les comptes masqués"
|
||||||
"write:mutes": "Gérer les comptes masqués"
|
"write:mutes": "Gérer les comptes masqués"
|
||||||
"write:notes": "Créer / supprimer des notes"
|
"write:notes": "Créer / supprimer des posts"
|
||||||
"read:notifications": "Afficher les notifications"
|
"read:notifications": "Afficher les notifications"
|
||||||
"write:notifications": "Gérer vos notifications"
|
"write:notifications": "Gérer vos notifications"
|
||||||
"read:reactions": "Lire les réactions"
|
"read:reactions": "Lire les réactions"
|
||||||
|
@ -1363,12 +1364,12 @@ _auth:
|
||||||
copyAsk: "Veuillez coller le code d’autorisation suivant dans l'application :"
|
copyAsk: "Veuillez coller le code d’autorisation suivant dans l'application :"
|
||||||
allPermissions: Accès complet au compte
|
allPermissions: Accès complet au compte
|
||||||
_antennaSources:
|
_antennaSources:
|
||||||
all: "Toutes les notes"
|
all: "Tous les posts"
|
||||||
homeTimeline: "Notes provenant des utilisateur·rice·s auxquel·les je suis abonné"
|
homeTimeline: "Posts provenant des utilisateur·rice·s auxquel·les je suis abonné"
|
||||||
users: "Notes venant de la part d’utilisateur·rice·s précis"
|
users: "Posts venant de la part d’utilisateur·rice·s précis"
|
||||||
userList: "Notes venant d’une liste spécifique"
|
userList: "Posts venant d’une liste spécifique"
|
||||||
userGroup: "Notes venant d’utilisateur·rice·s du groupe spécifié"
|
userGroup: "Posts venant d’utilisateur·rice·s du groupe spécifié"
|
||||||
instances: Notes de tous les utilisateurs d'un serveur
|
instances: Posts de tous les utilisateurs d'un serveur
|
||||||
_weekday:
|
_weekday:
|
||||||
sunday: "Dimanche"
|
sunday: "Dimanche"
|
||||||
monday: "Lundi"
|
monday: "Lundi"
|
||||||
|
@ -1401,7 +1402,7 @@ _widgets:
|
||||||
_userList:
|
_userList:
|
||||||
chooseList: Sélectionner une liste
|
chooseList: Sélectionner une liste
|
||||||
unixClock: Horloge UNIX
|
unixClock: Horloge UNIX
|
||||||
meiliIndexCount: Notes indexées
|
meiliIndexCount: Posts indexés
|
||||||
serverInfo: Info serveur
|
serverInfo: Info serveur
|
||||||
meiliStatus: État du serveur
|
meiliStatus: État du serveur
|
||||||
meiliSize: Taille de l’index
|
meiliSize: Taille de l’index
|
||||||
|
@ -1446,8 +1447,8 @@ _visibility:
|
||||||
localOnly: "Local seulement"
|
localOnly: "Local seulement"
|
||||||
localOnlyDescription: "Caché pour les utilisateur·rice·s distant"
|
localOnlyDescription: "Caché pour les utilisateur·rice·s distant"
|
||||||
_postForm:
|
_postForm:
|
||||||
replyPlaceholder: "Répondre à cette note ..."
|
replyPlaceholder: "Répondre à ce post ..."
|
||||||
quotePlaceholder: "Citez cette note ..."
|
quotePlaceholder: "Citez ce post ..."
|
||||||
channelPlaceholder: "Publier sur une chaîne…"
|
channelPlaceholder: "Publier sur une chaîne…"
|
||||||
_placeholders:
|
_placeholders:
|
||||||
a: "Quoi de neuf ?"
|
a: "Quoi de neuf ?"
|
||||||
|
@ -1473,7 +1474,7 @@ _profile:
|
||||||
locationDescription: Si vous entrez votre ville en premier, votre heure locale sera
|
locationDescription: Si vous entrez votre ville en premier, votre heure locale sera
|
||||||
affichée aux autres utilisateur·rice·s.
|
affichée aux autres utilisateur·rice·s.
|
||||||
_exportOrImport:
|
_exportOrImport:
|
||||||
allNotes: "Toutes les notes"
|
allNotes: "Tous les posts"
|
||||||
followingList: "Abonnements"
|
followingList: "Abonnements"
|
||||||
muteList: "Comptes masqués"
|
muteList: "Comptes masqués"
|
||||||
blockingList: "Comptes bloqués"
|
blockingList: "Comptes bloqués"
|
||||||
|
@ -1486,10 +1487,10 @@ _charts:
|
||||||
usersIncDec: "Variation du nombre d'utilisateur·rice·s"
|
usersIncDec: "Variation du nombre d'utilisateur·rice·s"
|
||||||
usersTotal: "Nombre des utilisateur·rice·s au total"
|
usersTotal: "Nombre des utilisateur·rice·s au total"
|
||||||
activeUsers: "Nombre d'utilisateurices actif·ve·s"
|
activeUsers: "Nombre d'utilisateurices actif·ve·s"
|
||||||
notesIncDec: "Variation du nombre des notes"
|
notesIncDec: "Variation du nombre de publications"
|
||||||
localNotesIncDec: "Variation du nombre de notes locales"
|
localNotesIncDec: "Variation du nombre de publications locales"
|
||||||
remoteNotesIncDec: "Variation du nombre de notes distantes"
|
remoteNotesIncDec: "Variation du nombre de publications distantes"
|
||||||
notesTotal: "Nombre total des notes"
|
notesTotal: "Nombre total des publications"
|
||||||
filesIncDec: "Variation du nombre de fichiers"
|
filesIncDec: "Variation du nombre de fichiers"
|
||||||
filesTotal: "Nombre total de fichiers"
|
filesTotal: "Nombre total de fichiers"
|
||||||
storageUsageIncDec: "Variation de l'utilisation du stockage"
|
storageUsageIncDec: "Variation de l'utilisation du stockage"
|
||||||
|
@ -1498,8 +1499,8 @@ _instanceCharts:
|
||||||
requests: "Requêtes"
|
requests: "Requêtes"
|
||||||
users: "Variation du nombre d'utilisateur·rice·s"
|
users: "Variation du nombre d'utilisateur·rice·s"
|
||||||
usersTotal: "Total cumulé du nombre d'utilisateur·rice·s"
|
usersTotal: "Total cumulé du nombre d'utilisateur·rice·s"
|
||||||
notes: "Variation du nombre de notes"
|
notes: "Variation du nombre de publications"
|
||||||
notesTotal: "Nombre total cumulé des notes"
|
notesTotal: "Nombre total cumulé des publications"
|
||||||
ff: "Variation des abonné·e·s / abonnements"
|
ff: "Variation des abonné·e·s / abonnements"
|
||||||
ffTotal: "Total cumulé du nombre d'abonné·e·s / abonnements"
|
ffTotal: "Total cumulé du nombre d'abonné·e·s / abonnements"
|
||||||
cacheSize: "Variation de la taille du cache"
|
cacheSize: "Variation de la taille du cache"
|
||||||
|
@ -1587,10 +1588,10 @@ _pages:
|
||||||
id: "Toile ID"
|
id: "Toile ID"
|
||||||
width: "Largeur"
|
width: "Largeur"
|
||||||
height: "Hauteur"
|
height: "Hauteur"
|
||||||
note: "Note intégrée"
|
note: "Post intégré"
|
||||||
_note:
|
_note:
|
||||||
id: "Identifiant de la note"
|
id: "Identifiant du post"
|
||||||
idDescription: "Vous pouvez aussi coller ici l'URL ici."
|
idDescription: "Vous pouvez aussi coller l'URL du post ici."
|
||||||
detailed: "Afficher les détails"
|
detailed: "Afficher les détails"
|
||||||
switch: "Interrupteur"
|
switch: "Interrupteur"
|
||||||
_switch:
|
_switch:
|
||||||
|
@ -1813,7 +1814,7 @@ _notification:
|
||||||
youGotMention: "{name} vous a mentionné"
|
youGotMention: "{name} vous a mentionné"
|
||||||
youGotReply: "Réponse de {name}"
|
youGotReply: "Réponse de {name}"
|
||||||
youGotQuote: "Cité·e par {name}"
|
youGotQuote: "Cité·e par {name}"
|
||||||
youRenoted: "{name} vous a Renoté"
|
youRenoted: "{name} vous a boosté"
|
||||||
youGotPoll: "{name} a participé à votre sondage"
|
youGotPoll: "{name} a participé à votre sondage"
|
||||||
youGotMessagingMessageFromUser: "{name} vous envoyé un message"
|
youGotMessagingMessageFromUser: "{name} vous envoyé un message"
|
||||||
youGotMessagingMessageFromGroup: "Un message a été envoyé au groupe {name}"
|
youGotMessagingMessageFromGroup: "Un message a été envoyé au groupe {name}"
|
||||||
|
@ -1828,7 +1829,7 @@ _notification:
|
||||||
follow: "Nouvel·le abonné·e"
|
follow: "Nouvel·le abonné·e"
|
||||||
mention: "Mentions"
|
mention: "Mentions"
|
||||||
reply: "Réponses"
|
reply: "Réponses"
|
||||||
renote: "Renotes"
|
renote: "Boosts"
|
||||||
quote: "Citations"
|
quote: "Citations"
|
||||||
reaction: "Réactions"
|
reaction: "Réactions"
|
||||||
pollVote: "Votes dans des sondages"
|
pollVote: "Votes dans des sondages"
|
||||||
|
@ -1840,9 +1841,9 @@ _notification:
|
||||||
_actions:
|
_actions:
|
||||||
followBack: "Suivre"
|
followBack: "Suivre"
|
||||||
reply: "Répondre"
|
reply: "Répondre"
|
||||||
renote: "Renoter"
|
renote: "Boosts"
|
||||||
reacted: a réagit à votre Note
|
reacted: a réagit à votre Note
|
||||||
renoted: a boosté votre Note
|
renoted: a boosté votre post
|
||||||
voted: a voté pour votre sondage
|
voted: a voté pour votre sondage
|
||||||
_deck:
|
_deck:
|
||||||
alwaysShowMainColumn: "Toujours afficher la colonne principale"
|
alwaysShowMainColumn: "Toujours afficher la colonne principale"
|
||||||
|
@ -1931,7 +1932,7 @@ moveAccountDescription: Ce processus est irréversible. Soyez sûr⋅e que vous
|
||||||
un alias pour ce compte sur votre nouveau compte avant de migrer. Merci d'entrer
|
un alias pour ce compte sur votre nouveau compte avant de migrer. Merci d'entrer
|
||||||
la mention du compte formaté comme ceci @personne@server.com
|
la mention du compte formaté comme ceci @personne@server.com
|
||||||
moveAccount: Déplacer le compte !
|
moveAccount: Déplacer le compte !
|
||||||
seperateRenoteQuote: Séparer les renotes et les boutons de citation
|
seperateRenoteQuote: Séparer les boutons de boosts et de citation
|
||||||
failedToFetchAccountInformation: Impossible de récupérer les informations de compte
|
failedToFetchAccountInformation: Impossible de récupérer les informations de compte
|
||||||
noEmailServerWarning: Serveur mail non configuré.
|
noEmailServerWarning: Serveur mail non configuré.
|
||||||
deleteAccount: Supprimer le compte
|
deleteAccount: Supprimer le compte
|
||||||
|
@ -2002,7 +2003,7 @@ forwardReportIsAnonymous: À la place de votre compte, un compte système anonym
|
||||||
affiché comme rapporteur au serveur distant.
|
affiché comme rapporteur au serveur distant.
|
||||||
noThankYou: Non merci
|
noThankYou: Non merci
|
||||||
addInstance: Ajouter un serveur
|
addInstance: Ajouter un serveur
|
||||||
renoteMute: Mettre en silence les renotes
|
renoteMute: Masquer les boosts
|
||||||
flagSpeakAsCat: Parler comme un chat
|
flagSpeakAsCat: Parler comme un chat
|
||||||
flagSpeakAsCatDescription: Vos messages seront nyanifiés en mode chat
|
flagSpeakAsCatDescription: Vos messages seront nyanifiés en mode chat
|
||||||
hiddenTags: Hashtags cachés
|
hiddenTags: Hashtags cachés
|
||||||
|
@ -2059,14 +2060,14 @@ pushNotificationAlreadySubscribed: Notifications push déjà activées
|
||||||
logoImageUrl: URL de l'image du logo
|
logoImageUrl: URL de l'image du logo
|
||||||
moveToLabel: 'Compte vers lequel vous migrez :'
|
moveToLabel: 'Compte vers lequel vous migrez :'
|
||||||
moveFrom: Migrer vers ce compte depuis un ancien compte
|
moveFrom: Migrer vers ce compte depuis un ancien compte
|
||||||
defaultReaction: Émoji de réaction par défaut pour les notes entrantes et sortantes
|
defaultReaction: Émoji de réaction par défaut pour les posts entrants et sortants
|
||||||
license: Licence
|
license: Licence
|
||||||
indexPosts: Indexer les Notes
|
indexPosts: Indexer les Posts
|
||||||
indexNotice: Indexation en cours. Cela prendra certainement du temps, veuillez ne
|
indexNotice: Indexation en cours. Cela prendra certainement du temps, veuillez ne
|
||||||
pas redémarrer votre serveur pour au moins une heure.
|
pas redémarrer votre serveur pour au moins une heure.
|
||||||
customKaTeXMacro: Macros KaTeX personnalisées
|
customKaTeXMacro: Macros KaTeX personnalisées
|
||||||
enableCustomKaTeXMacro: Activer les macros KaTeX personnalisées
|
enableCustomKaTeXMacro: Activer les macros KaTeX personnalisées
|
||||||
noteId: ID de Note
|
noteId: ID des Posts
|
||||||
customKaTeXMacroDescription: "Définissez des macros pour écrire des expressions mathématiques
|
customKaTeXMacroDescription: "Définissez des macros pour écrire des expressions mathématiques
|
||||||
simplement ! La notation se conforme aux définitions de commandes LaTeX et s'écrit
|
simplement ! La notation se conforme aux définitions de commandes LaTeX et s'écrit
|
||||||
\\newcommand{\\·name}{content} ou \\newcommand{\\name}[number of arguments]{content}.
|
\\newcommand{\\·name}{content} ou \\newcommand{\\name}[number of arguments]{content}.
|
||||||
|
@ -2085,7 +2086,7 @@ deleted: Effacé
|
||||||
editNote: Modifier note
|
editNote: Modifier note
|
||||||
edited: 'Modifié à {date} {time}'
|
edited: 'Modifié à {date} {time}'
|
||||||
flagShowTimelineRepliesDescription: Si activé, affiche dans le fil les réponses des
|
flagShowTimelineRepliesDescription: Si activé, affiche dans le fil les réponses des
|
||||||
utilisatieur·rice·s aux notes des autres.
|
utilisatieur·rice·s aux posts des autres.
|
||||||
_experiments:
|
_experiments:
|
||||||
alpha: Alpha
|
alpha: Alpha
|
||||||
beta: Beta
|
beta: Beta
|
||||||
|
@ -2096,21 +2097,21 @@ _experiments:
|
||||||
peut entraîner des ralentissements lors du chargement si votre file d'attente
|
peut entraîner des ralentissements lors du chargement si votre file d'attente
|
||||||
est congestionnée.
|
est congestionnée.
|
||||||
findOtherInstance: Trouver un autre serveur
|
findOtherInstance: Trouver un autre serveur
|
||||||
userSaysSomethingReasonQuote: '{name} a cité une note contenant {reason}'
|
userSaysSomethingReasonQuote: '{name} a cité un post contenant {reason}'
|
||||||
signupsDisabled: Les inscriptions sur ce serveur sont actuellement désactivés, mais
|
signupsDisabled: Les inscriptions sur ce serveur sont actuellement désactivés, mais
|
||||||
vous pouvez toujours vous inscrire sur un autre serveur ! Si vous avez un code d'invitation
|
vous pouvez toujours vous inscrire sur un autre serveur ! Si vous avez un code d'invitation
|
||||||
pour ce serveur, entrez-le ci-dessous s'il vous plait.
|
pour ce serveur, entrez-le ci-dessous s'il vous plait.
|
||||||
apps: Applications
|
apps: Applications
|
||||||
userSaysSomethingReasonReply: '{noms} a répondu à une note contenant {raison}'
|
userSaysSomethingReasonReply: '{noms} a répondu à un post contenant {raison}'
|
||||||
defaultValueIs: 'défaut : {valeur}'
|
defaultValueIs: 'défaut : {valeur}'
|
||||||
searchPlaceholder: Recherchez sur Firefish
|
searchPlaceholder: Recherchez sur Firefish
|
||||||
removeReaction: Retirer votre réaction
|
removeReaction: Retirer votre réaction
|
||||||
selectChannel: Sélectionner une chaîne
|
selectChannel: Sélectionner une chaîne
|
||||||
expandOnNoteClick: Ouvrir la note en cliquant
|
expandOnNoteClick: Ouvrir le post en cliquant
|
||||||
preventAiLearning: Empêcher le récupération de données par des IA
|
preventAiLearning: Empêcher le récupération de données par des IA
|
||||||
listsDesc: Les listes vous laissent créer des fils personnalisés avec des utilisateur·rice·s
|
listsDesc: Les listes vous laissent créer des fils personnalisés avec des utilisateur·rice·s
|
||||||
spécifié·e·s. Elles sont accessibles depuis la page des fils.
|
spécifié·e·s. Elles sont accessibles depuis la page des fils.
|
||||||
indexFromDescription: Laisser vide pour indexer toutes les Notes
|
indexFromDescription: Laisser vide pour indexer toutes les Posts
|
||||||
_feeds:
|
_feeds:
|
||||||
jsonFeed: flux JSON
|
jsonFeed: flux JSON
|
||||||
atom: Atom
|
atom: Atom
|
||||||
|
@ -2118,9 +2119,9 @@ _feeds:
|
||||||
rss: RSS
|
rss: RSS
|
||||||
alt: ALT
|
alt: ALT
|
||||||
swipeOnMobile: Permettre le balayage entre les pages
|
swipeOnMobile: Permettre le balayage entre les pages
|
||||||
expandOnNoteClickDesc: Si désactivé, vous pourrez toujours ouvrir les Notes dans le
|
expandOnNoteClickDesc: Si désactivé, vous pourrez toujours ouvrir les posts dans le
|
||||||
menu du clic droit et en cliquant sur l’horodatage.
|
menu du clic droit et en cliquant sur l’horodatage.
|
||||||
indexFrom: Indexer à partir de l’ID des Notes
|
indexFrom: Indexer à partir de l’ID des Posts
|
||||||
older: plus ancien
|
older: plus ancien
|
||||||
newer: plus récent
|
newer: plus récent
|
||||||
accessibility: Accessibilité
|
accessibility: Accessibilité
|
||||||
|
@ -2128,7 +2129,7 @@ silencedInstancesDescription: Listez les noms de domaine de serveurs que vous vo
|
||||||
masquer. Les comptes des serveurs listés seront traités comme "Masqués", ne pourront
|
masquer. Les comptes des serveurs listés seront traités comme "Masqués", ne pourront
|
||||||
faire que des demandes d’abonnement, et ne pourront pas mentionner les comptes locaux
|
faire que des demandes d’abonnement, et ne pourront pas mentionner les comptes locaux
|
||||||
si non-suivis. Cela n’affectera en rien les serveurs bloqués.
|
si non-suivis. Cela n’affectera en rien les serveurs bloqués.
|
||||||
antennasDesc: "Les Antennes affichent de nouvelles notes selon les critères que vous
|
antennasDesc: "Les Antennes affichent de nouveaux posts selon les critères que vous
|
||||||
indiqués.\nElles peuvent être consultées depuis la page des fils."
|
indiqués.\nElles peuvent être consultées depuis la page des fils."
|
||||||
image: Image
|
image: Image
|
||||||
video: Vidéo
|
video: Vidéo
|
||||||
|
@ -2138,10 +2139,10 @@ cw: Avertissement de contenu
|
||||||
xl: XL
|
xl: XL
|
||||||
reflectMayTakeTime: Il pourra s’écouler un certain temps avant que les changements
|
reflectMayTakeTime: Il pourra s’écouler un certain temps avant que les changements
|
||||||
ne soient reflétés.
|
ne soient reflétés.
|
||||||
userSaysSomethingReasonRenote: '{name} a boosté une note contenant {reason}'
|
userSaysSomethingReasonRenote: '{name} a boosté un post contenant {reason}'
|
||||||
sendModMail: Envoyer un avis à la modération
|
sendModMail: Envoyer un avis à la modération
|
||||||
clipsDesc: Les clips sont comme des favoris catégorisés pouvant être partagés. Vous
|
clipsDesc: Les clips sont comme des favoris catégorisés pouvant être partagés. Vous
|
||||||
pouvez créer des clips à partir du menu de chaque note.
|
pouvez créer des clips à partir du menu de chaque post.
|
||||||
unclip: Dé-clipper
|
unclip: Dé-clipper
|
||||||
secureMode: Mode sécurisé (Authorized Fetch)
|
secureMode: Mode sécurisé (Authorized Fetch)
|
||||||
secureModeInfo: Quand sollicité depuis d'autres serveurs, ne pas répondre sans preuve.
|
secureModeInfo: Quand sollicité depuis d'autres serveurs, ne pas répondre sans preuve.
|
||||||
|
@ -2174,8 +2175,8 @@ isPatron: Mécène Firefish
|
||||||
_filters:
|
_filters:
|
||||||
fromUser: De l’utilisateur
|
fromUser: De l’utilisateur
|
||||||
withFile: Avec fichier
|
withFile: Avec fichier
|
||||||
notesBefore: Notes avant
|
notesBefore: Posts avant
|
||||||
notesAfter: Notes après
|
notesAfter: Posts après
|
||||||
followersOnly: Abonnés uniquement
|
followersOnly: Abonnés uniquement
|
||||||
followingOnly: Abonnements uniquement
|
followingOnly: Abonnements uniquement
|
||||||
fromDomain: Du domaine
|
fromDomain: Du domaine
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
_lang_: "Bahasa Indonesia"
|
_lang_: "Bahasa Indonesia"
|
||||||
headlineFirefish: "Jaringan terhubung melalui catatan"
|
headlineFirefish: "Platform media sosial sumber terbuka dan terdesentralisasi yang
|
||||||
|
merdeka sepenuhnya! 🚀"
|
||||||
introFirefish: "Selamat datang! Firefish adalah media sosial sumber terbuka dan terdesentralisasi
|
introFirefish: "Selamat datang! Firefish adalah media sosial sumber terbuka dan terdesentralisasi
|
||||||
yang selamanya bebas! 🚀"
|
yang selamanya bebas! 🚀"
|
||||||
monthAndDay: "{day} {month}"
|
monthAndDay: "{day} {month}"
|
||||||
|
@ -93,7 +94,7 @@ youShouldUpgradeClient: "Untuk melihat halaman ini, mohon muat ulang untuk memut
|
||||||
enterListName: "Masukkan nama daftar"
|
enterListName: "Masukkan nama daftar"
|
||||||
privacy: "Privasi"
|
privacy: "Privasi"
|
||||||
makeFollowManuallyApprove: "Permintaan mengikuti membutuhkan persetujuan"
|
makeFollowManuallyApprove: "Permintaan mengikuti membutuhkan persetujuan"
|
||||||
defaultNoteVisibility: "Privasi bawaan catatan"
|
defaultNoteVisibility: "Visibilitas bawaan"
|
||||||
follow: "Ikuti"
|
follow: "Ikuti"
|
||||||
followRequest: "Permintaan Mengikuti"
|
followRequest: "Permintaan Mengikuti"
|
||||||
followRequests: "Permintaan mengikuti"
|
followRequests: "Permintaan mengikuti"
|
||||||
|
@ -743,7 +744,7 @@ developer: "Pengembang"
|
||||||
makeExplorable: "Buat akun tampil di \"Jelajahi\""
|
makeExplorable: "Buat akun tampil di \"Jelajahi\""
|
||||||
makeExplorableDescription: "Jika kamu menonaktifkan ini, akun kamu tidak akan muncul
|
makeExplorableDescription: "Jika kamu menonaktifkan ini, akun kamu tidak akan muncul
|
||||||
di bagian \"Jelajahi\"."
|
di bagian \"Jelajahi\"."
|
||||||
showGapBetweenNotesInTimeline: "Tampilkan jarak diantara catatan pada linimasa"
|
showGapBetweenNotesInTimeline: "Tampilkan jarak diantara postingan pada linimasa"
|
||||||
duplicate: "Duplikat"
|
duplicate: "Duplikat"
|
||||||
left: "Kiri"
|
left: "Kiri"
|
||||||
center: "Tengah"
|
center: "Tengah"
|
||||||
|
@ -834,7 +835,7 @@ gallery: "Galeri"
|
||||||
recentPosts: "Postingan terbaru"
|
recentPosts: "Postingan terbaru"
|
||||||
popularPosts: "Postingan populer"
|
popularPosts: "Postingan populer"
|
||||||
shareWithNote: "Bagikan dengan postingan"
|
shareWithNote: "Bagikan dengan postingan"
|
||||||
ads: "Iklan"
|
ads: "Spanduk komunitas"
|
||||||
expiration: "Batas akhir"
|
expiration: "Batas akhir"
|
||||||
memo: "Memo"
|
memo: "Memo"
|
||||||
priority: "Prioritas"
|
priority: "Prioritas"
|
||||||
|
@ -1245,8 +1246,7 @@ _tutorial:
|
||||||
step1_2: "Ayo siapkan. Lekas mulai tanpa basa-basi!"
|
step1_2: "Ayo siapkan. Lekas mulai tanpa basa-basi!"
|
||||||
step1_3: "Linimasa kamu kosong, karena kamu belum mencatat catatan apapun atau mengikuti
|
step1_3: "Linimasa kamu kosong, karena kamu belum mencatat catatan apapun atau mengikuti
|
||||||
siapapun."
|
siapapun."
|
||||||
step2_1: "Selesaikan menyetel profilmu sebelum menulis sebuah catatan atau mengikuti
|
step2_1: "Pertama, isi profilmu lebih dahulu."
|
||||||
seseorang."
|
|
||||||
step2_2: "Menyediakan beberapa informasi tentang siapa kamu akan membuatnya lebih
|
step2_2: "Menyediakan beberapa informasi tentang siapa kamu akan membuatnya lebih
|
||||||
mudah bagi orang lain untuk menentukan jika mereka ingin postinganmu atau mengikutimu."
|
mudah bagi orang lain untuk menentukan jika mereka ingin postinganmu atau mengikutimu."
|
||||||
step3_1: "Sekarang saatnya mengikuti beberapa orang!"
|
step3_1: "Sekarang saatnya mengikuti beberapa orang!"
|
||||||
|
@ -1558,7 +1558,7 @@ _pages:
|
||||||
if: "Jika"
|
if: "Jika"
|
||||||
_if:
|
_if:
|
||||||
variable: "Variabel"
|
variable: "Variabel"
|
||||||
post: "Buat catatan"
|
post: "Formulir posting"
|
||||||
_post:
|
_post:
|
||||||
text: "Isi"
|
text: "Isi"
|
||||||
attachCanvasImage: "Posting dengan kanvas sebagai gambar"
|
attachCanvasImage: "Posting dengan kanvas sebagai gambar"
|
||||||
|
@ -2011,7 +2011,7 @@ pushNotificationAlreadySubscribed: Pemberitahuan dorong sudah aktif
|
||||||
pushNotificationNotSupported: Peramban atau servermu tidak mendukung pemberitahuan
|
pushNotificationNotSupported: Peramban atau servermu tidak mendukung pemberitahuan
|
||||||
dorong
|
dorong
|
||||||
apps: Aplikasi
|
apps: Aplikasi
|
||||||
showAds: Tampilkan iklan
|
showAds: Tampilkan spanduk komunitas
|
||||||
enterSendsMessage: Tekan Enter pada Pesan untuk mengirim pesan (matikan dengan Ctrl
|
enterSendsMessage: Tekan Enter pada Pesan untuk mengirim pesan (matikan dengan Ctrl
|
||||||
+ Enter)
|
+ Enter)
|
||||||
showAdminUpdates: Indikasi versi Firefish baru tersedia (hanya admin)
|
showAdminUpdates: Indikasi versi Firefish baru tersedia (hanya admin)
|
||||||
|
@ -2157,3 +2157,9 @@ origin: Asal
|
||||||
objectStorageS3ForcePathStyle: Gunakan URL titik akhir berbasis lokasi
|
objectStorageS3ForcePathStyle: Gunakan URL titik akhir berbasis lokasi
|
||||||
objectStorageS3ForcePathStyleDesc: Aktifkan ini untuk membuat URL titik akhir dalam
|
objectStorageS3ForcePathStyleDesc: Aktifkan ini untuk membuat URL titik akhir dalam
|
||||||
format 's3.amazonaws.com/<bucket>/' di atas '<bucket>.s3.amazonaws.com'.
|
format 's3.amazonaws.com/<bucket>/' di atas '<bucket>.s3.amazonaws.com'.
|
||||||
|
deletePasskeys: Hapus passkeys
|
||||||
|
inputNotMatch: Masukan tidak cocok
|
||||||
|
delete2fa: Nonaktifkan 2FA
|
||||||
|
delete2faConfirm: Ini akan menghapus 2FA secara permanen pada akun ini. Lanjutkan?
|
||||||
|
deletePasskeysConfirm: Ini akan menghapus semua passkeys dan kunci keamanan pada akun
|
||||||
|
ini secara permanen. Lanjutkan?
|
||||||
|
|
|
@ -1076,7 +1076,7 @@ _aboutFirefish:
|
||||||
about: "Firefishは、2022年に生まれたThatOneCalculatorによるMisskeyのforkです。"
|
about: "Firefishは、2022年に生まれたThatOneCalculatorによるMisskeyのforkです。"
|
||||||
contributors: "主なコントリビューター"
|
contributors: "主なコントリビューター"
|
||||||
allContributors: "全てのコントリビューター"
|
allContributors: "全てのコントリビューター"
|
||||||
originalMisskeyContributors: "フォーク元のMisskeyの主なコントリビューター"
|
misskeyContributors: "フォーク元のMisskeyの主なコントリビューター"
|
||||||
source: "ソースコード"
|
source: "ソースコード"
|
||||||
translation: "Firefishを翻訳"
|
translation: "Firefishを翻訳"
|
||||||
donate: "Firefishに寄付"
|
donate: "Firefishに寄付"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "firefish",
|
"name": "firefish",
|
||||||
"version": "1.0.4-dev6",
|
"version": "1.0.4-beta",
|
||||||
"codename": "aqua",
|
"codename": "aqua",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -22,6 +22,8 @@
|
||||||
"dev": "pnpm node ./scripts/dev.js",
|
"dev": "pnpm node ./scripts/dev.js",
|
||||||
"dev:staging": "NODE_OPTIONS=--max_old_space_size=3072 NODE_ENV=development pnpm run build && pnpm run start",
|
"dev:staging": "NODE_OPTIONS=--max_old_space_size=3072 NODE_ENV=development pnpm run build && pnpm run start",
|
||||||
"lint": "pnpm -r --parallel run lint",
|
"lint": "pnpm -r --parallel run lint",
|
||||||
|
"debug": "pnpm run build:debug && pnpm run start",
|
||||||
|
"build:debug": "pnpm -r --parallel run build:debug && pnpm run gulp",
|
||||||
"cy:open": "cypress open --browser --e2e --config-file=cypress.config.ts",
|
"cy:open": "cypress open --browser --e2e --config-file=cypress.config.ts",
|
||||||
"cy:run": "cypress run",
|
"cy:run": "cypress run",
|
||||||
"e2e": "start-server-and-test start:test http://localhost:61812 cy:run",
|
"e2e": "start-server-and-test start:test http://localhost:61812 cy:run",
|
||||||
|
|
|
@ -42,13 +42,15 @@ async fn main() {
|
||||||
None => "redis",
|
None => "redis",
|
||||||
Some(_) => "rediss",
|
Some(_) => "rediss",
|
||||||
};
|
};
|
||||||
let redis_uri_userpass = match redis_conf.user {
|
let redis_user = redis_conf.user.unwrap_or("default".to_string());
|
||||||
None => "".to_string(),
|
let redis_uri_userpass = format!(
|
||||||
Some(user) => format!("{}:{}@", user, encode(&redis_conf.pass.unwrap_or_default())),
|
"{}:{}",
|
||||||
};
|
redis_user,
|
||||||
|
encode(&redis_conf.pass.unwrap_or_default())
|
||||||
|
);
|
||||||
let redis_uri_hostport = format!("{}:{}", redis_conf.host, redis_conf.port);
|
let redis_uri_hostport = format!("{}:{}", redis_conf.host, redis_conf.port);
|
||||||
let redis_uri = format!(
|
let redis_uri = format!(
|
||||||
"{}://{}{}/{}",
|
"{}://{}@{}/{}",
|
||||||
redis_proto, redis_uri_userpass, redis_uri_hostport, redis_conf.db
|
redis_proto, redis_uri_userpass, redis_uri_hostport, redis_conf.db
|
||||||
);
|
);
|
||||||
env::set_var(CACHE_URL_ENV, redis_uri);
|
env::set_var(CACHE_URL_ENV, redis_uri);
|
||||||
|
|
|
@ -36,8 +36,8 @@
|
||||||
"artifacts": "napi artifacts",
|
"artifacts": "napi artifacts",
|
||||||
"build": "pnpm run build:napi && pnpm run build:migration",
|
"build": "pnpm run build:napi && pnpm run build:migration",
|
||||||
"build:napi": "napi build --features napi --platform --release ./built/",
|
"build:napi": "napi build --features napi --platform --release ./built/",
|
||||||
"build:migration": "cargo build --locked --release --manifest-path ./migration/Cargo.toml && cp ./target/release/migration ./built/migration",
|
"build:migration": "cargo build --locked --release --manifest-path ./migration/Cargo.toml && cp -v ./target/release/migration ./built/migration",
|
||||||
"build:debug": "napi build --platform ./built/ && cargo build --manifest-path ./migration/Cargo.toml",
|
"build:debug": "napi build --features napi --platform ./built/ && cargo build --locked --manifest-path ./migration/Cargo.toml && cp -v ./target/debug/migration ./built/migration",
|
||||||
"prepublishOnly": "napi prepublish -t npm",
|
"prepublishOnly": "napi prepublish -t npm",
|
||||||
"test": "pnpm run cargo:test && pnpm run build:napi && ava",
|
"test": "pnpm run cargo:test && pnpm run build:napi && ava",
|
||||||
"universal": "napi universal",
|
"universal": "napi universal",
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
"revertmigration:cargo": "./native-utils/built/migration down",
|
"revertmigration:cargo": "./native-utils/built/migration down",
|
||||||
"check:connect": "node ./check_connect.js",
|
"check:connect": "node ./check_connect.js",
|
||||||
"build": "pnpm swc src -d built -D",
|
"build": "pnpm swc src -d built -D",
|
||||||
|
"build:debug": "pnpm swc src -d built -s -D",
|
||||||
"watch": "pnpm swc src -d built -D -w",
|
"watch": "pnpm swc src -d built -D -w",
|
||||||
"lint": "pnpm rome check --apply *",
|
"lint": "pnpm rome check --apply *",
|
||||||
"mocha": "cross-env NODE_ENV=test TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=\"./test/tsconfig.json\" mocha",
|
"mocha": "cross-env NODE_ENV=test TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=\"./test/tsconfig.json\" mocha",
|
||||||
|
|
|
@ -156,7 +156,7 @@ export function toHtml(
|
||||||
|
|
||||||
search(node) {
|
search(node) {
|
||||||
const a = doc.createElement("a");
|
const a = doc.createElement("a");
|
||||||
a.href = `https://search.annoyingorange.xyz/search?q=${node.props.query}`;
|
a.href = `/search/${node.props.query}`;
|
||||||
a.textContent = node.props.content;
|
a.textContent = node.props.content;
|
||||||
return a;
|
return a;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
export type Post = {
|
export type Post = {
|
||||||
text: string | null;
|
text: string | undefined;
|
||||||
cw: string | null;
|
cw: string | null;
|
||||||
localOnly: boolean;
|
localOnly: boolean;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
|
visibility: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function parse(acct: any): Post {
|
export function parse(acct: any): Post {
|
||||||
return {
|
return {
|
||||||
text: acct.text,
|
text: acct.text || undefined,
|
||||||
cw: acct.cw,
|
cw: acct.cw,
|
||||||
localOnly: acct.localOnly,
|
localOnly: acct.localOnly,
|
||||||
createdAt: new Date(acct.createdAt),
|
createdAt: new Date(acct.createdAt),
|
||||||
|
visibility: "hidden" + (acct.visibility || ""),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import {
|
||||||
backgroundQueue,
|
backgroundQueue,
|
||||||
} from "./queues.js";
|
} from "./queues.js";
|
||||||
import type { ThinUser } from "./types.js";
|
import type { ThinUser } from "./types.js";
|
||||||
|
import { Note } from "@/models/entities/note.js";
|
||||||
|
|
||||||
function renderError(e: Error): any {
|
function renderError(e: Error): any {
|
||||||
return {
|
return {
|
||||||
|
@ -358,6 +359,7 @@ export function createImportCkPostJob(
|
||||||
user: ThinUser,
|
user: ThinUser,
|
||||||
post: any,
|
post: any,
|
||||||
signatureCheck: boolean,
|
signatureCheck: boolean,
|
||||||
|
parent: Note | null = null,
|
||||||
) {
|
) {
|
||||||
return dbQueue.add(
|
return dbQueue.add(
|
||||||
"importCkPost",
|
"importCkPost",
|
||||||
|
@ -365,6 +367,7 @@ export function createImportCkPostJob(
|
||||||
user: user,
|
user: user,
|
||||||
post: post,
|
post: post,
|
||||||
signatureCheck: signatureCheck,
|
signatureCheck: signatureCheck,
|
||||||
|
parent: parent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
removeOnComplete: true,
|
removeOnComplete: true,
|
||||||
|
|
|
@ -3,7 +3,13 @@ import create from "@/services/note/create.js";
|
||||||
import { Users } from "@/models/index.js";
|
import { Users } from "@/models/index.js";
|
||||||
import type { DbUserImportMastoPostJobData } from "@/queue/types.js";
|
import type { DbUserImportMastoPostJobData } from "@/queue/types.js";
|
||||||
import { queueLogger } from "../../logger.js";
|
import { queueLogger } from "../../logger.js";
|
||||||
|
import { uploadFromUrl } from "@/services/drive/upload-from-url.js";
|
||||||
|
import type { DriveFile } from "@/models/entities/drive-file.js";
|
||||||
import type Bull from "bull";
|
import type Bull from "bull";
|
||||||
|
import { createImportCkPostJob } from "@/queue/index.js";
|
||||||
|
import { Notes, NoteEdits } from "@/models/index.js";
|
||||||
|
import type { Note } from "@/models/entities/note.js";
|
||||||
|
import { genId } from "@/misc/gen-id.js";
|
||||||
|
|
||||||
const logger = queueLogger.createSubLogger("import-firefish-post");
|
const logger = queueLogger.createSubLogger("import-firefish-post");
|
||||||
|
|
||||||
|
@ -17,6 +23,7 @@ export async function importCkPost(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const post = job.data.post;
|
const post = job.data.post;
|
||||||
|
/*
|
||||||
if (post.replyId != null) {
|
if (post.replyId != null) {
|
||||||
done();
|
done();
|
||||||
return;
|
return;
|
||||||
|
@ -29,23 +36,74 @@ export async function importCkPost(
|
||||||
done();
|
done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { text, cw, localOnly, createdAt } = Post.parse(post);
|
*/
|
||||||
const note = await create(user, {
|
const urls = (post.files || [])
|
||||||
|
.map((x: any) => x.url)
|
||||||
|
.filter((x: String) => x.startsWith("http"));
|
||||||
|
const files: DriveFile[] = [];
|
||||||
|
for (const url of urls) {
|
||||||
|
try {
|
||||||
|
const file = await uploadFromUrl({
|
||||||
|
url: url,
|
||||||
|
user: user,
|
||||||
|
});
|
||||||
|
files.push(file);
|
||||||
|
} catch (e) {
|
||||||
|
logger.error(`Skipped adding file to drive: ${url}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const { text, cw, localOnly, createdAt, visibility } = Post.parse(post);
|
||||||
|
let note = await Notes.findOneBy({
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
files: undefined,
|
text: text,
|
||||||
poll: undefined,
|
userId: user.id,
|
||||||
text: text || undefined,
|
|
||||||
reply: null,
|
|
||||||
renote: null,
|
|
||||||
cw: cw,
|
|
||||||
localOnly,
|
|
||||||
visibility: "hidden",
|
|
||||||
visibleUsers: [],
|
|
||||||
channel: null,
|
|
||||||
apMentions: new Array(0),
|
|
||||||
apHashtags: undefined,
|
|
||||||
apEmojis: undefined,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (note && (note?.fileIds?.length || 0) < files.length) {
|
||||||
|
const update: Partial<Note> = {};
|
||||||
|
update.fileIds = files.map((x) => x.id);
|
||||||
|
await Notes.update(note.id, update);
|
||||||
|
await NoteEdits.insert({
|
||||||
|
id: genId(),
|
||||||
|
noteId: note.id,
|
||||||
|
text: note.text || undefined,
|
||||||
|
cw: note.cw,
|
||||||
|
fileIds: note.fileIds,
|
||||||
|
updatedAt: new Date(),
|
||||||
|
});
|
||||||
|
logger.info(`Note file updated`);
|
||||||
|
}
|
||||||
|
if (!note) {
|
||||||
|
note = await create(user, {
|
||||||
|
createdAt: createdAt,
|
||||||
|
files: files.length == 0 ? undefined : files,
|
||||||
|
poll: undefined,
|
||||||
|
text: text || undefined,
|
||||||
|
reply: post.replyId ? job.data.parent : null,
|
||||||
|
renote: post.renoteId ? job.data.parent : null,
|
||||||
|
cw: cw,
|
||||||
|
localOnly,
|
||||||
|
visibility: visibility,
|
||||||
|
visibleUsers: [],
|
||||||
|
channel: null,
|
||||||
|
apMentions: new Array(0),
|
||||||
|
apHashtags: undefined,
|
||||||
|
apEmojis: undefined,
|
||||||
|
});
|
||||||
|
logger.info(`Create new note`);
|
||||||
|
} else {
|
||||||
|
logger.info(`Note exist`);
|
||||||
|
}
|
||||||
logger.succ("Imported");
|
logger.succ("Imported");
|
||||||
|
if (post.childNotes) {
|
||||||
|
for (const child of post.childNotes) {
|
||||||
|
createImportCkPostJob(
|
||||||
|
job.data.user,
|
||||||
|
child,
|
||||||
|
job.data.signatureCheck,
|
||||||
|
note,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,9 @@ import { resolveNote } from "@/remote/activitypub/models/note.js";
|
||||||
import { Note } from "@/models/entities/note.js";
|
import { Note } from "@/models/entities/note.js";
|
||||||
import { uploadFromUrl } from "@/services/drive/upload-from-url.js";
|
import { uploadFromUrl } from "@/services/drive/upload-from-url.js";
|
||||||
import type { DriveFile } from "@/models/entities/drive-file.js";
|
import type { DriveFile } from "@/models/entities/drive-file.js";
|
||||||
|
import { Notes, NoteEdits } from "@/models/index.js";
|
||||||
|
import type { Note } from "@/models/entities/note.js";
|
||||||
|
import { genId } from "@/misc/gen-id.js";
|
||||||
|
|
||||||
const logger = queueLogger.createSubLogger("import-masto-post");
|
const logger = queueLogger.createSubLogger("import-masto-post");
|
||||||
|
|
||||||
|
@ -67,23 +70,47 @@ export async function importMastoPost(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let note = await Notes.findOneBy({
|
||||||
const note = await create(user, {
|
|
||||||
createdAt: new Date(post.object.published),
|
createdAt: new Date(post.object.published),
|
||||||
files: files.length == 0 ? undefined : files,
|
text: text,
|
||||||
poll: undefined,
|
userId: user.id,
|
||||||
text: text || undefined,
|
|
||||||
reply,
|
|
||||||
renote: null,
|
|
||||||
cw: post.object.sensitive ? post.object.summary : undefined,
|
|
||||||
localOnly: false,
|
|
||||||
visibility: "hidden",
|
|
||||||
visibleUsers: [],
|
|
||||||
channel: null,
|
|
||||||
apMentions: new Array(0),
|
|
||||||
apHashtags: undefined,
|
|
||||||
apEmojis: undefined,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (note && (note?.fileIds?.length || 0) < files.length) {
|
||||||
|
const update: Partial<Note> = {};
|
||||||
|
update.fileIds = files.map((x) => x.id);
|
||||||
|
await Notes.update(note.id, update);
|
||||||
|
await NoteEdits.insert({
|
||||||
|
id: genId(),
|
||||||
|
noteId: note.id,
|
||||||
|
text: note.text || undefined,
|
||||||
|
cw: note.cw,
|
||||||
|
fileIds: note.fileIds,
|
||||||
|
updatedAt: new Date(),
|
||||||
|
});
|
||||||
|
logger.info(`Note file updated`);
|
||||||
|
}
|
||||||
|
if (!note) {
|
||||||
|
note = await create(user, {
|
||||||
|
createdAt: new Date(post.object.published),
|
||||||
|
files: files.length == 0 ? undefined : files,
|
||||||
|
poll: undefined,
|
||||||
|
text: text || undefined,
|
||||||
|
reply,
|
||||||
|
renote: null,
|
||||||
|
cw: post.object.sensitive ? post.object.summary : undefined,
|
||||||
|
localOnly: false,
|
||||||
|
visibility: "hiddenpublic",
|
||||||
|
visibleUsers: [],
|
||||||
|
channel: null,
|
||||||
|
apMentions: new Array(0),
|
||||||
|
apHashtags: undefined,
|
||||||
|
apEmojis: undefined,
|
||||||
|
});
|
||||||
|
logger.info(`Create new note`);
|
||||||
|
} else {
|
||||||
|
logger.info(`Note exist`);
|
||||||
|
}
|
||||||
job.progress(100);
|
job.progress(100);
|
||||||
done();
|
done();
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,8 @@ export async function importPosts(
|
||||||
const parsed = JSON.parse(json);
|
const parsed = JSON.parse(json);
|
||||||
if (parsed instanceof Array) {
|
if (parsed instanceof Array) {
|
||||||
logger.info("Parsing key style posts");
|
logger.info("Parsing key style posts");
|
||||||
for (const post of JSON.parse(json)) {
|
const arr = recreateChain(parsed);
|
||||||
|
for (const post of arr) {
|
||||||
createImportCkPostJob(job.data.user, post, job.data.signatureCheck);
|
createImportCkPostJob(job.data.user, post, job.data.signatureCheck);
|
||||||
}
|
}
|
||||||
} else if (parsed instanceof Object) {
|
} else if (parsed instanceof Object) {
|
||||||
|
@ -74,3 +75,32 @@ export async function importPosts(
|
||||||
logger.succ("Imported");
|
logger.succ("Imported");
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function recreateChain(arr: any[]): any {
|
||||||
|
type NotesMap = {
|
||||||
|
[id: string]: any;
|
||||||
|
};
|
||||||
|
const notesTree: any[] = [];
|
||||||
|
const lookup: NotesMap = {};
|
||||||
|
for (const note of arr) {
|
||||||
|
lookup[`${note.id}`] = note;
|
||||||
|
note.childNotes = [];
|
||||||
|
if (note.replyId == null && note.renoteId == null) {
|
||||||
|
notesTree.push(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const note of arr) {
|
||||||
|
let parent = null;
|
||||||
|
if (note.replyId != null) {
|
||||||
|
parent = lookup[`${note.replyId}`];
|
||||||
|
}
|
||||||
|
if (note.renoteId != null) {
|
||||||
|
parent = lookup[`${note.renoteId}`];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
parent.childNotes.push(note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return notesTree;
|
||||||
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ export type DbUserImportMastoPostJobData = {
|
||||||
user: ThinUser;
|
user: ThinUser;
|
||||||
post: any;
|
post: any;
|
||||||
signatureCheck: boolean;
|
signatureCheck: boolean;
|
||||||
|
parent: Note | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ObjectStorageJobData =
|
export type ObjectStorageJobData =
|
||||||
|
|
|
@ -27,6 +27,8 @@ export function apiStatusMastodon(router: Router): void {
|
||||||
let body: any = ctx.request.body;
|
let body: any = ctx.request.body;
|
||||||
if (body.in_reply_to_id)
|
if (body.in_reply_to_id)
|
||||||
body.in_reply_to_id = convertId(body.in_reply_to_id, IdType.FirefishId);
|
body.in_reply_to_id = convertId(body.in_reply_to_id, IdType.FirefishId);
|
||||||
|
if (body.quote_id)
|
||||||
|
body.quote_id = convertId(body.quote_id, IdType.FirefishId);
|
||||||
if (
|
if (
|
||||||
(!body.poll && body["poll[options][]"]) ||
|
(!body.poll && body["poll[options][]"]) ||
|
||||||
(!body.media_ids && body["media_ids[]"])
|
(!body.media_ids && body["media_ids[]"])
|
||||||
|
|
|
@ -18,6 +18,10 @@ export function argsToBools(q: ParsedUrlQuery) {
|
||||||
const toBoolean = (value: string) =>
|
const toBoolean = (value: string) =>
|
||||||
!["0", "f", "F", "false", "FALSE", "off", "OFF"].includes(value);
|
!["0", "f", "F", "false", "FALSE", "off", "OFF"].includes(value);
|
||||||
|
|
||||||
|
// Keys taken from:
|
||||||
|
// - https://docs.joinmastodon.org/methods/accounts/#statuses
|
||||||
|
// - https://docs.joinmastodon.org/methods/timelines/#public
|
||||||
|
// - https://docs.joinmastodon.org/methods/timelines/#tag
|
||||||
let object: any = q;
|
let object: any = q;
|
||||||
if (q.only_media)
|
if (q.only_media)
|
||||||
if (typeof q.only_media === "string")
|
if (typeof q.only_media === "string")
|
||||||
|
@ -25,6 +29,13 @@ export function argsToBools(q: ParsedUrlQuery) {
|
||||||
if (q.exclude_replies)
|
if (q.exclude_replies)
|
||||||
if (typeof q.exclude_replies === "string")
|
if (typeof q.exclude_replies === "string")
|
||||||
object.exclude_replies = toBoolean(q.exclude_replies);
|
object.exclude_replies = toBoolean(q.exclude_replies);
|
||||||
|
if (q.exclude_reblogs)
|
||||||
|
if (typeof q.exclude_reblogs === "string")
|
||||||
|
object.exclude_reblogs = toBoolean(q.exclude_reblogs);
|
||||||
|
if (q.pinned)
|
||||||
|
if (typeof q.pinned === "string") object.pinned = toBoolean(q.pinned);
|
||||||
|
if (q.local)
|
||||||
|
if (typeof q.local === "string") object.local = toBoolean(q.local);
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
221
packages/backend/src/server/file/byte-range-readable.ts
Normal file
221
packages/backend/src/server/file/byte-range-readable.ts
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
import { Readable, ReadableOptions } from "node:stream";
|
||||||
|
import { Buffer, constants as BufferConstants } from "node:buffer";
|
||||||
|
import * as fs from "node:fs";
|
||||||
|
|
||||||
|
interface ByteRange {
|
||||||
|
start: bigint;
|
||||||
|
end: bigint;
|
||||||
|
size: bigint;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BOUNDARY_CHARS =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
const BYTERANGE_SPEC_REGEX = /^bytes=(.+)$/;
|
||||||
|
const BYTERANGE_REGEX = /(\d*)-(\d*)/;
|
||||||
|
|
||||||
|
const BIGINT_0 = BigInt(0);
|
||||||
|
const BIGINT_1 = BigInt(1);
|
||||||
|
const BOUNDARY_SIZE = 40;
|
||||||
|
|
||||||
|
function extractRanges(
|
||||||
|
fileSize: bigint,
|
||||||
|
maxByteRanges: number,
|
||||||
|
rangeHeaderValue: string,
|
||||||
|
): ByteRange[] {
|
||||||
|
const ranges: ByteRange[] = [];
|
||||||
|
|
||||||
|
if (!rangeHeaderValue) return ranges;
|
||||||
|
|
||||||
|
const rangeSpecMatch = rangeHeaderValue.match(BYTERANGE_SPEC_REGEX);
|
||||||
|
if (!rangeSpecMatch) return [];
|
||||||
|
|
||||||
|
const rangeSpecs = rangeSpecMatch[1].split(",");
|
||||||
|
for (let i = 0; i < rangeSpecs.length; i = i + 1) {
|
||||||
|
const byteRange = rangeSpecs[i].match(BYTERANGE_REGEX);
|
||||||
|
if (!byteRange) return [];
|
||||||
|
|
||||||
|
let start: bigint;
|
||||||
|
let end: bigint;
|
||||||
|
let size: bigint;
|
||||||
|
|
||||||
|
if (byteRange[1]) {
|
||||||
|
start = BigInt(byteRange[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (byteRange[2]) {
|
||||||
|
end = BigInt(byteRange[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start === undefined && end === undefined) {
|
||||||
|
/* some invalid range like bytes=- */
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start === undefined) {
|
||||||
|
/* end-of-file range like -500 */
|
||||||
|
start = fileSize - end;
|
||||||
|
end = fileSize - BIGINT_1;
|
||||||
|
if (start < BIGINT_0) return []; /* range larger than file, return */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end === undefined) {
|
||||||
|
/* range like 0- */
|
||||||
|
end = fileSize - BIGINT_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start > end || end >= fileSize) {
|
||||||
|
/* return empty range to issue regular 200 */
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
size = end - start + BIGINT_1;
|
||||||
|
|
||||||
|
if (1 > maxByteRanges - ranges.length) return [];
|
||||||
|
|
||||||
|
ranges.push({
|
||||||
|
start: start,
|
||||||
|
end: end,
|
||||||
|
size: size,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ranges;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBoundary(len: number): string {
|
||||||
|
let chars = [];
|
||||||
|
for (let i = 0; i < len; i = i + 1) {
|
||||||
|
chars[i] = BOUNDARY_CHARS.charAt(
|
||||||
|
Math.floor(Math.random() * BOUNDARY_CHARS.length),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return chars.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
class ByteRangeReadable extends Readable {
|
||||||
|
size: bigint; /* the total size in bytes */
|
||||||
|
boundary: string; /* boundary marker to use in multipart headers */
|
||||||
|
|
||||||
|
private fd: number;
|
||||||
|
private ranges: ByteRange[];
|
||||||
|
private index: number; /* index within ranges */
|
||||||
|
private position: bigint;
|
||||||
|
private end: bigint;
|
||||||
|
private contentType: string;
|
||||||
|
private fileSize: bigint;
|
||||||
|
private headers: Buffer[];
|
||||||
|
private trailer: Buffer;
|
||||||
|
|
||||||
|
static parseByteRanges(
|
||||||
|
fileSize: bigint,
|
||||||
|
maxByteRanges: number,
|
||||||
|
rangeHeaderValue?: string,
|
||||||
|
): ByteRange[] {
|
||||||
|
return extractRanges(fileSize, maxByteRanges, rangeHeaderValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private createPartHeader(range: ByteRange): Buffer {
|
||||||
|
return Buffer.from(
|
||||||
|
[
|
||||||
|
"",
|
||||||
|
`--${this.boundary}`,
|
||||||
|
`Content-Type: ${this.contentType}`,
|
||||||
|
`Content-Range: bytes ${range.start}-${range.end}/${this.fileSize}`,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
].join("\r\n"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
fd: number,
|
||||||
|
fileSize: bigint,
|
||||||
|
ranges: ByteRange[],
|
||||||
|
contentType: string,
|
||||||
|
opts?: ReadableOptions,
|
||||||
|
) {
|
||||||
|
super(opts);
|
||||||
|
|
||||||
|
if (ranges.length === 0) {
|
||||||
|
throw Error("this requires at least 1 byte range");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fd = fd;
|
||||||
|
this.ranges = ranges;
|
||||||
|
this.fileSize = fileSize;
|
||||||
|
this.contentType = contentType;
|
||||||
|
|
||||||
|
this.position = BIGINT_1;
|
||||||
|
this.end = BIGINT_0;
|
||||||
|
this.index = -1;
|
||||||
|
this.headers = [];
|
||||||
|
|
||||||
|
this.size = BIGINT_0;
|
||||||
|
|
||||||
|
if (this.ranges.length === 1) {
|
||||||
|
this.size = this.ranges[0].size;
|
||||||
|
} else {
|
||||||
|
this.boundary = createBoundary(BOUNDARY_SIZE);
|
||||||
|
this.ranges.forEach((r) => {
|
||||||
|
const header = this.createPartHeader(r);
|
||||||
|
this.headers.push(header);
|
||||||
|
|
||||||
|
this.size += BigInt(header.length) + r.size;
|
||||||
|
});
|
||||||
|
this.trailer = Buffer.from(`\r\n--${this.boundary}--\r\n`);
|
||||||
|
this.size += BigInt(this.trailer.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_read(n) {
|
||||||
|
if (this.index == this.ranges.length) {
|
||||||
|
this.push(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.position > this.end) {
|
||||||
|
/* move ahead to the next index */
|
||||||
|
this.index++;
|
||||||
|
|
||||||
|
if (this.index === this.ranges.length) {
|
||||||
|
if (this.trailer) {
|
||||||
|
this.push(this.trailer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.push(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.position = this.ranges[this.index].start;
|
||||||
|
this.end = this.ranges[this.index].end;
|
||||||
|
|
||||||
|
if (this.ranges.length > 1) {
|
||||||
|
this.push(this.headers[this.index]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const max = this.end - this.position + BIGINT_1;
|
||||||
|
|
||||||
|
if (n > max) n = Number(max);
|
||||||
|
const buf = Buffer.alloc(n);
|
||||||
|
|
||||||
|
fs.read(this.fd, buf, 0, n, this.position, (err, bytesRead) => {
|
||||||
|
if (err) {
|
||||||
|
this.destroy(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (bytesRead == 0) {
|
||||||
|
/* something seems to have gone wrong? */
|
||||||
|
this.push(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytesRead > n) bytesRead = n;
|
||||||
|
|
||||||
|
this.position += BigInt(bytesRead);
|
||||||
|
this.push(buf.slice(0, bytesRead));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { ByteRange, ByteRangeReadable };
|
|
@ -14,6 +14,7 @@ import { detectType } from "@/misc/get-file-info.js";
|
||||||
import { convertToWebp } from "@/services/drive/image-processor.js";
|
import { convertToWebp } from "@/services/drive/image-processor.js";
|
||||||
import { GenerateVideoThumbnail } from "@/services/drive/generate-video-thumbnail.js";
|
import { GenerateVideoThumbnail } from "@/services/drive/generate-video-thumbnail.js";
|
||||||
import { StatusError } from "@/misc/fetch.js";
|
import { StatusError } from "@/misc/fetch.js";
|
||||||
|
import { ByteRangeReadable } from "./byte-range-readable.js";
|
||||||
import { FILE_TYPE_BROWSERSAFE } from "@/const.js";
|
import { FILE_TYPE_BROWSERSAFE } from "@/const.js";
|
||||||
|
|
||||||
const _filename = fileURLToPath(import.meta.url);
|
const _filename = fileURLToPath(import.meta.url);
|
||||||
|
@ -21,6 +22,8 @@ const _dirname = dirname(_filename);
|
||||||
|
|
||||||
const assets = `${_dirname}/../../server/file/assets/`;
|
const assets = `${_dirname}/../../server/file/assets/`;
|
||||||
|
|
||||||
|
const MAX_BYTE_RANGES = 10;
|
||||||
|
|
||||||
const commonReadableHandlerGenerator =
|
const commonReadableHandlerGenerator =
|
||||||
(ctx: Koa.Context) => (e: Error): void => {
|
(ctx: Koa.Context) => (e: Error): void => {
|
||||||
serverLogger.error(e);
|
serverLogger.error(e);
|
||||||
|
@ -122,31 +125,88 @@ export default async function (ctx: Koa.Context) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let contentType;
|
||||||
|
let filename;
|
||||||
|
let fileHandle;
|
||||||
|
|
||||||
if (isThumbnail || isWebpublic) {
|
if (isThumbnail || isWebpublic) {
|
||||||
const { mime, ext } = await detectType(InternalStorage.resolvePath(key));
|
const { mime, ext } = await detectType(InternalStorage.resolvePath(key));
|
||||||
const filename = rename(file.name, {
|
(contentType = FILE_TYPE_BROWSERSAFE.includes(mime)
|
||||||
suffix: isThumbnail ? "-thumb" : "-web",
|
? mime
|
||||||
extname: ext ? `.${ext}` : undefined,
|
: "application/octet-stream"),
|
||||||
}).toString();
|
(filename = rename(file.name, {
|
||||||
|
suffix: isThumbnail ? "-thumb" : "-web",
|
||||||
|
extname: ext ? `.${ext}` : undefined,
|
||||||
|
}).toString());
|
||||||
|
|
||||||
ctx.body = InternalStorage.read(key);
|
fileHandle = await InternalStorage.open(key, "r");
|
||||||
ctx.set(
|
|
||||||
"Content-Type",
|
|
||||||
FILE_TYPE_BROWSERSAFE.includes(mime) ? mime : "application/octet-stream",
|
|
||||||
);
|
|
||||||
ctx.set("Cache-Control", "max-age=31536000, immutable");
|
|
||||||
ctx.set("Content-Disposition", contentDisposition("inline", filename));
|
|
||||||
} else {
|
} else {
|
||||||
const readable = InternalStorage.read(file.accessKey!);
|
(contentType = FILE_TYPE_BROWSERSAFE.includes(file.type)
|
||||||
readable.on("error", commonReadableHandlerGenerator(ctx));
|
? file.type
|
||||||
ctx.body = readable;
|
: "application/octet-stream"),
|
||||||
ctx.set(
|
(filename = file.name);
|
||||||
"Content-Type",
|
fileHandle = await InternalStorage.open(file.accessKey!, "r");
|
||||||
FILE_TYPE_BROWSERSAFE.includes(file.type)
|
}
|
||||||
? file.type
|
|
||||||
: "application/octet-stream",
|
// We can let Koa evaluate conditionals by setting
|
||||||
);
|
// the status to 200, along with the lastModified
|
||||||
ctx.set("Cache-Control", "max-age=31536000, immutable");
|
// and etag properties, then checking ctx.fresh.
|
||||||
ctx.set("Content-Disposition", contentDisposition("inline", file.name));
|
// Additionally, Range is ignored if a conditional GET would
|
||||||
|
// result in a 304 response, so we can return early here.
|
||||||
|
|
||||||
|
ctx.status = 200;
|
||||||
|
ctx.etag = file.md5;
|
||||||
|
ctx.lastModified = file.createdAt;
|
||||||
|
|
||||||
|
// When doing a conditional request, we MUST return a "Cache-Control" header
|
||||||
|
// if a normal 200 response would have included.
|
||||||
|
ctx.set("Cache-Control", "max-age=31536000, immutable");
|
||||||
|
|
||||||
|
if (ctx.fresh) {
|
||||||
|
ctx.status = 304;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.length = file.size;
|
||||||
|
ctx.set("Content-Disposition", contentDisposition("inline", filename));
|
||||||
|
ctx.set("Content-Type", contentType);
|
||||||
|
|
||||||
|
const ranges = ByteRangeReadable.parseByteRanges(
|
||||||
|
BigInt(file.size),
|
||||||
|
MAX_BYTE_RANGES,
|
||||||
|
ctx.headers["range"],
|
||||||
|
);
|
||||||
|
const readable =
|
||||||
|
ranges.length === 0
|
||||||
|
? fileHandle.createReadStream()
|
||||||
|
: new ByteRangeReadable(
|
||||||
|
fileHandle.fd,
|
||||||
|
BigInt(file.size),
|
||||||
|
ranges,
|
||||||
|
contentType,
|
||||||
|
);
|
||||||
|
readable.on("error", commonReadableHandlerGenerator(ctx));
|
||||||
|
ctx.body = readable;
|
||||||
|
|
||||||
|
if (ranges.length === 0) {
|
||||||
|
ctx.set("Accept-Ranges", "bytes");
|
||||||
|
} else {
|
||||||
|
ctx.status = 206;
|
||||||
|
ctx.length = readable.size;
|
||||||
|
readable.on("close", async () => {
|
||||||
|
await fileHandle.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ranges.length === 1) {
|
||||||
|
ctx.set(
|
||||||
|
"Content-Range",
|
||||||
|
`bytes ${ranges[0].start}-${ranges[0].end}/${file.size}`,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ctx.set(
|
||||||
|
"Content-Type",
|
||||||
|
`multipart/byteranges; boundary=${readable.boundary}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import * as fs from "node:fs";
|
import * as fs from "node:fs";
|
||||||
|
import * as fsPromises from "node:fs/promises";
|
||||||
import * as Path from "node:path";
|
import * as Path from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import { dirname } from "node:path";
|
import { dirname } from "node:path";
|
||||||
|
@ -13,6 +14,10 @@ export class InternalStorage {
|
||||||
public static resolvePath = (key: string) =>
|
public static resolvePath = (key: string) =>
|
||||||
Path.resolve(InternalStorage.path, key);
|
Path.resolve(InternalStorage.path, key);
|
||||||
|
|
||||||
|
public static open(key: string, flags: string) {
|
||||||
|
return fsPromises.open(InternalStorage.resolvePath(key), flags);
|
||||||
|
}
|
||||||
|
|
||||||
public static read(key: string) {
|
public static read(key: string) {
|
||||||
return fs.createReadStream(InternalStorage.resolvePath(key));
|
return fs.createReadStream(InternalStorage.resolvePath(key));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,13 @@ async function getRelMeLinks(url: string): Promise<string[]> {
|
||||||
try {
|
try {
|
||||||
const html = await getHtml(url);
|
const html = await getHtml(url);
|
||||||
const dom = new JSDOM(html);
|
const dom = new JSDOM(html);
|
||||||
const relMeLinks = [
|
const allLinks = [...dom.window.document.querySelectorAll("a, link")];
|
||||||
...dom.window.document.querySelectorAll("a[rel='me']"),
|
const relMeLinks = allLinks
|
||||||
...dom.window.document.querySelectorAll("link[rel='me']"),
|
.filter((a) => {
|
||||||
].map((a) => (a as HTMLAnchorElement | HTMLLinkElement).href);
|
const relAttribute = a.getAttribute("rel");
|
||||||
|
return relAttribute ? relAttribute.split(" ").includes("me") : false;
|
||||||
|
})
|
||||||
|
.map((a) => (a as HTMLAnchorElement | HTMLLinkElement).href);
|
||||||
return relMeLinks;
|
return relMeLinks;
|
||||||
} catch {
|
} catch {
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -172,7 +172,7 @@ export default async (
|
||||||
// rome-ignore lint/suspicious/noAsyncPromiseExecutor: FIXME
|
// rome-ignore lint/suspicious/noAsyncPromiseExecutor: FIXME
|
||||||
new Promise<Note>(async (res, rej) => {
|
new Promise<Note>(async (res, rej) => {
|
||||||
const dontFederateInitially =
|
const dontFederateInitially =
|
||||||
data.localOnly || data.visibility === "hidden";
|
data.localOnly || data.visibility?.startsWith("hidden");
|
||||||
|
|
||||||
// If you reply outside the channel, match the scope of the target.
|
// If you reply outside the channel, match the scope of the target.
|
||||||
// TODO (I think it's a process that could be done on the client side, but it's server side for now.)
|
// TODO (I think it's a process that could be done on the client side, but it's server side for now.)
|
||||||
|
@ -206,7 +206,8 @@ export default async (
|
||||||
if (data.channel != null) data.visibility = "public";
|
if (data.channel != null) data.visibility = "public";
|
||||||
if (data.channel != null) data.visibleUsers = [];
|
if (data.channel != null) data.visibleUsers = [];
|
||||||
if (data.channel != null) data.localOnly = true;
|
if (data.channel != null) data.localOnly = true;
|
||||||
if (data.visibility === "hidden") data.visibility = "public";
|
if (data.visibility.startsWith("hidden"))
|
||||||
|
data.visibility = data.visibility.slice(6);
|
||||||
|
|
||||||
// enforce silent clients on server
|
// enforce silent clients on server
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "pnpm vite build --watch --mode development",
|
"watch": "pnpm vite build --watch --mode development",
|
||||||
"build": "pnpm vite build",
|
"build": "pnpm vite build",
|
||||||
|
"build:debug": "pnpm run build",
|
||||||
"lint": "pnpm rome check **/*.ts --apply && pnpm run lint:vue",
|
"lint": "pnpm rome check **/*.ts --apply && pnpm run lint:vue",
|
||||||
"lint:vue": "pnpm paralint --ext .vue --fix '**/*.vue' --cache",
|
"lint:vue": "pnpm paralint --ext .vue --fix '**/*.vue' --cache",
|
||||||
"format": "pnpm rome format * --write && pnpm prettier --write '**/*.{scss,vue}' --cache --cache-strategy metadata"
|
"format": "pnpm rome format * --write && pnpm prettier --write '**/*.{scss,vue}' --cache --cache-strategy metadata"
|
||||||
|
|
|
@ -132,7 +132,7 @@ export default defineComponent({
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
> *:not(:last-child) {
|
&:not(.date-separated-list-nogap) > *:not(:last-child) {
|
||||||
margin-bottom: var(--margin);
|
margin-bottom: var(--margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,9 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { i18n } from "@/i18n";
|
import { i18n } from "@/i18n";
|
||||||
|
import { useRouter } from "@/router";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
q: string;
|
q: string;
|
||||||
|
@ -19,10 +22,7 @@ const props = defineProps<{
|
||||||
const query = ref(props.q);
|
const query = ref(props.q);
|
||||||
|
|
||||||
const search = () => {
|
const search = () => {
|
||||||
window.open(
|
router.push(`/search/${query.value}`);
|
||||||
`https://search.annoyingorange.xyz/search?q=${query.value}`,
|
|
||||||
"_blank",
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -45,14 +45,17 @@ const instance = props.instance ?? {
|
||||||
const commonNames = new Map<string, string>([
|
const commonNames = new Map<string, string>([
|
||||||
["birdsitelive", "BirdsiteLIVE"],
|
["birdsitelive", "BirdsiteLIVE"],
|
||||||
["bookwyrm", "BookWyrm"],
|
["bookwyrm", "BookWyrm"],
|
||||||
|
["bridgy-fed", "Bridgy Fed"],
|
||||||
["foundkey", "FoundKey"],
|
["foundkey", "FoundKey"],
|
||||||
["gnusocial", "GNU social"],
|
["gnusocial", "GNU Social"],
|
||||||
["gotosocial", "GoToSocial"],
|
["gotosocial", "GoToSocial"],
|
||||||
["microblogpub", "microblog.pub"],
|
["microblogpub", "microblog.pub"],
|
||||||
["nextcloud social", "Nextcloud Social"],
|
["nextcloud social", "Nextcloud Social"],
|
||||||
["peertube", "PeerTube"],
|
["peertube", "PeerTube"],
|
||||||
["snac", "snac"],
|
["snac", "snac"],
|
||||||
|
["snac2", "snac2"],
|
||||||
["takahe", "Takahē"],
|
["takahe", "Takahē"],
|
||||||
|
["wafrn", "WAFRN"],
|
||||||
["wordpress", "WordPress"],
|
["wordpress", "WordPress"],
|
||||||
["writefreely", "WriteFreely"],
|
["writefreely", "WriteFreely"],
|
||||||
["wxwclub", "wxwClub"],
|
["wxwclub", "wxwClub"],
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
:aria-label="media.comment"
|
:aria-label="media.comment"
|
||||||
preload="none"
|
preload="none"
|
||||||
controls
|
controls
|
||||||
|
playsinline
|
||||||
@contextmenu.stop
|
@contextmenu.stop
|
||||||
>
|
>
|
||||||
<source :src="media.url" :type="mediaType" />
|
<source :src="media.url" :type="mediaType" />
|
||||||
|
|
|
@ -106,31 +106,26 @@
|
||||||
:text="'@namekuji@firefish.social (Backend)'"
|
:text="'@namekuji@firefish.social (Backend)'"
|
||||||
/></FormLink>
|
/></FormLink>
|
||||||
<FormLink to="/@dev@post.naskya.net"
|
<FormLink to="/@dev@post.naskya.net"
|
||||||
><Mfm :text="'@dev@post.naskya.net (Backend)'"
|
><Mfm :text="'@dev@post.naskya.net (Fullstack)'"
|
||||||
/></FormLink>
|
/></FormLink>
|
||||||
<FormLink to="/@panos@firefish.social"
|
<FormLink to="/@panos@firefish.social"
|
||||||
><Mfm
|
><Mfm
|
||||||
:text="'@panos@firefish.social (Project Coordinator)'"
|
:text="'@panos@firefish.social (Project Coordinator)'"
|
||||||
/></FormLink>
|
/></FormLink>
|
||||||
<FormLink
|
<FormLink to="/@blackspike@mastodon.cloud"
|
||||||
to="https://www.youtube.com/c/Henkiwashere"
|
><Mfm
|
||||||
external
|
:text="'@blackspike@mastodon.cloud (Logo Design)'"
|
||||||
>Henki (error images artist)</FormLink
|
/></FormLink>
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<template #caption
|
<h3
|
||||||
><MkLink
|
style="
|
||||||
url="https://git.joinfirefish.org/firefish/firefish/activity"
|
font-weight: 700;
|
||||||
>{{
|
margin: 1.5em 0 16px;
|
||||||
i18n.ts._aboutFirefish.allContributors
|
font-size: 1em;
|
||||||
}}</MkLink
|
"
|
||||||
></template
|
|
||||||
>
|
>
|
||||||
</FormSection>
|
{{ i18n.ts._aboutFirefish.misskeyContributors }}
|
||||||
<FormSection>
|
</h3>
|
||||||
<template #label>{{
|
|
||||||
i18n.ts._aboutFirefish.originalMisskeyContributors
|
|
||||||
}}</template>
|
|
||||||
<div class="_formLinks">
|
<div class="_formLinks">
|
||||||
<FormLink to="/@syuilo@misskey.io"
|
<FormLink to="/@syuilo@misskey.io"
|
||||||
><Mfm :text="'@syuilo@misskey.io'"
|
><Mfm :text="'@syuilo@misskey.io'"
|
||||||
|
@ -151,6 +146,12 @@
|
||||||
><Mfm :text="'@robflop@misskey.io'"
|
><Mfm :text="'@robflop@misskey.io'"
|
||||||
/></FormLink>
|
/></FormLink>
|
||||||
</div>
|
</div>
|
||||||
|
<h3>
|
||||||
|
<MkLink
|
||||||
|
url="https://git.joinfirefish.org/firefish/firefish/activity"
|
||||||
|
>{{ i18n.ts._aboutFirefish.allContributors }}
|
||||||
|
</MkLink>
|
||||||
|
</h3>
|
||||||
</FormSection>
|
</FormSection>
|
||||||
<FormSection>
|
<FormSection>
|
||||||
<template #label
|
<template #label
|
||||||
|
|
|
@ -218,6 +218,7 @@ definePageMetadata(
|
||||||
> .users {
|
> .users {
|
||||||
> .inputs {
|
> .inputs {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
gap: 0.4rem;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
|
|
|
@ -5,14 +5,15 @@
|
||||||
/></template>
|
/></template>
|
||||||
<MkSpacer :content-max="800">
|
<MkSpacer :content-max="800">
|
||||||
<MkPagination
|
<MkPagination
|
||||||
|
ref="paginationEl"
|
||||||
v-slot="{ items }"
|
v-slot="{ items }"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
class="ruryvtyk _content"
|
class="ruryvtyk _gaps_m"
|
||||||
>
|
>
|
||||||
<section
|
<section
|
||||||
v-for="(announcement, i) in items"
|
v-for="announcement in items"
|
||||||
:key="announcement.id"
|
:key="announcement.id"
|
||||||
class="_card announcement"
|
class="announcement _panel"
|
||||||
>
|
>
|
||||||
<div class="_title">
|
<div class="_title">
|
||||||
<span v-if="$i && !announcement.isRead">🆕 </span>
|
<span v-if="$i && !announcement.isRead">🆕 </span>
|
||||||
|
@ -31,7 +32,7 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="$i && !announcement.isRead" class="_footer">
|
<div v-if="$i && !announcement.isRead" class="_footer">
|
||||||
<MkButton primary @click="read(items, announcement, i)"
|
<MkButton primary @click="read(announcement.id)"
|
||||||
><i class="ph-check ph-bold ph-lg"></i>
|
><i class="ph-check ph-bold ph-lg"></i>
|
||||||
{{ i18n.ts.gotIt }}</MkButton
|
{{ i18n.ts.gotIt }}</MkButton
|
||||||
>
|
>
|
||||||
|
@ -43,7 +44,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {} from "vue";
|
import { ref } from "vue";
|
||||||
import MkPagination from "@/components/MkPagination.vue";
|
import MkPagination from "@/components/MkPagination.vue";
|
||||||
import MkButton from "@/components/MkButton.vue";
|
import MkButton from "@/components/MkButton.vue";
|
||||||
import * as os from "@/os";
|
import * as os from "@/os";
|
||||||
|
@ -55,13 +56,14 @@ const pagination = {
|
||||||
limit: 10,
|
limit: 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: これは実質的に親コンポーネントから子コンポーネントのプロパティを変更してるのでなんとかしたい
|
const paginationEl = ref<InstanceType<typeof MkPagination>>();
|
||||||
function read(items, announcement, i) {
|
function read(id: string) {
|
||||||
items[i] = {
|
if (!paginationEl.value) return;
|
||||||
...announcement,
|
paginationEl.value.updateItem(id, (announcement) => {
|
||||||
isRead: true,
|
announcement.isRead = true;
|
||||||
};
|
return announcement;
|
||||||
os.api("i/read-announcement", { announcementId: announcement.id });
|
});
|
||||||
|
os.api("i/read-announcement", { announcementId: id });
|
||||||
}
|
}
|
||||||
|
|
||||||
const headerActions = $computed(() => []);
|
const headerActions = $computed(() => []);
|
||||||
|
|
|
@ -19,21 +19,21 @@ import { i18n } from "@/i18n";
|
||||||
|
|
||||||
const paginationForLocal = {
|
const paginationForLocal = {
|
||||||
endpoint: "notes/featured" as const,
|
endpoint: "notes/featured" as const,
|
||||||
limit: 10,
|
limit: 15,
|
||||||
origin: "local",
|
origin: "local",
|
||||||
offsetMode: true,
|
offsetMode: true,
|
||||||
params: {
|
params: {
|
||||||
days: 14,
|
days: 5,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const paginationForRemote = {
|
const paginationForRemote = {
|
||||||
endpoint: "notes/featured" as const,
|
endpoint: "notes/featured" as const,
|
||||||
limit: 20,
|
limit: 15,
|
||||||
offsetMode: true,
|
offsetMode: true,
|
||||||
params: {
|
params: {
|
||||||
origin: "remote",
|
origin: "remote",
|
||||||
days: 7,
|
days: 5,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
:threshold="10"
|
:threshold="10"
|
||||||
:centeredSlides="true"
|
:centeredSlides="true"
|
||||||
:modules="[Virtual]"
|
:modules="[Virtual]"
|
||||||
:space-between="20"
|
:space-between="30"
|
||||||
:virtual="true"
|
:virtual="true"
|
||||||
:allow-touch-move="
|
:allow-touch-move="
|
||||||
defaultStore.state.swipeOnMobile &&
|
defaultStore.state.swipeOnMobile &&
|
||||||
|
|
|
@ -130,6 +130,12 @@
|
||||||
@update:modelValue="save()"
|
@update:modelValue="save()"
|
||||||
>{{ i18n.ts.keepCw }}</FormSwitch
|
>{{ i18n.ts.keepCw }}</FormSwitch
|
||||||
>
|
>
|
||||||
|
<FormSwitch
|
||||||
|
v-model="addRe"
|
||||||
|
class="_formBlock"
|
||||||
|
@update:modelValue="save()"
|
||||||
|
>{{ i18n.ts.addRe }}
|
||||||
|
</FormSwitch>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -164,6 +170,7 @@ let rememberNoteVisibility = $computed(
|
||||||
defaultStore.makeGetterSetter("rememberNoteVisibility"),
|
defaultStore.makeGetterSetter("rememberNoteVisibility"),
|
||||||
);
|
);
|
||||||
let keepCw = $computed(defaultStore.makeGetterSetter("keepCw"));
|
let keepCw = $computed(defaultStore.makeGetterSetter("keepCw"));
|
||||||
|
let addRe = $computed(defaultStore.makeGetterSetter("addRe"));
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
os.api("i/update", {
|
os.api("i/update", {
|
||||||
|
|
|
@ -127,8 +127,8 @@
|
||||||
</FormFolder>
|
</FormFolder>
|
||||||
<template #caption>{{
|
<template #caption>{{
|
||||||
i18n.t("_profile.metadataDescription", {
|
i18n.t("_profile.metadataDescription", {
|
||||||
a: "\<code\>\<a\>\</code\>",
|
a: "\<a\>",
|
||||||
l: "\<code\>\<a\>\</code\>",
|
l: "\<a\>",
|
||||||
rel: `rel="me" href="https://${host}/@${$i.username}"`,
|
rel: `rel="me" href="https://${host}/@${$i.username}"`,
|
||||||
})
|
})
|
||||||
}}</template>
|
}}</template>
|
||||||
|
|
|
@ -219,7 +219,7 @@
|
||||||
{{ i18n.ts.sendModMail }}</FormButton
|
{{ i18n.ts.sendModMail }}</FormButton
|
||||||
>
|
>
|
||||||
<FormButton
|
<FormButton
|
||||||
v-if="$i.isAdmin"
|
v-if="user.host == null && $i.isAdmin"
|
||||||
inline
|
inline
|
||||||
danger
|
danger
|
||||||
@click="delete2fa"
|
@click="delete2fa"
|
||||||
|
@ -227,7 +227,7 @@
|
||||||
{{ i18n.ts.delete2fa }}</FormButton
|
{{ i18n.ts.delete2fa }}</FormButton
|
||||||
>
|
>
|
||||||
<FormButton
|
<FormButton
|
||||||
v-if="$i.isAdmin"
|
v-if="user.host == null && $i.isAdmin"
|
||||||
inline
|
inline
|
||||||
danger
|
danger
|
||||||
@click="deletePasskeys"
|
@click="deletePasskeys"
|
||||||
|
|
|
@ -87,17 +87,13 @@
|
||||||
v-if="user.isAdmin"
|
v-if="user.isAdmin"
|
||||||
v-tooltip.noDelay="i18n.ts.isAdmin"
|
v-tooltip.noDelay="i18n.ts.isAdmin"
|
||||||
style="color: var(--badge)"
|
style="color: var(--badge)"
|
||||||
><i
|
><i class="ph-crown ph-bold ph-lg"></i
|
||||||
class="ph-bookmark-simple ph-fill ph-lg"
|
|
||||||
></i
|
|
||||||
></span>
|
></span>
|
||||||
<span
|
<span
|
||||||
v-if="!user.isAdmin && user.isModerator"
|
v-if="!user.isAdmin && user.isModerator"
|
||||||
v-tooltip.noDelay="i18n.ts.isModerator"
|
v-tooltip.noDelay="i18n.ts.isModerator"
|
||||||
style="color: var(--badge)"
|
style="color: var(--badge)"
|
||||||
><i
|
><i class="ph-gavel ph-bold ph-lg"></i
|
||||||
class="ph-bookmark-simple ph-bold ph-lg"
|
|
||||||
></i
|
|
||||||
></span>
|
></span>
|
||||||
<span
|
<span
|
||||||
v-if="user.isLocked"
|
v-if="user.isLocked"
|
||||||
|
@ -176,9 +172,7 @@
|
||||||
v-if="user.isAdmin"
|
v-if="user.isAdmin"
|
||||||
v-tooltip.noDelay="i18n.ts.isAdmin"
|
v-tooltip.noDelay="i18n.ts.isAdmin"
|
||||||
style="color: var(--badge)"
|
style="color: var(--badge)"
|
||||||
><i
|
><i class="ph-crown ph-bold ph-lg"></i
|
||||||
class="ph-bookmark-simple ph-fill ph-lg"
|
|
||||||
></i
|
|
||||||
></span>
|
></span>
|
||||||
<span
|
<span
|
||||||
v-if="!user.isAdmin && user.isModerator"
|
v-if="!user.isAdmin && user.isModerator"
|
||||||
|
@ -187,9 +181,7 @@
|
||||||
color: var(--badge);
|
color: var(--badge);
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
"
|
"
|
||||||
><i
|
><i class="ph-gavel ph-bold ph-lg"></i
|
||||||
class="ph-bookmark-simple ph-bold ph-lg"
|
|
||||||
></i
|
|
||||||
></span>
|
></span>
|
||||||
<span
|
<span
|
||||||
v-if="user.isLocked"
|
v-if="user.isLocked"
|
||||||
|
|
|
@ -46,6 +46,8 @@ html {
|
||||||
tab-size: 2;
|
tab-size: 2;
|
||||||
scroll-padding: 60px;
|
scroll-padding: 60px;
|
||||||
overflow-x: clip;
|
overflow-x: clip;
|
||||||
|
text-size-adjust: none;
|
||||||
|
-webkit-text-size-adjust: none;
|
||||||
|
|
||||||
&.useCJKFont {
|
&.useCJKFont {
|
||||||
font-family: "Hiragino Maru Gothic Pro", "BIZ UDGothic", Roboto,
|
font-family: "Hiragino Maru Gothic Pro", "BIZ UDGothic", Roboto,
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
"types": "./built/index.d.ts",
|
"types": "./built/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "pnpm swc src -d built -D",
|
"build": "pnpm swc src -d built -D",
|
||||||
|
"build:debug": "pnpm swc src -d built -s -D",
|
||||||
"render": "pnpm run build && pnpm run api && pnpm run api-prod && cp temp/firefish-js.api.json etc/ && pnpm run api-doc",
|
"render": "pnpm run build && pnpm run api && pnpm run api-prod && cp temp/firefish-js.api.json etc/ && pnpm run api-doc",
|
||||||
"tsd": "tsc && tsd",
|
"tsd": "tsc && tsd",
|
||||||
"api": "pnpm api-extractor run --local --verbose",
|
"api": "pnpm api-extractor run --local --verbose",
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"typings": "./lib/src/index.d.ts",
|
"typings": "./lib/src/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc -p ./",
|
"build": "tsc -p ./",
|
||||||
|
"build:debug": "pnpm run build",
|
||||||
"lint": "pnpm rome check **/*.ts --apply",
|
"lint": "pnpm rome check **/*.ts --apply",
|
||||||
"format": "pnpm rome format --write src/**/*.ts",
|
"format": "pnpm rome format --write src/**/*.ts",
|
||||||
"doc": "typedoc --out ../docs ./src",
|
"doc": "typedoc --out ../docs ./src",
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack",
|
"build": "webpack",
|
||||||
|
"build:debug": "pnpm run build",
|
||||||
"watch": "pnpm swc src -d built -D -w",
|
"watch": "pnpm swc src -d built -D -w",
|
||||||
"lint": "pnpm rome check **/*.ts --apply",
|
"lint": "pnpm rome check **/*.ts --apply",
|
||||||
"format": "pnpm rome format * --write"
|
"format": "pnpm rome format * --write"
|
||||||
|
|
82
patrons.json
82
patrons.json
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"patrons": [
|
"patrons": [
|
||||||
"@atomicpoet@calckey.social",
|
"@atomicpoet@firefish.social",
|
||||||
"@shoq@mastodon.social",
|
"@shoq@mastodon.social",
|
||||||
"@pikadude@erisly.social",
|
"@pikadude@erisly.social",
|
||||||
"@sage@stop.voring.me",
|
"@sage@stop.voring.me",
|
||||||
"@sky@therian.club",
|
"@sky@therian.club",
|
||||||
"@panos@electricrequiem.com",
|
"@panos@electricrequiem.com",
|
||||||
"@redhunt07@www.foxyhole.io",
|
"@redhunt07@www.foxyhole.io",
|
||||||
"@griff@calckey.social",
|
"@griff@firefish.social",
|
||||||
"@cafkafk@ck.cafkafk.com",
|
"@cafkafk@ck.cafkafk.com",
|
||||||
"@privateger@plasmatrap.com",
|
"@privateger@plasmatrap.com",
|
||||||
"@effye@toot.thoughtworks.com",
|
"@effye@toot.thoughtworks.com",
|
||||||
|
@ -17,56 +17,56 @@
|
||||||
"@topher@mastodon.online",
|
"@topher@mastodon.online",
|
||||||
"@hanicef@stop.voring.me",
|
"@hanicef@stop.voring.me",
|
||||||
"@nmkj@calckey.jp",
|
"@nmkj@calckey.jp",
|
||||||
"@unattributed@calckey.social",
|
"@unattributed@firefish.social",
|
||||||
"@cody@misskey.codingneko.com",
|
"@cody@misskey.codingneko.com",
|
||||||
"@kate@blahaj.zone",
|
"@kate@blahaj.zone",
|
||||||
"@emtk@mkkey.net",
|
"@emtk@mkkey.net",
|
||||||
"@jovikowi@calckey.social",
|
"@jovikowi@firefish.social",
|
||||||
"@padraig@calckey.social",
|
"@padraig@firefish.social",
|
||||||
"@pancakes@cats.city",
|
"@pancakes@cats.city",
|
||||||
"@theresmiling@calckey.social",
|
"@theresmiling@firefish.social",
|
||||||
"@kristian@calckey.social",
|
"@kristian@firefish.social",
|
||||||
"@jo@blahaj.zone",
|
"@jo@blahaj.zone",
|
||||||
"@narF@calckey.social",
|
"@narF@firefish.social",
|
||||||
"@AlderForrest@raining.anvil.top",
|
"@AlderForrest@raining.anvil.top",
|
||||||
"@box464@calckey.social",
|
"@box464@firefish.social",
|
||||||
"@MariaTheMartian@calckey.social",
|
"@MariaTheMartian@firefish.social",
|
||||||
"@nisemikol@calckey.social",
|
"@nisemikol@firefish.social",
|
||||||
"@smallpatatas@blahaj.zone",
|
"@smallpatatas@blahaj.zone",
|
||||||
"@bayra@stop.voring.me",
|
"@bayra@stop.voring.me",
|
||||||
"@frost@wolfdo.gg",
|
"@frost@wolfdo.gg",
|
||||||
"@joebiden@fuckgov.org",
|
"@joebiden@fuckgov.org",
|
||||||
"@nyaa@calckey.social",
|
"@nyaa@firefish.social",
|
||||||
"@Dan@calckey.social",
|
"@Dan@firefish.social",
|
||||||
"@dana@calckey.social",
|
"@dana@firefish.social",
|
||||||
"@Jdreben@calckey.social",
|
"@Jdreben@firefish.social",
|
||||||
"@natalie@prismst.one",
|
"@natalie@prismst.one",
|
||||||
"@KelsonV@wandering.shop",
|
"@KelsonV@wandering.shop",
|
||||||
"@breakfastmtn@calckey.social",
|
"@breakfastmtn@firefish.social",
|
||||||
"@richardazia@mastodon.social",
|
"@richardazia@mastodon.social",
|
||||||
"@joestone@calckey.social",
|
"@joestone@firefish.social",
|
||||||
"@aj@calckey.social",
|
"@aj@firefish.social",
|
||||||
"@zepfanman@ramblingreaders.org",
|
"@zepfanman@ramblingreaders.org",
|
||||||
"@kimby@stop.voring.me",
|
"@kimby@stop.voring.me",
|
||||||
"@fyrfli@fyrfli.social",
|
"@fyrfli@fyrfli.social",
|
||||||
"@riversidebryan@firefish.lgbt",
|
"@riversidebryan@firefish.lgbt",
|
||||||
"@aRubes@sloth.run",
|
"@aRubes@sloth.run",
|
||||||
"@andreasdotorg@calckey.social",
|
"@andreasdotorg@firefish.social",
|
||||||
"@ozzy@calckey.online",
|
"@ozzy@calckey.online",
|
||||||
"@leni@windycity.style",
|
"@leni@windycity.style",
|
||||||
"@mhzmodels@calckey.art",
|
"@mhzmodels@calckey.art",
|
||||||
"@ReflexVE@calckey.social",
|
"@ReflexVE@firefish.social",
|
||||||
"@mark@calckey.social",
|
"@mark@firefish.social",
|
||||||
"@skyizwhite@himagine.club",
|
"@skyizwhite@himagine.club",
|
||||||
"@Uwu@calckey.social",
|
"@Uwu@firefish.social",
|
||||||
"@jGoose@calckey.social",
|
"@jGoose@firefish.social",
|
||||||
"@kunev@blewsky.social",
|
"@kunev@blewsky.social",
|
||||||
"@Simoto@electricrequiem.com",
|
"@Simoto@electricrequiem.com",
|
||||||
"@Evoterra@calckey.social",
|
"@Evoterra@firefish.social",
|
||||||
"@LauraLangdon@procial.tchncs.de",
|
"@LauraLangdon@procial.tchncs.de",
|
||||||
"@mho@social.heise.de",
|
"@mho@social.heise.de",
|
||||||
"@richardazia@calckey.social",
|
"@richardazia@firefish.social",
|
||||||
"@blues653@calckey.social",
|
"@blues653@firefish.social",
|
||||||
"@rafale_blue@calc.04.si",
|
"@rafale_blue@calc.04.si",
|
||||||
"@esm@lethallava.land",
|
"@esm@lethallava.land",
|
||||||
"@vmstan@vmst.io",
|
"@vmstan@vmst.io",
|
||||||
|
@ -74,33 +74,33 @@
|
||||||
"@renere@distance.blue",
|
"@renere@distance.blue",
|
||||||
"@theking@kitsunes.club",
|
"@theking@kitsunes.club",
|
||||||
"@toof@fedi.toofie.net",
|
"@toof@fedi.toofie.net",
|
||||||
"@Punko@calckey.social",
|
"@Punko@firefish.social",
|
||||||
"@joesbrat67@calckey.social",
|
"@joesbrat67@firefish.social",
|
||||||
"@arth@calckey.social",
|
"@arth@firefish.social",
|
||||||
"@octofloofy@ck.octofloofy.ink",
|
"@octofloofy@ck.octofloofy.ink",
|
||||||
"@pauliehedron@infosec.town",
|
"@pauliehedron@infosec.town",
|
||||||
"@soulthunk@lethallava.land",
|
"@soulthunk@lethallava.land",
|
||||||
"@bumble@ibe.social",
|
"@bumble@ibe.social",
|
||||||
"@DarrenNevares@calckey.social",
|
"@DarrenNevares@firefish.social",
|
||||||
"@irfan@calckey.social",
|
"@irfan@firefish.social",
|
||||||
"@dvd@dvd.chat",
|
"@dvd@dvd.chat",
|
||||||
"@charlie2alpha@electricrequiem.com",
|
"@charlie2alpha@electricrequiem.com",
|
||||||
"@arndot@layer8.space",
|
"@arndot@layer8.space",
|
||||||
"@ryan@c.ryanccn.dev",
|
"@ryan@c.ryanccn.dev",
|
||||||
"@lapastora_deprova@calckey.social",
|
"@lapastora_deprova@firefish.social",
|
||||||
"@rameez@calckey.social",
|
"@rameez@firefish.social",
|
||||||
"@dracoling@firetribe.org",
|
"@dracoling@firetribe.org",
|
||||||
"@Space6host@calckey.social",
|
"@Space6host@firefish.social",
|
||||||
"@zakalwe@plasmatrap.com",
|
"@zakalwe@plasmatrap.com",
|
||||||
"@seasicksailor@calckey.social",
|
"@seasicksailor@firefish.social",
|
||||||
"@geerue@calckey.social",
|
"@geerue@firefish.social",
|
||||||
"@WXFanatic@m.ai6yr.org",
|
"@WXFanatic@m.ai6yr.org",
|
||||||
"@Hunkabilly@calckey.world",
|
"@Hunkabilly@calckey.world",
|
||||||
"@samleegray@calckey.social",
|
"@samleegray@firefish.social",
|
||||||
"@schwarzewald@kodow.net",
|
"@schwarzewald@kodow.net",
|
||||||
"@Conatusprinciple@calckey.social",
|
"@Conatusprinciple@firefish.social",
|
||||||
"@183231bcb@firefish.lgbt",
|
"@183231bcb@firefish.lgbt",
|
||||||
"@wiase@calckey.social",
|
"@wiase@firefish.social",
|
||||||
"@leonieke@vitaulium.nl",
|
"@leonieke@vitaulium.nl",
|
||||||
"@soulfire@wackywolf.xyz",
|
"@soulfire@wackywolf.xyz",
|
||||||
"@elbullazul@pub.elbullazul.com",
|
"@elbullazul@pub.elbullazul.com",
|
||||||
|
@ -110,8 +110,8 @@
|
||||||
"@hryggrbyr@ibe.social"
|
"@hryggrbyr@ibe.social"
|
||||||
],
|
],
|
||||||
"sponsors": [
|
"sponsors": [
|
||||||
"@atomicpoet@calckey.social",
|
"@atomicpoet@firefish.social",
|
||||||
"@unattributed@calckey.social",
|
"@unattributed@firefish.social",
|
||||||
"@jtbennett@noc.social",
|
"@jtbennett@noc.social",
|
||||||
"\nInterkosmos Link"
|
"\nInterkosmos Link"
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in a new issue