Removed the frontend and removed unnecesary resource files
ci/woodpecker/tag/ociImageTag Pipeline is pending
Details
4
.envrc
|
@ -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
|
|
|
@ -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"
|
|
||||||
]
|
|
||||||
}
|
|
3
.weblate
|
@ -1,3 +0,0 @@
|
||||||
[weblate]
|
|
||||||
url = https://hosted.weblate.org/api/
|
|
||||||
translation = calckey/locales
|
|
|
@ -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
|
||||||
|
|
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 56 KiB |
|
@ -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.
|
|
||||||
*/
|
|
95
gulpfile.js
|
@ -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"),
|
|
||||||
);
|
|
||||||
});
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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.
|
|
1537
locales/ar-SA.yml
1661
locales/bn-BD.yml
2134
locales/ca-ES.yml
1009
locales/cs-CZ.yml
|
@ -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
|
|
2153
locales/de-DE.yml
|
@ -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.
|
|
2078
locales/en-US.yml
1929
locales/es-ES.yml
970
locales/fi.yml
|
@ -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.
|
|
2040
locales/fr-FR.yml
1792
locales/id-ID.yml
|
@ -1,3 +0,0 @@
|
||||||
declare const locales: { [lang: string]: any };
|
|
||||||
|
|
||||||
export = locales;
|
|
|
@ -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
|
|
||||||
),
|
|
||||||
{},
|
|
||||||
);
|
|
1563
locales/it-IT.yml
1933
locales/ja-JP.yml
1415
locales/ja-KS.yml
|
@ -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"
|
|
|
@ -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: "ಹೆಸರಿಸಿದ"
|
|
1717
locales/ko-KR.yml
|
@ -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
|
|
|
@ -1,2 +0,0 @@
|
||||||
---
|
|
||||||
_lang_: "Norsk Bokmål"
|
|
2032
locales/pl-PL.yml
|
@ -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"
|
|
|
@ -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ê
|
|
|
@ -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"
|
|
1991
locales/ru-RU.yml
1735
locales/sk-SK.yml
|
@ -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"
|
|
1193
locales/th-TH.yml
|
@ -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"
|
|
|
@ -1,6 +0,0 @@
|
||||||
---
|
|
||||||
_lang_: "ياپونچە"
|
|
||||||
search: "ئىزدەش"
|
|
||||||
searchByGoogle: "ئىزدەش"
|
|
||||||
_mfm:
|
|
||||||
search: "ئىزدەش"
|
|
1455
locales/uk-UA.yml
1740
locales/vi-VN.yml
1751
locales/zh-CN.yml
1848
locales/zh-TW.yml
14
package.json
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
})();
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
|
@ -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"]
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
};
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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)
|
|
|
@ -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}`)
|
|
|
@ -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>`)
|
|
||||||
}
|
|
|
@ -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')
|
|
|
@ -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')
|
|
|
@ -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}`)
|
|
|
@ -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}`)
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"tabWidth": 4,
|
|
||||||
"useTabs": true,
|
|
||||||
"singleQuote": false,
|
|
||||||
"vueIndentScriptAndStyle": false,
|
|
||||||
"plugins": ["vue"],
|
|
||||||
"overrides": [
|
|
||||||
{
|
|
||||||
"files": "*.vue",
|
|
||||||
"options": {
|
|
||||||
"parser": "vue"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
|
@ -1,7 +0,0 @@
|
||||||
declare module "@/themes/*.json5" {
|
|
||||||
import { Theme } from "@/scripts/theme";
|
|
||||||
|
|
||||||
const theme: Theme;
|
|
||||||
|
|
||||||
export default theme;
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
/// <reference types="vue/macros-global" />
|
|
||||||
|
|
||||||
declare module "*.vue" {
|
|
||||||
import type { DefineComponent } from "vue";
|
|
||||||
const component: DefineComponent<{}, {}, any>;
|
|
||||||
export default component;
|
|
||||||
}
|
|
Before Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 68 KiB |
|
@ -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 |
|
@ -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 |
Before Width: | Height: | Size: 6.9 KiB |
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|