Merge branch 'develop' into refactor/queue
4
.gitignore
vendored
|
@ -62,3 +62,7 @@ yarn*
|
|||
# Nix Development shell items
|
||||
.devenv
|
||||
.direnv
|
||||
|
||||
# Cargo cache for Docker
|
||||
/.cargo-cache
|
||||
/.cargo-target
|
||||
|
|
9706
CHANGELOG.md
|
@ -3,6 +3,7 @@ FROM node:19-alpine as build
|
|||
WORKDIR /calckey
|
||||
|
||||
# Install compilation dependencies
|
||||
RUN apk update
|
||||
RUN apk add --no-cache --no-progress git alpine-sdk python3 rust cargo vips
|
||||
|
||||
# Copy only the dependency-related files first, to cache efficiently
|
||||
|
@ -35,7 +36,7 @@ FROM node:19-alpine
|
|||
WORKDIR /calckey
|
||||
|
||||
# Install runtime dependencies
|
||||
RUN apk add --no-cache --no-progress tini ffmpeg vips-dev zip unzip
|
||||
RUN apk add --no-cache --no-progress tini ffmpeg vips-dev zip unzip rust cargo
|
||||
|
||||
COPY . ./
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ If you have access to a server that supports one of the sources below, I recomme
|
|||
|
||||
### 🏗️ Build dependencies
|
||||
|
||||
- 🦀 [Rust toolchain](https://www.rust-lang.org/)
|
||||
- 🦀 At least [Rust](https://www.rust-lang.org/) v1.65.0
|
||||
- 🦬 C/C++ compiler & build tools
|
||||
- `build-essential` on Debian/Ubuntu Linux
|
||||
- `base-devel` on Arch Linux
|
||||
|
|
|
@ -8,7 +8,9 @@ services:
|
|||
depends_on:
|
||||
- db
|
||||
- redis
|
||||
- meilisearch
|
||||
### Uncomment one of the following to use a search engine
|
||||
# - meilisearch
|
||||
# - sonic
|
||||
ports:
|
||||
- "3000:3000"
|
||||
networks:
|
||||
|
@ -17,6 +19,8 @@ services:
|
|||
environment:
|
||||
NODE_ENV: production
|
||||
volumes:
|
||||
- ./.cargo-cache:/root/.cargo
|
||||
- ./.cargo-target:/calckey/packages/backend/native-utils/target
|
||||
- ./files:/calckey/files
|
||||
- ./.config:/calckey/.config:ro
|
||||
|
||||
|
|
112
gulpfile.js
|
@ -2,66 +2,98 @@
|
|||
* Gulp tasks
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const gulp = require('gulp');
|
||||
const replace = require('gulp-replace');
|
||||
const terser = require('gulp-terser');
|
||||
const cssnano = require('gulp-cssnano');
|
||||
const fs = require("fs");
|
||||
const gulp = require("gulp");
|
||||
const replace = require("gulp-replace");
|
||||
const terser = require("gulp-terser");
|
||||
const cssnano = require("gulp-cssnano");
|
||||
|
||||
const locales = require('./locales');
|
||||
const meta = require('./package.json');
|
||||
const locales = require("./locales");
|
||||
const meta = require("./package.json");
|
||||
|
||||
gulp.task('copy:backend:views', () =>
|
||||
gulp.src('./packages/backend/src/server/web/views/**/*').pipe(gulp.dest('./packages/backend/built/server/web/views'))
|
||||
gulp.task("copy:backend:views", () =>
|
||||
gulp
|
||||
.src("./packages/backend/src/server/web/views/**/*")
|
||||
.pipe(gulp.dest("./packages/backend/built/server/web/views")),
|
||||
);
|
||||
|
||||
|
||||
gulp.task('copy:backend:custom', () =>
|
||||
gulp.src('./custom/assets/**/*').pipe(gulp.dest('./packages/backend/assets/'))
|
||||
gulp.task("copy:backend:custom", () =>
|
||||
gulp
|
||||
.src("./custom/assets/**/*")
|
||||
.pipe(gulp.dest("./packages/backend/assets/")),
|
||||
);
|
||||
|
||||
gulp.task('copy:client:fonts', () =>
|
||||
gulp.src('./packages/client/node_modules/three/examples/fonts/**/*').pipe(gulp.dest('./built/_client_dist_/fonts/'))
|
||||
gulp.task("copy:client:fonts", () =>
|
||||
gulp
|
||||
.src("./packages/client/node_modules/three/examples/fonts/**/*")
|
||||
.pipe(gulp.dest("./built/_client_dist_/fonts/")),
|
||||
);
|
||||
|
||||
gulp.task('copy:client:locales', cb => {
|
||||
fs.mkdirSync('./built/_client_dist_/locales', { recursive: true });
|
||||
gulp.task("copy:client:locales", (cb) => {
|
||||
fs.mkdirSync("./built/_client_dist_/locales", { recursive: true });
|
||||
|
||||
const v = { '_version_': meta.version };
|
||||
const v = { _version_: meta.version };
|
||||
|
||||
for (const [lang, locale] of Object.entries(locales)) {
|
||||
fs.writeFileSync(`./built/_client_dist_/locales/${lang}.${meta.version}.json`, JSON.stringify({ ...locale, ...v }), 'utf-8');
|
||||
fs.writeFileSync(
|
||||
`./built/_client_dist_/locales/${lang}.${meta.version}.json`,
|
||||
JSON.stringify({ ...locale, ...v }),
|
||||
"utf-8",
|
||||
);
|
||||
}
|
||||
|
||||
cb();
|
||||
});
|
||||
|
||||
|
||||
gulp.task('build:backend:script', () => {
|
||||
return gulp.src(['./packages/backend/src/server/web/boot.js', './packages/backend/src/server/web/bios.js', './packages/backend/src/server/web/cli.js'])
|
||||
.pipe(replace('LANGS', JSON.stringify(Object.keys(locales))))
|
||||
.pipe(terser({
|
||||
toplevel: true
|
||||
}))
|
||||
.pipe(gulp.dest('./packages/backend/built/server/web/'));
|
||||
gulp.task("build:backend:script", () => {
|
||||
return gulp
|
||||
.src([
|
||||
"./packages/backend/src/server/web/boot.js",
|
||||
"./packages/backend/src/server/web/bios.js",
|
||||
"./packages/backend/src/server/web/cli.js",
|
||||
])
|
||||
.pipe(replace("LANGS", JSON.stringify(Object.keys(locales))))
|
||||
.pipe(
|
||||
terser({
|
||||
toplevel: true,
|
||||
}),
|
||||
)
|
||||
.pipe(gulp.dest("./packages/backend/built/server/web/"));
|
||||
});
|
||||
|
||||
gulp.task('build:backend:style', () => {
|
||||
return gulp.src(['./packages/backend/src/server/web/style.css', './packages/backend/src/server/web/bios.css', './packages/backend/src/server/web/cli.css'])
|
||||
.pipe(cssnano({
|
||||
zindex: false
|
||||
}))
|
||||
.pipe(gulp.dest('./packages/backend/built/server/web/'));
|
||||
gulp.task("build:backend:style", () => {
|
||||
return gulp
|
||||
.src([
|
||||
"./packages/backend/src/server/web/style.css",
|
||||
"./packages/backend/src/server/web/bios.css",
|
||||
"./packages/backend/src/server/web/cli.css",
|
||||
])
|
||||
.pipe(
|
||||
cssnano({
|
||||
zindex: false,
|
||||
}),
|
||||
)
|
||||
.pipe(gulp.dest("./packages/backend/built/server/web/"));
|
||||
});
|
||||
|
||||
gulp.task('build', gulp.parallel(
|
||||
'copy:client:locales', 'copy:backend:views', 'copy:backend:custom', 'build:backend:script', 'build:backend:style', 'copy:client:fonts'
|
||||
));
|
||||
gulp.task(
|
||||
"build",
|
||||
gulp.parallel(
|
||||
"copy:client:locales",
|
||||
"copy:backend:views",
|
||||
"copy:backend:custom",
|
||||
"build:backend:script",
|
||||
"build:backend:style",
|
||||
"copy:client:fonts",
|
||||
),
|
||||
);
|
||||
|
||||
gulp.task('default', gulp.task('build'));
|
||||
gulp.task("default", gulp.task("build"));
|
||||
|
||||
gulp.task('watch', () => {
|
||||
gulp.watch([
|
||||
'./packages/*/src/**/*',
|
||||
], { ignoreInitial: false }, gulp.task('build'));
|
||||
gulp.task("watch", () => {
|
||||
gulp.watch(
|
||||
["./packages/*/src/**/*"],
|
||||
{ ignoreInitial: false },
|
||||
gulp.task("build"),
|
||||
);
|
||||
});
|
||||
|
|
|
@ -68,3 +68,5 @@ body:
|
|||
options:
|
||||
- label: I agree to follow this project's Contribution Guidelines
|
||||
required: true
|
||||
- label: I have searched the issue tracker for similar issues, and this is not a duplicate.
|
||||
required: true
|
||||
|
|
|
@ -68,3 +68,5 @@ body:
|
|||
options:
|
||||
- label: I agree to follow this project's Contribution Guidelines
|
||||
required: true
|
||||
- label: I have searched the issue tracker for similar requests, and this is not a duplicate.
|
||||
required: true
|
||||
|
|
|
@ -67,7 +67,7 @@ files: "Fitxers"
|
|||
download: "Baixa"
|
||||
driveFileDeleteConfirm: "Segur que vols eliminar el fitxer «{name}»? S'eliminarà de
|
||||
totes les notes que el continguin com a fitxer adjunt."
|
||||
unfollowConfirm: "Segur que vols deixar de seguir {name}?"
|
||||
unfollowConfirm: "Segur que vols deixar de seguir a {name}?"
|
||||
exportRequested: "Has sol·licitat una exportació. Això pot trigar una estona. S'afegirà
|
||||
al teu Disc un cop completada."
|
||||
importRequested: "Has sol·licitat una importació. Això pot trigar una estona."
|
||||
|
@ -139,7 +139,7 @@ searchByGoogle: "Cercar"
|
|||
file: "Fitxers"
|
||||
_email:
|
||||
_follow:
|
||||
title: "t'ha seguit"
|
||||
title: "Tens un nou seguidor"
|
||||
_receiveFollowRequest:
|
||||
title: Heu rebut una sol·licitud de seguiment
|
||||
_mfm:
|
||||
|
@ -228,6 +228,11 @@ _mfm:
|
|||
alwaysPlay: Reprodueix automàticament tots els MFM animats
|
||||
fade: Esvair
|
||||
fadeDescription: Esvaeix el contingut cap a dintre i cap en fora.
|
||||
crop: Retallar
|
||||
advanced: MFM avançat
|
||||
advancedDescription: Si està desactivat, només permet l'etiquetatge bàsic tret que
|
||||
es reproduïnt un MFM animat
|
||||
cropDescription: Retalla el contingut.
|
||||
_theme:
|
||||
keys:
|
||||
mention: "Menció"
|
||||
|
@ -328,7 +333,7 @@ _2fa:
|
|||
_widgets:
|
||||
notifications: "Notificacions"
|
||||
timeline: "Línia de temps"
|
||||
unixClock: Rellotge UNIX
|
||||
unixClock: Rellotge d'UNIX
|
||||
federation: Federació
|
||||
instanceCloud: Núvol de servidors
|
||||
trends: Tendència
|
||||
|
@ -340,9 +345,9 @@ _widgets:
|
|||
onlineUsers: Usuaris en línia
|
||||
memo: Notes adhesives
|
||||
digitalClock: Rellotge digital
|
||||
postForm: Formulari de notes
|
||||
postForm: Formulari per publicar
|
||||
slideshow: Presentació de diapositives
|
||||
serverMetric: Mètriques del servidor
|
||||
serverMetric: Estadístiques del servidor
|
||||
userList: Llista d'usuaris
|
||||
rss: Lector d'RSS
|
||||
jobQueue: Cua de treball
|
||||
|
@ -350,6 +355,10 @@ _widgets:
|
|||
chooseList: Selecciona una llista
|
||||
aiscript: Consola AiScript
|
||||
button: Botó
|
||||
serverInfo: Informació del servidor
|
||||
meiliStatus: Estat del servidor
|
||||
meiliSize: Mida de l'índex
|
||||
meiliIndexCount: Publicacions indexades
|
||||
_cw:
|
||||
show: "Carregar més"
|
||||
files: '{count} fitxers'
|
||||
|
@ -382,7 +391,7 @@ _profile:
|
|||
metadataDescription: Fent servir això, podràs mostrar camps d'informació addicionals
|
||||
al vostre perfil.
|
||||
_exportOrImport:
|
||||
followingList: "Seguint"
|
||||
followingList: "Usuaris que segueixes"
|
||||
muteList: "Silencia"
|
||||
blockingList: "Bloqueja"
|
||||
userLists: "Llistes"
|
||||
|
@ -684,7 +693,7 @@ _pages:
|
|||
_notification:
|
||||
youWereFollowed: "t'ha seguit"
|
||||
_types:
|
||||
follow: "Seguint"
|
||||
follow: "Nous seguidors"
|
||||
mention: "Menció"
|
||||
renote: "Impulsos"
|
||||
quote: "Citar"
|
||||
|
@ -700,7 +709,7 @@ _notification:
|
|||
_actions:
|
||||
reply: "Respondre"
|
||||
renote: "Impulsos"
|
||||
followBack: et va seguir de tornada
|
||||
followBack: t'ha tornat el seguiment
|
||||
youGotQuote: "{name} t'ha citat"
|
||||
fileUploaded: El fitxer s'ha penjat correctament
|
||||
youGotMention: "{nom} t'ha esmentat"
|
||||
|
@ -725,8 +734,9 @@ _deck:
|
|||
mentions: "Mencions"
|
||||
widgets: Ginys
|
||||
main: Principal
|
||||
antenna: Antenes
|
||||
antenna: Antena
|
||||
direct: Missatges directes
|
||||
channel: Canal
|
||||
alwaysShowMainColumn: Mostra sempre la columna principal
|
||||
columnAlign: Alinear columnes
|
||||
introduction: Crea la interfície perfecta per a tu organitzant columnes lliurement!
|
||||
|
@ -780,7 +790,7 @@ showOnRemote: Mostra al servidor remot
|
|||
wallpaper: Fons de pantalla
|
||||
setWallpaper: Estableix fons de pantalla
|
||||
removeWallpaper: Elimina el fons de pantalla
|
||||
followConfirm: Segur que vols seguir a l'usuari {name}?
|
||||
followConfirm: Segur que vols seguir a {name}?
|
||||
proxyAccount: Compte proxy
|
||||
proxyAccountDescription: Un compte proxy es un compte que actua com un seguidor remot
|
||||
per a usuaris sota determinades condicions. Per exemple, quant un usuari afegeix
|
||||
|
@ -1178,7 +1188,7 @@ large: Gran
|
|||
notificationSetting: Preferències de notificacions
|
||||
makeActive: Activar
|
||||
notificationSettingDesc: Tria el tipus de notificació que es veure.
|
||||
notifyAntenna: Notificar noves notes
|
||||
notifyAntenna: Notificar publicacions noves
|
||||
withFileAntenna: Només notes amb fitxers
|
||||
enableServiceworker: Activa les notificacions push per al teu navegador
|
||||
antennaUsersDescription: Escriu un nom d'usuari per línea
|
||||
|
@ -1238,7 +1248,7 @@ sample: Exemple
|
|||
abuseReports: Informes
|
||||
reportAbuse: Informe
|
||||
reporter: Informador
|
||||
reporterOrigin: Origen d'el informador
|
||||
reporterOrigin: Origen informador
|
||||
forwardReport: Envia l'informe a un servidor remot
|
||||
abuseReported: El teu informe ha sigut enviat. Moltes gràcies.
|
||||
reporteeOrigin: Origen de l'informe
|
||||
|
@ -1526,7 +1536,7 @@ aiChanMode: Ai-chan a la interfície d'usuari clàssica
|
|||
keepCw: Mantenir els avisos de contingut
|
||||
pubSub: Comptes Pub/Sub
|
||||
lastCommunication: Última comunicació
|
||||
breakFollowConfirm: Confirmes que vols eliminar un seguidor?
|
||||
breakFollowConfirm: Confirmes que vols eliminar el seguidor?
|
||||
itsOn: Activat
|
||||
itsOff: Desactivat
|
||||
emailRequiredForSignup: Requereix una adreça de correu electrònic per registrar-te
|
||||
|
@ -1585,7 +1595,7 @@ silenceThisInstance: Silencia el servidor
|
|||
silencedInstancesDescription: Llista amb els noms dels servidors que vols silenciar.
|
||||
Els comptes als servidors silenciats seran tractades com "Silenciades", només poden
|
||||
fer sol·licituds de seguiments, i no poden mencionar comptes locals si no les segueixen.
|
||||
Això no afectarà els servidoes bloquejats.
|
||||
Això no afectarà els servidors bloquejats.
|
||||
objectStorageEndpointDesc: Deixa això buit si fas servir AWS, S3, d'una altre manera
|
||||
específica un "endpoint" com a '<host>' o '<host>:<port>', depend del proveïdor
|
||||
que facis servir.
|
||||
|
@ -1618,7 +1628,7 @@ enableAutoSensitiveDescription: Permet la detecció i el marcatge automàtics de
|
|||
localOnly: Només local
|
||||
customKaTeXMacroDescription: "Configura macros per escriure expressions matemàtiques
|
||||
fàcilment! La notació s'ajusta a les definicions de l'ordre LaTeX i s'escriu com
|
||||
a \\newcommand{\\name}{content} o \\newcommand{\\name}[nombre d'arguments]{contingut}.
|
||||
a \\newcommand{\\ name}{content} o \\newcommand{\\name}[nombre d'arguments]{content}.
|
||||
Per exemple, \\newcommand{\\add}[2]{#1 + #2} ampliarà \\add{3}{foo} a 3 + foo. Els
|
||||
claudàtors que envolten el nom de la macro es poden canviar per claudàtors rodons
|
||||
o quadrats. Això afecta els claudàtors utilitzats per als arguments. Es pot definir
|
||||
|
@ -1673,14 +1683,14 @@ disablePagesScript: Desactivar AiScript a les pàgines
|
|||
updateRemoteUser: Actualitzar la informació de l'usuari remot
|
||||
deleteAllFiles: Esborrar tots els fitxers
|
||||
deleteAllFilesConfirm: Segur que vols esborrar tots els fitxers?
|
||||
removeAllFollowing: Deixar de seguir a tots els que segueixis
|
||||
removeAllFollowing: Deixar de seguir a tots els usuaris que segueixes
|
||||
accentColor: Color principal
|
||||
textColor: Color del text
|
||||
value: Valor
|
||||
sendErrorReportsDescription: "Quant està activat quant aparegui un error, es compartirà
|
||||
amb els desenvolupadors de Calckey, que ajudarà a millorar la qualitat.\nAixò inclourà
|
||||
informació com la versió del teu sistema operatiu, el navegador que estiguis fent
|
||||
servir, la teva activitat a Calckey, etc."
|
||||
sendErrorReportsDescription: "Quan està activat, quan es produeixi un problema la
|
||||
informació detallada d'errors es compartirà amb Calckey, ajudant a millorar la qualitat
|
||||
de Calckey.\nAixò inclourà informació com la versió del vostre sistema operatiu,
|
||||
quin navegador utilitzeu, la vostra activitat a Calckey, etc."
|
||||
myTheme: El meu tema
|
||||
backgroundColor: Color de fons
|
||||
saveAs: Desa com...
|
||||
|
@ -1822,7 +1832,7 @@ _channel:
|
|||
featured: Tendència
|
||||
owned: Propietari
|
||||
usersCount: '{n} Participants'
|
||||
following: Seguit
|
||||
following: Seguit per
|
||||
notesCount: '{n} Notes'
|
||||
nameAndDescription: Nom i descripció
|
||||
nameOnly: Només nom
|
||||
|
@ -1855,7 +1865,7 @@ _tutorial:
|
|||
step5_3: La línea de temps d'inici {icon} es on pots veure les publicacions dels
|
||||
comptes que segueixes.
|
||||
step5_6: La línia de temps de Recomanats {icon} és on pots veure les publicacions
|
||||
dels servidors recomanen els administradors.
|
||||
dels servidors que recomanen els administradors.
|
||||
step5_7: La línia de temps Global {icon} és on pots veure les publicacions de tots
|
||||
els servidors connectats.
|
||||
step6_1: Aleshores, què és aquest lloc?
|
||||
|
@ -1873,9 +1883,9 @@ _tutorial:
|
|||
step2_2: Proporcionar informació sobre qui sou facilitarà que altres puguin saber
|
||||
si volen veure les vostres notes o seguir-vos.
|
||||
step3_1: Ara toca seguir a algunes persones!
|
||||
step3_2: "Les teves líneas de temps domèstiques i socials es basen en qui seguiu,
|
||||
així que proveu de seguir un parell de comptes per començar.\nFeu clic al cercle
|
||||
més situat a la part superior dreta d'un perfil per seguir-los."
|
||||
step3_2: "Les teves líneas de temps d'inici i social es basen en qui seguiu, així
|
||||
que proveu de seguir un parell de comptes per començar.\nFeu clic al cercle més
|
||||
situat a la part superior dreta d'un perfil per seguir-los."
|
||||
step4_2: A algunes persones els agrada fer una publicació de {introduction} o un
|
||||
senzill "Hola món!"
|
||||
step5_1: Línies de temps, línies de temps a tot arreu!
|
||||
|
@ -1966,13 +1976,13 @@ _instanceCharts:
|
|||
users: Diferència en el nombre d'usuaris
|
||||
usersTotal: Nombre acumulat d'usuaris
|
||||
notes: Diferència en el nombre de notes
|
||||
ffTotal: Nombre acumulat d'usuaris seguits/seguidors seguits
|
||||
ffTotal: Nombre acumulat d'usuaris que segueixes/et segueixen
|
||||
cacheSize: Diferència en la mida de la memòria cau
|
||||
cacheSizeTotal: Mida total acumulada de la memòria cau
|
||||
files: Diferència en el nombre de fitxers
|
||||
filesTotal: Nombre acumulat de fitxers
|
||||
notesTotal: Nombre acumulat de notes
|
||||
ff: "Diferència en el nombre d'usuaris seguits/seguidors seguits "
|
||||
ff: "Diferència en el nombre d'usuaris que segueixes/que et segueixen "
|
||||
_timelines:
|
||||
home: Inici
|
||||
local: Local
|
||||
|
@ -2006,7 +2016,7 @@ _auth:
|
|||
callback: Tornant a l'aplicació
|
||||
denied: Accés denegat
|
||||
pleaseGoBack: Si us plau, torneu a l'aplicació
|
||||
copyAsk: Enganxeu el següent codi d'autorització a l'aplicació
|
||||
copyAsk: Posa el següent codi d'autorització a l'aplicació
|
||||
_weekday:
|
||||
wednesday: Dimecres
|
||||
saturday: Dissabte
|
||||
|
@ -2020,7 +2030,7 @@ _messaging:
|
|||
dms: Privat
|
||||
_antennaSources:
|
||||
all: Totes les notes
|
||||
homeTimeline: Notes dels usuaris que segueixes
|
||||
homeTimeline: Publicacions dels usuaris que segueixes
|
||||
users: Notes d'usuaris concrets
|
||||
userGroup: Notes d'usuaris d'un grup determinat
|
||||
userList: Notes d'una llista determinada d'usuaris
|
||||
|
@ -2053,7 +2063,12 @@ _experiments:
|
|||
enablePostEditing: Activà l'edició de publicacions
|
||||
title: Experiments
|
||||
postEditingCaption: Mostra l'opció perquè els usuaris editin les seves publicacions
|
||||
existents mitjançant el menú d'opcions de publicació
|
||||
mitjançant el menú d'opcions de publicació, i permet rebre publicacions editades
|
||||
d'altres servidors.
|
||||
enablePostImports: Activar l'importació de publicacions
|
||||
postImportsCaption: Permet els usuaris importar publicacions desde comptes a Calckey,
|
||||
Misskey, Mastodon, Akkoma i Pleroma. Pot fer que el servidor vagi més lent durant
|
||||
la càrrega si tens un coll d'ampolla a la cua.
|
||||
noGraze: Si us plau, desactiva l'extensió del navegador "Graze for Mastodon", ja que
|
||||
interfereix amb Calckey.
|
||||
accessibility: Accessibilitat
|
||||
|
@ -2064,3 +2079,15 @@ silencedWarning: S'està mostrant aquesta pàgina per què aquest usuari és d'u
|
|||
que l'administrador a silenciat, així que pot ser spam.
|
||||
jumpToPrevious: Vés a l'anterior
|
||||
cw: Avís de contingut
|
||||
antennasDesc: "Les antenes mostren publicacions noves que coincideixen amb els criteris
|
||||
establerts!\nS'hi pot accedir des de la pàgina de línies de temps."
|
||||
expandOnNoteClick: Obre la publicació amb un clic
|
||||
expandOnNoteClickDesc: Si està desactivat, encara pots obrir les publicacions al menú
|
||||
del botó dret o fent clic a la marca de temps.
|
||||
channelFederationWarn: Els canals encara no es federen amb altres servidors
|
||||
searchPlaceholder: Cerca a Calckey
|
||||
listsDesc: Les llistes et permeten crear línies de temps amb usuaris específics. Es
|
||||
pot accedir des de la pàgina de línies de temps.
|
||||
clipsDesc: Els clips són com marcadors categoritzats que es poden compartir. Podeu
|
||||
crear clips des del menú de publicacions individuals.
|
||||
selectChannel: Selecciona un canal
|
||||
|
|
|
@ -216,3 +216,21 @@ perHour: Hver time
|
|||
perDay: Hver dag
|
||||
stopActivityDelivery: Stop med at sende aktiviteter
|
||||
blockThisInstance: Blokere denne instans
|
||||
muteAndBlock: Mutes og blokeringer
|
||||
mutedUsers: Mutede brugere
|
||||
newer: nyere
|
||||
older: ældre
|
||||
silencedInstances: Nedtonede servere
|
||||
clearQueue: Ryd kø
|
||||
clearQueueConfirmTitle: Er du sikker på, at du ønsker at rydde køen?
|
||||
clearCachedFiles: Ryd cache
|
||||
clearCachedFilesConfirm: Er du sikker på, at du ønsker at slette alle cachede eksterne
|
||||
filer?
|
||||
blockedInstances: Blokerede servere
|
||||
blockedInstancesDescription: Listen af navne på servere, du ønsker at blokere. Servere
|
||||
på listen vil ikke længere kunne kommunikere med denne server.
|
||||
hiddenTags: Skjulte hashtags
|
||||
clearQueueConfirmText: De indlæg i denne kø, der ikke allerede er leveret, vil ikke
|
||||
blive federeret. Denne operation er almindeligvis ikke påkrævet.
|
||||
jumpToPrevious: Spring til tidligere
|
||||
cw: Advarsel om indhold
|
||||
|
|
|
@ -3,7 +3,7 @@ headlineMisskey: "Eine dezentralisierte Open-Source Social Media Plattform, die
|
|||
immer gratis bleibt! 🚀"
|
||||
introMisskey: "Willkommen! Calckey ist eine dezentralisierte Open-Source Social Media
|
||||
Plattform, die für immer gratis bleibt!🚀"
|
||||
monthAndDay: "{day}.{month}."
|
||||
monthAndDay: "{month}/{day}"
|
||||
search: "Suchen"
|
||||
notifications: "Benachrichtigungen"
|
||||
username: "Nutzername"
|
||||
|
@ -25,9 +25,9 @@ openInWindow: "In einem Fenster öffnen"
|
|||
profile: "Profil"
|
||||
timeline: "Timelines"
|
||||
noAccountDescription: "Dieser Nutzer hat seine Profilbeschreibung noch nicht ausgefüllt."
|
||||
login: "Anmelden"
|
||||
login: "Login"
|
||||
loggingIn: "Du wirst angemeldet"
|
||||
logout: "Abmelden"
|
||||
logout: "Logout"
|
||||
signup: "Registrieren"
|
||||
uploading: "Wird hochgeladen …"
|
||||
save: "Speichern"
|
||||
|
@ -66,7 +66,7 @@ import: "Import"
|
|||
export: "Export"
|
||||
files: "Dateien"
|
||||
download: "Herunterladen"
|
||||
driveFileDeleteConfirm: "Möchtest du die Datei „{name}“ wirklich löschen? Es wird
|
||||
driveFileDeleteConfirm: "Möchtest du die Datei \"{name}\" wirklich löschen? Es wird
|
||||
aus allen Beiträgen entfernt, die die Datei als Anhang enthalten."
|
||||
unfollowConfirm: "Bist du dir sicher, daß du {name} nicht mehr folgen möchtest?"
|
||||
exportRequested: "Du hast einen Export angefragt. Dies kann etwas Zeit in Anspruch
|
||||
|
@ -150,8 +150,8 @@ settingGuide: "Empfohlene Einstellungen"
|
|||
cacheRemoteFiles: "Cache für entfernte Dateien"
|
||||
cacheRemoteFilesDescription: "Ist diese Einstellung deaktiviert, so werden Dateien
|
||||
von anderen Servern direkt von dort geladen. Hierdurch wird Speicherplatz auf diesem
|
||||
Server eingespart, aber durch die fehlende Generierung von Vorschaubildern mehr
|
||||
Bandbreite benötigt."
|
||||
Server eingespart, aber durch die fehlende Generierung von Vorschaubildern wird
|
||||
mehr Bandbreite benötigt."
|
||||
flagAsBot: "Dieses Nutzerkonto als Bot kennzeichnen"
|
||||
flagAsBotDescription: "Aktiviere diese Option, falls dieses Nutzerkonto durch ein
|
||||
Programm gesteuert wird. Falls aktiviert, agiert es als Flag für andere Entwickler
|
||||
|
@ -166,7 +166,7 @@ autoAcceptFollowed: "Automatisches Genehmigen von Folgeanfragen von Benutzern, d
|
|||
Sie folgen"
|
||||
addAccount: "Nutzerkonto hinzufügen"
|
||||
loginFailed: "Anmeldung fehlgeschlagen"
|
||||
showOnRemote: "Ansicht auf dem Herkunftsserver"
|
||||
showOnRemote: "Zur Ansicht auf dem Herkunftsserver"
|
||||
general: "Allgemein"
|
||||
wallpaper: "Hintergrundbild"
|
||||
setWallpaper: "Hintergrundbild festlegen"
|
||||
|
@ -234,14 +234,14 @@ default: "Standard"
|
|||
defaultValueIs: "Der Standardwert ist: {value}"
|
||||
noCustomEmojis: "Es gibt keine benutzerdefinierten Emoji"
|
||||
noJobs: "Keine Jobs vorhanden"
|
||||
federating: "Wird föderiert"
|
||||
federating: "Eine Verbindung zum Server wird hergestellt"
|
||||
blocked: "Blockiert"
|
||||
suspended: "suspendiert"
|
||||
all: "Alles"
|
||||
subscribing: "Registrieren"
|
||||
publishing: "Veröffentlichen"
|
||||
notResponding: "Antwortet nicht"
|
||||
instanceFollowing: "Auf dem Server folgen"
|
||||
instanceFollowing: "Folgen auf dem Server"
|
||||
instanceFollowers: "Follower des Servers"
|
||||
instanceUsers: "Nutzer dieses Servers"
|
||||
changePassword: "Passwort ändern"
|
||||
|
@ -252,7 +252,7 @@ newPassword: "Neues Passwort"
|
|||
newPasswordRetype: "Neues Passwort bestätigen"
|
||||
attachFile: "Dateien anhängen"
|
||||
more: "Mehr!"
|
||||
featured: "Ausgewählt"
|
||||
featured: "Besonderheiten"
|
||||
usernameOrUserId: "Nutzername oder Nutzer-ID"
|
||||
noSuchUser: "Nutzer nicht gefunden"
|
||||
lookup: "Suche nach"
|
||||
|
@ -286,7 +286,7 @@ agreeTo: "Ich stimme {0} zu"
|
|||
tos: "Nutzungsbedingungen"
|
||||
start: "Beginnen Sie"
|
||||
home: "Home"
|
||||
remoteUserCaution: "Informationen von Remote-Nutzern können unvollständig sein."
|
||||
remoteUserCaution: "Informationen von Nutzern anderer Server sind möglicherweise unvollständig."
|
||||
activity: "Aktivität"
|
||||
images: "Bilder"
|
||||
birthday: "Geburtstag"
|
||||
|
@ -338,8 +338,8 @@ unwatch: "Nicht mehr beobachten"
|
|||
accept: "Akzeptieren"
|
||||
reject: "Ablehnen"
|
||||
normal: "Normal"
|
||||
instanceName: "Name des Servers"
|
||||
instanceDescription: "Beschreibung des Servers"
|
||||
instanceName: "Server-Name"
|
||||
instanceDescription: "Server-Beschreibung"
|
||||
maintainerName: "Betreiber"
|
||||
maintainerEmail: "Betreiber-Email"
|
||||
tosUrl: "URL der Nutzungsbedingungen"
|
||||
|
@ -371,8 +371,9 @@ pinnedUsers: "Angeheftete Nutzer"
|
|||
pinnedUsersDescription: "Gib durch Leerzeichen getrennte Nutzer an, die an die \"\
|
||||
Erkunden\"-Seite angeheftet werden sollen."
|
||||
pinnedPages: "Angeheftete Nutzer-Seiten"
|
||||
pinnedPagesDescription: "Geben Sie die Pfade der Nutzer-Seiten, getrennt durch Zeilenumbrüche,
|
||||
ein, die Sie an die oberste Startseite dieses Servers anheften möchten."
|
||||
pinnedPagesDescription: "Geben Sie die Dateipfade, getrennt durch Zeilenumbrüche,
|
||||
derjenigen Seiten ein, die Sie an die obere Seitenbegrenzung des Servers anpinnen
|
||||
möchten."
|
||||
pinnedClipId: "ID des anzuheftenden Clips"
|
||||
pinnedNotes: "Angeheftete Beiträge"
|
||||
hcaptcha: "hCaptcha"
|
||||
|
@ -584,7 +585,7 @@ deleteAllFiles: "Alle Dateien löschen"
|
|||
deleteAllFilesConfirm: "Möchtest du wirklich alle Dateien löschen?"
|
||||
removeAllFollowing: "Allen gefolgten Nutzern entfolgen"
|
||||
removeAllFollowingDescription: "Wenn Sie dies ausführen, werden alle Konten von {host}
|
||||
entfolgt. Bitte führen Sie dies aus, wenn der Server z.B. nicht mehr existiert."
|
||||
entfolgt. Bitte führen Sie dies aus, wenn der Server beispielsweise nicht mehr existiert."
|
||||
userSuspended: "Dieser Nutzer wurde gesperrt."
|
||||
userSilenced: "Dieser Nutzer wurde instanzweit stummgeschaltet."
|
||||
yourAccountSuspendedTitle: "Dieses Nutzerkonto ist gesperrt"
|
||||
|
@ -692,9 +693,9 @@ abuseReported: "Deine Meldung wurde versendet. Vielen Dank."
|
|||
reporter: "Melder"
|
||||
reporteeOrigin: "Herkunft des Gemeldeten"
|
||||
reporterOrigin: "Herkunft des Meldenden"
|
||||
forwardReport: "Einen Bericht auch an den beteiligten anderen Server weiterleiten"
|
||||
forwardReport: "Einen Meldung zusätzlich an den mit-beteiligten Server senden"
|
||||
forwardReportIsAnonymous: "Anstelle Ihres Nutzerkontos wird ein anonymes Systemkonto
|
||||
als Berichterstatter auf dem beteiligten anderen Server angezeigt."
|
||||
als Hinweisgeber auf dem mit-beteiligten Server angezeigt."
|
||||
send: "Senden"
|
||||
abuseMarkAsResolved: "Meldung als gelöst markieren"
|
||||
openInNewTab: "In neuem Tab öffnen"
|
||||
|
@ -702,7 +703,7 @@ openInSideView: "In Seitenansicht öffnen"
|
|||
defaultNavigationBehaviour: "Standardnavigationsverhalten"
|
||||
editTheseSettingsMayBreakAccount: "Bei Bearbeitung dieser Einstellungen besteht die
|
||||
Gefahr, dein Nutzerkonto zu beschädigen."
|
||||
instanceTicker: "Serveranzeige zu Beiträgen"
|
||||
instanceTicker: "Zeige zu einem Beitrag den Herkunfts-Server an"
|
||||
waitingFor: "Warte auf {x}"
|
||||
random: "Zufällig"
|
||||
system: "System"
|
||||
|
@ -834,7 +835,7 @@ active: "Aktiv"
|
|||
offline: "Offline"
|
||||
notRecommended: "Nicht empfohlen"
|
||||
botProtection: "Schutz vor Bots"
|
||||
instanceBlocking: "Föderierte Blockieren/Stummschalten"
|
||||
instanceBlocking: "Verbundene Server verwalten"
|
||||
selectAccount: "Nutzerkonto auswählen"
|
||||
switchAccount: "Konto wechseln"
|
||||
enabled: "Aktiviert"
|
||||
|
@ -899,7 +900,7 @@ manageAccounts: "Nutzerkonten verwalten"
|
|||
makeReactionsPublic: "Reaktionsverlauf veröffentlichen"
|
||||
makeReactionsPublicDescription: "Jeder wird die Liste deiner gesendeten Reaktionen
|
||||
einsehen können."
|
||||
classic: "Classic"
|
||||
classic: "Mittig/zentriert"
|
||||
muteThread: "Thread stummschalten"
|
||||
unmuteThread: "Threadstummschaltung aufheben"
|
||||
ffVisibility: "Sichtbarkeit von Gefolgten/Followern"
|
||||
|
@ -921,7 +922,7 @@ overridedDeviceKind: "Gerätetyp"
|
|||
smartphone: "Smartphone"
|
||||
tablet: "Tablet"
|
||||
auto: "Automatisch"
|
||||
themeColor: "Farbe der Laufschrift (Ticker)"
|
||||
themeColor: "Farbe der Ticker-Laufschrift"
|
||||
size: "Größe"
|
||||
numberOfColumn: "Spaltenanzahl"
|
||||
searchByGoogle: "Suchen"
|
||||
|
@ -945,18 +946,19 @@ recentNHours: "Die letzten {n} Stunden"
|
|||
recentNDays: "Die letzten {n} Tage"
|
||||
noEmailServerWarning: "Es ist kein Email-Server konfiguriert."
|
||||
thereIsUnresolvedAbuseReportWarning: "Es liegen ungelöste Meldungen vor."
|
||||
recommended: "Empfehlung"
|
||||
recommended: "Favoriten"
|
||||
check: "Kontrolle"
|
||||
driveCapOverrideLabel: "Die Cloud-Drive-Kapazität dieses Nutzers verändern"
|
||||
driveCapOverrideCaption: "Gib einen Wert von 0 oder weniger ein, um die Kapazität
|
||||
auf den Standard zurückzusetzen."
|
||||
requireAdminForView: "Melde dich mit einem Administratorkonto an, um dies einzusehen."
|
||||
isSystemAccount: "Ein Nutzerkonto, dass durch das System erstellt und automatisch
|
||||
kontrolliert wird."
|
||||
isSystemAccount: "Dieses Konto wird vom System erstellt und automatisch verwaltet.
|
||||
Bitte moderieren, bearbeiten, löschen oder manipulieren Sie dieses Konto nicht,
|
||||
da es sonst zu einem Server-Absturz kommen könnte."
|
||||
typeToConfirm: "Bitte gib zur Bestätigung {x} ein"
|
||||
deleteAccount: "Nutzerkonto löschen"
|
||||
document: "Dokumentation"
|
||||
numberOfPageCache: "Seitencachegröße"
|
||||
numberOfPageCache: "Anzahl der zwischengespeicherten Seiten"
|
||||
numberOfPageCacheDescription: "Das Erhöhen dieses Caches führt zu einer angenehmerern
|
||||
Nutzererfahrung, erhöht aber Serverlast und Arbeitsspeicherauslastung."
|
||||
logoutConfirm: "Wirklich abmelden?"
|
||||
|
@ -965,7 +967,7 @@ statusbar: "Statusleiste"
|
|||
pleaseSelect: "Wähle eine Option"
|
||||
reverse: "Umkehren"
|
||||
colored: "Farbig"
|
||||
refreshInterval: "Aktualisierungsrate "
|
||||
refreshInterval: "Aktualisierungsintervall "
|
||||
label: "Beschriftung"
|
||||
type: "Art"
|
||||
speed: "Geschwindigkeit"
|
||||
|
@ -980,7 +982,7 @@ cannotUploadBecauseInappropriate: "Diese Datei kann nicht hochgeladen werden, da
|
|||
cannotUploadBecauseNoFreeSpace: "Die Datei konnte nicht hochgeladen werden, da dein
|
||||
Cloud-Drive-Speicherplatz aufgebraucht ist."
|
||||
beta: "Beta"
|
||||
enableAutoSensitive: "NSFW-Automarkierung"
|
||||
enableAutoSensitive: "Selbstständige NSFW-Kennzeichnung"
|
||||
enableAutoSensitiveDescription: "Erlaubt, wo möglich, die automatische Erkennung und
|
||||
Kennzeichnung von NSFW-Medien durch maschinelles Lernen. Auch wenn diese Option
|
||||
deaktiviert ist, kann sie über den Server aktiviert sein."
|
||||
|
@ -999,7 +1001,7 @@ _sensitiveMediaDetection:
|
|||
sensitivityDescription: "Durch das Senken der Sensitivität kann die Anzahl an Fehlerkennungen
|
||||
(sog. false positives) reduziert werden. Durch ein Erhöhen dieser kann die Anzahl
|
||||
an verpassten Erkennungen (sog. false negatives) reduziert werden."
|
||||
setSensitiveFlagAutomatically: "Als NSFW markieren"
|
||||
setSensitiveFlagAutomatically: "Als NSFW kennzeichnen"
|
||||
setSensitiveFlagAutomaticallyDescription: "Die Resultate der internen Erkennung
|
||||
werden beibehalten, auch wenn diese Option deaktiviert ist."
|
||||
analyzeVideos: "Videoanalyse aktivieren"
|
||||
|
@ -1039,9 +1041,9 @@ _forgotPassword:
|
|||
enterEmail: "Gib die Email-Adresse ein, mit der du dich registriert hast. An diese
|
||||
wird ein Link gesendet, mit dem du dein Passwort zurücksetzen kannst."
|
||||
ifNoEmail: "Solltest du bei der Registrierung keine Email-Adresse angegeben haben,
|
||||
wende dich bitte an den Administrator."
|
||||
contactAdmin: "Dieser Server unterstützt die Verwendung von Email-Adressen nicht.
|
||||
Kontaktiere bitte den Server-Administrator, um dein Passwort zurücksetzen zu lassen."
|
||||
wende dich bitte an den Server-Administrator."
|
||||
contactAdmin: "Dieser Server unterstützt keine Verwendung von Email-Adressen. Kontaktiere
|
||||
bitte den Server-Administrator, um dein Passwort zurücksetzen zu lassen."
|
||||
_gallery:
|
||||
my: "Meine Bilder-Galerie"
|
||||
liked: "Mit \"Gefällt mir\" markierte Beiträge"
|
||||
|
@ -1054,7 +1056,7 @@ _email:
|
|||
title: "Du hast eine Follow-Anfrage erhalten"
|
||||
_plugin:
|
||||
install: "Plugins installieren"
|
||||
installWarn: "Installiere bitte nur vertrauenswürdige Plugins."
|
||||
installWarn: "Bitte nur vertrauenswürdige Plugins installieren."
|
||||
manage: "Plugins verwalten"
|
||||
_preferencesBackups:
|
||||
list: "Erstellte Backups"
|
||||
|
@ -1095,8 +1097,8 @@ _aboutMisskey:
|
|||
Personen sehr. Danke! 🥰"
|
||||
patrons: "UnterstützerInnen"
|
||||
_nsfw:
|
||||
respect: "Als NSFW markierte Bilder verbergen"
|
||||
ignore: "Als NSFW markierte Bilder nicht verbergen"
|
||||
respect: "Mit NSFW gekennzeichnete Bilder verbergen"
|
||||
ignore: "Mit NSFW gekennzeichnete Bilder nicht verbergen"
|
||||
force: "Alle Medien verbergen"
|
||||
_mfm:
|
||||
cheatSheet: "MFM Spickzettel"
|
||||
|
@ -1183,6 +1185,10 @@ _mfm:
|
|||
scaleDescription: Skaliere den Inhalt um einen bestimmten Betrag.
|
||||
foregroundDescription: Ändern der Vordergrundfarbe von Text.
|
||||
backgroundDescription: Ändern der Hintergrundfarbe von Text
|
||||
play: MFM abspielen
|
||||
stop: MFM anhalten
|
||||
warn: MFM können schnell bewegte oder anderweitig auffallende Animationen enthalten
|
||||
alwaysPlay: Alle animierten MFM immer automatisch abspielen
|
||||
_instanceTicker:
|
||||
none: "Nie anzeigen"
|
||||
remote: "Für Nutzer eines anderen Servers anzeigen"
|
||||
|
@ -1225,12 +1231,12 @@ _wordMute:
|
|||
hard: "Schwer"
|
||||
mutedNotes: "Stummgeschaltete Beiträge"
|
||||
_instanceMute:
|
||||
instanceMuteDescription: "Schaltet alle Beiträge/boosts stumm, die von den gelisteten
|
||||
instanceMuteDescription: "Schaltet alle Beiträge/Boosts stumm, die von den gelisteten
|
||||
Servern stammen, inklusive Antworten von Nutzern an einen Nutzer eines stummgeschalteten
|
||||
Servers."
|
||||
instanceMuteDescription2: "Mit Zeilenumbrüchen trennen"
|
||||
title: "Blendet Beiträge von aufgelisteten Servern aus."
|
||||
heading: "Liste der stummzuschaltenden Server"
|
||||
heading: "Liste der Server die stummgeschaltet werden sollen"
|
||||
_theme:
|
||||
explore: "Farbkombinationen finden"
|
||||
install: "Eine Farbkombination installieren"
|
||||
|
@ -1345,21 +1351,19 @@ _tutorial:
|
|||
step5_1: "Timelines, Timelines überall!"
|
||||
step5_2: "Dein Server hat {timelines} verschiedene Timelines aktiviert."
|
||||
step5_3: "Die {icon} Home-Timeline ist die Timeline, in der du die Beiträge der
|
||||
Nutzerkonten sehen kannst, denen du folgst und von jedem anderen auf diesem Server.
|
||||
Solltest du bevorzugen, dass deine Home-Timeline nur Beiträge von den Nutzerkonten
|
||||
enthält, denen du folgst, kannst du das ganz einfach in den Einstellungen ändern!"
|
||||
step5_4: "In der {Icon} Local-Timeline kannst du die Beiträge aller anderen Mitglieder
|
||||
dieses Servers sehen."
|
||||
step5_5: "Die {icon} Social-Timeline zeigt dir ausschließlich Beiträge von Nutzerkonten
|
||||
denen Du folgst."
|
||||
step5_6: "In der {icon} Empfehlungen-Timeline kannst du Beiträge von Servern sehen,
|
||||
die dir von den Server-Administratoren empfohlen/vorgeschlagen werden."
|
||||
step5_7: "In der {icon} Global-Timeline können Sie Beiträge von jedem anderen verbundenen
|
||||
Server im fediverse sehen."
|
||||
Nutzerkonten sehen kannst, denen du folgst."
|
||||
step5_4: "In der {Icon} Local-Timeline kannst du die Beiträge von jedem/jeder sehen
|
||||
der/die auf diesem Server registriert ist."
|
||||
step5_5: "Die Social-Timeline {icon} ist eine Kombination aus der Home-Timeline
|
||||
und der Local-Timeline."
|
||||
step5_6: "In der {icon} \"Favoriten\"-Timeline können sie Beiträge von Servern sehen,
|
||||
die von den Server-Administratoren vorgeschlagen werden."
|
||||
step5_7: "In der {icon} Global-Timeline können Sie Beiträge von allen verknüpften
|
||||
Servern aus dem Fediverse sehen."
|
||||
step6_1: "Also, was ist das hier?"
|
||||
step6_2: "Schön, mit Deiner Anmeldung zu Calckey bist Du gleichzeitig einem Portal
|
||||
zum Fediverse beigetreten, einem Netzwerk mit Tausenden von verbundenen Servern
|
||||
(häufig noch als \"Instanzen\" bezeichnet)."
|
||||
step6_2: "Mit Deiner Anmeldung zu Calckey bist Du gleichzeitig einem Portal zum
|
||||
Fediverse beigetreten, einem Netzwerk mit Tausenden von, miteinander verbundenen,
|
||||
Servern."
|
||||
step6_3: "Jeder der Server funktioniert auf unterschiedliche Weise, und nicht alle
|
||||
Server führen Calckey aus. Dieser jedoch schon! Es ist zu Beginn vielleicht ein
|
||||
wenig kompliziert, aber Sie werden in kürzester Zeit den Dreh raus haben."
|
||||
|
@ -1568,9 +1572,9 @@ _timelines:
|
|||
local: "Local-TL"
|
||||
social: "Social-TL"
|
||||
global: "Global-TL"
|
||||
recommended: Empfehlungen
|
||||
recommended: Admin-Favoriten
|
||||
_pages:
|
||||
newPage: "Seite erstellen"
|
||||
newPage: "Neue Seite erstellen"
|
||||
editPage: "Seite bearbeiten"
|
||||
readPage: "Quelltextansicht"
|
||||
created: "Seite erfolgreich erstellt"
|
||||
|
@ -1898,6 +1902,9 @@ _notification:
|
|||
followBack: "folgt dir nun auch"
|
||||
reply: "Antworten"
|
||||
renote: "Renote"
|
||||
voted: haben bei deiner Umfrage abgestimmt
|
||||
reacted: hat auf deinen Beitrag reagiert
|
||||
renoted: hat Ihren Beitrag geteilt
|
||||
_deck:
|
||||
alwaysShowMainColumn: "Hauptspalte immer zeigen"
|
||||
columnAlign: "Spaltenausrichtung"
|
||||
|
@ -1928,9 +1935,9 @@ _deck:
|
|||
direct: "Direktnachrichten"
|
||||
renameProfile: Arbeitsbereich umbenennen
|
||||
nameAlreadyExists: Der Name für den Arbeitsbereich ist bereits vorhanden.
|
||||
enableRecommendedTimeline: Empfohlenen Zeitplan aktivieren
|
||||
enableRecommendedTimeline: '"Favoriten"-Timeline einschalten'
|
||||
secureMode: Sicherer Modus (Autorisierter Abruf)
|
||||
instanceSecurity: Serversicherheit
|
||||
instanceSecurity: Server-Sicherheit
|
||||
manageGroups: Gruppen verwalten
|
||||
noThankYou: Nein, danke
|
||||
privateMode: Privater Modus
|
||||
|
@ -1938,22 +1945,22 @@ enableEmojiReactions: Emoji-Reaktionen aktivieren
|
|||
flagSpeakAsCat: Wie eine Katze sprechen
|
||||
showEmojisInReactionNotifications: Emojis in Reaktionsbenachrichtigungen anzeigen
|
||||
userSaysSomethingReason: '{name} sagte {reason}'
|
||||
hiddenTagsDescription: 'Liste die Hashtags (ohne #) welche du von Trending und Explore
|
||||
verstecken möchtest. Versteckte Hashtags sind durch andere Wege weiterhin auffindbar.
|
||||
Blockierte Server sind nicht betroffen, auch wenn sie hier aufgeführt sind.'
|
||||
hiddenTagsDescription: 'Geben sie hier die Schlagworte (ohne #hashtag) an, die vom
|
||||
"Trending and Explore" ausgeschlossen werden sollen. Versteckte Schlagworte sind
|
||||
immer noch über andere Wege auffindbar.'
|
||||
addInstance: Server hinzufügen
|
||||
flagSpeakAsCatDescription: Deine Beiträge werden im Katzenmodus nyanisiert
|
||||
hiddenTags: Versteckte Hashtags
|
||||
antennaInstancesDescription: Nenne einen Servernamen pro Zeile
|
||||
antennaInstancesDescription: Geben sie einen Server-Namen pro Zeile ein
|
||||
secureModeInfo: Bei Anfragen an andere Server nicht ohne Nachweis zurücksenden.
|
||||
renoteMute: Boosts stummschalten
|
||||
renoteUnmute: Stummschaltung von Boosts aufheben
|
||||
noInstances: Es gibt keine Server
|
||||
noInstances: Keine Server gefunden
|
||||
privateModeInfo: Wenn diese Option aktiviert ist, können nur als vertrauenswürdig
|
||||
eingestufte Server mit deinem Server föderieren. Alle Beiträge werden für die Öffentlichkeit
|
||||
verborgen.
|
||||
eingestufte Server mit diesem Server verknüpft werden. Alle Beiträge werden für
|
||||
die Öffentlichkeit verborgen.
|
||||
allowedInstances: Vertrauenswürdige Server
|
||||
selectInstance: Wähle einen Server
|
||||
selectInstance: Wähle einen Server aus
|
||||
silencedInstancesDescription: Liste die Hostnamen der Server auf, die du stummschalten
|
||||
möchtest. Nutzerkonten in den aufgelisteten Servern werden als "Stumm" behandelt,
|
||||
können nur Follow-Anfragen stellen und können keine lokalen Nutzerkonten erwähnen,
|
||||
|
@ -1968,7 +1975,7 @@ deleted: Gelöscht
|
|||
breakFollowConfirm: Sind sie sicher, dass sie eine(n) Follower entfernen möchten?
|
||||
unsubscribePushNotification: Push-Benachrichtigungen deaktivieren
|
||||
pushNotificationAlreadySubscribed: Push-Benachrichtigungen sind bereits aktiviert
|
||||
pushNotificationNotSupported: Dein Browser oder der Server unterstützt keine Push-Benachrichtigungen
|
||||
pushNotificationNotSupported: Ihr Browser oder der Server unterstützt keine Push-Benachrichtigungen
|
||||
pushNotification: Push-Benachrichtigungen
|
||||
subscribePushNotification: Push-Benachrichtigungen aktivieren
|
||||
showLocalPosts: 'Zeige lokale Beiträge in:'
|
||||
|
@ -1983,7 +1990,7 @@ moveToLabel: 'Nutzerkonto zu dem sie umziehen:'
|
|||
moveAccountDescription: 'Dieser Vorgang kann nicht rückgängig gemacht werden! Stellen
|
||||
sie vor dem Umzug dieses Nutzerkontos sicher, dass Sie einen Namen für Ihr neues
|
||||
Nutzerkonto eingerichtet haben. Bitte geben sie die Bezeichnung des neuen Nutzerkontos
|
||||
wie folgt ein: @name@instance.xyz'
|
||||
wie folgt ein: @name@server.xyz'
|
||||
findOtherInstance: Einen anderen Server finden
|
||||
sendPushNotificationReadMessage: Löschung der Push-Benachrichtigungen sobald die entsprechenden
|
||||
Benachrichtigungen oder Beiträge gelesen wurden.
|
||||
|
@ -1998,7 +2005,7 @@ socialTimeline: Social-Timeline
|
|||
moveFrom: Bisheriges Nutzerkonto zu diesem Nutzerkonto umziehen
|
||||
_messaging:
|
||||
groups: Gruppen
|
||||
dms: Persönlich
|
||||
dms: Privat
|
||||
recommendedInstances: Empfohlene Server
|
||||
logoImageUrl: URL des Logo-Bildes
|
||||
userSaysSomethingReasonReply: '{name} hat auf einen Beitrag geantwortet der {reason}
|
||||
|
@ -2020,23 +2027,23 @@ adminCustomCssWarn: Diese Einstellung sollte nur verwendet werden, wenn Sie wiss
|
|||
mehr normal funktionieren. Bitte stellen Sie sicher, dass Ihr CSS ordnungsgemäß
|
||||
funktioniert, indem Sie es in Ihren Benutzereinstellungen testen.
|
||||
customMOTD: Benutzerdefinierte Meldung des Tages (Begrüßungsbildschirmmeldungen)
|
||||
allowedInstancesDescription: Hosts von Instanzen, die für den Verbund auf die Whitelist
|
||||
gesetzt werden sollen, jeweils durch eine neue Zeile getrennt (gilt nur im privaten
|
||||
Modus).
|
||||
allowedInstancesDescription: Hosts von Servern, die zur Verbindung auf die Liste vertrauenswürdiger
|
||||
Server gesetzt werden sollen, werden jeweils durch eine neue Zeile getrennt eingegeben
|
||||
(gilt nur im privaten Modus).
|
||||
migration: Migration
|
||||
updateAvailable: Es könnte eine Aktualisierung verfügbar sein!
|
||||
showAdminUpdates: Anzeigen, dass eine neue Calckey-Version verfügbar ist (nur Administrator)
|
||||
customMOTDDescription: Benutzerdefinierte Meldungen für die Meldung des Tages (Begrüßungsbildschirm),
|
||||
die durch Zeilenumbrüche getrennt sind und nach dem Zufallsprinzip jedes Mal angezeigt
|
||||
werden, wenn ein Benutzer die Seite (neu) lädt.
|
||||
recommendedInstancesDescription: Empfohlene Instanzen, die durch Zeilenumbrüche getrennt
|
||||
sind, werden in der empfohlenen Zeitachse angezeigt. Fügen Sie NICHT "https://"
|
||||
hinzu, sondern NUR die Domain.
|
||||
recommendedInstancesDescription: Empfohlene Server, die durch Zeilenumbrüche getrennt
|
||||
sind, werden in der "Favoriten"-Timeline angezeigt. Fügen Sie NICHT "https://" hinzu,
|
||||
sondern NUR die Domain.
|
||||
sendModMail: Moderationshinweis senden
|
||||
moveFromDescription: 'Dadurch wird ein Alias Ihres alten Nutzerkontos festgelegt,
|
||||
sodass Sie von ihrem bisherigen Konto zu diesem Nutzerkonto wechseln können. Tun
|
||||
Sie dies, BEVOR Sie von Ihrem bisherigen Nutzerkonto hierhin wechseln. Bitte geben
|
||||
Sie den Namen des Nutzerkontos wie folgt ein: person@server.xyz'
|
||||
Sie den Namen des Nutzerkontos wie folgt ein: @person@server.xyz'
|
||||
preventAiLearning: KI gestütztes bot-scraping unterdrücken
|
||||
preventAiLearningDescription: Fordern Sie KI-Sprachmodelle von Drittanbietern auf,
|
||||
die von Ihnen hochgeladenen Inhalte, wie z. B. Beiträge und Bilder, nicht zu untersuchen.
|
||||
|
@ -2059,3 +2066,26 @@ older: älter
|
|||
newer: neuer
|
||||
accessibility: Erreichbarkeit
|
||||
jumpToPrevious: Zum Vorherigen springen
|
||||
silencedWarning: Diese Meldung wird angezeigt, weil diese Nutzer von Servern stammen,
|
||||
die Ihr Administrator abgeschaltet hat, so dass es sich möglicherweise um Spam handelt.
|
||||
_experiments:
|
||||
enablePostEditing: Beitragsbearbeitung ermöglichen
|
||||
title: Funktionstests
|
||||
postEditingCaption: Zeigt die Option für Nutzer an, ihre bestehenden Beiträge über
|
||||
das Menü "Beitragsoptionen" zu bearbeiten
|
||||
noGraze: Bitte deaktivieren Sie die Browsererweiterung "Graze for Mastodon", da sie
|
||||
die Funktion von Calckey stört.
|
||||
indexFrom: Indizieren ab Beitrags-ID (frei lassen, um jeden Beitrag zu indizieren)
|
||||
indexNotice: Indizierung gestartet. Dies wird wahrscheinlich eine Weile dauern. Bitte
|
||||
starte den Server für mindestens eine Stunde nicht neu.
|
||||
customKaTeXMacroDescription: "Richten Sie Makros ein, um mathematische Ausdrücke einfach
|
||||
zu schreiben! Die Notation entspricht den LaTeX-Befehlsdefinitionen und wird als\n
|
||||
\\newcommand{\\name}{content} or \\newcommand{\\name}[number of arguments]{content}\n
|
||||
geschrieben.\nZum Beispiel wird\n\\newcommand{\\add}[2]{#1 + #2} \\add{3}{foo} um
|
||||
3 + foo erweitert.\nDie geschweiften Klammern, die den Makronamen umgeben, können
|
||||
in runde oder eckige Klammern geändert werden. Dies hat Auswirkungen auf die Klammern,
|
||||
die für die Argumente verwendet werden. Pro Zeile kann ein (und nur ein) Makro definiert
|
||||
werden, und Sie können die Zeile nicht mitten in der Definition umbrechen. Ungültige
|
||||
Zeilen werden einfach ignoriert. Es werden nur einfache Funktionen zur Substitution
|
||||
von Zeichenketten unterstützt; erweiterte Syntax, wie z. B. bedingte Verzweigungen,
|
||||
können hier nicht verwendet werden."
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
_lang_: "English"
|
||||
headlineMisskey: "An open source, decentralized social media platform that's free\
|
||||
\ forever! \U0001F680"
|
||||
introMisskey: "Welcome! Calckey is an open source, decentralized social media platform\
|
||||
\ that's free forever! \U0001F680"
|
||||
headlineMisskey: "An open source, decentralized social media platform that's free
|
||||
forever! 🚀"
|
||||
introMisskey: "Welcome! Calckey is an open source, decentralized social media platform
|
||||
that's free forever! 🚀"
|
||||
monthAndDay: "{month}/{day}"
|
||||
search: "Search"
|
||||
searchPlaceholder: "Search Calckey"
|
||||
|
@ -49,8 +49,8 @@ copyLink: "Copy link"
|
|||
delete: "Delete"
|
||||
deleted: "Deleted"
|
||||
deleteAndEdit: "Delete and edit"
|
||||
deleteAndEditConfirm: "Are you sure you want to delete this post and edit it? You\
|
||||
\ will lose all reactions, boosts and replies to it."
|
||||
deleteAndEditConfirm: "Are you sure you want to delete this post and edit it? You
|
||||
will lose all reactions, boosts and replies to it."
|
||||
editNote: "Edit note"
|
||||
edited: "Edited"
|
||||
addToList: "Add to list"
|
||||
|
@ -76,11 +76,11 @@ import: "Import"
|
|||
export: "Export"
|
||||
files: "Files"
|
||||
download: "Download"
|
||||
driveFileDeleteConfirm: "Are you sure you want to delete the file \"{name}\"? It will\
|
||||
\ be removed from all posts that contain it as an attachment."
|
||||
driveFileDeleteConfirm: "Are you sure you want to delete the file \"{name}\"? It will
|
||||
be removed from all posts that contain it as an attachment."
|
||||
unfollowConfirm: "Are you sure that you want to unfollow {name}?"
|
||||
exportRequested: "You've requested an export. This may take a while. It will be added\
|
||||
\ to your Drive once completed."
|
||||
exportRequested: "You've requested an export. This may take a while. It will be added
|
||||
to your Drive once completed."
|
||||
importRequested: "You've requested an import. This may take a while."
|
||||
lists: "Lists"
|
||||
listsDesc: "Lists let you create timelines with specified users. They can be accessed from the timelines page."
|
||||
|
@ -96,8 +96,8 @@ error: "Error"
|
|||
somethingHappened: "An error has occurred"
|
||||
retry: "Retry"
|
||||
pageLoadError: "An error occurred loading the page."
|
||||
pageLoadErrorDescription: "This is normally caused by network errors or the browser's\
|
||||
\ cache. Try clearing the cache and then try again after waiting a little while."
|
||||
pageLoadErrorDescription: "This is normally caused by network errors or the browser's
|
||||
cache. Try clearing the cache and then try again after waiting a little while."
|
||||
serverIsDead: "This server is not responding. Please wait for a while and try again."
|
||||
youShouldUpgradeClient: "To view this page, please refresh to update your client."
|
||||
enterListName: "Enter a name for the list"
|
||||
|
@ -147,6 +147,7 @@ unsuspendConfirm: "Are you sure that you want to unsuspend this account?"
|
|||
selectList: "Select a list"
|
||||
selectAntenna: "Select an antenna"
|
||||
selectWidget: "Select a widget"
|
||||
selectChannel: "Select a channel"
|
||||
editWidgets: "Edit widgets"
|
||||
editWidgetsExit: "Done"
|
||||
customEmojis: "Custom Emoji"
|
||||
|
@ -157,21 +158,21 @@ emojiUrl: "Emoji URL"
|
|||
addEmoji: "Add"
|
||||
settingGuide: "Recommended settings"
|
||||
cacheRemoteFiles: "Cache remote files"
|
||||
cacheRemoteFilesDescription: "When this setting is disabled, remote files are loaded\
|
||||
\ directly from the remote server. Disabling this will decrease storage usage,\
|
||||
\ but increase traffic, as thumbnails will not be generated."
|
||||
cacheRemoteFilesDescription: "When this setting is disabled, remote files are loaded
|
||||
directly from the remote server. Disabling this will decrease storage usage, but
|
||||
increase traffic, as thumbnails will not be generated."
|
||||
flagAsBot: "Mark this account as a bot"
|
||||
flagAsBotDescription: "Enable this option if this account is controlled by a program.\
|
||||
\ If enabled, it will act as a flag for other developers to prevent endless interaction\
|
||||
\ chains with other bots and adjust Calckey's internal systems to treat this account\
|
||||
\ as a bot."
|
||||
flagAsCat: "Are you a cat? \U0001F63A"
|
||||
flagAsBotDescription: "Enable this option if this account is controlled by a program.
|
||||
If enabled, it will act as a flag for other developers to prevent endless interaction
|
||||
chains with other bots and adjust Calckey's internal systems to treat this account
|
||||
as a bot."
|
||||
flagAsCat: "Are you a cat? 😺"
|
||||
flagAsCatDescription: "You'll get cat ears and speak like a cat!"
|
||||
flagSpeakAsCat: "Speak as a cat"
|
||||
flagSpeakAsCatDescription: "Your posts will get nyanified when in cat mode"
|
||||
flagShowTimelineReplies: "Show replies in timeline"
|
||||
flagShowTimelineRepliesDescription: "Shows replies of users to posts of other users\
|
||||
\ in the timeline if turned on."
|
||||
flagShowTimelineRepliesDescription: "Shows replies of users to posts of other users
|
||||
in the timeline if turned on."
|
||||
autoAcceptFollowed: "Automatically approve follow requests from users you're following"
|
||||
addAccount: "Add account"
|
||||
loginFailed: "Failed to sign in"
|
||||
|
@ -185,10 +186,10 @@ searchWith: "Search: {q}"
|
|||
youHaveNoLists: "You don't have any lists"
|
||||
followConfirm: "Are you sure that you want to follow {name}?"
|
||||
proxyAccount: "Proxy Account"
|
||||
proxyAccountDescription: "A proxy account is an account that acts as a remote follower\
|
||||
\ for users under certain conditions. For example, when a user adds a remote user\
|
||||
\ to the list, the remote user's activity will not be delivered to the server\
|
||||
\ if no local user is following that user, so the proxy account will follow instead."
|
||||
proxyAccountDescription: "A proxy account is an account that acts as a remote follower
|
||||
for users under certain conditions. For example, when a user adds a remote user
|
||||
to the list, the remote user's activity will not be delivered to the server if no
|
||||
local user is following that user, so the proxy account will follow instead."
|
||||
host: "Host"
|
||||
selectUser: "Select a user"
|
||||
selectInstance: "Select an server"
|
||||
|
@ -220,22 +221,22 @@ instanceInfo: "Server Information"
|
|||
statistics: "Statistics"
|
||||
clearQueue: "Clear queue"
|
||||
clearQueueConfirmTitle: "Are you sure that you want to clear the queue?"
|
||||
clearQueueConfirmText: "Any undelivered posts remaining in the queue will not be federated.\
|
||||
\ Usually this operation is not needed."
|
||||
clearQueueConfirmText: "Any undelivered posts remaining in the queue will not be federated.
|
||||
Usually this operation is not needed."
|
||||
clearCachedFiles: "Clear cache"
|
||||
clearCachedFilesConfirm: "Are you sure that you want to delete all cached remote files?"
|
||||
blockedInstances: "Blocked Servers"
|
||||
blockedInstancesDescription: "List the hostnames of the servers that you want to\
|
||||
\ block. Listed servers will no longer be able to communicate with this servers."
|
||||
blockedInstancesDescription: "List the hostnames of the servers that you want to block.
|
||||
Listed servers will no longer be able to communicate with this servers."
|
||||
silencedInstances: "Silenced Servers"
|
||||
silencedInstancesDescription: "List the hostnames of the servers that you want to\
|
||||
\ silence. Accounts in the listed servers are treated as \"Silenced\", can only\
|
||||
\ make follow requests, and cannot mention local accounts if not followed. This\
|
||||
\ will not affect the blocked servers."
|
||||
silencedInstancesDescription: "List the hostnames of the servers that you want to
|
||||
silence. Accounts in the listed servers are treated as \"Silenced\", can only make
|
||||
follow requests, and cannot mention local accounts if not followed. This will not
|
||||
affect the blocked servers."
|
||||
hiddenTags: "Hidden Hashtags"
|
||||
hiddenTagsDescription: "List the hashtags (without the #) of the hashtags you wish\
|
||||
\ to hide from trending and explore. Hidden hashtags are still discoverable via\
|
||||
\ other means."
|
||||
hiddenTagsDescription: "List the hashtags (without the #) of the hashtags you wish
|
||||
to hide from trending and explore. Hidden hashtags are still discoverable via other
|
||||
means."
|
||||
muteAndBlock: "Mutes and Blocks"
|
||||
mutedUsers: "Muted users"
|
||||
blockedUsers: "Blocked users"
|
||||
|
@ -286,8 +287,8 @@ saved: "Saved"
|
|||
messaging: "Chat"
|
||||
upload: "Upload"
|
||||
keepOriginalUploading: "Keep original image"
|
||||
keepOriginalUploadingDescription: "Saves the originally uploaded image as-is. If turned\
|
||||
\ off, a version to display on the web will be generated on upload."
|
||||
keepOriginalUploadingDescription: "Saves the originally uploaded image as-is. If turned
|
||||
off, a version to display on the web will be generated on upload."
|
||||
fromDrive: "From Drive"
|
||||
fromUrl: "From URL"
|
||||
uploadFromUrl: "Upload from a URL"
|
||||
|
@ -337,8 +338,8 @@ unableToDelete: "Unable to delete"
|
|||
inputNewFileName: "Enter a new filename"
|
||||
inputNewDescription: "Enter new caption"
|
||||
inputNewFolderName: "Enter a new folder name"
|
||||
circularReferenceFolder: "The destination folder is a subfolder of the folder you\
|
||||
\ wish to move."
|
||||
circularReferenceFolder: "The destination folder is a subfolder of the folder you
|
||||
wish to move."
|
||||
hasChildFilesOrFolders: "Since this folder is not empty, it can not be deleted."
|
||||
copyUrl: "Copy URL"
|
||||
rename: "Rename"
|
||||
|
@ -373,8 +374,8 @@ disconnectService: "Disconnect"
|
|||
enableLocalTimeline: "Enable local timeline"
|
||||
enableGlobalTimeline: "Enable global timeline"
|
||||
enableRecommendedTimeline: "Enable recommended timeline"
|
||||
disablingTimelinesInfo: "Adminstrators and Moderators will always have access to all\
|
||||
\ timelines, even if they are not enabled."
|
||||
disablingTimelinesInfo: "Adminstrators and Moderators will always have access to all
|
||||
timelines, even if they are not enabled."
|
||||
registration: "Register"
|
||||
enableRegistration: "Enable new user registration"
|
||||
invite: "Invite"
|
||||
|
@ -386,11 +387,11 @@ bannerUrl: "Banner image URL"
|
|||
backgroundImageUrl: "Background image URL"
|
||||
basicInfo: "Basic info"
|
||||
pinnedUsers: "Pinned users"
|
||||
pinnedUsersDescription: "List usernames separated by line breaks to be pinned in the\
|
||||
\ \"Explore\" tab."
|
||||
pinnedUsersDescription: "List usernames separated by line breaks to be pinned in the
|
||||
\"Explore\" tab."
|
||||
pinnedPages: "Pinned Pages"
|
||||
pinnedPagesDescription: "Enter the paths of the Pages you want to pin to the top page\
|
||||
\ of this server, separated by line breaks."
|
||||
pinnedPagesDescription: "Enter the paths of the Pages you want to pin to the top page
|
||||
of this server, separated by line breaks."
|
||||
pinnedClipId: "ID of the clip to pin"
|
||||
pinnedNotes: "Pinned posts"
|
||||
hcaptcha: "hCaptcha"
|
||||
|
@ -401,9 +402,9 @@ recaptcha: "reCAPTCHA"
|
|||
enableRecaptcha: "Enable reCAPTCHA"
|
||||
recaptchaSiteKey: "Site key"
|
||||
recaptchaSecretKey: "Secret key"
|
||||
avoidMultiCaptchaConfirm: "Using multiple Captcha systems may cause interference between\
|
||||
\ them. Would you like to disable the other Captcha systems currently active? If\
|
||||
\ you would like them to stay enabled, press cancel."
|
||||
avoidMultiCaptchaConfirm: "Using multiple Captcha systems may cause interference between
|
||||
them. Would you like to disable the other Captcha systems currently active? If you
|
||||
would like them to stay enabled, press cancel."
|
||||
antennas: "Antennas"
|
||||
antennasDesc: "Antennas display new posts matching the criteria you set!\n They can be accessed from the timelines page."
|
||||
manageAntennas: "Manage Antennas"
|
||||
|
@ -411,8 +412,8 @@ name: "Name"
|
|||
antennaSource: "Antenna source"
|
||||
antennaKeywords: "Keywords to listen to"
|
||||
antennaExcludeKeywords: "Keywords to exclude"
|
||||
antennaKeywordsDescription: "Separate with spaces for an AND condition or with line\
|
||||
\ breaks for an OR condition."
|
||||
antennaKeywordsDescription: "Separate with spaces for an AND condition or with line
|
||||
breaks for an OR condition."
|
||||
notifyAntenna: "Notify about new posts"
|
||||
withFileAntenna: "Only posts with files"
|
||||
enableServiceworker: "Enable Push-Notifications for your Browser"
|
||||
|
@ -543,27 +544,26 @@ showFeaturedNotesInTimeline: "Show featured posts in timelines"
|
|||
objectStorage: "Object Storage"
|
||||
useObjectStorage: "Use object storage"
|
||||
objectStorageBaseUrl: "Base URL"
|
||||
objectStorageBaseUrlDesc: "The URL used as reference. Specify the URL of your CDN\
|
||||
\ or Proxy if you are using either.\nFor S3 use 'https://<bucket>.s3.amazonaws.com'\
|
||||
\ and for GCS or equivalent services use 'https://storage.googleapis.com/<bucket>',\
|
||||
\ etc."
|
||||
objectStorageBaseUrlDesc: "The URL used as reference. Specify the URL of your CDN
|
||||
or Proxy if you are using either.\nFor S3 use 'https://<bucket>.s3.amazonaws.com'
|
||||
and for GCS or equivalent services use 'https://storage.googleapis.com/<bucket>',
|
||||
etc."
|
||||
objectStorageBucket: "Bucket"
|
||||
objectStorageBucketDesc: "Please specify the bucket name used at your provider."
|
||||
objectStoragePrefix: "Prefix"
|
||||
objectStoragePrefixDesc: "Files will be stored under directories with this prefix."
|
||||
objectStorageEndpoint: "Endpoint"
|
||||
objectStorageEndpointDesc: "Leave this empty if you are using AWS S3, otherwise specify\
|
||||
\ the endpoint as '<host>' or '<host>:<port>', depending on the service you are\
|
||||
\ using."
|
||||
objectStorageEndpointDesc: "Leave this empty if you are using AWS S3, otherwise specify
|
||||
the endpoint as '<host>' or '<host>:<port>', depending on the service you are using."
|
||||
objectStorageRegion: "Region"
|
||||
objectStorageRegionDesc: "Specify a region like 'xx-east-1'. If your service does\
|
||||
\ not distinguish between regions, leave this blank or enter 'us-east-1'."
|
||||
objectStorageRegionDesc: "Specify a region like 'xx-east-1'. If your service does
|
||||
not distinguish between regions, leave this blank or enter 'us-east-1'."
|
||||
objectStorageUseSSL: "Use SSL"
|
||||
objectStorageUseSSLDesc: "Turn this off if you are not going to use HTTPS for API\
|
||||
\ connections"
|
||||
objectStorageUseSSLDesc: "Turn this off if you are not going to use HTTPS for API
|
||||
connections"
|
||||
objectStorageUseProxy: "Connect over Proxy"
|
||||
objectStorageUseProxyDesc: "Turn this off if you are not going to use a Proxy for\
|
||||
\ API connections"
|
||||
objectStorageUseProxyDesc: "Turn this off if you are not going to use a Proxy for
|
||||
API connections"
|
||||
objectStorageSetPublicRead: "Set \"public-read\" on upload"
|
||||
serverLogs: "Server logs"
|
||||
deleteAll: "Delete all"
|
||||
|
@ -591,9 +591,9 @@ sort: "Sort"
|
|||
ascendingOrder: "Ascending"
|
||||
descendingOrder: "Descending"
|
||||
scratchpad: "Scratchpad"
|
||||
scratchpadDescription: "The scratchpad provides an environment for AiScript experiments.\
|
||||
\ You can write, execute, and check the results of it interacting with Calckey in\
|
||||
\ it."
|
||||
scratchpadDescription: "The scratchpad provides an environment for AiScript experiments.
|
||||
You can write, execute, and check the results of it interacting with Calckey in
|
||||
it."
|
||||
output: "Output"
|
||||
script: "Script"
|
||||
disablePagesScript: "Disable AiScript on Pages"
|
||||
|
@ -603,14 +603,14 @@ updateRemoteUser: "Update remote user information"
|
|||
deleteAllFiles: "Delete all files"
|
||||
deleteAllFilesConfirm: "Are you sure that you want to delete all files?"
|
||||
removeAllFollowing: "Unfollow all followed users"
|
||||
removeAllFollowingDescription: "Executing this unfollows all accounts from {host}.\
|
||||
\ Please run this if the server e.g. no longer exists."
|
||||
removeAllFollowingDescription: "Executing this unfollows all accounts from {host}.
|
||||
Please run this if the server e.g. no longer exists."
|
||||
userSuspended: "This user has been suspended."
|
||||
userSilenced: "This user is being silenced."
|
||||
yourAccountSuspendedTitle: "This account is suspended"
|
||||
yourAccountSuspendedDescription: "This account has been suspended due to breaking\
|
||||
\ the server's terms of services or similar. Contact the administrator if you would\
|
||||
\ like to know a more detailed reason. Please do not create a new account."
|
||||
yourAccountSuspendedDescription: "This account has been suspended due to breaking
|
||||
the server's terms of services or similar. Contact the administrator if you would
|
||||
like to know a more detailed reason. Please do not create a new account."
|
||||
menu: "Menu"
|
||||
divider: "Divider"
|
||||
addItem: "Add Item"
|
||||
|
@ -651,14 +651,14 @@ permission: "Permissions"
|
|||
enableAll: "Enable all"
|
||||
disableAll: "Disable all"
|
||||
tokenRequested: "Grant access to account"
|
||||
pluginTokenRequestedDescription: "This plugin will be able to use the permissions\
|
||||
\ set here."
|
||||
pluginTokenRequestedDescription: "This plugin will be able to use the permissions
|
||||
set here."
|
||||
notificationType: "Notification type"
|
||||
edit: "Edit"
|
||||
emailServer: "Email server"
|
||||
enableEmail: "Enable email distribution"
|
||||
emailConfigInfo: "Used to confirm your email during sign-up or if you forget your\
|
||||
\ password"
|
||||
emailConfigInfo: "Used to confirm your email during sign-up or if you forget your
|
||||
password"
|
||||
email: "Email"
|
||||
emailAddress: "Email address"
|
||||
smtpConfig: "SMTP Server Configuration"
|
||||
|
@ -672,8 +672,8 @@ smtpSecureInfo: "Turn this off when using STARTTLS"
|
|||
testEmail: "Test email delivery"
|
||||
wordMute: "Word mute"
|
||||
regexpError: "Regular Expression error"
|
||||
regexpErrorDescription: "An error occurred in the regular expression on line {line}\
|
||||
\ of your {tab} word mutes:"
|
||||
regexpErrorDescription: "An error occurred in the regular expression on line {line}
|
||||
of your {tab} word mutes:"
|
||||
instanceMute: "Server Mutes"
|
||||
userSaysSomething: "{name} said something"
|
||||
userSaysSomethingReason: "{name} said {reason}"
|
||||
|
@ -694,13 +694,13 @@ create: "Create"
|
|||
notificationSetting: "Notification settings"
|
||||
notificationSettingDesc: "Select the types of notification to display."
|
||||
useGlobalSetting: "Use global settings"
|
||||
useGlobalSettingDesc: "If turned on, your account's notification settings will be\
|
||||
\ used. If turned off, individual configurations can be made."
|
||||
useGlobalSettingDesc: "If turned on, your account's notification settings will be
|
||||
used. If turned off, individual configurations can be made."
|
||||
other: "Other"
|
||||
regenerateLoginToken: "Regenerate login token"
|
||||
regenerateLoginTokenDescription: "Regenerates the token used internally during login.\
|
||||
\ Normally this action is not necessary. If regenerated, all devices will be logged\
|
||||
\ out."
|
||||
regenerateLoginTokenDescription: "Regenerates the token used internally during login.
|
||||
Normally this action is not necessary. If regenerated, all devices will be logged
|
||||
out."
|
||||
setMultipleBySeparatingWithSpace: "Separate multiple entries with spaces."
|
||||
fileIdOrUrl: "File ID or URL"
|
||||
behavior: "Behavior"
|
||||
|
@ -708,15 +708,15 @@ sample: "Sample"
|
|||
abuseReports: "Reports"
|
||||
reportAbuse: "Report"
|
||||
reportAbuseOf: "Report {name}"
|
||||
fillAbuseReportDescription: "Please fill in details regarding this report. If it is\
|
||||
\ about a specific post, please include its URL."
|
||||
fillAbuseReportDescription: "Please fill in details regarding this report. If it is
|
||||
about a specific post, please include its URL."
|
||||
abuseReported: "Your report has been sent. Thank you very much."
|
||||
reporter: "Reporter"
|
||||
reporteeOrigin: "Reportee Origin"
|
||||
reporterOrigin: "Reporter Origin"
|
||||
forwardReport: "Forward report to remote server"
|
||||
forwardReportIsAnonymous: "Instead of your account, an anonymous system account will\
|
||||
\ be displayed as reporter at the remote server."
|
||||
forwardReportIsAnonymous: "Instead of your account, an anonymous system account will
|
||||
be displayed as reporter at the remote server."
|
||||
send: "Send"
|
||||
abuseMarkAsResolved: "Mark report as resolved"
|
||||
openInNewTab: "Open in new tab"
|
||||
|
@ -734,11 +734,11 @@ createNew: "Create new"
|
|||
optional: "Optional"
|
||||
createNewClip: "Create new clip"
|
||||
unclip: "Unclip"
|
||||
confirmToUnclipAlreadyClippedNote: "This post is already part of the \"{name}\" clip.\
|
||||
\ Do you want to remove it from this clip instead?"
|
||||
confirmToUnclipAlreadyClippedNote: "This post is already part of the \"{name}\" clip.
|
||||
Do you want to remove it from this clip instead?"
|
||||
public: "Public"
|
||||
i18nInfo: "Calckey is being translated into various languages by volunteers. You can\
|
||||
\ help at {link}."
|
||||
i18nInfo: "Calckey is being translated into various languages by volunteers. You can
|
||||
help at {link}."
|
||||
manageAccessTokens: "Manage access tokens"
|
||||
accountInfo: "Account Info"
|
||||
notesCount: "Number of posts"
|
||||
|
@ -757,16 +757,15 @@ no: "No"
|
|||
driveFilesCount: "Number of Drive files"
|
||||
driveUsage: "Drive space usage"
|
||||
noCrawle: "Reject crawler indexing"
|
||||
noCrawleDescription: "Ask search engines to not index your profile page, posts, Pages,\
|
||||
\ etc."
|
||||
lockedAccountInfo: "Unless you set your post visiblity to \"Followers only\", your\
|
||||
\ posts will be visible to anyone, even if you require followers to be manually\
|
||||
\ approved."
|
||||
noCrawleDescription: "Ask search engines to not index your profile page, posts, Pages,
|
||||
etc."
|
||||
lockedAccountInfo: "Unless you set your post visiblity to \"Followers only\", your
|
||||
posts will be visible to anyone, even if you require followers to be manually approved."
|
||||
alwaysMarkSensitive: "Mark as NSFW by default"
|
||||
loadRawImages: "Load original images instead of showing thumbnails"
|
||||
disableShowingAnimatedImages: "Don't play animated images"
|
||||
verificationEmailSent: "A verification email has been sent. Please follow the included\
|
||||
\ link to complete verification."
|
||||
verificationEmailSent: "A verification email has been sent. Please follow the included
|
||||
link to complete verification."
|
||||
notSet: "Not set"
|
||||
emailVerified: "Email has been verified"
|
||||
noteFavoritesCount: "Number of bookmarked posts"
|
||||
|
@ -779,8 +778,8 @@ clipsDesc: "Clips are like share-able categorized bookmarks. You can create clip
|
|||
experimentalFeatures: "Experimental features"
|
||||
developer: "Developer"
|
||||
makeExplorable: "Make account visible in \"Explore\""
|
||||
makeExplorableDescription: "If you turn this off, your account will not show up in\
|
||||
\ the \"Explore\" section."
|
||||
makeExplorableDescription: "If you turn this off, your account will not show up in
|
||||
the \"Explore\" section."
|
||||
showGapBetweenNotesInTimeline: "Show a gap between posts on the timeline"
|
||||
duplicate: "Duplicate"
|
||||
left: "Left"
|
||||
|
@ -795,10 +794,10 @@ onlineUsersCount: "{n} users are online"
|
|||
nUsers: "{n} Users"
|
||||
nNotes: "{n} Posts"
|
||||
sendErrorReports: "Send error reports"
|
||||
sendErrorReportsDescription: "When turned on, detailed error information will be shared\
|
||||
\ with Calckey when a problem occurs, helping to improve the quality of Calckey.\n\
|
||||
This will include information such the version of your OS, what browser you're using,\
|
||||
\ your activity in Calckey, etc."
|
||||
sendErrorReportsDescription: "When turned on, detailed error information will be shared
|
||||
with Calckey when a problem occurs, helping to improve the quality of Calckey.\n
|
||||
This will include information such the version of your OS, what browser you're using,
|
||||
your activity in Calckey, etc."
|
||||
myTheme: "My theme"
|
||||
backgroundColor: "Background color"
|
||||
accentColor: "Accent color"
|
||||
|
@ -837,17 +836,17 @@ unlikeConfirm: "Really remove your like?"
|
|||
fullView: "Full view"
|
||||
quitFullView: "Exit full view"
|
||||
addDescription: "Add description"
|
||||
userPagePinTip: "You can display posts here by selecting \"Pin to profile\" from the\
|
||||
\ menu of individual posts."
|
||||
notSpecifiedMentionWarning: "This post contains mentions of users not included as\
|
||||
\ recipients"
|
||||
userPagePinTip: "You can display posts here by selecting \"Pin to profile\" from the
|
||||
menu of individual posts."
|
||||
notSpecifiedMentionWarning: "This post contains mentions of users not included as
|
||||
recipients"
|
||||
info: "About"
|
||||
userInfo: "User information"
|
||||
unknown: "Unknown"
|
||||
onlineStatus: "Online status"
|
||||
hideOnlineStatus: "Hide online status"
|
||||
hideOnlineStatusDescription: "Hiding your online status reduces the convenience of\
|
||||
\ some features such as the search."
|
||||
hideOnlineStatusDescription: "Hiding your online status reduces the convenience of
|
||||
some features such as the search."
|
||||
online: "Online"
|
||||
active: "Active"
|
||||
offline: "Offline"
|
||||
|
@ -884,15 +883,15 @@ secureMode: "Secure Mode (Authorized Fetch)"
|
|||
instanceSecurity: "Server Security"
|
||||
secureModeInfo: "When requesting from other servers, do not send back without proof."
|
||||
privateMode: "Private Mode"
|
||||
privateModeInfo: "When enabled, only whitelisted servers can federate with your\
|
||||
\ server. All posts will be hidden from the public."
|
||||
privateModeInfo: "When enabled, only whitelisted servers can federate with your server.
|
||||
All posts will be hidden from the public."
|
||||
allowedInstances: "Whitelisted Servers"
|
||||
allowedInstancesDescription: "Hosts of servers to be whitelisted for federation,\
|
||||
\ each separated by a new line (only applies in private mode)."
|
||||
allowedInstancesDescription: "Hosts of servers to be whitelisted for federation, each
|
||||
separated by a new line (only applies in private mode)."
|
||||
previewNoteText: "Show preview"
|
||||
customCss: "Custom CSS"
|
||||
customCssWarn: "This setting should only be used if you know what it does. Entering\
|
||||
\ improper values may cause the client to stop functioning normally."
|
||||
customCssWarn: "This setting should only be used if you know what it does. Entering
|
||||
improper values may cause the client to stop functioning normally."
|
||||
global: "Global"
|
||||
recommended: "Recommended"
|
||||
squareAvatars: "Display squared avatars"
|
||||
|
@ -909,9 +908,9 @@ whatIsNew: "Show changes"
|
|||
translate: "Translate"
|
||||
translatedFrom: "Translated from {x}"
|
||||
accountDeletionInProgress: "Account deletion is currently in progress"
|
||||
usernameInfo: "A name that identifies your account from others on this server. You\
|
||||
\ can use the alphabet (a~z, A~Z), digits (0~9) or underscores (_). Usernames cannot\
|
||||
\ be changed later."
|
||||
usernameInfo: "A name that identifies your account from others on this server. You
|
||||
can use the alphabet (a~z, A~Z), digits (0~9) or underscores (_). Usernames cannot
|
||||
be changed later."
|
||||
aiChanMode: "Ai-chan in Classic UI"
|
||||
keepCw: "Keep content warnings"
|
||||
pubSub: "Pub/Sub Accounts"
|
||||
|
@ -928,14 +927,14 @@ filter: "Filter"
|
|||
controlPanel: "Control Panel"
|
||||
manageAccounts: "Manage Accounts"
|
||||
makeReactionsPublic: "Set reaction history to public"
|
||||
makeReactionsPublicDescription: "This will make the list of all your past reactions\
|
||||
\ publicly visible."
|
||||
makeReactionsPublicDescription: "This will make the list of all your past reactions
|
||||
publicly visible."
|
||||
classic: "Centered"
|
||||
muteThread: "Mute thread"
|
||||
unmuteThread: "Unmute thread"
|
||||
ffVisibility: "Follows/Followers Visibility"
|
||||
ffVisibilityDescription: "Allows you to configure who can see who you follow and who\
|
||||
\ follows you."
|
||||
ffVisibilityDescription: "Allows you to configure who can see who you follow and who
|
||||
follows you."
|
||||
continueThread: "Continue thread"
|
||||
deleteAccountConfirm: "This will irreversibly delete your account. Proceed?"
|
||||
incorrectPassword: "Incorrect password."
|
||||
|
@ -975,16 +974,18 @@ noEmailServerWarning: "Email server not configured."
|
|||
thereIsUnresolvedAbuseReportWarning: "There are unsolved reports."
|
||||
check: "Check"
|
||||
driveCapOverrideLabel: "Change the drive capacity for this user"
|
||||
driveCapOverrideCaption: "Reset the capacity to default by inputting a value of 0\
|
||||
\ or lower."
|
||||
driveCapOverrideCaption: "Reset the capacity to default by inputting a value of 0
|
||||
or lower."
|
||||
requireAdminForView: "You must log in with an administrator account to view this."
|
||||
isSystemAccount: "This account is created and automatically operated by the system. Please do not moderate, edit, delete, or otherwise tamper with this account, or it may break your server."
|
||||
isSystemAccount: "This account is created and automatically operated by the system.
|
||||
Please do not moderate, edit, delete, or otherwise tamper with this account, or
|
||||
it may break your server."
|
||||
typeToConfirm: "Please enter {x} to confirm"
|
||||
deleteAccount: "Delete account"
|
||||
document: "Documentation"
|
||||
numberOfPageCache: "Number of cached pages"
|
||||
numberOfPageCacheDescription: "Increasing this number will improve convenience for\
|
||||
\ users but cause more server load as well as more memory to be used."
|
||||
numberOfPageCacheDescription: "Increasing this number will improve convenience for
|
||||
users but cause more server load as well as more memory to be used."
|
||||
logoutConfirm: "Really log out?"
|
||||
lastActiveDate: "Last used at"
|
||||
statusbar: "Status bar"
|
||||
|
@ -1001,19 +1002,19 @@ sensitiveMediaDetection: "Detection of NSFW media"
|
|||
localOnly: "Local only"
|
||||
remoteOnly: "Remote only"
|
||||
failedToUpload: "Upload failed"
|
||||
cannotUploadBecauseInappropriate: "This file could not be uploaded because parts of\
|
||||
\ it have been detected as potentially NSFW."
|
||||
cannotUploadBecauseInappropriate: "This file could not be uploaded because parts of
|
||||
it have been detected as potentially NSFW."
|
||||
cannotUploadBecauseNoFreeSpace: "Upload failed due to lack of Drive capacity."
|
||||
cannotUploadBecauseExceedsFileSizeLimit: "This file could not be uploaded because\
|
||||
\ it exceeds the maximum allowed size."
|
||||
cannotUploadBecauseExceedsFileSizeLimit: "This file could not be uploaded because
|
||||
it exceeds the maximum allowed size."
|
||||
beta: "Beta"
|
||||
enableAutoSensitive: "Automatic NSFW-Marking"
|
||||
enableAutoSensitiveDescription: "Allows automatic detection and marking of NSFW media\
|
||||
\ through Machine Learning where possible. Even if this option is disabled, it may\
|
||||
\ be enabled server-wide."
|
||||
activeEmailValidationDescription: "Enables stricter validation of email addresses,\
|
||||
\ which includes checking for disposable addresses and by whether it can actually\
|
||||
\ be communicated with. When unchecked, only the format of the email is validated."
|
||||
enableAutoSensitiveDescription: "Allows automatic detection and marking of NSFW media
|
||||
through Machine Learning where possible. Even if this option is disabled, it may
|
||||
be enabled server-wide."
|
||||
activeEmailValidationDescription: "Enables stricter validation of email addresses,
|
||||
which includes checking for disposable addresses and by whether it can actually
|
||||
be communicated with. When unchecked, only the format of the email is validated."
|
||||
navbar: "Navigation bar"
|
||||
shuffle: "Shuffle"
|
||||
account: "Account"
|
||||
|
@ -1023,27 +1024,27 @@ subscribePushNotification: "Enable push notifications"
|
|||
unsubscribePushNotification: "Disable push notifications"
|
||||
pushNotificationAlreadySubscribed: "Push notifications are already enabled"
|
||||
pushNotificationNotSupported: "Your browser or server does not support push notifications"
|
||||
sendPushNotificationReadMessage: "Delete push notifications once the relevant notifications\
|
||||
\ or messages have been read"
|
||||
sendPushNotificationReadMessage: "Delete push notifications once the relevant notifications
|
||||
or messages have been read"
|
||||
sendPushNotificationReadMessageCaption: "A notification containing the text \"{emptyPushNotificationMessage}\"\
|
||||
\ will be displayed for a short time. This may increase the battery usage of your\
|
||||
\ device, if applicable."
|
||||
\ will be displayed for a short time. This may increase the battery usage of your
|
||||
device, if applicable."
|
||||
showAds: "Show ads"
|
||||
enterSendsMessage: "Press Return in Messaging to send message (off is Ctrl + Return)"
|
||||
adminCustomCssWarn: "This setting should only be used if you know what it does. Entering\
|
||||
\ improper values may cause EVERYONE'S clients to stop functioning normally. Please\
|
||||
\ ensure your CSS works properly by testing it in your user settings."
|
||||
adminCustomCssWarn: "This setting should only be used if you know what it does. Entering
|
||||
improper values may cause EVERYONE'S clients to stop functioning normally. Please
|
||||
ensure your CSS works properly by testing it in your user settings."
|
||||
customMOTD: "Custom MOTD (splash screen messages)"
|
||||
customMOTDDescription: "Custom messages for the MOTD (splash screen) separated by\
|
||||
\ line breaks to be shown randomly every time a user loads/reloads the page."
|
||||
customMOTDDescription: "Custom messages for the MOTD (splash screen) separated by
|
||||
line breaks to be shown randomly every time a user loads/reloads the page."
|
||||
customSplashIcons: "Custom splash screen icons (urls)"
|
||||
customSplashIconsDescription: "URLs for custom splash screen icons separated by line\
|
||||
\ breaks to be shown randomly every time a user loads/reloads the page. Please make\
|
||||
\ sure the images are on a static URL, preferably all resized to 192x192."
|
||||
customSplashIconsDescription: "URLs for custom splash screen icons separated by line
|
||||
breaks to be shown randomly every time a user loads/reloads the page. Please make
|
||||
sure the images are on a static URL, preferably all resized to 192x192."
|
||||
showUpdates: "Show a popup when Calckey updates"
|
||||
recommendedInstances: "Recommended servers"
|
||||
recommendedInstancesDescription: "Recommended servers separated by line breaks to\
|
||||
\ appear in the recommended timeline. Do NOT add `https://`, ONLY the domain."
|
||||
recommendedInstancesDescription: "Recommended servers separated by line breaks to
|
||||
appear in the recommended timeline. Do NOT add `https://`, ONLY the domain."
|
||||
caption: "Auto Caption"
|
||||
splash: "Splash Screen"
|
||||
updateAvailable: "There might be an update available!"
|
||||
|
@ -1055,18 +1056,18 @@ migration: "Migration"
|
|||
moveTo: "Move current account to new account"
|
||||
moveToLabel: "Account you're moving to:"
|
||||
moveAccount: "Move account!"
|
||||
moveAccountDescription: "This process is irreversible. Make sure you've set up an\
|
||||
\ alias for this account on your new account before moving. Please enter the tag\
|
||||
\ of the account formatted like @person@server.com"
|
||||
moveAccountDescription: "This process is irreversible. Make sure you've set up an
|
||||
alias for this account on your new account before moving. Please enter the tag of
|
||||
the account formatted like @person@server.com"
|
||||
moveFrom: "Move to this account from an older account"
|
||||
moveFromLabel: "Account you're moving from:"
|
||||
moveFromDescription: "This will set an alias of your old account so that you can move\
|
||||
\ from that account to this current one. Do this BEFORE moving from your older account.\
|
||||
\ Please enter the tag of the account formatted like @person@server.com"
|
||||
migrationConfirm: "Are you absolutely sure you want to migrate your account to {account}?\
|
||||
\ Once you do this, you won't be able to reverse it, and you won't be able to use\
|
||||
\ your account normally again.\nAlso, please ensure that you've set this current\
|
||||
\ account as the account you're moving from."
|
||||
moveFromDescription: "This will set an alias of your old account so that you can move
|
||||
from that account to this current one. Do this BEFORE moving from your older account.
|
||||
Please enter the tag of the account formatted like @person@server.com"
|
||||
migrationConfirm: "Are you absolutely sure you want to migrate your account to {account}?
|
||||
Once you do this, you won't be able to reverse it, and you won't be able to use
|
||||
your account normally again.\nAlso, please ensure that you've set this current account
|
||||
as the account you're moving from."
|
||||
defaultReaction: "Default emoji reaction for outgoing and incoming posts"
|
||||
license: "License"
|
||||
indexPosts: "Index Posts"
|
||||
|
@ -1075,42 +1076,49 @@ indexFromDescription: "Leave blank to index every post"
|
|||
indexNotice: "Now indexing. This will probably take a while, please don't restart\
|
||||
\ your server for at least an hour."
|
||||
customKaTeXMacro: "Custom KaTeX macros"
|
||||
customKaTeXMacroDescription: "Set up macros to write mathematical expressions easily!\
|
||||
\ The notation conforms to the LaTeX command definitions and is written as \\newcommand{\\\
|
||||
name}{content} or \\newcommand{\\name}[number of arguments]{content}. For example,\
|
||||
\ \\newcommand{\\add}[2]{#1 + #2} will expand \\add{3}{foo} to 3 + foo. The curly\
|
||||
\ brackets surrounding the macro name can be changed to round or square brackets.\
|
||||
\ This affects the brackets used for arguments. One (and only one) macro can be\
|
||||
\ defined per line, and you can't break the line in the middle of the definition.\
|
||||
\ Invalid lines are simply ignored. Only simple string substitution functions are\
|
||||
\ supported; advanced syntax, such as conditional branching, cannot be used here."
|
||||
customKaTeXMacroDescription: "Set up macros to write mathematical expressions easily!
|
||||
The notation conforms to the LaTeX command definitions and is written as \\newcommand{\\
|
||||
name}{content} or \\newcommand{\\name}[number of arguments]{content}. For example,
|
||||
\\newcommand{\\add}[2]{#1 + #2} will expand \\add{3}{foo} to 3 + foo. The curly
|
||||
brackets surrounding the macro name can be changed to round or square brackets.
|
||||
This affects the brackets used for arguments. One (and only one) macro can be defined
|
||||
per line, and you can't break the line in the middle of the definition. Invalid
|
||||
lines are simply ignored. Only simple string substitution functions are supported;
|
||||
advanced syntax, such as conditional branching, cannot be used here."
|
||||
enableCustomKaTeXMacro: "Enable custom KaTeX macros"
|
||||
noteId: "Post ID"
|
||||
signupsDisabled: "Signups on this server are currently disabled, but you can always\
|
||||
\ sign up at another server! If you have an invitation code for this server, please\
|
||||
\ enter it below."
|
||||
signupsDisabled: "Signups on this server are currently disabled, but you can always
|
||||
sign up at another server! If you have an invitation code for this server, please
|
||||
enter it below."
|
||||
findOtherInstance: "Find another server"
|
||||
apps: "Apps"
|
||||
sendModMail: "Send Moderation Notice"
|
||||
preventAiLearning: "Prevent AI bot scraping"
|
||||
preventAiLearningDescription: "Request third-party AI language models not to study\
|
||||
\ content you upload, such as posts and images."
|
||||
noGraze: "Please disable the \"Graze for Mastodon\" browser extension, as it interferes with Calckey."
|
||||
silencedWarning: "This page is showing because these usera are from servers your admin silenced, so they may potentially be spam."
|
||||
preventAiLearningDescription: "Request third-party AI language models not to study
|
||||
content you upload, such as posts and images."
|
||||
noGraze: "Please disable the \"Graze for Mastodon\" browser extension, as it interferes
|
||||
with Calckey."
|
||||
silencedWarning: "This page is showing because these users are from servers your admin
|
||||
silenced, so they may potentially be spam."
|
||||
isBot: "This account is a bot"
|
||||
isLocked: "This account has follow approvals"
|
||||
isModerator: "Moderator"
|
||||
isAdmin: "Administrator"
|
||||
isPatron: "Calckey Patron"
|
||||
|
||||
_sensitiveMediaDetection:
|
||||
description: "Reduces the effort of server moderation through automatically recognizing\
|
||||
\ NSFW media via Machine Learning. This will slightly increase the load on the\
|
||||
\ server."
|
||||
description: "Reduces the effort of server moderation through automatically recognizing
|
||||
NSFW media via Machine Learning. This will slightly increase the load on the server."
|
||||
sensitivity: "Detection sensitivity"
|
||||
sensitivityDescription: "Reducing the sensitivity will lead to fewer misdetections\
|
||||
\ (false positives) whereas increasing it will lead to fewer missed detections\
|
||||
\ (false negatives)."
|
||||
sensitivityDescription: "Reducing the sensitivity will lead to fewer misdetections
|
||||
(false positives) whereas increasing it will lead to fewer missed detections (false
|
||||
negatives)."
|
||||
setSensitiveFlagAutomatically: "Mark as NSFW"
|
||||
setSensitiveFlagAutomaticallyDescription: "The results of the internal detection\
|
||||
\ will be retained even if this option is turned off."
|
||||
setSensitiveFlagAutomaticallyDescription: "The results of the internal detection
|
||||
will be retained even if this option is turned off."
|
||||
analyzeVideos: "Enable analysis of videos"
|
||||
analyzeVideosDescription: "Analyzes videos in addition to images. This will slightly\
|
||||
\ increase the load on the server."
|
||||
analyzeVideosDescription: "Analyzes videos in addition to images. This will slightly
|
||||
increase the load on the server."
|
||||
_emailUnavailable:
|
||||
used: "This email address is already being used"
|
||||
format: "The format of this email address is invalid"
|
||||
|
@ -1124,15 +1132,15 @@ _ffVisibility:
|
|||
_signup:
|
||||
almostThere: "Almost there"
|
||||
emailAddressInfo: "Please enter your email address. It will not be made public."
|
||||
emailSent: "A confirmation email has been sent to your email address ({email}).\
|
||||
\ Please click the included link to complete account creation."
|
||||
emailSent: "A confirmation email has been sent to your email address ({email}).
|
||||
Please click the included link to complete account creation."
|
||||
_accountDelete:
|
||||
accountDelete: "Delete account"
|
||||
mayTakeTime: "As account deletion is a resource-heavy process, it may take some\
|
||||
\ time to complete depending on how much content you have created and how many\
|
||||
\ files you have uploaded."
|
||||
sendEmail: "Once account deletion has been completed, an email will be sent to the\
|
||||
\ email address registered to this account."
|
||||
mayTakeTime: "As account deletion is a resource-heavy process, it may take some
|
||||
time to complete depending on how much content you have created and how many files
|
||||
you have uploaded."
|
||||
sendEmail: "Once account deletion has been completed, an email will be sent to the
|
||||
email address registered to this account."
|
||||
requestAccountDelete: "Request account deletion"
|
||||
started: "Deletion has been started."
|
||||
inProgress: "Deletion is currently in progress"
|
||||
|
@ -1140,12 +1148,12 @@ _ad:
|
|||
back: "Back"
|
||||
reduceFrequencyOfThisAd: "Show this ad less"
|
||||
_forgotPassword:
|
||||
enterEmail: "Enter the email address you used to register. A link with which you\
|
||||
\ can reset your password will then be sent to it."
|
||||
ifNoEmail: "If you did not use an email during registration, please contact the\
|
||||
\ server administrator instead."
|
||||
contactAdmin: "This server does not support using email addresses, please contact\
|
||||
\ the server administrator to reset your password instead."
|
||||
enterEmail: "Enter the email address you used to register. A link with which you
|
||||
can reset your password will then be sent to it."
|
||||
ifNoEmail: "If you did not use an email during registration, please contact the
|
||||
server administrator instead."
|
||||
contactAdmin: "This server does not support using email addresses, please contact
|
||||
the server administrator to reset your password instead."
|
||||
_gallery:
|
||||
my: "My Gallery"
|
||||
liked: "Liked Posts"
|
||||
|
@ -1168,15 +1176,15 @@ _preferencesBackups:
|
|||
save: "Save changes"
|
||||
inputName: "Please enter a name for this backup"
|
||||
cannotSave: "Saving failed"
|
||||
nameAlreadyExists: "A backup called \"{name}\" already exists. Please enter a different\
|
||||
\ name."
|
||||
applyConfirm: "Do you really want to apply the \"{name}\" backup to this device?\
|
||||
\ Existing settings of this device will be overwritten."
|
||||
nameAlreadyExists: "A backup called \"{name}\" already exists. Please enter a different
|
||||
name."
|
||||
applyConfirm: "Do you really want to apply the \"{name}\" backup to this device?
|
||||
Existing settings of this device will be overwritten."
|
||||
saveConfirm: "Save backup as {name}?"
|
||||
deleteConfirm: "Delete the {name} backup?"
|
||||
renameConfirm: "Rename this backup from \"{old}\" to \"{new}\"?"
|
||||
noBackups: "No backups exist. You may backup your client settings on this server\
|
||||
\ by using \"Create new backup\"."
|
||||
noBackups: "No backups exist. You may backup your client settings on this server
|
||||
by using \"Create new backup\"."
|
||||
createdAt: "Created at: {date} {time}"
|
||||
updatedAt: "Updated at: {date} {time}"
|
||||
cannotLoad: "Loading failed"
|
||||
|
@ -1188,15 +1196,15 @@ _registry:
|
|||
domain: "Domain"
|
||||
createKey: "Create key"
|
||||
_aboutMisskey:
|
||||
about: "Calckey is a fork of Misskey made by ThatOneCalculator, which has been in\
|
||||
\ development since 2022."
|
||||
about: "Calckey is a fork of Misskey made by ThatOneCalculator, which has been in
|
||||
development since 2022."
|
||||
contributors: "Main contributors"
|
||||
allContributors: "All contributors"
|
||||
source: "Source code"
|
||||
translation: "Translate Calckey"
|
||||
donate: "Donate to Calckey"
|
||||
morePatrons: "We also appreciate the support of many other helpers not listed here.\
|
||||
\ Thank you! \U0001F970"
|
||||
morePatrons: "We also appreciate the support of many other helpers not listed here.
|
||||
Thank you! 🥰"
|
||||
patrons: "Calckey patrons"
|
||||
_nsfw:
|
||||
respect: "Hide NSFW media"
|
||||
|
@ -1208,9 +1216,11 @@ _mfm:
|
|||
warn: "MFM may contain rapidly moving or flashy animations"
|
||||
alwaysPlay: "Always autoplay all animated MFM"
|
||||
cheatSheet: "MFM Cheatsheet"
|
||||
intro: "MFM is a markup language used on Misskey, Calckey, Akkoma, and more that\
|
||||
\ can be used in many places. Here you can view a list of all available MFM syntax."
|
||||
intro: "MFM is a markup language used on Misskey, Calckey, Akkoma, and more that
|
||||
can be used in many places. Here you can view a list of all available MFM syntax."
|
||||
dummy: "Calckey expands the world of the Fediverse"
|
||||
advanced: "Advanced MFM"
|
||||
advancedDescription: "If disabled, only allows for basic markup unless animated MFM is playing"
|
||||
mention: "Mention"
|
||||
mentionDescription: "You can specify a user by using an At-Symbol and a username."
|
||||
hashtag: "Hashtag"
|
||||
|
@ -1228,8 +1238,8 @@ _mfm:
|
|||
inlineCode: "Code (Inline)"
|
||||
inlineCodeDescription: "Displays inline syntax highlighting for (program) code."
|
||||
blockCode: "Code (Block)"
|
||||
blockCodeDescription: "Displays syntax highlighting for multi-line (program) code\
|
||||
\ in a block."
|
||||
blockCodeDescription: "Displays syntax highlighting for multi-line (program) code
|
||||
in a block."
|
||||
inlineMath: "Math (Inline)"
|
||||
inlineMathDescription: "Display math formulas (KaTeX) in-line"
|
||||
blockMath: "Math (Block)"
|
||||
|
@ -1237,8 +1247,8 @@ _mfm:
|
|||
quote: "Quote"
|
||||
quoteDescription: "Displays content as a quote."
|
||||
emoji: "Custom Emoji"
|
||||
emojiDescription: "By surrounding a custom emoji name with colons, custom emoji\
|
||||
\ can be displayed."
|
||||
emojiDescription: "By surrounding a custom emoji name with colons, custom emoji
|
||||
can be displayed."
|
||||
search: "Search"
|
||||
searchDescription: "Displays a search box with pre-entered text."
|
||||
flip: "Flip"
|
||||
|
@ -1286,8 +1296,8 @@ _mfm:
|
|||
background: "Background color"
|
||||
backgroundDescription: "Change the background color of text."
|
||||
plain: "Plain"
|
||||
plainDescription: "Deactivates the effects of all MFM contained within this MFM\
|
||||
\ effect."
|
||||
plainDescription: "Deactivates the effects of all MFM contained within this MFM
|
||||
effect."
|
||||
_instanceTicker:
|
||||
none: "Never show"
|
||||
remote: "Show for remote users"
|
||||
|
@ -1319,19 +1329,19 @@ _menuDisplay:
|
|||
hide: "Hide"
|
||||
_wordMute:
|
||||
muteWords: "Muted words"
|
||||
muteWordsDescription: "Separate with spaces for an AND condition or with line breaks\
|
||||
\ for an OR condition."
|
||||
muteWordsDescription: "Separate with spaces for an AND condition or with line breaks
|
||||
for an OR condition."
|
||||
muteWordsDescription2: "Surround keywords with slashes to use regular expressions."
|
||||
softDescription: "Hide posts that fulfil the set conditions from the timeline."
|
||||
hardDescription: "Prevents posts fulfilling the set conditions from being added\
|
||||
\ to the timeline. In addition, these posts will not be added to the timeline\
|
||||
\ even if the conditions are changed."
|
||||
hardDescription: "Prevents posts fulfilling the set conditions from being added
|
||||
to the timeline. In addition, these posts will not be added to the timeline even
|
||||
if the conditions are changed."
|
||||
soft: "Soft"
|
||||
hard: "Hard"
|
||||
mutedNotes: "Muted posts"
|
||||
_instanceMute:
|
||||
instanceMuteDescription: "This will mute any posts/boosts from the listed servers,\
|
||||
\ including those of users replying to a user from a muted server."
|
||||
instanceMuteDescription: "This will mute any posts/boosts from the listed servers,
|
||||
including those of users replying to a user from a muted server."
|
||||
instanceMuteDescription2: "Separate with newlines"
|
||||
title: "Hides posts from listed servers."
|
||||
heading: "List of servers to be muted"
|
||||
|
@ -1437,31 +1447,32 @@ _tutorial:
|
|||
step1_1: "Welcome!"
|
||||
step1_2: "Let's get you set up. You'll be up and running in no time!"
|
||||
step2_1: "First, please fill out your profile."
|
||||
step2_2: "Providing some information about who you are will make it easier for others\
|
||||
\ to tell if they want to see your posts or follow you."
|
||||
step2_2: "Providing some information about who you are will make it easier for others
|
||||
to tell if they want to see your posts or follow you."
|
||||
step3_1: "Now it's time to follow some people!"
|
||||
step3_2: "Your home and social timelines are based off of who you follow, so try\
|
||||
\ following a couple accounts to get started.\nClick the plus circle on the top\
|
||||
\ right of a profile to follow them."
|
||||
step3_2: "Your home and social timelines are based off of who you follow, so try
|
||||
following a couple accounts to get started.\nClick the plus circle on the top
|
||||
right of a profile to follow them."
|
||||
step4_1: "Let's get you out there."
|
||||
step4_2: "For your first post, some people like to make an {introduction} post or\
|
||||
\ a simple \"Hello world!\""
|
||||
step4_2: "For your first post, some people like to make an {introduction} post or
|
||||
a simple \"Hello world!\""
|
||||
step5_1: "Timelines, timelines everywhere!"
|
||||
step5_2: "Your server has {timelines} different timelines enabled."
|
||||
step5_3: "The Home {icon} timeline is where you can see posts from the accounts\
|
||||
\ you follow."
|
||||
step5_4: "The Local {icon} timeline is where you can see posts from everyone else on this server."
|
||||
step5_3: "The Home {icon} timeline is where you can see posts from the accounts
|
||||
you follow."
|
||||
step5_4: "The Local {icon} timeline is where you can see posts from everyone else
|
||||
on this server."
|
||||
step5_5: "The Social {icon} timeline is a combination of the Home and Local timelines."
|
||||
step5_6: "The Recommended {icon} timeline is where you can see posts from servers\
|
||||
\ the admins recommend."
|
||||
step5_7: "The Global {icon} timeline is where you can see posts from every other\
|
||||
\ connected server."
|
||||
step6_1: "So, what is this place?"
|
||||
step6_2: "Well, you didn't just join Calckey. You joined a portal to the Fediverse,\
|
||||
\ an interconnected network of thousands of servers."
|
||||
step6_3: "Each server works in different ways, and not all servers run Calckey.\
|
||||
\ This one does though! It's a bit complicated, but you'll get the hang of it\
|
||||
\ in no time."
|
||||
step6_2: "Well, you didn't just join Calckey. You joined a portal to the Fediverse,
|
||||
an interconnected network of thousands of servers."
|
||||
step6_3: "Each server works in different ways, and not all servers run Calckey.
|
||||
This one does though! It's a bit complicated, but you'll get the hang of it in
|
||||
no time."
|
||||
step6_4: "Now go, explore, and have fun!"
|
||||
_2fa:
|
||||
alreadyRegistered: "You have already registered a 2-factor authentication device."
|
||||
|
@ -1472,9 +1483,9 @@ _2fa:
|
|||
step2Url: "You can also enter this URL if you're using a desktop program:"
|
||||
step3: "Enter the token provided by your app to finish setup."
|
||||
step4: "From now on, any future login attempts will ask for such a login token."
|
||||
securityKeyInfo: "Besides fingerprint or PIN authentication, you can also setup\
|
||||
\ authentication via hardware security keys that support FIDO2 to further secure\
|
||||
\ your account."
|
||||
securityKeyInfo: "Besides fingerprint or PIN authentication, you can also setup
|
||||
authentication via hardware security keys that support FIDO2 to further secure
|
||||
your account."
|
||||
_permissions:
|
||||
"read:account": "View your account information"
|
||||
"write:account": "Edit your account information"
|
||||
|
@ -1510,8 +1521,8 @@ _permissions:
|
|||
"write:gallery-likes": "Edit your list of liked gallery posts"
|
||||
_auth:
|
||||
shareAccess: "Would you like to authorize \"{name}\" to access this account?"
|
||||
shareAccessAsk: "Are you sure you want to authorize this application to access your\
|
||||
\ account?"
|
||||
shareAccessAsk: "Are you sure you want to authorize this application to access your
|
||||
account?"
|
||||
permissionAsk: "This application requests the following permissions"
|
||||
pleaseGoBack: "Please go back to the application"
|
||||
callback: "Returning to the application"
|
||||
|
@ -1618,14 +1629,14 @@ _profile:
|
|||
youCanIncludeHashtags: "You can also include hashtags in your bio."
|
||||
metadata: "Additional Information"
|
||||
metadataEdit: "Edit additional Information"
|
||||
metadataDescription: "Using these, you can display additional information fields\
|
||||
\ in your profile."
|
||||
metadataDescription: "Using these, you can display additional information fields
|
||||
in your profile."
|
||||
metadataLabel: "Label"
|
||||
metadataContent: "Content"
|
||||
changeAvatar: "Change avatar"
|
||||
changeBanner: "Change banner"
|
||||
locationDescription: "If you enter your city first, it will display your local time\
|
||||
\ to other users."
|
||||
locationDescription: "If you enter your city first, it will display your local time
|
||||
to other users."
|
||||
_exportOrImport:
|
||||
allNotes: "All posts"
|
||||
followingList: "Followed users"
|
||||
|
@ -1943,8 +1954,8 @@ _pages:
|
|||
_for:
|
||||
arg1: "Number of times to repeat"
|
||||
arg2: "Action"
|
||||
typeError: "Slot {slot} accepts values of type \"{expect}\", but the provided\
|
||||
\ value is of type \"{actual}\"!"
|
||||
typeError: "Slot {slot} accepts values of type \"{expect}\", but the provided
|
||||
value is of type \"{actual}\"!"
|
||||
thereIsEmptySlot: "Slot {slot} is empty!"
|
||||
types:
|
||||
string: "Text"
|
||||
|
@ -2013,24 +2024,25 @@ _deck:
|
|||
deleteProfile: "Delete workspace"
|
||||
nameAlreadyExists: "This workspace name already exists."
|
||||
introduction: "Create the perfect interface for you by arranging columns freely!"
|
||||
introduction2: "Click on the + on the right of the screen to add new colums whenever\
|
||||
\ you want."
|
||||
widgetsIntroduction: "Please select \"Edit widgets\" in the column menu and add\
|
||||
\ a widget."
|
||||
introduction2: "Click on the + on the right of the screen to add new colums whenever
|
||||
you want."
|
||||
widgetsIntroduction: "Please select \"Edit widgets\" in the column menu and add
|
||||
a widget."
|
||||
_columns:
|
||||
main: "Main"
|
||||
widgets: "Widgets"
|
||||
notifications: "Notifications"
|
||||
tl: "Timeline"
|
||||
antenna: "Antennas"
|
||||
antenna: "Antenna"
|
||||
list: "List"
|
||||
channel: "Channel"
|
||||
mentions: "Mentions"
|
||||
direct: "Direct messages"
|
||||
_experiments:
|
||||
title: "Experiments"
|
||||
enablePostEditing: "Enable post editing"
|
||||
postEditingCaption: "Shows the option for users to edit their existing posts via\
|
||||
\ the post options menu."
|
||||
\ the post options menu, and allows post edits from other instances to be recieved."
|
||||
enablePostImports: "Enable post imports"
|
||||
postImportsCaption: "Allows users to import their posts from past Calckey,\
|
||||
\ Misskey, Mastodon, Akkoma, and Pleroma accounts. It may cause slowdowns during\
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
_lang_: "日本語"
|
||||
headlineMisskey: "ずっと無料でオープンソースの非中央集権型ソーシャルメディアプラットフォーム\U0001F680"
|
||||
introMisskey: "ようこそ!Calckeyは、オープンソースの非中央集権型ソーシャルメディアプラットフォームです。\nいま起こっていることを共有したり、あなたについて皆に発信しましょう\U0001F4E1\
|
||||
\n「リアクション」機能で、皆の投稿に素早く反応を追加できます\U0001F44D\n新しい世界を探検しよう\U0001F680"
|
||||
headlineMisskey: "ずっと無料でオープンソースの非中央集権型ソーシャルメディアプラットフォーム🚀"
|
||||
introMisskey: "ようこそ!Calckeyは、オープンソースの非中央集権型ソーシャルメディアプラットフォームです。\nいま起こっていることを共有したり、あなたについて皆に発信しましょう📡\n\
|
||||
「リアクション」機能で、皆の投稿に素早く反応を追加できます👍\n新しい世界を探検しよう🚀"
|
||||
monthAndDay: "{month}月 {day}日"
|
||||
search: "検索"
|
||||
notifications: "通知"
|
||||
|
@ -17,7 +17,7 @@ enterUsername: "ユーザー名を入力"
|
|||
renotedBy: "{user}がブースト"
|
||||
noNotes: "投稿はありません"
|
||||
noNotifications: "通知はありません"
|
||||
instance: "インスタンス"
|
||||
instance: "サーバー"
|
||||
settings: "設定"
|
||||
basicSettings: "基本設定"
|
||||
otherSettings: "その他の設定"
|
||||
|
@ -33,7 +33,7 @@ uploading: "アップロード中"
|
|||
save: "保存"
|
||||
users: "ユーザー"
|
||||
addUser: "ユーザーを追加"
|
||||
addInstance: "インスタンスを追加"
|
||||
addInstance: "サーバーを追加"
|
||||
favorite: "お気に入り"
|
||||
favorites: "お気に入り"
|
||||
unfavorite: "お気に入り解除"
|
||||
|
@ -133,6 +133,7 @@ unsuspendConfirm: "解凍しますか?"
|
|||
selectList: "リストを選択"
|
||||
selectAntenna: "アンテナを選択"
|
||||
selectWidget: "ウィジェットを選択"
|
||||
selectChannel: "チャンネルを選択"
|
||||
editWidgets: "ウィジェットを編集"
|
||||
editWidgetsExit: "編集を終了"
|
||||
customEmojis: "カスタム絵文字"
|
||||
|
@ -146,7 +147,7 @@ cacheRemoteFiles: "リモートのファイルをキャッシュする"
|
|||
cacheRemoteFilesDescription: "この設定を無効にすると、リモートファイルをキャッシュせず直リンクします。サーバーのストレージを節約できますが、サムネイルが生成されないので通信量が増加します。"
|
||||
flagAsBot: "Botとして設定"
|
||||
flagAsBotDescription: "このアカウントがBotである場合は、この設定をオンにします。オンにすると、反応の連鎖を防ぐためのフラグとして他の開発者に役立ったり、Calckeyのシステム上での扱いがBotに合ったものになります。"
|
||||
flagAsCat: "あなたは…猫?\U0001F63A"
|
||||
flagAsCat: "あなたは…猫?😺"
|
||||
flagAsCatDescription: "このアカウントが猫であることを示す猫モードを有効にするには、このフラグをオンにします。"
|
||||
flagSpeakAsCat: "猫語で話す"
|
||||
flagSpeakAsCatDescription: "猫モードが有効の場合にオンにすると、あなたの投稿の「な」を「にゃ」に変換します。"
|
||||
|
@ -165,14 +166,14 @@ searchWith: "検索: {q}"
|
|||
youHaveNoLists: "リストがありません"
|
||||
followConfirm: "{name}をフォローしますか?"
|
||||
proxyAccount: "プロキシアカウント"
|
||||
proxyAccountDescription: "プロキシアカウントは、特定の条件下でユーザーのリモートフォローを代行するアカウントです。例えば、ユーザーがリモートユーザーをリストに入れたとき、リストに入れられたユーザーを誰もフォローしていないとアクティビティがインスタンスに配達されないため、代わりにプロキシアカウントがフォローするようにします。"
|
||||
proxyAccountDescription: "プロキシアカウントは、特定の条件下でユーザーのリモートフォローを代行するアカウントです。例えば、ユーザーがリモートユーザーをリストに入れたとき、リストに入れられたユーザーを誰もフォローしていないとアクティビティがサーバーに配達されないため、代わりにプロキシアカウントがフォローするようにします。"
|
||||
host: "ホスト"
|
||||
selectUser: "ユーザーを選択"
|
||||
selectInstance: "インスタンスを選択"
|
||||
selectInstance: "サーバーを選択"
|
||||
recipient: "宛先"
|
||||
annotation: "注釈"
|
||||
federation: "連合"
|
||||
instances: "インスタンス"
|
||||
instances: "サーバー"
|
||||
registeredAt: "初観測"
|
||||
latestRequestSentAt: "直近のリクエスト送信"
|
||||
latestRequestReceivedAt: "直近のリクエスト受信"
|
||||
|
@ -182,8 +183,8 @@ charts: "チャート"
|
|||
perHour: "1時間ごと"
|
||||
perDay: "1日ごと"
|
||||
stopActivityDelivery: "アクティビティの配送を停止"
|
||||
blockThisInstance: "このインスタンスをブロック"
|
||||
silenceThisInstance: "このインスタンスをサイレンス"
|
||||
blockThisInstance: "このサーバーをブロック"
|
||||
silenceThisInstance: "このサーバーをサイレンス"
|
||||
operations: "操作"
|
||||
software: "ソフトウェア"
|
||||
version: "バージョン"
|
||||
|
@ -193,22 +194,22 @@ jobQueue: "ジョブキュー"
|
|||
cpuAndMemory: "CPUとメモリ"
|
||||
network: "ネットワーク"
|
||||
disk: "ディスク"
|
||||
instanceInfo: "インスタンス情報"
|
||||
instanceInfo: "サーバー情報"
|
||||
statistics: "統計"
|
||||
clearQueue: "キューをクリア"
|
||||
clearQueueConfirmTitle: "キューをクリアしますか?"
|
||||
clearQueueConfirmText: "未配達の投稿は配送されなくなります。通常この操作を行う必要はありません。"
|
||||
clearCachedFiles: "キャッシュをクリア"
|
||||
clearCachedFilesConfirm: "キャッシュされたリモートファイルをすべて削除しますか?"
|
||||
blockedInstances: "ブロックしたインスタンス"
|
||||
blockedInstancesDescription: "ブロックしたいインスタンスのホストを改行で区切って設定します。ブロックされたインスタンスは、このインスタンスとやり取りできなくなります。"
|
||||
silencedInstances: "サイレンスしたインスタンス"
|
||||
silencedInstancesDescription: "サイレンスしたいインスタンスのホストを改行で区切って設定します。サイレンスされたインスタンスに所属するアカウントはすべて「サイレンス」として扱われ、フォローがすべてリクエストになり、フォロワーでないローカルアカウントにはメンションできなくなります。ブロックしたインスタンスには影響しません。"
|
||||
blockedInstances: "ブロックしたサーバー"
|
||||
blockedInstancesDescription: "ブロックしたいサーバーのホストを改行で区切って設定します。ブロックされたサーバーは、このサーバーとやり取りできなくなります。"
|
||||
silencedInstances: "サイレンスしたサーバー"
|
||||
silencedInstancesDescription: "サイレンスしたいサーバーのホストを改行で区切って設定します。サイレンスされたサーバーに所属するアカウントはすべて「サイレンス」として扱われ、フォローがすべてリクエストになり、フォロワーでないローカルアカウントにはメンションできなくなります。ブロックしたサーバーには影響しません。"
|
||||
muteAndBlock: "ミュートとブロック"
|
||||
mutedUsers: "ミュートしたユーザー"
|
||||
blockedUsers: "ブロックしたユーザー"
|
||||
noUsers: "ユーザーはいません"
|
||||
noInstances: "インスタンスはありません"
|
||||
noInstances: "サーバーがありません"
|
||||
editProfile: "プロフィールを編集"
|
||||
noteDeleteConfirm: "この投稿を削除しますか?"
|
||||
pinLimitExceeded: "これ以上ピン留めできません"
|
||||
|
@ -228,9 +229,9 @@ all: "全て"
|
|||
subscribing: "購読中"
|
||||
publishing: "配信中"
|
||||
notResponding: "応答なし"
|
||||
instanceFollowing: "インスタンスのフォロー"
|
||||
instanceFollowers: "インスタンスのフォロワー"
|
||||
instanceUsers: "インスタンスのユーザー"
|
||||
instanceFollowing: "サーバーのフォロー"
|
||||
instanceFollowers: "サーバーのフォロワー"
|
||||
instanceUsers: "このサーバーの利用者"
|
||||
changePassword: "パスワードを変更"
|
||||
security: "セキュリティ"
|
||||
retypedNotMatch: "入力が一致しません。"
|
||||
|
@ -321,8 +322,8 @@ unwatch: "ウォッチ解除"
|
|||
accept: "許可"
|
||||
reject: "拒否"
|
||||
normal: "正常"
|
||||
instanceName: "インスタンス名"
|
||||
instanceDescription: "インスタンスの紹介"
|
||||
instanceName: "サーバー名"
|
||||
instanceDescription: "サーバーの紹介文"
|
||||
maintainerName: "管理者の名前"
|
||||
maintainerEmail: "管理者のメールアドレス"
|
||||
tosUrl: "利用規約URL"
|
||||
|
@ -353,7 +354,7 @@ basicInfo: "基本情報"
|
|||
pinnedUsers: "ピン留めユーザー"
|
||||
pinnedUsersDescription: "「みつける」ページなどにピン留めしたいユーザーを改行で区切って記述します。"
|
||||
pinnedPages: "ピン留めページ"
|
||||
pinnedPagesDescription: "インスタンスのトップページにピン留めしたいページのパスを改行で区切って記述します。"
|
||||
pinnedPagesDescription: "サーバーのトップページにピン留めしたいページのパスを改行で区切って記述します。"
|
||||
pinnedClipId: "ピン留めするクリップのID"
|
||||
pinnedNotes: "ピン留めされた投稿"
|
||||
hcaptcha: "hCaptcha"
|
||||
|
@ -376,7 +377,7 @@ notifyAntenna: "新しい投稿を通知する"
|
|||
withFileAntenna: "ファイルが添付された投稿のみ"
|
||||
enableServiceworker: "ブラウザへのプッシュ通知を有効にする"
|
||||
antennaUsersDescription: "ユーザー名を改行で区切って指定します"
|
||||
antennaInstancesDescription: "インスタンスを改行で区切って指定します"
|
||||
antennaInstancesDescription: "サーバーを改行で区切って指定します"
|
||||
caseSensitive: "大文字小文字を区別する"
|
||||
withReplies: "返信を含む"
|
||||
connectedTo: "次のアカウントに接続されています"
|
||||
|
@ -501,8 +502,8 @@ showFeaturedNotesInTimeline: "タイムラインにおすすめの投稿を表
|
|||
objectStorage: "オブジェクトストレージ"
|
||||
useObjectStorage: "オブジェクトストレージを使用"
|
||||
objectStorageBaseUrl: "Base URL"
|
||||
objectStorageBaseUrlDesc: "参照に使用するURL。CDNやProxyを使用している場合はそのURL、S3: 'https://<bucket>.s3.amazonaws.com'、GCS等:\
|
||||
\ 'https://storage.googleapis.com/<bucket>'。"
|
||||
objectStorageBaseUrlDesc: "参照に使用するURL。CDNやProxyを使用している場合はそのURL、S3: 'https://<bucket>.s3.amazonaws.com'、GCS等:
|
||||
'https://storage.googleapis.com/<bucket>'。"
|
||||
objectStorageBucket: "Bucket"
|
||||
objectStorageBucketDesc: "使用サービスのbucket名を指定してください。"
|
||||
objectStoragePrefix: "Prefix"
|
||||
|
@ -550,7 +551,7 @@ updateRemoteUser: "リモートユーザー情報の更新"
|
|||
deleteAllFiles: "すべてのファイルを削除"
|
||||
deleteAllFilesConfirm: "すべてのファイルを削除しますか?"
|
||||
removeAllFollowing: "フォローを全解除"
|
||||
removeAllFollowingDescription: "{host}からのフォローをすべて解除します。そのインスタンスがもう存在しなくなった場合などに実行してください。"
|
||||
removeAllFollowingDescription: "{host}からのフォローをすべて解除します。そのサーバーがもう存在しなくなった場合などに実行してください。"
|
||||
userSuspended: "このユーザーは凍結されています。"
|
||||
userSilenced: "このユーザーはサイレンスされています。"
|
||||
yourAccountSuspendedTitle: "アカウントが凍結されています"
|
||||
|
@ -615,7 +616,7 @@ testEmail: "配信テスト"
|
|||
wordMute: "ワードミュート"
|
||||
regexpError: "正規表現エラー"
|
||||
regexpErrorDescription: "{tab}ワードミュートの{line}行目の正規表現にエラーが発生しました:"
|
||||
instanceMute: "インスタンスミュート"
|
||||
instanceMute: "サーバーミュート"
|
||||
userSaysSomething: "{name}が何かを言いました"
|
||||
userSaysSomethingReason: "{name}が{reason}と言いました"
|
||||
userSaysSomethingReasonReply: "{name}が{reason}を含む投稿に返信しました"
|
||||
|
@ -650,15 +651,15 @@ abuseReported: "内容が送信されました。ご報告ありがとうござ
|
|||
reporter: "通報者"
|
||||
reporteeOrigin: "通報先"
|
||||
reporterOrigin: "通報元"
|
||||
forwardReport: "リモートインスタンスに通報を転送する"
|
||||
forwardReportIsAnonymous: "リモートインスタンスからはあなたの情報は見れず、匿名のシステムアカウントとして表示されます。"
|
||||
forwardReport: "リモートサーバーに通報を転送する"
|
||||
forwardReportIsAnonymous: "リモートサーバーからはあなたの情報は見られず、匿名のシステムアカウントとして表示されます。"
|
||||
send: "送信"
|
||||
abuseMarkAsResolved: "対応済みにする"
|
||||
openInNewTab: "新しいタブで開く"
|
||||
openInSideView: "サイドビューで開く"
|
||||
defaultNavigationBehaviour: "デフォルトのナビゲーション"
|
||||
editTheseSettingsMayBreakAccount: "これらの設定を編集するとアカウントが破損する可能性があります。"
|
||||
instanceTicker: "投稿のインスタンス情報"
|
||||
instanceTicker: "投稿のサーバー情報"
|
||||
waitingFor: "{x}を待っています"
|
||||
random: "ランダム"
|
||||
system: "システム"
|
||||
|
@ -722,7 +723,8 @@ onlineUsersCount: "{n}人がオンライン"
|
|||
nUsers: "{n}ユーザー"
|
||||
nNotes: "{n}投稿"
|
||||
sendErrorReports: "エラーリポートを送信"
|
||||
sendErrorReportsDescription: "オンにすると、問題が発生したときにエラーの詳細情報がCalckeyに共有され、ソフトウェアの品質向上に役立てられます。エラー情報には、OSのバージョン、ブラウザの種類、行動履歴などが含まれます。"
|
||||
sendErrorReportsDescription: "オンにすると、問題が発生したときにエラーの詳細情報がCalckeyに共有され、ソフトウェアの品質向上に役立てられます。\n\
|
||||
エラー情報には、OSのバージョン、ブラウザの種類、行動履歴などが含まれます。"
|
||||
myTheme: "マイテーマ"
|
||||
backgroundColor: "背景"
|
||||
accentColor: "アクセント"
|
||||
|
@ -746,7 +748,7 @@ capacity: "容量"
|
|||
inUse: "使用中"
|
||||
editCode: "コードを編集"
|
||||
apply: "適用"
|
||||
receiveAnnouncementFromInstance: "インスタンスからのお知らせを受け取る"
|
||||
receiveAnnouncementFromInstance: "サーバーからのお知らせを受け取る"
|
||||
emailNotification: "メール通知"
|
||||
publish: "公開"
|
||||
inChannelSearch: "チャンネル内検索"
|
||||
|
@ -774,7 +776,7 @@ active: "アクティブ"
|
|||
offline: "オフライン"
|
||||
notRecommended: "非推奨"
|
||||
botProtection: "Botプロテクション"
|
||||
instanceBlocking: "連合ブロック・サイレンス"
|
||||
instanceBlocking: "連合の管理"
|
||||
selectAccount: "アカウントを選択"
|
||||
switchAccount: "アカウントを切り替え"
|
||||
enabled: "有効"
|
||||
|
@ -802,12 +804,12 @@ low: "低"
|
|||
emailNotConfiguredWarning: "メールアドレスの設定がされていません。"
|
||||
ratio: "比率"
|
||||
secureMode: "セキュアモード (Authorized Fetch)"
|
||||
instanceSecurity: "インスタンスのセキュリティー"
|
||||
secureModeInfo: "他のインスタンスからリクエストするときに、証明を付けなければ返送しません。他のインスタンスの設定ファイルでsignToActivityPubGetはtrueにしてください。"
|
||||
instanceSecurity: "サーバーのセキュリティー"
|
||||
secureModeInfo: "認証情報の無いリモートサーバーからのリクエストに応えません。"
|
||||
privateMode: "非公開モード"
|
||||
privateModeInfo: "有効にすると、許可したインスタンスのみからリクエストを受け付けます。"
|
||||
allowedInstances: "許可されたインスタンス"
|
||||
allowedInstancesDescription: "許可したいインスタンスのホストを改行で区切って設定します。非公開モードだけで有効です。"
|
||||
privateModeInfo: "有効にすると、許可したサーバーのみからリクエストを受け付けます。"
|
||||
allowedInstances: "許可されたサーバー"
|
||||
allowedInstancesDescription: "許可したいサーバーのホストを改行で区切って設定します。非公開モードだけで有効です。"
|
||||
previewNoteText: "本文をプレビュー"
|
||||
customCss: "カスタムCSS"
|
||||
customCssWarn: "この設定は必ず知識のある方が行ってください。不適切な設定を行うとクライアントが正常に使用できなくなる恐れがあります。"
|
||||
|
@ -846,7 +848,7 @@ controlPanel: "コントロールパネル"
|
|||
manageAccounts: "アカウントを管理"
|
||||
makeReactionsPublic: "リアクション一覧を公開する"
|
||||
makeReactionsPublicDescription: "あなたがしたリアクション一覧を誰でも見れるようにします。"
|
||||
classic: "クラシック"
|
||||
classic: "中央寄せ"
|
||||
muteThread: "スレッドをミュート"
|
||||
unmuteThread: "スレッドのミュートを解除"
|
||||
ffVisibility: "つながりの公開範囲"
|
||||
|
@ -872,8 +874,8 @@ themeColor: "テーマカラー"
|
|||
size: "サイズ"
|
||||
numberOfColumn: "列の数"
|
||||
searchByGoogle: "検索"
|
||||
instanceDefaultLightTheme: "インスタンスデフォルトのライトテーマ"
|
||||
instanceDefaultDarkTheme: "インスタンスデフォルトのダークテーマ"
|
||||
instanceDefaultLightTheme: "サーバーの標準ライトテーマ"
|
||||
instanceDefaultDarkTheme: "サーバーの標準ダークテーマ"
|
||||
instanceDefaultThemeDescription: "オブジェクト形式のテーマコードを記入します。"
|
||||
mutePeriod: "ミュートする期限"
|
||||
indefinitely: "無期限"
|
||||
|
@ -895,7 +897,7 @@ check: "チェック"
|
|||
driveCapOverrideLabel: "このユーザーのドライブ容量上限を変更"
|
||||
driveCapOverrideCaption: "0以下を指定すると解除されます。"
|
||||
requireAdminForView: "閲覧するには管理者アカウントでログインしている必要があります。"
|
||||
isSystemAccount: "システムにより自動で作成・管理されているアカウントです。"
|
||||
isSystemAccount: "システムにより自動で作成・管理されているアカウントです。モデレーション・編集・削除を行うとサーバーの動作が不正になる可能性があるため、操作しないでください。"
|
||||
typeToConfirm: "この操作を行うには {x} と入力してください"
|
||||
deleteAccount: "アカウント削除"
|
||||
document: "ドキュメント"
|
||||
|
@ -922,7 +924,7 @@ cannotUploadBecauseNoFreeSpace: "ドライブの空き容量が無いためア
|
|||
cannotUploadBecauseExceedsFileSizeLimit: "ファイルサイズの制限を超えているためアップロードできません。"
|
||||
beta: "ベータ"
|
||||
enableAutoSensitive: "自動NSFW判定"
|
||||
enableAutoSensitiveDescription: "利用可能な場合は、機械学習を利用して自動でメディアにNSFWフラグを設定します。この機能をオフにしても、インスタンスによっては自動で設定されることがあります。"
|
||||
enableAutoSensitiveDescription: "利用可能な場合は、機械学習を利用して自動でメディアにNSFWフラグを設定します。この機能をオフにしても、サーバーによっては自動で設定されることがあります。"
|
||||
activeEmailValidationDescription: "ユーザーのメールアドレスのバリデーションを、捨てアドかどうかや実際に通信可能かどうかなどを判定しより積極的に行います。オフにすると単に文字列として正しいかどうかのみチェックされます。"
|
||||
showAds: "広告を表示する"
|
||||
navbar: "ナビゲーションバー"
|
||||
|
@ -933,18 +935,18 @@ pushNotification: "プッシュ通知"
|
|||
subscribePushNotification: "プッシュ通知を有効化"
|
||||
unsubscribePushNotification: "プッシュ通知を停止する"
|
||||
pushNotificationAlreadySubscribed: "プッシュ通知は有効です"
|
||||
pushNotificationNotSupported: "ブラウザかサーバーがプッシュ通知に非対応"
|
||||
pushNotificationNotSupported: "ブラウザまたはサーバーがプッシュ通知に非対応です"
|
||||
sendPushNotificationReadMessage: "通知やメッセージが既読になったらプッシュ通知を削除する"
|
||||
sendPushNotificationReadMessageCaption: "「{emptyPushNotificationMessage}」という通知が一瞬表示されるようになります。端末の電池消費量が増加する可能性があります。"
|
||||
adminCustomCssWarn: "この設定は、それが何をするものであるかを知っている場合のみ使用してください。不適切な値を入力すると、クライアントが正常に動作しなくなる可能性があります。ユーザー設定でCSSをテストし、正しく動作することを確認してください。"
|
||||
customMOTD: "カスタムMOTD(スプラッシュスクリーンメッセージ)"
|
||||
customMOTDDescription: "ユーザがページをロード/リロードするたびにランダムに表示される、改行で区切られたMOTD(スプラッシュスクリーン)用のカスタムメッセージ"
|
||||
customSplashIcons: "カスタムスプラッシュスクリーンアイコン"
|
||||
customSplashIconsDescription: "ユーザがページをロード/リロードするたびにランダムに表示される、改行で区切られたカスタムスプラッシュスクリーンアイコンの\
|
||||
\ URL。画像は静的なURLで、できればすべて192x192にリサイズしてください。"
|
||||
customSplashIconsDescription: "ユーザがページをロード/リロードするたびにランダムに表示される、改行で区切られたカスタムスプラッシュスクリーンアイコンの
|
||||
URL。画像は静的なURLで、できればすべて192x192にリサイズしてください。"
|
||||
showUpdates: "Calckeyの更新時にポップアップを表示する"
|
||||
recommendedInstances: "おすすめインスタンス"
|
||||
recommendedInstancesDescription: "おすすめタイムラインに表示するインスタンスを改行区切りで入力してください。`https://`は書かず、ドメインのみを入力してください。"
|
||||
recommendedInstances: "おすすめサーバー"
|
||||
recommendedInstancesDescription: "おすすめタイムラインに表示するサーバーを改行区切りで入力してください。`https://`は書かず、ドメインのみを入力してください。"
|
||||
caption: "自動キャプション"
|
||||
splash: "スプラッシュスクリーン"
|
||||
updateAvailable: "アップデートがありますよ!"
|
||||
|
@ -956,10 +958,10 @@ migration: "アカウントの引っ越し"
|
|||
moveTo: "このアカウントを新しいアカウントに引っ越す"
|
||||
moveToLabel: "引っ越し先のアカウント:"
|
||||
moveAccount: "引っ越し実行!"
|
||||
moveAccountDescription: "この操作は取り消せません。まずは引っ越し先のアカウントでこのアカウントに対しエイリアスを作成したことを確認してください。エイリアス作成後、引っ越し先のアカウントをこのように入力してください:@person@instance.com"
|
||||
moveAccountDescription: "この操作は取り消せません。まずは引っ越し先のアカウントでこのアカウントに対しエイリアスを作成したことを確認してください。エイリアス作成後、引っ越し先のアカウントをこのように入力してください:@person@server.com"
|
||||
moveFrom: "別のアカウントからこのアカウントに引っ越す"
|
||||
moveFromLabel: "引っ越し元のアカウント:"
|
||||
moveFromDescription: "別のアカウントからこのアカウントにフォロワーを引き継いで引っ越したい場合、ここでエイリアスを作成しておく必要があります。必ず引っ越しを実行する前に作成してください!引っ越し元のアカウントをこのように入力してください:@person@instance.com"
|
||||
moveFromDescription: "別のアカウントからこのアカウントにフォロワーを引き継いで引っ越したい場合、ここでエイリアスを作成しておく必要があります。必ず引っ越しを実行する前に作成してください!引っ越し元のアカウントをこのように入力してください:@person@server.com"
|
||||
migrationConfirm: "本当にこのアカウントを {account} に引っ越しますか?一度引っ越しを行うと取り消せず、二度とこのアカウントを元の状態で使用できなくなります。\n\
|
||||
この操作を行う前に引っ越し先のアカウントでエイリアスを作成する必要があります。エイリアスが作成されているか、必ず確認してください。"
|
||||
defaultReaction: "リモートとローカルの投稿に対するデフォルトの絵文字リアクション"
|
||||
|
@ -969,9 +971,9 @@ indexFrom: "この投稿ID以降をインデックスする"
|
|||
indexFromDescription: "空白で全ての投稿を指定します"
|
||||
indexNotice: "インデックスを開始しました。完了まで時間がかかる場合があるため、少なくとも1時間はサーバーを再起動しないでください。"
|
||||
customKaTeXMacro: "カスタムKaTeXマクロ"
|
||||
customKaTeXMacroDescription: "数式入力を楽にするためのマクロを設定しましょう!記法はLaTeXにおけるコマンドの定義と同様に \\newcommand{\\\
|
||||
name}{content} または \\newcommand{\\add}[2]{#1 + #2} のように記述します。後者の例では \\add{3}{foo}\
|
||||
\ が 3 + foo に展開されます。また、マクロの名前を囲む波括弧を丸括弧 () および角括弧 [] に変更した場合、マクロの引数に使用する括弧が変更されます。マクロの定義は一行に一つのみで、途中で改行はできません。マクロの定義が無効な行は無視されます。文字列を単純に置換する機能のみに対応していて、条件分岐などの高度な構文は使用できません。"
|
||||
customKaTeXMacroDescription: "数式入力を楽にするためのマクロを設定しましょう!記法はLaTeXにおけるコマンドの定義と同様に \\newcommand{\\
|
||||
name}{content} または \\newcommand{\\add}[2]{#1 + #2} のように記述します。後者の例では \\add{3}{foo}
|
||||
が 3 + foo に展開されます。また、マクロの名前を囲む波括弧を丸括弧 () および角括弧 [] に変更した場合、マクロの引数に使用する括弧が変更されます。マクロの定義は一行に一つのみで、途中で改行はできません。マクロの定義が無効な行は無視されます。文字列を単純に置換する機能のみに対応していて、条件分岐などの高度な構文は使用できません。"
|
||||
enableCustomKaTeXMacro: "カスタムKaTeXマクロを有効にする"
|
||||
preventAiLearning: "AIによる学習を防止"
|
||||
preventAiLearningDescription: "投稿したノート、添付した画像などのコンテンツを学習の対象にしないようAIに要求します。これはnoaiフラグをHTMLレスポンスに含めることによって実現されます。"
|
||||
|
@ -1012,7 +1014,7 @@ _ad:
|
|||
_forgotPassword:
|
||||
enterEmail: "アカウントに登録したメールアドレスを入力してください。そのアドレス宛てに、パスワードリセット用のリンクが送信されます。"
|
||||
ifNoEmail: "メールアドレスを登録していない場合は、管理者までお問い合わせください。"
|
||||
contactAdmin: "このインスタンスではメールがサポートされていないため、パスワードリセットを行う場合は管理者までお問い合わせください。"
|
||||
contactAdmin: "このインスタンスではメールアドレスの登録がサポートされていないため、パスワードリセットを行う場合は管理者までお問い合わせください。"
|
||||
_gallery:
|
||||
my: "自分の投稿"
|
||||
liked: "いいねした投稿"
|
||||
|
@ -1058,7 +1060,7 @@ _aboutMisskey:
|
|||
source: "ソースコード"
|
||||
translation: "Calckeyを翻訳"
|
||||
donate: "Calckeyに寄付"
|
||||
morePatrons: "他にも多くの方が支援してくれています。ありがとうございます! \U0001F970"
|
||||
morePatrons: "他にも多くの方が支援してくれています。ありがとうございます! 🥰"
|
||||
patrons: "支援者"
|
||||
_nsfw:
|
||||
respect: "閲覧注意のメディアは隠す"
|
||||
|
@ -1073,7 +1075,7 @@ _mfm:
|
|||
hashtag: "ハッシュタグ"
|
||||
hashtagDescription: "ナンバーサイン + タグで、ハッシュタグを示せます。"
|
||||
url: "URL"
|
||||
urlDescription: "URLを示せます。"
|
||||
urlDescription: "URLを表示できます。"
|
||||
link: "リンク"
|
||||
linkDescription: "文章の特定の範囲を、URLに紐づけられます。"
|
||||
bold: "太字"
|
||||
|
@ -1131,9 +1133,9 @@ _mfm:
|
|||
plain: "プレーン"
|
||||
plainDescription: "内側の構文を全て無効にします。"
|
||||
position: 位置
|
||||
stop: MFMアニメーションを停止
|
||||
stop: MFMを停止
|
||||
alwaysPlay: MFMアニメーションを自動再生する
|
||||
play: MFMアニメーションを再生
|
||||
play: MFMを再生
|
||||
warn: MFMアニメーションは激しい動きを含む可能性があります。
|
||||
positionDescription: 位置を指定した値だけずらします。
|
||||
foreground: 文字色
|
||||
|
@ -1142,6 +1144,12 @@ _mfm:
|
|||
scale: 拡大・縮小
|
||||
scaleDescription: 大きさを指定した値に拡大・縮小します。
|
||||
foregroundDescription: 文字の色を変更します。
|
||||
fade: フェード
|
||||
fadeDescription: フェードインとフェードアウトする。
|
||||
crop: 切り抜き
|
||||
cropDescription: 内容を切り抜く。
|
||||
advancedDescription: オフにすると、アニメーション再生中を除いて基本的なMFMだけ表示します。
|
||||
advanced: 高度なMFM
|
||||
_instanceTicker:
|
||||
none: "表示しない"
|
||||
remote: "リモートユーザーに表示"
|
||||
|
@ -1181,10 +1189,10 @@ _wordMute:
|
|||
hard: "ハード"
|
||||
mutedNotes: "ミュートされた投稿"
|
||||
_instanceMute:
|
||||
instanceMuteDescription: "ミュートしたインスタンスのユーザーへの返信を含めて、設定したインスタンスの全ての投稿とブーストをミュートします。"
|
||||
instanceMuteDescription: "ミュートしたサーバーのユーザーへの返信を含めて、設定したサーバーの全ての投稿とブーストをミュートします。"
|
||||
instanceMuteDescription2: "改行で区切って設定します"
|
||||
title: "設定したインスタンスの投稿を隠します。"
|
||||
heading: "ミュートするインスタンス"
|
||||
title: "設定したサーバーの投稿を隠します。"
|
||||
heading: "ミュートするサーバー"
|
||||
_theme:
|
||||
explore: "テーマを探す"
|
||||
install: "テーマのインストール"
|
||||
|
@ -1294,14 +1302,14 @@ _tutorial:
|
|||
step4_1: "投稿してみましょう!"
|
||||
step4_2: "最初は{introduction}に投稿したり、シンプルに「こんにちは、アカウント作ってみました!」などの投稿をする人もいます。"
|
||||
step5_1: "タイムライン、タイムラインだらけ!"
|
||||
step5_2: "あなたのインスタンスでは{timelines}種類のタイムラインが有効になっています。"
|
||||
step5_3: "ホーム{icon}タイムラインでは、あなたがフォローしているアカウントとこのインスタンスのみんなの投稿を見られます。もしフォローしているアカウントの投稿だけ見たい場合は、設定から変更できます。"
|
||||
step5_4: "ローカル{icon}タイムラインでは、このインスタンスにいるみんなの投稿を見られます。"
|
||||
step5_5: "ソーシャル{icon}タイムラインでは、あなたがフォローしているアカウントの投稿を見られます。"
|
||||
step5_6: "おすすめ{icon}タイムラインでは、管理人がおすすめするインスタンスの投稿を見られます。"
|
||||
step5_7: "グローバル{icon}タイムラインでは、接続している他のすべてのインスタンスからの投稿を見られます。"
|
||||
step5_2: "あなたのサーバーでは{timelines}種類のタイムラインが有効になっています。"
|
||||
step5_3: "ホーム{icon}タイムラインでは、あなたがフォローしているアカウントの投稿を見られます。"
|
||||
step5_4: "ローカル{icon}タイムラインでは、このサーバーにいるみんなの投稿を見られます。"
|
||||
step5_5: "ソーシャル{icon}タイムラインでは、ホームタイムラインとローカルタイムラインの投稿が両方表示されます。"
|
||||
step5_6: "おすすめ{icon}タイムラインでは、管理人がおすすめするサーバーの投稿を見られます。"
|
||||
step5_7: "グローバル{icon}タイムラインでは、接続している他のすべてのサーバーからの投稿を見られます。"
|
||||
step6_1: "じゃあ、ここはどんな場所なの?"
|
||||
step6_2: "実は、あなたはただCalckeyに参加しただけではありません。ここは、何千もの相互接続されたサーバーが構成する Fediverse への入口です。各サーバーは「インスタンス」と呼ばれます。"
|
||||
step6_2: "実は、あなたはただCalckeyに参加しただけではありません。ここは、何千もの相互接続されたサーバーが構成する Fediverse への入口です。"
|
||||
step6_3: "それぞれのサーバーでは必ずしもCalckeyが使われているわけではなく、異なる動作をするサーバーもあります。しかし、あなたは他のサーバーのアカウントもフォローしたり、返信・ブーストができます。一見難しそうですが大丈夫!すぐ慣れます。"
|
||||
step6_4: "これで完了です。お楽しみください!"
|
||||
_2fa:
|
||||
|
@ -1361,7 +1369,7 @@ _antennaSources:
|
|||
users: "指定した一人または複数のユーザーの投稿"
|
||||
userList: "指定したリストのユーザーの投稿"
|
||||
userGroup: "指定したグループのユーザーの投稿"
|
||||
instances: "指定したインスタンスの全ユーザーの投稿"
|
||||
instances: "指定したサーバーの全ユーザーの投稿"
|
||||
_weekday:
|
||||
sunday: "日曜日"
|
||||
monday: "月曜日"
|
||||
|
@ -1384,7 +1392,7 @@ _widgets:
|
|||
digitalClock: "デジタル時計"
|
||||
unixClock: "UNIX時計"
|
||||
federation: "連合"
|
||||
instanceCloud: "インスタンスクラウド"
|
||||
instanceCloud: "サーバークラウド"
|
||||
postForm: "投稿フォーム"
|
||||
slideshow: "スライドショー"
|
||||
button: "ボタン"
|
||||
|
@ -1395,6 +1403,10 @@ _widgets:
|
|||
userList: "ユーザーリスト"
|
||||
_userList:
|
||||
chooseList: "リストを選択"
|
||||
meiliStatus: サーバーステータス
|
||||
serverInfo: サーバー情報
|
||||
meiliSize: インデックスサイズ
|
||||
meiliIndexCount: インデックス済みの投稿
|
||||
_cw:
|
||||
hide: "隠す"
|
||||
show: "もっと見る"
|
||||
|
@ -1823,6 +1835,9 @@ _notification:
|
|||
followBack: "フォローバック"
|
||||
reply: "返信"
|
||||
renote: "ブースト"
|
||||
reacted: がリアクションしました
|
||||
renoted: がブーストしました
|
||||
voted: が投票しました
|
||||
_deck:
|
||||
alwaysShowMainColumn: "常にメインカラムを表示"
|
||||
columnAlign: "カラムの寄せ"
|
||||
|
@ -1849,6 +1864,7 @@ _deck:
|
|||
tl: "タイムライン"
|
||||
antenna: "アンテナ"
|
||||
list: "リスト"
|
||||
channel: "チャンネル"
|
||||
mentions: "あなた宛て"
|
||||
direct: "ダイレクト"
|
||||
noteId: 投稿のID
|
||||
|
@ -1858,7 +1874,10 @@ apps: "アプリ"
|
|||
_experiments:
|
||||
enablePostEditing: 投稿の編集機能を有効にする
|
||||
title: 試験的な機能
|
||||
postEditingCaption: 投稿のメニューに既存の投稿を編集するボタンを表示します。
|
||||
postEditingCaption: 投稿のメニューに既存の投稿を編集するボタンを表示し、他サーバーの編集も受信できるようにします。
|
||||
postImportsCaption:
|
||||
ユーザーが過去の投稿をCalckey・Misskey・Mastodon・Akkoma・Pleromaからインポートすることを許可します。キューが溜まっているときにインポートするとサーバーに負荷がかかる可能性があります。
|
||||
enablePostImports: 投稿のインポートを有効にする
|
||||
sendModMail: モデレーションノートを送る
|
||||
deleted: 削除済み
|
||||
editNote: 投稿を編集
|
||||
|
@ -1866,3 +1885,16 @@ edited: 編集済み
|
|||
signupsDisabled:
|
||||
現在、このサーバーでは新規登録が一般開放されていません。招待コードをお持ちの場合には、以下の欄に入力してください。招待コードをお持ちでない場合にも、新規登録を開放している他のサーバーには入れますよ!
|
||||
findOtherInstance: 他のサーバーを探す
|
||||
newer: 新しい投稿
|
||||
older: 古い投稿
|
||||
accessibility: アクセシビリティ
|
||||
jumpToPrevious: 前に戻る
|
||||
cw: 閲覧注意
|
||||
silencedWarning: スパムの可能性があるため、これらのユーザーが所属するサーバーは管理者によりサイレンスされています。
|
||||
searchPlaceholder: Calckeyを検索
|
||||
channelFederationWarn: 現時点では、チャンネルは他のサーバーへ連合しません
|
||||
listsDesc: リストでは指定したユーザーだけのタイムラインを作れます。リストには「タイムライン」のページからアクセスできます。
|
||||
antennasDesc: "アンテナでは指定した条件に合致する投稿が表示されます。\nアンテナには「タイムライン」のページからアクセスできます。"
|
||||
expandOnNoteClickDesc: オフの場合、右クリックメニューか日付をクリックすることで開けます。
|
||||
expandOnNoteClick: クリックで投稿の詳細を開く
|
||||
clipsDesc: クリップは分類と共有ができるブックマークです。各投稿のメニューからクリップを作成できます。
|
||||
|
|
|
@ -642,3 +642,43 @@ promote: Promoten
|
|||
objectStorage: Objectopslag
|
||||
useObjectStorage: Gebruik objectopslag
|
||||
objectStorageBaseUrl: Basis -URL
|
||||
objectStorageUseSSLDesc: Schakel dit uit als je geen HTTPS voor je API connecties
|
||||
gebruikt
|
||||
objectStorageUseProxy: Verbind over Proxy
|
||||
objectStorageUseProxyDesc: Schakel dit uit als je geen Proxy voor je API connecties
|
||||
gebruikt
|
||||
sounds: Geluiden
|
||||
lastUsedDate: Laatst gebruikt op
|
||||
installedDate: Geautoriseerd op
|
||||
sort: Sorteren
|
||||
output: Uitvoer
|
||||
script: Script
|
||||
popout: Pop-out
|
||||
descendingOrder: Aflopend
|
||||
showInPage: Toon in de pagina
|
||||
chooseEmoji: Kies een emoji
|
||||
ascendingOrder: Oplopend
|
||||
volume: Volume
|
||||
masterVolume: Master volume
|
||||
details: Details
|
||||
unableToProcess: Deze operatie kon niet worden voltooid
|
||||
nothing: Niks te zien hier
|
||||
scratchpad: Kladblok
|
||||
recentUsed: Recentelijk gebruikt
|
||||
install: Installeer
|
||||
uninstall: Verwijderen
|
||||
installedApps: Geautoriseerde Applicaties
|
||||
state: Status
|
||||
updateRemoteUser: Update externe gebruikersinformatie
|
||||
listen: Luister
|
||||
none: Geen
|
||||
scratchpadDescription: Het kladblok is een omgeving voor AiScript experimenten. Je
|
||||
kan hier schrijven, uitvoeren, en de resultaten bekijken van de interactie met Calckey.
|
||||
disablePagesScript: Zet AiScript op Pages uit
|
||||
deleteAllFiles: Verwijder alle bestanden
|
||||
deleteAllFilesConfirm: Weet je zeker dat je alle bestanden wil verwijderen?
|
||||
removeAllFollowing: Ontvolg alle gevolgde gebruikers
|
||||
serverLogs: Server logboek
|
||||
deleteAll: Verwijder alles
|
||||
showFixedPostForm: Toon het post formulier bovenaan de tijdlijn
|
||||
newNoteRecived: Er zijn nieuwe posts
|
||||
|
|
10
package.json
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "calckey",
|
||||
"version": "14.0.0-dev40",
|
||||
"version": "14.0.0-dev46",
|
||||
"codename": "aqua",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://codeberg.org/calckey/calckey.git"
|
||||
},
|
||||
"packageManager": "pnpm@8.6.0",
|
||||
"packageManager": "pnpm@8.6.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"rebuild": "pnpm run clean && pnpm -r run build && pnpm run gulp",
|
||||
|
@ -27,7 +27,7 @@
|
|||
"e2e": "start-server-and-test start:test http://localhost:61812 cy:run",
|
||||
"mocha": "pnpm --filter backend run mocha",
|
||||
"test": "pnpm run mocha",
|
||||
"format": "pnpm rome format packages/**/* --write && pnpm -r run format",
|
||||
"format": "pnpm -r run format",
|
||||
"clean": "pnpm node ./scripts/clean.js",
|
||||
"clean-all": "pnpm node ./scripts/clean-all.js",
|
||||
"cleanall": "pnpm run clean-all"
|
||||
|
@ -40,8 +40,6 @@
|
|||
"@bull-board/ui": "5.2.0",
|
||||
"@napi-rs/cli": "^2.16.1",
|
||||
"@tensorflow/tfjs": "^3.21.0",
|
||||
"focus-trap": "^7.2.0",
|
||||
"focus-trap-vue": "^4.0.1",
|
||||
"js-yaml": "4.1.0",
|
||||
"seedrandom": "^3.0.5"
|
||||
},
|
||||
|
@ -57,7 +55,7 @@
|
|||
"gulp-replace": "1.1.4",
|
||||
"gulp-terser": "2.1.0",
|
||||
"install-peers": "^1.0.4",
|
||||
"rome": "^11.0.0",
|
||||
"rome": "^12.1.3",
|
||||
"start-server-and-test": "1.15.2",
|
||||
"typescript": "4.9.4"
|
||||
}
|
||||
|
|
1
packages/backend/native-utils/.gitignore
vendored
|
@ -187,7 +187,6 @@ built/
|
|||
#Added by cargo
|
||||
|
||||
/target
|
||||
Cargo.lock
|
||||
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
|
|
3332
packages/backend/native-utils/Cargo.lock
generated
Normal file
|
@ -13,7 +13,6 @@ default = []
|
|||
convert = ["dep:native-utils"]
|
||||
|
||||
[dependencies]
|
||||
async-std = { version = "1", features = ["attributes", "tokio1"] }
|
||||
serde_json = "1.0.96"
|
||||
native-utils = { path = "../", optional = true }
|
||||
indicatif = { version = "0.17.4", features = ["tokio"] }
|
||||
|
@ -21,6 +20,7 @@ tokio = { version = "1.28.2", features = ["full"] }
|
|||
futures = "0.3.28"
|
||||
serde_yaml = "0.9.21"
|
||||
serde = { version = "1.0.163", features = ["derive"] }
|
||||
urlencoding = "2.1.2"
|
||||
|
||||
[dependencies.sea-orm-migration]
|
||||
version = "0.11.0"
|
||||
|
|
|
@ -1,24 +1,29 @@
|
|||
use serde::Deserialize;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use urlencoding::encode;
|
||||
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
#[cfg(feature = "convert")]
|
||||
mod vec_to_json;
|
||||
|
||||
#[async_std::main]
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let cwd = env::current_dir().unwrap();
|
||||
let yml = fs::File::open(cwd.join("../../.config/default.yml"))
|
||||
.expect("Unable to read '.config/default.yml'");
|
||||
let config: Config = serde_yaml::from_reader(yml).expect("Unable to parse");
|
||||
.expect("Failed to open '.config/default.yml'");
|
||||
let config: Config = serde_yaml::from_reader(yml).expect("Failed to parse yaml");
|
||||
|
||||
env::set_var(
|
||||
"DATABASE_URL",
|
||||
format!(
|
||||
"postgres://{}:{}@{}:{}/{}",
|
||||
config.db.user, config.db.pass, config.db.host, config.db.port, config.db.db
|
||||
config.db.user,
|
||||
encode(&config.db.pass),
|
||||
config.db.host,
|
||||
config.db.port,
|
||||
config.db.db,
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
@ -8,16 +8,17 @@
|
|||
"start:test": "NODE_ENV=test pnpm node ./built/index.js",
|
||||
"migrate": "pnpm run migrate:typeorm && pnpm run migrate:cargo",
|
||||
"migrate:typeorm": "typeorm migration:run -d ormconfig.js",
|
||||
"migrate:cargo": "cargo run --manifest-path native-utils/migration/Cargo.toml -- up",
|
||||
"migrate:cargo": "cargo run --manifest-path ./native-utils/migration/Cargo.toml -- up",
|
||||
"revertmigration": "pnpm run revertmigration:cargo && pnpm run revertmigration:typeorm",
|
||||
"revertmigration:typeorm": "typeorm migration:revert -d ormconfig.js",
|
||||
"revertmigration:cargo": "cargo run --manifest-path native-utils/migration/Cargo.toml -- down",
|
||||
"revertmigration:cargo": "cargo run --manifest-path ./native-utils/migration/Cargo.toml -- down",
|
||||
"check:connect": "node ./check_connect.js",
|
||||
"build": "pnpm swc src -d built -D",
|
||||
"watch": "pnpm swc src -d built -D -w",
|
||||
"lint": "pnpm rome check \"src/**/*.ts\"",
|
||||
"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",
|
||||
"test": "pnpm run mocha"
|
||||
"test": "pnpm run mocha",
|
||||
"format": "pnpm rome format * --write"
|
||||
},
|
||||
"resolutions": {
|
||||
"chokidar": "^3.3.1"
|
||||
|
@ -31,10 +32,10 @@
|
|||
"@bull-board/koa": "5.2.0",
|
||||
"@bull-board/ui": "5.2.0",
|
||||
"@calckey/megalodon": "5.2.0",
|
||||
"@discordapp/twemoji": "14.0.2",
|
||||
"@discordapp/twemoji": "14.1.2",
|
||||
"@elastic/elasticsearch": "7.17.0",
|
||||
"@koa/cors": "3.4.3",
|
||||
"@koa/multer": "3.0.0",
|
||||
"@koa/multer": "3.0.2",
|
||||
"@koa/router": "9.0.1",
|
||||
"@peertube/http-signature": "1.7.0",
|
||||
"@redocly/openapi-core": "1.0.0-beta.120",
|
||||
|
@ -42,7 +43,7 @@
|
|||
"@syuilo/aiscript": "0.11.1",
|
||||
"@tensorflow/tfjs": "^4.2.0",
|
||||
"adm-zip": "^0.5.10",
|
||||
"ajv": "8.11.2",
|
||||
"ajv": "8.12.0",
|
||||
"archiver": "5.3.1",
|
||||
"argon2": "^0.30.3",
|
||||
"async-mutex": "^0.4.0",
|
||||
|
@ -50,7 +51,7 @@
|
|||
"autolinker": "4.0.0",
|
||||
"autwh": "0.1.0",
|
||||
"aws-sdk": "2.1277.0",
|
||||
"axios": "^1.3.2",
|
||||
"axios": "^1.4.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"blurhash": "1.1.5",
|
||||
"bullmq": "^3.15.0",
|
||||
|
@ -76,7 +77,7 @@
|
|||
"is-svg": "4.3.2",
|
||||
"js-yaml": "4.1.0",
|
||||
"jsdom": "20.0.3",
|
||||
"jsonld": "6.0.0",
|
||||
"jsonld": "8.2.0",
|
||||
"jsrsasign": "10.6.1",
|
||||
"koa": "2.13.4",
|
||||
"koa-body": "^6.0.1",
|
||||
|
@ -89,44 +90,44 @@
|
|||
"koa-send": "5.0.1",
|
||||
"koa-slow": "2.1.0",
|
||||
"koa-views": "7.0.2",
|
||||
"meilisearch": "0.32.4",
|
||||
"meilisearch": "0.33.0",
|
||||
"mfm-js": "0.23.3",
|
||||
"mime-types": "2.1.35",
|
||||
"multer": "1.4.4-lts.1",
|
||||
"native-utils": "link:native-utils",
|
||||
"nested-property": "4.0.0",
|
||||
"node-fetch": "3.3.0",
|
||||
"nodemailer": "6.8.0",
|
||||
"node-fetch": "3.3.1",
|
||||
"nodemailer": "6.9.3",
|
||||
"nsfwjs": "2.4.2",
|
||||
"oauth": "^0.10.0",
|
||||
"os-utils": "0.0.14",
|
||||
"parse5": "7.1.2",
|
||||
"pg": "8.8.0",
|
||||
"pg": "8.11.0",
|
||||
"private-ip": "2.3.4",
|
||||
"probe-image-size": "7.2.3",
|
||||
"promise-limit": "2.7.0",
|
||||
"punycode": "2.1.1",
|
||||
"punycode": "2.3.0",
|
||||
"pureimage": "0.3.15",
|
||||
"qrcode": "1.5.1",
|
||||
"qs": "6.9.7",
|
||||
"qrcode": "1.5.3",
|
||||
"qs": "6.11.2",
|
||||
"random-seed": "0.3.0",
|
||||
"ratelimiter": "3.4.1",
|
||||
"re2": "1.18.0",
|
||||
"re2": "1.19.0",
|
||||
"redis-lock": "0.1.4",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"rename": "1.0.4",
|
||||
"rndstr": "1.0.0",
|
||||
"rss-parser": "3.12.0",
|
||||
"sanitize-html": "2.8.1",
|
||||
"rss-parser": "3.13.0",
|
||||
"sanitize-html": "2.10.0",
|
||||
"seedrandom": "^3.0.5",
|
||||
"semver": "7.3.8",
|
||||
"sharp": "0.31.3",
|
||||
"semver": "7.5.1",
|
||||
"sharp": "0.32.1",
|
||||
"sonic-channel": "^1.3.1",
|
||||
"speakeasy": "2.0.0",
|
||||
"stringz": "2.1.0",
|
||||
"summaly": "2.7.0",
|
||||
"syslog-pro": "1.0.0",
|
||||
"systeminformation": "5.16.9",
|
||||
"systeminformation": "5.17.17",
|
||||
"tesseract.js": "^3.0.3",
|
||||
"tinycolor2": "1.5.2",
|
||||
"tmp": "0.2.1",
|
||||
|
@ -134,13 +135,13 @@
|
|||
"typeorm": "0.3.11",
|
||||
"ulid": "2.3.0",
|
||||
"uuid": "9.0.0",
|
||||
"web-push": "3.5.0",
|
||||
"web-push": "3.6.1",
|
||||
"websocket": "1.0.34",
|
||||
"xev": "3.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@swc/cli": "^0.1.62",
|
||||
"@swc/core": "^1.3.50",
|
||||
"@swc/core": "^1.3.62",
|
||||
"@types/adm-zip": "^0.5.0",
|
||||
"@types/bcryptjs": "2.4.2",
|
||||
"@types/cbor": "6.0.0",
|
||||
|
@ -164,7 +165,7 @@
|
|||
"@types/mocha": "9.1.1",
|
||||
"@types/node": "18.11.18",
|
||||
"@types/node-fetch": "3.0.3",
|
||||
"@types/nodemailer": "6.4.7",
|
||||
"@types/nodemailer": "6.4.8",
|
||||
"@types/oauth": "0.9.1",
|
||||
"@types/probe-image-size": "^7.2.0",
|
||||
"@types/pug": "2.0.6",
|
||||
|
@ -175,8 +176,8 @@
|
|||
"@types/ratelimiter": "3.4.4",
|
||||
"@types/redis": "4.0.11",
|
||||
"@types/rename": "1.0.4",
|
||||
"@types/sanitize-html": "2.8.0",
|
||||
"@types/semver": "7.3.13",
|
||||
"@types/sanitize-html": "2.9.0",
|
||||
"@types/semver": "7.5.0",
|
||||
"@types/sharp": "0.31.1",
|
||||
"@types/sinonjs__fake-timers": "8.1.2",
|
||||
"@types/speakeasy": "2.0.7",
|
||||
|
@ -185,10 +186,10 @@
|
|||
"@types/uuid": "8.3.4",
|
||||
"@types/web-push": "3.3.2",
|
||||
"@types/websocket": "1.0.5",
|
||||
"@types/ws": "8.5.3",
|
||||
"@types/ws": "8.5.4",
|
||||
"autobind-decorator": "2.4.0",
|
||||
"cross-env": "7.0.3",
|
||||
"eslint": "^8.31.0",
|
||||
"eslint": "^8.42.0",
|
||||
"execa": "6.1.0",
|
||||
"json5": "2.2.3",
|
||||
"json5-loader": "4.0.1",
|
||||
|
@ -196,11 +197,11 @@
|
|||
"pug": "3.0.2",
|
||||
"strict-event-emitter-types": "2.0.0",
|
||||
"swc-loader": "^0.2.3",
|
||||
"ts-loader": "9.4.2",
|
||||
"ts-loader": "9.4.3",
|
||||
"ts-node": "10.9.1",
|
||||
"tsconfig-paths": "4.1.2",
|
||||
"typescript": "4.9.4",
|
||||
"webpack": "^5.75.0",
|
||||
"ws": "8.11.0"
|
||||
"tsconfig-paths": "4.2.0",
|
||||
"typescript": "5.1.3",
|
||||
"webpack": "^5.85.1",
|
||||
"ws": "8.13.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ async function connectDb(): Promise<void> {
|
|||
}
|
||||
}
|
||||
|
||||
async function spawnWorkers(limit: number = 1) {
|
||||
async function spawnWorkers(limit = 1) {
|
||||
const workers = Math.min(limit, os.cpus().length);
|
||||
bootLogger.info(`Starting ${workers} worker${workers === 1 ? "" : "s"}...`);
|
||||
await Promise.all([...Array(workers)].map(spawnWorker));
|
||||
|
|
|
@ -61,6 +61,66 @@ if (hasConfig) {
|
|||
),
|
||||
);
|
||||
|
||||
posts
|
||||
.updateStopWords([
|
||||
"the",
|
||||
"a",
|
||||
"as",
|
||||
"be",
|
||||
"of",
|
||||
"they",
|
||||
"these",
|
||||
"これ",
|
||||
"それ",
|
||||
"あれ",
|
||||
"この",
|
||||
"その",
|
||||
"あの",
|
||||
"ここ",
|
||||
"そこ",
|
||||
"あそこ",
|
||||
"こちら",
|
||||
"どこ",
|
||||
"だれ",
|
||||
"なに",
|
||||
"なん",
|
||||
"何",
|
||||
"私",
|
||||
"貴方",
|
||||
"貴方方",
|
||||
"我々",
|
||||
"私達",
|
||||
"あの人",
|
||||
"あのか",
|
||||
"彼女",
|
||||
"彼",
|
||||
"です",
|
||||
"ありま",
|
||||
"おりま",
|
||||
"います",
|
||||
"は",
|
||||
"が",
|
||||
"の",
|
||||
"に",
|
||||
"を",
|
||||
"で",
|
||||
"え",
|
||||
"から",
|
||||
"まで",
|
||||
"より",
|
||||
"も",
|
||||
"どの",
|
||||
"と",
|
||||
"し",
|
||||
"それで",
|
||||
"しかし",
|
||||
])
|
||||
.catch((e) =>
|
||||
logger.error(
|
||||
`Failed to set Meilisearch stop words, database size will be larger: ${e}`,
|
||||
),
|
||||
);
|
||||
|
||||
logger.info("Connected to MeiliSearch");
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,9 @@ export const db = new DataSource({
|
|||
|
||||
export async function initDb(force = false) {
|
||||
await nativeInitDatabase(
|
||||
`postgres://${config.db.user}:${config.db.pass}@${config.db.host}:${config.db.port}/${config.db.db}`,
|
||||
`postgres://${config.db.user}:${encodeURIComponent(config.db.pass)}@${
|
||||
config.db.host
|
||||
}:${config.db.port}/${config.db.db}`,
|
||||
);
|
||||
if (force) {
|
||||
if (db.isInitialized) {
|
||||
|
|
|
@ -26,6 +26,7 @@ export async function checkHitAntenna(
|
|||
antennaUserFollowing?: User["id"][],
|
||||
): Promise<boolean> {
|
||||
if (note.visibility === "specified") return false;
|
||||
if (note.visibility === "home") return false;
|
||||
|
||||
// アンテナ作成者がノート作成者にブロックされていたらスキップ
|
||||
const blockings = await blockingCache.fetch(noteUser.id, () =>
|
||||
|
|
|
@ -3,6 +3,32 @@ import { Meta } from "@/models/entities/meta.js";
|
|||
|
||||
let cache: Meta;
|
||||
|
||||
export function metaToPugArgs(meta: Meta): object {
|
||||
let motd = ["Loading..."];
|
||||
if (meta.customMOTD.length > 0) {
|
||||
motd = meta.customMOTD;
|
||||
}
|
||||
let splashIconUrl = meta.iconUrl;
|
||||
if (meta.customSplashIcons.length > 0) {
|
||||
splashIconUrl =
|
||||
meta.customSplashIcons[
|
||||
Math.floor(Math.random() * meta.customSplashIcons.length)
|
||||
];
|
||||
}
|
||||
|
||||
return {
|
||||
img: meta.bannerUrl,
|
||||
title: meta.name || "Calckey",
|
||||
instanceName: meta.name || "Calckey",
|
||||
desc: meta.description,
|
||||
icon: meta.iconUrl,
|
||||
splashIcon: splashIconUrl,
|
||||
themeColor: meta.themeColor,
|
||||
randomMOTD: motd[Math.floor(Math.random() * motd.length)],
|
||||
privateMode: meta.privateMode,
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchMeta(noCache = false): Promise<Meta> {
|
||||
if (!noCache && cache) return cache;
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@ export default async (job: Bull.Job<InboxJobData>): Promise<string> => {
|
|||
const info = Object.assign({}, activity) as any;
|
||||
info["@context"] = undefined;
|
||||
logger.debug(JSON.stringify(info, null, 2));
|
||||
|
||||
if (!signature?.keyId) return `Invalid signature: ${signature}`;
|
||||
|
||||
//#endregion
|
||||
const host = toPuny(new URL(signature.keyId).hostname);
|
||||
|
||||
|
|
|
@ -67,8 +67,6 @@ export function parseUri(value: string | IObject): UriParseResult {
|
|||
}
|
||||
|
||||
export default class DbResolver {
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
* AP Note => Misskey Note in DB
|
||||
*/
|
||||
|
|
|
@ -11,8 +11,6 @@ export class LdSignature {
|
|||
public preLoad = true;
|
||||
public loderTimeout = 10 * 1000;
|
||||
|
||||
constructor() {}
|
||||
|
||||
public async signRsaSignature2017(
|
||||
data: any,
|
||||
privateKey: string,
|
||||
|
|
|
@ -53,6 +53,7 @@ import { In } from "typeorm";
|
|||
import { DB_MAX_IMAGE_COMMENT_LENGTH } from "@/misc/hard-limits.js";
|
||||
import { truncate } from "@/misc/truncate.js";
|
||||
import { type Size, getEmojiSize } from "@/misc/emoji-meta.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
|
||||
const logger = apLogger;
|
||||
|
||||
|
@ -544,6 +545,10 @@ function notEmpty(partial: Partial<any>) {
|
|||
export async function updateNote(value: string | IObject, resolver?: Resolver) {
|
||||
const uri = typeof value === "string" ? value : value.id;
|
||||
if (!uri) throw new Error("Missing note uri");
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.experimentalFeatures?.postEdits === false) {
|
||||
throw new Error("Post edits disabled.");
|
||||
}
|
||||
|
||||
// Skip if URI points to this server
|
||||
if (uri.startsWith(`${config.url}/`)) throw new Error("uri points local");
|
||||
|
|
|
@ -23,6 +23,12 @@ export const meta = {
|
|||
code: "NO_SUCH_USER_GROUP",
|
||||
id: "aa3c0b9a-8cae-47c0-92ac-202ce5906682",
|
||||
},
|
||||
|
||||
tooManyAntennas: {
|
||||
message: "Too many antennas.",
|
||||
code: "TOO_MANY_ANTENNAS",
|
||||
id: "c3a5a51e-04d4-11ee-be56-0242ac120002",
|
||||
},
|
||||
},
|
||||
|
||||
res: {
|
||||
|
@ -97,6 +103,13 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
let userList;
|
||||
let userGroupJoining;
|
||||
|
||||
const antennas = await Antennas.findBy({
|
||||
userId: user.id,
|
||||
});
|
||||
if (antennas.length > 5 && !user.isAdmin) {
|
||||
throw new ApiError(meta.errors.tooManyAntennas);
|
||||
}
|
||||
|
||||
if (ps.src === "list" && ps.userListId) {
|
||||
userList = await UserLists.findOneBy({
|
||||
id: ps.userListId,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import * as JSON5 from "json5";
|
||||
import JSON5 from "json5";
|
||||
import { IsNull, MoreThan } from "typeorm";
|
||||
import config from "@/config/index.js";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
|
@ -323,7 +323,7 @@ export const meta = {
|
|||
optional: false,
|
||||
nullable: false,
|
||||
},
|
||||
elasticsearch: {
|
||||
searchFilters: {
|
||||
type: "boolean",
|
||||
optional: false,
|
||||
nullable: false,
|
||||
|
@ -521,7 +521,7 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
recommendedTimeline: !instance.disableRecommendedTimeline,
|
||||
globalTimeLine: !instance.disableGlobalTimeline,
|
||||
emailRequiredForSignup: instance.emailRequiredForSignup,
|
||||
elasticsearch: config.elasticsearch ? true : false,
|
||||
searchFilters: config.meilisearch ? true : false,
|
||||
hcaptcha: instance.enableHcaptcha,
|
||||
recaptcha: instance.enableRecaptcha,
|
||||
objectStorage: instance.useObjectStorage,
|
||||
|
|
|
@ -244,8 +244,9 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
if (user.movedToUri != null) throw new ApiError(meta.errors.accountLocked);
|
||||
|
||||
const instanceMeta = await fetchMeta();
|
||||
if (instanceMeta.experimentalFeatures?.postImports === false)
|
||||
if (instanceMeta.experimentalFeatures?.postEdits === false) {
|
||||
throw new ApiError(meta.errors.editsDisabled);
|
||||
}
|
||||
|
||||
if (!Users.isLocalUser(user)) {
|
||||
throw new ApiError(meta.errors.notLocalUser);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import define from "../define.js";
|
||||
import { redisClient } from "@/db/redis.js";
|
||||
|
||||
export const meta = {
|
||||
tags: ["meta"],
|
||||
|
@ -16,13 +17,16 @@ export const paramDef = {
|
|||
|
||||
export default define(meta, paramDef, async () => {
|
||||
let patrons;
|
||||
await fetch(
|
||||
"https://codeberg.org/calckey/calckey/raw/branch/develop/patrons.json",
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
patrons = data["patrons"];
|
||||
});
|
||||
const cachedPatrons = await redisClient.get("patrons");
|
||||
if (cachedPatrons) {
|
||||
patrons = JSON.parse(cachedPatrons);
|
||||
}
|
||||
else {
|
||||
patrons = await fetch(
|
||||
"https://codeberg.org/calckey/calckey/raw/branch/develop/patrons.json",
|
||||
).then((response) => response.json());
|
||||
await redisClient.set("patrons", JSON.stringify(patrons), "EX", 3600);
|
||||
}
|
||||
|
||||
return patrons;
|
||||
return patrons["patrons"];
|
||||
});
|
||||
|
|
|
@ -46,7 +46,7 @@ export default class Connection {
|
|||
private channels: Channel[] = [];
|
||||
private subscribingNotes: Map<string, number> = new Map();
|
||||
private cachedNotes: Packed<"Note">[] = [];
|
||||
private isMastodonCompatible: boolean = false;
|
||||
private isMastodonCompatible = false;
|
||||
private host: string;
|
||||
private accessToken: string;
|
||||
private currentSubscribe: string[][] = [];
|
||||
|
|
|
@ -82,6 +82,9 @@ const nodeinfo2 = async () => {
|
|||
disableRecommendedTimeline: meta.disableRecommendedTimeline,
|
||||
disableGlobalTimeline: meta.disableGlobalTimeline,
|
||||
emailRequiredForSignup: meta.emailRequiredForSignup,
|
||||
searchFilters: config.meilisearch ? true : false,
|
||||
postEditing: meta.experimentalFeatures?.postEditing || false,
|
||||
postImports: meta.experimentalFeatures?.postImports || false,
|
||||
enableHcaptcha: meta.enableHcaptcha,
|
||||
enableRecaptcha: meta.enableRecaptcha,
|
||||
maxNoteTextLength: MAX_NOTE_TEXT_LENGTH,
|
||||
|
|
|
@ -16,7 +16,7 @@ import { BullAdapter } from "@bull-board/api/bullAdapter.js";
|
|||
import { KoaAdapter } from "@bull-board/koa";
|
||||
|
||||
import { In, IsNull } from "typeorm";
|
||||
import { fetchMeta } from "@/misc/fetch-meta.js";
|
||||
import { fetchMeta, metaToPugArgs } from "@/misc/fetch-meta.js";
|
||||
import config from "@/config/index.js";
|
||||
import {
|
||||
Users,
|
||||
|
@ -362,15 +362,12 @@ const userPage: Router.Middleware = async (ctx, next) => {
|
|||
: [];
|
||||
|
||||
const userDetail = {
|
||||
...metaToPugArgs(meta),
|
||||
user,
|
||||
profile,
|
||||
me,
|
||||
avatarUrl: await Users.getAvatarUrl(user),
|
||||
sub: subParam,
|
||||
instanceName: meta.name || "Calckey",
|
||||
icon: meta.iconUrl,
|
||||
themeColor: meta.themeColor,
|
||||
privateMode: meta.privateMode,
|
||||
};
|
||||
|
||||
await ctx.render("user", userDetail);
|
||||
|
@ -408,6 +405,7 @@ router.get("/notes/:note", async (ctx, next) => {
|
|||
});
|
||||
const meta = await fetchMeta();
|
||||
await ctx.render("note", {
|
||||
...metaToPugArgs(meta),
|
||||
note: _note,
|
||||
profile,
|
||||
avatarUrl: await Users.getAvatarUrl(
|
||||
|
@ -415,13 +413,13 @@ router.get("/notes/:note", async (ctx, next) => {
|
|||
),
|
||||
// TODO: Let locale changeable by instance setting
|
||||
summary: getNoteSummary(_note),
|
||||
instanceName: meta.name || "Calckey",
|
||||
icon: meta.iconUrl,
|
||||
privateMode: meta.privateMode,
|
||||
themeColor: meta.themeColor,
|
||||
});
|
||||
|
||||
ctx.set("Cache-Control", "public, max-age=15");
|
||||
ctx.set(
|
||||
"Content-Security-Policy",
|
||||
"default-src 'self' 'unsafe-inline'; img-src '*'; frame-ancestors '*'",
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -441,6 +439,7 @@ router.get("/posts/:note", async (ctx, next) => {
|
|||
const profile = await UserProfiles.findOneByOrFail({ userId: note.userId });
|
||||
const meta = await fetchMeta();
|
||||
await ctx.render("note", {
|
||||
...metaToPugArgs(meta),
|
||||
note: _note,
|
||||
profile,
|
||||
avatarUrl: await Users.getAvatarUrl(
|
||||
|
@ -448,10 +447,6 @@ router.get("/posts/:note", async (ctx, next) => {
|
|||
),
|
||||
// TODO: Let locale changeable by instance setting
|
||||
summary: getNoteSummary(_note),
|
||||
instanceName: meta.name || "Calckey",
|
||||
icon: meta.iconUrl,
|
||||
privateMode: meta.privateMode,
|
||||
themeColor: meta.themeColor,
|
||||
});
|
||||
|
||||
ctx.set("Cache-Control", "public, max-age=15");
|
||||
|
@ -482,15 +477,12 @@ router.get("/@:user/pages/:page", async (ctx, next) => {
|
|||
const profile = await UserProfiles.findOneByOrFail({ userId: page.userId });
|
||||
const meta = await fetchMeta();
|
||||
await ctx.render("page", {
|
||||
...metaToPugArgs(meta),
|
||||
page: _page,
|
||||
profile,
|
||||
avatarUrl: await Users.getAvatarUrl(
|
||||
await Users.findOneByOrFail({ id: page.userId }),
|
||||
),
|
||||
instanceName: meta.name || "Calckey",
|
||||
icon: meta.iconUrl,
|
||||
themeColor: meta.themeColor,
|
||||
privateMode: meta.privateMode,
|
||||
});
|
||||
|
||||
if (["public"].includes(page.visibility)) {
|
||||
|
@ -517,15 +509,12 @@ router.get("/clips/:clip", async (ctx, next) => {
|
|||
const profile = await UserProfiles.findOneByOrFail({ userId: clip.userId });
|
||||
const meta = await fetchMeta();
|
||||
await ctx.render("clip", {
|
||||
...metaToPugArgs(meta),
|
||||
clip: _clip,
|
||||
profile,
|
||||
avatarUrl: await Users.getAvatarUrl(
|
||||
await Users.findOneByOrFail({ id: clip.userId }),
|
||||
),
|
||||
instanceName: meta.name || "Calckey",
|
||||
privateMode: meta.privateMode,
|
||||
icon: meta.iconUrl,
|
||||
themeColor: meta.themeColor,
|
||||
});
|
||||
|
||||
ctx.set("Cache-Control", "public, max-age=15");
|
||||
|
@ -545,15 +534,12 @@ router.get("/gallery/:post", async (ctx, next) => {
|
|||
const profile = await UserProfiles.findOneByOrFail({ userId: post.userId });
|
||||
const meta = await fetchMeta();
|
||||
await ctx.render("gallery-post", {
|
||||
...metaToPugArgs(meta),
|
||||
post: _post,
|
||||
profile,
|
||||
avatarUrl: await Users.getAvatarUrl(
|
||||
await Users.findOneByOrFail({ id: post.userId }),
|
||||
),
|
||||
instanceName: meta.name || "Calckey",
|
||||
icon: meta.iconUrl,
|
||||
themeColor: meta.themeColor,
|
||||
privateMode: meta.privateMode,
|
||||
});
|
||||
|
||||
ctx.set("Cache-Control", "public, max-age=15");
|
||||
|
@ -574,11 +560,8 @@ router.get("/channels/:channel", async (ctx, next) => {
|
|||
const _channel = await Channels.pack(channel);
|
||||
const meta = await fetchMeta();
|
||||
await ctx.render("channel", {
|
||||
...metaToPugArgs(meta),
|
||||
channel: _channel,
|
||||
instanceName: meta.name || "Calckey",
|
||||
icon: meta.iconUrl,
|
||||
themeColor: meta.themeColor,
|
||||
privateMode: meta.privateMode,
|
||||
});
|
||||
|
||||
ctx.set("Cache-Control", "public, max-age=15");
|
||||
|
@ -629,27 +612,9 @@ router.get("/api/v1/streaming", async (ctx) => {
|
|||
// Render base html for all requests
|
||||
router.get("(.*)", async (ctx) => {
|
||||
const meta = await fetchMeta();
|
||||
let motd = ["Loading..."];
|
||||
if (meta.customMOTD.length > 0) {
|
||||
motd = meta.customMOTD;
|
||||
}
|
||||
let splashIconUrl = meta.iconUrl;
|
||||
if (meta.customSplashIcons.length > 0) {
|
||||
splashIconUrl =
|
||||
meta.customSplashIcons[
|
||||
Math.floor(Math.random() * meta.customSplashIcons.length)
|
||||
];
|
||||
}
|
||||
|
||||
await ctx.render("base", {
|
||||
img: meta.bannerUrl,
|
||||
title: meta.name || "Calckey",
|
||||
instanceName: meta.name || "Calckey",
|
||||
desc: meta.description,
|
||||
icon: meta.iconUrl,
|
||||
splashIcon: splashIconUrl,
|
||||
themeColor: meta.themeColor,
|
||||
randomMOTD: motd[Math.floor(Math.random() * motd.length)],
|
||||
privateMode: meta.privateMode,
|
||||
...metaToPugArgs(meta),
|
||||
});
|
||||
ctx.set("Cache-Control", "public, max-age=3");
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ export async function convertToWebp(
|
|||
path: string,
|
||||
width: number,
|
||||
height: number,
|
||||
quality: number = 85,
|
||||
quality = 85,
|
||||
): Promise<IImage> {
|
||||
return convertSharpToWebp(await sharp(path), width, height, quality);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ export async function convertSharpToWebp(
|
|||
sharp: sharp.Sharp,
|
||||
width: number,
|
||||
height: number,
|
||||
quality: number = 85,
|
||||
quality = 85,
|
||||
): Promise<IImage> {
|
||||
const data = await sharp
|
||||
.resize(width, height, {
|
||||
|
|
|
@ -597,20 +597,20 @@ export default async (
|
|||
lastNotedAt: new Date(),
|
||||
});
|
||||
|
||||
const count = await Notes.countBy({
|
||||
await Notes.countBy({
|
||||
userId: user.id,
|
||||
channelId: data.channel.id,
|
||||
}).then((count) => {
|
||||
// この処理が行われるのはノート作成後なので、ノートが一つしかなかったら最初の投稿だと判断できる
|
||||
// TODO: とはいえノートを削除して何回も投稿すればその分だけインクリメントされる雑さもあるのでどうにかしたい
|
||||
if (count === 1) {
|
||||
Channels.increment({ id: data.channel!.id }, "usersCount", 1);
|
||||
if (count === 1 && data.channel != null) {
|
||||
Channels.increment({ id: data.channel.id }, "usersCount", 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Register to search database
|
||||
await index(note);
|
||||
await index(note, false);
|
||||
});
|
||||
|
||||
async function renderNoteOrRenoteActivity(data: Option, note: Note) {
|
||||
|
@ -650,9 +650,12 @@ async function insertNote(
|
|||
emojis: string[],
|
||||
mentionedUsers: MinimumUser[],
|
||||
) {
|
||||
if (data.createdAt === null || data.createdAt === undefined) {
|
||||
data.createdAt = new Date();
|
||||
}
|
||||
const insert = new Note({
|
||||
id: genId(data.createdAt!),
|
||||
createdAt: data.createdAt!,
|
||||
id: genId(data.createdAt),
|
||||
createdAt: data.createdAt,
|
||||
fileIds: data.files ? data.files.map((file) => file.id) : [],
|
||||
replyId: data.reply ? data.reply.id : null,
|
||||
renoteId: data.renote ? data.renote.id : null,
|
||||
|
@ -669,7 +672,7 @@ async function insertNote(
|
|||
tags: tags.map((tag) => normalizeForSearch(tag)),
|
||||
emojis,
|
||||
userId: user.id,
|
||||
localOnly: data.localOnly!,
|
||||
localOnly: data.localOnly || false,
|
||||
visibility: data.visibility as any,
|
||||
visibleUserIds:
|
||||
data.visibility === "specified"
|
||||
|
@ -716,14 +719,23 @@ async function insertNote(
|
|||
if (insert.hasPoll) {
|
||||
// Start transaction
|
||||
await db.transaction(async (transactionalEntityManager) => {
|
||||
if (!data.poll) throw new Error("Empty poll data");
|
||||
|
||||
await transactionalEntityManager.insert(Note, insert);
|
||||
|
||||
let expiresAt: Date | null;
|
||||
if (!data.poll.expiresAt || isNaN(data.poll.expiresAt.getTime())) {
|
||||
expiresAt = null;
|
||||
} else {
|
||||
expiresAt = data.poll.expiresAt;
|
||||
}
|
||||
|
||||
const poll = new Poll({
|
||||
noteId: insert.id,
|
||||
choices: data.poll!.choices,
|
||||
expiresAt: data.poll!.expiresAt,
|
||||
multiple: data.poll!.multiple,
|
||||
votes: new Array(data.poll!.choices.length).fill(0),
|
||||
choices: data.poll.choices,
|
||||
expiresAt,
|
||||
multiple: data.poll.multiple,
|
||||
votes: new Array(data.poll.choices.length).fill(0),
|
||||
noteVisibility: insert.visibility,
|
||||
userId: user.id,
|
||||
userHost: user.host,
|
||||
|
|
Before Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 441 B After Width: | Height: | Size: 130 B |
Before Width: | Height: | Size: 441 B After Width: | Height: | Size: 130 B |
Before Width: | Height: | Size: 424 B |
Before Width: | Height: | Size: 536 B |
|
@ -8,25 +8,25 @@
|
|||
"format": "pnpm prettier --write '**/*.vue'"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@discordapp/twemoji": "14.0.2",
|
||||
"@discordapp/twemoji": "14.1.2",
|
||||
"@phosphor-icons/web": "^2.0.3",
|
||||
"@rollup/plugin-alias": "3.1.9",
|
||||
"@rollup/plugin-json": "4.1.0",
|
||||
"@rollup/pluginutils": "^4.2.1",
|
||||
"@syuilo/aiscript": "0.11.1",
|
||||
"@types/escape-regexp": "0.0.1",
|
||||
"@types/glob": "8.0.0",
|
||||
"@types/gulp": "4.0.10",
|
||||
"@types/gulp-rename": "2.0.1",
|
||||
"@types/katex": "0.14.0",
|
||||
"@types/glob": "8.1.0",
|
||||
"@types/gulp": "4.0.11",
|
||||
"@types/gulp-rename": "2.0.2",
|
||||
"@types/katex": "0.16.0",
|
||||
"@types/matter-js": "0.18.2",
|
||||
"@types/punycode": "2.1.0",
|
||||
"@types/seedrandom": "3.0.4",
|
||||
"@types/seedrandom": "3.0.5",
|
||||
"@types/throttle-debounce": "5.0.0",
|
||||
"@types/tinycolor2": "1.4.3",
|
||||
"@types/uuid": "8.3.4",
|
||||
"@vitejs/plugin-vue": "4.0.0",
|
||||
"@vue/compiler-sfc": "3.2.45",
|
||||
"@vitejs/plugin-vue": "4.2.3",
|
||||
"@vue/compiler-sfc": "3.3.4",
|
||||
"autobind-decorator": "2.4.0",
|
||||
"autosize": "5.0.2",
|
||||
"blurhash": "1.1.5",
|
||||
|
@ -46,23 +46,25 @@
|
|||
"date-fns": "2.30.0",
|
||||
"escape-regexp": "0.0.1",
|
||||
"eventemitter3": "4.0.7",
|
||||
"gsap": "^3.11.4",
|
||||
"idb-keyval": "6.2.0",
|
||||
"focus-trap": "^7.4.3",
|
||||
"focus-trap-vue": "^4.0.2",
|
||||
"gsap": "^3.11.5",
|
||||
"idb-keyval": "6.2.1",
|
||||
"insert-text-at-cursor": "0.3.0",
|
||||
"json5": "2.2.3",
|
||||
"katex": "0.16.4",
|
||||
"katex": "0.16.7",
|
||||
"matter-js": "0.18.0",
|
||||
"mfm-js": "0.23.3",
|
||||
"photoswipe": "5.3.4",
|
||||
"prettier": "2.8.7",
|
||||
"photoswipe": "5.3.7",
|
||||
"prettier": "2.8.8",
|
||||
"prettier-plugin-vue": "1.1.6",
|
||||
"prismjs": "1.29.0",
|
||||
"punycode": "2.1.1",
|
||||
"querystring": "0.2.1",
|
||||
"rndstr": "1.0.0",
|
||||
"rollup": "3.9.1",
|
||||
"rollup": "3.23.1",
|
||||
"s-age": "1.1.2",
|
||||
"sass": "1.57.1",
|
||||
"sass": "1.62.1",
|
||||
"seedrandom": "3.0.5",
|
||||
"start-server-and-test": "1.15.2",
|
||||
"strict-event-emitter-types": "2.0.0",
|
||||
|
@ -73,15 +75,15 @@
|
|||
"three": "0.146.0",
|
||||
"throttle-debounce": "5.0.0",
|
||||
"tinycolor2": "1.5.2",
|
||||
"tsc-alias": "1.8.2",
|
||||
"tsconfig-paths": "4.1.2",
|
||||
"tsc-alias": "1.8.6",
|
||||
"tsconfig-paths": "4.2.0",
|
||||
"twemoji-parser": "14.0.0",
|
||||
"typescript": "4.9.4",
|
||||
"typescript": "5.1.3",
|
||||
"uuid": "9.0.0",
|
||||
"vanilla-tilt": "1.8.0",
|
||||
"vite": "4.3.9",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vue": "3.2.45",
|
||||
"vue": "3.3.4",
|
||||
"vue-isyourpasswordsafe": "^2.0.0",
|
||||
"vue-plyr": "^7.0.0",
|
||||
"vue-prism-editor": "2.0.0-alpha.2",
|
||||
|
|
|
@ -102,12 +102,8 @@ function isMe(message): boolean {
|
|||
opacity: 0.8;
|
||||
}
|
||||
|
||||
&:not(.isMe):not(.isRead) {
|
||||
> div {
|
||||
background-image: url("/client-assets/unread.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 center;
|
||||
}
|
||||
&:not(.isRead) {
|
||||
background-color: var(--accentedBg);
|
||||
}
|
||||
|
||||
&:after {
|
||||
|
@ -179,13 +175,6 @@ function isMe(message): boolean {
|
|||
|
||||
&.max-width_400px {
|
||||
> .message {
|
||||
&:not(.isMe):not(.isRead) {
|
||||
> div {
|
||||
background-image: none;
|
||||
border-left: solid 4px #3aa2dc;
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
padding: 16px;
|
||||
font-size: 0.9em;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<MkA
|
||||
v-if="url.startsWith('/')"
|
||||
v-user-preview="canonical"
|
||||
class="akbvjaqn"
|
||||
class="mention"
|
||||
:class="{ isMe }"
|
||||
:to="url"
|
||||
@click.stop
|
||||
|
@ -19,7 +19,7 @@
|
|||
</MkA>
|
||||
<a
|
||||
v-else
|
||||
class="akbvjaqn"
|
||||
class="mention"
|
||||
:href="url"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
|
@ -58,7 +58,7 @@ const isMe =
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.akbvjaqn {
|
||||
.mention {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
padding: 2px 8px 2px 2px;
|
||||
|
@ -68,6 +68,7 @@ const isMe =
|
|||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
color: var(--mention);
|
||||
isolation: isolate;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
|
|
|
@ -128,7 +128,11 @@
|
|||
<button
|
||||
v-else-if="!item.hidden"
|
||||
class="_button item"
|
||||
:class="{ danger: item.danger, active: item.active }"
|
||||
:class="{
|
||||
danger: item.danger,
|
||||
accent: item.accent,
|
||||
active: item.active,
|
||||
}"
|
||||
:disabled="item.active"
|
||||
@click="clicked(item.action, $event)"
|
||||
@mouseenter.passive="onItemMouseEnter(item)"
|
||||
|
@ -365,10 +369,6 @@ onBeforeUnmount(() => {
|
|||
position: relative;
|
||||
}
|
||||
|
||||
> &.icon {
|
||||
transform: translateY(0em);
|
||||
}
|
||||
|
||||
&:not(:disabled):hover,
|
||||
&:focus-visible {
|
||||
color: var(--accent);
|
||||
|
@ -402,6 +402,26 @@ onBeforeUnmount(() => {
|
|||
}
|
||||
}
|
||||
|
||||
&.accent {
|
||||
color: var(--accent);
|
||||
|
||||
&:hover {
|
||||
color: var(--accent);
|
||||
|
||||
&:before {
|
||||
background: var(--accentedBg);
|
||||
}
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: var(--fgOnAccent);
|
||||
|
||||
&:before {
|
||||
background: var(--accent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: var(--fgOnAccent);
|
||||
opacity: 1;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
<div ref="headerEl" class="header">
|
||||
<button
|
||||
v-if="withOkButton"
|
||||
:aria-label="i18n.t('close')"
|
||||
class="_button"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
|
@ -36,6 +37,7 @@
|
|||
</span>
|
||||
<button
|
||||
v-if="!withOkButton"
|
||||
:aria-label="i18n.t('close')"
|
||||
class="_button"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
|
@ -43,6 +45,7 @@
|
|||
</button>
|
||||
<button
|
||||
v-if="withOkButton"
|
||||
:aria-label="i18n.t('ok')"
|
||||
class="_button"
|
||||
:disabled="okButtonDisabled"
|
||||
@click="$emit('ok')"
|
||||
|
@ -61,6 +64,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { FocusTrap } from "focus-trap-vue";
|
||||
import MkModal from "./MkModal.vue";
|
||||
import { i18n } from "@/i18n";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
|
|
|
@ -572,6 +572,7 @@ defineExpose({
|
|||
font-size: 1.05em;
|
||||
overflow: clip;
|
||||
contain: content;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
||||
// これらの指定はパフォーマンス向上には有効だが、ノートの高さは一定でないため、
|
||||
// 下の方までスクロールすると上のノートの高さがここで決め打ちされたものに変化し、表示しているノートの位置が変わってしまう
|
||||
|
@ -820,6 +821,10 @@ defineExpose({
|
|||
color: var(--fgHighlighted);
|
||||
}
|
||||
|
||||
> i {
|
||||
display: inline !important;
|
||||
}
|
||||
|
||||
> .count {
|
||||
display: inline;
|
||||
margin: 0 0 0 8px;
|
||||
|
|
|
@ -559,7 +559,7 @@ onUnmounted(() => {
|
|||
inset: 0px 8px;
|
||||
}
|
||||
&:not(.max-width_450px)::before {
|
||||
bottom: 12px;
|
||||
bottom: 16px;
|
||||
}
|
||||
&:first-of-type::before {
|
||||
top: 12px;
|
||||
|
@ -614,8 +614,16 @@ onUnmounted(() => {
|
|||
font-size: 0.9em;
|
||||
}
|
||||
&.max-width_450px {
|
||||
> .reply-to:first-child {
|
||||
padding-top: 14px;
|
||||
> .reply-to {
|
||||
&::before {
|
||||
inset-inline: -24px;
|
||||
}
|
||||
&:first-child {
|
||||
padding-top: 14px;
|
||||
&::before {
|
||||
top: -24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> :deep(.note-container) {
|
||||
|
|
|
@ -20,8 +20,6 @@ const props = defineProps<{
|
|||
note: misskey.entities.Note;
|
||||
pinned?: boolean;
|
||||
}>();
|
||||
|
||||
const showContent = $ref(false);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
@ -506,6 +506,10 @@ function noteClick(e) {
|
|||
color: var(--fgHighlighted);
|
||||
}
|
||||
|
||||
> i {
|
||||
display: inline !important;
|
||||
}
|
||||
|
||||
> .count {
|
||||
display: inline;
|
||||
margin: 0 0 0 8px;
|
||||
|
@ -539,6 +543,14 @@ function noteClick(e) {
|
|||
border-radius: var(--radius);
|
||||
}
|
||||
}
|
||||
&.reply-to {
|
||||
> .main > .body {
|
||||
margin-left: calc(0px - var(--avatarSize) - 38px);
|
||||
padding-left: calc(var(--avatarSize) + 38px);
|
||||
margin-top: -16px;
|
||||
padding-top: 16px;
|
||||
}
|
||||
}
|
||||
&.reply {
|
||||
--avatarSize: 38px;
|
||||
.avatar-container {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
ref="buttonRef"
|
||||
v-tooltip.noDelay.bottom="i18n.ts.renote"
|
||||
class="button _button canRenote"
|
||||
:class="{ renoted: hasRenotedBefore }"
|
||||
@click="renote(false, $event)"
|
||||
>
|
||||
<i class="ph-repeat ph-bold ph-lg"></i>
|
||||
|
@ -64,17 +65,18 @@ useTooltip(buttonRef, async (showing) => {
|
|||
);
|
||||
});
|
||||
|
||||
const renote = async (viaKeyboard = false, ev?: MouseEvent) => {
|
||||
let hasRenotedBefore = $ref(false);
|
||||
os.api("notes/renotes", {
|
||||
noteId: props.note.id,
|
||||
userId: $i.id,
|
||||
limit: 1,
|
||||
}).then((res) => {
|
||||
hasRenotedBefore = res.length > 0;
|
||||
});
|
||||
|
||||
const renote = (viaKeyboard = false, ev?: MouseEvent) => {
|
||||
pleaseLogin();
|
||||
|
||||
const renotes = await os.api("notes/renotes", {
|
||||
noteId: props.note.id,
|
||||
userId: $i.id,
|
||||
limit: 1,
|
||||
});
|
||||
|
||||
const hasRenotedBefore = renotes.length > 0;
|
||||
|
||||
let buttonActions: Array<MenuItem> = [];
|
||||
|
||||
if (props.note.visibility === "public") {
|
||||
|
@ -88,6 +90,7 @@ const renote = async (viaKeyboard = false, ev?: MouseEvent) => {
|
|||
renoteId: props.note.id,
|
||||
visibility: "public",
|
||||
});
|
||||
hasRenotedBefore = true;
|
||||
const el =
|
||||
ev &&
|
||||
((ev.currentTarget ?? ev.target) as
|
||||
|
@ -114,6 +117,7 @@ const renote = async (viaKeyboard = false, ev?: MouseEvent) => {
|
|||
renoteId: props.note.id,
|
||||
visibility: "home",
|
||||
});
|
||||
hasRenotedBefore = true;
|
||||
const el =
|
||||
ev &&
|
||||
((ev.currentTarget ?? ev.target) as
|
||||
|
@ -141,6 +145,7 @@ const renote = async (viaKeyboard = false, ev?: MouseEvent) => {
|
|||
visibility: "specified",
|
||||
visibleUserIds: props.note.visibleUserIds,
|
||||
});
|
||||
hasRenotedBefore = true;
|
||||
const el =
|
||||
ev &&
|
||||
((ev.currentTarget ?? ev.target) as
|
||||
|
@ -165,6 +170,7 @@ const renote = async (viaKeyboard = false, ev?: MouseEvent) => {
|
|||
renoteId: props.note.id,
|
||||
visibility: "followers",
|
||||
});
|
||||
hasRenotedBefore = true;
|
||||
const el =
|
||||
ev &&
|
||||
((ev.currentTarget ?? ev.target) as
|
||||
|
@ -202,6 +208,7 @@ const renote = async (viaKeyboard = false, ev?: MouseEvent) => {
|
|||
localOnly: true,
|
||||
}
|
||||
);
|
||||
hasRenotedBefore = true;
|
||||
const el =
|
||||
ev &&
|
||||
((ev.currentTarget ?? ev.target) as
|
||||
|
@ -240,6 +247,7 @@ const renote = async (viaKeyboard = false, ev?: MouseEvent) => {
|
|||
os.api("notes/unrenote", {
|
||||
noteId: props.note.id,
|
||||
});
|
||||
hasRenotedBefore = false;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -253,7 +261,9 @@ const renote = async (viaKeyboard = false, ev?: MouseEvent) => {
|
|||
cursor: default;
|
||||
}
|
||||
&.renoted {
|
||||
background: var(--accent);
|
||||
color: var(--accent) !important;
|
||||
opacity: 1 !important;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
isLong,
|
||||
manyImages: note.files.length > 4,
|
||||
showContent: note.cw && !showContent,
|
||||
disableAnim: disableMfm,
|
||||
animatedMfm: !disableMfm,
|
||||
}"
|
||||
>
|
||||
<XShowMoreButton
|
||||
|
@ -213,8 +213,8 @@ const isLong =
|
|||
!props.detailedView &&
|
||||
((props.note.cw == null &&
|
||||
props.note.text != null &&
|
||||
(props.note.text.split("\n").length > 9 ||
|
||||
props.note.text.length > 500)) ||
|
||||
(props.note.text.split("\n").length > 10 ||
|
||||
props.note.text.length > 800)) ||
|
||||
props.note.files.length > 4);
|
||||
|
||||
const collapsed = $ref(props.note.cw == null && isLong);
|
||||
|
@ -231,7 +231,7 @@ const mfms = props.note.text
|
|||
|
||||
const hasMfm = $ref(mfms && mfms.length > 0);
|
||||
|
||||
let disableMfm = $ref(hasMfm && defaultStore.state.animatedMfm);
|
||||
let disableMfm = $ref(defaultStore.state.animatedMfm);
|
||||
|
||||
async function toggleMfm() {
|
||||
if (disableMfm) {
|
||||
|
@ -340,7 +340,7 @@ function focusFooter(ev) {
|
|||
&.collapsed,
|
||||
&.showContent {
|
||||
position: relative;
|
||||
max-height: calc(9em + 50px);
|
||||
max-height: calc(15em + 100px);
|
||||
> .body {
|
||||
max-height: inherit;
|
||||
mask: linear-gradient(black calc(100% - 64px), transparent);
|
||||
|
@ -348,10 +348,10 @@ function focusFooter(ev) {
|
|||
black calc(100% - 64px),
|
||||
transparent
|
||||
);
|
||||
padding-inline: 50px;
|
||||
margin-inline: -50px;
|
||||
margin-top: -50px;
|
||||
padding-top: 50px;
|
||||
padding-inline: 100px;
|
||||
margin-inline: -100px;
|
||||
margin-top: -100px;
|
||||
padding-top: 100px;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
|
@ -360,7 +360,7 @@ function focusFooter(ev) {
|
|||
}
|
||||
&.collapsed {
|
||||
&.manyImages {
|
||||
max-height: calc(9em + 200px);
|
||||
max-height: calc(15em + 250px);
|
||||
}
|
||||
> .body {
|
||||
box-sizing: border-box;
|
||||
|
@ -381,11 +381,11 @@ function focusFooter(ev) {
|
|||
}
|
||||
:deep(.fade) {
|
||||
inset: 0;
|
||||
top: 40px;
|
||||
top: 90px;
|
||||
}
|
||||
}
|
||||
|
||||
&.disableAnim :deep(span) {
|
||||
&:not(.animatedMfm) :deep(span) {
|
||||
animation: none !important;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,14 +6,18 @@
|
|||
:author="author"
|
||||
:customEmojis="customEmojis"
|
||||
:isNote="isNote"
|
||||
class="havbbuyv"
|
||||
:class="{ nowrap }"
|
||||
class="mfm-object"
|
||||
:class="{
|
||||
nowrap,
|
||||
advancedMfm: defaultStore.state.advancedMfm,
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {} from "vue";
|
||||
import MfmCore from "@/components/mfm";
|
||||
import { defaultStore } from "@/store";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
|
@ -34,284 +38,309 @@ const props = withDefaults(
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.mfm-x2 {
|
||||
--mfm-zoom-size: 200%;
|
||||
.content:not(.animatedMfm) {
|
||||
.mfm-object:not(.advancedMfm) {
|
||||
[style*="animation:"] {
|
||||
animation: none !important;
|
||||
}
|
||||
[style*="transform:"] {
|
||||
transform: none !important;
|
||||
}
|
||||
[style*="background-color:"] {
|
||||
background: none !important;
|
||||
}
|
||||
[style*="color:"] {
|
||||
color: inherit !important;
|
||||
}
|
||||
[style*="font-family:"] {
|
||||
font-family: inherit !important;
|
||||
}
|
||||
[style*="clip-path:"] {
|
||||
clip-path: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mfm-object.advancedMfm,
|
||||
.content.animatedMfm {
|
||||
.mfm-x2 {
|
||||
--mfm-zoom-size: 200%;
|
||||
}
|
||||
|
||||
.mfm-x3 {
|
||||
--mfm-zoom-size: 400%;
|
||||
}
|
||||
.mfm-x3 {
|
||||
--mfm-zoom-size: 400%;
|
||||
}
|
||||
|
||||
.mfm-x4 {
|
||||
--mfm-zoom-size: 600%;
|
||||
}
|
||||
|
||||
.mfm-x2,
|
||||
.mfm-x3,
|
||||
.mfm-x4 {
|
||||
font-size: var(--mfm-zoom-size);
|
||||
.mfm-x4 {
|
||||
--mfm-zoom-size: 600%;
|
||||
}
|
||||
|
||||
.mfm-x2,
|
||||
.mfm-x3,
|
||||
.mfm-x4 {
|
||||
/* only half effective */
|
||||
font-size: calc(var(--mfm-zoom-size) / 2 + 50%);
|
||||
font-size: var(--mfm-zoom-size);
|
||||
|
||||
.mfm-x2,
|
||||
.mfm-x3,
|
||||
.mfm-x4 {
|
||||
/* disabled */
|
||||
font-size: 100%;
|
||||
/* only half effective */
|
||||
font-size: calc(var(--mfm-zoom-size) / 2 + 50%);
|
||||
|
||||
.mfm-x2,
|
||||
.mfm-x3,
|
||||
.mfm-x4 {
|
||||
/* disabled */
|
||||
font-size: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mfm-spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
@keyframes mfm-spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mfm-spinX {
|
||||
0% {
|
||||
transform: perspective(128px) rotateX(0deg);
|
||||
@keyframes mfm-spinX {
|
||||
0% {
|
||||
transform: perspective(128px) rotateX(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: perspective(128px) rotateX(360deg);
|
||||
}
|
||||
}
|
||||
100% {
|
||||
transform: perspective(128px) rotateX(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mfm-spinY {
|
||||
0% {
|
||||
transform: perspective(128px) rotateY(0deg);
|
||||
@keyframes mfm-spinY {
|
||||
0% {
|
||||
transform: perspective(128px) rotateY(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: perspective(128px) rotateY(360deg);
|
||||
}
|
||||
}
|
||||
100% {
|
||||
transform: perspective(128px) rotateY(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mfm-jump {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
@keyframes mfm-jump {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
25% {
|
||||
transform: translateY(-16px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
75% {
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
25% {
|
||||
transform: translateY(-16px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
75% {
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mfm-bounce {
|
||||
0% {
|
||||
transform: translateY(0) scale(1, 1);
|
||||
@keyframes mfm-bounce {
|
||||
0% {
|
||||
transform: translateY(0) scale(1, 1);
|
||||
}
|
||||
25% {
|
||||
transform: translateY(-16px) scale(1, 1);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(0) scale(1, 1);
|
||||
}
|
||||
75% {
|
||||
transform: translateY(0) scale(1.5, 0.75);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0) scale(1, 1);
|
||||
}
|
||||
}
|
||||
25% {
|
||||
transform: translateY(-16px) scale(1, 1);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(0) scale(1, 1);
|
||||
}
|
||||
75% {
|
||||
transform: translateY(0) scale(1.5, 0.75);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0) scale(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// const val = () => `translate(${Math.floor(Math.random() * 20) - 10}px, ${Math.floor(Math.random() * 20) - 10}px)`;
|
||||
// let css = '';
|
||||
// for (let i = 0; i <= 100; i += 5) { css += `${i}% { transform: ${val()} }\n`; }
|
||||
@keyframes mfm-twitch {
|
||||
0% {
|
||||
transform: translate(7px, -2px);
|
||||
// const val = () => `translate(${Math.floor(Math.random() * 20) - 10}px, ${Math.floor(Math.random() * 20) - 10}px)`;
|
||||
// let css = '';
|
||||
// for (let i = 0; i <= 100; i += 5) { css += `${i}% { transform: ${val()} }\n`; }
|
||||
@keyframes mfm-twitch {
|
||||
0% {
|
||||
transform: translate(7px, -2px);
|
||||
}
|
||||
5% {
|
||||
transform: translate(-3px, 1px);
|
||||
}
|
||||
10% {
|
||||
transform: translate(-7px, -1px);
|
||||
}
|
||||
15% {
|
||||
transform: translate(0px, -1px);
|
||||
}
|
||||
20% {
|
||||
transform: translate(-8px, 6px);
|
||||
}
|
||||
25% {
|
||||
transform: translate(-4px, -3px);
|
||||
}
|
||||
30% {
|
||||
transform: translate(-4px, -6px);
|
||||
}
|
||||
35% {
|
||||
transform: translate(-8px, -8px);
|
||||
}
|
||||
40% {
|
||||
transform: translate(4px, 6px);
|
||||
}
|
||||
45% {
|
||||
transform: translate(-3px, 1px);
|
||||
}
|
||||
50% {
|
||||
transform: translate(2px, -10px);
|
||||
}
|
||||
55% {
|
||||
transform: translate(-7px, 0px);
|
||||
}
|
||||
60% {
|
||||
transform: translate(-2px, 4px);
|
||||
}
|
||||
65% {
|
||||
transform: translate(3px, -8px);
|
||||
}
|
||||
70% {
|
||||
transform: translate(6px, 7px);
|
||||
}
|
||||
75% {
|
||||
transform: translate(-7px, -2px);
|
||||
}
|
||||
80% {
|
||||
transform: translate(-7px, -8px);
|
||||
}
|
||||
85% {
|
||||
transform: translate(9px, 3px);
|
||||
}
|
||||
90% {
|
||||
transform: translate(-3px, -2px);
|
||||
}
|
||||
95% {
|
||||
transform: translate(-10px, 2px);
|
||||
}
|
||||
100% {
|
||||
transform: translate(-2px, -6px);
|
||||
}
|
||||
}
|
||||
5% {
|
||||
transform: translate(-3px, 1px);
|
||||
}
|
||||
10% {
|
||||
transform: translate(-7px, -1px);
|
||||
}
|
||||
15% {
|
||||
transform: translate(0px, -1px);
|
||||
}
|
||||
20% {
|
||||
transform: translate(-8px, 6px);
|
||||
}
|
||||
25% {
|
||||
transform: translate(-4px, -3px);
|
||||
}
|
||||
30% {
|
||||
transform: translate(-4px, -6px);
|
||||
}
|
||||
35% {
|
||||
transform: translate(-8px, -8px);
|
||||
}
|
||||
40% {
|
||||
transform: translate(4px, 6px);
|
||||
}
|
||||
45% {
|
||||
transform: translate(-3px, 1px);
|
||||
}
|
||||
50% {
|
||||
transform: translate(2px, -10px);
|
||||
}
|
||||
55% {
|
||||
transform: translate(-7px, 0px);
|
||||
}
|
||||
60% {
|
||||
transform: translate(-2px, 4px);
|
||||
}
|
||||
65% {
|
||||
transform: translate(3px, -8px);
|
||||
}
|
||||
70% {
|
||||
transform: translate(6px, 7px);
|
||||
}
|
||||
75% {
|
||||
transform: translate(-7px, -2px);
|
||||
}
|
||||
80% {
|
||||
transform: translate(-7px, -8px);
|
||||
}
|
||||
85% {
|
||||
transform: translate(9px, 3px);
|
||||
}
|
||||
90% {
|
||||
transform: translate(-3px, -2px);
|
||||
}
|
||||
95% {
|
||||
transform: translate(-10px, 2px);
|
||||
}
|
||||
100% {
|
||||
transform: translate(-2px, -6px);
|
||||
}
|
||||
}
|
||||
|
||||
// const val = () => `translate(${Math.floor(Math.random() * 6) - 3}px, ${Math.floor(Math.random() * 6) - 3}px) rotate(${Math.floor(Math.random() * 24) - 12}deg)`;
|
||||
// let css = '';
|
||||
// for (let i = 0; i <= 100; i += 5) { css += `${i}% { transform: ${val()} }\n`; }
|
||||
@keyframes mfm-shake {
|
||||
0% {
|
||||
transform: translate(-3px, -1px) rotate(-8deg);
|
||||
// const val = () => `translate(${Math.floor(Math.random() * 6) - 3}px, ${Math.floor(Math.random() * 6) - 3}px) rotate(${Math.floor(Math.random() * 24) - 12}deg)`;
|
||||
// let css = '';
|
||||
// for (let i = 0; i <= 100; i += 5) { css += `${i}% { transform: ${val()} }\n`; }
|
||||
@keyframes mfm-shake {
|
||||
0% {
|
||||
transform: translate(-3px, -1px) rotate(-8deg);
|
||||
}
|
||||
5% {
|
||||
transform: translate(0px, -1px) rotate(-10deg);
|
||||
}
|
||||
10% {
|
||||
transform: translate(1px, -3px) rotate(0deg);
|
||||
}
|
||||
15% {
|
||||
transform: translate(1px, 1px) rotate(11deg);
|
||||
}
|
||||
20% {
|
||||
transform: translate(-2px, 1px) rotate(1deg);
|
||||
}
|
||||
25% {
|
||||
transform: translate(-1px, -2px) rotate(-2deg);
|
||||
}
|
||||
30% {
|
||||
transform: translate(-1px, 2px) rotate(-3deg);
|
||||
}
|
||||
35% {
|
||||
transform: translate(2px, 1px) rotate(6deg);
|
||||
}
|
||||
40% {
|
||||
transform: translate(-2px, -3px) rotate(-9deg);
|
||||
}
|
||||
45% {
|
||||
transform: translate(0px, -1px) rotate(-12deg);
|
||||
}
|
||||
50% {
|
||||
transform: translate(1px, 2px) rotate(10deg);
|
||||
}
|
||||
55% {
|
||||
transform: translate(0px, -3px) rotate(8deg);
|
||||
}
|
||||
60% {
|
||||
transform: translate(1px, -1px) rotate(8deg);
|
||||
}
|
||||
65% {
|
||||
transform: translate(0px, -1px) rotate(-7deg);
|
||||
}
|
||||
70% {
|
||||
transform: translate(-1px, -3px) rotate(6deg);
|
||||
}
|
||||
75% {
|
||||
transform: translate(0px, -2px) rotate(4deg);
|
||||
}
|
||||
80% {
|
||||
transform: translate(-2px, -1px) rotate(3deg);
|
||||
}
|
||||
85% {
|
||||
transform: translate(1px, -3px) rotate(-10deg);
|
||||
}
|
||||
90% {
|
||||
transform: translate(1px, 0px) rotate(3deg);
|
||||
}
|
||||
95% {
|
||||
transform: translate(-2px, 0px) rotate(-3deg);
|
||||
}
|
||||
100% {
|
||||
transform: translate(2px, 1px) rotate(2deg);
|
||||
}
|
||||
}
|
||||
5% {
|
||||
transform: translate(0px, -1px) rotate(-10deg);
|
||||
}
|
||||
10% {
|
||||
transform: translate(1px, -3px) rotate(0deg);
|
||||
}
|
||||
15% {
|
||||
transform: translate(1px, 1px) rotate(11deg);
|
||||
}
|
||||
20% {
|
||||
transform: translate(-2px, 1px) rotate(1deg);
|
||||
}
|
||||
25% {
|
||||
transform: translate(-1px, -2px) rotate(-2deg);
|
||||
}
|
||||
30% {
|
||||
transform: translate(-1px, 2px) rotate(-3deg);
|
||||
}
|
||||
35% {
|
||||
transform: translate(2px, 1px) rotate(6deg);
|
||||
}
|
||||
40% {
|
||||
transform: translate(-2px, -3px) rotate(-9deg);
|
||||
}
|
||||
45% {
|
||||
transform: translate(0px, -1px) rotate(-12deg);
|
||||
}
|
||||
50% {
|
||||
transform: translate(1px, 2px) rotate(10deg);
|
||||
}
|
||||
55% {
|
||||
transform: translate(0px, -3px) rotate(8deg);
|
||||
}
|
||||
60% {
|
||||
transform: translate(1px, -1px) rotate(8deg);
|
||||
}
|
||||
65% {
|
||||
transform: translate(0px, -1px) rotate(-7deg);
|
||||
}
|
||||
70% {
|
||||
transform: translate(-1px, -3px) rotate(6deg);
|
||||
}
|
||||
75% {
|
||||
transform: translate(0px, -2px) rotate(4deg);
|
||||
}
|
||||
80% {
|
||||
transform: translate(-2px, -1px) rotate(3deg);
|
||||
}
|
||||
85% {
|
||||
transform: translate(1px, -3px) rotate(-10deg);
|
||||
}
|
||||
90% {
|
||||
transform: translate(1px, 0px) rotate(3deg);
|
||||
}
|
||||
95% {
|
||||
transform: translate(-2px, 0px) rotate(-3deg);
|
||||
}
|
||||
100% {
|
||||
transform: translate(2px, 1px) rotate(2deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mfm-rubberBand {
|
||||
from {
|
||||
transform: scale3d(1, 1, 1);
|
||||
@keyframes mfm-rubberBand {
|
||||
from {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
30% {
|
||||
transform: scale3d(1.25, 0.75, 1);
|
||||
}
|
||||
40% {
|
||||
transform: scale3d(0.75, 1.25, 1);
|
||||
}
|
||||
50% {
|
||||
transform: scale3d(1.15, 0.85, 1);
|
||||
}
|
||||
65% {
|
||||
transform: scale3d(0.95, 1.05, 1);
|
||||
}
|
||||
75% {
|
||||
transform: scale3d(1.05, 0.95, 1);
|
||||
}
|
||||
to {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
30% {
|
||||
transform: scale3d(1.25, 0.75, 1);
|
||||
}
|
||||
40% {
|
||||
transform: scale3d(0.75, 1.25, 1);
|
||||
}
|
||||
50% {
|
||||
transform: scale3d(1.15, 0.85, 1);
|
||||
}
|
||||
65% {
|
||||
transform: scale3d(0.95, 1.05, 1);
|
||||
}
|
||||
75% {
|
||||
transform: scale3d(1.05, 0.95, 1);
|
||||
}
|
||||
to {
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mfm-rainbow {
|
||||
0% {
|
||||
filter: hue-rotate(0deg) contrast(150%) saturate(150%);
|
||||
@keyframes mfm-rainbow {
|
||||
0% {
|
||||
filter: hue-rotate(0deg) contrast(150%) saturate(150%);
|
||||
}
|
||||
100% {
|
||||
filter: hue-rotate(360deg) contrast(150%) saturate(150%);
|
||||
}
|
||||
}
|
||||
100% {
|
||||
filter: hue-rotate(360deg) contrast(150%) saturate(150%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes mfm-fade {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
@keyframes mfm-fade {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.havbbuyv {
|
||||
.mfm-object {
|
||||
white-space: pre-wrap;
|
||||
|
||||
&.nowrap {
|
||||
|
|
|
@ -36,9 +36,7 @@
|
|||
v-if="metadata.avatar"
|
||||
class="avatar"
|
||||
:user="metadata.avatar"
|
||||
:disable-preview="true"
|
||||
:show-indicator="true"
|
||||
disableLink
|
||||
/>
|
||||
<i
|
||||
v-else-if="metadata.icon && !narrow"
|
||||
|
@ -374,6 +372,7 @@ onUnmounted(() => {
|
|||
display: flex;
|
||||
> .buttons {
|
||||
&:not(:empty) {
|
||||
margin-right: 8px;
|
||||
margin-left: calc(0px - var(--margin));
|
||||
}
|
||||
> .avatar {
|
||||
|
@ -426,8 +425,7 @@ onUnmounted(() => {
|
|||
width: $size;
|
||||
height: $size;
|
||||
vertical-align: bottom;
|
||||
margin: 0 8px;
|
||||
pointer-events: none;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
> .icon {
|
||||
|
|
|
@ -57,6 +57,12 @@ export default defineComponent({
|
|||
if (t == null) return null;
|
||||
return t.match(/^[0-9.]+s$/) ? t : null;
|
||||
};
|
||||
// const validEase = (e: string | null | undefined) => {
|
||||
// if (e == null) return null;
|
||||
// return e.match(/(steps)?\(-?[0-9.]+,-?[0-9.]+,-?[0-9.]+,-?[0-9.]+\)/)
|
||||
// ? (e.startsWith("steps") ? e : "cubic-bezier" + e)
|
||||
// : null
|
||||
// }
|
||||
|
||||
const genEl = (ast: mfm.MfmNode[]) =>
|
||||
concat(
|
||||
|
@ -102,22 +108,27 @@ export default defineComponent({
|
|||
switch (token.props.name) {
|
||||
case "tada": {
|
||||
const speed = validTime(token.props.args.speed) || "1s";
|
||||
style = `font-size: 150%; animation: tada ${speed} linear infinite both;`;
|
||||
const delay = validTime(token.props.args.delay) || "0s";
|
||||
// const ease = validEase(token.props.args.ease) || "linear";
|
||||
style = `font-size: 150%; animation: tada ${speed} ${delay} linear infinite both;`;
|
||||
break;
|
||||
}
|
||||
case "jelly": {
|
||||
const speed = validTime(token.props.args.speed) || "1s";
|
||||
style = `animation: mfm-rubberBand ${speed} linear infinite both;`;
|
||||
const delay = validTime(token.props.args.delay) || "0s";
|
||||
style = `animation: mfm-rubberBand ${speed} ${delay} linear infinite both;`;
|
||||
break;
|
||||
}
|
||||
case "twitch": {
|
||||
const speed = validTime(token.props.args.speed) || "0.5s";
|
||||
style = `animation: mfm-twitch ${speed} ease infinite;`;
|
||||
const delay = validTime(token.props.args.delay) || "0s";
|
||||
style = `animation: mfm-twitch ${speed} ${delay} ease infinite;`;
|
||||
break;
|
||||
}
|
||||
case "shake": {
|
||||
const speed = validTime(token.props.args.speed) || "0.5s";
|
||||
style = `animation: mfm-shake ${speed} ease infinite;`;
|
||||
const delay = validTime(token.props.args.delay) || "0s";
|
||||
style = `animation: mfm-shake ${speed} ${delay} ease infinite;`;
|
||||
break;
|
||||
}
|
||||
case "spin": {
|
||||
|
@ -132,22 +143,26 @@ export default defineComponent({
|
|||
? "mfm-spinY"
|
||||
: "mfm-spin";
|
||||
const speed = validTime(token.props.args.speed) || "1.5s";
|
||||
style = `animation: ${anime} ${speed} linear infinite; animation-direction: ${direction};`;
|
||||
const delay = validTime(token.props.args.delay) || "0s";
|
||||
style = `animation: ${anime} ${speed} ${delay} linear infinite; animation-direction: ${direction};`;
|
||||
break;
|
||||
}
|
||||
case "jump": {
|
||||
const speed = validTime(token.props.args.speed) || "0.75s";
|
||||
style = `animation: mfm-jump ${speed} linear infinite;`;
|
||||
const delay = validTime(token.props.args.delay) || "0s";
|
||||
style = `animation: mfm-jump ${speed} ${delay} linear infinite;`;
|
||||
break;
|
||||
}
|
||||
case "bounce": {
|
||||
const speed = validTime(token.props.args.speed) || "0.75s";
|
||||
style = `animation: mfm-bounce ${speed} linear infinite; transform-origin: center bottom;`;
|
||||
const delay = validTime(token.props.args.delay) || "0s";
|
||||
style = `animation: mfm-bounce ${speed} ${delay} linear infinite; transform-origin: center bottom;`;
|
||||
break;
|
||||
}
|
||||
case "rainbow": {
|
||||
const speed = validTime(token.props.args.speed) || "1s";
|
||||
style = `animation: mfm-rainbow ${speed} linear infinite;`;
|
||||
const delay = validTime(token.props.args.delay) || "0s";
|
||||
style = `animation: mfm-rainbow ${speed} ${delay} linear infinite;`;
|
||||
break;
|
||||
}
|
||||
case "sparkle": {
|
||||
|
@ -161,7 +176,8 @@ export default defineComponent({
|
|||
? "alternate-reverse"
|
||||
: "alternate";
|
||||
const speed = validTime(token.props.args.speed) || "1.5s";
|
||||
style = `animation: mfm-fade ${speed} linear infinite; animation-direction: ${direction};`;
|
||||
const delay = validTime(token.props.args.delay) || "0s";
|
||||
style = `animation: mfm-fade ${speed} ${delay} linear infinite; animation-direction: ${direction};`;
|
||||
break;
|
||||
}
|
||||
case "flip": {
|
||||
|
|
|
@ -5,7 +5,6 @@ import type * as Misskey from "calckey-js";
|
|||
// TODO: 他のタブと永続化されたstateを同期
|
||||
|
||||
const instanceData = localStorage.getItem("instance");
|
||||
|
||||
// TODO: instanceをリアクティブにするかは再考の余地あり
|
||||
|
||||
export const instance: Misskey.entities.DetailedInstanceMetadata = reactive(
|
||||
|
|
|
@ -91,7 +91,7 @@ export const navbarItemDef = reactive({
|
|||
to: "/gallery",
|
||||
},
|
||||
clips: {
|
||||
title: "clip",
|
||||
title: "clips",
|
||||
icon: "ph-paperclip ph-bold ph-lg",
|
||||
show: computed(() => $i != null),
|
||||
to: "/my/clips",
|
||||
|
|
|
@ -17,16 +17,25 @@
|
|||
{{ file.name }}
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="_button" @click="chooseFile">
|
||||
<button
|
||||
class="_button"
|
||||
@click="chooseFile"
|
||||
:aria-label="i18n.t('attachFile')"
|
||||
>
|
||||
<i class="ph-upload ph-bold ph-lg"></i>
|
||||
</button>
|
||||
<button class="_button" @click="insertEmoji">
|
||||
<button
|
||||
class="_button"
|
||||
@click="insertEmoji"
|
||||
:aria-label="i18n.t('chooseEmoji')"
|
||||
>
|
||||
<i class="ph-smiley ph-bold ph-lg"></i>
|
||||
</button>
|
||||
<button
|
||||
class="send _button"
|
||||
:disabled="!canSend || sending"
|
||||
:title="i18n.ts.send"
|
||||
:aria-label="i18n.ts.send"
|
||||
@click="send"
|
||||
>
|
||||
<template v-if="!sending"
|
||||
|
|
|
@ -14,7 +14,10 @@
|
|||
:title="i18n.ts.delete"
|
||||
@click="del"
|
||||
>
|
||||
<img src="/client-assets/remove.png" alt="Delete" />
|
||||
<i
|
||||
style="color: var(--accentLighten)"
|
||||
class="ph-x-circle ph-fill ph-lg"
|
||||
></i>
|
||||
</button>
|
||||
<div v-if="!message.isDeleted" class="content">
|
||||
<Mfm
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#default="{ items: messages, fetching: pFetching }"
|
||||
>
|
||||
<XList
|
||||
aria-live="polite"
|
||||
v-if="messages.length > 0"
|
||||
v-slot="{ item: message }"
|
||||
:class="{
|
||||
|
@ -48,7 +49,11 @@
|
|||
</MkPagination>
|
||||
</div>
|
||||
<footer>
|
||||
<div v-if="typers.length > 0" class="typers">
|
||||
<div
|
||||
v-if="typers.length > 0"
|
||||
class="typers"
|
||||
aria-live="polite"
|
||||
>
|
||||
<I18n
|
||||
:src="i18n.ts.typingUsers"
|
||||
text-tag="span"
|
||||
|
|
|
@ -54,12 +54,6 @@
|
|||
<FormSwitch v-model="disablePagesScript" class="_formBlock">{{
|
||||
i18n.ts.disablePagesScript
|
||||
}}</FormSwitch>
|
||||
<FormSwitch v-model="expandOnNoteClick" class="_formBlock"
|
||||
>{{ i18n.ts.expandOnNoteClick
|
||||
}}<template #caption>{{
|
||||
i18n.ts.expandOnNoteClickDesc
|
||||
}}</template>
|
||||
</FormSwitch>
|
||||
<FormSwitch v-model="profile.showTimelineReplies" class="_formBlock"
|
||||
>{{ i18n.ts.flagShowTimelineReplies
|
||||
}}<template #caption
|
||||
|
@ -87,6 +81,18 @@
|
|||
|
||||
<FormSection>
|
||||
<template #label>{{ i18n.ts.accessibility }}</template>
|
||||
<FormSwitch v-model="expandOnNoteClick" class="_formBlock"
|
||||
>{{ i18n.ts.expandOnNoteClick
|
||||
}}<template #caption>{{
|
||||
i18n.ts.expandOnNoteClickDesc
|
||||
}}</template>
|
||||
</FormSwitch>
|
||||
<FormSwitch v-model="advancedMfm" class="_formBlock">
|
||||
{{ i18n.ts._mfm.advanced
|
||||
}}<template #caption>{{
|
||||
i18n.ts._mfm.advancedDescription
|
||||
}}</template>
|
||||
</FormSwitch>
|
||||
<FormSwitch v-model="autoplayMfm" class="_formBlock">
|
||||
{{ i18n.ts._mfm.alwaysPlay }}
|
||||
<template #caption>
|
||||
|
@ -285,6 +291,7 @@ const showGapBetweenNotesInTimeline = computed(
|
|||
defaultStore.makeGetterSetter("showGapBetweenNotesInTimeline")
|
||||
);
|
||||
const showAds = computed(defaultStore.makeGetterSetter("showAds"));
|
||||
const advancedMfm = computed(defaultStore.makeGetterSetter("advancedMfm"));
|
||||
const autoplayMfm = computed(
|
||||
defaultStore.makeGetterSetter(
|
||||
"animatedMfm",
|
||||
|
@ -374,6 +381,7 @@ watch(
|
|||
swipeOnDesktop,
|
||||
seperateRenoteQuote,
|
||||
showAdminUpdates,
|
||||
advancedMfm,
|
||||
autoplayMfm,
|
||||
expandOnNoteClick,
|
||||
],
|
||||
|
|
|
@ -152,46 +152,50 @@ function top(): void {
|
|||
scroll(rootEl, { top: 0 });
|
||||
}
|
||||
|
||||
async function chooseList(ev: MouseEvent): Promise<void> {
|
||||
const lists = await os.api("users/lists/list");
|
||||
const items = [
|
||||
{
|
||||
type: "link" as const,
|
||||
text: i18n.ts.manageLists,
|
||||
icon: "ph-faders-horizontal ph-bold ph-lg",
|
||||
to: "/my/lists",
|
||||
},
|
||||
].concat(
|
||||
lists.map((list) => ({
|
||||
type: "link" as const,
|
||||
text: list.name,
|
||||
icon: "",
|
||||
to: `/timeline/list/${list.id}`,
|
||||
}))
|
||||
);
|
||||
os.popupMenu(items, ev.currentTarget ?? ev.target);
|
||||
const lists = os.api("users/lists/list");
|
||||
async function chooseList(ev: MouseEvent) {
|
||||
await lists.then((res) => {
|
||||
const items = [
|
||||
{
|
||||
type: "link" as const,
|
||||
text: i18n.ts.manageLists,
|
||||
icon: "ph-faders-horizontal ph-bold ph-lg",
|
||||
to: "/my/lists",
|
||||
},
|
||||
].concat(
|
||||
res.map((list) => ({
|
||||
type: "link" as const,
|
||||
text: list.name,
|
||||
icon: "",
|
||||
to: `/timeline/list/${list.id}`,
|
||||
}))
|
||||
);
|
||||
os.popupMenu(items, ev.currentTarget ?? ev.target);
|
||||
});
|
||||
}
|
||||
|
||||
async function chooseAntenna(ev: MouseEvent): Promise<void> {
|
||||
const antennas = await os.api("antennas/list");
|
||||
const items = [
|
||||
{
|
||||
type: "link" as const,
|
||||
indicate: false,
|
||||
text: i18n.ts.manageAntennas,
|
||||
icon: "ph-faders-horizontal ph-bold ph-lg",
|
||||
to: "/my/antennas",
|
||||
},
|
||||
].concat(
|
||||
antennas.map((antenna) => ({
|
||||
type: "link" as const,
|
||||
text: antenna.name,
|
||||
icon: "",
|
||||
indicate: antenna.hasUnreadNote,
|
||||
to: `/timeline/antenna/${antenna.id}`,
|
||||
}))
|
||||
);
|
||||
os.popupMenu(items, ev.currentTarget ?? ev.target);
|
||||
const antennas = os.api("antennas/list");
|
||||
async function chooseAntenna(ev: MouseEvent) {
|
||||
await antennas.then((res) => {
|
||||
const items = [
|
||||
{
|
||||
type: "link" as const,
|
||||
indicate: false,
|
||||
text: i18n.ts.manageAntennas,
|
||||
icon: "ph-faders-horizontal ph-bold ph-lg",
|
||||
to: "/my/antennas",
|
||||
},
|
||||
].concat(
|
||||
res.map((antenna) => ({
|
||||
type: "link" as const,
|
||||
text: antenna.name,
|
||||
icon: "",
|
||||
indicate: antenna.hasUnreadNote,
|
||||
to: `/timeline/antenna/${antenna.id}`,
|
||||
}))
|
||||
);
|
||||
os.popupMenu(items, ev.currentTarget ?? ev.target);
|
||||
});
|
||||
}
|
||||
|
||||
function saveSrc(
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
/></span>
|
||||
<span
|
||||
v-if="user.isAdmin"
|
||||
:title="i18n.ts.isAdmin"
|
||||
v-tooltip.noDelay="i18n.ts.isAdmin"
|
||||
style="color: var(--badge)"
|
||||
><i
|
||||
class="ph-bookmark-simple ph-fill ph-lg"
|
||||
|
@ -62,22 +62,36 @@
|
|||
></span>
|
||||
<span
|
||||
v-if="!user.isAdmin && user.isModerator"
|
||||
:title="i18n.ts.isModerator"
|
||||
v-tooltip.noDelay="i18n.ts.isModerator"
|
||||
style="color: var(--badge)"
|
||||
><i
|
||||
class="ph-bookmark-simple ph-bold"
|
||||
class="ph-bookmark-simple ph-bold ph-lg"
|
||||
></i
|
||||
></span>
|
||||
<span
|
||||
v-if="user.isLocked"
|
||||
:title="i18n.ts.isLocked"
|
||||
v-tooltip.noDelay="i18n.ts.isLocked"
|
||||
><i class="ph-lock ph-bold ph-lg"></i
|
||||
></span>
|
||||
<span
|
||||
v-if="user.isBot"
|
||||
:title="i18n.ts.isBot"
|
||||
v-tooltip.noDelay="i18n.ts.isBot"
|
||||
><i class="ph-robot ph-bold ph-lg"></i
|
||||
></span>
|
||||
<span
|
||||
v-if="
|
||||
patrons?.includes(
|
||||
`@${user.username}@${
|
||||
user.host || host
|
||||
}`
|
||||
)
|
||||
"
|
||||
v-tooltip.noDelay="i18n.ts.isPatron"
|
||||
style="color: var(--badge)"
|
||||
><i
|
||||
class="ph-hand-coins ph-bold ph-lg"
|
||||
></i
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -110,7 +124,7 @@
|
|||
/></span>
|
||||
<span
|
||||
v-if="user.isAdmin"
|
||||
:title="i18n.ts.isAdmin"
|
||||
v-tooltip.noDelay="i18n.ts.isAdmin"
|
||||
style="color: var(--badge)"
|
||||
><i
|
||||
class="ph-bookmark-simple ph-fill ph-lg"
|
||||
|
@ -118,18 +132,32 @@
|
|||
></span>
|
||||
<span
|
||||
v-if="!user.isAdmin && user.isModerator"
|
||||
:title="i18n.ts.isModerator"
|
||||
v-tooltip.noDelay="i18n.ts.isModerator"
|
||||
style="color: var(--badge)"
|
||||
><i class="ph-bookmark-simple ph-bold"></i
|
||||
></span>
|
||||
<span
|
||||
v-if="user.isLocked"
|
||||
:title="i18n.ts.isLocked"
|
||||
v-tooltip.noDelay="i18n.ts.isLocked"
|
||||
><i class="ph-lock ph-bold ph-lg"></i
|
||||
></span>
|
||||
<span v-if="user.isBot" :title="i18n.ts.isBot"
|
||||
<span
|
||||
v-if="user.isBot"
|
||||
v-tooltip.noDelay="i18n.ts.isBot"
|
||||
><i class="ph-robot ph-bold ph-lg"></i
|
||||
></span>
|
||||
<span
|
||||
v-if="
|
||||
patrons?.includes(
|
||||
`@${user.username}@${
|
||||
user.host || host
|
||||
}`
|
||||
)
|
||||
"
|
||||
v-tooltip.noDelay="i18n.ts.isPatron"
|
||||
style="color: var(--badge)"
|
||||
><i class="ph-hand-coins ph-bold ph-lg"></i
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="follow-container">
|
||||
|
@ -324,6 +352,7 @@ import * as os from "@/os";
|
|||
import { useRouter } from "@/router";
|
||||
import { i18n } from "@/i18n";
|
||||
import { $i } from "@/account";
|
||||
import { host } from "@/config";
|
||||
|
||||
const XPhotos = defineAsyncComponent(() => import("./index.photos.vue"));
|
||||
const XActivity = defineAsyncComponent(() => import("./index.activity.vue"));
|
||||
|
@ -392,6 +421,8 @@ const timeForThem = $computed(() => {
|
|||
return "";
|
||||
});
|
||||
|
||||
const patrons = await os.api("patrons");
|
||||
|
||||
function menu(ev) {
|
||||
os.popupMenu(
|
||||
getUserMenu(props.user, router),
|
||||
|
|
|
@ -262,13 +262,6 @@ export function getNoteMenu(props: {
|
|||
null,
|
||||
]
|
||||
: []),
|
||||
instance.features.postEditing && isAppearAuthor
|
||||
? {
|
||||
icon: "ph-pencil-line ph-bold ph-lg",
|
||||
text: i18n.ts.edit,
|
||||
action: edit,
|
||||
}
|
||||
: undefined,
|
||||
{
|
||||
icon: "ph-clipboard-text ph-bold ph-lg",
|
||||
text: i18n.ts.copyContent,
|
||||
|
@ -372,33 +365,45 @@ export function getNoteMenu(props: {
|
|||
}]
|
||||
: []
|
||||
),*/
|
||||
...(!isAppearAuthor
|
||||
? [
|
||||
null,
|
||||
{
|
||||
icon: "ph-warning-circle ph-bold ph-lg",
|
||||
text: i18n.ts.reportAbuse,
|
||||
action: () => {
|
||||
const u =
|
||||
appearNote.url ||
|
||||
appearNote.uri ||
|
||||
`${url}/notes/${appearNote.id}`;
|
||||
os.popup(
|
||||
defineAsyncComponent(
|
||||
() => import("@/components/MkAbuseReportWindow.vue"),
|
||||
),
|
||||
{
|
||||
user: appearNote.user,
|
||||
initialComment: `Note: ${u}\n-----\n`,
|
||||
},
|
||||
{},
|
||||
"closed",
|
||||
);
|
||||
},
|
||||
null,
|
||||
!isAppearAuthor
|
||||
? {
|
||||
icon: "ph-warning-circle ph-bold ph-lg",
|
||||
text: i18n.ts.reportAbuse,
|
||||
action: () => {
|
||||
const u =
|
||||
appearNote.url ||
|
||||
appearNote.uri ||
|
||||
`${url}/notes/${appearNote.id}`;
|
||||
os.popup(
|
||||
defineAsyncComponent(
|
||||
() => import("@/components/MkAbuseReportWindow.vue"),
|
||||
),
|
||||
{
|
||||
user: appearNote.user,
|
||||
initialComment: `Note: ${u}\n-----\n`,
|
||||
},
|
||||
{},
|
||||
"closed",
|
||||
);
|
||||
},
|
||||
]
|
||||
: []),
|
||||
|
||||
}
|
||||
: undefined,
|
||||
instance.features.postEditing && isAppearAuthor
|
||||
? {
|
||||
icon: "ph-pencil-line ph-bold ph-lg",
|
||||
text: i18n.ts.edit,
|
||||
accent: true,
|
||||
action: edit,
|
||||
}
|
||||
: undefined,
|
||||
isAppearAuthor
|
||||
? {
|
||||
icon: "ph-eraser ph-bold ph-lg",
|
||||
text: i18n.ts.deleteAndEdit,
|
||||
action: delEdit,
|
||||
}
|
||||
: undefined,
|
||||
isAppearAuthor || isModerator
|
||||
? {
|
||||
icon: "ph-trash ph-bold ph-lg",
|
||||
|
@ -407,14 +412,6 @@ export function getNoteMenu(props: {
|
|||
action: del,
|
||||
}
|
||||
: undefined,
|
||||
|
||||
isAppearAuthor
|
||||
? {
|
||||
icon: "ph-eraser ph-bold ph-lg",
|
||||
text: i18n.ts.deleteAndEdit,
|
||||
action: delEdit,
|
||||
}
|
||||
: undefined,
|
||||
].filter((x) => x !== undefined);
|
||||
} else {
|
||||
menu = [
|
||||
|
|
|
@ -14,7 +14,7 @@ function parseSingleKaTeXMacro(src: string): [string, KaTeXMacro] {
|
|||
if (!src.startsWith("\\newcommand") || src.slice(-1) !== "}") return invalid;
|
||||
|
||||
// current index we are checking (= "\\newcommand".length)
|
||||
let currentPos: number = 11;
|
||||
let currentPos = 11;
|
||||
currentPos = skipSpaces(currentPos);
|
||||
|
||||
// parse {\name}, (\name), or [\name]
|
||||
|
@ -61,8 +61,8 @@ function parseSingleKaTeXMacro(src: string): [string, KaTeXMacro] {
|
|||
currentPos = skipSpaces(currentPos);
|
||||
|
||||
while (currentPos < src.length - 1) {
|
||||
let numbersignPos: number = -1;
|
||||
let isEscaped: boolean = false;
|
||||
let numbersignPos = -1;
|
||||
let isEscaped = false;
|
||||
|
||||
for (let i = currentPos; i < src.length - 1; ++i) {
|
||||
if (src[i] !== "\\" && src[i] !== "#") {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import * as os from "@/os";
|
||||
import { i18n } from "@/i18n";
|
||||
import { mainRouter } from "@/router";
|
||||
// import { instance } from "@/instance";
|
||||
|
||||
export async function search() {
|
||||
// const searchOptions =
|
||||
|
@ -14,6 +15,8 @@ export async function search() {
|
|||
// "filter:following => show results only from users you follow\n" +
|
||||
// "filter:followers => show results only from followers\n";
|
||||
|
||||
// const searchFiltersAvailable = instance.searchFilters;
|
||||
|
||||
const { canceled, result: query } = await os.inputText({
|
||||
title: i18n.ts.search,
|
||||
placeholder: i18n.ts.searchPlaceholder,
|
||||
|
|
|
@ -7,7 +7,7 @@ export class StickySidebar {
|
|||
private isTop = false;
|
||||
private isBottom = false;
|
||||
private offsetTop: number;
|
||||
private globalHeaderHeight: number = 59;
|
||||
private globalHeaderHeight = 59;
|
||||
|
||||
constructor(
|
||||
container: StickySidebar["container"],
|
||||
|
|
|
@ -174,6 +174,10 @@ export const defaultStore = markRaw(
|
|||
where: "device",
|
||||
default: true,
|
||||
},
|
||||
advancedMfm: {
|
||||
where: "device",
|
||||
default: true,
|
||||
},
|
||||
animatedMfm: {
|
||||
where: "device",
|
||||
default: true,
|
||||
|
|
|
@ -73,7 +73,6 @@ html {
|
|||
body::-webkit-scrollbar {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
|
||||
}
|
||||
body::-webkit-scrollbar-thumb {
|
||||
border-radius: 100px;
|
||||
|
|
|
@ -51,6 +51,7 @@ export type MenuButton = {
|
|||
icon?: string;
|
||||
indicate?: boolean;
|
||||
danger?: boolean;
|
||||
accent?: boolean;
|
||||
active?: boolean;
|
||||
hidden?: boolean;
|
||||
avatar?: Misskey.entities.User;
|
||||
|
|
|
@ -92,7 +92,12 @@
|
|||
><i class="icon ph-door ph-bold ph-fw ph-lg"></i
|
||||
><span class="text">{{ i18n.ts.controlPanel }}</span>
|
||||
</MkA>
|
||||
<button v-click-anime class="item _button" @click="more">
|
||||
<button
|
||||
v-click-anime
|
||||
v-tooltip.noDelay.right="i18n.ts.more"
|
||||
class="item _button"
|
||||
@click="more"
|
||||
>
|
||||
<i
|
||||
class="icon ph-dots-three-outline ph-bold ph-fw ph-lg"
|
||||
></i
|
||||
|
@ -172,7 +177,7 @@ const calcViewState = () => {
|
|||
|
||||
calcViewState();
|
||||
|
||||
window.addEventListener("resize", calcViewState);
|
||||
matchMedia("(max-width: 1279px)").onchange = (mql) => calcViewState();
|
||||
|
||||
watch(defaultStore.reactiveState.menuDisplay, () => {
|
||||
calcViewState();
|
||||
|
@ -391,7 +396,8 @@ function more(ev: MouseEvent) {
|
|||
|
||||
> .item {
|
||||
position: relative;
|
||||
display: block;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 30px;
|
||||
line-height: 2.85rem;
|
||||
margin-bottom: 0.5rem;
|
||||
|
|
|
@ -245,6 +245,7 @@ const addColumn = async (ev) => {
|
|||
"tl",
|
||||
"antenna",
|
||||
"list",
|
||||
"channel",
|
||||
"mentions",
|
||||
"direct",
|
||||
];
|
||||
|
|
73
packages/client/src/ui/deck/channel-column.vue
Normal file
|
@ -0,0 +1,73 @@
|
|||
<template>
|
||||
<XColumn
|
||||
:menu="menu"
|
||||
:column="column"
|
||||
:is-stacked="isStacked"
|
||||
@parent-focus="($event) => emit('parent-focus', $event)"
|
||||
>
|
||||
<template #header>
|
||||
<i class="ph-television ph-bold ph-lg"></i
|
||||
><span style="margin-left: 8px">{{ column.name }}</span>
|
||||
</template>
|
||||
|
||||
<XTimeline
|
||||
v-if="column.channelId"
|
||||
ref="timeline"
|
||||
src="channel"
|
||||
:channel="column.channelId"
|
||||
@after="() => emit('loaded')"
|
||||
/>
|
||||
</XColumn>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {} from "vue";
|
||||
import XColumn from "./column.vue";
|
||||
import { updateColumn, Column } from "./deck-store";
|
||||
import XTimeline from "@/components/MkTimeline.vue";
|
||||
import * as os from "@/os";
|
||||
import { i18n } from "@/i18n";
|
||||
|
||||
const props = defineProps<{
|
||||
column: Column;
|
||||
isStacked: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: "loaded"): void;
|
||||
(ev: "parent-focus", direction: "up" | "down" | "left" | "right"): void;
|
||||
}>();
|
||||
|
||||
let timeline = $ref<InstanceType<typeof XTimeline>>();
|
||||
|
||||
if (props.column.channelId == null) {
|
||||
setChannel();
|
||||
}
|
||||
|
||||
async function setChannel() {
|
||||
const channels = await os.api("channels/followed");
|
||||
const { canceled, result: channel } = await os.select({
|
||||
title: i18n.ts.selectChannel,
|
||||
items: channels.map((x) => ({
|
||||
value: x,
|
||||
text: x.name,
|
||||
})),
|
||||
default: props.column.channelId,
|
||||
});
|
||||
if (canceled) return;
|
||||
updateColumn(props.column.id, {
|
||||
name: channel.name,
|
||||
channelId: channel.id,
|
||||
});
|
||||
}
|
||||
|
||||
const menu = [
|
||||
{
|
||||
icon: "ph-pencil ph-bold ph-lg",
|
||||
text: i18n.ts.selectChannel,
|
||||
action: setChannel,
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<style lang="scss" module></style>
|
|
@ -49,6 +49,12 @@
|
|||
:is-stacked="isStacked"
|
||||
@parent-focus="emit('parent-focus', $event)"
|
||||
/>
|
||||
<XChannelColumn
|
||||
v-else-if="column.type === 'channel'"
|
||||
:column="column"
|
||||
:is-stacked="isStacked"
|
||||
@parent-focus="emit('parent-focus', $event)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -61,6 +67,7 @@ import XNotificationsColumn from "./notifications-column.vue";
|
|||
import XWidgetsColumn from "./widgets-column.vue";
|
||||
import XMentionsColumn from "./mentions-column.vue";
|
||||
import XDirectColumn from "./direct-column.vue";
|
||||
import XChannelColumn from "./channel-column.vue";
|
||||
import { Column } from "./deck-store";
|
||||
|
||||
defineProps<{
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
</main>
|
||||
</MkStickyContainer>
|
||||
|
||||
<div v-if="isDesktop" ref="widgetsEl" class="widgets">
|
||||
<XWidgets @mounted="attachSticky" />
|
||||
<div v-if="isDesktop" ref="widgetsEl" class="widgets-container">
|
||||
<XWidgets />
|
||||
</div>
|
||||
|
||||
<button
|
||||
|
@ -380,17 +380,6 @@ const onContextmenu = (ev: MouseEvent) => {
|
|||
);
|
||||
};
|
||||
|
||||
const attachSticky = (el: any) => {
|
||||
const sticky = new StickySidebar(widgetsEl);
|
||||
window.addEventListener(
|
||||
"scroll",
|
||||
() => {
|
||||
sticky.calc(window.scrollY);
|
||||
},
|
||||
{ passive: true }
|
||||
);
|
||||
};
|
||||
|
||||
function top() {
|
||||
window.scroll({ top: 0, behavior: "smooth" });
|
||||
}
|
||||
|
@ -451,7 +440,7 @@ console.log(mainRouter.currentRoute.value.name);
|
|||
$widgets-hide-threshold: 1090px;
|
||||
|
||||
// ほんとは単に 100vh と書きたいところだが... https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
|
||||
min-height: calc(var(--vh, 1vh) * 100);
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
|
||||
|
@ -560,10 +549,15 @@ console.log(mainRouter.currentRoute.value.name);
|
|||
}
|
||||
}
|
||||
|
||||
> .widgets {
|
||||
padding: 0 var(--margin);
|
||||
width: 300px;
|
||||
> .widgets-container {
|
||||
margin-right: calc(var(--margin) / 2);
|
||||
width: calc(300px + (var(--margin) * 1.5));
|
||||
flex: 0 0 auto;
|
||||
box-sizing: content-box;
|
||||
> :deep(.widgets) {
|
||||
padding-left: var(--margin);
|
||||
padding-right: calc(var(--margin) / 2);
|
||||
}
|
||||
|
||||
@media (max-width: $widgets-hide-threshold) {
|
||||
display: none;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<aside class="efzpzdvf" :aria-label="i18n.ts._deck._columns.widgets">
|
||||
<aside class="widgets" :aria-label="i18n.ts._deck._columns.widgets">
|
||||
<MkAd class="a" :prefer="['widget']" />
|
||||
<XWidgets
|
||||
:edit="editMode"
|
||||
|
@ -83,20 +83,24 @@ function updateWidgets(widgets) {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.efzpzdvf {
|
||||
.widgets {
|
||||
position: sticky;
|
||||
top: var(--stickyTop, 0px);
|
||||
height: min-content;
|
||||
min-height: 100vh;
|
||||
padding: var(--margin) 0;
|
||||
box-sizing: border-box;
|
||||
max-height: 100vh;
|
||||
box-sizing: content-box;
|
||||
overflow: hidden auto;
|
||||
&:not(:hover):not(:focus-within)::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
> * {
|
||||
margin: var(--margin) 0;
|
||||
width: 300px;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
> :first-child {
|
||||
margin-top: calc(var(--margin) * 2);
|
||||
}
|
||||
|
||||
> .add {
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
:meta="meta"
|
||||
/>
|
||||
<XMeili
|
||||
v-else-if="widgetProps.view === 5"
|
||||
v-else-if="instance.searchFilters && widgetProps.view === 5"
|
||||
:connection="connection"
|
||||
:meta="meta"
|
||||
/>
|
||||
|
@ -67,6 +67,7 @@ import { GetFormResultType } from "@/scripts/form";
|
|||
import * as os from "@/os";
|
||||
import { stream } from "@/stream";
|
||||
import { i18n } from "@/i18n";
|
||||
import { instance } from "@/instance";
|
||||
|
||||
const name = "serverMetric";
|
||||
|
||||
|
@ -108,7 +109,10 @@ os.api("server-info", {}).then((res) => {
|
|||
});
|
||||
|
||||
const toggleView = () => {
|
||||
if (widgetProps.view === 5) {
|
||||
if (
|
||||
(widgetProps.view === 5 && instance.searchFilters) ||
|
||||
(widgetProps.view === 4 && !instance.searchFilters)
|
||||
) {
|
||||
widgetProps.view = 0;
|
||||
} else {
|
||||
widgetProps.view++;
|
||||
|
|
|
@ -4,17 +4,17 @@
|
|||
"scripts": {
|
||||
"build": "webpack",
|
||||
"watch": "pnpm swc src -d built -D -w",
|
||||
"lint": "pnpm rome check \"src/**/*.ts\""
|
||||
"lint": "pnpm rome check \"src/**/*.ts\"",
|
||||
"format": "pnpm rome format * --write"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@swc/cli": "^0.1.62",
|
||||
"@swc/core": "^1.3.50",
|
||||
"@swc/core": "^1.3.62",
|
||||
"@swc/core-android-arm64": "1.3.11",
|
||||
"calckey-js": "workspace:*",
|
||||
"idb-keyval": "^6.2.0",
|
||||
"idb-keyval": "^6.2.1",
|
||||
"swc-loader": "^0.2.3",
|
||||
"webpack": "^5.75.0",
|
||||
"webpack-cli": "^5.0.1"
|
||||
"webpack": "^5.85.1",
|
||||
"webpack-cli": "^5.1.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Notification manager for SW
|
||||
*/
|
||||
declare var self: ServiceWorkerGlobalScope;
|
||||
declare let self: ServiceWorkerGlobalScope;
|
||||
|
||||
import { swLang } from "@/scripts/lang";
|
||||
import { cli } from "@/scripts/operations";
|
||||
|
@ -45,7 +45,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(
|
|||
*/
|
||||
case "notification":
|
||||
switch (data.body.type) {
|
||||
case "follow":
|
||||
case "follow": {
|
||||
// users/showの型定義をswos.apiへ当てはめるのが困難なのでapiFetch.requestを直接使用
|
||||
const account = await getAccountFromId(data.userId);
|
||||
if (!account) return null;
|
||||
|
@ -71,6 +71,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(
|
|||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
case "mention":
|
||||
return [
|
||||
|
@ -157,7 +158,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(
|
|||
},
|
||||
];
|
||||
|
||||
case "reaction":
|
||||
case "reaction": {
|
||||
let reaction = data.body.reaction;
|
||||
let badge: string | undefined;
|
||||
|
||||
|
@ -214,6 +215,7 @@ async function composeNotification<K extends keyof pushNotificationDataMap>(
|
|||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
case "pollVote":
|
||||
return [
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Language manager for SW
|
||||
*/
|
||||
declare var self: ServiceWorkerGlobalScope;
|
||||
declare let self: ServiceWorkerGlobalScope;
|
||||
|
||||
import { get, set } from "idb-keyval";
|
||||
import { I18n } from "@/scripts/i18n";
|
||||
|
@ -23,7 +23,7 @@ class SwLang {
|
|||
public i18n: Promise<I18n<any>> | null = null;
|
||||
|
||||
public fetchLocale() {
|
||||
return (this.i18n = this._fetch());
|
||||
return this.i18n === this._fetch();
|
||||
}
|
||||
|
||||
private async _fetch() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
declare var self: ServiceWorkerGlobalScope;
|
||||
declare let self: ServiceWorkerGlobalScope;
|
||||
|
||||
import { get } from "idb-keyval";
|
||||
import { pushNotificationDataMap } from "@/types";
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Operations
|
||||
* 各種操作
|
||||
*/
|
||||
declare var self: ServiceWorkerGlobalScope;
|
||||
declare let self: ServiceWorkerGlobalScope;
|
||||
|
||||
import * as Misskey from "calckey-js";
|
||||
import { SwMessage, swMessageOrderType } from "@/types";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
declare var self: ServiceWorkerGlobalScope;
|
||||
declare let self: ServiceWorkerGlobalScope;
|
||||
|
||||
import {
|
||||
createEmptyNotification,
|
||||
|
|
|
@ -47,6 +47,15 @@
|
|||
"@natalie@prismst.one",
|
||||
"@KelsonV@wandering.shop",
|
||||
"@breakfastmtn@calckey.social",
|
||||
"@richardazia@mastodon.social",
|
||||
"@joestone@calckey.social",
|
||||
"@aj@calckey.social",
|
||||
"@zepfanman@ramblingreaders.org",
|
||||
"@kimby@stop.voring.me",
|
||||
"@fyrfli@bkgrdclrschm.link",
|
||||
"@riversidebryan@calckey.lgbt",
|
||||
"@aRubes@sloth.run",
|
||||
"@andreasdotorg@calckey.social",
|
||||
"\nInterkosmos Link"
|
||||
]
|
||||
}
|
||||
|
|