Removed the frontend and removed unnecesary resource files
ci/woodpecker/tag/ociImageTag Pipeline is pending Details

This commit is contained in:
Natty 2023-07-07 22:33:05 +02:00
parent d47566626a
commit 347568fc8d
Signed by: natty
GPG Key ID: BF6CB659ADEE60EC
682 changed files with 63 additions and 140489 deletions

4
.envrc
View File

@ -1,4 +0,0 @@
if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
fi
use flake . --impure

View File

@ -1,11 +0,0 @@
{
"recommendations": [
"editorconfig.editorconfig",
"eg2.vscode-npm-script",
"rome.rome",
"Vue.volar",
"Vue.vscode-typescript-vue-plugin",
"arcanis.vscode-zipfs",
"Orta.vscode-twoslash-queries"
]
}

View File

@ -1,3 +0,0 @@
[weblate]
url = https://hosted.weblate.org/api/
translation = calckey/locales

View File

@ -56,8 +56,6 @@ COPY . ./
# Copy node modules # Copy node modules
COPY --from=build /calckey/node_modules /calckey/node_modules COPY --from=build /calckey/node_modules /calckey/node_modules
COPY --from=build /calckey/packages/backend/node_modules /calckey/packages/backend/node_modules COPY --from=build /calckey/packages/backend/node_modules /calckey/packages/backend/node_modules
COPY --from=build /calckey/packages/sw/node_modules /calckey/packages/sw/node_modules
COPY --from=build /calckey/packages/client/node_modules /calckey/packages/client/node_modules
COPY --from=build /calckey/packages/calckey-js/node_modules /calckey/packages/calckey-js/node_modules COPY --from=build /calckey/packages/calckey-js/node_modules /calckey/packages/calckey-js/node_modules
# Copy the finished compiled files # Copy the finished compiled files

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

View File

@ -1,7 +0,0 @@
/*
* !!! WARNING !!!
* Editing this file may cause your instance to break for EVERYONE.
* Please know what you're doing and test it out with regular user custom CSS.
* With that said, GLHF!
* This may eventuallly be replaced with a function in the admin panel.
*/

View File

@ -1,95 +0,0 @@
/**
* 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 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: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:locales", (cb) => {
fs.mkdirSync("./built/_client_dist_/locales", { recursive: true });
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",
);
}
cb();
});
gulp.task("build:backend:script", () => {
return gulp
.src([
"./packages/backend/src/server/web/boot.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",
])
.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("default", gulp.task("build"));
gulp.task("watch", () => {
gulp.watch(
["./packages/*/src/**/*"],
{ ignoreInitial: false },
gulp.task("build"),
);
});

View File

@ -1,136 +0,0 @@
name: 🐛 Bug Report
about: File a bug report
title: "[Bug]: "
blank_issues_enabled: true
contact_links:
- name: 💁 Support Matrix
url: https://matrix.to/#/%23calckey:matrix.fedibird.com
about: Having trouble with deployment? Ask the support chat.
- name: 🔒 Resposible Disclosure
url: https://codeberg.org/calckey/calckey/src/branch/develop/SECURITY.md
about: Found a security vulnerability? Please disclose it responsibly.
body:
- type: markdown
attributes:
value: |
💖 Thanks for taking the time to fill out this bug report!
💁 Having trouble with deployment? [Ask the support chat.](https://matrix.to/#/%23calckey:matrix.fedibird.com)
🔒 Found a security vulnerability? [Please disclose it responsibly.](https://codeberg.org/calckey/calckey/src/branch/develop/SECURITY.md)
🤝 By submitting this issue, you agree to follow our [Contribution Guidelines.](https://codeberg.org/calckey/calckey/src/branch/develop/CONTRIBUTING.md)
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Please give us a brief description of what happened.
placeholder: Tell us what you see!
validations:
required: true
- type: textarea
id: what-is-expected
attributes:
label: What did you expect to happen?
description: Please give us a brief description of what you expected to happen.
placeholder: Tell us what you wish happened!
validations:
required: true
- type: input
id: version
attributes:
label: Version
description: What version of calckey is your instance running? You can find this by clicking your instance's logo at the bottom left and then clicking instance information.
placeholder: v13.1.4.1
validations:
required: true
- type: input
id: instance
attributes:
label: Instance
description: What instance of calckey are you using?
placeholder: calckey.social
validations:
required: false
- type: dropdown
id: issue-type
attributes:
label: What type of issue is this?
description: If this happens on your device and has to do with the user interface, it's client-side. If this happens on either with the API or the backend, or you got a server-side error in the client, it's server-side.
multiple: false
options:
- Client-side
- Server-side
- Other (Please Specify)
- type: dropdown
id: browsers
attributes:
label: What browser are you using? (Client-side issues only)
multiple: false
options:
- N/A
- Firefox
- Chrome
- Brave
- Librewolf
- Chromium
- Safari
- Microsoft Edge
- Other (Please Specify)
- type: dropdown
id: device
attributes:
label: What operating system are you using? (Client-side issues only)
multiple: false
options:
- N/A
- Windows
- MacOS
- Linux
- Android
- iOS
- Other (Please Specify)
- type: dropdown
id: deplotment-method
attributes:
label: How do you deploy Calckey on your server? (Server-side issues only)
multiple: false
options:
- N/A
- Manual
- Ubuntu Install Script
- Docker Compose
- Docker Prebuilt Image
- Helm Chart
- YunoHost
- AUR Package
- Other (Please Specify)
- type: dropdown
id: operating-system
attributes:
label: What operating system are you using? (Server-side issues only)
multiple: false
options:
- N/A
- Ubuntu >= 22.04
- Ubuntu < 22.04
- Debian
- Arch
- RHEL (CentOS/AlmaLinux/Rocky Linux)
- FreeBSD
- OpenBSD
- Android
- Other (Please Specify)
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. You can find your log by inspecting the page, and going to the "console" tab. This will be automatically formatted into code, so no need for backticks.
render: shell
- type: checkboxes
id: terms
attributes:
label: Contribution Guidelines
description: By submitting this issue, you agree to follow our [Contribution Guidelines](https://codeberg.org/calckey/calckey/src/branch/develop/CONTRIBUTING.md)
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

View File

@ -1,61 +0,0 @@
name: ✨ Feature Request
about: Request a Feature
title: "[Feature]: "
blank_issues_enabled: true
contact_links:
- name: 💁 Support Matrix
url: https://matrix.to/#/%23calckey:matrix.fedibird.com
about: Having trouble with deployment? Ask the support chat.
- name: 🔒 Resposible Disclosure
url: https://codeberg.org/calckey/calckey/src/branch/develop/SECURITY.md
about: Found a security vulnerability? Please disclose it responsibly.
body:
- type: markdown
attributes:
value: |
💖 Thanks for taking the time to fill out this feature request!
💁 Having trouble with deployment? [Ask the support chat.](https://matrix.to/#/%23calckey:matrix.fedibird.com)
🔒 Found a security vulnerability? [Please disclose it responsibly.](https://codeberg.org/calckey/calckey/src/branch/develop/SECURITY.md)
🤝 By submitting this issue, you agree to follow our [Contribution Guidelines.](https://codeberg.org/calckey/calckey/src/branch/develop/CONTRIBUTING.md)
- type: textarea
id: what-feature
attributes:
label: What feature would you like implemented?
description: Please give us a brief description of what you'd like.
placeholder: Tell us what you want!
validations:
required: true
- type: textarea
id: why-add-feature
attributes:
label: Why should we add this feature?
description: Please give us a brief description of why your feature is important.
placeholder: Tell us why you want this feature!
validations:
required: true
- type: input
id: version
attributes:
label: Version
description: What version of calckey is your instance running? You can find this by clicking your instance's logo at the bottom left and then clicking instance information.
placeholder: Calckey Version 13.1.4.1
validations:
required: true
- type: input
id: instance
attributes:
label: Instance
description: What instance of calckey are you using?
placeholder: calckey.social
validations:
required: false
- type: checkboxes
id: terms
attributes:
label: Contribution Guidelines
description: By submitting this issue, you agree to follow our [Contribution Guidelines](https://codeberg.org/calckey/calckey/src/branch/develop/CONTRIBUTING.md)
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

View File

@ -1,6 +0,0 @@
# **DO NOT edit locale files** except `ja-JP.yml`.
When you add text to the ja-JP file (of misskey-dev/misskey), it will automatically be applied to other language files.
Translations added in ja-JP file should contain the original Japanese strings.
Please see [Contribution guide](../CONTRIBUTING.md) for more information.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,236 +0,0 @@
_lang_: "Dansk"
monthAndDay: '{month}/{day}'
search: Søge
notifications: Notifikationer
username: Brugernavn
password: Adgangskode
forgotPassword: Glemt adgangskode
fetchingAsApObject: Henter fra Fediverset
ok: OK
gotIt: Forstået!
cancel: Annullere
enterUsername: Indtast brugernavn
instance: Instans
renotedBy: Forstærket fra {user}
noNotes: Ingen opslag
otherSettings: Andre Indstillinger
profile: Profil
timeline: Tidslinje
signup: Registrere
logout: Log Ud
login: Log ind
uploading: Uploader...
save: Gem
users: Brugere
favorited: Tilsat til bogmærker.
unfavorite: Fjerne fra bogmærker
alreadyFavorited: Allerede inden i bogmærker.
pin: Fastgøre til profil
unpin: Løse fra profil
delete: Slet
addToList: Tilsæt til liste
deleteAndEdit: Slet og ændre
reply: Svar
loadMore: Indlæs mere
receiveFollowRequest: Følgeanmodning er blevet sendt
import: Importere
export: Eksportere
driveFileDeleteConfirm: Er du sikker på at du vil slette filen "{name}"? Denne vil
blive slettet fra alle tilknyttede opslage.
unfollowConfirm: Er du sikker på at du vil ikke følge {name} længere?
privacy: Privatlivs
enterListName: Indtast navnen for denne list
makeFollowManuallyApprove: Følgeanmodninger kræver godkendelse
unrenote: Fratag forstærkelse
renote: Forstærk
add: Tilsæt
reactionSetting: Reaktioner til at vise i reaktion-vælgeren
reactionSettingDescription2: Bevæg til at flytte om på, tryk til at slette og indtast
"+" til at tilsætte.
rememberNoteVisibility: Husk opslagsynlidhedsindstillinger
emojis: Emoji
flagShowTimelineReplies: Vis svare i tidslinjen
flagAsCatDescription: Du kommer til at få katøre og tale som en kat!
showOnRemote: Vis på fjerninstans
general: Generelt
accountMoved: 'Bruger har flyttet til et nyt konto:'
settings: Indstillinger
basicSettings: Primær Indstillinger
openInWindow: Åben i vindue
noAccountDescription: Denne bruger har ikke skrevet deres bio endnu.
loggingIn: Logger ind
cantFavorite: Kunne ikke tilsætte til bogmærker.
copyUsername: Kopi brugernavn
copyContent: Kopi indholdet
copyLink: Kopi link
searchUser: Søg for en bruger
files: Filer
noLists: Du har ingen liste
lists: Lister
reaction: Reaktioner
sensitive: NSFW
emoji: Emoji
cacheRemoteFilesDescription: Når denne indstilling er deaktiveret, fremmed filer bliver
indlæset direkte fra denne fjerneinstans. Hvis du deaktivere dette så vil det formindske
brugte opbevaringsplads men det vil også få netværktraffic til at stige fordi miniaturebilleder
vil ikke blive skabt.
flagAsBot: Markere denne konto som en robot
flagShowTimelineRepliesDescription: Vis svare af brugere til opslage af andre brugere
i tidslinjen hvis den bliver tændt.
loginFailed: Kunne ikke logge ind
silenceThisInstance: Nedtone denne instans
deleteAndEditConfirm: Er du sikker på at du vil slet denne opslag og ændre det? Du
vil tabe alle reaktioner, forstærkninger og svarer indenfor denne opslag.
editNote: Ændre note
deleted: Slettet
edited: 'Ændret den {date} {time}'
sendMessage: Send en besked
youShouldUpgradeClient: Til at vise denne side, vær sød at refresh til at opdatere
din brugerenhed.
defaultNoteVisibility: Standard synlighed
follow: Følge
followRequest: Følge
followRequests: Følgeanmodninger
unfollow: Følge ikke længere
followRequestPending: Følgeanmodning ventes på
enterEmoji: Indtast en emoji
renoted: Forstærket.
cantRenote: Denne opslag kunne ikke forstærkes.
cantReRenote: En forstærkelse kan ikke forstærkes.
quote: Citere
pinnedNote: Fastgjort opslag
pinned: Fastgøre til profil
you: Dig
clickToShow: Tryk til at vise
unblock: Blokere ikke længere
suspend: Suspendere
unsuspend: Suspendere ikke længere
blockConfirm: Er du sikker på at du vil blokere denne konto?
unblockConfirm: Er du sikker på at du vil ikke blokere denne konto endnu længere?
suspendConfirm: Er du sikker på at du vil suspendere denne konto?
selectAntenna: Vælg en antenne
selectWidget: Vælg en widget
editWidgets: Ændre widgettere
customEmojis: Brugerdefineret emoji
emojiName: Emoji navn
operations: Operationer
software: Software
metadata: Metadata
version: Version
monitor: Vagt
jobQueue: Jobkø
statistics: Statistik
cpuAndMemory: CPU og hukommelse
network: Netværk
disk: Disk
instanceInfo: Instans information
noThankYou: Nej tak
noNotifications: Intet notifikationer
addUser: Indsæt en bruger
addInstance: Indsæt en instans
favorite: Indsæt til bogmærker
favorites: Bogmærker
showMore: Vis mere
showLess: Luk
youGotNewFollower: følgte dig
followRequestAccepted: Følgeanmodning accepteret
mention: Nævne
mentions: Nævnene
directNotes: Direkt beskeder
importAndExport: Importere/Eksporter data
download: Download
exportRequested: Du har bedt om en eksport. Det vil tage noget tid. Den vil blive
tilsæt til din Drev når den er færdig.
importRequested: Du har bedt om en eksport. Det vil tage noget tid.
note: Opslag
notes: Opslage
following: Følger
followers: Følgere
followsYou: Følger dig
createList: Skab en list
manageLists: Administrere lister
error: Fejl
somethingHappened: En fejl har opstået
retry: Gentage
pageLoadError: En fejl har opstået ved indlæsning af siden.
pageLoadErrorDescription: Dette er normalt på grund af netværksproblemer eller din
browser's cache. Prøv at ryd cachen og så gentage efter et styk tid.
serverIsDead: Serveren svarer ikke. Vær sød at vente et styk tid og prøv igen.
editWidgetsExit: Færdig
headlineMisskey: En åben-kildekode, decentraliseret social-media platform som er frit
forevigt! 🚀
introMisskey: Velkommen! Calckey er en åbent-kildekode, decentraliseret social-media
platform som er frit forevigt!🚀
enableEmojiReactions: Aktivere emoji reaktioner
unsuspendConfirm: Er du sikker på at du vil ikke suspendere denne konto endnu længere?
selectList: Vælg en list
showEmojisInReactionNotifications: Vis emoji i reaktion notifikationer
attachCancel: Fjern tilknyttelse
markAsSensitive: Markere som NSFW
unmarkAsSensitive: Markere ikke som NSFW længere
enterFileName: Indtast filnavn
mute: Nedtone
unmute: Nedtone ikke længere
renoteMute: Nedtone forstærkninger
renoteUnmute: Nedtone forstærkninger ikke længere
block: Blokere
cacheRemoteFiles: Cachere fremmed filer
flagAsBotDescription: Aktivere denne valgmulighed hvis denne konto er kontrolleret
af en komputerprogram. Hvis den et tændt så vil det signalere til andre udviklere
som arbejder på komputer-kontrolleret social-media kontoer og det vil også adjustere
Calckey's indresystemer til at behandle denne konto som en robot.
flagAsCat: Er du en kat? 😺
flagSpeakAsCat: Tale som en kat
emojiUrl: Emoji URL
addEmoji: Tilsæt
settingGuide: Anbefalet indstillinger
flagSpeakAsCatDescription: Din opslage vil blive nyaniferet når du er i kat-mode
autoAcceptFollowed: Automatisk godkende følgeanmodninger fra brugere som du selv følger
addAccount: Tilsæt konto
wallpaper: Baggrund
setWallpaper: Sæt baggrund
removeWallpaper: Fjern baggrund
host: Host
selectUser: Vælg en bruger
searchWith: 'Søge: {q}'
youHaveNoLists: Du har ingen liste
followConfirm: Er du sikker på at du vil gerne følge {name}?
proxyAccount: Proxykonto
proxyAccountDescription: En proxykonto er en konto som virker som en fremmed følger
for bruger under særlige konditioner. For eksempel, når en bruger tilsætter en fjernbruger
til denne list, vil denne fjernbruger's aktivitet ikke blive leveret til den instans
hvis ingen lokalebruger følger fjernbrugeren, så denne proxykonto vil følge den
istedetfor.
instances: Instanser
registeredAt: Registreret på
latestRequestSentAt: Sidste anmodning sendt
latestRequestReceivedAt: Sidste anmodning modtaget
selectInstance: Vælg en instans
recipient: Recipient(er)
annotation: Kommentarer
federation: Føderation
latestStatus: Senest status
storageUsage: Opbevaringspladsbrug
charts: Grafer
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

File diff suppressed because it is too large Load Diff

View File

@ -1,819 +0,0 @@
_lang_: "Ελληνικά"
monthAndDay: "{day}/{month}"
search: "Αναζήτηση"
notifications: "Ειδοποιήσεις"
username: "Όνομα μέλους"
password: "Κωδικός πρόσβασης"
forgotPassword: "Ξέχασα τον κωδικό πρόσβασης"
fetchingAsApObject: "Άντληση από το Fediverse"
ok: "Εντάξει"
gotIt: "Τό'πιασα!"
cancel: "Ακύρωση"
enterUsername: "Εισαγωγή ονόματος μέλους"
renotedBy: "Προωθήθηκε από {user}"
noNotes: "Δεν υπάρχουν δημοσιεύσεις"
noNotifications: "Δεν υπάρχουν ειδοποιήσεις"
settings: "Ρυθμίσεις"
basicSettings: "Βασικές Ρυθμίσεις"
otherSettings: "Άλλες Ρυθμίσεις"
openInWindow: "Άνοιγμα σε παράθυρο"
profile: "Προφίλ"
timeline: "Χρονολόγιο"
noAccountDescription: "Αυτό το μέλος δεν έχει γράψει βιογραφικό ακόμη."
login: "Σύνδεση"
loggingIn: "Συνδέεστε"
logout: "Αποσύνδεση"
signup: "Εγγραφή"
uploading: "Ανέβασμα..."
save: "Αποθήκευση"
users: "Μέλη"
addUser: "Προσθήκη μέλους"
favorite: "Προσθήκη στους σελιδοδείκτες"
favorites: "Σελιδοδείκτες"
unfavorite: "Αφαίρεση από τους σελιδοδείκτες"
favorited: "Προστέθηκε στους σελιδοδείκτες."
alreadyFavorited: "Έχει ήδη προστεθεί στους σελιδοδείκτες."
cantFavorite: "Αδυναμία προσθήκης στους σελιδοδείκτες."
pin: "Καρφίτσωμα στο προφίλ"
unpin: "Ξεκαρφίτσωμα από το προφίλ"
copyContent: "Αντιγραφή περιεχομένων"
copyLink: "Αντιγραφή συνδέσμου"
delete: "Διαγραφή"
deleteAndEdit: "Διαγραφή και επεξεργασία"
deleteAndEditConfirm: "Σίγουρα θέλετε να διαγράψετε αυτή τη δημοσίευση και να την\
\ επεξεργαστείτε; Θα χάσετε όλες τις αντιδράσεις, προωθήσεις και απαντήσεις σε αυτήν."
addToList: "Προσθήκη στη λίστα"
sendMessage: "Αποστολή μηνύματος"
copyUsername: "Αντιγραφή ονόματος μέλους"
searchUser: "Αναζήτηση μέλους"
reply: "Απάντηση"
loadMore: "Φόρτωσε περισσότερα"
showMore: "Δείξε περισσότερα"
showLess: "Κλείσιμο"
youGotNewFollower: "σε ακολούθησε"
receiveFollowRequest: "Λάβατε αίτημα ακολούθησης"
followRequestAccepted: "Το αίτημα ακολούθησης έγινε δεκτό"
mention: "Επισήμανση"
mentions: "Επισημάνσεις"
directNotes: "Απευθείας μηνύματα"
importAndExport: "Εισαγωγή/Εξαγωγή Δεδομένων"
import: "Εισαγωγή"
export: "Εξαγωγή"
files: "Αρχεία"
download: "Κατέβασμα"
driveFileDeleteConfirm: "Θέλετε σίγουρα να διαγράψετε το αρχείο \"{name}\"; Οι δημοσιεύσεις\
\ με αυτό το συνημμένο αρχείο επίσης θα διαγραφούν."
unfollowConfirm: "Θέλετε σίγουρα να σταματήσετε να ακολουθείτε το μέλος {name};"
exportRequested: "Ζητήσατε μία εξαγωγή. Αυτό μπορεί να πάρει κάποιον χρόνο. Θα προστεθεί\
\ στον Αποθηκευτικό Χώρο σας μόλις ολοκληρωθεί."
importRequested: "Ζητήσατε μια εισαγωγή. Αυτό μπορεί να πάρει κάποιον χρόνο."
lists: "Λίστες"
noLists: "Δεν έχετε λίστες"
note: "Δημοσίευση"
notes: "Δημοσιεύσεις"
following: "Ακολουθεί"
followers: "Ακολουθούν"
followsYou: "Σε ακολουθεί"
createList: "Δημιουργία λίστας"
manageLists: "Διαχείριση λιστών"
error: "Σφάλμα"
somethingHappened: "Προέκυψε ένα σφάλμα"
retry: "Προσπάθεια ξανά"
pageLoadError: "Ένα σφάλμα προέκυψε φορτώνοντας τη σελίδα."
pageLoadErrorDescription: "Αυτό κανονικά προκαλείται από σφάλματα δικτύου ή από την\
\ προσωρινή μνήμη του προγράμματος περιήγησης. Δοκιμάστε να σβήσετε την προσωρινή\
\ μνήμη (cache) και να δοκιμάσετε ξανά μετά από λίγο."
serverIsDead: "Αυτός ο διακομιστής (server) δεν αποκρίνεται. Παρακαλώ περιμένετε λίγο\
\ και δοκιμάστε ξανά."
youShouldUpgradeClient: "Για να δείτε αυτή τη σελίδα, παρακαλώ επαναφορτώστε για να\
\ γίνει ενημέρωση."
enterListName: "Πληκτρολογήστε ένα όνομα για τη λίστα"
privacy: "Ιδιωτικότητα"
makeFollowManuallyApprove: "Τα αιτήματα ακολούθησης χρειάζονται έγκριση"
defaultNoteVisibility: "Προεπιλεγμένη ορατότητα"
follow: "Ακολουθήστε"
followRequest: "Ακολουθήστε"
followRequests: "Αιτήματα ακολούθησης"
unfollow: "Να μην ακολουθώ"
followRequestPending: "Το αίτημα ακολούθησης εκκρεμεί"
enterEmoji: "Εισάγετε ένα emoji"
renote: "Προώθηση"
unrenote: "Αναίρεση προώθησης"
renoted: "Προωθήθηκε."
cantRenote: "Αυτή η δημοσίευση δεν μπορεί να προωθηθεί."
cantReRenote: "Μία προώθηση δεν μπορεί να προωθηθεί."
quote: "Παράθεση"
pinnedNote: "Καρφιτσωμένη δημοσίευση"
pinned: "Καρφίτσωμα στο προφίλ"
you: "Εσύ"
clickToShow: "Κάντε κλικ για εμφάνιση"
add: "Προσθήκη"
reaction: "Αντιδράσεις"
reactionSetting: "Αντιδράσεις που θα εμφανίζονται στον επιλογέα"
reactionSettingDescription2: "Σύρετε για να αλλάξετε τη σειρά, κάντε κλικ για να διαγράψετε,\
\ πατήστε \"+\" για να προσθέσετε."
rememberNoteVisibility: "Θυμήσου τις ρυθμίσεις ορατότητας για τις δημοσιεύσεις"
attachCancel: "Αφαίρεση επισυναπτόμενου"
enterFileName: "Πληκτρολογήστε όνομα αρχείου"
mute: "Σίγαση"
unmute: "Διακοπή σίγασης"
block: "Μπλοκάρισμα"
unblock: "Διακοπή μπλοκαρίσματος"
suspend: "Αποβολή"
unsuspend: "Διακοπή αποβολής"
blockConfirm: "Θέλετε σίγουρα να μπλοκάρετε αυτόν τον λογαριασμό;"
unblockConfirm: "Θέλετε σίγουρα να ξεμπλοκάρετε αυτόν τον λογαριασμό;"
suspendConfirm: "Θέλετε σίγουρα να αποβάλετε αυτόν τον λογαριασμό;"
unsuspendConfirm: "Θέλετε σίγουρα να άρετε την αποβολή αυτού του λογαριασμού;"
selectList: "Επιλέξτε μια λίστα"
selectAntenna: "Επιλέξτε μια αντένα"
selectWidget: "Επιλέξτε ένα πρόσθετο"
editWidgets: "Επεξεργασία πρόσθετων"
editWidgetsExit: "Ολοκληρώθηκε"
customEmojis: "Προσαρμοσμένα Emoji"
emojiName: "Όνομα emoji"
addEmoji: "Προσθήκη"
settingGuide: "Προτεινόμενες ρυθμίσεις"
flagAsBot: "Δήλωση αυτού του λογαριασμού ως bot"
flagAsCat: "Είσαι γατί; \U0001F63A"
flagShowTimelineReplies: "Εμφάνιση απαντήσεων στο χρονολόγιο"
addAccount: "Προσθήκη λογαριασμού"
general: "Γενικές"
wallpaper: "Ταπετσαρία"
setWallpaper: "Ορισμός ταπετσαρίας"
removeWallpaper: "Αφαίρεση ταπετσαρίας"
searchWith: "Αναζήτηση: {q}"
youHaveNoLists: "Δεν έχετε λίστες"
followConfirm: "Θέλετε σίγουρα να ακολουθήσετε τον λογαριασμό {name};"
host: "Φιλοξενεί (Host)"
selectUser: "Επιλέξτε ένα μέλος"
recipient: "Αποδέκτης-τρια(-ες)"
annotation: "Σχόλια"
federation: "Ομοσπονδία"
storageUsage: "Χρήση χώρου"
version: "Έκδοση"
metadata: "Μεταδεδομένα"
network: "Δίκτυο"
disk: "Δίσκος"
instanceInfo: "Πληροφορίες Instance"
statistics: "Στατιστικά"
clearQueue: "Εκκαθάριση ουράς"
clearQueueConfirmTitle: "Θέλετε να διαγράψετε την ουρά;"
clearCachedFiles: "Εκκαθάριση προσωρινής μνήμης (cache)"
done: "Ολοκληρώθηκε"
attachFile: "Επισύναψη αρχείων"
more: "Περισσότερα!"
noSuchUser: "Το μέλος δεν βρέθηκε"
announcements: "Ανακοινώσεις"
imageUrl: "URL εικόνας"
remove: "Διαγραφή"
removed: "Η διαγραφή ολοκληρώθηκε επιτυχώς"
saved: "Αποθηκεύτηκε"
messaging: "Συνομιλία"
upload: "Ανεβάστε"
fromDrive: "Από τον Αποθηκευτικό Χώρο"
fromUrl: "Από URL"
uploadFromUrl: "Ανέβασμα από URL"
explore: "Εξερεύνηση"
messageRead: "Διαβάστηκε"
startMessaging: "Ξεκινήστε μια νέα συνομιλία"
nUsersRead: "διαβάστηκε από {n}"
tos: "Όροι Χρήσης"
start: "Ας αρχίσουμε"
home: "Κεντρικό"
activity: "Δραστηριότητα"
images: "Εικόνες"
birthday: "Γενέθλια"
registeredDate: "Έγινε μέλος στις"
location: "Τοποθεσία"
theme: "Θέματα"
light: "Φωτεινό"
dark: "Σκοτεινό"
drive: "Αποθηκευτικός Χώρος"
fileName: "Όνομα αρχείου"
selectFile: "Επιλέξτε ένα αρχείο"
selectFiles: "Επιλέξτε αρχεία"
selectFolder: "Επιλέξτε φάκελο"
selectFolders: "Επιλέξτε φακέλους"
renameFile: "Μετονομασία αρχείου"
addFile: "Προσθέστε ένα αρχείο"
emptyDrive: "Ο Αποθηκευτικός Χώρος σας είναι άδειος"
copyUrl: "Αντιγραφή διεύθυνσης URL"
rename: "Μετονομασία"
avatar: "Άβαταρ"
banner: "Εξώφυλλο"
reload: "Ανανέωση"
doNothing: "Αγνόηση"
watch: "Παρακολούθηση"
unwatch: "Διακοπή παρακολούθησης"
accept: "Αποδοχή"
reject: "Απόρριψη"
normal: "Κανονικό"
instanceName: "Όνομα instance"
thisYear: "Έτος"
thisMonth: "Μήνας"
today: "Σήμερα"
dayX: "{day}"
pages: "Σελίδες"
connectService: "Σύνδεση"
disconnectService: "Αποσύνδεση"
registration: "Εγγραφή"
pinnedPages: "Καρφιτσωμένες Σελίδες"
pinnedNotes: "Καρφιτσωμένες δημοσιεύσεις"
antennas: "Αντένες"
manageAntennas: "Διαχείριση Αντενών"
name: "Όνομα"
antennaSource: "Πηγή Αντένας"
antennaKeywords: "Λέξεις-κλειδιά για παρακολούθηση"
antennaExcludeKeywords: "Λέξεις-κλειδιά για εξαίρεση"
notifyAntenna: "Ειδοποίηση για νέες δημοσιεύσεις"
withFileAntenna: "Μόνο δημοσιεύσεις με αρχεία"
caseSensitive: "Διάκριση Πεζών-Κεφαλαίων"
popularTags: "Δημοφιλείς ετικέτες"
userList: "Λίστες"
about: "Σχετικά με"
moderator: "Συντονιστής/στρια"
moderation: "Συντονισμός"
cacheClear: "Εκκαθάριση προσωρινής μνήμης (cache)"
markAsReadAllNotifications: "Σημειώστε όλες τις ειδοποιήσεις ως διαβασμένες"
group: "Ομάδα"
groups: "Ομάδες"
createGroup: "Δημιουργία ομάδας"
ownedGroups: "Οι ομάδες σας"
groupName: "Όνομα ομάδας"
members: "Μέλη"
transfer: "Μεταφορά"
messagingWithUser: "Προσωπική συνομιλία"
messagingWithGroup: "Ομαδική συνομιλία"
title: "Τίτλος"
text: "Κείμενο"
enable: "Ενεργοποίηση"
next: "Επόμενο"
noteOf: "Δημοσίευση από {user}"
inviteToGroup: "Πρόσκληση στην ομάδα"
quoteAttached: "Παράθεση"
signinRequired: "Παρακαλούμε δημιουργήστε λογαριασμό ή συνδεθείτε πριν συνεχίσετε"
category: "Κατηγορία"
tags: "Ετικέτες"
createAccount: "Δημιουργία λογαριασμού"
local: "Τοπικό"
remote: "Απομακρυσμένο"
total: "Σύνολο"
appearance: "Εμφάνιση"
accountSettings: "Ρυθμίσεις Λογαριασμού"
sounds: "Ήχοι"
sound: "Ήχοι"
listen: "Ακρόαση"
showInPage: "Εμφάνιση στη σελίδα"
volume: "Ένταση"
masterVolume: "Κεντρική ένταση"
details: "Λεπτομέρειες"
install: "Εγκαταστήστε"
uninstall: "Απεγκατάσταση"
manage: "Διαχείριση"
smtpHost: "Φιλοξενεί (Host)"
smtpUser: "Όνομα μέλους"
smtpPass: "Κωδικός"
notificationSetting: "Ρυθμίσεις ειδοποιήσεων"
notificationSettingDesc: "Επιλέξτε τους τύπους ειδοποιήσεων για προβολή."
switchUi: "Διάταξη"
clip: "Κλιπ"
driveFilesCount: "Αριθμός αρχείων Αποθηκευτικού Χώρου"
driveUsage: "Χρήση Αποθηκευτικού Χώρου"
noteFavoritesCount: "Αριθμός αγαπημένων σημειωμάτων"
clips: "Κλιπ"
clearCache: "Εκκαθάριση προσωρινής μνήμης"
emailNotification: "Ειδοποιήσεις μέσω mail"
inChannelSearch: "Αναζήτηση στο κανάλι"
info: "Πληροφορίες"
notRecommended: "Δεν προτείνεται"
switchAccount: "Αλλαγή λογαριασμού"
user: "Μέλη"
administration: "Διαχείριση"
switch: "Εναλλαγή"
gallery: "Γκαλερί"
global: "Παγκόσμιο"
searchResult: "Αποτελέσματα αναζήτησης"
learnMore: "Μάθετε περισσότερα"
controlPanel: "Πίνακας ελέγχου"
manageAccounts: "Διαχείριση Λογαριασμών"
searchByGoogle: "Αναζήτηση"
file: "Αρχεία"
recommended: "Προτεινόμενα"
cannotUploadBecauseNoFreeSpace: "Το ανέβασμα απέτυχε λόγω ανεπαρκούς Αποθηκευτικού\
\ Χώρου."
_email:
_follow:
title: "Έχετε ένα νέο ακόλουθο"
_mfm:
mention: "Επισήμανση"
quote: "Παράθεση"
emoji: "Επιπλέον emoji"
search: "Αναζήτηση"
_channel:
featured: "Δημοφιλή"
_theme:
keys:
panel: "Πίνακας"
mention: "Επισήμανση"
renote: "Κοινοποίηση σημειώματος"
_sfx:
note: "Σημειώματα"
notification: "Ειδοποιήσεις"
chat: "Συνομιλία"
chatBg: "Συνομιλία (Παρασκήνιο)"
antenna: "Αντένες"
channel: "Ειδοποιήσεις καναλιών"
_ago:
future: "Μελλοντικό"
justNow: "Μόλις τώρα"
secondsAgo: "{n} δευτερόλεπτο(α) πριν"
minutesAgo: "{n} λεπτό(ά) πριν"
hoursAgo: "{n} ώρα(ες) πριν"
daysAgo: "{n} μέρα(ες) πριν"
weeksAgo: "{n} εβδομάδα(ες) πριν"
monthsAgo: "{n} μήνα(ες) πριν"
yearsAgo: "{n} έτος(η) πριν"
_permissions:
"write:drive": "Επεξεργαστείτε ή διαγράψτε τα αρχεία και τους φακέλους του Αποθηκευτικού\
\ Χώρου σας"
"read:favorites": "Δείτε τη λίστα με τους σελιδοδείκτες σας"
"write:favorites": "Επεξεργαστείτε τη λίστα με τους σελιδοδείκτες σας"
"read:messaging": "Δείτε τις συνομιλίες σας"
"write:messaging": "Γράψτε ή διαγράψτε μηνύματα συνομιλίας"
"read:notifications": "Δείτε τις ειδοποιήσεις σας"
"write:notifications": "Διαχειριστείτε τις ειδοποιήσεις σας"
"read:pages": "Δείτε τις Σελίδες σας"
"write:pages": "Επεξεργαστείτε ή διαγράψτε τις σελίδες σας"
"write:gallery-likes": Επεξεργασία της λίστας των αγαπημένων σας δημοσιεύσεων γκαλερί
"read:gallery": Δείτε την γκαλερί σας
"write:gallery": Επεξεργασία της γκαλερί σας
"read:gallery-likes": Δείτε τη λίστα των αγαπημένων σας δημοσιεύσεων γκαλερί
_antennaSources:
all: "Όλα τα σημειώματα"
homeTimeline: "Σημειώματα από μέλη που ακολουθείτε"
users: "Σημειώματα από συγκεκριμένα μέλη"
userList: "Σημειώματα από καθορισμένη λίστα μελών"
userGroup: "Σημειώματα από μέλη καθορισμένης ομάδας"
_widgets:
profile: "Προφίλ"
instanceInfo: "Πληροφορίες του instance"
notifications: "Ειδοποιήσεις"
timeline: "Χρονολόγιο"
calendar: "Ημερολόγιο"
trends: "Δημοφιλή"
clock: "Ρολόι"
activity: "Δραστηριότητα"
photos: "Φωτογραφίες"
digitalClock: "Ψηφιακό ρολόι"
federation: "Ομοσπονδία"
postForm: "Φόρμα δημοσίευσης"
button: "Κουμπί"
onlineUsers: "Συνδεδεμένα μέλη"
_userList:
chooseList: "Επιλέξτε μία λίστα"
_cw:
show: "Δείτε περισσότερα"
_visibility:
home: "Κεντρικό"
homeDescription: "Δημοσίευση στο κεντρικό χρονολόγιο μόνο"
followers: "Ακολουθούν"
_profile:
name: "Όνομα"
username: "Όνομα μέλους"
changeAvatar: Αλλαγή άβαταρ
_exportOrImport:
allNotes: "Όλα τα σημειώματα"
followingList: "Ακολουθεί"
muteList: "Μέλη σε σίγαση"
blockingList: "Μπλοκαρισμένα μέλη"
userLists: "Λίστες"
_charts:
federation: "Ομοσπονδία"
_timelines:
home: "Κεντρικό"
local: "Τοπικό"
social: "Κοινωνικό"
global: "Παγκόσμιο"
_pages:
viewPage: "Δείτε τις Σελίδες σας"
blocks:
image: "Εικόνες"
_notification:
youGotMessagingMessageFromUser: "{name} σάς έστειλε ένα μήνυμα συνομιλίας"
youWereFollowed: "σε ακολούθησε"
_types:
follow: "Νέοι ακόλουθοι"
mention: "Επισήμανση"
renote: "Κοινοποίηση σημειώματος"
quote: "Παράθεση"
reaction: "Αντιδράσεις"
_actions:
reply: "Απάντηση"
renote: "Κοινοποίηση σημειώματος"
_deck:
widgetsIntroduction: "Παρακαλούμε επιλέξτε \"Επεξεργασία πρόσθετων\" στο μενού και\
\ προσθέστε μαραφέτι."
_columns:
widgets: "Πρόσθετα"
notifications: "Ειδοποιήσεις"
tl: "Χρονολόγιο"
antenna: "Αντένες"
list: "Λίστα"
mentions: "Επισημάνσεις"
sensitive: Ευαίσθητο περιεχόμενο (NSFW)
createFolder: Δημιουργία φακέλου
uploadFromUrlDescription: Το URL του αρχείου που θέλετε να ανεβάσετε
emptyFolder: Αυτός ο φάκελος είναι άδειος
unableToDelete: Αδυναμία διαγραφής
recentlyUpdatedUsers: Πρόσφατα ενεργά μέλη
recentlyRegisteredUsers: Νέα μέλη
exploreUsersCount: Υπάρχουν {count} μέλη
help: Βοήθεια
inputNewFileName: Πληκτρολογήστε ένα νέο όνομα αρχείου
nothing: Δεν υπάρχει τίποτα να δείτε εδώ
newNoteRecived: Υπάρχουν νέες δημοσιεύσεις
passwordMatched: Ταιριάζει
unmarkAsSensitive: Αναίρεση επισήμανσης ως Ευαίσθητο Περιεχόμενο (NSFW)
blockedUsers: Μπλοκαρισμένα μέλη
noteDeleteConfirm: Θέλετε σίγουρα να διαγράψετε αυτή τη δημοσίευση;
preview: Προεπισκόπηση
noCustomEmojis: Δεν υπάρχουν emoji
tosUrl: URL Όρων Χρήσης
monthX: '{month}'
markAsReadAllTalkMessages: Σημειώστε όλα τα μηνύματα ως διαβασμένα
inputMessageHere: Γράψτε εδώ το μήνυμά σας
close: Κλείσιμο
newMessageExists: Υπάρχουν νέα μηνύματα
usernameInvalidFormat: Μπορείτε να χρησιμοποιήσετε κεφαλαία και μικρά γράμματα, αριθμούς,
και κάτω παύλες.
tooShort: Πολύ σύντομο
passwordNotMatched: Δεν ταιριάζει
existingAccount: Υπάρχων λογαριασμός
deleteAll: Διαγραφή όλων
chooseEmoji: Επιλέξτε ένα emoji
sort: Ταξινόμηση
descendingOrder: Φθίνουσα
deleteAllFiles: Διαγραφή όλων των αρχείων
userSuspended: Αυτό το μέλος έχει αποβληθεί.
menu: Μενού
divider: Χώρισμα
deletedNote: Διαγραμμένη δημοσίευση
useCw: Απόκρυψη περιεχομένου
description: Περιγραφή
width: Πλάτος
disableAll: Απενεργοποίηση όλων
notificationType: Τύπος ειδοποίησης
wordMute: Σίγαση λέξεων
userSaysSomething: '{name} είπε κάτι'
metrics: Μετρήσεις
overview: Γενική εικόνα
database: Βάση δεδομένων
channel: Κανάλια
other: Άλλα
abuseReports: Αναφορές
reportAbuse: Αναφορά
unclip: Ακύρωση κλιπ
public: Δημόσιο
renotedCount: Αριθμός προωθήσεων που ελήφθησαν
alwaysMarkSensitive: Επισήμανση ως ευαίσθητο περιεχόμενο (NSFW) ως προεπιλογή
markAllAsRead: Σημειώστε τα όλα ως διαβασμένα
_gallery:
like: Μου αρέσει
liked: Αγαπημένες δημοσιεύσεις
my: Η Γκαλερί μου
unlike: Δεν μου αρέσει
showOnRemote: Δείτε στο απομακρυσμένο instance
perDay: Ανά Ημέρα
software: Λογισμικό
cpuAndMemory: CPU και Μνήμη
noUsers: Δεν υπάρχουν μέλη
processing: Επεξεργασία
changePassword: Αλλαγή κωδικού
security: Ασφάλεια
featured: Προτεινόμενα
keepOriginalUploading: Διατήρηση πρωτότυπης εικόνας
manageGroups: Διαχείριση ομάδων
deleteFolder: Διαγραφή φακέλου
nsfw: Ευαίσθητο περιεχόμενο (NSFW)
nUsersMentioned: Έχει αναφερθεί από {n} μέλη
notFound: Δεν βρέθηκε
markAsReadAllUnreadNotes: Σημειώστε όλες τις δημοσιεύσεις ως διαβασμένες
invites: Προσκλήσεις
quoteQuestion: Να προστεθεί ως Παράθεση;
noMessagesYet: Δεν υπάρχουν μηνύματα ακόμη
onlyOneFileCanBeAttached: Μπορείτε να επισυνάψετε μόνο ένα αρχείο σε ένα μήνυμα
tooLong: Υπερβολικά μακροσκελές
or: Ή
language: Γλώσσα
groupInvited: Προσκληθήκατε σε μία ομάδα
ascendingOrder: Αύξουσα
visibility: Ορατότητα
invisibleNote: Αόρατη δημοσίευση
enableInfiniteScroll: Αυτόματη φόρτωση περισσοτέρων
poll: Ψηφοφορία
enablePlayer: Άνοιγμα προβολής βίντεο
large: Μεγάλο
medium: Μεσαίο
small: Μικρό
postToGallery: Δημιουργία νέας δημοσίευσης γκαλερί
reloadConfirm: Θα θέλατε να ανανεώσετε το χρονολόγιο;
enableAll: Ενεργοποίηση όλων
permission: Εξουσιοδοτήσεις
sample: Δείγμα
copy: Αντιγραφή
display: Προβολή
send: Αποστολή
behavior: Συμπεριφορά
useGlobalSetting: Χρήση παγκόσμιων ρυθμίσεων
abuseMarkAsResolved: Επισήμανση της αναφοράς ως επιλυμένης
openInNewTab: Άνοιγμα σε νέα καρτέλα
_sensitiveMediaDetection:
setSensitiveFlagAutomatically: Επισήμανση ως ευαίσθητο περιεχόμενο (NSFW)
defaultNavigationBehaviour: Προεπιλεγμένη συμπεριφορά περιήγησης
system: Σύστημα
createNew: Δημιουργία νέου
createNewClip: Δημιουργία νέου κλιπ
repliesCount: Αριθμός απεσταλμένων απαντήσεων
optional: Προαιρετικό
renotesCount: Αριθμός προωθήσεων σε δημοσιεύσεις άλλων
addItem: Προσθήκη αντικειμένου
disablePlayer: Κλείσιμο προβολής βίντεο
describeFile: Προσθήκη περιγραφής
enterFileDescription: Πληκτρολογήστε περιγραφή
author: Συντάκτης/τρια
setMultipleBySeparatingWithSpace: Διαχωρίστε πολλαπλές καταχωρήσεις με κενά.
random: Τυχαίο
accountInfo: Πληροφορίες Λογαριασμού
notesCount: Αριθμός δημοσιεύσεων
repliedCount: Αριθμός απαντήσεων που ελήφθησαν
flagAsCatDescription: Θα έχεις γατοαυτιά και θα μιλάς σαν γατί!
muteAndBlock: Σιγάσεις και Μπλοκαρίσματα
mutedUsers: Σιγασμένα μέλη
editProfile: Επεξεργασία προφίλ
pinLimitExceeded: Δεν μπορείτε να καρφιτσώσετε άλλες δημοσιεύσεις
currentPassword: Τρέχων κωδικός
newPassword: Νέος κωδικός
newPasswordRetype: Ξαναπληκτρολογήστε τον νέο κωδικό
notesAndReplies: Δημοσιεύσεις και απαντήσεις
popularUsers: Δημοφιλή μέλη
share: Κοινοποίηση
retype: Πληκτρολογήστε ξανά
invitations: Προσκλήσεις
available: Διαθέσιμο
unavailable: Μη διαθέσιμο
youHaveNoGroups: Δεν έχετε ομάδες
doing: Επεξεργασία...
yourAccountSuspendedTitle: Αυτός ο λογαριασμός έχει αποβληθεί
leaveConfirm: Υπάρχουν αλλαγές που δεν έχουν σωθεί. Θέλετε να τις απορρίψετε;
height: Ύψος
edit: Επεξεργασία
headlineMisskey: Μία ανοιχτού λογισμικού, αποκεντρωμένη πλατφόρμα κοινωνικής δικτύωσης
που θα είναι για πάντα ελεύθερη! 🚀
introMisskey: Καλώς ήρθατε! Το Calckey είναι μία ανοιχτού λογισμικού, αποκεντρωμένη
πλατφόρμα κοινωνικής δικτύωσης που θα είναι για πάντα ελεύθερη! 🚀
markAsSensitive: Επισήμανση ως Ευαίσθητο Περιεχόμενο (NSFW)
autoAcceptFollowed: Αυτόματη έγκριση αιτημάτων ακολούθησης από λογαριασμούς που ακολουθείτε
loginFailed: Αποτυχία σύνδεσης
accountMoved: 'Έχει μεταφερθεί σε νέο λογαριασμό:'
perHour: Ανά Ώρα
remoteUserCaution: Οι πληροφορίες από απομακρυσμένους λογαριασμούς μπορεί να είναι
ατελείς.
folderName: Όνομα φακέλου
renameFolder: Μετονομασία φακέλου
recentUsed: Χρησιμοποιήθηκαν πρόσφατα
deleteAllFilesConfirm: Σίγουρα θέλετε να διαγράψετε όλα τα αρχεία;
removeAllFollowing: Διακοπή ακολούθησης όλων των ακολουθούμενων μελών
userSilenced: Αυτό το μέλος είναι υπό σιώπηση.
makeActive: Ενεργοποίηση
create: Δημιουργία
reportAbuseOf: Αναφορά {name}
cacheRemoteFilesDescription: Όταν αυτή η ρύθμιση είναι απενεργοποιημένη, τα απομακρυσμένα
αρχεία φορτώνονται απευθείας από το απομακρυσμένο instance. Η απενεργοποίηση θα
μειώσει τη χρήση του δίσκου σας, αλλά θα αυξήσει την κίνηση δεδομένων, καθώς δεν
θα δημιουργούνται σμικρύνσεις αρχείων (thumbnails).
registeredAt: Εγγράφηκε στις
latestStatus: Τελευταία κατάσταση
charts: Πίνακες
stopActivityDelivery: Σταμάτα να στέλνεις δραστηριότητες
operations: Λειτουργίες
monitor: Παρακολούθηση
jobQueue: Ουρά εργασιών
blockedInstances: Μπλοκαρισμένα Instances
blockedInstancesDescription: Παραθέστε τις διευθύνσεις (hostnames) των instances που
θέλετε να μπλοκάρετε. Τα παρακάτω instances δεν θα μπορούν πλέον να επικοινωνούν
με αυτό το instance.
intro: Η εγκατάσταση του Calckey τελείωσε! Παρακαλώ δημιουργήστε ένα μέλος διαχειριστή/στρια.
noThankYou: Όχι, ευχαριστώ
addInstance: Προσθήκη instance
renoteMute: Σίγαση προωθήσεων
emojiUrl: Διεύθυνση emoji (URL)
cacheRemoteFiles: Προσωρινή αποθήκευση απομακρυσμένων αρχείων
flagSpeakAsCat: Να μιλάς σαν γατί
flagSpeakAsCatDescription: Οι δημοσιεύσεις σου θα nyaοποιούνται όταν είσαι γατί
selectInstance: Επιλέξτε ένα instance
latestRequestSentAt: Τελευταίο αίτημα στάλθηκε
hiddenTags: Κρυμμένες Ετικέτες (Hashtags)
noInstances: Δεν υπάρχουν instances
renoteUnmute: Διακοπή σίγασης προωθήσεων
flagAsBotDescription: Ενεργοποιήστε αυτή την επιλογή αν αυτός ο λογαριασμός ελέγχεται
από ένα πρόγραμμα. Αν ενεργοποιηθεί, θα λειτουργεί σαν σημάδι για τους προγραμματιστές,
ώστε να αποφύγουν ατέρμονη αλληλεπίδραση με άλλα bots και για να ρυθμίσει τα εσωτερικά
συστήματα του Calckey ώστε να αντιμετωπίζουν αυτόν τον λογαριασμό ως bot.
flagShowTimelineRepliesDescription: Εμφάνιση απαντήσεων μελών σε δημοσιεύσεις άλλων
μελών στο χρονολόγιο.
latestRequestReceivedAt: Τελευταίο αίτημα ελήφθη
blockThisInstance: Μπλοκάρισμα αυτού του instance
clearQueueConfirmText: Τυχόν δημοσιεύσεις στην ουρά που δεν έχουν αποσταλεί δεν θα
ομοσπονδοποιηθούν. Συνήθως αυτή η λειτουργία δεν χρειάζεται.
clearCachedFilesConfirm: Σίγουρα θέλετε να διαγράψετε όλα τα προσωρινά αποθηκευμένα
απομακρυσμένα αρχεία;
default: Προεπιλεγμένο
defaultValueIs: 'Προεπιλεγμένο: {value}'
noJobs: Δεν υπάρχουν εργασίες (jobs)
federating: Ομοσπονδοποιείται
blocked: Μπλοκαρισμένο
suspended: Σε αποβολή
instanceFollowing: Ακολουθεί στο instance
instanceFollowers: Ακόλουθοι του instance
instanceUsers: Μέλη αυτού του instance
retypedNotMatch: Οι καταχωρήσεις δεν ταιριάζουν.
usernameOrUserId: Όνομα μέλους ή ταυτότητα μέλους (id)
removeAreYouSure: Θέλετε σίγουρα να αφαιρέσετε το "{x}";
deleteAreYouSure: Θέλετε σίγουρα να διαγράψετε το "{x}";
resetAreYouSure: Σίγουρα επανεκκίνηση;
uploadFromUrlMayTakeTime: Ίσως πάρει λίγο χρόνο μέχρι το ανέβασμα να ολοκληρωθεί.
noMoreHistory: Δεν υπάρχει περαιτέρω ιστορικό
agreeTo: Συμφωνώ στο {0}
yearsOld: '{age} ετών'
themeForDarkMode: Θέμα για τη Σκοτεινή Λειτουργία
syncDeviceDarkMode: Συγχρονισμός της Σκοτεινής Λειτουργίας με τις ρυθμίσεις της συσκευής
σας
inputNewDescription: Προσθέστε νέα περιγραφή
whenServerDisconnected: Όταν χάνεται η σύνδεση στον σέρβερ
disconnectedFromServer: Η σύνδεση στον σέρβερ έχει χαθεί
instanceDescription: Περιγραφή instance
maintainerEmail: Διεύθυνση email προγραμματιστή/στριας
yearX: '{year}'
enableGlobalTimeline: Ενεργοποίηση παγκόσμιου χρονολογίου
enableLocalTimeline: Ενεργοποίηση τοπικού χρονολογίου
enableRegistration: Ενεργοποίηση εγγραφής νέων μελών
invite: Πρόσκληση
disablingTimelinesInfo: Οι Διαχειρίστριες-ες και οι Συντονιστές-στριες θα έχουν πάντα
πρόσβαση σε όλα τα χρονολόγια, ακόμα κι αν δεν είναι ενεργοποιημένα.
inMb: Σε megabytes
iconUrl: Διεύθυνση URL εικονιδίου
bannerUrl: Διεύθυνση URL εικόνας Εξώφυλλου
pinnedUsers: Καρφιτσωμένα μέλη
hcaptchaSiteKey: Κλειδί του site
recaptcha: Προστασία reCAPTCHA
enableServiceworker: Ενεργοποίηση Ειδοποιήσεων Push για τον browser σας
recentlyDiscoveredUsers: Μέλη που ανακαλύφθηκαν πρόσφατα
twoStepAuthentication: Επαλήθευση δύο παραγόντων
securityKey: Κλειδί ασφάλειας
registerSecurityKey: Καταχωρήστε ένα κλειδί ασφάλειας
resetPassword: Επαναφορά κωδικού
newPasswordIs: Ο νέος κωδικός είναι "{password}"
uploadFolder: Προεπιλεγμένος φάκελος για ανέβασμα αρχείων
joinedGroups: Οι ομάδες που είστε μέλος
checking: Έλεγχος...
invitationCode: Κωδικός πρόσκλησης
normalPassword: Μέτριος κωδικός
weakPassword: Αδύναμος κωδικός
strongPassword: Δυνατός κωδικός
signinWith: Συνδεθείτε με {x}
tapSecurityKey: Βάλτε το κλειδί ασφάλειας
signinFailed: Αδυναμία σύνδεσης. Το όνομα μέλους ή ο κωδικός είναι λάθος.
aboutX: Σχετικά με {x}
useOsNativeEmojis: Χρήση των Emoji του λειτουργικού συστήματος
uiLanguage: Γλώσσα διεπαφής
disableDrawer: Να μη χρησιμοποιούνται μενού σε στιλ συρταριού
noHistory: Δεν υπάρχει διαθέσιμο ιστορικό
joinOrCreateGroup: Λάβετε πρόσκληση για μία ομάδα ή δημιουργήστε τη δική σας.
docSource: Πηγή αυτού του εγγράφου
regenerate: Επαναδημιουργία
fontSize: Μέγεθος γραμματοσειράς
noFollowRequests: Δεν έχετε αιτήματα ακολούθησης σε αναμονή
dashboard: Ταμπλό
clientSettings: Ρυθμίσεις διεπαφής
numberOfDays: Αριθμός ημερών
hideThisNote: Απόκρυψη αυτής της δημοσίευσης
showFeaturedNotesInTimeline: Εμφάνιση προτεινόμενων δημοσιεύσεων στα χρονολόγια
objectStorage: Αποθήκευση Object Storage
useObjectStorage: Χρήση object storage
objectStorageBucket: ''
showFixedPostForm: Εμφάνιση της φόρμας δημοσίευσης στο πάνω μέρος των χρονολογίων
none: Κανένα
unableToProcess: Η επιχείρηση ήταν αδύνατο να ολοκληρωθεί
installedApps: Εφαρμογές με εξουσιοδότηση
state: Κατάσταση
installedDate: Εξουσιοδοτήθηκε στις
lastUsedDate: Χρησιμοποιήθηκε τελευταία φορά στις
scratchpadDescription: Το σημειωματάριο παρέχει ένα περιβάλλον για πειραματισμό με
AiScript. Σε αυτό μπορείτε να γράψετε, να εκτελέσετε, και να δοκιμάσετε τα αποτελέσματα
της αλληλεπίδρασης του AiScript με το Calckey.
scratchpad: Σημειωματάριο
output: Αποτέλεσμα
updateRemoteUser: Ανανέωση πληροφοριών απομακρυσμένου μέλους
disablePagesScript: Απενεργοποίηση του AiScript στις Σελίδες
removeAllFollowingDescription: Η εκτέλεση θα διακόψη την ακολούθηση όλων των μελών
από {host}. Παρακαλούμε εκτελέστε το αν το instance π.χ. δεν υπάρχει πια.
caption: Αυτόματη Περιγραφή
all: Όλα
subscribing: Εγγραφή σε συνδρομή
publishing: Δημοσιεύεται
notResponding: Δεν αποκρίνεται
keepOriginalUploadingDescription: Αποθηκεύει το πρωτότυπο αρχείο όπως είναι. Αν απενεργοποιηθεί,
μία έκδοση για προβολή στο ίντερνετ θα δημιουργηθεί κατά το ανέβασμα.
lookup: Αναζήτηση
lightThemes: Φωτεινά θέματα
darkThemes: Σκοτεινά θέματα
inputNewFolderName: Πληκτρολογήστε ένα νέο όνομα φακέλου
hasChildFilesOrFolders: Εφόσον αυτός ο φάκελος δεν είναι άδειος, δεν μπορεί να διαγραφεί.
integration: Ενσωματώσεις
enableRecommendedTimeline: Ενεργοποίηση χρονολογίου προτεινόμενων
driveCapacityPerLocalAccount: Μέγεθος Αποθηκευτικού Χώρου ανά τοπικό μέλος
driveCapacityPerRemoteAccount: Μέγεθος Αποθηκευτικού Χώρου ανά απομακρυσμένο μέλος
basicInfo: Βασικές πληροφορίες
pinnedClipId: Ταυτότητα (id) του κλιπ για καρφίτσωμα
hcaptcha: Προστασία hCaptcha
enableHcaptcha: Ενεργοποίηση hCaptcha
hcaptchaSecretKey: Μυστικό κλειδί
enableRecaptcha: Ενεργοποίηση reCAPTCHA
recaptchaSiteKey: Κλειδί του site
recaptchaSecretKey: Μυστικό κλειδί
antennaKeywordsDescription: Διαχωρίστε με κενά για συνθήκη ΚΑΙ ή με αλλαγή γραμμής
για συνθήκη Ή.
antennaUsersDescription: Παραθέστε ένα όνομα μέλους ανά γραμμή
antennaInstancesDescription: Παραθέστε ένα instance host ανά γραμμή
withReplies: Να περιλαμβάνονται οι απαντήσεις
withFiles: Να περιλαμβάνουν αρχεία
silence: Σιώπηση
silenceConfirm: Θέλετε σίγουρα να σιωπήσετε αυτό το μέλος;
unsilenceConfirm: Σίγουρα θέλετε να αναιρέσετε τη σιώπηση αυτού του μέλους;
securityKeyName: Όνομα κλειδιού
lastUsed: Τελευταία χρήση
unregister: Απεγγραφή
notFoundDescription: Δεν ήταν δυνατό να βρεθεί σελίδα που να ανταποκρίνεται σε αυτή
τη διεύθυνση URL.
signinHistory: Ιστορικό συνδέσεων
disableAnimatedMfm: Απενεργοποίηση του MFM με κίνηση
dayOverDayChanges: Αλλαγές την τελευταία ημέρα
promotion: Προμοταρισμένα
promote: Προμοτάρισμα
squareAvatars: Εμφάνιση τετραγωνισμένων άβαταρ
aboutMisskey: Σχετικά με το Calckey
maintainerName: Προγραμματιστής/στρια
uploadFromUrlRequested: Το ανέβασμα ζητήθηκε
themeForLightMode: Θέμα για τη Φωτεινή Λειτουργία
circularReferenceFolder: Ο φάκελος του προορισμού είναι υποφάκελος του φακέλου που
θέλετε να μετακινήσετε.
backgroundImageUrl: Διεύθυνση URL εικόνας φόντου
pinnedUsersDescription: Παραθέστε τα ονόματα μελών που θα είναι καρφιτσωμένα στην
καρτέλα "Εξερεύνηση" χωρίζοντάς τα με αλλαγή γραμμής.
openImageInNewTab: Άνοιγμα εικόνων σε νέα καρτέλα
weekOverWeekChanges: Αλλαγές την τελευταία εβδομάδα
exploreFediverse: Εξερευνήστε το Fediverse
unsilence: Αναίρεση σιώπησης
administrator: Διαχειριστής/στρια
passwordLessLogin: Σύνδεση χωρίς κωδικό
reduceUiAnimation: Ελάττωση των κινούμενων εικόνων
serviceworkerInfo: Πρέπει να είναι ενεργοποιημένο για ειδοποιήσεις push.
expandTweet: Διεύρυνση τουιτ
themeEditor: Επεξεργασία θεμάτων
deck: Ντεκ
undeck: Έξοδος από το Ντεκ
useFullReactionPicker: Χρήση επιλογέα αντιδράσεων πλήρους μεγέθους
tokenRequested: Παροχή πρόσβασης στον λογαριασμό
emailServer: Σέρβερ email
enableEmail: Ενεργοποίηση του email distribution
emailAddress: Διεύθυνση email
emailConfigInfo: Χρησιμοποιείται για επιβεβαίωση του email σας κατά την εγγραφή ή
αν ξεχάσετε τον κωδικό σας
regenerateLoginToken: Επαναδημιουργία token σύνδεσης
fileIdOrUrl: Ταυτότητα αρχείου (ID) ή διεύθυνση URL
typingUsers: '{users} πληκτρολογεί'
yourAccountSuspendedDescription: Αυτός ο λογαριασμός έχει αποβληθεί λόγω μη συμμόρφωσης
με τους κανόνες του σέρβερ ή κάτι παρόμοιο. Επικοινωνήστε με τον διαχειριστή/στρια
αν θα θέλατε έναν πιο λεπτομερή λόγο. Παρακαλούμε μη δημιουργήσετε νέο λογαριασμό.
inboxUrl: Διεύθυνση URL των Εισερχομένων
generateAccessToken: Δημιουργία token πρόσβασης
emptyToDisableSmtpAuth: Αφήστε το όνομα μέλους και τον κωδικό άδεια για να απενεργοποιήσετε
την επαλήθευση SMTP
instanceMute: Σιγάσεις instance
userSaysSomethingReason: '{name} είπε {reason}'
logs: Αρχεία καταγραφής
abuseReported: Η αναφορά σας στάλθηκε. Ευχαριστούμε πολύ.
reporter: Έκανε την αναφορά
reporteeOrigin: Καταγωγή αναφερόμενου λογαριασμού
reporterOrigin: Καταγωγή λογαριασμού που έκανε την αναφορά
forwardReport: Προώθηση της αναφοράς στο απομακρυσμένο instance
openInSideView: Άνοιγμα σε προβολή παράθεσης
delayed: Με καθυστέρηση
useGlobalSettingDesc: Αν ενεργοποιηθεί, οι ρυθμίσεις ειδοποιήσεων του λογαριασμού
σας θα χρησιμοποιηθούν. Αν απενεργοποιηθεί, μπορούν να γίνουν ανεξάρτητες ρυθμίσεις.
fillAbuseReportDescription: Παρακαλούμε συμπληρώστε λεπτομέρειες σχετικά με αυτή την
αναφορά. Αν πρόκειται για συγκεκριμένη δημοσίευση, παρακαλούμε συμπεριλάβετε τη
διεύθυνση URL της δημοσίευσης.
forwardReportIsAnonymous: Αντί για τον λογαριασμό σας, μία ανώνυμη αναφορά από λογαριασμό
του συστήματος θα εμφανιστεί στο απομακρυσμένο instance.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,970 +0,0 @@
_lang_: "Suomi"
username: Käyttäjänimi
fetchingAsApObject: Hae Fedeversestä
gotIt: Selvä!
cancel: Peruuta
enterUsername: Anna käyttäjänimi
renotedBy: Buustannut {user}
noNotes: Ei lähetyksiä
noNotifications: Ei ilmoituksia
instance: Instanssi
settings: Asetukset
basicSettings: Perusasetukset
otherSettings: Muut asetukset
openInWindow: Avaa ikkunaan
profile: Profiili
timeline: Aikajana
noAccountDescription: Käyttäjä ei ole vielä kirjoittanut kuvaustaan vielä.
login: Kirjaudu sisään
loggingIn: Kirjautuu sisään
logout: Kirjaudu ulos
uploading: Tallentaa ylös...
save: Tallenna
favorites: Kirjanmerkit
unfavorite: Poista kirjanmerkeistä
favorited: Lisätty kirjanmerkkeihin.
alreadyFavorited: Lisätty jo kirjanmerkkeihin.
cantFavorite: Ei voitu lisätä kirjanmerkkeihin.
pin: Kiinnitä profiiliin
unpin: Irroita profiilista
delete: Poista
forgotPassword: Unohtunut salasana
search: Etsi
notifications: Ilmoitukset
password: Salasana
ok: OK
noThankYou: Ei kiitos
signup: Rekisteröidy
users: Käyttäjät
addUser: Lisää käyttäjä
addInstance: Lisää instanssi
favorite: Lisää kirjanmerkkeihin
copyContent: Kopioi sisältö
deleteAndEdit: Poista ja muokkaa
copyLink: Kopioi linkki
makeFollowManuallyApprove: Seuraajapyyntö vaatii hyväksymistä
follow: Seuraa
pinned: Kiinnitä profiiliin
followRequestPending: Seuraajapyyntö odottaa
you: Sinä
unrenote: Peruuta buustaus
reaction: Reaktiot
reactionSettingDescription2: Vedä uudelleenjärjestelläksesi, napsauta poistaaksesi,
paina "+" lisätäksesi.
attachCancel: Poista liite
enterFileName: Anna tiedostonimi
mute: Hiljennä
unmute: Poista hiljennys
headlineMisskey: Avoimen lähdekoodin, hajautettu sosiaalisen median alusta, joka on
ikuisesti ilmainen! 🚀
monthAndDay: '{day}/{month}'
deleteAndEditConfirm: Oletko varma, että haluat poistaa tämän lähetyksen ja muokata
sitä? Menetät kaikki reaktiot, buustaukset ja vastaukset lähetyksestäsi.
addToList: Lisää listaan
sendMessage: Lähetä viesti
reply: Vastaa
loadMore: Lataa enemmän
showMore: Näytä enemmän
receiveFollowRequest: Seuraajapyyntö vastaanotettu
followRequestAccepted: Seuraajapyyntö hyväksytty
mentions: Maininnat
importAndExport: Tuo/Vie Tietosisältö
import: Tuo
export: Vie
files: Tiedostot
download: Lataa
unfollowConfirm: Oletko varma, ettet halua seurata enää käyttäjää {name}?
noLists: Sinulla ei ole listoja
note: Viesti
notes: Viestit
following: Seuraa
createList: Luo lista
manageLists: Hallitse listoja
error: Virhe
somethingHappened: On tapahtunut virhe
retry: Yritä uudelleen
pageLoadError: Virhe ladattaessa sivua.
serverIsDead: Tämä palvelin ei vastaa. Yritä hetken kuluttua uudelleen.
youShouldUpgradeClient: Nähdäksesi tämän sivun, virkistä päivittääksesi asiakasohjelmasi.
privacy: Tietosuoja
defaultNoteVisibility: Oletusnäkyvyys
followRequest: Seuraajapyyntö
followRequests: Seuraajapyynnöt
unfollow: Poista seuraaminen
enterEmoji: Syötä emoji
renote: Buustaa
renoted: Buustattu.
cantRenote: Tätä lähetystä ei voi buustata.
cantReRenote: Buustausta ei voi buustata.
quote: Lainaus
pinnedNote: Lukittu lähetys
clickToShow: Napsauta nähdäksesi
sensitive: Herkkää sisältöä (NSFW)
add: Lisää
enableEmojiReactions: Ota käyttöön emoji-reaktiot
showEmojisInReactionNotifications: Näytä emojit reaktioilmoituksissa
reactionSetting: Reaktiot näytettäväksi reaktiovalitsimessa
rememberNoteVisibility: Muista lähetyksen näkyvyysasetukset
markAsSensitive: Merkitse herkäksi sisällöksi (NSFW)
unmarkAsSensitive: Poista merkintä herkkää sisältöä (NSFW)
renoteMute: Hiljennä buustit
renoteUnmute: Poista buustien hiljennys
block: Estä
unblock: Poista esto
unsuspend: Poista keskeytys
suspend: Keskeytys
blockConfirm: Oletko varma, että haluat estää tämän tilin?
unblockConfirm: Oletko varma, että haluat poistaa tämän tilin eston?
selectAntenna: Valitse antenni
selectWidget: Valitse vimpain
editWidgets: Muokkaa vimpaimia
editWidgetsExit: Valmis
emoji: Emoji
emojis: Emojit
emojiName: Emojin nimi
emojiUrl: Emojin URL-linkki
cacheRemoteFiles: Taltioi etätiedostot välimuistiin
flagAsBot: Merkitse tili botiksi
flagAsBotDescription: Ota tämä vaihtoehto käyttöön, jos tätä tiliä ohjaa ohjelma.
Jos se on käytössä, se toimii lippuna muille kehittäjille, jotta estetään loputtomat
vuorovaikutusketjut muiden bottien kanssa ja säädetään Calckeyn sisäiset järjestelmät
käsittelemään tätä tiliä botina.
flagAsCat: Oletko kissa? 🐱
flagAsCatDescription: Saat kissan korvat ja puhut kuin kissa!
flagSpeakAsCat: Puhu kuin kissa
flagShowTimelineReplies: Näytä vastaukset aikajanalla
addAccount: Lisää tili
loginFailed: Kirjautuminen epäonnistui
showOnRemote: Katsele etäinstanssilla
general: Yleistä
accountMoved: 'Käyttäjä on muuttanut uuteen tiliin:'
wallpaper: Taustakuva
setWallpaper: Aseta taustakuva
searchWith: 'Etsi: {q}'
youHaveNoLists: Sinulla ei ole listoja
followConfirm: Oletko varma, että haluat seurata käyttäjää {name}?
host: Isäntä
selectUser: Valitse käyttäjä
annotation: Kommentit
registeredAt: Rekisteröity
latestRequestReceivedAt: Viimeisin pyyntö vastaanotettu
latestRequestSentAt: Viimeisin pyyntö lähetetty
storageUsage: Tallennustilan käyttö
charts: Kaaviot
stopActivityDelivery: Lopeta toimintojen lähettäminen
blockThisInstance: Estä tämä instanssi
operations: Toiminnot
metadata: Metatieto
monitor: Seuranta
jobQueue: Työjono
cpuAndMemory: Prosessori ja muisti
network: Verkko
disk: Levy
clearCachedFiles: Tyhjennä välimuisti
clearCachedFilesConfirm: Oletko varma, että haluat tyhjentää kaikki välimuistiin tallennetut
etätiedostot?
blockedInstances: Estetyt instanssit
hiddenTags: Piilotetut asiatunnisteet
mention: Maininta
copyUsername: Kopioi käyttäjänimi
searchUser: Etsi käyttäjää
showLess: Sulje
youGotNewFollower: seurasi sinua
directNotes: Yksityisviestit
driveFileDeleteConfirm: Oletko varma, että haluat poistaa tiedoston " {name}"? Se
poistetaan kaikista viesteistä, jotka sisältävät sen liitetiedostona.
importRequested: Olet pyytänyt viemistä. Tämä voi viedä hetken.
exportRequested: Olet pyytänyt tuomista. Tämä voi viedä hetken. Se lisätään asemaan
kun tuonti valmistuu.
lists: Listat
followers: Seuraajat
followsYou: Seuraa sinua
pageLoadErrorDescription: Tämä yleensä johtuu verkkovirheistä tai selaimen välimuistista.
Kokeile tyhjentämällä välimuisti ja yritä sitten hetken kuluttua uudelleen.
enterListName: Anna listalle nimi
instanceInfo: Instanssin tiedot
clearQueue: Tyhjennä jono
suspendConfirm: Oletko varma, että haluat keskeyttää tämän tilin?
unsuspendConfirm: Oletko varma, että haluat poistaa tämän tilin keskeytyksen?
selectList: Valitse lista
customEmojis: Kustomoitu Emoji
addEmoji: Lisää
settingGuide: Suositellut asetukset
cacheRemoteFilesDescription: Kun tämä asetus ei ole käytössä, etätiedostot on ladattu
suoraan etäinstanssilta. Asetuksen poistaminen käytöstä vähentää tallennustilan
käyttöä, mutta lisää verkkoliikennettä kun pienoiskuvat eivät muodostu.
flagSpeakAsCatDescription: Lähetyksesi nyanifioidaan, kun olet kissatilassa
flagShowTimelineRepliesDescription: Näyttää käyttäjien vastaukset muiden käyttäjien
lähetyksiin aikajanalla, jos se on päällä.
autoAcceptFollowed: Automaattisesti hyväksy seuraamispyynnöt käyttäjiltä, joita seuraat
perHour: Tunnissa
removeWallpaper: Poista taustakuva
recipient: Vastaanottaja(t)
federation: Federaatio
software: Ohjelmisto
proxyAccount: Proxy-tili
proxyAccountDescription: Välitystili (Proxy-tili) on tili, joka toimii käyttäjien
etäseuraajana tietyin edellytyksin. Kun käyttäjä esimerkiksi lisää etäkäyttäjän
luetteloon, etäkäyttäjän toimintaa ei toimiteta instanssiin, jos yksikään paikallinen
käyttäjä ei seuraa kyseistä käyttäjää, joten välitystili seuraa sen sijaan.
latestStatus: Viimeisin tila
selectInstance: Valitse instanssi
instances: Instanssit
perDay: Päivässä
version: Versio
statistics: Tilastot
clearQueueConfirmTitle: Oletko varma, että haluat tyhjentää jonon?
introMisskey: Tervetuloa! Calckey on avoimen lähdekoodin, hajautettu sosiaalisen median
alusta, joka on ikuisesti ilmainen! 🚀
clearQueueConfirmText: Mitkään välittämättömät lähetykset, jotka ovat jonossa, eivät
federoidu. Yleensä tätä toimintoa ei tarvita.
blockedInstancesDescription: Lista instanssien isäntänimistä, jotka haluat estää.
Listatut instanssit eivät kykene kommunikoimaan enää tämän instanssin kanssa.
security: Turvallisuus
retypedNotMatch: Syöte ei kelpaa.
fromDrive: Asemasta
keepOriginalUploading: Säilytä alkuperäinen kuva
uploadFromUrlDescription: Tiedoston URL, jonka haluat ylösladata
themeForLightMode: Teema vaaleassa tilassa
theme: Teemat
themeForDarkMode: Teema tummassa tilassa
drive: Asema
darkThemes: Tummat teemat
copyUrl: Kopioi URL-linkki
rename: Uudelleennimeä
maintainerName: Ylläpitäjä
maintainerEmail: Ylläpitäjän sähköposti
tosUrl: Palvelun ehdot URL-linkki
thisYear: Vuosi
backgroundImageUrl: Taustakuvan URL-linkki
basicInfo: Perustiedot
pinnedPagesDescription: Kirjoita niiden sivujen polut, jotka haluat liittää tämän
instanssin yläsivulle rivinvaihdoin erotettuna.
hcaptchaSiteKey: Sivuston avain
hcaptchaSecretKey: Salausavain
silencedInstances: Hiljennetyt instanssit
muteAndBlock: Hiljennykset ja estetyt
mutedUsers: Hiljennetyt käyttäjät
blockedUsers: Estetyt käyttäjät
noUsers: Ei yhtään käyttäjää
noInstances: Ei yhtään instanssia
editProfile: Muokkaa profiilia
noteDeleteConfirm: Oletko varma, että haluat poistaa tämän viestin?
pinLimitExceeded: Et voi kiinnittää enempää viestejä
intro: Calckey -asennus valmis! Ole hyvä ja luo admin-käyttäjä.
done: Valmis
processing: Suorittaa
preview: Esikatselu
default: Oletus
defaultValueIs: 'Oletus: {value}'
noCustomEmojis: Ei emojia
noJobs: Ei töitä
federating: Federoi
blocked: Estetty
silenced: Hiljennetty
suspended: Keskeytetty
all: Kaikki
publishing: Julkaisee
subscribing: Tilaa
notResponding: Ei vastaa
instanceFollowing: Seuraa instanssia
instanceFollowers: Instanssin seuraajat
instanceUsers: Instanssin käyttäjät
changePassword: Muuta salasana
newPasswordRetype: Uudelleensyötä uusi salasana
more: Lisää!
featured: Esillä
usernameOrUserId: Käyttäjänimi tai käyttäjä id
noSuchUser: Käyttäjää ei löydy
lookup: Hae
announcements: Tiedoitteet
imageUrl: Kuva URL-linkki
removed: Onnistuneesti poistettu
removeAreYouSure: Oletko varma, että haluat poistaa " {x}"?
resetAreYouSure: Haluatko nollata?
saved: Tallennettu
messaging: Juttele
upload: Lataa ylös
fromUrl: URL:stä
uploadFromUrl: Ylöslataa URL:stä
uploadFromUrlRequested: Ylöslataus pyydetty
uploadFromUrlMayTakeTime: Voi viedä hetki, kun ylöslataus on valmis.
explore: Tutustu
messageRead: Lue
noMoreHistory: Ei lisää historiaa
startMessaging: Aloita uusi juttelu
manageGroups: Hallitse ryhmiä
nUsersRead: lukenut {n}
agreeTo: Hyväksyn {0}
tos: Palvelun ehdot
start: Aloita
home: Koti
remoteUserCaution: Etäkäyttäjän tiedot saattavat olla puutteellisia.
light: Vaalea
dark: Tumma
lightThemes: Vaaleat teemat
syncDeviceDarkMode: Synkronoi tumma tila laitteen asetuksen mukaan
fileName: Tiedostonimi
selectFile: Valitse tiedosto
selectFiles: Valitse tiedostot
selectFolder: Valitse kansio
selectFolders: Valitse kansiot
renameFile: Uudelleennimeä tiedosto
folderName: Kansionimi
createFolder: Luo kansio
renameFolder: Uudelleennimeä kansio
deleteFolder: Poista kansio
addFile: Lisää tiedosto
emptyDrive: Asemasi on tyhjä
emptyFolder: Tämä kansio on tyhjä
unableToDelete: Ei voitu poistaa
inputNewFileName: Syötä uusi tiedostonimi
inputNewDescription: Syötä uusi kuvateksti
inputNewFolderName: Syötä uusi kansionimi
hasChildFilesOrFolders: Koska kansio ei ole tyhjä, sitä ei voi poistaa.
avatar: Kuvake
banner: Banneri
nsfw: Herkkää sisältöä (NSFW)
whenServerDisconnected: Kun yhteys palvelimeen menetetään
disconnectedFromServer: Yhteys palvelimeen katkennut
reload: Päivitä
doNothing: Hylkää
reloadConfirm: Haluaisitko päivittää aikajanan?
unwatch: Lopeta katselu
watch: Katsele
accept: Hyväksy
reject: Hylkää
normal: Normaali
instanceName: Instanssin nimi
thisMonth: Kuukausi
today: Tänään
monthX: '{month}'
connectService: Yhdistä
disconnectService: Katkaise yhteys
enableLocalTimeline: Ota käyttöön paikallinen aikajana
enableGlobalTimeline: Ota käyttöön globaali aikajana
enableRecommendedTimeline: Ota käyttöön suositellut -aikajana
registration: Rekisteröinti
enableRegistration: Ota käyttöön uuden käyttäjän rekisteröinti
driveCapacityPerLocalAccount: Aseman kapasiteetti paikallista käyttäjää kohti
driveCapacityPerRemoteAccount: Aseman kapasiteetti etäkäyttäjää kohti
inMb: megatavuissa
bannerUrl: Bannerikuvan URL-linkki
pinnedUsers: Kiinnitetyt käyttäjät
pinnedPages: Kiinnitetyt sivut
pinnedClipId: Kiinnitettävän leikkeen ID
enableHcaptcha: Ota käyttöön hCaptcha-tunnistus
recaptcha: CAPTCHA uudelleen
enableRecaptcha: Ota käyttöön CAPTCHA uudelleen
recaptchaSiteKey: Sivuston avain
recaptchaSecretKey: Salausavain
silenceThisInstance: Hiljennä tämä instanssi
silencedInstancesDescription: Lista isäntänimistä, joka haluat hiljentää. Tilejä listassa
kohdellaan "hiljennettynä", ne voivat tehdä seuraajapyyntöjä ja eivät voi tehdä
mainintoja paikallistileistä jossei seurattu. Tämä ei vaikuta estettyihin instansseihin.
hiddenTagsDescription: 'Listaa aihetunnisteet (ilman #-merkkiä) aihetunnisteet, jotka
haluat piilottaa trendaavista ja Tutustu-osiosta. Piilotetut aihetunnisteet ovat
kuitenkin löydettävissä muilla keinoilla. Estetyt instanssit eivät vaikuta, vaikka
listattu tähän.'
currentPassword: Nykyinen salasana
newPassword: Uusi salasana
attachFile: Liitetyt tiedostot
keepOriginalUploadingDescription: Tallentaa alkuperäisen kuvan sellaisenaan. Jos kytketty
päältä, webissä näytettävä versio luodaan ylöslatauksen yhteydessä.
remove: Poista
circularReferenceFolder: Kohdekansio on kansion alikansio, jonka haluat siirtää.
deleteAreYouSure: Oletko varma, että haluat poistaa kokonaan" {x}"?
yearsOld: '{age} vuotias'
activity: Aktiivisuus
images: Kuvat
birthday: Syntymäpäivä
registeredDate: Liittynyt
location: Sijainti
disablingTimelinesInfo: Järjestelmänvalvojilla ja moderaattoreilla on aina pääsy kaikille
aikajanoille, vaikka olisikin poistettu käytöstä.
dayX: '{day}'
yearX: '{year}'
pages: Sivut
integration: Integraatiot
instanceDescription: Instanssin kuvaus
invite: Kutsu
iconUrl: Ikoni URL-linkki
pinnedUsersDescription: Listaa käyttäjänimet eroteltuna rivivaihdoin kiinnittääksesi
ne "Tutustu" välilehteen.
pinnedNotes: Kiinnitetyt viestit
hcaptcha: hCaptcha-tunnistus
antennaSource: Antennin lähde
invitationCode: Kutsukoodi
checking: Tarkistetaan...
passwordNotMatched: Ei vastaa
doing: Käsittelee...
category: Kategoria
tags: Tagit
disableAnimatedMfm: Poista MFM -animaatiot käytöstä
openImageInNewTab: Avaa kuvat uuteen välilehteen
dashboard: Kojelauta
local: Paikallinen
remote: Etä
total: Yhteensä
weekOverWeekChanges: Muutokset viime viikkoon
objectStorageRegion: Alue
popout: Ulosvedettävä
volume: Äänenvoimakkuus
masterVolume: Master äänenvoimakkuus
details: Yksityiskohdat
chooseEmoji: Valitse emoji
descendingOrder: Laskevasti
scratchpad: Raaputusalusta
output: Ulostulo
invisibleNote: Näkymätön viesti
enableInfiniteScroll: Lataa enemmän automaattisesti
visibility: Näkyvyys
useCw: Piilota sisältö
poll: Kysely
enablePlayer: Avaa videotoistimeen
enterFileDescription: Syötä tiedostokuvaus
author: Kirjoittaja
manage: Hallinta
description: Kuvaus
describeFile: Lisää tiedostokuvaus
height: Korkeus
large: Suuri
medium: Keskikokoinen
small: Pieni
other: Muu
create: Luo
regenerateLoginTokenDescription: Luo uudelleen kirjautumisen aikana sisäisesti käytettävän
tunnuksen. Normaalisti tämä toiminto ei ole tarpeen. Jos tunniste luodaan uudelleen,
kaikki laitteet kirjautuvat ulos.
setMultipleBySeparatingWithSpace: Erottele useat merkinnät välilyönneillä.
fileIdOrUrl: Tiedosto ID tai URL-linkki
behavior: Käytös
instanceTicker: Viestejä koskevat instanssitiedot
waitingFor: Odottaa {x}
random: Satunnainen
system: Järjestelmä
switchUi: Ulkoasu
createNew: Luo uusi
followersCount: Seuraajien määrä
renotedCount: Saatujen buustausten määrä
followingCount: Seurattujen tilien määrä
notSet: Ei asetettu
nUsers: '{n} Käyttäjää'
nNotes: '{n} Viestiä'
sendErrorReports: Lähetä virheraportteja
backgroundColor: Taustaväri
accentColor: Korostusväri
textColor: Tekstin väri
advanced: Edistynyt
saveAs: Tallenna nimellä...
invalidValue: Epäkelpo arvo.
registry: Rekisteri
closeAccount: Sulje tili
currentVersion: Nykyinen versio
capacity: Kapasiteetti
clear: Palaa
_theme:
explore: Tutustu teemoihin
silenceConfirm: Oletko varma, että haluat hiljentää tämän käyttäjän?
notesAndReplies: Viestit ja vastaukset
withFiles: Tiedostot sisältyvät
silence: Hiljennä
popularTags: Suositut tagit
userList: Listat
about: Tietoja
aboutMisskey: Tietoja Calckeystä
exploreFediverse: Tutustu fediverseen
recentlyUpdatedUsers: Vastikään lisätyt käyttäjät
recentlyRegisteredUsers: Uudet liittyneet jäyttäjät
recentlyDiscoveredUsers: Vastikään löydetyt käyttäjät
exploreUsersCount: Täällä on {count} käyttäjää
share: Jaa
moderation: Sisällön valvonta
nUsersMentioned: Mainittu {n} käyttäjältä
securityKey: Turva-avain
securityKeyName: Avainnimi
registerSecurityKey: Rekisteröi turva-avain
lastUsed: Viimeksi käytetty
unregister: Poista rekisteröinti
passwordLessLogin: Salasanaton sisäänkirjautuminen
cacheClear: Tyhjennä välimuisti
markAsReadAllNotifications: Merkitse kaikki ilmoitukset luetuksi
markAsReadAllUnreadNotes: Merkitse kaikki viestit luetuiksi
uploadFolder: Oletuskansio ylöslatauksille
createGroup: Luo ryhmä
group: Ryhmä
groups: Ryhmät
ownedGroups: Omistetut ryhmät
help: Apua
inputMessageHere: Syötä viesti tähän
close: Sulje
joinedGroups: Liittyneet ryhmät
invites: Kutsut
groupName: Ryhmänimi
members: Jäsenet
language: Kieli
signinHistory: Kirjautumishistoria
docSource: Tämän dokumentin lähde
createAccount: Luo tili
existingAccount: Olemassa oleva tili
promotion: Edistetty
promote: Edistää
numberOfDays: Päivien määrä
accountSettings: Tilin asetukset
objectStorage: Objektitallennus
useObjectStorage: Käytä objektitallennusta
objectStorageBaseUrl: Perus URL-linkki
objectStorageBaseUrlDesc: "Viitteenä käytetty URL-linkki. Määritä CDN:n tai välityspalvelimen\
\ URL-linkki, jos käytät kumpaakin.\nKäytä S3:lle 'https://<bucket>.s3.amazonaws.com'\
\ ja GCS:lle tai vastaaville palveluille 'https://storage.googleapis.com/<bucket>'\
\ jne."
objectStorageBucket: Kauha
newNoteRecived: Uusia viestejä
smtpPort: Portti
instanceMute: Instanssin mykistys
repliesCount: Lähetettyjen vastausten määrä
updatedAt: Päivitetty
notFound: Ei löydy
useOsNativeEmojis: Käytä käyttöjärjestelmän natiivi-Emojia
joinOrCreateGroup: Tule kutsutuksi ryhmään tai luo oma ryhmä.
text: Teksti
usernameInvalidFormat: Käytä isoja ja pieniä kirjaimia, numeroita ja erikoismerkkejä.
unsilenceConfirm: Oletko varma, että haluat poistaa käyttäjän hiljennyksen?
popularUsers: Suositut käyttäjät
moderator: Moderaattori
twoStepAuthentication: Kaksivaiheinen tunnistus
notFoundDescription: URL-linkkiin liittyvää sivua ei löytynyt.
antennaKeywords: Kuunneltavat avainsanat
antennaExcludeKeywords: Poislasketut avainsanat
antennaKeywordsDescription: Erottele välilyönneillä AND-ehtoa varten tai rivinvaihdolla
OR-ehtoa varten.
notifyAntenna: Ilmoita uusista viesteistä
withFileAntenna: Vain viestit tiedoston kanssa
enableServiceworker: Ota käyttöön Push-notifikaatiot selaimessasi
antennaUsersDescription: Luettele yksi käyttäjänimi rivi kohti
antennaInstancesDescription: Luettele yksi instanssi riviä kohti
caseSensitive: Isot ja pienet kirjaimet
withReplies: Sisällytä vastaukset
connectedTo: Seuraavat tili(t) on yhdistetty
unsilence: Poista hiljennys
administrator: Järjestelmänvalvoja
token: Merkki
resetPassword: Resetoi salasana
reduceUiAnimation: Vähennä käyttöliittymän animaatioita
transfer: Siirrä
messagingWithUser: Yksityisjuttelu
title: Otsikko
enable: Ota käyttöön
next: Seuraava
retype: Syötä uudelleen
noteOf: Lähettänyt {user}
inviteToGroup: Kutsu ryhmään
quoteAttached: Lainaus
quoteQuestion: Liitä lainauksena?
noMessagesYet: Ei vielä viestejä
newMessageExists: Uusia viestejä
onlyOneFileCanBeAttached: Voit liittää vain yhden tiedoston viestiin
signinRequired: Ole hyvä ja rekisteröidy tai kirjaudu sisään jatkaaksesi
invitations: Kutsut
available: Saatavilla
unavailable: Ei saatavissa
tooShort: Liian lyhyt
tooLong: Liian pitkä
weakPassword: Heikko salasana
normalPassword: Kohtalainen salasana
strongPassword: Vahva salasana
passwordMatched: Vastaa
signinWith: Kirjaudu sisään {x}
signinFailed: Ei voitu kirjautua sisään. Annettu käyttäjänimi tai salasana virheellinen.
tapSecurityKey: Napsauta turva-avaintasi
or: Tai
uiLanguage: Anna käyttöliittymän kieli
groupInvited: Sinut on kutsuttu ryhmään
aboutX: Tietoja {x}
disableDrawer: Älä käytä laatikkotyyppisiä valikoita
youHaveNoGroups: Sinulla ei ole ryhmiä
noHistory: Ei historiaa saatavilla
regenerate: Uudelleenluo
fontSize: Kirjasinkoko
dayOverDayChanges: Muutokset eiliseen
clientSettings: Asiakkaan asetukset
hideThisNote: Piilota tämä viesti
showFeaturedNotesInTimeline: Näytä esillä olevat viestit aikajanalla
objectStorageBucketDesc: Määritä palveluntarjoajasi käyttämä kauhan nimi.
objectStoragePrefix: Etuliite
objectStorageEndpoint: Päätepiste
objectStorageRegionDesc: Määritä alue, kuten "xx-east-1". Jos palvelusi ei tee eroa
alueiden välillä, jätä tämä kohta tyhjäksi tai kirjoita "us-east-1".
objectStorageUseSSL: Käytä SSL-salausta
objectStorageUseSSLDesc: Poista tämä käytöstä, jos et aio käyttää HTTPS:ää API-yhteyksissä
objectStorageUseProxy: Yhdistä välityspalvelimen kautta
objectStorageUseProxyDesc: Poista tämä käytöstä, jos et aio käyttää välityspalvelinta
API-yhteyksiä varten
objectStorageSetPublicRead: Aseta "public-read" ylöslataukseen
serverLogs: Palvelimen lokit
deleteAll: Poista kaikki
showFixedPostForm: Näytä viesti-ikkuna aikajanan yläpuolella
sounds: Äänet
listen: Kuuntele
none: Ei mitään
showInPage: Näytä sivulla
recentUsed: Vastikään käytetty
install: Asenna
uninstall: Poista asennus
installedApps: Hyväksytyt sovellukset
nothing: Ei nähtävää täällä
state: Tila
sort: Järjestä
ascendingOrder: Nousevasti
scratchpadDescription: Raaputusalusta tarjoaa ympäristön AiScript-kokeiluja varten.
Voit kirjoittaa, suorittaa ja tarkistaa sen tulokset vuorovaikutuksessa siinä olevan
Calckeyn kanssa.
script: Skripti
disablePagesScript: Poista AiScript käytöstä sivuilla
updateRemoteUser: Päivitä etäkäyttäjän tiedot
deleteAllFiles: Poista kaikki tiedostot
deleteAllFilesConfirm: Oletko varma, että haluat poistaa kaikki tiedostot?
removeAllFollowing: Poista seuraaminen kaikista seuratuista käyttäjistä
removeAllFollowingDescription: Tämän suorittaminen poistaa kaikki {host}:n tilit.
Suorita tämä, jos instanssia ei esimerkiksi enää ole olemassa.
userSuspended: Tämä käyttäjä on hyllytetty.
userSilenced: Tämä käyttäjä on hiljennetty.
yourAccountSuspendedTitle: Tämä tili on hyllytetty
yourAccountSuspendedDescription: Tämä tili on hyllytetty palvelimen palveluehtojen
tai vastaavien rikkomisen vuoksi. Ota yhteyttä ylläpitäjään, jos haluat tietää tarkemman
syyn. Älä luo uutta tiliä.
menu: Valikko
divider: Jakaja
addItem: Lisää kohde
relays: Releet
addRelay: Lisää rele
inboxUrl: Saavuneen postin URL
addedRelays: Lisätyt releet
serviceworkerInfo: Pitää ottaa käyttöön Push-notifikaatioissa.
deletedNote: Poistetut viestit
disablePlayer: Sulje videotoistin
expandTweet: Laajenna twiittiä
themeEditor: Teemaeditori
leaveConfirm: Tallentamattomia muutoksia olemassa. Hylätäänkö ne?
plugins: Liitännäiset
preferencesBackups: Asetusten varmuuskopiot
deck: Kansi
undeck: Jätä kansi
useBlurEffectForModal: Käytä blur-efektiä modaaleissa
useFullReactionPicker: Käytä täysikokoista reaktiovalitsinta
width: Leveys
generateAccessToken: Luo käyttöoikeustunniste
enableAll: Ota käyttöön kaikki
disableAll: Poista käytöstä kaikki
tokenRequested: Myönnä oikeus tiliin
notificationType: Ilmoituksen tyyppi
edit: Muokkaa
emailServer: Sähköpostipalvelin
enableEmail: Ota sähköpostin jakelu käyttöön
emailConfigInfo: Käytetään vahvistamaan sähköpostiosoitteesi rekisteröitymisen yhteydessä
tai jos unohdat salasanasi
email: Sähköposti
smtpHost: Isäntä
smtpUser: Käyttäjänimi
smtpPass: Salasana
emptyToDisableSmtpAuth: Jätä käyttäjänimi ja salasana tyhjäksi ohittaaksesi SMTP verifioinnin
smtpSecureInfo: Kytke tämä päältä kun käytät STARTTLS
testEmail: Kokeile email-lähetystä
wordMute: Sanan hiljennys
regexpError: Säännöllinen lausekevirhe
userSaysSomething: '{name} sanoi jotakin'
userSaysSomethingReason: '{name} sanoi {reason}'
makeActive: Aktivoi
display: Näyttö
copy: Kopioi
metrics: Mittarit
overview: Yleiskatsaus
logs: Lokit
delayed: Viivästynyt
database: Tietokanta
channel: Kanavat
notificationSetting: Ilmoitusasetukset
notificationSettingDesc: Valitse näytettävät ilmoitustyypit.
useGlobalSetting: Käytä globaaleja asetuksia
regenerateLoginToken: Luo kirjautumistunniste uudelleen
sample: Näyte
abuseReports: Raportit
reportAbuse: Raportti
reportAbuseOf: Raportti {name}
fillAbuseReportDescription: Täytä tätä raporttia koskevat tiedot. Jos se koskee tiettyä
viestiä, ilmoita sen URL-linkki.
abuseReported: Raporttisi on lähetetty. Kiitoksia paljon.
reporter: Raportoija
reporteeOrigin: Ilmoittajan alkuperä
reporterOrigin: Raportoijan alkuperä
forwardReport: Välitä raportti etäinstanssille
forwardReportIsAnonymous: Tilisi sijasta anonyymi järjestelmätili näytetään toimittajana
etäinstanssissa.
send: Lähetä
abuseMarkAsResolved: Merkitse raportti ratkaistuksi
openInNewTab: Avaa uuteen välilehteen
openInSideView: Avaa sivunäkymään
defaultNavigationBehaviour: Navigoinnin oletuskäyttäytyminen
editTheseSettingsMayBreakAccount: Näiden asetusten muuttaminen voi vahingoittaa tiliäsi.
desktop: Työpöytä
clip: Leike
optional: Vaihtoehtoinen
createNewClip: Luo uusi leike
unclip: Poista leike
confirmToUnclipAlreadyClippedNote: Tämä viesti on jo osa "{name}"-leikettä. Haluatko
sen sijaan poistaa sen tästä leikkeestä?
manageAccessTokens: Hallitse käyttöoikeuskoodeja
accountInfo: Tilin tiedot
notesCount: Viestien määrä
renotesCount: Lähetettyjen buustausten määrä
repliedCount: Saatujen vastausten määrä
sentReactionsCount: Lähetettyjen reaktioiden määrä
receivedReactionsCount: Saatujen reaktioiden määrä
pollVotesCount: Lähetettyjen kyselyäänien määrä
pollVotedCount: Saatujen kyselyäänien määrä
yes: Kyllä
no: Ei
driveFilesCount: Tiedostojen määrä asemalla
driveUsage: Aseman tilankäyttö
noCrawle: Hylkää hakukoneindeksointi
noCrawleDescription: Pyydä hakukoneita olemaan indeksoimatta profiilisivuasi, viestejäsi,
sivujasi jne.
alwaysMarkSensitive: Merkitse oletusarvoisesti herkäksi sisällöksi (NSFW)
loadRawImages: Alkuperäisten kuvien lataaminen pikkukuvien näyttämisen sijaan
disableShowingAnimatedImages: Älä näytä animoituja kuvia
verificationEmailSent: Vahvistussähköposti on lähetetty. Seuraa mukana olevaa linkkiä
suorittaaksesi vahvistuksen loppuun.
emailVerified: Sähköposti on vahvistettu
noteFavoritesCount: Kirjanmerkittyjen viestien määrä
pageLikedCount: Saatujen Sivu-tykkäysten määrä
pageLikesCount: Sivut-tykkäysten määrä
contact: Yhteystieto
useSystemFont: Käytä järjestelmän oletuskirjasinta
clips: Leikkeet
experimentalFeatures: Kokeiluluontoiset ominaisuudet
developer: Kehittäjä
makeExplorable: Tee tili näkyväksi osiossa "Tutustu"
makeExplorableDescription: Jos otat tämän pois käytöstä, tilisi ei näy "Tutustu"-osiossa.
showGapBetweenNotesInTimeline: Näytä väli viestien välissä aikajanalla
duplicate: Monista
left: Vasen
center: Keskellä
wide: Leveä
narrow: Kapea
reloadToApplySetting: Asetus otetaan käyttöön vain uudelleenladattaessa. Ladataanko
uudelleen nyt?
showTitlebar: Näytä otsikkorivi
clearCache: Tyhjennä välimuisti
onlineUsersCount: '{n} käyttäjää online-tilassa'
myTheme: Minun teemani
value: Arvo
saveConfirm: Tallenna muutokset?
deleteConfirm: Poistetaanko tosiaan?
latestVersion: Uusin versio
newVersionOfClientAvailable: Asiakasohjelmiston uudempi versio saatavilla.
usageAmount: Käyttö
inUse: Käytetty
editCode: Muokkaa koodia
apply: Käytä
receiveAnnouncementFromInstance: Vastaanota ilmoituksia tästä instanssista
emailNotification: Sähköposti-ilmoitukset
publish: Julkaise
inChannelSearch: Etsi kanavalta
useReactionPickerForContextMenu: Avaa reaktiovalitsin napsauttamalla oikeaa
typingUsers: '{users} kirjoittaa'
jumpToSpecifiedDate: Hyppää tiettyyn päivään
markAllAsRead: Merkitse kaikki luetuksi
goBack: Takaisin
unlikeConfirm: Poistatko todella tykkäyksesi?
fullView: Täysi koko
quitFullView: Poistu täydestä koosta
addDescription: Lisää kuvaus
markAsReadAllTalkMessages: Merkitse kaikki yksityisviestit luetuiksi
appearance: Ulkonäkö
messagingWithGroup: Ryhmäjuttelu
newPasswordIs: Uusi salasana on "{password}"
noFollowRequests: Sinulla ei ole odottavia seuraajapyyntöjä
objectStoragePrefixDesc: Tiedostot tallennetaan hakemistoihin tällä etuliitteellä.
objectStorageEndpointDesc: Jätä tämä tyhjäksi, jos käytät AWS S3:a. Muuten määritä
päätepisteeksi '<host>' tai '<host>:<port>' käyttämästäsi palvelusta riippuen.
unableToProcess: Toimenpidettä ei voida suorittaa loppuun
installedDate: Hyväksynyt
lastUsedDate: Viimeksi käytetty
pluginTokenRequestedDescription: Tämä litännäinen voi käyttää tässä asetettuja käyttöoikeuksia.
permission: Oikeudet
smtpConfig: Lähtevän sähköpostin palvelimen (SMTP) asetukset
regexpErrorDescription: 'Säännöllisessä lausekkeessa tapahtui virhe rivillä {line}
sanan {tab} sanan mykistäminen rivillä {line}:'
emailAddress: Sähköpostiosoite
smtpSecure: Käytä implisiittistä SSL/TLS:ää SMTP-yhteyksissä
useGlobalSettingDesc: Jos se on päällä, käytetään tilisi ilmoitusasetuksia. Jos se
on pois päältä, voit tehdä yksilöllisiä asetuksia.
public: Julkinen
i18nInfo: Vapaaehtoiset kääntävät Calckeyta eri kielille. Voit auttaa osoitteessa
{link}.
lockedAccountInfo: Ellet aseta postauksen näkyvyydeksi "Vain seuraajille", postauksesi
näkyvät kaikille, vaikka vaatisitkin seuraajilta manuaalista hyväksyntää.
sendErrorReportsDescription: "Kun tämä on päällä, yksityiskohtaiset virhetiedot jaetaan\
\ Calckeyn kanssa ongelman ilmetessä, mikä auttaa parantamaan Calckeyn laatua.\n\
Näihin tietoihin sisältyy esimerkiksi käyttöjärjestelmäversio, käyttämäsi selain,\
\ toimintasi Calckeyssä jne."
createdAt: Luotu
youAreRunningUpToDateClient: Käytössäsi on asiakasohjelman uusin versio.
needReloadToApply: Uudelleenlataus vaaditaan, jotta tämä näkyy.
showingPastTimeline: Näytetään parhaillaan vanhaa aikajanaa
userPagePinTip: Voit näyttää viestit täällä valitsemalla yksittäisten viestien valikosta
"Kiinnitä profiiliin".
notSpecifiedMentionWarning: Tämä viesti sisältää mainintoja käyttäjistä, joita ei
ole mainittu vastaanottajina
name: Nimi
allowedInstances: Sallitut (whitelisted) instanssit
hashtags: Aihetunnisteet
troubleshooting: Vianetsintä
received: Vastaanotettu
searchResult: Hakutulokset
filter: Suodatin
antennas: Antennit
noMaintainerInformationWarning: Ylläpitäjän tietoja ei ole konfiguroitu.
controlPanel: Hallintapaneeli
manageAccounts: Hallitse tilejä
makeReactionsPublic: Aseta reaktiohistoria julkiseksi
unread: Lukematon
deleted: Poistettu
editNote: Muokkaa viestiä
edited: 'Muokattu klo {date} {time}'
avoidMultiCaptchaConfirm: Useiden Captcha-järjestelmien käyttö voi aiheuttaa häiriöitä
niiden välillä. Haluatko poistaa käytöstä muut tällä hetkellä käytössä olevat Captcha-järjestelmät?
Jos haluat, että ne pysyvät käytössä, paina peruutusnäppäintä.
manageAntennas: Hallitse antenneja
info: Tietoja
userInfo: Käyttäjätiedot
unknown: Tuntematon
onlineStatus: Online-tila
hideOnlineStatus: Piilota Online-tila
hideOnlineStatusDescription: Online-tilasi piilottaminen vähentää joidenkin toimintojen,
kuten haun, käyttömukavuutta.
online: Online
active: Aktiivinen
offline: Offline
botProtection: Botti-suojaus
instanceBlocking: Federaatio Esto/Hiljennys
enabled: Otettu käyttöön
quickAction: Pikatoiminnot
user: Käyttäjä
accounts: Tilit
switch: Vaihda
noBotProtectionWarning: Botti-suojausta ei ole konfiguroitu.
configure: Konfiguroi
postToGallery: Luo uusi galleriaviesti
gallery: Galleria
recentPosts: Viimeaikaiset sivut
popularPosts: Suositut sivut
ads: Mainokset
expiration: Aikaraja
memo: Muistio
priority: Prioriteetti
high: Korkea
middle: Keskitaso
low: Alhainen
emailNotConfiguredWarning: Sähköpostiosoitetta ei ole asetettu.
ratio: Suhde
secureMode: Suojattu moodi (Valtuutettu nouto)
instanceSecurity: Instanssiturvallisuus
allowedInstancesDescription: Federaatiota varten sallitulle listalle (whitelisted)
otettavien instanssien isännät, kukin erotettuna uudella rivillä (sovelletaan vain
yksityisessä tilassa).
previewNoteText: Näytä esikatselu
customCss: Kustomoitu CSS
customCssWarn: Tätä asetusta tulisi käyttää vain, jos tiedät, mitä se tekee. Vääränlaisten
arvojen syöttäminen voi aiheuttaa sen, että asiakasohjelma lakkaa toimimasta normaalisti.
recommended: Suositeltu
squareAvatars: Näytä neliön malliset kuvakkeet
seperateRenoteQuote: Erilliset buustaa ja lainaa -napit
sent: Lähetetty
useBlurEffect: Käytä blur-efektejä käyttöliittymässä
misskeyUpdated: Calckey on päivitetty!
whatIsNew: Näytä muutokset
translate: Käännä
translatedFrom: Käännetty kielestä {x}
accountDeletionInProgress: Tilin poistaminen on parhaillaan menossa
usernameInfo: Nimi, joka erottaa tilisi muista tällä palvelimella olevista tileistä. Voit
käyttää aakkosia (a~z, A~Z), numeroita (0~9) tai alaviivoja (_). Käyttäjätunnuksia
ei voi muuttaa myöhemmin.
aiChanMode: Ai-chan klassisessa käyttöliittymässä
keepCw: Pidä sisältövaroitukset
pubSub: Pub/Sub tilit
lastCommunication: Viimeisin kommunikaatio
unresolved: Ratkaisematon
breakFollow: Poista seuraaja
breakFollowConfirm: Oletko varma, että haluat poistaa seuraajan?
itsOn: Otettu käyttöön
itsOff: Poistettu käytöstä
emailRequiredForSignup: Vaadi sähköpostiosoitetta sisäänkirjautumiseen
makeReactionsPublicDescription: Tämä laittaa viimeisimmät reaktiosi julkisesti näkyväksi.
classic: Klassinen
muteThread: Mykistä lanka
unmuteThread: Poista langan mykistys
ffVisibility: Seurataan/Seurattavien näkyvyys
notRecommended: Ei suositeltu
disabled: Poistettu käytöstä
selectAccount: Valitse tili
switchAccount: Vaihda tili
administration: Hallinta
shareWithNote: Jaa viestin kanssa
secureModeInfo: Kun pyydät muista instansseista, älä lähetä takaisin ilman todisteita.
privateMode: Yksityinen moodi
privateModeInfo: Kun tämä on käytössä, vain sallittujen (whitelisted) luetteloon merkityt
instanssit voivat liittyä instansseihisi. Kaikki viestit piilotetaan yleisöltä.
global: Globaali
resolved: Ratkaistu
learnMore: Opi lisää
continueThread: Jatka lankaa
file: Tiedosto
cropImageAsk: Haluatko rajata tätä kuvaa?
recentNHours: Viimeiset {n} tuntia
rateLimitExceeded: Nopeusraja ylittynyt
cropImage: Rajaa kuvaa
socialTimeline: Sosiaalinen aikajana
themeColor: Instanssi Ticker Väri
check: Tarkista
ffVisibilityDescription: Antaa sinun konfiguroida, kuka voi nähdä ketä seuraat ja
kuka seuraa sinua.
homeTimeline: Koti aikajana
size: Koko
showLocalPosts: 'Näytä paikalliset viestit:'
oneDay: Päivä
instanceDefaultDarkTheme: Instanssikattava tumma oletusteema
recentNDays: Viimeiset {n} päivää
reflectMayTakeTime: Voi kestää jonkin aikaa, ennen kuin tämä näkyy.
failedToFetchAccountInformation: Ei voitu hakea tietoja
requireAdminForView: Sinun tulee kirjautua järjestelmänvalvojana nähdäksesi tämän.
driveCapOverrideCaption: Resetoi oletusarvoon syöttämällä arvo 0 tai alempi.
isSystemAccount: Järjestelmän luoma ja automaattisesti käyttämä tili.
userSaysSomethingReasonReply: '{name} vastasi viestiin sisältäen {reason}'
userSaysSomethingReasonRenote: '{name} buustasi viestiin sisältäen {reason}'
voteConfirm: Vahvista äänesi vaihtoehdolle "{choice}"?
hide: Piilota
leaveGroup: Poistu ryhmästä
leaveGroupConfirm: Oletko varma, että haluat poistua ryhmästä "{name}"?
welcomeBackWithName: Tervetuloa takaisin, {name}
clickToFinishEmailVerification: Klikkaa [{ok}] viimeistelläksesi sähköpostivahvistuksen.
overridedDeviceKind: Laitetyyppi
tablet: Tabletti
numberOfColumn: Sarakkeiden määrä
searchByGoogle: Etsi
mutePeriod: Vaiennuksen kesto
indefinitely: Pysyvästi
tenMinutes: 10 minuuttia
oneHour: Tunti
thereIsUnresolvedAbuseReportWarning: On ratkaisemattomia raportteja.
driveCapOverrideLabel: Muuta aseman kapasiteetti tälle käyttäjälle
userSaysSomethingReasonQuote: '{name} lainasi viestiä sisältäen {reason}'
deleteAccountConfirm: Tämä peruuttamattomasti poistaa tilisi. Jatketaanko?
incorrectPassword: Väärä salasana.
useDrawerReactionPickerForMobile: Näytä reaktiovalitsin mobiilissa laatikkomallisena
smartphone: Älypuhelin
auto: Automaattinen
oneWeek: Viikko
instanceDefaultLightTheme: Instanssin kattava vaalea oletusteema
instanceDefaultThemeDescription: Anna teemakoodi objektiformaatille.
noEmailServerWarning: Sähköpostipalvelinta ei konfiguroituna.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3
locales/index.d.ts vendored
View File

@ -1,3 +0,0 @@
declare const locales: { [lang: string]: any };
export = locales;

View File

@ -1,91 +0,0 @@
/**
* Languages Loader
*/
const fs = require("fs");
const yaml = require("js-yaml");
const languages = [];
const languages_custom = [];
const merge = (...args) =>
args.reduce(
(a, c) => ({
...a,
...c,
...Object.entries(a)
.filter(([k]) => c && typeof c[k] === "object")
.reduce((a, [k, v]) => ((a[k] = merge(v, c[k])), a), {}),
}),
{},
);
fs.readdirSync(__dirname).forEach((file) => {
if (file.includes(".yml")) {
file = file.slice(0, file.indexOf("."));
languages.push(file);
}
});
fs.readdirSync(__dirname + "/../custom/locales").forEach((file) => {
if (file.includes(".yml")) {
file = file.slice(0, file.indexOf("."));
languages_custom.push(file);
}
});
const primaries = {
en: "US",
ja: "JP",
zh: "CN",
};
// 何故か文字列にバックスペース文字が混入することがあり、YAMLが壊れるので取り除く
const clean = (text) =>
text.replace(new RegExp(String.fromCodePoint(0x08), "g"), "");
const locales = languages.reduce(
(a, c) => (
(a[c] =
yaml.load(clean(fs.readFileSync(`${__dirname}/${c}.yml`, "utf-8"))) ||
{}),
a
),
{},
);
const locales_custom = languages_custom.reduce(
(a, c) => (
(a[c] =
yaml.load(
clean(
fs.readFileSync(`${__dirname}/../custom/locales/${c}.yml`, "utf-8"),
),
) || {}),
a
),
{},
);
Object.assign(locales, locales_custom);
module.exports = Object.entries(locales).reduce(
(a, [k, v]) => (
(a[k] = (() => {
const [lang] = k.split("-");
switch (k) {
case "ja-JP":
return v;
case "ja-KS":
case "en-US":
return merge(locales["ja-JP"], v);
default:
return merge(
locales["ja-JP"],
locales["en-US"],
locales[`${lang}-${primaries[lang]}`] || {},
v,
);
}
})()),
a
),
{},
);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,126 +0,0 @@
---
_lang_: "Taqbaylit"
monthAndDay: "{day}/{month}"
search: "Nadi"
notifications: "Ilɣuyen"
username: "Isem n umseqdac"
password: "Awal uffir"
ok: "IH"
settings: "Iɣewwaṛen"
otherSettings: "Iɣewwaren nniḍen"
profile: "Amaɣnu"
signup: "Jerred"
save: "Sekles"
delete: "Kkes"
addToList: "Rnu ɣer tebdart"
reply: "Err"
loadMore: "Wali ugar"
showMore: "Wali ugar"
youGotNewFollower: "Yeṭṭafaṛ-ik·em-id"
mention: "Bder"
import: "Kter"
export: "Sifeḍ"
files: "Ifuyla"
download: "Sider"
lists: "Tibdarin"
noLists: "Ulac ɣur-k·m ula d yiwet n tabdart"
following: "Ig ṭṭafaṛ"
followers: "Imeḍfaṛen"
followsYou: "Yeṭṭafaṛ-ik·em-id"
createList: "Snulfu-d tabdart"
enterListName: "Isem n tebdart"
privacy: "Tabaḍnit"
follow: "Ḍfeṛ"
you: "Kečči·mmi"
selectList: "Fren tabdart"
youHaveNoLists: "Ulac ɣur-k·m ula d yiwet n tabdart"
security: "Taɣellist"
remove: "Kkes"
connectService: "Qqen"
userList: "Tibdarin"
securityKey: "Tasarutt n tɣellist"
securityKeyName: "Isem n tsarutt"
signinRequired: "Ttxil jerred"
signinWith: "Tuqqna s {x}"
tapSecurityKey: "Sekcem tasarutt-ik·im n tɣellist"
uiLanguage: "Tutlayt n wegrudem"
accountSettings: "Iɣewwaṛen n umiḍan"
plugins: "Izegrar"
email: "Imayl"
emailAddress: "Tansa imayl"
smtpUser: "Isem n umseqdac"
smtpPass: "Awal uffir"
other: "Wiyyaḍ"
accountInfo: "Talɣut n umiḍan"
emailNotification: "Ilɣa imayl"
selectAccount: "Fren amiḍan"
accounts: "Imiḍan"
searchByGoogle: "Nadi"
file: "Ifuyla"
account: "Imiḍan"
_email:
_follow:
title: "Yeṭṭafaṛ-ik·em-id"
_mfm:
mention: "Bder"
search: "Nadi"
font: "Tasefsit"
_theme:
keys:
mention: "Bder"
_sfx:
notification: "Ilɣuyen"
_permissions:
"write:account": "Ẓreg talɣut n umiḍan-ik·im"
_widgets:
notifications: "Ilɣuyen"
_cw:
show: "Wali ugar"
_visibility:
followers: "Imeḍfaṛen"
_profile:
username: "Isem n umseqdac"
_exportOrImport:
followingList: "Ig ṭṭafaṛ"
muteList: "Sgugem"
blockingList: "Seḥbes"
userLists: "Tibdarin"
_pages:
contents: "Agbur"
font: "Tasefsit"
fontSerif: "Serif"
fontSansSerif: "Sans Serif"
eyeCatchingImageRemove: "Kkes tugna i d-ijebden"
selectType: "Fren anaw"
contentBlocks: "Agbur"
inputBlocks: "Anekcum"
specialBlocks: "Uzzig"
script:
categories:
list: "Tibdarin"
blocks:
_join:
arg1: "Tibdarin"
_randomPick:
arg1: "Tibdarin"
_dailyRandomPick:
arg1: "Tibdarin"
_seedRandomPick:
arg2: "Tibdarin"
_pick:
arg1: "Tibdarin"
_listLen:
arg1: "Tibdarin"
types:
array: "Tibdarin"
_notification:
youWereFollowed: "Yeṭṭafaṛ-ik·em-id"
_types:
follow: "Ig ṭṭafaṛ"
mention: "Bder"
_actions:
reply: "Err"
_deck:
_columns:
notifications: "Ilɣuyen"
list: "Tibdarin"

View File

@ -1,86 +0,0 @@
---
_lang_: "ಕನ್ನಡ"
introMisskey: "ಸ್ವಾಗತ! Calckey ಓಪನ್ ಸೋರ್ಸ್ ಒಕ್ಕೂಟ ಮೈಕ್ರೋಬ್ಲಾಗಿಂಗ್ ಸೇವೆಯಾಗಿದೆ.\n ಏನಾಗುತ್ತಿದೆ ಎಂಬುದನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಅಥವಾ ನಿಮ್ಮ ಬಗ್ಗೆ ಎಲ್ಲರಿಗೂ ಹೇಳಲು \"ಟಿಪ್ಪಣಿ\"ಗಳನ್ನು ರಚಿಸಿ📡\n \"ಸ್ಪಂದನೆ\" ಕ್ರಿಯೆಯೊಂದಿಗೆ, ನೀವು ಎಲ್ಲರ ಟಿಪ್ಪಣಿಗಳಿಗೆ ತ್ವರಿತವಾಗಿ ಸ್ಪಂದನೆಗಳನ್ನು ಕೂಡ ಸೇರಿಸಬಹುದು.👍\n ಹೊಸ ಜಗತ್ತನ್ನು ಅನ್ವೇಷಿಸಿ🚀"
monthAndDay: "{month}ನೇ ತಿಂಗಳ {day}ನೇ ದಿನ"
search: "ಹುಡುಕು"
notifications: "ಅಧಿಸೂಚನೆಗಳು"
username: "ಬಳಕೆಹೆಸರು"
password: "ಗುಪ್ತಪದ"
fetchingAsApObject: "ಒಕ್ಕೂಟದಿಂದ ಪಡೆಯಲಾಗುತ್ತಿದೆ"
ok: "ಸರಿ"
gotIt: "ಅರ್ಥವಾಯಿತು!"
cancel: "ರದ್ದು"
enterUsername: "ಬಳಕೆಹೆಸರನ್ನು ಭರ್ತಿ ಮಾಡಿ"
renotedBy: "{user} ಪುನರಾವರ್ತಿಸಿದರು"
noNotes: "ಟಿಪ್ಪಣಿಗಳಿಲ್ಲ"
noNotifications: "ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"
instance: "ನಿದರ್ಶನ"
settings: "ಸಿದ್ಧತೆಗಳು"
profile: "ಪ್ರೊಫೈಲು"
timeline: "ಸಮಯಸಾಲು"
noAccountDescription: "ಇವರು ಸ್ವಯಂ ಪರಿಚಯ ರಚಿಸಿಲ್ಲ"
login: "ಪ್ರವೇಶ"
loggingIn: "ಪ್ರವೇಶಿಸುತ್ತಾ..."
logout: "ಆಚೆಗೆ"
signup: "ನೋಂದಣಿ"
uploading: "ಅಪ್‌ಲೋಡಾಗುತ್ತಿದೆ"
save: "ಉಳಿಸಿ"
users: "ಬಳಕೆದಾರ"
addUser: "ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿ"
favorite: "ಮೆಚ್ಚಿನ"
favorites: "ಮೆಚ್ಚಿನವುಗಳು"
unfavorite: "ಮೆಚ್ಚುಗೆ ಅಳಿಸು"
pin: "ಪ್ರೊಫ಼ೈಲಿಗೆ ಅಂಟಿಸು"
unpin: "ಪ್ರೊಫ಼ೈಲಿಂದ ಅಂಟುತೆಗೆ"
copyContent: "ವಿಷಯವನ್ನು ನಕಲಿಸು"
copyLink: "ಲಿಂಕನ್ನು ನಕಲಿಸು"
delete: "ಅಳಿಸು"
addToList: "ಪಟ್ಟಿಗೆ ಸೇರಿಸು"
sendMessage: "ಸಂದೇಶ ಕಳುಹಿಸು"
copyUsername: "ಬಳಕೆಹೆಸರು ನಕಲಿಸು"
reply: "ಉತ್ತರಿಸು"
loadMore: "ಇನ್ನಷ್ಟು ನೋಡು"
showMore: "ಇನ್ನಷ್ಟು ನೋಡು"
youGotNewFollower: "ಹಿಂಬಾಲಿಸಿದರು"
receiveFollowRequest: "ಹಿಂಬಾಲನೆ ವಿನಂತಿ ಬಂದಿದೆ"
followRequestAccepted: "ಹಿಂಬಾಲನೆ ವಿನಂತಿ ಸ್ವೀಕರಿಸಲಾಯಿತು"
mentions: "ಹೆಸರಿಸಿದ"
directNotes: "ನೇರ ಟಿಪ್ಪಣಿಗಳು"
importAndExport: "ಆಮದು/ರಫ್ತು"
import: "ಆಮದು"
export: "ರಫ್ತು"
files: "ಕಡತಗಳು"
download: "ಜಾಲದಿಂದಿಳಿಸು"
driveFileDeleteConfirm: "\"{name}\" ಕಡತವನ್ನು ಅಳಿಸಲು ನೀವು ಬಯಸುವಿರಾ? ಈ ನೋಡಿರಿ ಲಗತ್ತಿಸಲಾದ ಟಿಪ್ಪಣಿ ಸಹ ಕಣ್ಮರೆಯಾಗುತ್ತದೆ."
unfollowConfirm: "{name}ಅನ್ನು ಹಿಂಬಾಲಿಸದಿರುವುದೇ?"
pinned: "ಪ್ರೊಫ಼ೈಲಿಗೆ ಅಂಟಿಸು"
instances: "ನಿದರ್ಶನ"
remove: "ಅಳಿಸು"
smtpUser: "ಬಳಕೆಹೆಸರು"
smtpPass: "ಗುಪ್ತಪದ"
user: "ಬಳಕೆದಾರ"
searchByGoogle: "ಹುಡುಕು"
file: "ಕಡತಗಳು"
_email:
_follow:
title: "ಹಿಂಬಾಲಿಸಿದರು"
_mfm:
search: "ಹುಡುಕು"
_sfx:
notification: "ಅಧಿಸೂಚನೆಗಳು"
_widgets:
notifications: "ಅಧಿಸೂಚನೆಗಳು"
timeline: "ಸಮಯಸಾಲು"
_cw:
show: "ಇನ್ನಷ್ಟು ನೋಡು"
_profile:
username: "ಬಳಕೆಹೆಸರು"
_notification:
youWereFollowed: "ಹಿಂಬಾಲಿಸಿದರು"
_actions:
reply: "ಉತ್ತರಿಸು"
_deck:
_columns:
notifications: "ಅಧಿಸೂಚನೆಗಳು"
tl: "ಸಮಯಸಾಲು"
mentions: "ಹೆಸರಿಸಿದ"

File diff suppressed because it is too large Load Diff

View File

@ -1,684 +0,0 @@
_lang_: "Nederlands"
headlineMisskey: "Een open source, gedecentraliseerd, social media platform dat voor
altijd gratis is! 🚀"
introMisskey: "Welkom! Calckey is een open source, gedecentraliseerde microblogdienst.\n
Maak \"notities\" om je gedachten te delen met iedereen om je heen. 📡\nMet \"reacties\"\
\ kun je ook snel je mening geven over berichten van anderen. 👍\nLaten we een nieuwe
wereld verkennen! 🚀"
monthAndDay: "{day} {month}"
search: "Zoeken"
notifications: "Meldingen"
username: "Gebruikersnaam"
password: "Wachtwoord"
forgotPassword: "Wachtwoord vergeten"
fetchingAsApObject: "Ophalen vanuit de Fediverse"
ok: "Ok"
gotIt: "Begrepen!"
cancel: "Annuleren"
enterUsername: "Voer een gebruikersnaam in"
renotedBy: "Hergedeeld door {user}"
noNotes: "Geen notities"
noNotifications: "Geen meldingen"
instance: "Server"
settings: "Instellingen"
basicSettings: "Basisinstellingen"
otherSettings: "Overige instellingen"
openInWindow: "In een venster openen"
profile: "Profiel"
timeline: "Tijdlijn"
noAccountDescription: "Deze gebruiker heeft nog geen bio geschreven"
login: "Inloggen"
loggingIn: "Aan het inloggen"
logout: "Afmelden"
signup: "Registreren"
uploading: "Bezig met uploaden"
save: "Opslaan"
users: "Gebruikers"
addUser: "Toevoegen gebruiker"
favorite: "Favorieten"
favorites: "Toevoegen aan favorieten"
unfavorite: "Verwijderen uit favorieten"
favorited: "Toegevoegd aan favorieten."
alreadyFavorited: "Al toegevoegd aan favorieten"
cantFavorite: "Kon niet toevoegen aan favorieten"
pin: "Vastmaken aan profielpagina"
unpin: "Losmaken van profielpagina"
copyContent: "Kopiëren inhoud"
copyLink: "Kopiëren link"
delete: "Verwijderen"
deleteAndEdit: "Verwijderen en bewerken"
deleteAndEditConfirm: "Weet je zeker dat je deze post wilt verwijderen en dan bewerken?
Je verliest alle reacties, boosts en antwoorden erop."
addToList: "Aan lijst toevoegen"
sendMessage: "Verstuur bericht"
copyUsername: "Gebruikersnaam kopiëren"
searchUser: "Zoek een gebruiker"
reply: "Antwoord"
loadMore: "Laad meer"
showMore: "Toon meer"
youGotNewFollower: "volgt jou"
receiveFollowRequest: "Volgverzoek ontvangen"
followRequestAccepted: "Volgverzoek geaccepteerd"
mention: "Vermelding"
mentions: "Vermeldingen"
directNotes: "Directe notities"
importAndExport: "Import / export"
import: "Import"
export: "Export"
files: "Bestanden"
download: "Downloaden"
driveFileDeleteConfirm: "Weet je zeker dat je het bestand \"{name}\" wilt verwijderen?
Posts met dit bestand als bijlage worden ook verwijderd."
unfollowConfirm: "Weet je zeker dat je {name} wilt ontvolgen?"
exportRequested: "Je hebt een export aangevraagd. Dit kan een tijdje duren. Het wordt
toegevoegd aan je Drive zodra het is voltooid."
importRequested: "Je hebt een import aangevraagd. Dit kan even duren."
lists: "Lijsten"
noLists: "Je hebt geen lijsten"
note: "Notitie"
notes: "Notities"
following: "Volgend"
followers: "Volgers"
followsYou: "Volgt jou"
createList: "Creëer lijst"
manageLists: "Lijsten beheren"
error: "Fout"
somethingHappened: "Er is iets misgegaan."
retry: "Probeer opnieuw"
pageLoadError: "Pagina laden mislukt"
pageLoadErrorDescription: "Dit wordt normaal gesproken veroorzaakt door netwerkfouten
of door de cache van de browser. Probeer de cache te wissen en probeer het na een
tijdje wachten opnieuw."
serverIsDead: "De server reageert niet. Wacht even en probeer het opnieuw."
youShouldUpgradeClient: "Werk je client bij om deze pagina te zien."
enterListName: "Voer de naam van de lijst in"
privacy: "Privacy"
makeFollowManuallyApprove: "Volgverzoeken vergen een goedkeuring"
defaultNoteVisibility: "Standaard zichtbaarheid"
follow: "Volgen"
followRequest: "Verzoek om te mogen volgen"
followRequests: "Volgverzoeken"
unfollow: "Ontvolgen"
followRequestPending: "Wachten op goedkeuring volgverzoek"
enterEmoji: "Voer een emoji in"
renote: "Boost"
unrenote: "Boost intrekken"
renoted: "Boosted."
cantRenote: "Dit bericht kan niet worden geboost."
cantReRenote: "Een boost kan niet worden geboost."
quote: "Quote"
pinnedNote: "Vastgemaakte post"
pinned: "Vastmaken aan profielpagina"
you: "Jij"
clickToShow: "Klik om te bekijken"
sensitive: "NSFW"
add: "Toevoegen"
reaction: "Reacties"
reactionSettingDescription2: "Sleep om opnieuw te ordenen, Klik om te verwijderen,
Druk op \"+\" om toe te voegen"
rememberNoteVisibility: "Onthoud post zichtbaarheidsinstellingen"
attachCancel: "Verwijder bijlage"
markAsSensitive: "Markeren als NSFW"
unmarkAsSensitive: "Geen NSFW"
enterFileName: "Bestandsnaam invoeren"
mute: "Dempen"
unmute: "Stop dempen"
block: "Blokkeren"
unblock: "Deblokkeren"
suspend: "Opschorten"
unsuspend: "Heractiveren"
blockConfirm: "Weet je zeker dat je dit account wil blokkeren?"
unblockConfirm: "Ben je zeker dat je deze account wil blokkeren?"
suspendConfirm: "Ben je zeker dat je deze account wil suspenderen?"
unsuspendConfirm: "Ben je zeker dat je deze account wil opnieuw aanstellen?"
flagAsBot: "Markeer dit account als een robot"
flagAsBotDescription: "Als dit account van een programma wordt beheerd, zet deze vlag
aan. Het aanzetten helpt andere ontwikkelaars om bijvoorbeeld onbedoelde feedback
loops te doorbreken of om Calckey meer geschikt te maken."
flagAsCat: "Markeer dit account als een kat."
flagAsCatDescription: "Zet deze vlag aan als je wilt aangeven dat dit account een
kat is."
flagShowTimelineReplies: "Toon antwoorden op de tijdlijn"
flagShowTimelineRepliesDescription: "Als je deze vlag aanzet, toont de tijdlijn ook
antwoorden op andere en niet alleen jouw eigen post."
autoAcceptFollowed: "Accepteer verzoeken om jezelf te volgen vanzelf als je de verzoeker
al volgt"
addAccount: "Account toevoegen"
loginFailed: "Aanmelding mislukt."
showOnRemote: "Bekijk op de externe server"
general: "Algemeen"
wallpaper: "Achtergrond"
setWallpaper: "Achtergrond instellen"
removeWallpaper: "Achtergrond verwijderen"
searchWith: "Zoeken: {q}"
youHaveNoLists: "Je hebt geen lijsten"
followConfirm: "Weet je zeker dat je {name} wilt volgen?"
proxyAccount: "Proxy account"
proxyAccountDescription: "Een proxy-account is een account dat onder bepaalde voorwaarden
fungeert als externe volger voor gebruikers. Als een gebruiker bijvoorbeeld een
externe gebruiker aan de lijst toevoegt, wordt de activiteit van de externe gebruiker
niet aan de server geleverd als geen lokale gebruiker die gebruiker volgt, dus het
proxy-account volgt in plaats daarvan."
host: "Server"
selectUser: "Kies een gebruiker"
recipient: "Ontvanger(s)"
annotation: "Reacties"
federation: "Federatie"
instances: "Servers"
registeredAt: "Geregistreerd op"
latestRequestSentAt: "Laatste aanvraag verstuurd"
latestRequestReceivedAt: "Laatste aanvraag ontvangen"
latestStatus: "Laatste status"
storageUsage: "Gebruikte opslagruimte"
charts: "Grafieken"
perHour: "Per uur"
perDay: "Per dag"
stopActivityDelivery: "Stop met versturen activiteiten"
blockThisInstance: "Blokkeer deze server"
operations: "Verwerkingen"
software: "Software"
version: "Versie"
metadata: "Metadata"
monitor: "Monitor"
jobQueue: "Job Queue"
cpuAndMemory: "CPU en geheugen"
network: "Netwerk"
disk: "Schijfruimte"
instanceInfo: "Serverinformatie"
statistics: "Statistieken"
clearQueue: "Wachtrij wissen"
clearQueueConfirmTitle: "Weet je zeker dat je de wachtrji leeg wil maken?"
clearQueueConfirmText: "Niet-bezorgde posts die nog in de wachtrij staan, worden niet
gefedereerd. Meestal is deze operatie niet nodig."
clearCachedFiles: "Cache opschonen"
clearCachedFilesConfirm: "Weet je zeker dat je alle externe bestanden in de cache
wilt verwijderen?"
blockedInstances: "Geblokkeerde servers"
blockedInstancesDescription: "Maak een lijst van de servers die moeten worden geblokkeerd,
gescheiden door regeleinden. Geblokkeerde servers kunnen niet meer communiceren
met deze server."
muteAndBlock: "Gedempt en geblokkeerd"
mutedUsers: "Gedempte gebruikers"
blockedUsers: "Geblokkeerde gebruikers"
noUsers: "Er zijn geen gebruikers."
editProfile: "Bewerk Profiel"
noteDeleteConfirm: "Ben je zeker dat je deze post wil verwijderen?"
pinLimitExceeded: "Je kunt geen posts meer vastprikken"
intro: "Installatie van Calckey geëindigd! Maak nu een beheerder aan."
done: "Klaar"
processing: "Bezig met verwerken"
preview: "Voorbeeld"
default: "Standaard"
noCustomEmojis: "Er zijn geen emojis"
noJobs: "Er zijn geen taken"
federating: "Federeren"
blocked: "Geblokkeerd"
suspended: "Opgeschort"
all: "Alle"
subscribing: "Abonneren"
publishing: "Publiceren"
notResponding: "Reageert niet"
instanceFollowing: "Volgend op server"
instanceFollowers: "Volgers op server"
instanceUsers: "Gebruikers van deze server"
changePassword: "Wachtwoord wijzigen"
security: "Beveiliging"
retypedNotMatch: "Invoer komt niet overeen"
currentPassword: "Huidig wachtwoord"
newPassword: "Nieuwe wachtwoord"
newPasswordRetype: "Nieuw wachtwoord (herhalen)"
attachFile: "Bestanden toevoegen"
more: "Meer!"
featured: "Uitgelicht"
usernameOrUserId: "Gebruikersnaam of id"
noSuchUser: "Gebruiker niet gevonden"
lookup: "Opzoeken"
announcements: "Aankondigingen"
imageUrl: "AfbeeldingsURL"
remove: "Verwijderen"
removed: "Succesvol verwijderd"
removeAreYouSure: "Weet je zeker dat je \"{x}\" wil verwijderen?"
deleteAreYouSure: "Weet je zeker dat je \"{x}\" wil verwijderen?"
resetAreYouSure: "Resetten?"
saved: "Opgeslagen"
messaging: "Chat"
upload: "Uploaden"
keepOriginalUploading: "Origineel beeld behouden."
keepOriginalUploadingDescription: "Bewaar de originele versie bij het uploaden van
afbeeldingen. Indien uitgeschakeld, wordt bij het uploaden een alternatieve versie
voor webpublicatie genereert."
fromDrive: "Van schijf"
fromUrl: "Van URL"
uploadFromUrl: "Uploaden vanaf een URL"
uploadFromUrlDescription: "URL van het bestand dat je wil uploaden"
uploadFromUrlRequested: "Uploadverzoek"
uploadFromUrlMayTakeTime: "Het kan even duren voordat het uploaden voltooid is."
explore: "Verkennen"
messageRead: "Lezen"
noMoreHistory: "Er is geen verdere geschiedenis"
startMessaging: "Start een gesprek"
nUsersRead: "gelezen door {n}"
agreeTo: "Ik stem in met {0}"
tos: "Gebruiksvoorwaarden"
start: "Aan de slag"
home: "Startpagina"
remoteUserCaution: "Aangezien deze gebruiker van een externe server afkomstig is,
kan de weergegeven informatie onvolledig zijn."
activity: "Activiteit"
images: "Afbeeldingen"
birthday: "Geboortedatum"
yearsOld: "{age} jaar"
registeredDate: "Inschrijvingsdatum"
location: "Locatie"
theme: "Thema's"
themeForLightMode: "Thema voor gebruik in de lichte modus"
themeForDarkMode: "Thema voor gebruik in de donkere modus"
light: "Licht"
dark: "Donker"
lightThemes: "Licht thema's"
darkThemes: "Donkere thema's"
syncDeviceDarkMode: "Synchroniseer donkere modus met je apparaatinstellingen"
drive: "Schijf"
fileName: "Bestandsnaam"
selectFile: "Kies een bestand"
selectFiles: "Selecteer bestanden"
selectFolder: "Kies een map"
selectFolders: "Kies mappen"
renameFile: "Wijzig bestandsnaam"
folderName: "Mapnaam"
createFolder: "Map aanmaken"
renameFolder: "Map hernoemen"
deleteFolder: "Map verwijderen"
addFile: "Bestand toevoegen"
emptyDrive: "Jouw Drive is leeg."
emptyFolder: "Deze map is leeg"
unableToDelete: "Kan niet worden verwijderd"
inputNewFileName: "Voer een nieuwe naam in"
copyUrl: "URL kopiëren"
rename: "Hernoemen"
avatar: "Avatar"
banner: "Banner"
nsfw: "NSFW"
whenServerDisconnected: "Wanneer de verbinding met de server wordt onderbroken"
disconnectedFromServer: "Verbinding met de server onderbroken."
inMb: "in megabytes"
pinnedNotes: "Vastgemaakte notitie"
userList: "Lijsten"
aboutMisskey: "Over Calckey"
administrator: "Beheerder"
token: "Token"
securityKeyName: "Sleutelnaam"
registerSecurityKey: "Zekerheids-Sleutel registreren"
lastUsed: "Laatst gebruikt"
unregister: "Uitschrijven"
passwordLessLogin: "Inloggen zonder wachtwoord"
resetPassword: "Wachtwoord terugzetten"
newPasswordIs: "Het nieuwe wachtwoord is „{password}”."
reduceUiAnimation: "Verminder beweging in de UI"
share: "Delen"
notFound: "Niet gevonden"
cacheClear: "Cache verwijderen"
smtpHost: "Server"
smtpUser: "Gebruikersnaam"
smtpPass: "Wachtwoord"
clearCache: "Cache opschonen"
user: "Gebruikers"
muteThread: "Discussies dempen "
unmuteThread: "Dempen van discussie ongedaan maken"
hide: "Verbergen"
searchByGoogle: "Zoeken"
cropImage: "Afbeelding bijsnijden"
cropImageAsk: "Bijsnijdengevraagd"
file: "Bestanden"
_email:
_follow:
title: "Je hebt een nieuwe volger"
_mfm:
mention: "Vermelding"
quote: "Quote"
search: "Zoeken"
_theme:
keys:
mention: "Vermelding"
renote: "Herdelen"
_sfx:
note: "Notities"
notification: "Meldingen"
chat: "Chat"
_widgets:
notifications: "Meldingen"
timeline: "Tijdlijn"
activity: "Activiteit"
federation: "Federatie"
jobQueue: "Job Queue"
_cw:
show: "Laad meer"
_visibility:
home: "Startpagina"
followers: "Volgers"
_profile:
username: "Gebruikersnaam"
_exportOrImport:
followingList: "Volgend"
muteList: "Dempen"
blockingList: "Blokkeren"
userLists: "Lijsten"
excludeMutingUsers: "Negeer gedempte gebruikers"
excludeInactiveUsers: "Negeer inactieve gebruikers"
_charts:
federation: "Federatie"
_timelines:
home: "Startpagina"
_pages:
blocks:
image: "Afbeeldingen"
script:
categories:
list: "Lijsten"
blocks:
_join:
arg1: "Lijsten"
_randomPick:
arg1: "Lijsten"
_dailyRandomPick:
arg1: "Lijsten"
_seedRandomPick:
arg2: "Lijsten"
_pick:
arg1: "Lijsten"
_listLen:
arg1: "Lijsten"
types:
array: "Lijsten"
_notification:
youWereFollowed: "volgt jou"
_types:
follow: "Volgend"
mention: "Vermelding"
renote: "Herdelen"
quote: "Quote"
reaction: "Reacties"
_actions:
reply: "Antwoord"
renote: "Herdelen"
_deck:
_columns:
notifications: "Meldingen"
tl: "Tijdlijn"
list: "Lijsten"
mentions: "Vermeldingen"
showLess: Sluiten
emoji: Emoji
selectList: Selecteer een lijst
selectAntenna: Selecteer een antenne
deleted: Verwijderd
editNote: Bewerk notitie
edited: 'Bewerkt om {date} {time}'
emojis: Emojis
emojiName: Emoji naam
emojiUrl: Emoji URL
addEmoji: Voeg toe
settingGuide: Aanbevolen instellingen
flagSpeakAsCat: Praat als een kat
accountMoved: 'Gebruiker is naar een nieuw account verhuisd:'
showEmojisInReactionNotifications: Toon emojis in reactie notificaties
selectWidget: Selecteer een widget
editWidgetsExit: Klaar
noThankYou: Nee bedankt
addInstance: Voeg een server toe
enableEmojiReactions: Schakel emoji reacties in
editWidgets: Bewerk widgets
thisYear: Jaar
thisMonth: Maand
registration: Registreren
_ffVisibility:
public: Openbaar
private: Privé
followers: Alleen zichtbaar voor volgers
noInstances: Er zijn geen servers
_signup:
almostThere: Bijna klaar
emailAddressInfo: Voer je emailadres in. Deze zal niet openbaar gemaakt worden.
_ad:
back: Terug
reduceFrequencyOfThisAd: Toon deze advertentie minder
pushNotificationNotSupported: Je browser of server ondersteunt geen pushmeldingen
sendPushNotificationReadMessage: Verwijder pushmeldingen wanneer de relevante meldingen
of berichten zijn gelezen
customEmojis: Custom emoji
cacheRemoteFiles: Cache externe bestanden
hiddenTags: Verborgen hashtags
enableRecommendedTimeline: Schakel aanbevolen tijdlijn in
_forgotPassword:
enterEmail: Voer het emailadres in dat je gebruikte om te registreren. Een link
waarmee je je wachtwoord opnieuw kunt instellen zal daar naartoe gestuurd worden.
jumpToReply: Spring naar Antwoord
newer: nieuwer
older: ouder
selectInstance: Kies een server
defaultValueIs: 'Standaard: {value}'
reload: Hernieuwen
doNothing: Negeren
today: Vandaag
inputNewDescription: Voer een nieuw onderschrift in
inputNewFolderName: Voer een nieuwe mapnaam in
circularReferenceFolder: De bestemmingsmap is een submap van de map die je wil verplaatsen.
hasChildFilesOrFolders: Omdat deze map niet leeg is, kan deze niet verwijderd worden.
enableLocalTimeline: Schakel lokale tijdlijn in
enableGlobalTimeline: Schakel globale tijdlijn in
enableRegistration: Nieuwe gebruikersregistratie inschakelen
invite: Uitnodigen
move: Verplaatsen
showAds: Toon advertenties
pushNotification: Pushmeldingen
_gallery:
my: Mijn Gallerij
reactionSetting: Reacties om te tonen in het reactie selectie menu
dayX: '{day}'
renoteMute: Demp boosts
reloadConfirm: Wil je de tijdlijn hernieuwen?
watch: Volgen
unwatch: Ontvolgen
accept: Accepteren
reject: Afwijzen
normal: Normaal
pages: Pagina's
integration: Integraties
connectService: Koppelen
monthX: '{month}'
yearX: '{year}'
instanceName: Servernaam
instanceDescription: Server omschrijving
maintainerName: Onderhouder
maintainerEmail: Onderhouder email
tosUrl: Algemene Voorwaarden URL
disconnectService: Ontkoppelen
unread: Ongelezen
manageGroups: Beheer groepen
subscribePushNotification: Pushmeldingen inschakelen
unsubscribePushNotification: Pushmeldingen uitschakelen
pushNotificationAlreadySubscribed: Pushmeldingen zijn al ingeschakeld
antennaSource: Antenne bron
antennaKeywords: Trefwoorden om naar te luisteren
antennaExcludeKeywords: Trefwoorden om te negeren
driveCapacityPerRemoteAccount: Schijfruimte per externe gebruiker
backgroundImageUrl: Achtergrondafbeelding URL
basicInfo: Basis informatie
pinnedUsers: Vastgezette gebruikers
pinnedPages: Vastgezette Pagina's
driveCapacityPerLocalAccount: Schijfruimte per lokale gebruiker
iconUrl: Icoon URL
bannerUrl: Banner afbeelding URL
manageAntennas: Beheer Antennes
name: Naam
notifyAntenna: Meld nieuwe posts
withFileAntenna: Alleen posts met bestanden
enableServiceworker: Schakel pushmeldingen voor je browser in
renoteUnmute: Ontdemp boosts
jumpToPrevious: Spring naar vorige
caseSensitive: Hoofdlettergevoelig
cw: Inhoudswaarschuwing
recaptcha: reCAPTCHA
enableRecaptcha: reCAPTCHA inschakelen
recaptchaSiteKey: Site sleutel
notFoundDescription: Een pagina met deze URL kon niet worden gevonden.
uploadFolder: Standaard map voor uploads
markAsReadAllNotifications: Markeer alle notificaties als gelezen
text: Tekst
enable: Inschakelen
or: Of
language: Taal
securityKey: Veiligheidssleutel
groupInvited: Je bent voor een groep uitgenodigd
docSource: Bron van dit document
createAccount: Maak account aan
groupName: Groepsnaam
members: Leden
messagingWithUser: Privé chat
messagingWithGroup: Groepschat
title: Titel
createGroup: Maak een groep
ownedGroups: Beheerde groepen
invites: Uitnodigingen
useOsNativeEmojis: Gebruik je standaard besturingssysteem Emojis
disableDrawer: Gebruik niet de lade-stijl menus
joinOrCreateGroup: Krijg een uitnodiging voor een groep of maak er zelf eentje aan.
noHistory: Geen geschiedenis beschikbaar
signinHistory: Inloggeschiedenis
available: Beschikbaar
unavailable: Niet beschikbaar
tooShort: Te kort
signinFailed: Niet gelukt om in te loggen. Gebruikersnaam of wachtwoord is incorrect.
tapSecurityKey: Tik je veiligheidssleutel aan
recaptchaSecretKey: Geheime sleutel
antennas: Antennes
antennaUsersDescription: Zet één gebruikersnaam per regel neer
notesAndReplies: Posts en antwoorden
withFiles: Met bestanden
popularUsers: Populaire gebruikers
recentlyUpdatedUsers: Recente actieve gebruikers
recentlyRegisteredUsers: Nieuwe gebruikers
recentlyDiscoveredUsers: Nieuwe ontdekte gebruikers
exploreUsersCount: Er zijn {count} gebruikers
about: Over
exploreFediverse: Ontdek de Fediverse
popularTags: Populaire labels
moderation: Moderatie
nUsersMentioned: Genoemd door {n} gebruikers
markAsReadAllUnreadNotes: Markeer alle posts als gelezen
markAsReadAllTalkMessages: Markeer alle berichten als gelezen
help: Help
inputMessageHere: Schrijf hier je bericht
close: Sluiten
group: Groep
groups: Groepen
newMessageExists: Er zijn nieuwe berichten
next: Volgende
noteOf: Post door {user}
inviteToGroup: Nodig uit voor de groep
quoteAttached: Quote
noMessagesYet: Nog geen berichten
weakPassword: Zwak wachtwoord
normalPassword: Middelmatig wachtwoord
strongPassword: Sterk wachtwoord
onlyOneFileCanBeAttached: Je kan maar één bestand toevoegen aan je bericht
invitationCode: Uitnodigingscode
checking: Controleren...
uiLanguage: Gebruikersinterface taal
aboutX: Over {x}
youHaveNoGroups: Je hebt geen groepen
disableAnimatedMfm: Schakel MFM met animaties uit
passwordMatched: Komt overeen
passwordNotMatched: Komt niet overeen
signinWith: Log in met {x}
fontSize: Tekstgrootte
openImageInNewTab: Open afbeeldingen in een nieuwe tab
category: Categorie
tags: Labels
existingAccount: Bestaand account
regenerate: Hernieuwen
dayOverDayChanges: Verschillen met gisteren
appearance: Uiterlijk
local: Lokaal
remote: Extern
total: Totaal
weekOverWeekChanges: Verschillen met vorige week
hcaptcha: hCaptcha
enableHcaptcha: hCaptcha inschakelen
hcaptchaSiteKey: Site sleutel
hcaptchaSecretKey: Geheime sleutel
withReplies: Met antwoorden
twoStepAuthentication: Tweefactorauthenticatie
moderator: Moderator
invitations: Uitnodigingen
tooLong: Te lang
doing: Verwerken...
silencedInstances: Gedempte Servers
cacheRemoteFilesDescription: Als deze instelling is uitgeschakeld, worden externe
bestanden direct van de externe server geladen. Het uitschakelen zal opslagruimte
verminderen, maar verkeer zal toenemen, omdat er geen thumbnails gemaakt zullen
worden.
flagSpeakAsCatDescription: Je posts zullen worden ge-'nyanified' als je in kat-modus
zit
avoidMultiCaptchaConfirm: Het gebruik van meerdere Captcha systemen kan voor storing
zorgen tussen ze. Wil je de andere actieve Captcha systemen uitschakelen? Als je
ze ingeschakeld wilt houden, klik op annuleren.
silence: Dempen
silenceConfirm: Weet je zeker dat je deze gebruiker wilt dempen?
unsilence: Ontdempen
unsilenceConfirm: Weet je zeker dat je het dempen van deze gebruiker ongedaan wilt
maken?
silenceThisInstance: Demp deze server
silenced: Gedempt
disablingTimelinesInfo: Beheerders en moderators zullen altijd toegang hebben tot
alle tijdlijnen, zelfs als deze uitgeschakeld zijn.
accountSettings: Account Instellingen
numberOfDays: Aantal dagen
hideThisNote: Verberg deze post
dashboard: Dashboard
accessibility: Toegankelijkheid
promotion: Gepromoot
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

View File

@ -1,2 +0,0 @@
---
_lang_: "Norsk Bokmål"

File diff suppressed because it is too large Load Diff

View File

@ -1,732 +0,0 @@
---
_lang_: "Português"
headlineMisskey: "Uma rede ligada por notas"
introMisskey: "Bem-vindo! Calckey é um serviço de microblogue descentralizado de código aberto.\nCria \"notas\" e partilha o que te ocorre com todos à tua volta. 📡\nCom \"reações\" podes também expressar logo o que sentes às notas de todos. 👍\nExploremos um novo mundo! 🚀"
monthAndDay: "{day}/{month}"
search: "Buscar"
notifications: "Notificações"
username: "Nome de usuário"
password: "Senha"
forgotPassword: "Esqueci a senha"
fetchingAsApObject: "Buscando no Fediverso"
ok: "OK"
gotIt: "Entendi"
cancel: "Cancelar"
enterUsername: "Digite o nome de usuário"
renotedBy: "Repostado por {user}"
noNotes: "Sem posts"
noNotifications: "Sem notificações"
instance: "Instância"
settings: "Configurações"
basicSettings: "Configurações básicas"
otherSettings: "Outras configurações"
openInWindow: "Abrir numa janela"
profile: "Perfil"
timeline: "Timeline"
noAccountDescription: "Este usuário não tem uma descrição."
login: "Iniciar sessão"
loggingIn: "Iniciando sessão…"
logout: "Sair"
signup: "Registrar-se"
uploading: "Enviando…"
save: "Guardar"
users: "Usuários"
addUser: "Adicionar usuário"
favorite: "Favoritar"
favorites: "Favoritar"
unfavorite: "Remover dos favoritos"
favorited: "Adicionado aos favoritos."
alreadyFavorited: "Já adicionado aos favoritos."
cantFavorite: "Não foi possível adicionar aos favoritos."
pin: "Afixar no perfil"
unpin: "Desafixar do perfil"
copyContent: "Copiar conteúdos"
copyLink: "Copiar hiperligação"
delete: "Eliminar"
deleteAndEdit: "Eliminar e editar"
deleteAndEditConfirm: "Tens a certeza que pretendes eliminar esta nota e editá-la? Irás perder todas as suas reações, renotas e respostas."
addToList: "Adicionar a lista"
sendMessage: "Enviar uma mensagem"
copyUsername: "Copiar nome de utilizador"
searchUser: "Pesquisar utilizador"
reply: "Responder"
loadMore: "Carregar mais"
showMore: "Ver mais"
showLess: "Fechar"
youGotNewFollower: "Você tem um novo seguidor"
receiveFollowRequest: "Pedido de seguimento recebido"
followRequestAccepted: "Pedido de seguir aceito"
mention: "Menção"
mentions: "Menções"
directNotes: "Notas diretas"
importAndExport: "Importar/Exportar"
import: "Importar"
export: "Exportar"
files: "Ficheiros"
download: "Descarregar"
driveFileDeleteConfirm: "Tens a certeza que pretendes apagar o ficheiro \"{name}\"? As notas que tenham este ficheiro anexado serão também apagadas."
unfollowConfirm: "Tens a certeza que queres deixar de seguir {name}?"
exportRequested: "Pediste uma exportação. Este processo pode demorar algum tempo. Será adicionado à tua Drive após a conclusão do processo."
importRequested: "Pediste uma importação. Este processo pode demorar algum tempo."
lists: "Listas"
noLists: "Não tens nenhuma lista"
note: "Post"
notes: "Posts"
following: "Seguindo"
followers: "Seguidores"
followsYou: "Segue-te"
createList: "Criar lista"
manageLists: "Gerir listas"
error: "Erro"
somethingHappened: "Ocorreu um erro"
retry: "Tentar novamente"
pageLoadError: "Ocorreu um erro ao carregar a página."
pageLoadErrorDescription: "Isto é normalmente causado por erros de rede ou pela cache do browser. Experimenta limpar a cache e tenta novamente após algum tempo."
serverIsDead: "O servidor não está respondendo. Por favor espere um pouco e tente novamente."
youShouldUpgradeClient: "Para visualizar essa página, por favor recarregue-a para atualizar seu cliente."
enterListName: "Insira um nome para a lista"
privacy: "Privacidade"
makeFollowManuallyApprove: "Pedidos de seguimento precisam ser aprovados"
defaultNoteVisibility: "Visibilidade padrão"
follow: "Seguindo"
followRequest: "Mandar pedido de seguimento"
followRequests: "Pedidos de seguimento"
unfollow: "Deixar de seguir"
followRequestPending: "Pedido de seguimento pendente"
enterEmoji: "Inserir emoji"
renote: "Repostar"
unrenote: "Desmarcar"
renoted: "Repostado"
cantRenote: "Não pode repostar"
cantReRenote: "Não pode repostar este repost"
quote: "Citar"
pinnedNote: "Post fixado"
pinned: "Afixar no perfil"
you: "Você"
clickToShow: "Clique para ver"
sensitive: "Conteúdo sensível"
add: "Adicionar"
reaction: "Reações"
reactionSetting: "Quais reações a mostrar no selecionador de reações"
reactionSettingDescription2: "Arraste para reordenar, clique para excluir, pressione + para adicionar."
rememberNoteVisibility: "Lembrar das configurações de visibilidade de notas"
attachCancel: "Remover anexo"
markAsSensitive: "Marcar como sensível"
unmarkAsSensitive: "Desmarcar como sensível"
enterFileName: "Digite o nome do ficheiro"
mute: "Silenciar"
unmute: "Dessilenciar"
block: "Bloquear"
unblock: "Desbloquear"
suspend: "Suspender"
unsuspend: "Cancelar suspensão"
blockConfirm: "Tem certeza que gostaria de bloquear essa conta?"
unblockConfirm: "Tem certeza que gostaria de desbloquear essa conta?"
suspendConfirm: "Tem certeza que gostaria de suspender essa conta?"
unsuspendConfirm: "Tem certeza que gostaria de cancelar a suspensão dessa conta?"
selectList: "Escolhe uma lista"
selectAntenna: "Escolhe uma antena"
selectWidget: "Escolhe um widget"
editWidgets: "Editar widgets"
editWidgetsExit: "Pronto"
customEmojis: "Emoji personalizado"
emoji: "Emoji"
emojis: "Emojis"
emojiName: "Nome do Emoji"
emojiUrl: "URL do Emoji"
addEmoji: "Adicionar um Emoji"
settingGuide: "Guia de configuração"
cacheRemoteFiles: "Memória transitória de arquivos remotos"
cacheRemoteFilesDescription: "Se você desabilitar essa configuração, os arquivos remotos não serão armazenados em memória transitória e serão vinculados diretamente. Economiza o armazenamento do servidor, mas não gera miniaturas, o que aumenta o tráfego."
flagAsBot: "Marcar conta como robô"
flagAsBotDescription: "Se esta conta for operada por um programa, ative este sinalizador. Quando ativado, serve como um sinalizador para evitar o encadeamento de reações para outros programadores, e o manuseio do sistema do Calckey é adequado para bots."
flagAsCat: "Marcar conta como gato"
flagAsCatDescription: "Ative essa opção para marcar essa conta como gato."
flagShowTimelineReplies: "Mostrar respostas na linha de tempo"
flagShowTimelineRepliesDescription: "Quando ativado, a linha do tempo mostra as respostas às outras notas do utilizador, além da nota do utilizador."
autoAcceptFollowed: "Aprove automaticamente os seguidores dos seguintes utilizadores"
addAccount: "Adicionar Conta"
loginFailed: "Não consegui logar"
showOnRemote: "Exibir remotamente"
general: "Geral"
wallpaper: "Papel de parede"
setWallpaper: "Definir papel de parede"
removeWallpaper: "Remover papel de parede"
searchWith: "Buscar: {q}"
youHaveNoLists: "Não tem nenhuma lista"
followConfirm: "Tem certeza que quer deixar de seguir {name}?"
proxyAccount: "Conta proxy"
proxyAccountDescription: "Uma conta proxy é uma conta que atua como seguidora remota para utilizadores sob determinadas condições. Por exemplo, quando um utilizador lista um utilizador remoto, a atividade não será entregue à instância, a menos que alguém esteja seguindo o utilizador listado, portanto, a conta proxy deve seguir."
host: "hospedeiro"
selectUser: "Selecionar utilizador"
recipient: "Morada"
annotation: "Anotação"
federation: "União"
instances: "Instância"
registeredAt: "Registrado em"
latestRequestSentAt: "Enviar a solicitação mais recente"
latestRequestReceivedAt: "Recebeu a última solicitação"
latestStatus: "Status mais recente"
storageUsage: "Uso de armazenamento"
charts: "gráfico"
perHour: "por hora"
perDay: "por dia"
stopActivityDelivery: "Parar a entrega de atividades"
blockThisInstance: "Bloquear esta instância"
operations: "operar"
software: "Programas"
version: "versão"
metadata: "Metadados"
monitor: "monitor"
jobQueue: "Fila de trabalhos"
cpuAndMemory: "CPU e memória"
network: "rede"
disk: "disco"
instanceInfo: "Informações da instância"
statistics: "Estatisticas"
clearQueue: "Limpar a fila"
clearQueueConfirmTitle: "Quer limpar a fila?"
clearQueueConfirmText: "Postagens não entregues não serão mais entregues. Normalmente você não precisa fazer isso."
clearCachedFiles: "Limpar memória transitória"
clearCachedFilesConfirm: "Tem certeza de que deseja excluir todos os arquivos remotos armazenados em memória transitória?"
blockedInstances: "Instância bloqueada"
blockedInstancesDescription: "Defina os anfitriões das instâncias que deseja bloquear, separados por quebras de linha. Uma instância bloqueada não poderá interagir com esta instância."
muteAndBlock: "Silenciar e bloquear"
mutedUsers: "Silenciar utilizador"
blockedUsers: "Utilizadores bloqueados"
noUsers: "Sem usuários"
editProfile: "Editar Perfil"
noteDeleteConfirm: "Deseja excluir esta nota?"
pinLimitExceeded: "Não consigo mais fixar"
intro: "A instalação do Calckey está completa! Crie uma conta de administrador."
done: "Concluído"
processing: "Em Progresso"
preview: "Pré-visualizar"
default: "Padrão"
noCustomEmojis: "Não há emojis"
noJobs: "Sem trabalho"
federating: "federar"
blocked: "Bloqueado"
suspended: "Cancelar subscrição"
all: "Todos"
subscribing: "Subscrito"
publishing: "Executando"
notResponding: "Sem resposta"
instanceFollowing: "Seguir a instância"
instanceFollowers: "Seguidores da instância"
instanceUsers: "Utilizador da instância"
changePassword: "Mudar senha"
security: "Segurança"
retypedNotMatch: "As entradas não coincidem."
currentPassword: "Palavra-passe atual"
newPassword: "Nova palavra-passe"
newPasswordRetype: "Nova senha (redigite)"
attachFile: "Anexar arquivo"
more: "Mais!"
featured: "Destaques"
usernameOrUserId: "Nome de utilizador ou ID de utilizador"
noSuchUser: "Utilizador não encontrado"
lookup: "Buscando"
announcements: "Notícia"
imageUrl: "URL da imagem"
remove: "Eliminar"
removed: "Foi deletado"
removeAreYouSure: "Deseja excluir \"{x}\"?"
deleteAreYouSure: "Deseja excluir \"{x}\"?"
resetAreYouSure: "Redefinir agora?"
saved: "Salvo"
messaging: "Chat"
upload: "Enviando"
keepOriginalUploading: "Manter a imagem original"
keepOriginalUploadingDescription: "Mantenha a versão original ao carregar a imagem. Quando desligado, a imagem para publicação na web será gerada no navegador no momento do upload."
fromDrive: "\nDa unidade"
fromUrl: "Da URL"
uploadFromUrl: "Carregamento de URL"
uploadFromUrlDescription: "URL do arquivo que você deseja enviar"
uploadFromUrlRequested: "Upload solicitado"
uploadFromUrlMayTakeTime: "Pode levar algum tempo para que o upload seja concluído."
explore: "Explorar"
messageRead: "Lida"
noMoreHistory: "Sem mais história"
startMessaging: "Iniciar conversação"
nUsersRead: "{n} Pessoas leem"
agreeTo: "Eu concordo com {0}"
tos: "Termos de serviço"
start: "começar"
home: "casa"
remoteUserCaution: "As informações estão incompletas porque é um utilizador remoto."
activity: "atividade"
images: "imagem"
birthday: "aniversário"
yearsOld: "{age} anos"
registeredDate: "Data de registro"
location: "Lugar, colocar"
theme: "tema"
themeForLightMode: "Temas usados no modo de luz"
themeForDarkMode: "Temas usados no modo escuro"
light: "Claro"
dark: "Escuro"
lightThemes: "Tema claro"
darkThemes: "Tema escuro"
syncDeviceDarkMode: "Sincronize com o modo escuro do dispositivo"
drive: "Unidades"
fileName: "Nome do Ficheiro"
selectFile: "Selecione os arquivos"
selectFiles: "Selecione os arquivos"
selectFolder: "Selecionar uma pasta"
selectFolders: "Selecionar uma pasta"
renameFile: "Renomear ficheiro"
folderName: "Nome da pasta"
createFolder: "Criar pasta"
renameFolder: "Renomear Pasta"
deleteFolder: "Eliminar Pasta"
addFile: "Adicionar arquivo"
emptyDrive: "A unidade está vazia"
emptyFolder: "A pasta está vazia"
unableToDelete: "Não é possível eliminar"
inputNewFileName: "Por favor, digite um novo nome para a pasta!"
inputNewDescription: "Insira uma nova legenda"
inputNewFolderName: "Por favor, digite um novo nome para a pasta!"
circularReferenceFolder: "A pasta de destino é uma subpasta da pasta que você deseja mover."
hasChildFilesOrFolders: "Esta pasta não está vazia e não pode ser excluída."
copyUrl: "Copiar URL"
rename: "Renomear"
avatar: "Avatar"
banner: "Capa"
nsfw: "Conteúdo sensível"
whenServerDisconnected: "Quando a conexão com o servidor é perdida"
disconnectedFromServer: "Desconectado do servidor"
reload: "Recarregar"
doNothing: "Nenhuma ação adicional"
reloadConfirm: "Quer recarregar?"
watch: "ver"
unwatch: "Não observar"
accept: "Aceitar"
reject: "Rejeitar"
normal: "Normal"
instanceName: "Nome da instância"
instanceDescription: "Descrição da instância"
maintainerName: "Nome do administrador"
maintainerEmail: "E-mail do Administrador:"
tosUrl: "URL dos Termos de Uso"
thisYear: "Este ano"
thisMonth: "Este mês"
today: "Hoje"
dayX: " Dia {day}"
monthX: "mês de {month}"
yearX: "Ano {year}"
pages: "Páginas"
integration: "Integração"
connectService: "Conectar"
disconnectService: "Desconectar"
enableLocalTimeline: "Ativar linha do tempo local"
enableGlobalTimeline: "Ativar linha do tempo global"
disablingTimelinesInfo: "Se você desabilitar essas linhas do tempo, administradores e moderadores ainda poderão usá-las por conveniência."
registration: "Registar"
enableRegistration: "Permitir que qualquer pessoa se registre"
invite: "Convidar"
driveCapacityPerLocalAccount: "Capacidade da unidade por utilizador local"
driveCapacityPerRemoteAccount: "Capacidade da unidade por utilizador remoto"
inMb: "Em megabytes"
iconUrl: "URL da imagem do ícone (favicon, etc.)"
bannerUrl: "URL da imagem do banner"
backgroundImageUrl: "URL da imagem de fundo"
basicInfo: "Informações básicas"
pinnedUsers: "Utilizador fixado"
pinnedUsersDescription: "Descreva os utilizadores que você deseja fixar na página \"Localizar\", etc., separados por quebras de linha."
pinnedPages: "Página fixada"
pinnedPagesDescription: "Descreva o caminho da página que você deseja fixar na página superior da instância, separada por quebras de linha."
pinnedClipId: "ID do clipe a ser fixado"
pinnedNotes: "Post fixado"
hcaptcha: "hCaptcha"
enableHcaptcha: "Ativar hCaptcha"
hcaptchaSiteKey: "Chave do sítio web"
hcaptchaSecretKey: "Chave secreta"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Habilitar reCAPTCHA"
recaptchaSiteKey: "Chave do sítio web"
recaptchaSecretKey: "Chave secreta"
avoidMultiCaptchaConfirm: "O uso de vários captchas pode causar interferência. Deseja desativar outros captchas? Você também pode cancelar e deixar vários captchas ativados."
antennas: "Antenas"
manageAntennas: "Gestão de antena"
name: "Nome"
antennaSource: "Origem de entrada"
antennaKeywords: "Palavras-chave recebidas"
antennaExcludeKeywords: "Palavras-chave negativas"
antennaKeywordsDescription: "Se você separá-lo com um espaço, será uma especificação AND, e se você separá-lo com uma quebra de linha, será uma especificação OR."
notifyAntenna: "Notificar novas notas"
withFileAntenna: "Apenas notas com arquivos anexados"
enableServiceworker: "Ative as notificações push para o seu navegador"
antennaUsersDescription: "Especificar nomes de utilizador separados por quebras de linha"
caseSensitive: "Maiúsculas e minúsculas"
withReplies: "Incluindo resposta"
connectedTo: "Você está conectado à seguinte conta"
notesAndReplies: "Publicações e respostas"
withFiles: "Com arquivo"
silence: "Silenciado"
silenceConfirm: "Quer silenciar?"
unsilence: "Liberar silenciar"
unsilenceConfirm: "Quer liberar o silêncio?"
popularUsers: "Utilizadores populares"
recentlyUpdatedUsers: "Utilizadores postados recentemente"
recentlyRegisteredUsers: "Utilizadores registrados recentemente"
recentlyDiscoveredUsers: "Utilizadores descobertos recentemente"
exploreUsersCount: "Há um utilizador de {count}"
exploreFediverse: "Explorar Fediverse"
popularTags: "Tags populares"
userList: "Listas"
about: "Informações"
aboutMisskey: "Sobre Calckey"
administrator: "Administrador"
token: "Símbolo"
twoStepAuthentication: "Verificação em duas etapas"
moderator: "Moderador"
nUsersMentioned: "Postado por {n} pessoas"
securityKey: "Chave de segurança"
securityKeyName: "Nome chave"
registerSecurityKey: "Registre a chave de segurança"
lastUsed: "Último uso"
unregister: "Cancelar registro"
passwordLessLogin: "Entrar sem senha"
resetPassword: "Redefinir senha"
newPasswordIs: "A nova senha é \"{password}\""
reduceUiAnimation: "Reduzir a animação da interface do utilizador"
share: "Compartilhar"
notFound: "Não encontrado"
notFoundDescription: "Não havia página correspondente ao URL especificado."
uploadFolder: "Destino de upload padrão"
cacheClear: "Excluir memória transitória"
markAsReadAllNotifications: "Marcar todas as notificações como lidas"
markAsReadAllUnreadNotes: "Marcar todas as postagens como lidas"
markAsReadAllTalkMessages: "Marcar todas as conversas como lidas"
help: "Ajuda"
inputMessageHere: "Escrever mensagem aqui"
close: "Fechar"
group: "Grupos"
groups: "Grupos"
createGroup: "Criar grupo"
ownedGroups: "Grupo próprio"
invites: "Convidar"
invitations: "Convidar"
tags: "Etiquetas"
docSource: "Fonte deste documento"
createAccount: "Criar conta"
existingAccount: "Contas existentes"
regenerate: "Gerar novamente"
fontSize: "Tamanho do texto"
noFollowRequests: "Não há aplicação de acompanhamento"
openImageInNewTab: "Abrir a imagem numa nova aba"
dashboard: "Painel de controle"
local: "Local"
remote: "Remoto"
total: "Total"
weekOverWeekChanges: "Em comparação com a semana anterior"
dayOverDayChanges: "Dia anterior"
appearance: "Aparência"
clientSettings: "Configurações do cliente"
accountSettings: "Configurações da conta"
promotion: "Promoção"
promote: "Promover"
numberOfDays: "Dias"
hideThisNote: "Ocultar esta nota"
showFeaturedNotesInTimeline: "Mostrar notas recomendadas na linha do tempo"
objectStorage: "Armazenamento de objetos"
useObjectStorage: "Usar armazenamento de objetos"
objectStorageBaseUrl: "URL base"
objectStorageBaseUrlDesc: "O URL usado para referência. Se você estiver usando um CDN ou Proxy, seu URL, S3:'https: // <bucket> .s3.amazonaws.com', GCS, etc .:'https://storage.googleapis.com/ <bucket>' ."
objectStorageBucket: "Bucket"
objectStorageBucketDesc: "Especifique o nome do bucket do serviço a ser usado."
objectStoragePrefix: "Prefixo"
objectStoragePrefixDesc: "Ele é armazenado neste diretório de prefixo."
objectStorageEndpoint: "Ponto final"
objectStorageEndpointDesc: "Especifique vazio para S3, caso contrário, especifique o ponto final para cada serviço. Especifique como'<host>'ou'<host>: <port>'."
objectStorageRegion: "Região"
objectStorageRegionDesc: "Especifique uma região como 'xx-east-1'. Caso seu serviço não tenha o conceito de região, ele deve estar vazio ou 'us-east-1'."
objectStorageUseSSL: "Usar SSL"
objectStorageUseSSLDesc: "Desative-o se não quiser usar https para conexões de API"
objectStorageUseProxy: "Usar proxy"
objectStorageUseProxyDesc: "Se você não usa proxy para conexão de API, desative-o."
objectStorageSetPublicRead: "Definir 'public-read' ao fazer o upload"
serverLogs: "Registro do servidor"
deleteAll: "Apagar Tudo"
showFixedPostForm: "Exibir o formulário de postagem na parte superior da linha do tempo"
newNoteRecived: "Nova nota recebida"
sounds: "Sons"
listen: "Ouvir"
none: "Nenhum"
showInPage: "Ver na página"
popout: "Sair"
volume: "Volume"
masterVolume: "volume principal"
details: "Detalhes"
output: "Resultado"
smtpHost: "hospedeiro"
smtpUser: "Nome de usuário"
smtpPass: "Senha"
clearCache: "Limpar memória transitória"
info: "Informações"
user: "Usuários"
searchByGoogle: "Buscar"
file: "Ficheiros"
_email:
_follow:
title: "Você tem um novo seguidor"
_mfm:
mention: "Menção"
quote: "Citar"
emoji: "Emoji personalizado"
search: "Buscar"
_theme:
keys:
mention: "Menção"
renote: "Repostar"
_sfx:
note: "Posts"
notification: "Notificações"
chat: "Chat"
_widgets:
notifications: "Notificações"
timeline: "Timeline"
activity: "atividade"
federation: "União"
jobQueue: "Fila de trabalhos"
_cw:
show: "Carregar mais"
_visibility:
home: "casa"
followers: "Seguidores"
_profile:
name: "Nome"
username: "Nome de usuário"
_exportOrImport:
followingList: "Seguindo"
muteList: "Silenciar"
blockingList: "Bloquear"
userLists: "Listas"
_charts:
federation: "União"
_timelines:
home: "casa"
_pages:
blocks:
image: "imagem"
_button:
_action:
_pushEvent:
event: "Nome do evento"
message: "Mostrar mensagem quando ativado"
variable: "Variável a mandar"
no-variable: "Nenhum"
callAiScript: "Invocar AiScript"
_callAiScript:
functionName: "Nome da função"
radioButton: "Escolha"
_radioButton:
values: "Lista de escolhas separadas por quebras de texto"
script:
categories:
logical: "Operação lógica"
operation: "Cálculos"
comparison: "Comparação"
list: "Listas"
blocks:
_strReplace:
arg2: "Texto que irá ser substituído"
arg3: "Substituir com"
strReverse: "Virar texto"
join: "Sequência de texto"
_join:
arg1: "Listas"
arg2: "Separador"
add: "Somar"
_add:
arg1: "A"
arg2: "B"
subtract: "Subtrair"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Multiplicar"
_multiply:
arg1: "A"
arg2: "B"
divide: "Dividir"
_divide:
arg1: "A"
arg2: "B"
mod: "O resto de"
_mod:
arg1: "A"
arg2: "B"
round: "Arredondar decimal"
_round:
arg1: "Numérico"
eq: "A e B são iguais"
_eq:
arg1: "A"
arg2: "B"
notEq: "A e B são diferentes"
_notEq:
arg1: "A"
arg2: "B"
and: "A e B"
_and:
arg1: "A"
arg2: "B"
or: "A OU B"
_or:
arg1: "A"
arg2: "B"
lt: "< A é menor do que B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A é maior do que B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A é maior ou igual a B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A é maior ou igual a B"
_gtEq:
arg1: "A"
arg2: "B"
if: "Galho"
_if:
arg1: "Se"
arg2: "Então"
arg3: "Se não"
not: "NÃO"
_not:
arg1: "NÃO"
random: "Aleatório"
_random:
arg1: "Probabilidade"
rannum: "Numeral aleatório"
_rannum:
arg1: "Valor mínimo"
arg2: "Valor máximo"
randomPick: "Escolher aleatoriamente de uma lista"
_randomPick:
arg1: "Listas"
dailyRandom: "Aleatório (Muda uma vez por dia para cada usuário)"
_dailyRandom:
arg1: "Probabilidade"
dailyRannum: "Numeral aleatório (Muda uma vez por dia para cada usuário)"
_dailyRannum:
arg1: "Valor mínimo"
arg2: "Valor máximo"
dailyRandomPick: "Escolher aleatoriamente de uma lista (Muda uma vez por dia para cada usuário)"
_dailyRandomPick:
arg1: "Listas"
seedRandom: "Aleatório (com semente)"
_seedRandom:
arg1: "Semente"
arg2: "Probabilidade"
seedRannum: "Número aleatório (com semente)"
_seedRannum:
arg1: "Semente"
arg2: "Valor mínimo"
arg3: "Valor máximo"
seedRandomPick: "Escolher aleatoriamente de uma lista (com uma semente)"
_seedRandomPick:
arg1: "Semente"
arg2: "Listas"
DRPWPM: "Escolher aleatoriamente de uma lista ponderada (Muda uma vez por dia para cada usuário)"
_DRPWPM:
arg1: "Lista de texto"
pick: "Escolhe a partir da lista"
_pick:
arg1: "Listas"
arg2: "Posição"
listLen: "Pegar comprimento da lista"
_listLen:
arg1: "Listas"
number: "Numérico"
stringToNumber: "Texto para numérico"
_stringToNumber:
arg1: "Texto"
numberToString: "Numérico para texto"
_numberToString:
arg1: "Numérico"
splitStrByLine: "Dividir texto por quebras"
_splitStrByLine:
arg1: "Texto"
ref: "Variável"
aiScriptVar: "Variável AiScript"
fn: "Função"
_fn:
slots: "Espaços"
slots-info: "Separar cada espaço com uma quebra de texto"
arg1: "Resultado"
for: "Repetição 'for'"
_for:
arg1: "Número de repetições"
arg2: "Ação"
typeError: "Espaço {slot} aceita valores de tipo \"{expect}\", mas o valor dado é do tipo \"{actual}\"!"
thereIsEmptySlot: "O espaço {slot} está vazio!"
types:
string: "Texto"
number: "Numérico"
array: "Listas"
stringArray: "Lista de texto"
emptySlot: "Espaço vazio"
enviromentVariables: "Variáveis de ambiente"
pageVariables: "Variáveis de página"
_relayStatus:
requesting: "Pendente"
accepted: "Aprovado"
rejected: "Recusado"
_notification:
fileUploaded: "Carregamento de arquivo efetuado com sucesso"
youGotMention: "{name} te mencionou"
youGotReply: "{name} te respondeu"
youGotQuote: "{name} te citou"
youGotPoll: "{name} votou em sua enquete"
youGotMessagingMessageFromUser: "{name} te mandou uma mensagem de bate-papo"
youGotMessagingMessageFromGroup: "Uma mensagem foi mandada para o grupo {name}"
youWereFollowed: "Você tem um novo seguidor"
youReceivedFollowRequest: "Você recebeu um pedido de seguimento"
yourFollowRequestAccepted: "Seu pedido de seguimento foi aceito"
youWereInvitedToGroup: "{userName} te convidou para um grupo"
pollEnded: "Os resultados da enquete agora estão disponíveis"
emptyPushNotificationMessage: "As notificações de alerta foram atualizadas"
_types:
all: "Todos"
follow: "Seguindo"
mention: "Menção"
reply: "Respostas"
renote: "Repostar"
quote: "Citar"
reaction: "Reações"
pollVote: "Votações em enquetes"
pollEnded: "Enquetes terminando"
receiveFollowRequest: "Recebeu pedidos de seguimento"
followRequestAccepted: "Aceitou pedidos de seguimento"
groupInvited: "Convites de grupo"
app: "Notificações de aplicativos conectados"
_actions:
followBack: "te seguiu de volta"
reply: "Responder"
renote: "Repostar"
_deck:
alwaysShowMainColumn: "Sempre mostrar a coluna principal"
columnAlign: "Alinhar colunas"
addColumn: "Adicionar coluna"
swapLeft: "Trocar de posição com a coluna à esquerda"
swapRight: "Trocar de posição com a coluna à direita"
swapUp: "Trocar de posição com a coluna acima"
swapDown: "Trocar de posição com a coluna abaixo"
popRight: "Acoplar coluna à direita"
profile: "Perfil"
_columns:
main: "Principal"
widgets: "Widgets"
notifications: "Notificações"
tl: "Timeline"
antenna: "Antenas"
list: "Listas"
mentions: "Menções"
direct: "Notas diretas"

View File

@ -1,87 +0,0 @@
username: Nome de usuário
ok: OK
_lang_: Inglês
headlineMisskey: Uma plataforma de mídia social descentralizada e de código aberto
que é gratuita para sempre! 🚀
search: Pesquisar
gotIt: Entendi!
introMisskey: Bem vinde! Calckey é uma plataforma de mídia social descentralizada
e de código aberto que é gratuita para sempre! 🚀
searchPlaceholder: Pesquise no Calckey
notifications: Notificações
password: Senha
forgotPassword: Esqueci a senha
cancel: Cancelar
noThankYou: Não, obrigade
save: Salvar
enterUsername: Insira nome de usuário
cw: Aviso de conteúdo
driveFileDeleteConfirm: Tem a certeza de que pretende apagar o arquivo "{name}"? O
arquivo será removido de todas as mensagens que o contenham como anexo.
deleteAndEdit: Deletar e editar
import: Importar
exportRequested: Você pediu uma exportação. Isso pode demorar um pouco. Será adicionado
ao seu Drive quando for completo.
note: Postar
notes: Postagens
deleteAndEditConfirm: Você tem certeza que quer deletar esse post e edita-lo? Você
vai perder todas as reações, impulsionamentos e respostas dele.
showLess: Fechar
importRequested: Você requisitou uma importação. Isso pode demorar um pouco.
listsDesc: Listas deixam você criar linhas do tempo com usuários específicos. Elas
podem ser acessadas pela página de linhas do tempo.
edited: 'Editado às {date} {time}'
sendMessage: Enviar uma mensagem
older: antigo
createList: Criar lista
loadMore: Carregar mais
mentions: Menções
importAndExport: Importar/Exportar Dados
files: Arquivos
lists: Listas
manageLists: Gerenciar listas
error: Erro
somethingHappened: Ocorreu um erro
retry: Tentar novamente
renotedBy: Impulsionado por {user}
noNotes: Nenhum post
noNotifications: Nenhuma notificação
instance: Servidor
settings: Configurações
basicSettings: Configurações Básicas
otherSettings: Outras Configurações
openInWindow: Abrir em janela
profile: Perfil
noAccountDescription: Esse usuário ainda não escreveu sua bio.
login: Entrar
loggingIn: Entrando
logout: Sair
signup: Criar conta
uploading: Enviando...
users: Usuários
addUser: Adicione um usuário
addInstance: Adicionar um servidor
cantFavorite: Não foi possível adicionar aos marcadores.
pin: Fixar no perfil
unpin: Desfixar do perfil
copyContent: Copiar conteúdos
copyLink: Copiar link
delete: Deletar
deleted: Deletado
editNote: Editar anotação
addToList: Adicionar a lista
copyUsername: Copiar nome de usuário
searchUser: Procurar por um usuário
reply: Responder
jumpToPrevious: Pular para o anterior
showMore: Mostrar mais
newer: novo
youGotNewFollower: seguiu você
mention: Mencionar
directNotes: Mensagens diretas
export: Exportar
unfollowConfirm: Você tem certez que deseja para de seguir {name}?
noLists: Você não possui nenhuma lista
following: Seguindo
followers: Seguidores
followsYou: Segue você

View File

@ -1,727 +0,0 @@
---
_lang_: "Română"
headlineMisskey: "O rețea conectată prin note"
introMisskey: "Bine ai venit! Calckey este un serviciu de microblogging open source și decentralizat.\nCreează \"note\" cu care să îți poți împărți gândurile cu oricine din jurul tău. 📡\nCu \"reacții\" îți poți expirma rapid părerea despre notele oricui. 👍\nHai să explorăm o lume nouă! 🚀"
monthAndDay: "{day}/{month}"
search: "Caută"
notifications: "Notificări"
username: "Nume de utilizator"
password: "Parolă"
forgotPassword: "Am uitat parola"
fetchingAsApObject: "Se aduce din Fediverse"
ok: "OK"
gotIt: "Am înțeles!"
cancel: "Anulează"
enterUsername: "Introdu numele de utilizator"
renotedBy: "Re-notat de {user}"
noNotes: "Nicio notă"
noNotifications: "Nicio notificare"
instance: "Instanță"
settings: "Setări"
basicSettings: "Setări generale"
otherSettings: "Alte Setări"
openInWindow: "Deschide într-o fereastră"
profile: "Profil"
timeline: "Cronologie"
noAccountDescription: "Acest utilizator încă nu a scris un bio."
login: "Autentifică-te"
loggingIn: "Se autentifică"
logout: "Deconectează-te"
signup: "Înregistrează-te"
uploading: "Se încarcă"
save: "Salvează"
users: "Utilizatori"
addUser: "Adăugă utilizator"
favorite: "Adaugă la favorite"
favorites: "Favorite"
unfavorite: "Elimină din favorite"
favorited: "Adăugat la favorite."
alreadyFavorited: "Deja adăugat la favorite."
cantFavorite: "Nu se poate adăuga la favorite."
pin: "Fixează pe profil"
unpin: "Anulati fixare"
copyContent: "Copiază conținutul"
copyLink: "Copiază link-ul"
delete: "Şterge"
deleteAndEdit: "Șterge și editează"
deleteAndEditConfirm: "Ești sigur că vrei să ștergi această notă și să o editezi? Vei pierde reacțiile, re-notele și răspunsurile acesteia."
addToList: "Adaugă în listă"
sendMessage: "Trimite un mesaj"
copyUsername: "Copiază numele de utilizator"
searchUser: "Caută un utilizator"
reply: "Răspunde"
loadMore: "Incarcă mai mult"
showMore: "Arată mai mult"
showLess: "Închide"
youGotNewFollower: "te-a urmărit"
receiveFollowRequest: "Cerere de urmărire primită"
followRequestAccepted: "Cerere de urmărire acceptată"
mention: "Mențiune"
mentions: "Mențiuni"
directNotes: "Note directe"
importAndExport: "Importă / Exportă"
import: "Importă"
export: "Exportă"
files: "Fișiere"
download: "Descarcă"
driveFileDeleteConfirm: "Ești sigur ca vrei să ștergi fișierul \"{name}\"? Notele atașate fișierului vor fi șterse și ele."
unfollowConfirm: "Ești sigur ca vrei să nu mai urmărești pe {name}?"
exportRequested: "Ai cerut un export. S-ar putea să ia un pic. Va fi adăugat in Drive-ul tău odată completat."
importRequested: "Ai cerut un import. S-ar putea să ia un pic."
lists: "Liste"
noLists: "Nu ai nici o listă"
note: "Notă"
notes: "Note"
following: "Urmărești"
followers: "Urmăritori"
followsYou: "Te urmărește"
createList: "Creează listă"
manageLists: "Gestionează listele"
error: "Eroare"
somethingHappened: "A survenit o eroare"
retry: "Reîncearcă"
pageLoadError: "A apărut o eroare la încărcarea paginii."
pageLoadErrorDescription: "De obicei asta este cauzat de o eroare de rețea sau cache-ul browser-ului. Încearcă să cureți cache-ul și apoi să încerci din nou puțin mai târziu."
serverIsDead: "Serverul nu răspunde. Te rugăm să aștepți o perioadă și să încerci din nou."
youShouldUpgradeClient: "Pentru a vedea această pagină, te rugăm să îți actualizezi clientul."
enterListName: "Introdu un nume pentru listă"
privacy: "Confidenţialitate"
makeFollowManuallyApprove: "Fă cererile de urmărire să necesite aprobare"
defaultNoteVisibility: "Vizibilitate implicită"
follow: "Urmărești"
followRequest: "Trimite cerere de urmărire"
followRequests: "Cereri de urmărire"
unfollow: "Nu mai urmări"
followRequestPending: "Cerere de urmărire în așteptare"
enterEmoji: "Introdu un emoji"
renote: "Re-notează"
unrenote: "Ia înapoi re-nota"
renoted: "Re-notat."
cantRenote: "Această postare nu poate fi re-notată."
cantReRenote: "O re-notă nu poate fi re-notată."
quote: "Citează"
pinnedNote: "Notă fixată"
pinned: "Fixat pe profil"
you: "Tu"
clickToShow: "Click pentru a afișa"
sensitive: "NSFW"
add: "Adaugă"
reaction: "Reacție"
reactionSetting: "Reacții care să apară in selectorul de reacții"
reactionSettingDescription2: "Trage pentru a rearanja, apasă pe \"+\" pentru a adăuga."
rememberNoteVisibility: "Amintește setarea de vizibilitate a notelor"
attachCancel: "Înlătură atașament"
markAsSensitive: "Marchează ca NSFW"
unmarkAsSensitive: "Demarchează ca NSFW"
enterFileName: "Introduceţi numele fişierului"
mute: "Amuțește"
unmute: "Înlătură amuțirea"
block: "Blochează"
unblock: "Deblochează"
suspend: "Suspendă"
unsuspend: "Anulează suspendare"
blockConfirm: "Ești sigur că vrei să blochezi acest cont?"
unblockConfirm: "Ești sigur ca vrei să deblochezi acest cont?"
suspendConfirm: "Ești sigur ca vrei să suspendezi acest cont?"
unsuspendConfirm: "Ești sigur ca vrei să nu mai suspendezi acest cont?"
selectList: "Selectează o listă"
selectAntenna: "Selectează o antenă"
selectWidget: "Selectați un widget"
editWidgets: "Editează widget-urile"
editWidgetsExit: "Terminat"
customEmojis: "Emoji personalizat"
emoji: "Emoji"
emojis: "Emoji-uri"
emojiName: "Numele emoji-ului"
emojiUrl: "URL-ul emoji-ului"
addEmoji: "Adaugă un emoji"
settingGuide: "Setări recomandate"
cacheRemoteFiles: "Ține fișierele externe in cache"
cacheRemoteFilesDescription: "Când această setare este dezactivată, fișierele externe sunt încărcate direct din instanța externă. Dezactivarea va scădea utilizarea spațiului de stocare, dar va crește traficul, deoarece thumbnail-urile nu vor fi generate."
flagAsBot: "Marchează acest cont ca bot"
flagAsBotDescription: "Activează această opțiune dacă acest cont este controlat de un program. Daca e activată, aceasta va juca rolul unui indicator pentru dezvoltatori pentru a preveni interacțiunea în lanțuri infinite cu ceilalți boți și ajustează sistemele interne al Calckey pentru a trata acest cont drept un bot."
flagAsCat: "Marchează acest cont ca pisică"
flagAsCatDescription: "Activează această opțiune dacă acest cont este o pisică."
flagShowTimelineReplies: "Arată răspunsurile în cronologie"
flagShowTimelineRepliesDescription: "Dacă e activată vor fi arătate în cronologie răspunsurile utilizatorilor către alte notele altor utilizatori."
autoAcceptFollowed: "Aprobă automat cererile de urmărire de la utilizatorii pe care îi urmărești"
addAccount: "Adaugă un cont"
loginFailed: "Autentificare eșuată"
showOnRemote: "Vezi mai multe pe instanța externă"
general: "General"
wallpaper: "Imagine de fundal"
setWallpaper: "Setați imaginea de fundal"
removeWallpaper: "Șterge imagine de fundal"
searchWith: "Caută: {q}"
youHaveNoLists: "Nu ai nici o listă"
followConfirm: "Ești sigur ca vrei să urmărești pe {name}?"
proxyAccount: "Cont proxy"
proxyAccountDescription: "Un cont proxy este un cont care se comportă ca un urmăritor extern pentru utilizatorii puși sub anumite condiții. De exemplu, când un cineva adaugă un utilizator extern intr-o listă, activitatea utilizatorului extern nu va fi adusă în instanță daca nici un utilizator local nu urmărește acel utilizator, așa că în schimb contul proxy îl va urmări."
host: "Gazdă"
selectUser: "Selectează un utilizator"
recipient: "Destinatar"
annotation: "Adnotări"
federation: "Federație"
instances: "Instanțe"
registeredAt: "Înregistrat în"
latestRequestSentAt: "Ultima cerere trimisă"
latestRequestReceivedAt: "Ultima cerere primită"
latestStatus: "Ultimul status"
storageUsage: "Utilizare stocare"
charts: "Diagrame"
perHour: "Pe oră"
perDay: "Pe zi"
stopActivityDelivery: "Nu mai trimite activități"
blockThisInstance: "Blochează această instanță"
operations: "Operațiuni"
software: "Software"
version: "Versiune"
metadata: "Metadata"
monitor: "Monitor"
jobQueue: "coada de job-uri"
cpuAndMemory: "CPU și memorie"
network: "Rețea"
disk: "Disk"
instanceInfo: "Informații despre instanță"
statistics: "Statistici"
clearQueue: "Șterge coada"
clearQueueConfirmTitle: "Ești sigur că vrei să cureți coada?"
clearQueueConfirmText: "Orice notă rămasă în coadă nu va fi federată. De obicei această operație nu este necesară."
clearCachedFiles: "Golește cache-ul"
clearCachedFilesConfirm: "Ești sigur că vrei să ștergi toate fișierele externe din cache?"
blockedInstances: "Instanțe blocate"
blockedInstancesDescription: "Scrie hostname-urile instanțelor pe care dorești să le blochezi. Instanțele listate nu vor mai putea să comunice cu această instanță."
muteAndBlock: "Amuțiri și Blocări"
mutedUsers: "Utilizatori amuțiți"
blockedUsers: "Utilizatori blocați"
noUsers: "Niciun utilizator"
editProfile: "Editează profilul"
noteDeleteConfirm: "Ești sigur că vrei să ștergi această notă?"
pinLimitExceeded: "Nu poți mai fixa mai multe note"
intro: "Calckey s-a instalat! Te rog crează un utilizator admin."
done: "Gata"
processing: "Se procesează"
preview: "Previzualizare"
default: "Prestabilit"
noCustomEmojis: "Nu e niciun emoji"
noJobs: "Nu e niciun job"
federating: "Federație"
blocked: "Blocat"
suspended: "Suspendat"
all: "Tot"
subscribing: "Abonare"
publishing: "Publicare"
notResponding: "Nu răspunde"
instanceFollowing: "Urmărind în instanță"
instanceFollowers: "Urmăritori ai instanței"
instanceUsers: "Utilizatori ai acestei instanțe"
changePassword: "Schimbă parolă"
security: "Securitate"
retypedNotMatch: "Intrările nu corespund"
currentPassword: "Parola curentă"
newPassword: "Parola nouă"
newPasswordRetype: "Rescrie parola nouă"
attachFile: "Atașează fișiere"
more: "Mai mult!"
featured: "Evidențiat"
usernameOrUserId: "Nume sau ID de utilizator"
noSuchUser: "Utilizatorul nu a fost găsit"
lookup: "Privire"
announcements: "Anunțuri"
imageUrl: "URL-ul imaginii"
remove: "Şterge"
removed: "Șterș cu succes"
removeAreYouSure: "Ești sigur că vrei să înlături {x}?"
deleteAreYouSure: "Ești sigur că vrei să ștergi {x}?"
resetAreYouSure: "Sigur vrei să resetezi?"
saved: "Salvat"
messaging: "Chat"
upload: "Încarcă"
keepOriginalUploading: "Păstrează imaginea originală"
keepOriginalUploadingDescription: "Salvează imaginea originala încărcată fără modificări. Dacă e oprită, o versiune pentru afișarea pe web va fi generată la încărcare."
fromDrive: "Din Drive"
fromUrl: "Din URL"
uploadFromUrl: "Încarcă dintr-un URL"
uploadFromUrlDescription: "URL-ul fișierului pe care dorești să îl încarci"
uploadFromUrlRequested: "Încărcare solicitată"
uploadFromUrlMayTakeTime: "S-ar putea să ia puțin până se finalizează încărcarea."
explore: "Explorează"
messageRead: "Citit"
noMoreHistory: "Nu există mai mult istoric"
startMessaging: "Începe un chat nou"
nUsersRead: "citit de {n}"
agreeTo: "Sunt de acord cu {0}"
tos: "Termenii de utilizare"
start: "Să începem"
home: "Acasă"
remoteUserCaution: "Deoarece acest utilizator este dintr-o instanță externă, informația afișată poate fi incompletă."
activity: "Activitate"
images: "Imagini"
birthday: "Zi de naștere"
yearsOld: "{age} ani"
registeredDate: "Data înregistrării"
location: "Locație"
theme: "Teme"
themeForLightMode: "Temă folosită pentru Modul Luminat"
themeForDarkMode: "Temă folosită pentru Modul Întunecat"
light: "Luminos"
dark: "Întunecat"
lightThemes: "Teme luminoase"
darkThemes: "Teme întunecate"
syncDeviceDarkMode: "Sincronizează Modul Întunecat cu setările dispozitivului"
drive: "Drive"
fileName: "Nume fișier"
selectFile: "Alege un fisier"
selectFiles: "Alege fișiere"
selectFolder: "Selectează un folder"
selectFolders: "Selectează folderele"
renameFile: "Redenumește fișier"
folderName: "Nume folder"
createFolder: "Crează folder"
renameFolder: "Redenumește acest folder"
deleteFolder: "Șterge acest folder"
addFile: "Adăugați un fișier"
emptyDrive: "Drive-ul tău e gol"
emptyFolder: "Folder-ul acesta este gol"
unableToDelete: "Nu se poate șterge"
inputNewFileName: "Introdu un nou nume de fișier"
inputNewDescription: "Introdu o descriere nouă"
inputNewFolderName: "Introdu un nume de folder nou"
circularReferenceFolder: "Destinația folderului este un subfolder al folderului pe care dorești să îl muți."
hasChildFilesOrFolders: "Acest folder nu este gol, așa că nu poate fi șters."
copyUrl: "Copiază URL"
rename: "Redenumește"
avatar: "Avatar"
banner: "Banner"
nsfw: "NSFW"
whenServerDisconnected: "Când pierzi conexiunea cu serverul"
disconnectedFromServer: "Conecțiunea cu serverul a fost pierdută"
reload: "Reîncarcă"
doNothing: "Ignoră"
reloadConfirm: "Ai dori să reîmprospătezi cronologia?"
watch: "Vezi"
unwatch: "Oprește-te din văzut"
accept: "Acceptă"
reject: "Respinge"
normal: "Normal"
instanceName: "Numele instanței"
instanceDescription: "Descrierea instanței"
maintainerName: "Administrator"
maintainerEmail: "Email-ul administratorului"
tosUrl: "URL-ul Termenilor de utilizare"
thisYear: "An"
thisMonth: "Lună"
today: "Azi"
dayX: "{day}"
monthX: "{month}"
yearX: "{year}"
pages: "Pagini"
integration: "Integrare"
connectService: "Conectează"
disconnectService: "Deconectează"
enableLocalTimeline: "Activează cronologia locală"
enableGlobalTimeline: "Activeaza cronologia globală"
disablingTimelinesInfo: "Administratorii și Moderatorii vor avea mereu access la toate cronologiile, chiar dacă nu sunt activate."
registration: "Inregistrare"
enableRegistration: "Activează înregistrările pentru utilizatori noi"
invite: "Invită"
driveCapacityPerLocalAccount: "Capacitatea Drive-ului per utilizator local"
driveCapacityPerRemoteAccount: "Capacitatea Drive-ului per utilizator extern"
inMb: "În megabytes"
iconUrl: "URL-ul iconiței"
bannerUrl: "URL-ul imaginii de banner"
backgroundImageUrl: "URL-ul imaginii de fundal"
basicInfo: "Informații de bază"
pinnedUsers: "Utilizatori fixați"
pinnedUsersDescription: "Scrie utilizatorii, separați prin pauză de rând, care vor fi fixați pe pagina \"Explorează\"."
pinnedPages: "Pagini fixate"
pinnedPagesDescription: "Introdu linkurile Paginilor pe care le vrei fixate in vâruful paginii acestei instanțe, separate de pauze de rând."
pinnedClipId: "ID-ul clip-ului pe care să îl fixezi"
pinnedNotes: "Notă fixată"
hcaptcha: "hCaptcha"
enableHcaptcha: "Activează hCaptcha"
hcaptchaSiteKey: "Site key"
hcaptchaSecretKey: "Secret key"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Activează reCAPTCHA"
recaptchaSiteKey: "Site key"
recaptchaSecretKey: "Secret key"
avoidMultiCaptchaConfirm: "Folosirea mai multor sisteme Captcha poate cauza interferență între acestea. Ai dori să dezactivezi alte sisteme Captcha acum active? Dacă preferi să rămână activate, apasă Anulare."
antennas: "Antene"
manageAntennas: "Gestionează Antenele"
name: "Nume"
antennaSource: "Sursa antenei"
antennaKeywords: "Cuvinte cheie ascultate"
antennaExcludeKeywords: "Cuvinte cheie excluse"
antennaKeywordsDescription: "Separă cu spații pentru o condiție ȘI sau cu o întrerupere de rând pentru o condiție SAU."
notifyAntenna: "Notifică-mă pentru note noi"
withFileAntenna: "Doar note cu fișiere"
enableServiceworker: "Activează ServiceWorker"
antennaUsersDescription: "Scrie un nume de utilizator per linie"
caseSensitive: "Sensibil la majuscule și minuscule"
withReplies: "Include răspunsuri"
connectedTo: "Următoarele conturi sunt conectate"
notesAndReplies: "Note și răspunsuri"
withFiles: "Incluzând fișiere"
silence: "Amuțește"
silenceConfirm: "Ești sigur că vrei să amuțești acest utilizator?"
unsilence: "Anulează amuțirea"
unsilenceConfirm: "Ești sigur că vrei să anulezi amuțirea acestui utilizator?"
popularUsers: "Utilizatori populari"
recentlyUpdatedUsers: "Utilizatori activi recent"
recentlyRegisteredUsers: "Utilizatori ce s-au alăturat recent"
recentlyDiscoveredUsers: "Utilizatori descoperiți recent"
exploreUsersCount: "Aici sunt {count} utilizatori"
exploreFediverse: "Explorează Fediverse-ul"
popularTags: "Taguri populare"
userList: "Liste"
about: "Despre"
aboutMisskey: "Despre Calckey"
administrator: "Administrator"
token: "Token"
twoStepAuthentication: "Autentificare în doi pași"
moderator: "Moderator"
nUsersMentioned: "Menționat de {n} utilizatori"
securityKey: "Cheie de securitate"
securityKeyName: "Numele cheii"
registerSecurityKey: "Înregistrează o cheie de securitate"
lastUsed: "Ultima utilizată"
unregister: "Dezînregistrează"
passwordLessLogin: "Autentificare fără parolă"
resetPassword: "Resetează parola"
newPasswordIs: "Noua parolă este \"{password}\""
reduceUiAnimation: "Redu animațiile interfeței"
share: "Distribuie"
notFound: "Nu a fost găsit"
notFoundDescription: "N-a fost găsită nicio pagină cu acest URL."
uploadFolder: "Folder implicit pentru încărcări"
cacheClear: "Golește cache-ul"
markAsReadAllNotifications: "Marchează toate notificările drept citit"
markAsReadAllUnreadNotes: "Marchează toate notele drept citit"
markAsReadAllTalkMessages: "Marchează toate mesajele drept citit"
help: "Ajutor"
inputMessageHere: "Introdu un mesaj aici"
close: "Închide"
group: "Grup"
groups: "Grupuri"
createGroup: "Crează un grup"
ownedGroups: "Grupuri deținute"
joinedGroups: "Grupuri alăturate"
invites: "Invită"
groupName: "Numele grupului"
members: "Membri"
transfer: "Transferă"
messagingWithUser: "Chat privat"
messagingWithGroup: "Chat de grup"
title: "Titlu"
text: "Text"
enable: "Activează"
next: "Următorul"
retype: "Introdu din nou"
noteOf: "Notă de {user}"
inviteToGroup: "Invită în grup"
quoteAttached: "Citat"
quoteQuestion: "Vrei să adaugi ca citat?"
noMessagesYet: "Niciun mesaj încă"
newMessageExists: "Ai mesaje noi"
onlyOneFileCanBeAttached: "Poți atașa un singur fișier la un mesaj"
signinRequired: "Te rog autentifică-te"
invitations: "Invită"
invitationCode: "Cod de invitație"
checking: "Se verifică..."
available: "Disponibil"
unavailable: "Indisponibil"
usernameInvalidFormat: "Poți folosi litere mari și mici, numere și underscore-uri."
tooShort: "Prea scurt"
tooLong: "Prea lung"
weakPassword: "Parolă slabă"
normalPassword: "Parolă medie"
strongPassword: "Parolă puternică"
passwordMatched: "Se potrivește!"
passwordNotMatched: "Nu se potrivește"
signinWith: "Autentifică-te cu {x}"
signinFailed: "Nu se poate autentifica. Numele de utilizator sau parola introduse sunt incorecte."
tapSecurityKey: "Apasă pe cheia ta de securitate."
or: "Sau"
language: "Limbă"
uiLanguage: "Limba interfeței"
groupInvited: "Ai fost invitat într-un grup"
aboutX: "Despre {x}"
useOsNativeEmojis: "Folosește emojiuri native OS-ului"
disableDrawer: "Nu folosi meniuri în stil sertar"
youHaveNoGroups: "Nu ai niciun grup"
joinOrCreateGroup: "Primește o invitație într-un grup sau creează unul nou."
noHistory: "Nu există istoric"
signinHistory: "Istoric autentificări"
disableAnimatedMfm: "Dezactivează MFM cu animații"
doing: "Se procesează..."
category: "Categorie"
tags: "Etichete"
docSource: "Sursa acestui document"
createAccount: "Creează un cont"
existingAccount: "Cont existent"
regenerate: "Regenerează"
fontSize: "Mărimea fontului"
noFollowRequests: "Nu ai nicio cerere de urmărire în așteptare"
openImageInNewTab: "Deschide imaginile în taburi noi"
dashboard: "Panou de control"
local: "Local"
remote: "Extern"
total: "Total"
weekOverWeekChanges: "Schimbări până săptămâna trecută"
dayOverDayChanges: "Schimbări până ieri"
appearance: "Aspect"
clientSettings: "Setări client"
accountSettings: "Setări cont"
promotion: "Promovat"
promote: "Promovează"
numberOfDays: "Numărul zilelor"
hideThisNote: "Ascunde această notă"
showFeaturedNotesInTimeline: "Arată notele recomandate în cronologii"
objectStorage: "Object Storage"
useObjectStorage: "Folosește Object Storage"
objectStorageBaseUrl: "URL de bază"
objectStorageBaseUrlDesc: "URL-ul este folosit pentru referință. Specifică URL-ul CDN-ului sau Proxy-ului tău dacă folosești unul. Pentru S3 folosește 'https://<bucket>.s3.amazonaws.com' și pentru GCS sau servicii echivalente folosește 'https://storage.googleapis.com/<bucket>', etc."
objectStorageBucket: "Bucket"
objectStorageBucketDesc: "Te rog specifică numele bucket-ului furnizorului tău."
objectStoragePrefix: "Prefix"
objectStoragePrefixDesc: "Fișierele vor fi stocate sub directoare cu acest prefix."
objectStorageEndpoint: "Endpoint"
objectStorageEndpointDesc: "Lasă acest câmp gol dacă folosești AWS S3, dacă nu specifică endpoint-ul ca '<host>' sau '<host>:<port>', depinzând de ce serviciu folosești."
objectStorageRegion: "Regiune"
objectStorageRegionDesc: "Specifică o regiune precum 'xx-east-1'. Dacă serviciul tău nu face distincția între regiuni lasă acest câmp gol sau introdu 'us-east-1'."
objectStorageUseSSL: "Folosește SSl"
objectStorageUseSSLDesc: "Oprește această opțiune dacă nu vei folosi HTTPS pentru conexiunile API-ului"
objectStorageUseProxy: "Conectează-te prin Proxy"
objectStorageUseProxyDesc: "Oprește această opțiune dacă vei nu folosi un Proxy pentru conexiunile API-ului"
objectStorageSetPublicRead: "Setează \"public-read\" pentru încărcare"
serverLogs: "Loguri server"
deleteAll: "Șterge tot"
showFixedPostForm: "Arată caseta de postare în vârful cronologie"
newNoteRecived: "Sunt note noi"
sounds: "Sunete"
listen: "Ascultă"
none: "Nimic"
showInPage: "Arată în pagină"
popout: "Scoate în afară"
volume: "Volum"
masterVolume: "Volumul principal"
details: "Detalii"
chooseEmoji: "Alege un emoji"
unableToProcess: "Această operație nu poate fi completată"
recentUsed: "Folosit recent"
install: "Instalează"
uninstall: "Dezinstalează"
installedApps: "Aplicații autorizate"
nothing: "Nu e nimic de văzut aici"
installedDate: "Autorizat la data de"
lastUsedDate: "Folosit ultima oara la"
state: "Stare"
sort: "Sortează"
ascendingOrder: "Crescător"
descendingOrder: "Descrescător"
scratchpad: "Scratchpad"
scratchpadDescription: "Scratchpad-ul oferă un mediu de experimentare în AiScript. Poți scrie, executa și verifica rezultatele acestuia interacționând cu Calckey în el."
output: "Ieșire"
script: "Script"
disablePagesScript: "Dezactivează AiScript în Pagini"
updateRemoteUser: "Actualizează informațiile utilizatorului extern"
deleteAllFiles: "Șterge toate fișierele"
deleteAllFilesConfirm: "Ești sigur că vrei să ștergi toate fișierele?"
removeAllFollowing: "Dezurmărește toți utilizatorii urmăriți"
removeAllFollowingDescription: "Asta va dez-urmări toate conturile din {host}. Te rog execută asta numai dacă instanța, de ex., nu mai există."
userSuspended: "Acest utilizator a fost suspendat."
userSilenced: "Acest utilizator a fost setat silențios."
yourAccountSuspendedTitle: "Acest cont a fost suspendat"
yourAccountSuspendedDescription: "Acest cont a fost suspendat din cauza încălcării termenilor de serviciu al serverului sau ceva similar. Contactează administratorul dacă ai dori să afli un motiv mai detaliat. Te rog nu crea un cont nou."
menu: "Meniu"
divider: "Separator"
addItem: "Adaugă element"
relays: "Relee"
addRelay: "Adaugă Releu"
inboxUrl: "URL-ul inbox-ului"
addedRelays: "Relee adăugate"
serviceworkerInfo: "Trebuie să fie activat pentru notificări push."
deletedNote: "Notă ștearsă"
invisibleNote: "Note ascunse"
enableInfiniteScroll: "Încarcă mai mult automat"
visibility: "Vizibilitate"
poll: "Sondaj"
useCw: "Ascunde conținutul"
enablePlayer: "Deschide player-ul video"
disablePlayer: "Închide player-ul video"
expandTweet: "Expandează tweet"
themeEditor: "Editor de teme"
description: "Descriere"
describeFile: "Adaugă titrări"
enterFileDescription: "Introdu titrările"
author: "Autor"
leaveConfirm: "Ai schimbări nesalvate. Vrei să renunți la ele?"
manage: "Gestionare"
plugins: "Pluginuri"
deck: "Deck"
undeck: "Părăsește Deck"
useBlurEffectForModal: "Folosește efect de blur pentru modale"
width: "Lăţime"
height: "Înălţime"
large: "Mare"
medium: "Mediu"
small: "Mic"
generateAccessToken: "Generează token de acces"
permission: "Permisiuni"
enableAll: "Actevează tot"
disableAll: "Dezactivează tot"
tokenRequested: "Acordă acces la cont"
pluginTokenRequestedDescription: "Acest plugin va putea să folosească permisiunile setate aici."
notificationType: "Tipul notificării"
edit: "Editează"
emailServer: "Server email"
enableEmail: "Activează distribuția de emailuri"
emailConfigInfo: "Folosit pentru a confirma emailul tău în timpul logări dacă îți uiți parola"
email: "Email"
emailAddress: "Adresă de email"
smtpConfig: "Configurare Server SMTP"
smtpHost: "Gazdă"
smtpPort: "Port"
smtpUser: "Nume de utilizator"
smtpPass: "Parolă"
emptyToDisableSmtpAuth: "Lasă username-ul și parola necompletate pentru a dezactiva verificarea SMTP"
smtpSecure: "Folosește SSL/TLS implicit pentru conecțiunile SMTP"
smtpSecureInfo: "Oprește opțiunea asta dacă STARTTLS este folosit"
testEmail: "Testează livrarea emailurilor"
wordMute: "Cuvinte pe mut"
regexpError: "Eroare de Expresie Regulată"
regexpErrorDescription: "A apărut o eroare în expresia regulată pe linia {line} al cuvintelor {tab} setate pe mut:"
instanceMute: "Instanțe pe mut"
userSaysSomething: "{name} a spus ceva"
makeActive: "Activează"
display: "Arată"
copy: "Copiază"
metrics: "Metrici"
overview: "Privire de ansamblu"
logs: "Log-uri"
delayed: "Întârziate"
database: "Baza de date"
channel: "Canale"
create: "Crează"
notificationSetting: "Setări notificări"
notificationSettingDesc: "Selectează tipurile de notificări care să fie arătate"
useGlobalSetting: "Folosește setările globale"
useGlobalSettingDesc: "Dacă opțiunea e pornită, notificările contului tău vor fi folosite. Dacă e oprită, configurația va fi individuală."
other: "Altele"
regenerateLoginToken: "Regenerează token de login"
regenerateLoginTokenDescription: "Regenerează token-ul folosit intern în timpul logări. În mod normal asta nu este necesar. Odată regenerat, toate dispozitivele vor fi delogate."
setMultipleBySeparatingWithSpace: "Separă mai multe intrări cu spații."
fileIdOrUrl: "Introdu ID sau URL"
behavior: "Comportament"
sample: "exemplu"
abuseReports: "Rapoarte"
reportAbuse: "Raportează"
reportAbuseOf: "Raportează {name}"
fillAbuseReportDescription: "Te rog scrie detaliile legate de acest raport. Dacă este despre o notă specifică, te rog introdu URL-ul ei."
abuseReported: "Raportul tău a fost trimis. Mulțumim."
reporter: "Raportorul"
reporteeOrigin: "Originea raportatului"
reporterOrigin: "Originea raportorului"
forwardReport: "Redirecționează raportul către instanța externă"
forwardReportIsAnonymous: "În locul contului tău, va fi afișat un cont anonim, de sistem, ca raportor către instanța externă."
send: "Trimite"
abuseMarkAsResolved: "Marchează raportul ca rezolvat"
openInNewTab: "Deschide în tab nou"
openInSideView: "Deschide în vedere laterală"
defaultNavigationBehaviour: "Comportament de navigare implicit"
editTheseSettingsMayBreakAccount: "Editarea acestor setări îți pot defecta contul."
waitingFor: "Așteptând pentru {x}"
random: "Aleator"
system: "Sistem"
switchUi: "Schimbă UI"
desktop: "Desktop"
clearCache: "Golește cache-ul"
info: "Despre"
user: "Utilizatori"
administration: "Gestionare"
middle: "Mediu"
sent: "Trimite"
searchByGoogle: "Caută"
file: "Fișiere"
_email:
_follow:
title: "te-a urmărit"
_mfm:
mention: "Mențiune"
quote: "Citează"
emoji: "Emoji personalizat"
search: "Caută"
_theme:
description: "Descriere"
keys:
mention: "Mențiune"
renote: "Re-notează"
divider: "Separator"
_sfx:
note: "Note"
notification: "Notificări"
chat: "Chat"
_widgets:
notifications: "Notificări"
timeline: "Cronologie"
activity: "Activitate"
federation: "Federație"
jobQueue: "coada de job-uri"
_cw:
show: "Incarcă mai mult"
_visibility:
home: "Acasă"
followers: "Urmăritori"
_profile:
name: "Nume"
username: "Nume de utilizator"
_exportOrImport:
followingList: "Urmărești"
muteList: "Amuțește"
blockingList: "Blochează"
userLists: "Liste"
_charts:
federation: "Federație"
_timelines:
home: "Acasă"
_pages:
blocks:
image: "Imagini"
script:
categories:
list: "Liste"
blocks:
_join:
arg1: "Liste"
_randomPick:
arg1: "Liste"
_dailyRandomPick:
arg1: "Liste"
_seedRandomPick:
arg2: "Liste"
_pick:
arg1: "Liste"
_listLen:
arg1: "Liste"
types:
array: "Liste"
_notification:
youWereFollowed: "te-a urmărit"
youWereInvitedToGroup: "Ai fost invitat într-un grup"
_types:
follow: "Urmărești"
mention: "Mențiune"
renote: "Re-notează"
quote: "Citează"
reaction: "Reacție"
_actions:
reply: "Răspunde"
renote: "Re-notează"
_deck:
_columns:
notifications: "Notificări"
tl: "Cronologie"
antenna: "Antene"
list: "Liste"
mentions: "Mențiuni"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,320 +0,0 @@
---
_lang_: "Svenska"
headlineMisskey: "Ett nätverk kopplat av noter"
introMisskey: "Välkommen! Calckey är en öppen och decentraliserad mikrobloggningstjänst.\nSkapa en \"not\" och dela dina tankar med alla runtomkring dig. 📡\nMed \"reaktioner\" kan du snabbt uttrycka dina känslor kring andras noter.👍\nLåt oss utforska en nya värld!🚀"
monthAndDay: "{day}/{month}"
search: "Sök"
notifications: "Notifikationer"
username: "Användarnamn"
password: "Lösenord"
forgotPassword: "Glömt lösenord"
fetchingAsApObject: "Hämtar från Fediversum"
ok: "OK"
gotIt: "Uppfattat!"
cancel: "Avbryt"
enterUsername: "Ange användarnamn"
renotedBy: "Omnoterad av {user}"
noNotes: "Inga noteringar"
noNotifications: "Inga aviseringar"
instance: "Instanser"
settings: "Inställningar"
basicSettings: "Basinställningar"
otherSettings: "Andra inställningar"
openInWindow: "Öppna i ett fönster"
profile: "Profil"
timeline: "Tidslinje"
noAccountDescription: "Användaren har inte skrivit en biografi än."
login: "Logga in"
loggingIn: "Loggar in"
logout: "Logga ut"
signup: "Registrera"
uploading: "Uppladdning sker..."
save: "Spara"
users: "Användare"
addUser: "Lägg till användare"
favorite: "Lägg till i favoriter"
favorites: "Favoriter"
unfavorite: "Avfavorisera"
favorited: "Tillagd i favoriter."
alreadyFavorited: "Redan tillagd i favoriter."
cantFavorite: "Gick inte att lägga till i favoriter."
pin: "Fäst till profil"
unpin: "Lossa från profil"
copyContent: "Kopiera innehåll"
copyLink: "Kopiera länk"
delete: "Radera"
deleteAndEdit: "Radera och ändra"
deleteAndEditConfirm: "Är du säker att du vill radera denna not och ändra den? Du kommer förlora alla reaktioner, omnoteringar och svar till den."
addToList: "Lägg till i lista"
sendMessage: "Skicka ett meddelande"
copyUsername: "Kopiera användarnamn"
searchUser: "Sök användare"
reply: "Svara"
loadMore: "Ladda mer"
showMore: "Visa mer"
youGotNewFollower: "följde dig"
receiveFollowRequest: "Följarförfrågan mottagen"
followRequestAccepted: "Följarförfrågan accepterad"
mention: "Nämn"
mentions: "Omnämningar"
directNotes: "Direktnoter"
importAndExport: "Importera / Exportera"
import: "Importera"
export: "Exportera"
files: "Filer"
download: "Nedladdning"
driveFileDeleteConfirm: "Är du säker att du vill radera filen \"{name}\"? Noter med denna fil bifogad kommer också raderas."
unfollowConfirm: "Är du säker att du vill avfölja {name}?"
exportRequested: "Du har begärt en export. Detta kan ta lite tid. Den kommer läggas till i din Drive när den blir klar."
importRequested: "Du har begärt en import. Detta kan ta lite tid."
lists: "Listor"
noLists: "Du har inga listor"
note: "Not"
notes: "Noter"
following: "Följer"
followers: "Följare"
followsYou: "Följer dig"
createList: "Skapa lista"
manageLists: "Hantera lista"
error: "Fel!"
somethingHappened: "Ett fel har uppstått"
retry: "Försök igen"
pageLoadError: "Det gick inte att ladda sidan."
pageLoadErrorDescription: "Detta händer oftast p.g.a. nätverksfel eller din webbläsarcache. Försök tömma din cache och testa sedan igen efter en liten stund."
serverIsDead: "Servern svarar inte. Vänta ett litet tag och försök igen."
youShouldUpgradeClient: "För att kunna se denna sida, vänligen ladda om sidan för att uppdatera din klient."
enterListName: "Skriv ett namn till listan"
privacy: "Integritet"
makeFollowManuallyApprove: "Följarförfrågningar kräver manuellt godkännande"
defaultNoteVisibility: "Standardsynlighet"
follow: "Följ"
followRequest: "Skicka följarförfrågan"
followRequests: "Följarförfrågningar"
unfollow: "Avfölj"
followRequestPending: "Följarförfrågning avvaktar för svar"
enterEmoji: "Skriv en emoji"
renote: "Omnotera"
unrenote: "Ta tillbaka omnotering"
renoted: "Omnoterad."
cantRenote: "Inlägget kunde inte bli omnoterat."
cantReRenote: "En omnotering kan inte bli omnoterad."
quote: "Citat"
pinnedNote: "Fästad not"
pinned: "Fäst till profil"
you: "Du"
clickToShow: "Klicka för att visa"
sensitive: "Känsligt innehåll"
add: "Lägg till"
reaction: "Reaktioner"
reactionSetting: "Reaktioner som ska visas i reaktionsväljaren"
reactionSettingDescription2: "Dra för att omordna, klicka för att radera, tryck \"+\" för att lägga till."
rememberNoteVisibility: "Komihåg notvisningsinställningar"
attachCancel: "Ta bort bilaga"
markAsSensitive: "Markera som känsligt innehåll"
unmarkAsSensitive: "Avmarkera som känsligt innehåll"
enterFileName: "Ange filnamn"
mute: "Tysta"
unmute: "Avtysta"
block: "Blockera"
unblock: "Avblockera"
suspend: "Suspendera"
unsuspend: "Ta bort suspenderingen"
blockConfirm: "Är du säker att du vill blockera kontot?"
unblockConfirm: "Är du säkert att du vill avblockera kontot?"
suspendConfirm: "Är du säker att du vill suspendera detta konto?"
unsuspendConfirm: "Är du säker att du vill avsuspendera detta konto?"
selectList: "Välj lista"
selectAntenna: "Välj en antenn"
selectWidget: "Välj en widget"
editWidgets: "Redigera widgets"
editWidgetsExit: "Avsluta redigering"
customEmojis: "Anpassa emoji"
emoji: "Emoji"
emojis: "Emoji"
emojiName: "Emoji namn"
emojiUrl: "Emoji länk"
addEmoji: "Lägg till emoji"
settingGuide: "Rekommenderade inställningar"
cacheRemoteFiles: "Spara externa filer till cachen"
cacheRemoteFilesDescription: "När denna inställning är avstängd kommer externa filer laddas direkt från den externa instansen. Genom att stänga av detta kommer lagringsutrymme minska i användning men kommer öka datatrafiken eftersom miniatyrer inte kommer genereras."
flagAsBot: "Markera konto som bot"
flagAsBotDescription: "Aktivera det här alternativet om kontot är kontrollerat av ett program. Om aktiverat kommer den fungera som en flagga för andra utvecklare för att hindra ändlösa kedjor med andra bottar. Det kommer också få Misskeys interna system att hantera kontot som en bot."
flagAsCat: "Markera konto som katt"
flagAsCatDescription: "Aktivera denna inställning för att markera kontot som en katt."
flagShowTimelineReplies: "Visa svar i tidslinje"
flagShowTimelineRepliesDescription: "Visar användarsvar till andra användares noter i tidslinjen om påslagen."
autoAcceptFollowed: "Godkänn följarförfrågningar från användare du följer automatiskt"
addAccount: "Lägg till konto"
loginFailed: "Inloggningen misslyckades"
showOnRemote: "Se på extern instans"
general: "Allmänt"
wallpaper: "Bakgrundsbild"
setWallpaper: "Välj bakgrund"
removeWallpaper: "Ta bort bakgrund"
searchWith: "Sök: {q}"
youHaveNoLists: "Du har inga listor"
followConfirm: "Är du säker att du vill följa {name}?"
proxyAccount: "Proxykonto"
proxyAccountDescription: "Ett proxykonto är ett konto som agerar som en extern följare för användare under vissa villkor. Till exempel, när en användare lägger till en extern användare till en lista så kommer den externa användarens aktivitet inte levireras till instansen om ingen lokal användare följer det kontot, så proxykontot används istället."
host: "Värd"
selectUser: "Välj användare"
recipient: "Mottagare"
annotation: "Kommentarer"
federation: "Federation"
instances: "Instanser"
registeredAt: "Registrerad på"
latestRequestSentAt: "Senaste förfrågan skickad"
latestRequestReceivedAt: "Senaste begäran mottagen"
latestStatus: "Senaste status"
storageUsage: "Använt lagringsutrymme"
charts: "Diagram"
perHour: "Per timme"
perDay: "Per dag"
stopActivityDelivery: "Sluta skicka aktiviteter"
blockThisInstance: "Blockera instans"
operations: "Operationer"
software: "Mjukvara"
version: "Version"
metadata: "Metadata"
monitor: "Övervakning"
jobQueue: "Jobbkö"
cpuAndMemory: "CPU och minne"
network: "Nätverk"
disk: "Disk"
instanceInfo: "Instansinformation"
statistics: "Statistik"
clearQueue: "Rensa kö"
clearQueueConfirmTitle: "Är du säker att du vill rensa kön?"
clearQueueConfirmText: "Om någon not är olevererad i kön kommer den inte federeras. Vanligtvis behövs inte denna handling."
clearCachedFiles: "Rensa cache"
clearCachedFilesConfirm: "Är du säker att du vill radera alla cachade externa filer?"
blockedInstances: "Blockerade instanser"
blockedInstancesDescription: "Lista adressnamn av instanser som du vill blockera. Listade instanser kommer inte längre kommunicera med denna instans."
muteAndBlock: "Tystningar och blockeringar"
mutedUsers: "Tystade användare"
blockedUsers: "Blockerade användare"
noUsers: "Det finns inga användare"
editProfile: "Redigera profil"
noteDeleteConfirm: "Är du säker på att du vill ta bort denna not?"
pinLimitExceeded: "Du kan inte fästa fler noter"
intro: "Calckey har installerats! Vänligen skapa en adminanvändare."
done: "Klar"
processing: "Bearbetar..."
preview: "Förhandsvisning"
default: "Standard"
defaultValueIs: "Standard: {value}"
noCustomEmojis: "Det finns ingen emoji"
noJobs: "Det finns inga jobb"
federating: "Federerar"
blocked: "Blockerad"
suspended: "Suspenderad"
all: "Allt"
subscribing: "Prenumererar"
publishing: "Publiceras"
notResponding: "Svarar inte"
instanceFollowing: "Följer på instans"
instanceFollowers: "Följare av instans"
instanceUsers: "Användare av denna instans"
changePassword: "Ändra lösenord"
security: "Säkerhet"
retypedNotMatch: "Inmatningen matchar inte"
currentPassword: "Nuvarande lösenord"
newPassword: "Nytt lösenord"
newPasswordRetype: "Bekräfta lösenord"
attachFile: "Bifoga filer"
more: "Mer!"
featured: "Utvalda"
usernameOrUserId: "Användarnamn eller användar-id"
noSuchUser: "Kan inte hitta användaren"
lookup: "Sökning"
announcements: "Nyheter"
imageUrl: "Bild-URL"
remove: "Radera"
removed: "Borttaget"
removeAreYouSure: "Är du säker att du vill radera \"{x}\"?"
deleteAreYouSure: "Är du säker att du vill radera \"{x}\"?"
resetAreYouSure: "Vill du återställa?"
saved: "Sparad"
messaging: "Chatt"
upload: "Ladda upp"
keepOriginalUploading: "Behåll originalbild"
nsfw: "Känsligt innehåll"
pinnedNotes: "Fästad not"
userList: "Listor"
smtpHost: "Värd"
smtpUser: "Användarnamn"
smtpPass: "Lösenord"
clearCache: "Rensa cache"
user: "Användare"
searchByGoogle: "Sök"
file: "Filer"
_email:
_follow:
title: "följde dig"
_mfm:
mention: "Nämn"
quote: "Citat"
emoji: "Anpassa emoji"
search: "Sök"
_theme:
keys:
mention: "Nämn"
renote: "Omnotera"
_sfx:
note: "Noter"
notification: "Notifikationer"
chat: "Chatt"
_widgets:
notifications: "Notifikationer"
timeline: "Tidslinje"
federation: "Federation"
jobQueue: "Jobbkö"
_cw:
show: "Ladda mer"
_visibility:
followers: "Följare"
_profile:
username: "Användarnamn"
_exportOrImport:
followingList: "Följer"
muteList: "Tysta"
blockingList: "Blockera"
userLists: "Listor"
_charts:
federation: "Federation"
_pages:
script:
categories:
list: "Listor"
blocks:
_join:
arg1: "Listor"
_randomPick:
arg1: "Listor"
_dailyRandomPick:
arg1: "Listor"
_seedRandomPick:
arg2: "Listor"
_pick:
arg1: "Listor"
_listLen:
arg1: "Listor"
types:
array: "Listor"
_notification:
youWereFollowed: "följde dig"
_types:
follow: "Följer"
mention: "Nämn"
renote: "Omnotera"
quote: "Citat"
reaction: "Reaktioner"
_actions:
reply: "Svara"
renote: "Omnotera"
_deck:
_columns:
notifications: "Notifikationer"
tl: "Tidslinje"
list: "Listor"
mentions: "Omnämningar"

File diff suppressed because it is too large Load Diff

View File

@ -1,63 +0,0 @@
---
_lang_: "Türkçe"
introMisskey: "Açık kaynaklı bir dağıtılmış mikroblog hizmeti olan Calckey'e hoş geldiniz.\nMisskey, neler olup bittiğini paylaşmak ve herkese sizden bahsetmek için \"notlar\" oluşturmanıza olanak tanıyan, açık kaynaklı, dağıtılmış bir mikroblog hizmetidir.\nHerkesin notlarına kendi tepkilerinizi hızlıca eklemek için \"Tepkiler\" özelliğini de kullanabilirsiniz👍.\nYeni bir dünyayı keşfedin🚀."
monthAndDay: "{month}Ay {day}Gün"
search: "Arama"
notifications: "Bildirim"
username: "Kullanıcı Adı"
password: "Şifre"
forgotPassword: "şifremi unuttum"
ok: "TAMAM"
gotIt: "Anladım"
cancel: "İptal"
enterUsername: "Kullanıcı adınızı giriniz"
noNotes: "Notlar mevcut değil."
noNotifications: "Bildirim bulunmuyor"
settings: "Ayarlar"
basicSettings: "Temel Ayarlar"
otherSettings: "Diğer Ayarlar"
openInWindow: "Bir pencere ile aç"
profile: "Profil"
timeline: "Zaman çizelgesi"
noAccountDescription: "Bu kullanıcı henüz biyografisini yazmadı"
login: "Giriş Yap "
logout: ıkış Yap"
signup: "Kayıt Ol"
uploading: "Yükleniyor"
users: "Kullanıcı"
addUser: "Kullanıcı Ekle"
favorite: "Favoriler"
favorites: "Favoriler"
unfavorite: "Favorilerden Kaldır"
favorited: "Favorilerime eklendi."
alreadyFavorited: "Zaten favorilerinizde kayıtlı."
pin: "Sabitlenmiş"
unpin: "Sabitlemeyi kaldır"
copyContent: "İçeriği kopyala"
copyLink: "Bağlantıyı Kopyala"
delete: "Sil"
deleteAndEdit: "Sil ve yeniden düzenle"
deleteAndEditConfirm: "Bu notu silip yeniden düzenlemek istiyor musunuz? Bu nota ilişkin tüm Tepkiler, Yeniden Notlar ve Yanıtlar da silinecektir."
addToList: "Listeye ekle"
sendMessage: "Mesaj Gönder"
copyUsername: "Kullanıcı Adını Kopyala"
searchUser: "Kullanıcıları ara"
pinned: "Sabitlenmiş"
remove: "Sil"
smtpUser: "Kullanıcı Adı"
smtpPass: "Şifre"
user: "Kullanıcı"
searchByGoogle: "Arama"
_mfm:
search: "Arama"
_sfx:
notification: "Bildirim"
_widgets:
notifications: "Bildirim"
timeline: "Zaman çizelgesi"
_profile:
username: "Kullanıcı Adı"
_deck:
_columns:
notifications: "Bildirim"
tl: "Zaman çizelgesi"

View File

@ -1,6 +0,0 @@
---
_lang_: "ياپونچە"
search: "ئىزدەش"
searchByGoogle: "ئىزدەش"
_mfm:
search: "ئىزدەش"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "calckey", "name": "calckey",
"version": "14.0.0-rc3-magnetar", "version": "14.0.0-alpha+magnetar-0.2.0",
"codename": "aqua", "codename": "aqua",
"repository": { "repository": {
"type": "git", "type": "git",
@ -9,15 +9,14 @@
"packageManager": "pnpm@8.6.3", "packageManager": "pnpm@8.6.3",
"private": true, "private": true,
"scripts": { "scripts": {
"rebuild": "pnpm run clean && pnpm node ./scripts/build-greet.js && pnpm -r run build && pnpm run gulp", "rebuild": "pnpm run clean && pnpm node ./scripts/build-greet.js && pnpm -r run build",
"build": "pnpm node ./scripts/build-greet.js && pnpm -r run build && pnpm run gulp", "build": "pnpm node ./scripts/build-greet.js && pnpm -r run build ",
"start": "pnpm --filter backend run start", "start": "pnpm --filter backend run start",
"start:test": "pnpm --filter backend run start:test", "start:test": "pnpm --filter backend run start:test",
"init": "pnpm run migrate", "init": "pnpm run migrate",
"migrate": "pnpm --filter backend run migrate", "migrate": "pnpm --filter backend run migrate",
"revertmigration": "pnpm --filter backend run revertmigration", "revertmigration": "pnpm --filter backend run revertmigration",
"migrateandstart": "pnpm run migrate && pnpm run start", "migrateandstart": "pnpm run migrate && pnpm run start",
"gulp": "gulp build",
"watch": "pnpm run dev", "watch": "pnpm run dev",
"dev": "pnpm node ./scripts/dev.js", "dev": "pnpm node ./scripts/dev.js",
"dev:staging": "NODE_OPTIONS=--max_old_space_size=3072 NODE_ENV=development pnpm run build && pnpm run start", "dev:staging": "NODE_OPTIONS=--max_old_space_size=3072 NODE_ENV=development pnpm run build && pnpm run start",
@ -43,17 +42,10 @@
"seedrandom": "^3.0.5" "seedrandom": "^3.0.5"
}, },
"devDependencies": { "devDependencies": {
"@types/gulp": "4.0.10",
"@types/gulp-rename": "2.0.1",
"chalk": "4.1.2", "chalk": "4.1.2",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"cypress": "10.11.0", "cypress": "10.11.0",
"execa": "5.1.1", "execa": "5.1.1",
"gulp": "4.0.2",
"gulp-cssnano": "2.1.3",
"gulp-rename": "2.0.0",
"gulp-replace": "1.1.4",
"gulp-terser": "2.1.0",
"install-peers": "^1.0.4", "install-peers": "^1.0.4",
"rome": "^12.1.3", "rome": "^12.1.3",
"start-server-and-test": "1.15.2", "start-server-and-test": "1.15.2",

View File

@ -28,7 +28,6 @@
"@bull-board/koa": "5.2.0", "@bull-board/koa": "5.2.0",
"@bull-board/ui": "5.2.0", "@bull-board/ui": "5.2.0",
"@calckey/megalodon": "5.2.0", "@calckey/megalodon": "5.2.0",
"@discordapp/twemoji": "14.1.2",
"@elastic/elasticsearch": "7.17.0", "@elastic/elasticsearch": "7.17.0",
"@koa/cors": "3.4.3", "@koa/cors": "3.4.3",
"@koa/multer": "3.0.2", "@koa/multer": "3.0.2",

View File

@ -25,7 +25,6 @@ import wellKnown from "./well-known.js";
import apiServer from "./api/index.js"; import apiServer from "./api/index.js";
import fileServer from "./file/index.js"; import fileServer from "./file/index.js";
import proxyServer from "./proxy/index.js"; import proxyServer from "./proxy/index.js";
import webServer from "./web/index.js";
import {initializeStreamingServer} from "./api/streaming.js"; import {initializeStreamingServer} from "./api/streaming.js";
import removeTrailingSlash from "koa-remove-trailing-slashes"; import removeTrailingSlash from "koa-remove-trailing-slashes";
@ -109,9 +108,6 @@ router.get("/identicon/:x", async (ctx) => {
// Register router // Register router
app.use(router.routes()); app.use(router.routes());
app.use(mount(webServer));
function createServer() { function createServer() {
return http.createServer(app.callback()); return http.createServer(app.callback());
} }

View File

@ -1,147 +0,0 @@
main > .tabs {
padding: 16px;
border-bottom: 4px solid #908caa;
}
#lsEditor > .adder {
margin: 16px;
padding: 16px;
border: 2px solid #908caa;
}
#lsEditor > .adder > textarea {
display: block;
width: 100%;
min-height: 5em;
box-sizing: border-box;
}
#lsEditor > .record {
padding: 16px;
border-bottom: 1px solid #908caa;
}
#lsEditor > .record > header {
font-weight: 700;
}
#lsEditor > .record > textarea {
display: block;
width: 100%;
min-height: 5em;
box-sizing: border-box;
}
html {
background: #191724;
}
main {
background: #1f1d2e;
border-radius: 10px;
}
#tl > div {
padding: 16px;
border-bottom: 1px solid #908caa;
}
#tl > div > header {
font-weight: 700;
}
* {
font-family: BIZ UDGothic, Roboto, HelveticaNeue, Arial, sans-serif;
}
#calckey_app {
display: none !important;
}
body,
html {
background-color: #191724;
color: #e0def4;
justify-content: center;
margin: auto;
padding: 10px;
text-align: center;
}
button {
border-radius: 999px;
padding: 0px 12px 0px 12px;
border: none;
cursor: pointer;
margin-bottom: 12px;
background: linear-gradient(90deg, rgb(156, 207, 216), rgb(49, 116, 143));
line-height: 50px;
color: #191724;
font-weight: bold;
font-size: 20px;
padding: 12px;
}
button {
border-radius: 999px;
padding: 0px 12px 0px 12px;
border: none;
cursor: pointer;
margin-bottom: 12px;
}
button {
background: #444;
line-height: 40px;
color: rgb(156, 207, 216);
font-size: 16px;
padding: 0 20px;
margin-right: 5px;
margin-left: 5px;
}
button:hover {
background: #555;
}
#ls {
background: linear-gradient(90deg, rgb(156, 207, 216), rgb(49, 116, 143));
line-height: 30px;
color: #191724;
font-weight: bold;
font-size: 18px;
padding: 12px;
}
#ls:hover {
background: rgb(156, 207, 216);
}
a {
color: rgb(156, 207, 216);
text-decoration: none;
}
p,
li {
font-size: 16px;
}
h1 {
font-size: 32px;
}
code {
font-family: Fira, FiraCode, monospace;
}
textarea {
background-color: #444;
border: solid #aaa;
border-radius: 10px;
color: #e0def4;
margin-top: 1rem;
margin-bottom: 1rem;
width: 20rem;
height: 7.5rem;
padding: 0.5rem;
}
textarea:focus {
border: solid #eee;
}
input {
background-color: #666;
border: solid #aaa;
border-radius: 10px;
color: #e0def4;
margin-top: 1rem;
margin-bottom: 1rem;
width: 10rem;
height: 1rem;
padding: 0.5rem;
}
input:focus {
border: solid #eee;
}

View File

@ -1,312 +0,0 @@
/**
* BOOT LOADER
* サーバーからレスポンスされるHTMLに埋め込まれるスクリプトで以下の役割を持ちます
* - 翻訳ファイルをフェッチする
* - バージョンに基づいて適切なメインスクリプトを読み込む
* - キャッシュされたコンパイル済みテーマを適用する
* - クライアントの設定値に基づいて対応するHTMLクラス等を設定する
* テーマをこの段階で設定するのはメインスクリプトが読み込まれる間もテーマを適用したいためです
* : webpackは介さないためこのファイルではrequireやimportは使えません
*/
"use strict";
// ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔なので
(async () => {
window.onerror = (e) => {
console.error(e);
renderError("SOMETHING_HAPPENED", e);
};
window.onunhandledrejection = (e) => {
console.error(e);
renderError("SOMETHING_HAPPENED_IN_PROMISE", e);
};
//#region Detect language & fetch translations
const v = localStorage.getItem("v") || VERSION;
const supportedLangs = LANGS;
let lang = localStorage.getItem("lang");
if (lang == null || !supportedLangs.includes(lang)) {
if (supportedLangs.includes(navigator.language)) {
lang = navigator.language;
} else {
lang = supportedLangs.find((x) => x.split("-")[0] === navigator.language);
// Fallback
if (lang == null) lang = "en-US";
}
}
const res = await fetch(`/assets/locales/${lang}.${v}.json`);
if (res.status === 200) {
localStorage.setItem("lang", lang);
localStorage.setItem("locale", await res.text());
localStorage.setItem("localeVersion", v);
} else {
await checkUpdate();
renderError("LOCALE_FETCH");
return;
}
//#endregion
//#region Script
function importAppScript() {
import(`/assets/${CLIENT_ENTRY}`).catch(async (e) => {
await checkUpdate();
console.error(e);
renderError("APP_IMPORT", e);
});
}
// タイミングによっては、この時点でDOMの構築が済んでいる場合とそうでない場合とがある
if (document.readyState !== "loading") {
importAppScript();
} else {
window.addEventListener("DOMContentLoaded", () => {
importAppScript();
});
}
//#endregion
//#region Theme
const theme = localStorage.getItem("theme");
if (theme) {
for (const [k, v] of Object.entries(JSON.parse(theme))) {
document.documentElement.style.setProperty(`--${k}`, v.toString());
// HTMLの theme-color 適用
if (k === "htmlThemeColor") {
for (const tag of document.head.children) {
if (
tag.tagName === "META" &&
tag.getAttribute("name") === "theme-color"
) {
tag.setAttribute("content", v);
break;
}
}
}
}
}
const colorSchema = localStorage.getItem("colorSchema");
if (colorSchema) {
document.documentElement.style.setProperty("color-schema", colorSchema);
}
//#endregion
let fontSize = localStorage.getItem("fontSize");
if (fontSize) {
if (fontSize < 10) {
// need to do this for now, as values before were 1, 2, 3 depending on the option
localStorage.setItem("fontSize", null);
fontSize = localStorage.getItem("fontSize");
}
document.documentElement.style.fontSize = fontSize + "px";
}
const useSystemFont = localStorage.getItem("useSystemFont");
if (useSystemFont) {
document.documentElement.classList.add("useSystemFont");
}
const wallpaper = localStorage.getItem("wallpaper");
if (wallpaper) {
document.documentElement.style.backgroundImage = `url(${wallpaper})`;
}
const customCss = localStorage.getItem("customCss");
if (customCss && customCss.length > 0) {
const style = document.createElement("style");
style.innerHTML = customCss;
document.head.appendChild(style);
}
async function addStyle(styleText) {
let css = document.createElement("style");
css.appendChild(document.createTextNode(styleText));
document.head.appendChild(css);
}
function renderError(code, details) {
let errorsElement = document.getElementById("errors");
if (!errorsElement) {
document.body.innerHTML = `
<svg class="icon-warning" xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-alert-triangle" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 9v2m0 4v.01"></path>
<path d="M5 19h14a2 2 0 0 0 1.84 -2.75l-7.1 -12.25a2 2 0 0 0 -3.5 0l-7.1 12.25a2 2 0 0 0 1.75 2.75"></path>
</svg>
<h1>An error has occurred!</h1>
<button class="button-big" onclick="location.reload(true);">
<span class="button-label-big">Refresh</span>
</button>
<p class="dont-worry">Don't worry, it's (probably) not your fault.</p>
<p>Please make sure your browser is up-to-date and any AdBlockers are off.</p>
<p>If the problem persists after refreshing, please contact your instance's administrator.<br>You may also try:</p>
<a href="/flush">
<button class="button-small">
<span class="button-label-small">Clear preferences and cache</span>
</button>
</a>
<br>
<div id="errors"></div>
`;
errorsElement = document.getElementById("errors");
}
const detailsElement = document.createElement("details");
detailsElement.innerHTML = `
<br>
<summary>
<code>ERROR CODE: ${code}</code>
</summary>
<code>${JSON.stringify(details)}</code>`;
errorsElement.appendChild(detailsElement);
addStyle(`
* {
font-family: BIZ UDGothic, Roboto, HelveticaNeue, Arial, sans-serif;
}
#calckey_app,
#splash {
display: none !important;
}
body,
html {
background-color: #191724;
color: #e0def4;
justify-content: center;
margin: auto;
padding: 10px;
text-align: center;
}
button {
border-radius: 999px;
padding: 0px 12px 0px 12px;
border: none;
cursor: pointer;
margin-bottom: 12px;
}
.button-big {
background: linear-gradient(90deg, rgb(196, 167, 231), rgb(235, 188, 186));
line-height: 50px;
}
.button-big:hover {
background: rgb(49, 116, 143);
}
.button-small {
background: #444;
line-height: 40px;
}
.button-small:hover {
background: #555;
}
.button-label-big {
color: #191724;
font-weight: bold;
font-size: 20px;
padding: 12px;
}
.button-label-small {
color: rgb(156, 207, 216);
font-size: 16px;
padding: 12px;
}
a {
color: rgb(156, 207, 216);
text-decoration: none;
}
p,
li {
font-size: 16px;
}
.dont-worry,
#msg {
font-size: 18px;
}
.icon-warning {
color: #f6c177;
height: 4rem;
padding-top: 2rem;
}
h1 {
font-size: 32px;
}
code {
font-family: Fira, FiraCode, monospace;
}
details {
background: #1f1d2e;
margin-bottom: 2rem;
padding: 0.5rem 1rem;
width: 40rem;
border-radius: 10px;
justify-content: center;
margin: auto;
}
summary {
cursor: pointer;
}
summary > * {
display: inline;
}
@media screen and (max-width: 500px) {
details {
width: 50%;
}
`);
}
async function checkUpdate() {
try {
const res = await fetch("/api/meta", {
method: "POST",
cache: "no-cache",
});
const meta = await res.json();
if (meta.version != v) {
localStorage.setItem("v", meta.version);
refresh();
}
} catch (e) {
console.error(e);
renderError("UPDATE_CHECK", e);
throw e;
}
}
function refresh() {
// Clear cache (service worker)
try {
navigator.serviceWorker.controller.postMessage("clear");
navigator.serviceWorker.getRegistrations().then((registrations) => {
registrations.forEach((registration) => registration.unregister());
});
} catch (e) {
console.error(e);
}
location.reload();
}
})();

View File

@ -1,65 +0,0 @@
import { Feed } from "feed";
import { In, IsNull } from "typeorm";
import config from "@/config/index.js";
import type { User } from "@/models/entities/user.js";
import { Notes, DriveFiles, UserProfiles, Users } from "@/models/index.js";
export default async function (user: User) {
const author = {
link: `${config.url}/@${user.username}`,
name: user.name || user.username,
};
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
const notes = await Notes.find({
where: {
userId: user.id,
renoteId: IsNull(),
visibility: In(["public", "home"]),
},
order: { createdAt: -1 },
take: 20,
});
const feed = new Feed({
id: author.link,
title: `${author.name} (@${user.username}@${config.host})`,
updated: notes[0].createdAt,
generator: "Calckey",
description: `${user.notesCount} Notes, ${
profile.ffVisibility === "public" ? user.followingCount : "?"
} Following, ${
profile.ffVisibility === "public" ? user.followersCount : "?"
} Followers${profile.description ? ` · ${profile.description}` : ""}`,
link: author.link,
image: await Users.getAvatarUrl(user),
feedLinks: {
json: `${author.link}.json`,
atom: `${author.link}.atom`,
},
author,
copyright: user.name || user.username,
});
for (const note of notes) {
const files =
note.fileIds.length > 0
? await DriveFiles.findBy({
id: In(note.fileIds),
})
: [];
const file = files.find((file) => file.type.startsWith("image/"));
feed.addItem({
title: `New note by ${author.name}`,
link: `${config.url}/notes/${note.id}`,
date: note.createdAt,
description: note.cw || undefined,
content: note.text || undefined,
image: file ? DriveFiles.getPublicUrl(file) || undefined : undefined,
});
}
return feed;
}

View File

@ -1,550 +0,0 @@
/**
* Web Client Server
*/
import {dirname} from "node:path";
import {fileURLToPath} from "node:url";
import {readFileSync} from "node:fs";
import Koa from "koa";
import Router from "@koa/router";
import send from "koa-send";
import favicon from "koa-favicon";
import views from "koa-views";
import {createBullBoard} from "@bull-board/api";
import {BullAdapter} from "@bull-board/api/bullAdapter.js";
import {KoaAdapter} from "@bull-board/koa";
import {In, IsNull} from "typeorm";
import {fetchMeta, metaToPugArgs} from "@/misc/fetch-meta.js";
import config from "@/config/index.js";
import {Channels, Clips, GalleryPosts, Notes, Pages, UserProfiles, Users,} from "@/models/index.js";
import * as Acct from "@/misc/acct.js";
import {getNoteSummary} from "@/misc/get-note-summary.js";
import {queues} from "@/queue/queues.js";
import {genOpenapiSpec} from "../api/openapi/gen-spec.js";
import {urlPreviewHandler} from "./url-preview.js";
import {manifestHandler} from "./manifest.js";
import packFeed from "./feed.js";
import {DAY, MINUTE} from "@/const.js";
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
const staticAssets = `${_dirname}/../../../assets/`;
const clientAssets = `${_dirname}/../../../../client/assets/`;
const assets = `${_dirname}/../../../../../built/_client_dist_/`;
const swAssets = `${_dirname}/../../../../../built/_sw_dist_/`;
// Init app
const app = new Koa();
//#region Bull Dashboard
const bullBoardPath = "/queue";
// Authenticate
app.use(async (ctx, next) => {
if (ctx.path === bullBoardPath || ctx.path.startsWith(`${bullBoardPath}/`)) {
const token = ctx.cookies.get("token");
if (token == null) {
ctx.status = 401;
return;
}
const user = await Users.findOneBy({ token });
if (user == null || !(user.isAdmin || user.isModerator)) {
ctx.status = 403;
return;
}
}
await next();
});
const serverAdapter = new KoaAdapter();
createBullBoard({
queues: queues.map((q) => new BullAdapter(q)),
serverAdapter,
});
serverAdapter.setBasePath(bullBoardPath);
app.use(serverAdapter.registerPlugin());
//#endregion
// Init renderer
app.use(
views(`${_dirname}/views`, {
extension: "pug",
options: {
version: config.version,
getClientEntry: () =>
process.env.NODE_ENV === "production"
? config.clientEntry
: JSON.parse(
readFileSync(
`${_dirname}/../../../../../built/_client_dist_/manifest.json`,
"utf-8",
),
)["src/init.ts"],
config,
},
}),
);
// Serve favicon
app.use(favicon(`${_dirname}/../../../assets/favicon.ico`));
// Common request handler
app.use(async (ctx, next) => {
// IFrameの中に入れられないようにする
ctx.set("X-Frame-Options", "DENY");
await next();
});
// Init router
const router = new Router();
//#region static assets
router.get("/static-assets/(.*)", async (ctx) => {
await send(ctx as any, ctx.path.replace("/static-assets/", ""), {
root: staticAssets,
maxage: 7 * DAY,
});
});
router.get("/client-assets/(.*)", async (ctx) => {
await send(ctx as any, ctx.path.replace("/client-assets/", ""), {
root: clientAssets,
maxage: 7 * DAY,
});
});
router.get("/assets/(.*)", async (ctx) => {
await send(ctx as any, ctx.path.replace("/assets/", ""), {
root: assets,
maxage: 7 * DAY,
});
});
// Apple touch icon
router.get("/apple-touch-icon.png", async (ctx) => {
await send(ctx as any, "/apple-touch-icon.png", {
root: staticAssets,
});
});
router.get("/twemoji/(.*)", async (ctx) => {
const path = ctx.path.replace("/twemoji/", "");
if (!path.match(/^[0-9a-f-]+\.svg$/)) {
ctx.status = 404;
return;
}
ctx.set(
"Content-Security-Policy",
"default-src 'none'; style-src 'unsafe-inline'",
);
await send(ctx as any, path, {
root: `${_dirname}/../../../node_modules/@discordapp/twemoji/dist/svg/`,
maxage: 30 * DAY,
});
});
// ServiceWorker
router.get("/sw.js", async (ctx) => {
await send(ctx as any, "/sw.js", {
root: swAssets,
maxage: 10 * MINUTE,
});
});
// Manifest
router.get("/manifest.json", manifestHandler);
router.get("/robots.txt", async (ctx) => {
await send(ctx as any, "/robots.txt", {
root: staticAssets,
});
});
//#endregion
// Docs
router.get("/api-doc", async (ctx) => {
await send(ctx as any, "/redoc.html", {
root: staticAssets,
});
});
// URL preview endpoint
router.get("/url", urlPreviewHandler);
router.get("/api.json", async (ctx) => {
ctx.body = genOpenapiSpec();
});
const getFeed = async (acct: string) => {
const meta = await fetchMeta();
if (meta.privateMode) {
return;
}
const { username, host } = Acct.parse(acct);
const user = await Users.findOneBy({
usernameLower: username.toLowerCase(),
host: host ?? IsNull(),
isSuspended: false,
});
return user && (await packFeed(user));
};
// As the /@user[.json|.rss|.atom]/sub endpoint is complicated, we will use a regex to switch between them.
const reUser = new RegExp(
"^/@(?<user>[^/]+?)(?:.(?<feed>json|rss|atom))?(?:/(?<sub>[^/]+))?$",
);
router.get(reUser, async (ctx, next) => {
const groups = reUser.exec(ctx.originalUrl)?.groups;
if (!groups) {
await next();
return;
}
ctx.params = groups;
console.log(ctx, ctx.params);
if (groups.feed) {
if (groups.sub) {
await next();
return;
}
switch (groups.feed) {
case "json":
await jsonFeed(ctx, next);
break;
case "rss":
await rssFeed(ctx, next);
break;
case "atom":
await atomFeed(ctx, next);
break;
}
return;
}
await userPage(ctx, next);
});
// Atom
const atomFeed: Router.Middleware = async (ctx) => {
const feed = await getFeed(ctx.params.user);
if (feed) {
ctx.set("Content-Type", "application/atom+xml; charset=utf-8");
ctx.body = feed.atom1();
} else {
ctx.status = 404;
}
};
// RSS
const rssFeed: Router.Middleware = async (ctx) => {
const feed = await getFeed(ctx.params.user);
if (feed) {
ctx.set("Content-Type", "application/rss+xml; charset=utf-8");
ctx.body = feed.rss2();
} else {
ctx.status = 404;
}
};
// JSON
const jsonFeed: Router.Middleware = async (ctx) => {
const feed = await getFeed(ctx.params.user);
if (feed) {
ctx.set("Content-Type", "application/json; charset=utf-8");
ctx.body = feed.json1();
} else {
ctx.status = 404;
}
};
//#region SSR (for crawlers)
// User
const userPage: Router.Middleware = async (ctx, next) => {
const userParam = ctx.params.user;
const subParam = ctx.params.sub;
const { username, host } = Acct.parse(userParam);
const user = await Users.findOneBy({
usernameLower: username.toLowerCase(),
host: host ?? IsNull(),
isSuspended: false,
});
if (user === null) {
await next();
return;
}
const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
const meta = await fetchMeta();
const me = profile.fields
? profile.fields
.filter((filed) => filed.value?.match(/^https?:/))
.map((field) => field.value)
: [];
const userDetail = {
...metaToPugArgs(meta),
user,
profile,
me,
avatarUrl: await Users.getAvatarUrl(user),
sub: subParam,
};
await ctx.render("user", userDetail);
ctx.set("Cache-Control", "public, max-age=15");
};
router.get("/users/:user", async (ctx) => {
const user = await Users.findOneBy({
id: ctx.params.user,
host: IsNull(),
isSuspended: false,
});
if (user == null) {
ctx.status = 404;
return;
}
ctx.redirect(`/@${user.username}${user.host == null ? "" : `@${user.host}`}`);
});
// Note
router.get("/notes/:note", async (ctx, next) => {
const note = await Notes.findOneBy({
id: ctx.params.note,
visibility: In(["public", "home"]),
});
try {
if (note) {
const _note = await Notes.pack(note);
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(
await Users.findOneByOrFail({ id: note.userId }),
),
// TODO: Let locale changeable by instance setting
summary: getNoteSummary(_note),
});
ctx.set("Cache-Control", "public, max-age=15");
ctx.set(
"Content-Security-Policy",
"default-src 'self' 'unsafe-inline'; img-src *; frame-ancestors *",
);
return;
}
} catch {}
await next();
});
router.get("/posts/:note", async (ctx, next) => {
const note = await Notes.findOneBy({
id: ctx.params.note,
visibility: In(["public", "home"]),
});
if (note) {
const _note = await Notes.pack(note);
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(
await Users.findOneByOrFail({ id: note.userId }),
),
// TODO: Let locale changeable by instance setting
summary: getNoteSummary(_note),
});
ctx.set("Cache-Control", "public, max-age=15");
return;
}
await next();
});
// Page
router.get("/@:user/pages/:page", async (ctx, next) => {
const { username, host } = Acct.parse(ctx.params.user);
const user = await Users.findOneBy({
usernameLower: username.toLowerCase(),
host: host ?? IsNull(),
});
if (user == null) return;
const page = await Pages.findOneBy({
name: ctx.params.page,
userId: user.id,
});
if (page) {
const _page = await Pages.pack(page);
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 }),
),
});
if (["public"].includes(page.visibility)) {
ctx.set("Cache-Control", "public, max-age=15");
} else {
ctx.set("Cache-Control", "private, max-age=0, must-revalidate");
}
return;
}
await next();
});
// Clip
// TODO: handling of private clips
router.get("/clips/:clip", async (ctx, next) => {
const clip = await Clips.findOneBy({
id: ctx.params.clip,
});
if (clip) {
const _clip = await Clips.pack(clip);
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 }),
),
});
ctx.set("Cache-Control", "public, max-age=15");
return;
}
await next();
});
// Gallery post
router.get("/gallery/:post", async (ctx, next) => {
const post = await GalleryPosts.findOneBy({ id: ctx.params.post });
if (post) {
const _post = await GalleryPosts.pack(post);
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 }),
),
});
ctx.set("Cache-Control", "public, max-age=15");
return;
}
await next();
});
// Channel
router.get("/channels/:channel", async (ctx, next) => {
const channel = await Channels.findOneBy({
id: ctx.params.channel,
});
if (channel) {
const _channel = await Channels.pack(channel);
const meta = await fetchMeta();
await ctx.render("channel", {
...metaToPugArgs(meta),
channel: _channel,
});
ctx.set("Cache-Control", "public, max-age=15");
return;
}
await next();
});
//#endregion
const override = (source: string, target: string, depth = 0) =>
[
undefined,
...target.split("/").filter((x) => x),
...source
.split("/")
.filter((x) => x)
.splice(depth),
].join("/");
router.get("/flush", async (ctx) => {
await ctx.render("flush");
});
// If a non-WebSocket request comes in to streaming and base html is returned with cache, the path will be cached by Proxy, etc. and it will be wrong.
router.get("/streaming", async (ctx) => {
ctx.status = 503;
ctx.set("Cache-Control", "private, max-age=0");
});
router.get("/api/v1/streaming", async (ctx) => {
ctx.status = 503;
ctx.set("Cache-Control", "private, max-age=0");
});
// Render base html for all requests
router.get("(.*)", async (ctx) => {
const meta = await fetchMeta();
await ctx.render("base", {
...metaToPugArgs(meta),
});
ctx.set("Cache-Control", "public, max-age=3");
});
// Register router
app.use(router.routes());
export default app;

View File

@ -1,72 +0,0 @@
{
"short_name": "Calckey",
"name": "Calckey",
"description": "An open source, decentralized social media platform that's free forever!",
"start_url": "/",
"display": "standalone",
"background_color": "#1f1d2e",
"theme_color": "#31748f",
"orientation": "portrait-primary",
"icons": [
{
"src": "/static-assets/icons/192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/static-assets/icons/512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "/static-assets/icons/maskable.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/static-assets/icons/monochrome.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "monochrome"
}
],
"share_target": {
"action": "/share/",
"params": {
"title": "title",
"text": "text",
"url": "url"
}
},
"screenshots": [
{
"src": "/static-assets/screenshots/1.webp",
"sizes": "1195x579",
"type": "image/webp",
"platform": "narrow",
"label": "Profile page"
},
{
"src": "/static-assets/screenshots/2.webp",
"sizes": "1195x579",
"type": "image/webp",
"platform": "narrow",
"label": "Posts"
}
],
"shortcuts": [
{
"name": "Notifications",
"short_name": "Notifs",
"url": "/my/notifications"
},
{
"name": "Chats",
"url": "/my/messaging"
}
],
"categories": ["social"]
}

View File

@ -1,18 +0,0 @@
import type Koa from "koa";
import { fetchMeta } from "@/misc/fetch-meta.js";
import manifest from "./manifest.json" assert { type: "json" };
export const manifestHandler = async (ctx: Koa.Context) => {
// TODO
//const res = structuredClone(manifest);
const res = JSON.parse(JSON.stringify(manifest));
const instance = await fetchMeta(true);
res.short_name = instance.name || "Calckey";
res.name = instance.name || "Calckey";
if (instance.themeColor) res.theme_color = instance.themeColor;
ctx.set("Cache-Control", "max-age=300");
ctx.body = res;
};

View File

@ -1,133 +0,0 @@
html {
background-color: var(--bg);
color: var(--fg);
}
@media (prefers-color-scheme: dark) {
html {
--bg: rgb(17, 17, 27);
--fg: rgb(224, 222, 244);
}
}
#splash {
position: fixed;
z-index: 10000;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
cursor: wait;
background-color: var(--bg);
opacity: 1;
transition: opacity 0.2s ease;
}
#splashIcon {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
width: 64px;
height: 64px;
pointer-events: none;
animation-duration: 1s;
animation-iteration-count: infinite;
animation-name: tada;
}
#splashSpinner {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
display: inline-block;
width: 28px;
height: 28px;
transform: translateY(110px);
display: none;
color: var(--accent);
}
#splashSpinner > .spinner {
position: absolute;
top: 0;
left: 0;
width: 28px;
height: 28px;
fill-rule: evenodd;
clip-rule: evenodd;
stroke-linecap: round;
stroke-linejoin: round;
stroke-miterlimit: 1.5;
}
#splashSpinner > .spinner.bg {
opacity: 0.275;
}
#splashSpinner > .spinner.fg {
animation: splashSpinner 0.5s linear infinite;
}
@keyframes splashSpinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes tada {
0% {
transform: scale3d(1, 1, 1);
}
10%,
20% {
transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
}
30%,
50%,
70%,
90% {
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
}
40%,
60%,
80% {
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
}
100% {
transform: scale3d(1, 1, 1);
}
}
@media(prefers-reduced-motion) {
#splashSpinner {
display: block;
}
#splashIcon {
animation: none;
}
}
#splashText {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
display: inline-block;
width: 70%;
height: 0;
text-align: center;
padding-top: 100px;
font-family: sans-serif;
}

View File

@ -1,88 +0,0 @@
import type Koa from "koa";
import summaly from "summaly";
import { fetchMeta } from "@/misc/fetch-meta.js";
import Logger from "@/services/logger.js";
import config from "@/config/index.js";
import { query } from "@/prelude/url.js";
import { getJson } from "@/misc/fetch.js";
const logger = new Logger("url-preview");
export const urlPreviewHandler = async (ctx: Koa.Context) => {
const url = ctx.query.url;
if (typeof url !== "string") {
ctx.status = 400;
return;
}
const lang = ctx.query.lang;
if (Array.isArray(lang)) {
ctx.status = 400;
return;
}
const meta = await fetchMeta();
logger.info(
meta.summalyProxy
? `(Proxy) Getting preview of ${url}@${lang} ...`
: `Getting preview of ${url}@${lang} ...`,
);
try {
const summary = meta.summalyProxy
? await getJson(
`${meta.summalyProxy}?${query({
url: url,
lang: lang ?? "en-US",
})}`,
)
: await summaly.default(url, {
followRedirects: false,
lang: lang ?? "en-US",
});
logger.succ(`Got preview of ${url}: ${summary.title}`);
if (
summary.url &&
!(summary.url.startsWith("http://") || summary.url.startsWith("https://"))
) {
throw new Error("unsupported schema included");
}
if (
summary.player?.url &&
!(
summary.player.url.startsWith("http://") ||
summary.player.url.startsWith("https://")
)
) {
throw new Error("unsupported schema included");
}
summary.icon = wrap(summary.icon);
summary.thumbnail = wrap(summary.thumbnail);
// Cache 7days
ctx.set("Cache-Control", "max-age=604800, immutable");
ctx.body = summary;
} catch (err) {
logger.warn(`Failed to get preview of ${url}: ${err}`);
ctx.status = 200;
ctx.set("Cache-Control", "max-age=86400, immutable");
ctx.body = "{}";
}
};
function wrap(url?: string): string | null {
return url != null
? url.match(/^https?:\/\//)
? `${config.url}/proxy/preview.webp?${query({
url,
preview: "1",
})}`
: url
: null;
}

View File

@ -1,96 +0,0 @@
block vars
block loadClientEntry
- const clientEntry = getClientEntry();
doctype html
//
-
___ _ _
/ __\__ _| | ___| | _____ _ _
/ / / _` | |/ __| |/ / _ \ | | |
/ /__| (_| | | (__| < __/ |_| |
\____/\__,_|_|\___|_|\_\___|\__, |
(___/
Thank you for using Calckey!
If you are reading this message... how about joining the development?
https://codeberg.org/calckey/calckey
html
- var timestamp = Date.now();
head
meta(charset='utf-8')
meta(name='application-name' content='Calckey')
meta(name='referrer' content='origin')
meta(name='darkreader-lock' content='')
meta(name='theme-color' content= themeColor || '#31748f')
meta(name='theme-color-orig' content= themeColor || '#31748f')
meta(property='twitter:card' content='summary')
meta(property='og:site_name' content= instanceName || 'Calckey')
meta(name='viewport' content='width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no')
link(rel='icon' href= icon || `/favicon.ico?${ timestamp }`)
link(rel='apple-touch-icon' href= icon || `/apple-touch-icon.png?${ timestamp }`)
link(rel='manifest' href='/manifest.json')
link(rel='prefetch' href=`/static-assets/badges/info.png?${ timestamp }`)
link(rel='prefetch' href=`/static-assets/badges/not-found.png?${ timestamp }`)
link(rel='prefetch' href=`/static-assets/badges/error.png?${ timestamp }`)
link(rel='stylesheet' href=`/static-assets/instance.css?${ timestamp }`)
link(rel='modulepreload' href=`/assets/${clientEntry.file}`)
if Array.isArray(clientEntry.css)
each href in clientEntry.css
link(rel='stylesheet' href=`/assets/${href}`)
title
block title
= title || 'Calckey'
block desc
meta(name='description' content=desc || 'An open source, decentralized social media platform that\'s free forever! 🚀')
block meta
if privateMode
meta(name='robots' content='noindex')
block og
meta(property='og:title' content=title || 'Calckey')
meta(property='og:description' content=desc || 'An open source, decentralized social media platform that\'s free forever! 🚀')
meta(property='og:image' content=img)
meta(property='og:image:alt' content=alt || 'Pfp')
style
include ../style.css
script.
var VERSION = "#{version}";
var CLIENT_ENTRY = "#{clientEntry.file}";
script
include ../boot.js
body
noscript: p
| JavaScriptを有効にしてください
br
| Please turn on your JavaScript
div#splash
img#splashIcon(src= splashIcon || `/static-assets/splash.png?${ timestamp }`)
span#splashText
block randomMOTD
= randomMOTD
div#splashSpinner
<svg class="spinner bg" viewBox="0 0 152 152" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1,0,0,1,12,12)">
<circle cx="64" cy="64" r="64" style="fill:none;stroke:currentColor;stroke-width:24px;"/>
</g>
</svg>
<svg class="spinner fg" viewBox="0 0 152 152" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1,0,0,1,12,12)">
<path d="M128,64C128,28.654 99.346,0 64,0C99.346,0 128,28.654 128,64Z" style="fill:none;stroke:currentColor;stroke-width:24px;"/>
</g>
</svg>
block content

View File

@ -1,20 +0,0 @@
extends ./base
block vars
- const title = privateMode ? instanceName : channel.name;
- const url = `${config.url}/channels/${channel.id}`;
block title
= `${title} | ${instanceName}`
block desc
unless privateMode
meta(name='description' content=channel.description)
block og
unless privateMode
meta(property='og:type' content='article')
meta(property='og:title' content= title)
meta(property='og:description' content= channel.description)
meta(property='og:url' content= url)
meta(property='og:image' content= channel.bannerUrl)

View File

@ -1,37 +0,0 @@
extends ./base
block vars
- const user = clip.user;
- const title = privateMode ? instanceName : clip.name;
- const url = `${config.url}/clips/${clip.id}`;
block title
= `${title} | ${instanceName}`
block desc
unless privateMode
meta(name='description' content= clip.description)
block og
unless privateMode
meta(property='og:type' content='article')
meta(property='og:title' content= title)
meta(property='og:description' content= clip.description)
meta(property='og:url' content= url)
meta(property='og:image' content= avatarUrl)
block meta
unless privateMode
if profile.noCrawle
meta(name='robots' content='noindex')
if profile.preventAiLearning
meta(name='robots' content='noai')
meta(name='robots' content='noimageai')
meta(name='misskey:user-username' content=user.username)
meta(name='misskey:user-id' content=user.id)
meta(name='misskey:clip-id' content=clip.id)
// todo
if user.twitter
meta(name='twitter:creator' content=`@${user.twitter.screenName}`)

View File

@ -1,71 +0,0 @@
doctype html
html
head
meta(charset='utf-8')
meta(name='application-name' content='Calckey')
meta(name='viewport' content='width=device-width, initial-scale=1.0')
title Flush Calckey
style.
* {
font-family: BIZ UDGothic, Roboto, HelveticaNeue, Arial, sans-serif;
}
body,
html {
background-color: #191724;
color: #e0def4;
justify-content: center;
margin: auto;
padding: 10px;
text-align: center;
}
a {
color: rgb(156, 207, 216);
text-decoration: none;
}
body
#msg
script.
const msg = document.getElementById('msg');
const successText = `\nSuccess Flush! <a href="/">Back to Calckey</a>\n成功しました。<a href="/">Calckeyを開き直してください。</a>`;
message('Start flushing.');
(async function() {
try {
localStorage.clear();
message('localStorage cleared.');
const idbPromises = ['MisskeyClient', 'keyval-store'].map((name, i, arr) => new Promise((res, rej) => {
const delidb = indexedDB.deleteDatabase(name);
delidb.onsuccess = () => res(message(`indexedDB "${name}" cleared. (${i + 1}/${arr.length})`));
delidb.onerror = e => rej(e)
}));
await Promise.all(idbPromises);
if (navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.postMessage('clear');
await navigator.serviceWorker.getRegistrations()
.then(registrations => {
return Promise.all(registrations.map(registration => registration.unregister()));
})
.catch(e => { throw new Error(e) });
}
message(successText);
} catch (e) {
message(`\n${e}\n\nFlush Failed. <a href="/flush">Please retry.</a>\n失敗しました。<a href="/flush">もう一度試してみてください。</a>`);
message(`\nIf you retry more than 3 times, clear the browser cache or contact to instance admin.\n3回以上試しても失敗する場合、ブラウザのキャッシュを消去し、それでもだめならインスタンス管理者に連絡してみてください。\n`)
console.error(e);
setTimeout(() => {
location = '/';
}, 10000)
}
})();
function message(text) {
msg.insertAdjacentHTML('beforeend', `<p>[${(new Date()).toString()}] ${text.replace(/\n/g,'<br>')}</p>`)
}

View File

@ -1,39 +0,0 @@
extends ./base
block vars
- const user = post.user;
- const title = privateMode ? instanceName : post.title;
- const url = `${config.url}/gallery/${post.id}`;
block title
= `${title} | ${instanceName}`
block desc
unless privateMode
meta(name='description' content= post.description)
block og
unless privateMode
meta(property='og:type' content='article')
meta(property='og:title' content= title)
meta(property='og:description' content= post.description)
meta(property='og:url' content= url)
meta(property='og:image' content= post.files[0].thumbnailUrl)
block meta
unless privateMode
if user.host || profile.noCrawle
meta(name='robots' content='noindex')
if profile.preventAiLearning
meta(name='robots' content='noai')
meta(name='robots' content='noimageai')
meta(name='misskey:user-username' content=user.username)
meta(name='misskey:user-id' content=user.id)
// todo
if user.twitter
meta(name='twitter:creator' content=`@${user.twitter.screenName}`)
if !user.host
link(rel='alternate' href=url type='application/activity+json')

View File

@ -1,59 +0,0 @@
extends ./base
block vars
- const user = note.user;
- const title = privateMode ? instanceName : (user.name ? `${user.name} (@${user.username}${user.host ? `@${user.host}` : ''})` : `@${user.username}`);
- const url = `${config.url}/notes/${note.id}`;
- const isRenote = note.renote && note.text == null && note.fileIds.length == 0 && note.poll == null;
- const isImage = note.files.length !== 0 && note.files[0].type.startsWith('image');
- const isVideo = note.files.length !== 0 && note.files[0].type.startsWith('video');
- const imageUrl = isImage ? note.files[0].url : isVideo ? note.files[0].thumbnailUrl : avatarUrl;
block title
= `${title} | ${instanceName}`
block desc
unless privateMode
meta(name='description' content= summary)
block og
unless privateMode
meta(property='og:type' content='article')
meta(property='og:title' content= title)
meta(property='og:description' content= summary)
meta(property='og:url' content= url)
meta(property='og:image' content= imageUrl)
if isImage && !note.files[0].isSensitive
meta(property='og:image:width' content=note.files[0].properties.width)
meta(property='og:image:height' content=note.files[0].properties.height)
meta(property='og:image:type' content=note.files[0].type)
meta(property='twitter:card' content="summary_large_image")
if isVideo
meta(property='og:video:type' content=note.files[0].type)
meta(property='og:video' content=note.files[0].url)
block meta
unless privateMode
if user.host || isRenote || profile.noCrawle
meta(name='robots' content='noindex')
if profile.preventAiLearning
meta(name='robots' content='noai')
meta(name='robots' content='noimageai')
meta(name='misskey:user-username' content=user.username)
meta(name='misskey:user-id' content=user.id)
meta(name='misskey:note-id' content=note.id)
// todo
if user.twitter
meta(name='twitter:creator' content=`@${user.twitter.screenName}`)
if note.prev
link(rel='prev' href=`${config.url}/notes/${note.prev}`)
if note.next
link(rel='next' href=`${config.url}/notes/${note.next}`)
if !user.host
link(rel='alternate' href=url type='application/activity+json')
if note.uri
link(rel='alternate' href=note.uri type='application/activity+json')

View File

@ -1,37 +0,0 @@
extends ./base
block vars
- const user = page.user;
- const title = privateMode ? instanceName : page.title;
- const url = `${config.url}/@${user.username}/${page.name}`;
block title
= `${title} | ${instanceName}`
block desc
unless privateMode
meta(name='description' content= page.summary)
block og
unless privateMode
meta(property='og:type' content='article')
meta(property='og:title' content= title)
meta(property='og:description' content= page.summary)
meta(property='og:url' content= url)
meta(property='og:image' content= page.eyeCatchingImage ? page.eyeCatchingImage.thumbnailUrl : avatarUrl)
block meta
unless privateMode
if profile.noCrawle
meta(name='robots' content='noindex')
if profile.preventAiLearning
meta(name='robots' content='noai')
meta(name='robots' content='noimageai')
meta(name='misskey:user-username' content=user.username)
meta(name='misskey:user-id' content=user.id)
meta(name='misskey:page-id' content=page.id)
// todo
if user.twitter
meta(name='twitter:creator' content=`@${user.twitter.screenName}`)

View File

@ -1,46 +0,0 @@
extends ./base
block vars
- const title = privateMode ? instanceName : (user.name ? `${user.name} (@${user.username})` : `@${user.username}`);
- const url = `${config.url}/@${(user.host ? `${user.username}@${user.host}` : user.username)}`;
block title
= `${title} | ${instanceName}`
block desc
unless privateMode
meta(name='description' content= profile.description)
block og
unless privateMode
meta(property='og:type' content='profile')
meta(property='og:title' content= title)
meta(property='og:description' content= profile.description)
meta(property='og:url' content= url)
meta(property='og:image' content= avatarUrl)
meta(property='profile:username' content= user.username)
block meta
unless privateMode
if user.host || profile.noCrawle
meta(name='robots' content='noindex')
if profile.preventAiLearning
meta(name='robots' content='noai')
meta(name='robots' content='noimageai')
meta(name='misskey:user-username' content=user.username)
meta(name='misskey:user-id' content=user.id)
if profile.twitter
meta(name='twitter:creator' content=`@${profile.twitter.screenName}`)
if !sub
if !user.host
link(rel='alternate' href=`${config.url}/users/${user.id}` type='application/activity+json')
if user.uri
link(rel='alternate' href=user.uri type='application/activity+json')
if profile.url
link(rel='alternate' href=profile.url type='text/html')
each m in me
link(rel='me' href=`${m}`)

View File

@ -1,15 +0,0 @@
{
"tabWidth": 4,
"useTabs": true,
"singleQuote": false,
"vueIndentScriptAndStyle": false,
"plugins": ["vue"],
"overrides": [
{
"files": "*.vue",
"options": {
"parser": "vue"
}
}
]
}

View File

@ -1,15 +0,0 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"path-intellisense.mappings": {
"@": "${workspaceRoot}/packages/client/src/"
},
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"**/Thumbs.db": true,
"**/_client_dist_": true
}
}

View File

@ -1,10 +0,0 @@
type FIXME = any;
declare const _LANGS_: string[][];
declare const _VERSION_: string;
declare const _ENV_: string;
declare const _DEV_: boolean;
declare const _PERF_PREFIX_: string;
declare const _DATA_TRANSFER_DRIVE_FILE_: string;
declare const _DATA_TRANSFER_DRIVE_FOLDER_: string;
declare const _DATA_TRANSFER_DECK_COLUMN_: string;

View File

@ -1,7 +0,0 @@
declare module "@/themes/*.json5" {
import { Theme } from "@/scripts/theme";
const theme: Theme;
export default theme;
}

View File

@ -1,7 +0,0 @@
/// <reference types="vue/macros-global" />
declare module "*.vue" {
import type { DefineComponent } from "vue";
const component: DefineComponent<{}, {}, any>;
export default component;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

View File

@ -1 +0,0 @@
<svg width="96" height="96" xmlns="http://www.w3.org/2000/svg"><path fill="#eb6f92" d="M0 45.255L45.254 0h39.6L0 84.854z"/></svg>

Before

Width:  |  Height:  |  Size: 130 B

View File

@ -1 +0,0 @@
<svg width="96" height="96" xmlns="http://www.w3.org/2000/svg"><path fill="#31748f" d="M0 45.255L45.254 0h39.6L0 84.854z"/></svg>

Before

Width:  |  Height:  |  Size: 130 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.9 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +0,0 @@
{
"name": "client",
"private": true,
"scripts": {
"watch": "pnpm vite build --watch --mode development",
"build": "pnpm vite build",
"lint": "pnpm rome check \"src/**/*.{ts,vue}\"",
"format": "pnpm prettier --write '**/*.vue'"
},
"devDependencies": {
"@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.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.5",
"@types/throttle-debounce": "5.0.0",
"@types/tinycolor2": "1.4.3",
"@types/uuid": "8.3.4",
"@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",
"broadcast-channel": "4.19.1",
"browser-image-resizer": "github:misskey-dev/browser-image-resizer",
"calckey-js": "workspace:*",
"chart.js": "4.3.0",
"chartjs-adapter-date-fns": "3.0.0",
"chartjs-chart-matrix": "^2.0.1",
"chartjs-plugin-gradient": "0.6.1",
"chartjs-plugin-zoom": "2.0.1",
"city-timezones": "^1.2.1",
"compare-versions": "5.0.3",
"cropperjs": "2.0.0-beta.2",
"cross-env": "7.0.3",
"cypress": "10.11.0",
"date-fns": "2.30.0",
"emojilib": "github:thatonecalculator/emojilib",
"escape-regexp": "0.0.1",
"eventemitter3": "4.0.7",
"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.7",
"matter-js": "0.18.0",
"mfm-js": "0.23.3",
"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.23.1",
"s-age": "1.1.2",
"sass": "1.62.1",
"seedrandom": "3.0.5",
"start-server-and-test": "1.15.2",
"strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0",
"swiper": "9.3.2",
"syuilo-password-strength": "0.0.1",
"textarea-caret": "3.1.0",
"three": "0.146.0",
"throttle-debounce": "5.0.0",
"tinycolor2": "1.5.2",
"tsc-alias": "1.8.6",
"tsconfig-paths": "4.2.0",
"twemoji-parser": "14.0.0",
"typescript": "5.1.3",
"unicode-emoji-json": "^0.4.0",
"uuid": "9.0.0",
"vanilla-tilt": "1.8.0",
"vite": "4.3.9",
"vite-plugin-compression": "^0.5.1",
"vue": "3.3.4",
"vue-isyourpasswordsafe": "^2.0.0",
"vue-plyr": "^7.0.0",
"vue-prism-editor": "2.0.0-alpha.2",
"vue3-otp-input": "^0.4.1",
"vuedraggable": "4.1.0"
}
}

View File

@ -1,294 +0,0 @@
import { defineAsyncComponent, reactive } from "vue";
import * as misskey from "calckey-js";
import { i18n } from "./i18n";
import { del, get, set } from "@/scripts/idb-proxy";
import { apiUrl } from "@/config";
import { waiting, api, popup, popupMenu, success, alert } from "@/os";
import { unisonReload, reloadChannel } from "@/scripts/unison-reload";
// TODO: 他のタブと永続化されたstateを同期
type Account = misskey.entities.MeDetailed;
const accountData = localStorage.getItem("account");
// TODO: 外部からはreadonlyに
export const $i = accountData
? reactive(JSON.parse(accountData) as Account)
: null;
export const iAmModerator = $i != null && ($i.isAdmin || $i.isModerator);
export const iAmAdmin = $i?.isAdmin;
export async function signout() {
waiting();
localStorage.removeItem("account");
await removeAccount($i.id);
const accounts = await getAccounts();
//#region Remove service worker registration
try {
if (navigator.serviceWorker.controller) {
const registration = await navigator.serviceWorker.ready;
const push = await registration.pushManager.getSubscription();
if (push) {
await fetch(`${apiUrl}/sw/unregister`, {
method: "POST",
body: JSON.stringify({
i: $i.token,
endpoint: push.endpoint,
}),
});
}
}
if (accounts.length === 0) {
await navigator.serviceWorker.getRegistrations().then((registrations) => {
return Promise.all(
registrations.map((registration) => registration.unregister()),
);
});
}
} catch (err) {}
//#endregion
document.cookie = "igi=; path=/";
if (accounts.length > 0) login(accounts[0].token);
else unisonReload("/");
}
export async function getAccounts(): Promise<
{ id: Account["id"]; token: Account["token"] }[]
> {
return (await get("accounts")) || [];
}
export async function addAccount(id: Account["id"], token: Account["token"]) {
const accounts = await getAccounts();
if (!accounts.some((x) => x.id === id)) {
await set("accounts", accounts.concat([{ id, token }]));
}
}
export async function removeAccount(id: Account["id"]) {
const accounts = await getAccounts();
accounts.splice(
accounts.findIndex((x) => x.id === id),
1,
);
if (accounts.length > 0) await set("accounts", accounts);
else await del("accounts");
}
function fetchAccount(token: string): Promise<Account> {
return new Promise((done, fail) => {
// Fetch user
fetch(`${apiUrl}/i`, {
method: "POST",
body: JSON.stringify({
i: token,
}),
})
.then((res) => res.json())
.then((res) => {
if (res.error) {
if (res.error.id === "a8c724b3-6e9c-4b46-b1a8-bc3ed6258370") {
showSuspendedDialog().then(() => {
signout();
});
} else {
alert({
type: "error",
title: i18n.ts.failedToFetchAccountInformation,
text: JSON.stringify(res.error),
});
}
} else {
res.token = token;
done(res);
}
})
.catch(fail);
});
}
export function updateAccount(accountData) {
for (const [key, value] of Object.entries(accountData)) {
$i[key] = value;
}
localStorage.setItem("account", JSON.stringify($i));
}
export function refreshAccount() {
return fetchAccount($i.token).then(updateAccount);
}
export async function login(token: Account["token"], redirect?: string) {
waiting();
if (_DEV_) console.log("logging as token ", token);
const me = await fetchAccount(token);
localStorage.setItem("account", JSON.stringify(me));
document.cookie = `token=${token}; path=/; max-age=31536000`; // bull dashboardの認証とかで使う
await addAccount(me.id, token);
if (redirect) {
// 他のタブは再読み込みするだけ
reloadChannel.postMessage(null);
// このページはredirectで指定された先に移動
location.href = redirect;
return;
}
unisonReload();
}
export async function openAccountMenu(
opts: {
includeCurrentAccount?: boolean;
withExtraOperation: boolean;
active?: misskey.entities.UserDetailed["id"];
onChoose?: (account: misskey.entities.UserDetailed) => void;
},
ev: MouseEvent,
) {
function showSigninDialog() {
popup(
defineAsyncComponent(() => import("@/components/MkSigninDialog.vue")),
{},
{
done: (res) => {
addAccount(res.id, res.i);
success();
},
},
"closed",
);
}
function createAccount() {
popup(
defineAsyncComponent(() => import("@/components/MkSignupDialog.vue")),
{},
{
done: (res) => {
addAccount(res.id, res.i);
switchAccountWithToken(res.i);
},
},
"closed",
);
}
async function switchAccount(account: misskey.entities.UserDetailed) {
const storedAccounts = await getAccounts();
const token = storedAccounts.find((x) => x.id === account.id).token;
switchAccountWithToken(token);
}
function switchAccountWithToken(token: string) {
login(token);
}
const storedAccounts = await getAccounts().then((accounts) =>
accounts.filter((x) => x.id !== $i.id),
);
const accountsPromise = api("users/show", {
userIds: storedAccounts.map((x) => x.id),
});
function createItem(account: misskey.entities.UserDetailed) {
return {
type: "user",
user: account,
active: opts.active != null ? opts.active === account.id : false,
action: () => {
if (opts.onChoose) {
opts.onChoose(account);
} else {
switchAccount(account);
}
},
};
}
const accountItemPromises = storedAccounts.map(
(a) =>
new Promise((res) => {
accountsPromise.then((accounts) => {
const account = accounts.find((x) => x.id === a.id);
if (account == null) return res(null);
res(createItem(account));
});
}),
);
if (opts.withExtraOperation) {
popupMenu(
[
...[
{
type: "link",
text: i18n.ts.profile,
to: `/@${$i.username}`,
avatar: $i,
},
null,
...(opts.includeCurrentAccount ? [createItem($i)] : []),
...accountItemPromises,
{
type: "parent",
icon: "ph-plus ph-bold ph-lg",
text: i18n.ts.addAccount,
children: [
{
text: i18n.ts.existingAccount,
action: () => {
showSigninDialog();
},
},
{
text: i18n.ts.createAccount,
action: () => {
createAccount();
},
},
],
},
{
type: "link",
icon: "ph-users ph-bold ph-lg",
text: i18n.ts.manageAccounts,
to: "/settings/accounts",
},
{
type: "button",
icon: "ph-sign-out ph-bold ph-lg",
text: i18n.ts.logout,
action: () => {
signout();
},
},
],
],
ev.currentTarget ?? ev.target,
{
align: "left",
},
);
} else {
popupMenu(
[
...(opts.includeCurrentAccount ? [createItem($i)] : []),
...accountItemPromises,
],
ev.currentTarget ?? ev.target,
{
align: "left",
},
);
}
}

View File

@ -1,147 +0,0 @@
<template>
<div class="bcekxzvu _gap _panel">
<div class="target">
<MkA
v-user-preview="report.targetUserId"
class="info"
:to="`/user-info/${report.targetUserId}`"
>
<MkAvatar
class="avatar"
:user="report.targetUser"
:show-indicator="true"
:disable-link="true"
/>
<div class="names">
<MkUserName class="name" :user="report.targetUser" />
<MkAcct
class="acct"
:user="report.targetUser"
style="display: block"
/>
</div>
</MkA>
<MkKeyValue class="_formBlock">
<template #key>{{ i18n.ts.registeredDate }}</template>
<template #value
>{{
new Date(report.targetUser.createdAt).toLocaleString()
}}
(<MkTime :time="report.targetUser.createdAt" />)</template
>
</MkKeyValue>
</div>
<div class="detail">
<div>
<Mfm :text="report.comment" />
</div>
<hr />
<div>
{{ i18n.ts.reporter }}: <MkAcct :user="report.reporter" />
</div>
<div v-if="report.assignee">
{{ i18n.ts.moderator }}:
<MkAcct :user="report.assignee" />
</div>
<div><MkTime :time="report.createdAt" /></div>
<div class="action">
<MkSwitch
v-model="forward"
:disabled="
report.targetUser.host == null || report.resolved
"
>
{{ i18n.ts.forwardReport }}
<template #caption>{{
i18n.ts.forwardReportIsAnonymous
}}</template>
</MkSwitch>
<MkButton v-if="!report.resolved" primary @click="resolve">{{
i18n.ts.abuseMarkAsResolved
}}</MkButton>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import MkButton from "@/components/MkButton.vue";
import MkSwitch from "@/components/form/switch.vue";
import MkKeyValue from "@/components/MkKeyValue.vue";
import { acct, userPage } from "@/filters/user";
import * as os from "@/os";
import { i18n } from "@/i18n";
const props = defineProps<{
report: any;
}>();
const emit = defineEmits<{
(ev: "resolved", reportId: string): void;
}>();
let forward = $ref(props.report.forwarded);
function resolve() {
os.apiWithDialog("admin/resolve-abuse-user-report", {
forward: forward,
reportId: props.report.id,
}).then(() => {
emit("resolved", props.report.id);
});
}
</script>
<style lang="scss" scoped>
.bcekxzvu {
display: flex;
> .target {
width: 35%;
box-sizing: border-box;
text-align: left;
padding: 24px;
border-right: solid 1px var(--divider);
> .info {
display: flex;
box-sizing: border-box;
align-items: center;
padding: 14px;
border-radius: 8px;
--c: rgb(255 196 0 / 15%);
background-image: linear-gradient(
45deg,
var(--c) 16.67%,
transparent 16.67%,
transparent 50%,
var(--c) 50%,
var(--c) 66.67%,
transparent 66.67%,
transparent 100%
);
background-size: 16px 16px;
> .avatar {
width: 42px;
height: 42px;
}
> .names {
margin-left: 0.3em;
padding: 0 8px;
flex: 1;
> .name {
font-weight: bold;
}
}
}
}
> .detail {
flex: 1;
padding: 24px;
}
}
</style>

View File

@ -1,86 +0,0 @@
<template>
<XWindow
ref="uiWindow"
:initial-width="400"
:initial-height="500"
:can-resize="true"
@closed="emit('closed')"
>
<template #header>
<i
class="ph-warning-circle ph-bold ph-lg"
style="margin-right: 0.5em"
></i>
<I18n :src="i18n.ts.reportAbuseOf" tag="span">
<template #name>
<b><MkAcct :user="user" /></b>
</template>
</I18n>
</template>
<div class="dpvffvvy _monolithic_">
<div class="_section">
<MkTextarea v-model="comment">
<template #label>{{ i18n.ts.details }}</template>
<template #caption>{{
i18n.ts.fillAbuseReportDescription
}}</template>
</MkTextarea>
</div>
<div class="_section">
<MkButton
primary
full
:disabled="comment.length === 0"
@click="send"
>{{ i18n.ts.send }}</MkButton
>
</div>
</div>
</XWindow>
</template>
<script setup lang="ts">
import { ref } from "vue";
import * as Misskey from "calckey-js";
import XWindow from "@/components/MkWindow.vue";
import MkTextarea from "@/components/form/textarea.vue";
import MkButton from "@/components/MkButton.vue";
import * as os from "@/os";
import { i18n } from "@/i18n";
const props = defineProps<{
user: Misskey.entities.User;
initialComment?: string;
}>();
const emit = defineEmits<{
(ev: "closed"): void;
}>();
const uiWindow = ref<InstanceType<typeof XWindow>>();
const comment = ref(props.initialComment || "");
function send() {
os.apiWithDialog(
"users/report-abuse",
{
userId: props.user.id,
comment: comment.value,
},
undefined
).then((res) => {
os.alert({
type: "success",
text: i18n.ts.abuseReported,
});
uiWindow.value?.close();
emit("closed");
});
}
</script>
<style lang="scss" scoped>
.dpvffvvy {
--root-margin: 16px;
}
</style>

View File

@ -1,280 +0,0 @@
<template>
<svg class="mbcofsoe" viewBox="0 0 10 10" preserveAspectRatio="none">
<template v-if="props.graduations === 'dots'">
<circle
v-for="(angle, i) in graduationsMajor"
:cx="5 + Math.sin(angle) * (5 - graduationsPadding)"
:cy="5 - Math.cos(angle) * (5 - graduationsPadding)"
:r="0.125"
:fill="
(props.twentyfour ? h : h % 12) === i
? nowColor
: majorGraduationColor
"
:opacity="
!props.fadeGraduations ||
(props.twentyfour ? h : h % 12) === i
? 1
: Math.max(
0,
1 -
angleDiff(hAngle, angle) / Math.PI -
numbersOpacityFactor
)
"
/>
</template>
<template v-else-if="props.graduations === 'numbers'">
<text
v-for="(angle, i) in texts"
:x="5 + Math.sin(angle) * (5 - textsPadding)"
:y="5 - Math.cos(angle) * (5 - textsPadding)"
text-anchor="middle"
dominant-baseline="middle"
:font-size="(props.twentyfour ? h : h % 12) === i ? 1 : 0.7"
:font-weight="
(props.twentyfour ? h : h % 12) === i ? 'bold' : 'normal'
"
:fill="
(props.twentyfour ? h : h % 12) === i
? nowColor
: 'currentColor'
"
:opacity="
!props.fadeGraduations ||
(props.twentyfour ? h : h % 12) === i
? 1
: Math.max(
0,
1 -
angleDiff(hAngle, angle) / Math.PI -
numbersOpacityFactor
)
"
>
{{ i === 0 ? (props.twentyfour ? "24" : "12") : i }}
</text>
</template>
<!--
<line
:x1="5 - (Math.sin(sAngle) * (sHandLengthRatio * handsTailLength))"
:y1="5 + (Math.cos(sAngle) * (sHandLengthRatio * handsTailLength))"
:x2="5 + (Math.sin(sAngle) * ((sHandLengthRatio * 5) - handsPadding))"
:y2="5 - (Math.cos(sAngle) * ((sHandLengthRatio * 5) - handsPadding))"
:stroke="sHandColor"
:stroke-width="thickness / 2"
stroke-linecap="round"
/>
-->
<line
class="s"
:class="{
animate: !disableSAnimate && sAnimation !== 'none',
elastic: sAnimation === 'elastic',
easeOut: sAnimation === 'easeOut',
}"
:x1="5 - 0 * (sHandLengthRatio * handsTailLength)"
:y1="5 + 1 * (sHandLengthRatio * handsTailLength)"
:x2="5 + 0 * (sHandLengthRatio * 5 - handsPadding)"
:y2="5 - 1 * (sHandLengthRatio * 5 - handsPadding)"
:stroke="sHandColor"
:stroke-width="thickness / 2"
:style="`transform: rotateZ(${sAngle}rad)`"
stroke-linecap="round"
/>
<line
:x1="5 - Math.sin(mAngle) * (mHandLengthRatio * handsTailLength)"
:y1="5 + Math.cos(mAngle) * (mHandLengthRatio * handsTailLength)"
:x2="5 + Math.sin(mAngle) * (mHandLengthRatio * 5 - handsPadding)"
:y2="5 - Math.cos(mAngle) * (mHandLengthRatio * 5 - handsPadding)"
:stroke="mHandColor"
:stroke-width="thickness"
stroke-linecap="round"
/>
<line
:x1="5 - Math.sin(hAngle) * (hHandLengthRatio * handsTailLength)"
:y1="5 + Math.cos(hAngle) * (hHandLengthRatio * handsTailLength)"
:x2="5 + Math.sin(hAngle) * (hHandLengthRatio * 5 - handsPadding)"
:y2="5 - Math.cos(hAngle) * (hHandLengthRatio * 5 - handsPadding)"
:stroke="hHandColor"
:stroke-width="thickness"
stroke-linecap="round"
/>
</svg>
</template>
<script lang="ts" setup>
import {
ref,
computed,
onMounted,
onBeforeUnmount,
shallowRef,
nextTick,
} from "vue";
import tinycolor from "tinycolor2";
import { globalEvents } from "@/events.js";
// https://stackoverflow.com/questions/1878907/how-can-i-find-the-difference-between-two-angles
const angleDiff = (a: number, b: number) => {
const x = Math.abs(a - b);
return Math.abs(((x + Math.PI) % (Math.PI * 2)) - Math.PI);
};
const graduationsPadding = 0.5;
const textsPadding = 0.6;
const handsPadding = 1;
const handsTailLength = 0.7;
const hHandLengthRatio = 0.75;
const mHandLengthRatio = 1;
const sHandLengthRatio = 1;
const numbersOpacityFactor = 0.35;
const props = withDefaults(
defineProps<{
thickness?: number;
offset?: number;
twentyfour?: boolean;
graduations?: "none" | "dots" | "numbers";
fadeGraduations?: boolean;
sAnimation?: "none" | "elastic" | "easeOut";
}>(),
{
numbers: false,
thickness: 0.1,
offset: 0 - new Date().getTimezoneOffset(),
twentyfour: false,
graduations: "dots",
fadeGraduations: true,
sAnimation: "elastic",
}
);
const graduationsMajor = computed(() => {
const angles: number[] = [];
const times = props.twentyfour ? 24 : 12;
for (let i = 0; i < times; i++) {
const angle = (Math.PI * i) / (times / 2);
angles.push(angle);
}
return angles;
});
const texts = computed(() => {
const angles: number[] = [];
const times = props.twentyfour ? 24 : 12;
for (let i = 0; i < times; i++) {
const angle = (Math.PI * i) / (times / 2);
angles.push(angle);
}
return angles;
});
let enabled = true;
let majorGraduationColor = $ref<string>();
//let minorGraduationColor = $ref<string>();
let sHandColor = $ref<string>();
let mHandColor = $ref<string>();
let hHandColor = $ref<string>();
let nowColor = $ref<string>();
let h = $ref<number>(0);
let m = $ref<number>(0);
let s = $ref<number>(0);
let hAngle = $ref<number>(0);
let mAngle = $ref<number>(0);
let sAngle = $ref<number>(0);
let disableSAnimate = $ref(false);
let sOneRound = false;
function tick() {
const now = new Date();
now.setMinutes(
now.getMinutes() + (new Date().getTimezoneOffset() + props.offset)
);
s = now.getSeconds();
m = now.getMinutes();
h = now.getHours();
hAngle =
(Math.PI * ((h % (props.twentyfour ? 24 : 12)) + (m + s / 60) / 60)) /
(props.twentyfour ? 12 : 6);
mAngle = (Math.PI * (m + s / 60)) / 30;
if (sOneRound) {
// (59->0)
sAngle = (Math.PI * 60) / 30;
window.setTimeout(() => {
disableSAnimate = true;
window.setTimeout(() => {
sAngle = 0;
window.setTimeout(() => {
disableSAnimate = false;
}, 100);
}, 100);
}, 700);
} else {
sAngle = (Math.PI * s) / 30;
}
sOneRound = s === 59;
}
tick();
function calcColors() {
const computedStyle = getComputedStyle(document.documentElement);
const dark = tinycolor(computedStyle.getPropertyValue("--bg")).isDark();
const accent = tinycolor(
computedStyle.getPropertyValue("--accent")
).toHexString();
majorGraduationColor = dark
? "rgba(255, 255, 255, 0.3)"
: "rgba(0, 0, 0, 0.3)";
//minorGraduationColor = dark ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
sHandColor = dark ? "rgba(255, 255, 255, 0.5)" : "rgba(0, 0, 0, 0.3)";
mHandColor = tinycolor(
computedStyle.getPropertyValue("--fg")
).toHexString();
hHandColor = accent;
nowColor = accent;
}
calcColors();
onMounted(() => {
const update = () => {
if (enabled) {
tick();
window.setTimeout(update, 1000);
}
};
update();
globalEvents.on("themeChanged", calcColors);
});
onBeforeUnmount(() => {
enabled = false;
globalEvents.off("themeChanged", calcColors);
});
</script>
<style lang="scss" scoped>
.mbcofsoe {
display: block;
> .s {
will-change: transform;
transform-origin: 50% 50%;
&.animate.elastic {
transition: transform 0.2s cubic-bezier(0.4, 2.08, 0.55, 0.44);
}
&.animate.easeOut {
transition: transform 0.7s cubic-bezier(0, 0.7, 0.3, 1);
}
}
}
</style>

View File

@ -1,564 +0,0 @@
<template>
<div
ref="rootEl"
class="swhvrteh _popup _shadow"
:style="{ zIndex }"
@contextmenu.prevent="() => {}"
>
<ol v-if="type === 'user'" ref="suggests" class="users">
<li
v-for="user in users"
tabindex="-1"
class="user"
@click="complete(type, user)"
@keydown="onKeydown"
>
<img class="avatar" :src="user.avatarUrl" />
<span class="name">
<MkUserName :key="user.id" :user="user" />
</span>
<span class="username">@{{ acct(user) }}</span>
</li>
<li
tabindex="-1"
class="choose"
@click="chooseUser()"
@keydown="onKeydown"
>
{{ i18n.ts.selectUser }}
</li>
</ol>
<ol v-else-if="hashtags.length > 0" ref="suggests" class="hashtags">
<li
v-for="hashtag in hashtags"
tabindex="-1"
@click="complete(type, hashtag)"
@keydown="onKeydown"
>
<span class="name">{{ hashtag }}</span>
</li>
</ol>
<ol v-else-if="emojis.length > 0" ref="suggests" class="emojis">
<li
v-for="emoji in emojis"
tabindex="-1"
@click="complete(type, emoji.emoji)"
@keydown="onKeydown"
>
<span v-if="emoji.isCustomEmoji" class="emoji"
><img
:src="
defaultStore.state.disableShowingAnimatedImages
? getStaticImageUrl(emoji.url)
: emoji.url
"
:alt="emoji.emoji"
/></span>
<span
v-else-if="!defaultStore.state.useOsNativeEmojis"
class="emoji"
><img :src="emoji.url" :alt="emoji.emoji"
/></span>
<span v-else class="emoji">{{ emoji.emoji }}</span>
<span
class="name"
v-html="emoji.name.replace(q, `<b>${q}</b>`)"
></span>
<span v-if="emoji.aliasOf" class="alias"
>({{ emoji.aliasOf }})</span
>
</li>
</ol>
<ol v-else-if="mfmTags.length > 0" ref="suggests" class="mfmTags">
<li
v-for="tag in mfmTags"
tabindex="-1"
@click="complete(type, tag)"
@keydown="onKeydown"
>
<span class="tag">{{ tag }}</span>
</li>
</ol>
</div>
</template>
<script lang="ts">
import {
markRaw,
ref,
onUpdated,
onMounted,
onBeforeUnmount,
nextTick,
watch,
} from "vue";
import contains from "@/scripts/contains";
import { char2filePath } from "@/scripts/twemoji-base";
import { getStaticImageUrl } from "@/scripts/get-static-image-url";
import { acct } from "@/filters/user";
import * as os from "@/os";
import { MFM_TAGS } from "@/scripts/mfm-tags";
import { defaultStore } from "@/store";
import { emojilist, addSkinTone } from "@/scripts/emojilist";
import { instance } from "@/instance";
import { i18n } from "@/i18n";
type EmojiDef = {
emoji: string;
name: string;
aliasOf?: string;
url?: string;
isCustomEmoji?: boolean;
};
const lib = emojilist.filter((x) => x.category !== "flags");
for (const emoji of lib) {
if (emoji.skin_tone_support) {
emoji.emoji = addSkinTone(emoji.emoji);
}
}
const emjdb: EmojiDef[] = lib.map((x) => ({
emoji: x.emoji,
name: x.slug,
url: char2filePath(x.emoji),
}));
for (const x of lib) {
if (x.keywords) {
for (const k of x.keywords) {
emjdb.push({
emoji: x.emoji,
name: k,
aliasOf: x.slug,
url: char2filePath(x.emoji),
});
}
}
}
emjdb.sort((a, b) => a.name.length - b.name.length);
//#region Construct Emoji DB
const customEmojis = instance.emojis;
const emojiDefinitions: EmojiDef[] = [];
for (const x of customEmojis) {
emojiDefinitions.push({
name: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true,
});
if (x.aliases) {
for (const alias of x.aliases) {
emojiDefinitions.push({
name: alias,
aliasOf: x.name,
emoji: `:${x.name}:`,
url: x.url,
isCustomEmoji: true,
});
}
}
}
emojiDefinitions.sort((a, b) => a.name.length - b.name.length);
const emojiDb = markRaw(emojiDefinitions.concat(emjdb));
//#endregion
export default {
emojiDb,
emojiDefinitions,
emojilist,
customEmojis,
};
</script>
<script lang="ts" setup>
const props = defineProps<{
type: string;
q: string | null;
textarea: HTMLTextAreaElement;
close: () => void;
x: number;
y: number;
}>();
const emit = defineEmits<{
(event: "done", value: { type: string; value: any }): void;
(event: "closed"): void;
}>();
const suggests = ref<Element>();
const rootEl = ref<HTMLDivElement>();
const fetching = ref(true);
const users = ref<any[]>([]);
const hashtags = ref<any[]>([]);
const emojis = ref<EmojiDef[]>([]);
const items = ref<Element[] | HTMLCollection>([]);
const mfmTags = ref<string[]>([]);
const select = ref(-1);
const zIndex = os.claimZIndex("high");
function complete(type: string, value: any) {
emit("done", { type, value });
emit("closed");
if (type === "emoji") {
let recents = defaultStore.state.recentlyUsedEmojis;
recents = recents.filter((emoji: any) => emoji !== value);
recents.unshift(value);
defaultStore.set("recentlyUsedEmojis", recents.splice(0, 32));
}
}
function setPosition() {
if (!rootEl.value) return;
if (props.x + rootEl.value.offsetWidth > window.innerWidth) {
rootEl.value.style.left =
window.innerWidth - rootEl.value.offsetWidth + "px";
} else {
rootEl.value.style.left = `${props.x}px`;
}
if (props.y + rootEl.value.offsetHeight > window.innerHeight) {
rootEl.value.style.top = props.y - rootEl.value.offsetHeight + "px";
rootEl.value.style.marginTop = "0";
} else {
rootEl.value.style.top = props.y + "px";
rootEl.value.style.marginTop = "calc(1em + 8px)";
}
}
function exec() {
select.value = -1;
if (suggests.value) {
for (const el of Array.from(items.value)) {
el.removeAttribute("data-selected");
}
}
if (props.type === "user") {
if (!props.q) {
users.value = [];
fetching.value = false;
return;
}
const cacheKey = `autocomplete:user:${props.q}`;
const cache = sessionStorage.getItem(cacheKey);
if (cache) {
users.value = JSON.parse(cache);
fetching.value = false;
} else {
os.api("users/search-by-username-and-host", {
username: props.q,
limit: 10,
detail: false,
}).then((searchedUsers) => {
users.value = searchedUsers as any[];
fetching.value = false;
//
sessionStorage.setItem(cacheKey, JSON.stringify(searchedUsers));
});
}
} else if (props.type === "hashtag") {
if (!props.q || props.q === "") {
hashtags.value = JSON.parse(
localStorage.getItem("hashtags") || "[]"
);
fetching.value = false;
} else {
const cacheKey = `autocomplete:hashtag:${props.q}`;
const cache = sessionStorage.getItem(cacheKey);
if (cache) {
const hashtags = JSON.parse(cache);
hashtags.value = hashtags;
fetching.value = false;
} else {
os.api("hashtags/search", {
query: props.q,
limit: 30,
}).then((searchedHashtags) => {
hashtags.value = searchedHashtags as any[];
fetching.value = false;
//
sessionStorage.setItem(
cacheKey,
JSON.stringify(searchedHashtags)
);
});
}
}
} else if (props.type === "emoji") {
if (!props.q || props.q === "") {
// 使
emojis.value = defaultStore.state.recentlyUsedEmojis
.map((emoji) =>
emojiDb.find((dbEmoji) => dbEmoji.emoji === emoji)
)
.filter((x) => x) as EmojiDef[];
return;
}
const matched: EmojiDef[] = [];
const max = 30;
emojiDb.some((x) => {
if (
x.name.startsWith(props.q ?? "") &&
!x.aliasOf &&
!matched.some((y) => y.emoji === x.emoji)
)
matched.push(x);
return matched.length === max;
});
if (matched.length < max) {
emojiDb.some((x) => {
if (
x.name.startsWith(props.q ?? "") &&
!matched.some((y) => y.emoji === x.emoji)
)
matched.push(x);
return matched.length === max;
});
}
if (matched.length < max) {
emojiDb.some((x) => {
if (
x.name.includes(props.q ?? "") &&
!matched.some((y) => y.emoji === x.emoji)
)
matched.push(x);
return matched.length === max;
});
}
emojis.value = matched;
} else if (props.type === "mfmTag") {
if (!props.q || props.q === "") {
mfmTags.value = MFM_TAGS;
return;
}
mfmTags.value = MFM_TAGS.filter((tag) => tag.startsWith(props.q ?? ""));
}
}
function onMousedown(event: Event) {
if (!contains(rootEl.value, event.target) && rootEl.value !== event.target)
props.close();
}
function onKeydown(event: KeyboardEvent) {
const cancel = () => {
event.preventDefault();
event.stopPropagation();
};
switch (event.key) {
case "Enter":
if (select.value !== -1) {
cancel();
(items.value[select.value] as any).click();
} else {
props.close();
}
break;
case "Escape":
cancel();
props.close();
break;
case "ArrowUp":
if (select.value !== -1) {
cancel();
selectPrev();
} else {
props.close();
}
break;
case "Tab":
case "ArrowDown":
cancel();
selectNext();
break;
default:
event.stopPropagation();
props.textarea.focus();
}
}
function selectNext() {
if (++select.value >= items.value.length) select.value = 0;
if (items.value.length === 0) select.value = -1;
applySelect();
}
function selectPrev() {
if (--select.value < 0) select.value = items.value.length - 1;
applySelect();
}
function applySelect() {
for (const el of Array.from(items.value)) {
el.removeAttribute("data-selected");
}
if (select.value !== -1) {
items.value[select.value].setAttribute("data-selected", "true");
(items.value[select.value] as any).focus();
}
}
function chooseUser() {
props.close();
os.selectUser().then((user) => {
complete("user", user);
props.textarea.focus();
});
}
onUpdated(() => {
setPosition();
items.value = suggests.value?.children ?? [];
});
onMounted(() => {
setPosition();
props.textarea.addEventListener("keydown", onKeydown);
for (const el of Array.from(document.querySelectorAll("body *"))) {
el.addEventListener("mousedown", onMousedown);
}
nextTick(() => {
exec();
watch(
() => props.q,
() => {
nextTick(() => {
exec();
});
}
);
});
});
onBeforeUnmount(() => {
props.textarea.removeEventListener("keydown", onKeydown);
for (const el of Array.from(document.querySelectorAll("body *"))) {
el.removeEventListener("mousedown", onMousedown);
}
});
</script>
<style lang="scss" scoped>
.swhvrteh {
position: fixed;
max-width: 100%;
margin-top: calc(1em + 8px);
overflow: hidden;
transition: top 0.1s ease, left 0.1s ease;
> ol {
display: block;
margin: 0;
padding: 4px 0;
max-height: 190px;
max-width: 500px;
overflow: auto;
list-style: none;
> li {
display: flex;
align-items: center;
padding: 4px 12px;
white-space: nowrap;
overflow: hidden;
font-size: 0.9em;
cursor: default;
&,
* {
user-select: none;
}
* {
overflow: hidden;
text-overflow: ellipsis;
}
&:hover {
background: var(--X3);
}
&[data-selected="true"] {
background: var(--accent);
&,
* {
color: #fff !important;
}
}
&:active {
background: var(--accentDarken);
&,
* {
color: #fff !important;
}
}
}
}
> .users > li {
.avatar {
min-width: 28px;
min-height: 28px;
max-width: 28px;
max-height: 28px;
margin: 0 8px 0 0;
border-radius: 100%;
}
.name {
margin: 0 8px 0 0;
}
}
> .emojis > li {
.emoji {
display: inline-block;
margin: 0 4px 0 0;
width: 24px;
> img {
width: 24px;
vertical-align: bottom;
}
}
.alias {
margin: 0 0 0 8px;
}
}
> .mfmTags > li {
.name {
}
}
}
</style>

View File

@ -1,44 +0,0 @@
<template>
<div class="defgtij">
<div v-for="user in users" :key="user.id" class="avatar-holder">
<MkAvatar :user="user" :show-indicator="true" class="avatar" />
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from "vue";
import * as os from "@/os";
const props = defineProps<{
userIds: string[];
}>();
const users = ref([]);
onMounted(async () => {
users.value = await os.api("users/show", {
userIds: props.userIds,
});
});
</script>
<style lang="scss">
.defgtij {
padding: 12px;
grid-gap: 12px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(30px, 40px));
place-content: center;
> .avatar-holder {
aspect-ratio: 1;
> .avatar {
width: 100%;
height: 100%;
aspect-ratio: 1;
}
}
}
</style>

View File

@ -1,254 +0,0 @@
<template>
<button
v-if="!link"
class="bghgjjyj _button"
:class="{ inline, primary, gradate, danger, rounded, full, mini, chip }"
:type="type"
@click="emit('click', $event)"
@mousedown="onMousedown"
>
<div ref="ripples" class="ripples"></div>
<div class="content">
<slot></slot>
</div>
</button>
<MkA
v-else
class="bghgjjyj _button"
:class="{ inline, primary, gradate, danger, rounded, full, mini }"
:to="to"
@mousedown="onMousedown"
>
<div ref="ripples" class="ripples"></div>
<div class="content">
<slot></slot>
</div>
</MkA>
</template>
<script lang="ts" setup>
import { nextTick, onMounted } from "vue";
const props = defineProps<{
type?: "button" | "submit" | "reset";
primary?: boolean;
gradate?: boolean;
rounded?: boolean;
inline?: boolean;
link?: boolean;
to?: string;
autofocus?: boolean;
wait?: boolean;
danger?: boolean;
full?: boolean;
mini?: boolean;
chip?: boolean;
}>();
const emit = defineEmits<{
(ev: "click", payload: MouseEvent): void;
}>();
let el = $ref<HTMLElement | null>(null);
let ripples = $ref<HTMLElement | null>(null);
onMounted(() => {
if (props.autofocus) {
nextTick(() => {
el!.focus();
});
}
});
function distance(p, q): number {
return Math.hypot(p.x - q.x, p.y - q.y);
}
function calcCircleScale(boxW, boxH, circleCenterX, circleCenterY): number {
const origin = { x: circleCenterX, y: circleCenterY };
const dist1 = distance({ x: 0, y: 0 }, origin);
const dist2 = distance({ x: boxW, y: 0 }, origin);
const dist3 = distance({ x: 0, y: boxH }, origin);
const dist4 = distance({ x: boxW, y: boxH }, origin);
return Math.max(dist1, dist2, dist3, dist4) * 2;
}
function onMousedown(evt: MouseEvent): void {
const target = evt.target! as HTMLElement;
const rect = target.getBoundingClientRect();
const ripple = document.createElement("div");
ripple.style.top = (evt.clientY - rect.top - 1).toString() + "px";
ripple.style.left = (evt.clientX - rect.left - 1).toString() + "px";
ripples!.appendChild(ripple);
const circleCenterX = evt.clientX - rect.left;
const circleCenterY = evt.clientY - rect.top;
const scale = calcCircleScale(
target.clientWidth,
target.clientHeight,
circleCenterX,
circleCenterY
);
window.setTimeout(() => {
ripple.style.transform = "scale(" + scale / 2 + ")";
}, 1);
window.setTimeout(() => {
ripple.style.transition = "all 1s ease";
ripple.style.opacity = "0";
}, 1000);
window.setTimeout(() => {
if (ripples) ripples.removeChild(ripple);
}, 2000);
}
</script>
<style lang="scss" scoped>
.bghgjjyj {
position: relative;
z-index: 1; // box-shadow
display: block;
min-width: 100px;
min-height: 35px;
width: max-content;
padding: 8px 16px;
text-align: center;
font-weight: normal;
font-size: max(12px, 1em);
box-shadow: none;
text-decoration: none;
background: var(--buttonBg);
border-radius: 5px;
overflow: clip;
box-sizing: border-box;
transition: background 0.1s ease;
margin-right: 0.2rem;
margin-left: 0.2rem;
&:not(:disabled):hover {
background: var(--buttonHoverBg);
}
&:not(:disabled):active {
background: var(--buttonHoverBg);
}
&.full {
width: 100%;
}
&.rounded {
border-radius: 999px;
}
&.primary {
font-weight: bold;
color: var(--fgOnAccent) !important;
background: var(--accent);
&:not(:disabled):hover {
background: var(--X8);
}
&:not(:disabled):active {
background: var(--X8);
}
}
&.gradate {
font-weight: bold;
color: var(--fgOnAccent) !important;
background: linear-gradient(
90deg,
var(--buttonGradateA),
var(--buttonGradateB)
);
&:not(:disabled):hover {
background: linear-gradient(90deg, var(--X8), var(--X8));
}
&:not(:disabled):active {
background: linear-gradient(90deg, var(--X8), var(--X8));
}
}
&.danger {
color: #eb6f92;
&.primary {
color: #e0def4;
background: #eb6f92;
&:not(:disabled):hover {
background: #eb6f92;
}
&:not(:disabled):active {
background: #b4637a;
}
}
}
&.mini {
padding: 4px 8px;
font-size: max(12px, 0.9em);
border-radius: 100px;
}
&.chip {
padding: 4px 12px;
font-size: max(12px, 0.9em);
min-width: unset;
border-radius: 100px;
}
&:disabled {
opacity: 0.7;
}
&:focus-visible {
outline: auto;
}
&.inline {
display: inline-block;
width: auto;
min-width: 100px;
}
> .ripples {
position: absolute;
z-index: 0;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 6px;
overflow: hidden;
::v-deep(div) {
position: absolute;
width: 2px;
height: 2px;
border-radius: 100%;
background: rgba(0, 0, 0, 0.1);
opacity: 1;
transform: scale(1);
transition: all 0.5s cubic-bezier(0, 0.5, 0, 1);
}
}
&.primary > .ripples ::v-deep(div) {
background: rgba(0, 0, 0, 0.15);
}
> .content {
position: relative;
z-index: 1;
}
}
</style>

View File

@ -1,136 +0,0 @@
<template>
<div>
<span v-if="!available">{{ i18n.ts.waiting }}<MkEllipsis /></span>
<div ref="captchaEl"></div>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, onMounted, onBeforeUnmount, watch } from "vue";
import { defaultStore } from "@/store";
import { i18n } from "@/i18n";
type Captcha = {
render(
container: string | Node,
options: {
readonly [_ in
| "sitekey"
| "theme"
| "type"
| "size"
| "tabindex"
| "callback"
| "expired"
| "expired-callback"
| "error-callback"
| "endpoint"]?: unknown;
}
): string;
remove(id: string): void;
execute(id: string): void;
reset(id?: string): void;
getResponse(id: string): string;
};
type CaptchaProvider = "hcaptcha" | "recaptcha";
type CaptchaContainer = {
readonly [_ in CaptchaProvider]?: Captcha;
};
declare global {
interface Window extends CaptchaContainer {}
}
const props = defineProps<{
provider: CaptchaProvider;
sitekey: string;
modelValue?: string | null;
}>();
const emit = defineEmits<{
(ev: "update:modelValue", v: string | null): void;
}>();
const available = ref(false);
const captchaEl = ref<HTMLDivElement | undefined>();
const variable = computed(() => {
switch (props.provider) {
case "hcaptcha":
return "hcaptcha";
case "recaptcha":
return "grecaptcha";
}
});
const loaded = !!window[variable.value];
const src = computed(() => {
switch (props.provider) {
case "hcaptcha":
return "https://js.hcaptcha.com/1/api.js?render=explicit&recaptchacompat=off";
case "recaptcha":
return "https://www.recaptcha.net/recaptcha/api.js?render=explicit";
}
});
const captcha = computed<Captcha>(
() => window[variable.value] || ({} as unknown as Captcha)
);
if (loaded) {
available.value = true;
} else {
(
document.getElementById(props.provider) ||
document.head.appendChild(
Object.assign(document.createElement("script"), {
async: true,
id: props.provider,
src: src.value,
})
)
).addEventListener("load", () => (available.value = true));
}
function reset() {
if (captcha.value.reset) captcha.value.reset();
}
function requestRender() {
if (captcha.value.render && captchaEl.value instanceof Element) {
captcha.value.render(captchaEl.value, {
sitekey: props.sitekey,
theme: defaultStore.state.darkMode ? "dark" : "light",
callback: callback,
"expired-callback": callback,
"error-callback": callback,
});
} else {
window.setTimeout(requestRender, 1);
}
}
function callback(response?: string) {
emit("update:modelValue", typeof response === "string" ? response : null);
}
onMounted(() => {
if (available.value) {
requestRender();
} else {
watch(available, requestRender);
}
});
onBeforeUnmount(() => {
reset();
});
defineExpose({
reset,
});
</script>

View File

@ -1,135 +0,0 @@
<template>
<button
class="hdcaacmi _button"
:class="{ wait, active: isFollowing, full }"
:disabled="wait"
@click="onClick"
>
<template v-if="!wait">
<template v-if="isFollowing">
<span v-if="full">{{ i18n.ts.unfollow }}</span
><i class="ph-minus ph-bold ph-lg"></i>
</template>
<template v-else>
<span v-if="full">{{ i18n.ts.follow }}</span
><i class="ph-plus ph-bold ph-lg"></i>
</template>
</template>
<template v-else>
<span v-if="full">{{ i18n.ts.processing }}</span
><i class="ph-circle-notch ph-bold ph-lg fa-pulse ph-fw ph-lg"></i>
</template>
</button>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import * as os from "@/os";
import { i18n } from "@/i18n";
const props = withDefaults(
defineProps<{
channel: Record<string, any>;
full?: boolean;
}>(),
{
full: false,
}
);
const isFollowing = ref<boolean>(props.channel.isFollowing);
const wait = ref(false);
async function onClick() {
wait.value = true;
try {
if (isFollowing.value) {
await os.api("channels/unfollow", {
channelId: props.channel.id,
});
isFollowing.value = false;
} else {
await os.api("channels/follow", {
channelId: props.channel.id,
});
isFollowing.value = true;
}
} catch (err) {
console.error(err);
} finally {
wait.value = false;
}
}
</script>
<style lang="scss" scoped>
.hdcaacmi {
position: relative;
display: inline-block;
font-weight: bold;
color: var(--accent);
background: transparent;
border: solid 1px var(--accent);
padding: 0;
height: 31px;
font-size: 16px;
border-radius: 32px;
background: #fff;
&.full {
padding: 0 8px 0 12px;
font-size: 14px;
}
&:not(.full) {
width: 31px;
}
&:focus-visible {
&:after {
content: "";
pointer-events: none;
position: absolute;
top: -5px;
right: -5px;
bottom: -5px;
left: -5px;
border: 2px solid var(--focus);
border-radius: 32px;
}
}
&:hover {
//background: mix($primary, #fff, 20);
}
&:active {
//background: mix($primary, #fff, 40);
}
&.active {
color: #fff;
background: var(--accent);
&:hover {
background: var(--accentLighten);
border-color: var(--accentLighten);
}
&:active {
background: var(--accentDarken);
border-color: var(--accentDarken);
}
}
&.wait {
cursor: wait !important;
opacity: 0.7;
}
> span {
margin-right: 6px;
}
}
</style>

View File

@ -1,42 +0,0 @@
<template>
<MkPagination :pagination="pagination">
<template #empty>
<div class="_fullinfo">
<img
src="/static-assets/badges/not-found.png"
class="_ghost"
:alt="i18n.ts.notFound"
/>
<div>{{ i18n.ts.notFound }}</div>
</div>
</template>
<template #default="{ items }">
<MkChannelPreview
v-for="item in items"
:key="item.id"
class="_margin"
:channel="extractor(item)"
/>
</template>
</MkPagination>
</template>
<script lang="ts" setup>
import MkChannelPreview from "@/components/MkChannelPreview.vue";
import MkPagination, { Paging } from "@/components/MkPagination.vue";
import { i18n } from "@/i18n";
const props = withDefaults(
defineProps<{
pagination: Paging;
noGap?: boolean;
extractor?: (item: any) => any;
}>(),
{
extractor: (item) => item,
}
);
</script>
<style lang="scss" scoped></style>

View File

@ -1,174 +0,0 @@
<template>
<MkA :to="`/channels/${channel.id}`" class="eftoefju _panel" tabindex="-1">
<div class="banner" :style="bannerStyle">
<div class="fade"></div>
<div class="name">
<i class="ph-television ph-bold ph-lg"></i> {{ channel.name }}
</div>
<div class="status">
<div>
<i class="ph-users ph-bold ph-lg ph-fw ph-lg"></i>
<I18n
:src="i18n.ts._channel.usersCount"
tag="span"
style="margin-left: 4px"
>
<template #n>
<b>{{ channel.usersCount }}</b>
</template>
</I18n>
</div>
<div>
<i class="ph-pencil ph-bold ph-lg ph-fw ph-lg"></i>
<I18n
:src="i18n.ts._channel.notesCount"
tag="span"
style="margin-left: 4px"
>
<template #n>
<b>{{ channel.notesCount }}</b>
</template>
</I18n>
</div>
</div>
</div>
<article v-if="channel.description">
<p :title="channel.description">
{{
channel.description.length > 85
? channel.description.slice(0, 85) + "…"
: channel.description
}}
</p>
</article>
<footer>
<span v-if="channel.lastNotedAt">
{{ i18n.ts.updatedAt }}: <MkTime :time="channel.lastNotedAt" />
</span>
</footer>
</MkA>
</template>
<script lang="ts" setup>
import { computed } from "vue";
import { i18n } from "@/i18n";
const props = defineProps<{
channel: Record<string, any>;
}>();
const bannerStyle = computed(() => {
if (props.channel.bannerUrl) {
return { backgroundImage: `url(${props.channel.bannerUrl})` };
} else {
return { backgroundColor: "#4c5e6d" };
}
});
</script>
<style lang="scss" scoped>
.eftoefju {
display: block;
overflow: hidden;
width: 100%;
&:hover {
text-decoration: none;
}
> .banner {
position: relative;
width: 100%;
height: 200px;
background-position: center;
background-size: cover;
> .fade {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 64px;
background: linear-gradient(0deg, var(--panel), var(--X15));
}
> .name {
position: absolute;
top: 16px;
left: 16px;
padding: 12px 16px;
-webkit-backdrop-filter: var(--blur, blur(8px));
backdrop-filter: var(--blur, blur(8px));
background: rgba(0, 0, 0, 0.2);
color: #fff;
font-size: 1.2em;
border-radius: 999px;
}
> .status {
position: absolute;
z-index: 1;
bottom: 16px;
right: 16px;
padding: 8px 12px;
font-size: 80%;
-webkit-backdrop-filter: var(--blur, blur(8px));
backdrop-filter: var(--blur, blur(8px));
background: rgba(0, 0, 0, 0.2);
border-radius: 6px;
color: #fff;
}
}
> article {
padding: 16px;
> p {
margin: 0;
font-size: 1em;
}
}
> footer {
padding: 12px 16px;
border-top: solid 0.5px var(--divider);
> span {
opacity: 0.7;
font-size: 0.9em;
}
}
@media (max-width: 550px) {
font-size: 0.9em;
> .banner {
height: 80px;
> .status {
display: none;
}
}
> article {
padding: 12px;
}
> footer {
display: none;
}
}
@media (max-width: 500px) {
font-size: 0.8em;
> .banner {
height: 70px;
}
> article {
padding: 8px;
}
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1,68 +0,0 @@
<template>
<MkTooltip
ref="tooltip"
:showing="showing"
:x="x"
:y="y"
:max-width="340"
:direction="'top'"
:inner-margin="16"
@closed="emit('closed')"
>
<div v-if="title || series" class="qpcyisrl">
<div v-if="title" class="title">{{ title }}</div>
<template v-if="series">
<div v-for="x in series" class="series">
<span
class="color"
:style="{
background: x.backgroundColor,
borderColor: x.borderColor,
}"
></span>
<span>{{ x.text }}</span>
</div>
</template>
</div>
</MkTooltip>
</template>
<script lang="ts" setup>
import {} from "vue";
import MkTooltip from "./MkTooltip.vue";
const props = defineProps<{
showing: boolean;
x: number;
y: number;
title?: string;
series?: {
backgroundColor: string;
borderColor: string;
text: string;
}[];
}>();
const emit = defineEmits<{
(ev: "closed"): void;
}>();
</script>
<style lang="scss" scoped>
.qpcyisrl {
> .title {
margin-bottom: 4px;
}
> .series {
> .color {
display: inline-block;
width: 8px;
height: 8px;
border-width: 1px;
border-style: solid;
margin-right: 8px;
}
}
}
</style>

View File

@ -1,39 +0,0 @@
<template>
<XModalWindow
ref="dialog"
:width="600"
@close="dialog?.close()"
@closed="$emit('closed')"
>
<template #header>{{ i18n.ts._mfm.cheatSheet }}</template>
<XCheatSheet :popup="true" style="background: var(--bg)" />
</XModalWindow>
</template>
<script lang="ts" setup>
import XModalWindow from "@/components/MkModalWindow.vue";
import XCheatSheet from "@/pages/mfm-cheat-sheet.vue";
import { i18n } from "@/i18n";
const emit = defineEmits<{
(ev: "done"): void;
(ev: "closed"): void;
}>();
const dialog = $ref<InstanceType<typeof XModalWindow>>();
function close(res) {
dialog.close();
}
</script>
<style lang="scss" scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s ease-in-out;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>

View File

@ -1,30 +0,0 @@
<template>
<code v-if="inline" :class="`language-${prismLang}`" v-html="html"></code>
<pre
v-else
:class="`language-${prismLang}`"
><code :class="`language-${prismLang}`" v-html="html"></code></pre>
</template>
<script lang="ts" setup>
import { computed } from "vue";
import Prism from "prismjs";
import "prismjs/themes/prism-okaidia.css";
const props = defineProps<{
code: string;
lang?: string;
inline?: boolean;
}>();
const prismLang = computed(() =>
Prism.languages[props.lang] ? props.lang : "js"
);
const html = computed(() =>
Prism.highlight(
props.code,
Prism.languages[prismLang.value],
prismLang.value
)
);
</script>

View File

@ -1,17 +0,0 @@
<template>
<XCode :code="code" :lang="lang" :inline="inline" />
</template>
<script lang="ts" setup>
import { defineAsyncComponent } from "vue";
defineProps<{
code: string;
lang?: string;
inline?: boolean;
}>();
const XCode = defineAsyncComponent(
() => import("@/components/MkCode.core.vue")
);
</script>

View File

@ -1,308 +0,0 @@
<template>
<div
v-size="{ max: [380] }"
class="ukygtjoj _panel"
:class="{
naked,
thin,
hideHeader: !showHeader,
scrollable,
closed: !showBody,
}"
>
<header v-if="showHeader" ref="header">
<div class="title"><slot name="header"></slot></div>
<div class="sub">
<slot name="func"></slot>
<button
v-if="foldable"
class="_button"
@click="() => (showBody = !showBody)"
>
<template v-if="showBody"
><i class="ph-caret-up ph-bold ph-lg"></i
></template>
<template v-else
><i class="ph-caret-down ph-bold ph-lg"></i
></template>
</button>
</div>
</header>
<transition
:name="$store.state.animation ? 'container-toggle' : ''"
@enter="enter"
@after-enter="afterEnter"
@leave="leave"
@after-leave="afterLeave"
>
<div
v-show="showBody"
ref="content"
class="content"
:class="{ omitted }"
>
<slot></slot>
<button
v-if="omitted"
class="fade _button"
@click="
() => {
ignoreOmit = true;
omitted = false;
}
"
>
<span>{{ i18n.ts.showMore }}</span>
</button>
</div>
</transition>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { i18n } from "@/i18n";
export default defineComponent({
props: {
showHeader: {
type: Boolean,
required: false,
default: true,
},
thin: {
type: Boolean,
required: false,
default: false,
},
naked: {
type: Boolean,
required: false,
default: false,
},
foldable: {
type: Boolean,
required: false,
default: false,
},
expanded: {
type: Boolean,
required: false,
default: true,
},
scrollable: {
type: Boolean,
required: false,
default: false,
},
maxHeight: {
type: Number,
required: false,
default: null,
},
},
data() {
return {
showBody: this.expanded,
omitted: null,
ignoreOmit: false,
i18n,
};
},
mounted() {
this.$watch(
"showBody",
(showBody) => {
const headerHeight = this.showHeader
? this.$refs.header.offsetHeight
: 0;
this.$el.style.minHeight = `${headerHeight}px`;
if (showBody) {
this.$el.style.flexBasis = "auto";
} else {
this.$el.style.flexBasis = `${headerHeight}px`;
}
},
{
immediate: true,
}
);
this.$el.style.setProperty("--maxHeight", this.maxHeight + "px");
const calcOmit = () => {
if (this.omitted || this.ignoreOmit || this.maxHeight == null)
return;
const height = this.$refs.content.offsetHeight;
this.omitted = height > this.maxHeight;
};
calcOmit();
new ResizeObserver((entries, observer) => {
calcOmit();
}).observe(this.$refs.content);
},
methods: {
toggleContent(show: boolean) {
if (!this.foldable) return;
this.showBody = show;
},
enter(el) {
const elementHeight = el.getBoundingClientRect().height;
el.style.height = 0;
el.offsetHeight; // reflow
el.style.height = elementHeight + "px";
},
afterEnter(el) {
el.style.height = null;
},
leave(el) {
const elementHeight = el.getBoundingClientRect().height;
el.style.height = elementHeight + "px";
el.offsetHeight; // reflow
el.style.height = 0;
},
afterLeave(el) {
el.style.height = null;
},
},
});
</script>
<style lang="scss" scoped>
.container-toggle-enter-active,
.container-toggle-leave-active {
overflow-y: hidden;
transition: opacity 0.5s, height 0.5s !important;
}
.container-toggle-enter-from {
opacity: 0;
}
.container-toggle-leave-to {
opacity: 0;
}
.ukygtjoj {
position: relative;
overflow: clip;
contain: content;
&.naked {
background: transparent !important;
box-shadow: none !important;
}
&.scrollable {
display: flex;
flex-direction: column;
> .content {
overflow: auto;
}
}
> header {
position: sticky;
top: var(--stickyTop, 0px);
left: 0;
color: var(--panelHeaderFg);
background: var(--panelHeaderBg);
border-bottom: solid 0.5px var(--panelHeaderDivider);
z-index: 2;
line-height: 1.4em;
> .title {
margin: 0;
padding: 12px 16px;
> ::v-deep(i) {
margin-right: 6px;
transform: translateY(0.1em);
}
&:empty {
display: none;
}
}
> .sub {
position: absolute;
z-index: 2;
top: 0;
right: 0;
height: 100%;
> ::v-deep(button) {
width: 42px;
height: 100%;
}
}
}
> .content {
--stickyTop: 0px;
&.omitted {
position: relative;
max-height: var(--maxHeight);
overflow: hidden;
> .fade {
display: block;
position: absolute;
z-index: 10;
bottom: 0;
left: 0;
width: 100%;
height: 64px;
background: linear-gradient(0deg, var(--panel), var(--X15));
> span {
display: inline-block;
background: var(--panel);
padding: 6px 10px;
font-size: 0.8em;
border-radius: 999px;
box-shadow: 0 2px 6px rgb(0 0 0 / 20%);
}
&:hover {
> span {
background: var(--panelHighlight);
}
}
}
}
}
&.max-width_380px,
&.thin {
> header {
> .title {
padding: 8px 10px;
font-size: 0.9em;
}
}
> .content {
}
}
}
._forceContainerFull_ .ukygtjoj {
> header {
> .title {
padding: 12px 16px !important;
}
}
}
._forceContainerFull_.ukygtjoj {
> header {
> .title {
padding: 12px 16px !important;
}
}
}
</style>

View File

@ -1,93 +0,0 @@
<template>
<transition :name="$store.state.animation ? 'fade' : ''" appear>
<div
ref="rootEl"
class="nvlagfpb"
:style="{ zIndex }"
@contextmenu.prevent.stop="() => {}"
>
<MkMenu :items="items" :align="'left'" @close="$emit('closed')" />
</div>
</transition>
</template>
<script lang="ts" setup>
import { onMounted, onBeforeUnmount } from "vue";
import MkMenu from "./MkMenu.vue";
import { MenuItem } from "./types/menu.vue";
import contains from "@/scripts/contains";
import * as os from "@/os";
const props = defineProps<{
items: MenuItem[];
ev: MouseEvent;
}>();
const emit = defineEmits<{
(ev: "closed"): void;
}>();
let rootEl = $ref<HTMLDivElement>();
let zIndex = $ref<number>(os.claimZIndex("high"));
onMounted(() => {
let left = props.ev.pageX + 1; // + 1
let top = props.ev.pageY + 1; // + 1
const width = rootEl.offsetWidth;
const height = rootEl.offsetHeight;
if (left + width - window.pageXOffset > window.innerWidth) {
left = window.innerWidth - width + window.pageXOffset;
}
if (top + height - window.pageYOffset > window.innerHeight) {
top = window.innerHeight - height + window.pageYOffset;
}
if (top < 0) {
top = 0;
}
if (left < 0) {
left = 0;
}
rootEl.style.top = `${top}px`;
rootEl.style.left = `${left}px`;
for (const el of Array.from(document.querySelectorAll("body *"))) {
el.addEventListener("mousedown", onMousedown);
}
});
onBeforeUnmount(() => {
for (const el of Array.from(document.querySelectorAll("body *"))) {
el.removeEventListener("mousedown", onMousedown);
}
});
function onMousedown(evt: Event) {
if (!contains(rootEl, evt.target) && rootEl !== evt.target) emit("closed");
}
</script>
<style lang="scss" scoped>
.nvlagfpb {
position: absolute;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s cubic-bezier(0.16, 1, 0.3, 1),
transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
transform-origin: left top;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: scale(0.9);
}
</style>

View File

@ -1,187 +0,0 @@
<template>
<XModalWindow
ref="dialogEl"
:width="800"
:height="500"
:scroll="false"
:with-ok-button="true"
@close="cancel()"
@ok="ok()"
@closed="$emit('closed')"
>
<template #header>{{ i18n.ts.cropImage }}</template>
<template #default="{ width, height }">
<div
class="mk-cropper-dialog"
:style="`--vw: ${width}px; --vh: ${height}px;`"
>
<Transition name="fade">
<div v-if="loading" class="loading">
<MkLoading />
</div>
</Transition>
<div class="container">
<img
ref="imgEl"
:src="imgUrl"
style="display: none"
@load="onImageLoad"
/>
</div>
</div>
</template>
</XModalWindow>
</template>
<script lang="ts" setup>
import { nextTick, onMounted } from "vue";
import * as misskey from "calckey-js";
import Cropper from "cropperjs";
import tinycolor from "tinycolor2";
import XModalWindow from "@/components/MkModalWindow.vue";
import * as os from "@/os";
import { $i } from "@/account";
import { defaultStore } from "@/store";
import { apiUrl, url } from "@/config";
import { query } from "@/scripts/url";
import { i18n } from "@/i18n";
const emit = defineEmits<{
(ev: "ok", cropped: misskey.entities.DriveFile): void;
(ev: "cancel"): void;
(ev: "closed"): void;
}>();
const props = defineProps<{
file: misskey.entities.DriveFile;
aspectRatio: number;
}>();
const imgUrl = `${url}/proxy/image.webp?${query({
url: props.file.url,
})}`;
let dialogEl = $ref<InstanceType<typeof XModalWindow>>();
let imgEl = $ref<HTMLImageElement>();
let cropper: Cropper | null = null;
let loading = $ref(true);
const ok = async () => {
const promise = new Promise<misskey.entities.DriveFile>(async (res) => {
const croppedCanvas = await cropper?.getCropperSelection()?.$toCanvas();
croppedCanvas.toBlob((blob) => {
const formData = new FormData();
formData.append("file", blob);
if (defaultStore.state.uploadFolder) {
formData.append("folderId", defaultStore.state.uploadFolder);
}
fetch(apiUrl + "/drive/files/create", {
method: "POST",
body: formData,
headers: {
authorization: `Bearer ${$i.token}`,
},
})
.then((response) => response.json())
.then((f) => {
res(f);
});
});
});
os.promiseDialog(promise);
const f = await promise;
emit("ok", f);
dialogEl.close();
};
const cancel = () => {
emit("cancel");
dialogEl.close();
};
const onImageLoad = () => {
loading = false;
if (cropper) {
cropper.getCropperImage()!.$center("contain");
cropper.getCropperSelection()!.$center();
}
};
onMounted(() => {
cropper = new Cropper(imgEl, {});
const computedStyle = getComputedStyle(document.documentElement);
const selection = cropper.getCropperSelection()!;
selection.themeColor = tinycolor(
computedStyle.getPropertyValue("--accent")
).toHexString();
selection.aspectRatio = props.aspectRatio;
selection.initialAspectRatio = props.aspectRatio;
selection.outlined = true;
window.setTimeout(() => {
cropper.getCropperImage()!.$center("contain");
selection.$center();
}, 100);
// 調
window.setTimeout(() => {
cropper.getCropperImage()!.$center("contain");
selection.$center();
}, 500);
});
</script>
<style lang="scss" scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s ease 0.5s;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.mk-cropper-dialog {
display: flex;
flex-direction: column;
width: var(--vw);
height: var(--vh);
position: relative;
> .loading {
position: absolute;
z-index: 10;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
-webkit-backdrop-filter: var(--blur, blur(10px));
backdrop-filter: var(--blur, blur(10px));
background: rgba(0, 0, 0, 0.5);
}
> .container {
flex: 1;
width: 100%;
height: 100%;
> ::v-deep(cropper-canvas) {
width: 100%;
height: 100%;
> cropper-selection > cropper-handle[action="move"] {
background: transparent;
}
}
}
}
</style>

Some files were not shown because too many files have changed in this diff Show More