Compare commits
107 Commits
Author | SHA1 | Date | |
---|---|---|---|
943a1940e2 | |||
15d166e30e | |||
83619fda98 | |||
12913a16fd | |||
e23ad7833d | |||
38aa760b57 | |||
acb9244205 | |||
3182606e99 | |||
7cc8646ad3 | |||
e793fced61 | |||
248edb5dfd | |||
9414a944b7 | |||
756b8a2a29 | |||
f142ed91fb | |||
6aef54a9e0 | |||
f1c9e596e8 | |||
862ddde0db | |||
ee5a060762 | |||
42d293ee60 | |||
04e27e160e | |||
62dede02ea | |||
6d1d7b5366 | |||
55e5c12441 | |||
0b34503c8a | |||
dc69490e3a | |||
1c241776a6 | |||
6812b895e7 | |||
ab439d0ed6 | |||
c7a2c368d4 | |||
2047860e71 | |||
1dbe03b210 | |||
b59a19c144 | |||
558d288e7b | |||
e24c8b6878 | |||
1772af9583 | |||
cb42f94d9c | |||
38474c7316 | |||
49febe1764 | |||
65addc8206 | |||
28f7e48dc6 | |||
d97fc9ce4e | |||
f26aeee819 | |||
c071467b6a | |||
334ca01092 | |||
c122ec2e79 | |||
d04014f875 | |||
e1247b3e45 | |||
8b9c445fef | |||
a65eb502d2 | |||
55c549a9f8 | |||
56600ba1df | |||
6b312f755e | |||
d6267f797d | |||
a2b8097b4b | |||
22bbee1fa3 | |||
fa1b38394c | |||
441790be2d | |||
5d66bb8794 | |||
a5cdc9a1f4 | |||
a5a2f9d01e | |||
89fb727f61 | |||
929e545514 | |||
3e7a87f75a | |||
caf40e40fb | |||
b608f63a1a | |||
dc44d9a0a8 | |||
bb926dd301 | |||
79cb836483 | |||
f1c4e4a10e | |||
798aedfc0f | |||
1077c2a637 | |||
cbe689607c | |||
948b70cb0f | |||
0263539202 | |||
52e54cf0dc | |||
24e7eeca0f | |||
d76345264d | |||
0eb115bf7e | |||
30d2a1d8b6 | |||
857c88e8d6 | |||
ffb9646ce9 | |||
db3724cf33 | |||
466c083233 | |||
ae2267220b | |||
c92744c3d3 | |||
35f075b887 | |||
6cc4edc5e8 | |||
c06091f78a | |||
f85399e355 | |||
47aaf04481 | |||
7063a6925f | |||
3cd04c4b81 | |||
942c802431 | |||
e6754eb880 | |||
70d02cf1be | |||
ef646b9576 | |||
ecd541873b | |||
5d10642e07 | |||
da34acd35f | |||
0108b8bfe3 | |||
b16c3798a4 | |||
4b33c42da7 | |||
961b3177d5 | |||
7dc85a624e | |||
bfd215542b | |||
d752275730 | |||
be7e389bb5 |
@ -2,6 +2,6 @@
|
||||
"extension": ["ts","js","cjs","mjs"],
|
||||
"require": ["ts-node/register", "tsconfig-paths/register"],
|
||||
"slow": 1000,
|
||||
"timeout": 30000,
|
||||
"timeout": 35000,
|
||||
"exit": true
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
v16.0.0
|
||||
v16.2.0
|
||||
|
@ -28,12 +28,7 @@ If your language is not listed in Crowdin, please open an issue.
|
||||
|
||||

|
||||
|
||||
## Internationalization (i18n)
|
||||
Misskey uses the Vue.js plugin [Vue I18n](https://github.com/kazupon/vue-i18n).
|
||||
Documentation of Vue I18n is available at http://kazupon.github.io/vue-i18n/introduction.html .
|
||||
|
||||
## Documentation
|
||||
* Documents for contributors are located in [`/docs`](/docs).
|
||||
* Documents for instance admins are located in [`/docs`](/docs).
|
||||
* Documents for end users are located in [`/src/docs`](/src/docs).
|
||||
|
||||
@ -41,8 +36,8 @@ Documentation of Vue I18n is available at http://kazupon.github.io/vue-i18n/intr
|
||||
* Test codes are located in [`/test`](/test).
|
||||
|
||||
## Continuous integration
|
||||
Misskey uses CircleCI for executing automated tests.
|
||||
Configuration files are located in [`/.circleci`](/.circleci).
|
||||
Misskey uses GitHub Actions for executing automated tests.
|
||||
Configuration files are located in [`/.github/workflows`](/.github/workflows).
|
||||
|
||||
## Adding MisskeyRoom items
|
||||
* Use English for material, object and texture names.
|
||||
|
4
COPYING
4
COPYING
@ -6,10 +6,6 @@ And is distributed under The GNU Affero General Public License Version 3, you sh
|
||||
|
||||
Misskey includes several third-party Open-Source softwares.
|
||||
|
||||
Unicode emoji regular expressions by Twitter, Inc.
|
||||
License: MIT
|
||||
https://github.com/twitter/twemoji-parser/blob/master/LICENSE.md
|
||||
|
||||
Emoji keywords for Unicode 11 and below by Mu-An Chiou
|
||||
License: MIT
|
||||
https://github.com/muan/emojilib/blob/master/LICENSE
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM node:16.0.0-alpine3.13 AS base
|
||||
FROM node:16.2.0-alpine3.13 AS base
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
|
@ -99,6 +99,11 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
||||
|
||||
To receive updates of this repo, follow [@repo@misskey.io](https://misskey.io/@repo) on fediverse.
|
||||
|
||||
Related projects
|
||||
----------------------------------------------------------------
|
||||
- [misskey.js](https://github.com/misskey-dev/misskey.js) - Misskey SDK for JavaScript
|
||||
- [mfm.js](https://github.com/misskey-dev/mfm.js) - MFM parser
|
||||
|
||||
:heart: Backers
|
||||
----------------------------------------------------------------
|
||||
<!-- PATREON_START -->
|
||||
|
9
SECURITY.md
Normal file
9
SECURITY.md
Normal file
@ -0,0 +1,9 @@
|
||||
# Reporting Security Issues
|
||||
|
||||
If you discover a security issue in Misskey, please report it by sending an
|
||||
email to [syuilotan@yahoo.co.jp](mailto:syuilotan@yahoo.co.jp).
|
||||
|
||||
This will allow us to assess the risk, and make a fix available before we add a
|
||||
bug report to the GitHub repository.
|
||||
|
||||
Thanks for helping make Misskey safe for everyone.
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 38 KiB |
Binary file not shown.
@ -4,7 +4,7 @@
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as gulp from 'gulp';
|
||||
import * as rimraf from 'rimraf';
|
||||
import rimraf from 'rimraf';
|
||||
const replace = require('gulp-replace');
|
||||
const terser = require('gulp-terser');
|
||||
const cssnano = require('gulp-cssnano');
|
||||
|
@ -259,8 +259,6 @@ monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "الصفحات"
|
||||
integration: "دمج"
|
||||
connectSerice: "أوصل"
|
||||
disconnectSerice: "قطع الاتصال"
|
||||
enableLocalTimeline: "تفعيل الخيط المحلي"
|
||||
enableGlobalTimeline: "تفعيل الخيط الزمني الشامل"
|
||||
disablingTimelinesInfo: "سيتمكن المسؤولون ومن تعديل دائمًا و من الوصول إلى جميع المخططات الزمنية ، حتى إذا لم يتم تمكينها."
|
||||
@ -387,7 +385,6 @@ updateRemoteUser: "تحديث المعلومات عن المستخدم البع
|
||||
deleteAllFiles: "حذف كافة الملفات"
|
||||
userSuspended: "تم تعليق هذا المستخدم."
|
||||
userSilenced: "تم إسكات هذا المستخدم."
|
||||
sidebar: "الشريط الجانبي"
|
||||
addItem: "إضافة عنصر"
|
||||
rooms: "الغرفة"
|
||||
relays: "المُرَحلات"
|
||||
@ -432,6 +429,7 @@ user: "المستخدمون"
|
||||
administration: "إدارة "
|
||||
expiration: "ينتهي استطلاع الرأي في"
|
||||
middle: "متوسط"
|
||||
global: "الشامل"
|
||||
_email:
|
||||
_follow:
|
||||
title: "يتابعك"
|
||||
@ -444,9 +442,7 @@ _reversi:
|
||||
total: "المجموع"
|
||||
_channel:
|
||||
featured: "المتداوَلة"
|
||||
_sidebar:
|
||||
full: "كامل"
|
||||
icon: "الصورة الرمزية"
|
||||
_menuDisplay:
|
||||
hide: "إخفاء"
|
||||
_theme:
|
||||
explore: "استكشف قوالب المظهر"
|
||||
|
@ -269,8 +269,6 @@ monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Stránky"
|
||||
integration: "Integrace"
|
||||
connectSerice: "Připojit"
|
||||
disconnectSerice: "Odpojit"
|
||||
enableLocalTimeline: "Povolit lokální čas"
|
||||
enableGlobalTimeline: "Povolit globální čas"
|
||||
registration: "Registrace"
|
||||
@ -392,7 +390,6 @@ script: "Skript"
|
||||
deleteAllFiles: "Smazat všechny soubory"
|
||||
deleteAllFilesConfirm: "Jste si jistí že chcete smazat všechny soubory?"
|
||||
userSuspended: "Tomuto uživateli byl pozastaven účet."
|
||||
sidebar: "Postranní panel"
|
||||
addItem: "Přidat položku"
|
||||
rooms: "Místnost"
|
||||
inboxUrl: "Inbox URL"
|
||||
@ -411,8 +408,6 @@ _mfm:
|
||||
search: "Vyhledávání"
|
||||
_reversi:
|
||||
total: "Celkem"
|
||||
_sidebar:
|
||||
icon: "Avatar"
|
||||
_theme:
|
||||
keys:
|
||||
mention: "Zmínění"
|
||||
|
@ -279,6 +279,7 @@ emptyDrive: "Drive ist leer"
|
||||
emptyFolder: "Der Ordner ist leer"
|
||||
unableToDelete: "Nicht löschbar"
|
||||
inputNewFileName: "Gib einen neuen Dateinamen ein"
|
||||
inputNewDescription: "Gib eine neue Beschreibung ein"
|
||||
inputNewFolderName: "Gib einen neuen Ordnernamen ein"
|
||||
circularReferenceFolder: "Der Zielordner ist ein Unterorder des Ordners, den du verschieben möchtest."
|
||||
hasChildFilesOrFolders: "Dieser Ordner kann nicht gelöscht werden, da er nicht leer ist."
|
||||
@ -310,8 +311,8 @@ monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Seiten"
|
||||
integration: "Integration"
|
||||
connectSerice: "Verbinden"
|
||||
disconnectSerice: "Trennen"
|
||||
connectService: "Verbinden"
|
||||
disconnectService: "Trennen"
|
||||
enableLocalTimeline: "Lokale Chronik aktivieren"
|
||||
enableGlobalTimeline: "Globale Chronik aktivieren"
|
||||
disablingTimelinesInfo: "Administratoren und Moderatoren haben immer Zugriff auf alle Chroniken, auch wenn diese deaktiviert sind."
|
||||
@ -325,6 +326,7 @@ driveCapacityPerRemoteAccount: "Drive-Kapazität pro Benutzer anderer Instanzen"
|
||||
inMb: "In Megabytes"
|
||||
iconUrl: "Icon-URL"
|
||||
bannerUrl: "Banner-URL"
|
||||
backgroundImageUrl: "Hintergrundbild-URL"
|
||||
basicInfo: "Basisdaten"
|
||||
pinnedUsers: "Angepinnte Benutzer"
|
||||
pinnedUsersDescription: "Gib einen Benutzernamen pro Zeile ein. Diese werden im \"Erkunden\" Tab angezeigt."
|
||||
@ -526,7 +528,7 @@ removeAllFollowing: "Allen gefolgten Benutzern entfolgen"
|
||||
removeAllFollowingDescription: "Allen Benutzerkonten von {host} entfolgen. Bitte führe dies durch, falls diese Instanz nicht mehr existiert."
|
||||
userSuspended: "Dieser Benutzer wurde gesperrt."
|
||||
userSilenced: "Dieser Benutzer wurde instanzweit stummgeschaltet."
|
||||
sidebar: "Seitenleiste"
|
||||
menu: "Menü"
|
||||
divider: "Trenner"
|
||||
addItem: "Element hinzufügen"
|
||||
rooms: "Raum"
|
||||
@ -546,6 +548,8 @@ disablePlayer: "Video-Player schließen"
|
||||
expandTweet: "Tweet ausklappen"
|
||||
themeEditor: "Farbthemen-Editor"
|
||||
description: "Beschreibung"
|
||||
describeFile: "Beschreibung hinzufügen"
|
||||
enterFileDescription: "Beschreibung eingeben"
|
||||
author: "Autor"
|
||||
leaveConfirm: "Es gibt unspeicherte Änderungen. Möchtest du diese verwerfen?"
|
||||
manage: "Verwaltung"
|
||||
@ -731,9 +735,11 @@ active: "Aktiv"
|
||||
offline: "Offline"
|
||||
notRecommended: "Nicht empfohlen"
|
||||
botProtection: "Bot-Schutz"
|
||||
instanceBlocking: "Blockierte Instanzen"
|
||||
selectAccount: "Benutzerkonto auswählen"
|
||||
enabled: "Aktiviert"
|
||||
disabled: "Deaktiviert"
|
||||
quickAction: "Schnellaktionen"
|
||||
user: "Benutzer"
|
||||
administration: "Verwaltung"
|
||||
accounts: "Benutzerkonten"
|
||||
@ -755,6 +761,10 @@ middle: "Mittel"
|
||||
low: "Niedrig"
|
||||
emailNotConfiguredWarning: "Keine Email-Adresse hinterlegt"
|
||||
ratio: "Verhältnis"
|
||||
customCss: "Benutzerdefiniertes CSS"
|
||||
customCssWarn: "Verwende diese Einstellung nur, wenn du weißt, was sie tut. Ungültige Eingaben können dazu führen, dass der Client nicht mehr normal funktioniert."
|
||||
global: "Global"
|
||||
squareAvatars: "Profilbilder quadratisch anzeigen"
|
||||
_ad:
|
||||
back: "Zurück"
|
||||
reduceFrequencyOfThisAd: "Diese Werbung weniger anzeigen"
|
||||
@ -904,9 +914,10 @@ _channel:
|
||||
following: "Gefolgt"
|
||||
usersCount: "{n} Teilnehmer"
|
||||
notesCount: "{n} Notizen"
|
||||
_sidebar:
|
||||
full: "Voll"
|
||||
icon: "Symbole"
|
||||
_menuDisplay:
|
||||
sideFull: "Horizontal"
|
||||
sideIcon: "Horizontal (Icons)"
|
||||
top: "Oben"
|
||||
hide: "Ausblenden"
|
||||
_wordMute:
|
||||
muteWords: "Wort stummschalten"
|
||||
|
@ -279,6 +279,7 @@ emptyDrive: "The drive is empty"
|
||||
emptyFolder: "This folder is empty"
|
||||
unableToDelete: "Unable to delete"
|
||||
inputNewFileName: "Enter a new filename"
|
||||
inputNewDescription: "Enter new caption"
|
||||
inputNewFolderName: "Enter a new folder name"
|
||||
circularReferenceFolder: "The destination folder is a subfolder of the folder you wish to move."
|
||||
hasChildFilesOrFolders: "Since this folder is not empty, it can not be deleted."
|
||||
@ -310,8 +311,8 @@ monthX: "{month}"
|
||||
yearX: "{year} /"
|
||||
pages: "Pages"
|
||||
integration: "Integration"
|
||||
connectSerice: "Connect"
|
||||
disconnectSerice: "Disconnect"
|
||||
connectService: "Connect"
|
||||
disconnectService: "Disconnect"
|
||||
enableLocalTimeline: "Enable local timeline"
|
||||
enableGlobalTimeline: "Enable global timeline"
|
||||
disablingTimelinesInfo: "Admins and Mods will always have access to all timelines, even if they are not enabled."
|
||||
@ -325,6 +326,7 @@ driveCapacityPerRemoteAccount: "Drive capacity per remote user"
|
||||
inMb: "In megabytes"
|
||||
iconUrl: "Icon URL"
|
||||
bannerUrl: "Banner image URL"
|
||||
backgroundImageUrl: "Background image URL"
|
||||
basicInfo: "Basic info"
|
||||
pinnedUsers: "Pinned user"
|
||||
pinnedUsersDescription: "List one username per line. Users listed here will be pinned under \"Explore\" tab."
|
||||
@ -526,7 +528,7 @@ removeAllFollowing: "Withhold All Followings"
|
||||
removeAllFollowingDescription: "Unfollow all accounts from {host}. Please run this if the instance no longer exists."
|
||||
userSuspended: "This user has been suspended."
|
||||
userSilenced: "This user has been silenced."
|
||||
sidebar: "Sidebar"
|
||||
menu: "Menu"
|
||||
divider: "Divider"
|
||||
addItem: "Add Item"
|
||||
rooms: "Room"
|
||||
@ -546,6 +548,8 @@ disablePlayer: "Close video player"
|
||||
expandTweet: "Expand tweet"
|
||||
themeEditor: "Theme editor"
|
||||
description: "Description"
|
||||
describeFile: "Add caption"
|
||||
enterFileDescription: "Enter caption"
|
||||
author: "Author"
|
||||
leaveConfirm: "There are unsaved changes. Do you want to discard them?"
|
||||
manage: "Management"
|
||||
@ -757,6 +761,10 @@ middle: "Medium"
|
||||
low: "Low"
|
||||
emailNotConfiguredWarning: "Email address not set"
|
||||
ratio: "Ratio"
|
||||
customCss: "Custom CSS"
|
||||
customCssWarn: "This setting should only be used if you know what it does. Entering improper values may cause the client to stop functioning normally."
|
||||
global: "Global"
|
||||
squareAvatars: "Display squared avatars"
|
||||
_ad:
|
||||
back: "Back"
|
||||
reduceFrequencyOfThisAd: "Show this ad less"
|
||||
@ -906,9 +914,10 @@ _channel:
|
||||
following: "Followed"
|
||||
usersCount: "{n} Participants"
|
||||
notesCount: "{n} Notes"
|
||||
_sidebar:
|
||||
full: "Full"
|
||||
icon: "Icons"
|
||||
_menuDisplay:
|
||||
sideFull: "Horizontal"
|
||||
sideIcon: "Horizontal (Icons)"
|
||||
top: "Top"
|
||||
hide: "Hide"
|
||||
_wordMute:
|
||||
muteWords: "Word to mute"
|
||||
|
337
locales/eo-UY.yml
Normal file
337
locales/eo-UY.yml
Normal file
@ -0,0 +1,337 @@
|
||||
---
|
||||
_lang_: "Esperanto"
|
||||
headlineMisskey: "Reto ligiĝas per notoj"
|
||||
introMisskey: "Bonvenon! Miskejo estas malferma kodaの分散型マイクロブログサービスです。\nBonvolu Krei「noto」、いま起こっていることを共有したり、あなたについて皆に発信しよう📡\n「 reaktigoj 」機能で、皆のnotojに素早く反応を追加することもできます👍\n新しい世界を探検しよう🚀"
|
||||
monthAndDay: "{day}-a/{month}"
|
||||
search: "Serĉi"
|
||||
notifications: "Sciigoj"
|
||||
username: "Uzantonomo"
|
||||
password: "Pasvorto"
|
||||
forgotPassword: "Ĉu vi forgesis pasvorton?"
|
||||
fetchingAsApObject: "Informpetado de fediverso..."
|
||||
ok: "Okej"
|
||||
gotIt: "Mi konprenas!"
|
||||
cancel: "Nuligi"
|
||||
enterUsername: "Entajpu uzantonomon"
|
||||
renotedBy: "Renotigojn faras {user}"
|
||||
noNotes: "Neniu noto!"
|
||||
noNotifications: "Vi ne havas sciigojn."
|
||||
instance: "Ekzemplo"
|
||||
settings: "Agordoj"
|
||||
basicSettings: "Ĝeneralaj agordoj"
|
||||
otherSettings: "Aliaj agordoj"
|
||||
openInWindow: "Malfermi en nova fenestro"
|
||||
profile: "Profilo"
|
||||
timeline: "Tempolinio"
|
||||
login: "Ensaluti"
|
||||
loggingIn: "Ensalutado..."
|
||||
logout: "Elsaluti"
|
||||
signup: "Krei konton"
|
||||
uploading: "Alŝutado..."
|
||||
save: "Konservi"
|
||||
users: "Uzanto"
|
||||
addUser: "Aldoni uzanton"
|
||||
favorite: "Preferi"
|
||||
favorites: "Preferataj"
|
||||
unfavorite: "Malpreferi"
|
||||
favorited: "Aldonita al preferatoj"
|
||||
alreadyFavorited: "Jame aldonita al preferatoj"
|
||||
cantFavorite: "Ne aldonita al preferatoj"
|
||||
pin: "Alpingli sur la profilo"
|
||||
unpin: "Depingli"
|
||||
copyContent: "Kopii enhavon"
|
||||
copyLink: "Kopii ligilon"
|
||||
delete: "Forviŝi"
|
||||
deleteAndEdit: "Forviŝi kaj redakti"
|
||||
deleteAndEditConfirm: "Ĉu vi certas, ke vi volas forviŝi la noton? La reaktigoj, renotigoj, kaj respondoj ankaŭ forigiĝos."
|
||||
addToList: "Aldoni al listo"
|
||||
sendMessage: "Sendi mesaĝon"
|
||||
copyUsername: "Kopii uzantonomon"
|
||||
searchUser: "Serĉi uzanton"
|
||||
reply: "Respondi"
|
||||
loadMore: "Vidu plu"
|
||||
showMore: "Vidi plu"
|
||||
youGotNewFollower: "Vi estas eksekvita."
|
||||
mention: "Mencioj"
|
||||
mentions: "Mencioj"
|
||||
directNotes: "Senperaj notoj"
|
||||
importAndExport: "Importaĵo / Eksportaĵo"
|
||||
import: "Importi"
|
||||
export: "Eksporti"
|
||||
files: "Dosieroj"
|
||||
download: "Elŝuti"
|
||||
driveFileDeleteConfirm: "Ĉu vi certas ke vi volas forviŝi la dosieron \"{name}\"? La notoj kun la aldonaĵo ankaŭ forviŝiĝos."
|
||||
unfollowConfirm: "Ĉu vi certas, ke vi volas ne plu sekvi {name}?"
|
||||
lists: "Listoj"
|
||||
noLists: "Neniu listo"
|
||||
note: "Elsendi noto"
|
||||
notes: "Notoj"
|
||||
following: "Sekvi"
|
||||
followers: "Sekvantoj"
|
||||
followsYou: "Sekvas vin"
|
||||
createList: "Kreii liston"
|
||||
error: "Eraro"
|
||||
somethingHappened: "Problemo okazis."
|
||||
retry: "Reprovi"
|
||||
enterListName: "Entajpu nomon de la listo"
|
||||
privacy: "Privateco"
|
||||
follow: "Sekvi"
|
||||
followRequest: "Peti eksekvi"
|
||||
followRequests: "Eksekvopetoj"
|
||||
unfollow: "Ne plu sekvi"
|
||||
renote: "Renotici"
|
||||
unrenote: "Forigi renotici"
|
||||
cantRenote: "Tiu noto estas renototebla."
|
||||
cantReRenote: "Renotigo ne estas renotigebla."
|
||||
quote: "Citi"
|
||||
pinnedNote: "Pinglita noto"
|
||||
pinned: "Alpingli sur la profilo"
|
||||
you: "Vi"
|
||||
clickToShow: "Klaku por malkaŝu"
|
||||
sensitive: "Enhavo ne estas deca por laborejo (NSFW)"
|
||||
add: "Aldoni"
|
||||
reaction: "Reagoj"
|
||||
enterFileName: "Entajpu dosiernomon"
|
||||
mute: "Silentigi"
|
||||
unmute: "Malsilentigi"
|
||||
block: "Bloki"
|
||||
unblock: "Malbloki"
|
||||
suspend: "Flostigi"
|
||||
unsuspend: "Fandi"
|
||||
blockConfirm: "Ĉu vi certas ke vi volas bloki la uzanton?"
|
||||
unblockConfirm: "Ĉu vi certas ke vi volas malbloki la uzanton?"
|
||||
suspendConfirm: "Ĉu vi certas ke vi volas frostigi la uzanton?"
|
||||
unsuspendConfirm: "Ĉu vi certas ke vi volas fandi la uzanton?"
|
||||
selectList: "Elekti liston"
|
||||
emojiUrl: "Retadreso de la emoĵio"
|
||||
flagAsBot: "Tiu uzanto estas roboto"
|
||||
flagAsCat: "Tiu uzanto estas kato"
|
||||
addAccount: "Aldoni konton"
|
||||
showOnRemote: "Vidi sur la transa ekzemplo"
|
||||
general: "Ĝenerala"
|
||||
searchWith: "Serĉi: {q}"
|
||||
youHaveNoLists: "Vi ne havas listojn."
|
||||
followConfirm: "Ĉu vi certas, ke vi volas sekvi {name}'n?"
|
||||
selectUser: "Elekti uzanton"
|
||||
annotation: "Komentarioj"
|
||||
federation: "Fediverso"
|
||||
instances: "Ekzemplo"
|
||||
blockThisInstance: "Bloki tiu ekzemplo"
|
||||
disk: "Diskilo"
|
||||
blockedInstances: "Blokitaj ekzemploj"
|
||||
muteAndBlock: "Silentitaj / Blokitaj"
|
||||
mutedUsers: "Silentigitaj uzantoj"
|
||||
blockedUsers: "Blokitaj uzantoj"
|
||||
noUsers: "Sen uzantoj"
|
||||
editProfile: "Redakti profilon"
|
||||
noteDeleteConfirm: "Ĉu vi certas ke vi volas forviŝi la noton?"
|
||||
pinLimitExceeded: "Vi ne plu povas alpingli noton."
|
||||
noCustomEmojis: "Neniu emoĵio"
|
||||
federating: "Konfederado"
|
||||
blocked: "Blokita"
|
||||
subscribing: "Abonita"
|
||||
notResponding: "Alvokato ne disponeblas"
|
||||
instanceFollowing: "Sekvi ekzemplon"
|
||||
instanceFollowers: "Sekvantoj de la ekzemplo"
|
||||
instanceUsers: "Uzantoj de la ekzemplo"
|
||||
changePassword: "Ŝanĝi pasvorton"
|
||||
currentPassword: "Aktuala pasvorto"
|
||||
newPassword: "Nova pasvorto"
|
||||
newPasswordRetype: "Reentajpu la novan pasvorton"
|
||||
attachFile: "Aldoni dosieron"
|
||||
more: "Plu!"
|
||||
usernameOrUserId: "Uzantonomo aŭ ID de uzanto"
|
||||
noSuchUser: "Neniuj uzantoj trovitaj."
|
||||
remove: "Forviŝi"
|
||||
removed: "Forviŝis"
|
||||
removeAreYouSure: "Ĉu vi certas ke vi volas forigi \"{x}\"?"
|
||||
deleteAreYouSure: "Ĉu vi certas ke vi volas forigi \"{x}\"?"
|
||||
messaging: "Babilejoj"
|
||||
upload: "Alŝuti"
|
||||
fromDrive: "De la diskilo"
|
||||
fromUrl: "De retadreso"
|
||||
uploadFromUrl: "Aldoni de retadreso"
|
||||
uploadFromUrlDescription: "Retadreso de la dosiero kiun vi volu alŝuti"
|
||||
games: "Ludoj sur Miskejo"
|
||||
messageRead: "Legita"
|
||||
startMessaging: "Komenci babiladon"
|
||||
tos: "Kondiĉoj de Uzado"
|
||||
start: "Komenciĝi"
|
||||
home: "Ĉefpaĝo"
|
||||
drive: "Diskilo"
|
||||
fileName: "Dosiernomo"
|
||||
selectFile: "Elekti dosieron"
|
||||
selectFiles: "Elekti dosieron"
|
||||
renameFile: "Renomigi dosieron"
|
||||
deleteFolder: "Forviŝi dosierujon"
|
||||
addFile: "Aldoni dosieron"
|
||||
emptyDrive: "La diskilo enhavas neniun."
|
||||
unableToDelete: "Ne forigebla"
|
||||
inputNewFileName: "Entajpu nova dosiernomon"
|
||||
hasChildFilesOrFolders: "La dosierujo estas neforviŝebla pro tio, ke ĝi enhavas dosieron."
|
||||
copyUrl: "Kopii retadreson"
|
||||
nsfw: "Enhavo ne estas deca por laborejo (NSFW)"
|
||||
instanceName: "Nomo de la ekzemplo"
|
||||
connectService: "Konekti"
|
||||
disconnectService: "Farkonektiĝi"
|
||||
driveCapacityPerLocalAccount: "Volumo po unu loka-uzanto"
|
||||
driveCapacityPerRemoteAccount: "Volumo po unu transa uzanto"
|
||||
pinnedUsers: "Alpinglita uzanto"
|
||||
pinnedNotes: "Pinglita noto"
|
||||
withFileAntenna: "Nur kun aldonaĵo"
|
||||
notesAndReplies: "Kun respondoj"
|
||||
withFiles: "Kun aldonaĵo"
|
||||
silenceConfirm: "Ĉu vi certas ke vi volas silentigi la uzanton?"
|
||||
unsilenceConfirm: "Ĉu vi certas ke vi volas malsilentigi la uzanton?"
|
||||
userList: "Listoj"
|
||||
aboutMisskey: "Pri Miskejo"
|
||||
passwordLessLogin: "Ensaluti sen pasvorto"
|
||||
resetPassword: "Restarigi pasvorton"
|
||||
newPasswordIs: "La nova pasvorto estas {password}."
|
||||
inputMessageHere: "Entajpu masaĝo tie ĉi"
|
||||
noteOf: "Noto de {user}"
|
||||
newMessageExists: "Vi ricevis novan mesaĝon."
|
||||
onlyOneFileCanBeAttached: "Vi povas aldoni nur unu dosieron po unu mesaĝo."
|
||||
uiLanguage: "Lingvo de la interfaco"
|
||||
noFollowRequests: "Vi ne havas eksekvopetojn."
|
||||
local: "Loka"
|
||||
remote: "Transa"
|
||||
hideThisNote: "Kaŝi tiun noton"
|
||||
deleteAllFiles: "Forvisi ĉiujn dosierojn"
|
||||
deleteAllFilesConfirm: "Ĉu vi certas, ke vi volas forviŝi ĉiujn viajn dosierojn?"
|
||||
invisibleNote: "Malpublika noto"
|
||||
emailServer: "Retpoŝta servilo"
|
||||
email: "Retpoŝto"
|
||||
emailAddress: "Retpoŝtadreso"
|
||||
smtpUser: "Uzantonomo"
|
||||
smtpPass: "Pasvorto"
|
||||
userSaysSomething: "{name} parolis ion"
|
||||
database: "Datumbazo"
|
||||
channel: "Kanalo"
|
||||
fileIdOrUrl: "Dosirero ID aŭ retadreso"
|
||||
send: "Sendi"
|
||||
i18nInfo: "Tradukojn de Misskey en diversaj lingvoj faras volontuloj. Vi povus kunlabori en tradukado sur {link}, se vi volus."
|
||||
driveFilesCount: "Numero de dosieroj en la diskilo"
|
||||
onlineUsersCount: "{n} uzanto(j) estas surkonektita"
|
||||
nUsers: "{n} uzanto(j)"
|
||||
emailNotification: "Sciigoj per retpoŝto"
|
||||
publish: "Publikigi"
|
||||
inChannelSearch: "Serĉi en kanalo"
|
||||
typingUsers: "{users} estas entajpanta(j)..."
|
||||
online: "Surkonektita"
|
||||
offline: "Forkonektita"
|
||||
instanceBlocking: "Ekzempla blokado"
|
||||
user: "Uzanto"
|
||||
_gallery:
|
||||
liked: "Ŝatitaj notoj"
|
||||
_email:
|
||||
_follow:
|
||||
title: "Vi estas eksekvita."
|
||||
_receiveFollowRequest:
|
||||
title: "Vi ricevis eksekvopeton."
|
||||
_aboutMisskey:
|
||||
about: "Misskey estas malferma koda programo evoluigata far syuilo ekde la 2014."
|
||||
source: "Fontkodo"
|
||||
translation: "Traduki Misskey'on"
|
||||
_mfm:
|
||||
mention: "Mencioj"
|
||||
url: "Retadreso"
|
||||
blockCode: "Kodo (Ujo)"
|
||||
blockMath: "Formulo (Ujo)"
|
||||
quote: "Citi"
|
||||
search: "Serĉi"
|
||||
_instanceTicker:
|
||||
none: "Ne montri"
|
||||
remote: "Montri al transaj uzantoj"
|
||||
_channel:
|
||||
create: "Krei kanalon"
|
||||
edit: "Redakti kanalon"
|
||||
following: "Sekvaton"
|
||||
_theme:
|
||||
keys:
|
||||
mention: "Mencioj"
|
||||
renote: "Renotici"
|
||||
_sfx:
|
||||
note: "Nova noto"
|
||||
notification: "Sciigoj"
|
||||
chat: "Babilejoj"
|
||||
channel: "Kanala sciigoj"
|
||||
_tutorial:
|
||||
title: "Uzado de Miskejo"
|
||||
_permissions:
|
||||
"read:blocks": "Vidi la listo de la uzantoj kiun vi blokis."
|
||||
"read:drive": "Vidi dosierojn en la diskilo"
|
||||
"read:channels": "Legi kanalon"
|
||||
_widgets:
|
||||
notifications: "Sciigoj"
|
||||
timeline: "Tempolinio"
|
||||
federation: "Fediverso"
|
||||
onlineUsers: "Surkonektita uzanto"
|
||||
_cw:
|
||||
show: "Vidu plu"
|
||||
files: "{count} dosiero(j)"
|
||||
_visibility:
|
||||
publicDescription: "Via noto aperiĝos sur konfederacia tempolinio"
|
||||
home: "Ĉefpaĝo"
|
||||
homeDescription: "Elsendi nur sur hejma tempolinio"
|
||||
followers: "Sekvantoj"
|
||||
followersDescription: "Elsendi nur al sekvantoj de mi"
|
||||
localOnly: "Nur loka"
|
||||
localOnlyDescription: "Nelegabla al transaj uzantoj"
|
||||
_postForm:
|
||||
channelPlaceholder: "Elsendi sur la kanalo"
|
||||
_profile:
|
||||
username: "Uzantonomo"
|
||||
_exportOrImport:
|
||||
followingList: "Sekvi"
|
||||
muteList: "Silentigi"
|
||||
blockingList: "Blokado"
|
||||
userLists: "Listoj"
|
||||
_timelines:
|
||||
home: "Hejmo"
|
||||
local: "Loka"
|
||||
social: "Hejmo kaj loka"
|
||||
_rooms:
|
||||
_furnitures:
|
||||
server: "Servilo"
|
||||
_pages:
|
||||
content: "Blokado de paĝo"
|
||||
url: "Retadreso de la paĝo"
|
||||
chooseBlock: "Aldoni blokado"
|
||||
script:
|
||||
categories:
|
||||
list: "Listoj"
|
||||
blocks:
|
||||
_join:
|
||||
arg1: "Listoj"
|
||||
_randomPick:
|
||||
arg1: "Listoj"
|
||||
_dailyRandomPick:
|
||||
arg1: "Listoj"
|
||||
_seedRandomPick:
|
||||
arg2: "Listoj"
|
||||
pick: "Elekti de la listo"
|
||||
_pick:
|
||||
arg1: "Listoj"
|
||||
_listLen:
|
||||
arg1: "Listoj"
|
||||
types:
|
||||
array: "Listoj"
|
||||
_notification:
|
||||
fileUploaded: "La dosiero sukcese alŝutiĝis."
|
||||
youWereFollowed: "Vi estas eksekvita."
|
||||
youReceivedFollowRequest: "Vi ricevis eksekvopeton."
|
||||
yourFollowRequestAccepted: "Via eksekvopeto estas akceptita."
|
||||
_types:
|
||||
follow: "Sekvi"
|
||||
mention: "Mencioj"
|
||||
renote: "Renotici"
|
||||
quote: "Citi"
|
||||
reaction: "Reagoj"
|
||||
receiveFollowRequest: "Eksekvopeto ricevita"
|
||||
_deck:
|
||||
_columns:
|
||||
notifications: "Sciigoj"
|
||||
tl: "Tempolinio"
|
||||
list: "Listoj"
|
||||
mentions: "Mencioj"
|
@ -309,8 +309,6 @@ monthX: "Mes {month}"
|
||||
yearX: "Año {year}"
|
||||
pages: "Páginas"
|
||||
integration: "Integración"
|
||||
connectSerice: "Conectarse"
|
||||
disconnectSerice: "Desconectarse"
|
||||
enableLocalTimeline: "Habilitar linea de tiempo local"
|
||||
enableGlobalTimeline: "Habilitar linea de tiempo global"
|
||||
disablingTimelinesInfo: "Aunque se desactiven estas lineas de tiempo, por conveniencia el administrador y los moderadores pueden seguir usándolos"
|
||||
@ -525,7 +523,6 @@ removeAllFollowing: "Retener todos los siguientes"
|
||||
removeAllFollowingDescription: "Cancelar todos los siguientes del servidor {host}. Ejecutar en caso de que esta instancia haya dejado de existir"
|
||||
userSuspended: "Este usuario ha sido suspendido."
|
||||
userSilenced: "Este usuario ha sido silenciado."
|
||||
sidebar: "Barra lateral"
|
||||
divider: "Divisor"
|
||||
addItem: "Agregar elemento"
|
||||
rooms: "Cuartos"
|
||||
@ -667,6 +664,7 @@ user: "Usuarios"
|
||||
administration: "Administrar"
|
||||
expiration: "Termina el"
|
||||
middle: "Mediano"
|
||||
global: "Global"
|
||||
_ad:
|
||||
back: "Deseleccionar"
|
||||
_gallery:
|
||||
@ -746,9 +744,7 @@ _channel:
|
||||
following: "Siguiendo"
|
||||
usersCount: "{n} participantes"
|
||||
notesCount: "{n} notas"
|
||||
_sidebar:
|
||||
full: "Completo"
|
||||
icon: "Avatar"
|
||||
_menuDisplay:
|
||||
hide: "Ocultar"
|
||||
_wordMute:
|
||||
muteWords: "Palabras que silenciar"
|
||||
|
@ -279,6 +279,7 @@ emptyDrive: "Le Drive est vide"
|
||||
emptyFolder: "Le dossier est vide"
|
||||
unableToDelete: "Suppression impossible"
|
||||
inputNewFileName: "Entrez un nouveau nom de fichier"
|
||||
inputNewDescription: "Veuillez entrer une nouvelle description"
|
||||
inputNewFolderName: "Entrez un nouveau nom de dossier"
|
||||
circularReferenceFolder: "Le dossier de destination est un sous-dossier du dossier que vous souhaitez déplacer."
|
||||
hasChildFilesOrFolders: "Impossible de supprimer ce dossier car il n'est pas vide."
|
||||
@ -310,8 +311,8 @@ monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Pages"
|
||||
integration: "Intégrations"
|
||||
connectSerice: "Connecter"
|
||||
disconnectSerice: "Déconnecter"
|
||||
connectService: "Connexion"
|
||||
disconnectService: "Déconnexion"
|
||||
enableLocalTimeline: "Activer le fil local"
|
||||
enableGlobalTimeline: "Activer le fil global"
|
||||
disablingTimelinesInfo: "Même si vous désactivez ces fils, les administrateur·rice·s et les modérateur·rice·s pourront toujours y accéder."
|
||||
@ -325,6 +326,7 @@ driveCapacityPerRemoteAccount: "Volume du Drive par utilisateur distant"
|
||||
inMb: "en mégaoctets"
|
||||
iconUrl: "URL de l'icône"
|
||||
bannerUrl: "URL de l’image de la bannière"
|
||||
backgroundImageUrl: "URL de l'image d'arrière-plan"
|
||||
basicInfo: "Informations basiques"
|
||||
pinnedUsers: "Utilisateur·rice épinglé·e"
|
||||
pinnedUsersDescription: "Listez les utilisateur·rice·s que vous souhaitez voir épinglé·e·s sur la page \"Découvrir\", un·e par ligne."
|
||||
@ -526,7 +528,6 @@ removeAllFollowing: "Retenir tous les abonnements"
|
||||
removeAllFollowingDescription: "Se désabonner de tous les comptes de {host}. Veuillez lancer cette action uniquement si l’instance n’existe plus."
|
||||
userSuspended: "Cet·te utilisateur·rice a été suspendu·e."
|
||||
userSilenced: "Cette utilisateur·trice a été mis·e en sourdine."
|
||||
sidebar: "Barre latérale"
|
||||
divider: "Séparateur"
|
||||
addItem: "Ajouter un élément"
|
||||
rooms: "Chambre"
|
||||
@ -546,6 +547,8 @@ disablePlayer: "Fermer le lecteur vidéo"
|
||||
expandTweet: "Étendre le tweet"
|
||||
themeEditor: "Éditeur de thèmes"
|
||||
description: "Description"
|
||||
describeFile: "Ajouter une description d'image"
|
||||
enterFileDescription: "Saisissez une description"
|
||||
author: "Auteur·rice"
|
||||
leaveConfirm: "Vous avez des modifications non-sauvegardées. Voulez-vous les ignorer ?"
|
||||
manage: "Gestion"
|
||||
@ -757,6 +760,7 @@ middle: "Moyen"
|
||||
low: "Basse"
|
||||
emailNotConfiguredWarning: "Vous n'avez pas configuré d'adresse e-mail."
|
||||
ratio: "Ratio"
|
||||
global: "Global"
|
||||
_ad:
|
||||
back: "Retour"
|
||||
reduceFrequencyOfThisAd: "Voir cette publicité moins souvent"
|
||||
@ -906,9 +910,7 @@ _channel:
|
||||
following: "Abonné·e"
|
||||
usersCount: "{n} Participant·e·s"
|
||||
notesCount: "{n} Notes"
|
||||
_sidebar:
|
||||
full: "Complet"
|
||||
icon: "Icônes"
|
||||
_menuDisplay:
|
||||
hide: "Masquer"
|
||||
_wordMute:
|
||||
muteWords: "Mots à filtrer"
|
||||
|
1440
locales/id-ID.yml
1440
locales/id-ID.yml
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,7 @@ const languages = [
|
||||
'en-US',
|
||||
'es-ES',
|
||||
'fr-FR',
|
||||
'id-ID',
|
||||
'ja-JP',
|
||||
'ja-KS',
|
||||
'kab-KAB',
|
||||
|
@ -274,6 +274,7 @@ emptyDrive: "Il Drive è vuoto"
|
||||
emptyFolder: "La cartella è vuota"
|
||||
unableToDelete: "Eliminazione impossibile"
|
||||
inputNewFileName: "Inserisci nome del nuovo file"
|
||||
inputNewDescription: "Inserisci una nuova descrizione"
|
||||
inputNewFolderName: "Inserisci nome della nuova cartella"
|
||||
circularReferenceFolder: "La cartella di destinazione è una sottocartella della cartella che vuoi spostare."
|
||||
hasChildFilesOrFolders: "Impossibile eliminare la cartella perché non è vuota"
|
||||
@ -305,8 +306,8 @@ monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Pagine"
|
||||
integration: "App collegate"
|
||||
connectSerice: "Connetti"
|
||||
disconnectSerice: "Disconnetti"
|
||||
connectService: "Connessione"
|
||||
disconnectService: "Disconnessione "
|
||||
enableLocalTimeline: "Abilita Timeline locale"
|
||||
enableGlobalTimeline: "Abilita Timeline federata"
|
||||
disablingTimelinesInfo: "Anche se disabiliti queste timeline, gli amministratori e i moderatori potranno sempre accederci."
|
||||
@ -513,7 +514,6 @@ removeAllFollowing: "Cancella tutti i follows"
|
||||
removeAllFollowingDescription: "Cancella tutti i follows del server {host}. Per favore, esegui se, ad esempio, l'istanza non esiste più."
|
||||
userSuspended: "L'utente è sospes@."
|
||||
userSilenced: "L'utente è silenziat@."
|
||||
sidebar: "Barra laterale"
|
||||
divider: "Linea di separazione"
|
||||
addItem: "Aggiungi elemento"
|
||||
rooms: "Camera"
|
||||
@ -533,6 +533,8 @@ disablePlayer: "Chiudi lettore video"
|
||||
expandTweet: "Espandi tweet"
|
||||
themeEditor: "Editor di temi"
|
||||
description: "Descrizione"
|
||||
describeFile: "Aggiungi una descrizione d'immagine"
|
||||
enterFileDescription: "Inserisci descrizione"
|
||||
author: "Autore"
|
||||
leaveConfirm: "Ci sono delle modifiche ancora non salvate. Vuoi cancellarle?"
|
||||
manage: "Gestione"
|
||||
@ -738,6 +740,7 @@ middle: "Media"
|
||||
low: "Bassa"
|
||||
emailNotConfiguredWarning: "Non hai impostato nessun indirizzo e-mail."
|
||||
ratio: "Rapporto"
|
||||
global: "Federata"
|
||||
_ad:
|
||||
back: "Indietro"
|
||||
reduceFrequencyOfThisAd: "Visualizza questa pubblicità meno spesso"
|
||||
@ -822,9 +825,7 @@ _channel:
|
||||
following: "Seguiti"
|
||||
usersCount: "{n} partecipanti"
|
||||
notesCount: "{n} note"
|
||||
_sidebar:
|
||||
full: "Intera"
|
||||
icon: "Icone"
|
||||
_menuDisplay:
|
||||
hide: "Nascondere"
|
||||
_wordMute:
|
||||
muteWords: "Parole da filtrare"
|
||||
|
@ -279,6 +279,7 @@ emptyDrive: "ドライブは空です"
|
||||
emptyFolder: "フォルダーは空です"
|
||||
unableToDelete: "削除できません"
|
||||
inputNewFileName: "新しいファイル名を入力してください"
|
||||
inputNewDescription: "新しいキャプションを入力してください"
|
||||
inputNewFolderName: "新しいフォルダ名を入力してください"
|
||||
circularReferenceFolder: "移動先のフォルダーは、移動するフォルダーのサブフォルダーです。"
|
||||
hasChildFilesOrFolders: "このフォルダは空でないため、削除できません。"
|
||||
@ -310,8 +311,8 @@ monthX: "{month}月"
|
||||
yearX: "{year}年"
|
||||
pages: "ページ"
|
||||
integration: "連携"
|
||||
connectSerice: "接続する"
|
||||
disconnectSerice: "切断する"
|
||||
connectService: "接続する"
|
||||
disconnectService: "切断する"
|
||||
enableLocalTimeline: "ローカルタイムラインを有効にする"
|
||||
enableGlobalTimeline: "グローバルタイムラインを有効にする"
|
||||
disablingTimelinesInfo: "これらのタイムラインを無効化しても、利便性のため管理者およびモデレーターは引き続き利用することができます。"
|
||||
@ -325,6 +326,7 @@ driveCapacityPerRemoteAccount: "リモートユーザーひとりあたりのド
|
||||
inMb: "メガバイト単位"
|
||||
iconUrl: "アイコン画像のURL (faviconなど)"
|
||||
bannerUrl: "バナー画像のURL"
|
||||
backgroundImageUrl: "背景画像のURL"
|
||||
basicInfo: "基本情報"
|
||||
pinnedUsers: "ピン留めユーザー"
|
||||
pinnedUsersDescription: "「みつける」ページなどにピン留めしたいユーザーを改行で区切って記述します。"
|
||||
@ -526,7 +528,7 @@ removeAllFollowing: "フォローを全解除"
|
||||
removeAllFollowingDescription: "{host}からのフォローをすべて解除します。そのインスタンスがもう存在しなくなった場合などに実行してください。"
|
||||
userSuspended: "このユーザーは凍結されています。"
|
||||
userSilenced: "このユーザーはサイレンスされています。"
|
||||
sidebar: "サイドバー"
|
||||
menu: "メニュー"
|
||||
divider: "分割線"
|
||||
addItem: "項目を追加"
|
||||
rooms: "ルーム"
|
||||
@ -546,6 +548,8 @@ disablePlayer: "プレイヤーを閉じる"
|
||||
expandTweet: "ツイートを展開する"
|
||||
themeEditor: "テーマエディター"
|
||||
description: "説明"
|
||||
describeFile: "キャプションを付ける"
|
||||
enterFileDescription: "キャプションを入力"
|
||||
author: "作者"
|
||||
leaveConfirm: "未保存の変更があります。破棄しますか?"
|
||||
manage: "管理"
|
||||
@ -757,6 +761,10 @@ middle: "中"
|
||||
low: "低"
|
||||
emailNotConfiguredWarning: "メールアドレスの設定がされていません。"
|
||||
ratio: "比率"
|
||||
customCss: "カスタムCSS"
|
||||
customCssWarn: "この設定は必ず知識のある方が行ってください。不適切な設定を行うとクライアントが正常に使用できなくなる恐れがあります。"
|
||||
global: "グローバル"
|
||||
squareAvatars: "アイコンを四角形で表示"
|
||||
|
||||
_ad:
|
||||
back: "戻る"
|
||||
@ -920,9 +928,10 @@ _channel:
|
||||
usersCount: "{n}人が参加中"
|
||||
notesCount: "{n}投稿があります"
|
||||
|
||||
_sidebar:
|
||||
full: "フル"
|
||||
icon: "アイコン"
|
||||
_menuDisplay:
|
||||
sideFull: "横"
|
||||
sideIcon: "横(アイコン)"
|
||||
top: "上部"
|
||||
hide: "隠す"
|
||||
|
||||
_wordMute:
|
||||
|
@ -308,8 +308,6 @@ monthX: "{month}月"
|
||||
yearX: "{year}年"
|
||||
pages: "ページ"
|
||||
integration: "連携"
|
||||
connectSerice: "つなぐ"
|
||||
disconnectSerice: "切ってまう"
|
||||
enableLocalTimeline: "ローカルタイムラインを使えるようにする"
|
||||
enableGlobalTimeline: "グローバルタイムラインを使えるようにする"
|
||||
disablingTimelinesInfo: "ここらへんのタイムラインを使えんようにしてしもても、管理者とモデレーターは使えるままになってるで、そうやなかったら不便やからな。"
|
||||
@ -513,7 +511,6 @@ removeAllFollowing: "フォローを全解除"
|
||||
removeAllFollowingDescription: "{host}からのフォローをすべて解除するで。そのインスタンスが消えて無くなった時とかには便利な機能やで。"
|
||||
userSuspended: "このユーザーは...凍結されとる。"
|
||||
userSilenced: "このユーザーは...サイレンスされとる。"
|
||||
sidebar: "サイドバー"
|
||||
divider: "分割線"
|
||||
rooms: "ルーム"
|
||||
relays: "リレー"
|
||||
@ -649,6 +646,7 @@ memo: "メモ"
|
||||
high: "高い"
|
||||
middle: "中"
|
||||
low: "低い"
|
||||
global: "グローバル"
|
||||
_ad:
|
||||
back: "戻る"
|
||||
_gallery:
|
||||
@ -733,9 +731,7 @@ _channel:
|
||||
removeBanner: "バナーを削除"
|
||||
featured: "トレンド"
|
||||
notesCount: "{n}こ投稿があるで"
|
||||
_sidebar:
|
||||
full: "フル"
|
||||
icon: "アイコン"
|
||||
_menuDisplay:
|
||||
hide: "隠す"
|
||||
_wordMute:
|
||||
soft: "ソフト"
|
||||
|
1
locales/jbo-EN.yml
Normal file
1
locales/jbo-EN.yml
Normal file
@ -0,0 +1 @@
|
||||
---
|
@ -279,6 +279,7 @@ emptyDrive: "드라이브가 비어 있습니다"
|
||||
emptyFolder: "폴더가 비어 있습니다"
|
||||
unableToDelete: "삭제할 수 없습니다"
|
||||
inputNewFileName: "바꿀 파일명을 입력해 주세요"
|
||||
inputNewDescription: "새 캡션을 입력해 주세요"
|
||||
inputNewFolderName: "바꿀 폴더명을 입력해 주세요"
|
||||
circularReferenceFolder: "지정한 폴더가 이동할 폴더의 하위 폴더입니다."
|
||||
hasChildFilesOrFolders: "이 폴더는 비어있지 않기 때문에 삭제할 수 없습니다."
|
||||
@ -310,8 +311,8 @@ monthX: "{month}월"
|
||||
yearX: "{year}년"
|
||||
pages: "페이지"
|
||||
integration: "연동"
|
||||
connectSerice: "접속"
|
||||
disconnectSerice: "연결 끊기"
|
||||
connectService: "계정 연동"
|
||||
disconnectService: "계정 연동 해제"
|
||||
enableLocalTimeline: "로컬 타임라인 활성화"
|
||||
enableGlobalTimeline: "글로벌 타임라인 활성화"
|
||||
disablingTimelinesInfo: "특정 타임라인을 비활성화하더라도 관리자 및 모더레이터는 계속 사용할 수 있습니다."
|
||||
@ -325,6 +326,7 @@ driveCapacityPerRemoteAccount: "리모트 유저 한 명당 드라이브 용량"
|
||||
inMb: "메가바이트 단위"
|
||||
iconUrl: "아이콘 URL"
|
||||
bannerUrl: "배너 이미지 URL"
|
||||
backgroundImageUrl: "배경 이미지 URL"
|
||||
basicInfo: "기본 정보"
|
||||
pinnedUsers: "고정된 유저"
|
||||
pinnedUsersDescription: "\"발견하기\" 페이지 등에 고정하고 싶은 유저를 한 줄에 한 명씩 적습니다."
|
||||
@ -526,7 +528,6 @@ removeAllFollowing: "모든 팔로잉 해제"
|
||||
removeAllFollowingDescription: "{host}(으)로부터 모든 팔로잉을 해제합니다. 해당 인스턴스가 더 이상 존재하지 않게 된 경우 등에 실행해 주세요."
|
||||
userSuspended: "이 계정은 정지된 상태입니다."
|
||||
userSilenced: "이 계정은 사일런스된 상태입니다."
|
||||
sidebar: "사이드바"
|
||||
divider: "구분선"
|
||||
addItem: "항목 추가"
|
||||
rooms: "방"
|
||||
@ -546,6 +547,8 @@ disablePlayer: "플레이어 닫기"
|
||||
expandTweet: "트윗 확장하기"
|
||||
themeEditor: "테마 에디터"
|
||||
description: "설명"
|
||||
describeFile: "캡션 추가"
|
||||
enterFileDescription: "캡션 입력"
|
||||
author: "작성자"
|
||||
leaveConfirm: "저장하지 않은 변경사항이 있습니다. 취소하시겠습니까?"
|
||||
manage: "관리"
|
||||
@ -757,6 +760,7 @@ middle: "보통"
|
||||
low: "낮음"
|
||||
emailNotConfiguredWarning: "메일 주소가 설정되어 있지 않습니다."
|
||||
ratio: "비율"
|
||||
global: "글로벌"
|
||||
_ad:
|
||||
back: "뒤로"
|
||||
reduceFrequencyOfThisAd: "이 광고의 표시 빈도 낮추기"
|
||||
@ -906,9 +910,7 @@ _channel:
|
||||
following: "팔로잉"
|
||||
usersCount: "{n}명 참여 중"
|
||||
notesCount: "{n}노트"
|
||||
_sidebar:
|
||||
full: "전체"
|
||||
icon: "아이콘"
|
||||
_menuDisplay:
|
||||
hide: "숨기기"
|
||||
_wordMute:
|
||||
muteWords: "뮤트할 단어"
|
||||
|
@ -1,2 +1,3 @@
|
||||
---
|
||||
_lang_: "Nederlands"
|
||||
headlineMisskey: "Netwerk verbonden door notities"
|
||||
|
@ -7,6 +7,7 @@ search: "Szukaj"
|
||||
notifications: "Powiadomienia"
|
||||
username: "Nazwa użytkownika"
|
||||
password: "Hasło"
|
||||
forgotPassword: "Nie pamiętam hasła"
|
||||
fetchingAsApObject: "Pobieranie z Fediwersum…"
|
||||
ok: "OK"
|
||||
gotIt: "Rozumiem!"
|
||||
@ -65,6 +66,7 @@ download: "Pobierz"
|
||||
driveFileDeleteConfirm: "Czy chcesz usunąć plik \"{name}\"? Zniknie również notatka, do której dołączony jest ten plik."
|
||||
unfollowConfirm: "Czy na pewno chcesz przestać obserwować {name}?"
|
||||
exportRequested: "Zażądałeś eksportu. Może to zająć trochę czasu. Po zakończeniu eksportu zostanie on dodany do Twoich \"dysków\"."
|
||||
importRequested: "Zażądano importu. Może to zająć chwilę."
|
||||
lists: "Listy"
|
||||
noLists: "Nie masz żadnych list"
|
||||
note: "Utwórz wpis"
|
||||
@ -133,9 +135,11 @@ settingGuide: "Proponowana konfiguracja"
|
||||
cacheRemoteFiles: "Przechowuj zdalne pliki w pamięci podręcznej"
|
||||
cacheRemoteFilesDescription: "Gdy ta opcja jest wyłączona, zdalne pliki są ładowane bezpośrednio ze zdalnych instancji. Wyłączenie the opcji zmniejszy użycie powierzchni dyskowej, ale zwiększy transfer, ponieważ miniaturki nie będą generowane."
|
||||
flagAsBot: "To konto jest botem"
|
||||
flagAsBotDescription: "Jeżeli ten kanał jest kontrolowany przez jakiś program, ustaw tę opcję. Jeżeli włączona, będzie działać jako flaga informująca innych programistów, aby zapobiegać nieskończonej interakcji z różnymi botami i dostosowywać wewnętrzne systemy Misskey, traktując konto jako bota."
|
||||
flagAsCat: "To konto jest kotem"
|
||||
flagAsCatDescription: "Przełącz tę opcję, aby konto było oznaczone jako kot."
|
||||
autoAcceptFollowed: "Automatycznie przyjmuj prośby o możliwość obserwacji od użytkowników, których obserwujesz"
|
||||
addAccount: "Dodaj konto"
|
||||
loginFailed: "Nie udało się zalogować"
|
||||
showOnRemote: "Zobacz na zdalnej instancji"
|
||||
general: "Ogólne"
|
||||
@ -179,6 +183,7 @@ clearQueueConfirmTitle: "Czy na pewno chcesz wyczyścić kolejkę?"
|
||||
clearCachedFiles: "Wyczyść pamięć podręczną"
|
||||
clearCachedFilesConfirm: "Czy na pewno chcesz usunąć wszystkie zdalne pliki z pamięci podręcznej?"
|
||||
blockedInstances: "Zablokowane instancje"
|
||||
blockedInstancesDescription: "Wypisz nazwy hostów instancji, które powinny zostać zablokowane. Wypisane instancje nie będą mogły dłużej komunikować się z tą instancją."
|
||||
muteAndBlock: "Wycisz / Zablokuj"
|
||||
mutedUsers: "Wyciszeni użytkownicy"
|
||||
blockedUsers: "Zablokowani użytkownicy"
|
||||
@ -271,6 +276,7 @@ emptyDrive: "Dysk jest pusty"
|
||||
emptyFolder: "Ten katalog jest pusty"
|
||||
unableToDelete: "Nie można usunąć"
|
||||
inputNewFileName: "Wprowadź nową nazwę pliku"
|
||||
inputNewDescription: "Proszę wpisać nowy napis"
|
||||
inputNewFolderName: "Wprowadź nową nazwę katalogu"
|
||||
circularReferenceFolder: "Katalog docelowy jest podkatalogiem katalogu, który chcesz przenieść."
|
||||
hasChildFilesOrFolders: "Ponieważ ten katalog nie jest pusty, nie może być usunięty."
|
||||
@ -291,16 +297,17 @@ reject: "Odrzuć"
|
||||
normal: "Normalny"
|
||||
instanceName: "Nazwa instancji"
|
||||
instanceDescription: "Opis instancji"
|
||||
maintainerName: "Administrator"
|
||||
maintainerEmail: "E-mail administratora"
|
||||
tosUrl: "Adres URL regulaminu"
|
||||
thisYear: "Rok"
|
||||
thisMonth: "Miesiąc"
|
||||
today: "Dziś"
|
||||
dayX: "{day}"
|
||||
monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Strony"
|
||||
integration: "Integracja"
|
||||
connectSerice: "Połącz"
|
||||
disconnectSerice: "Rozłącz"
|
||||
enableLocalTimeline: "Włącz lokalną oś czasu"
|
||||
enableGlobalTimeline: "Włącz globalną oś czasu"
|
||||
disablingTimelinesInfo: "Administratorzy i moderatorzy będą zawsze mieć dostęp do wszystkich osi czasu, nawet gdy są one wyłączone."
|
||||
@ -332,6 +339,7 @@ manageAntennas: "Zarządzaj Antenami"
|
||||
name: "Nazwa"
|
||||
antennaSource: "Źródło Anteny"
|
||||
antennaExcludeKeywords: "Wykluczone słowa kluczowe"
|
||||
notifyAntenna: "Powiadamiaj o nowych wpisach"
|
||||
withFileAntenna: "Filtruj tylko wpisy z załączonym plikiem"
|
||||
enableServiceworker: "Włącz ServiceWorker"
|
||||
antennaUsersDescription: "Wypisz po jednej nazwie użytkownika w linii"
|
||||
@ -358,6 +366,7 @@ administrator: "Admin"
|
||||
token: "Token"
|
||||
twoStepAuthentication: "Uwierzytelnianie dwuskładnikowe"
|
||||
moderator: "Moderator"
|
||||
nUsersMentioned: "{n} wspomnianych użytkowników"
|
||||
securityKey: "Klucz bezpieczeństwa"
|
||||
securityKeyName: "Nazwa klucza"
|
||||
registerSecurityKey: "Zarejestruj klucz bezpieczeństwa"
|
||||
@ -397,6 +406,7 @@ retype: "Wprowadź ponownie"
|
||||
noteOf: "Wpisy {user}"
|
||||
inviteToGroup: "Zaproś do grupy"
|
||||
maxNoteTextLength: "Limit znaków dla wpisów"
|
||||
quoteAttached: "Zacytowano"
|
||||
quoteQuestion: "Czy na pewno chcesz umieścić cytat?"
|
||||
noMessagesYet: "Nie napisano jeszcze wiadomości"
|
||||
newMessageExists: "Masz nową wiadomość"
|
||||
@ -419,6 +429,7 @@ signinWith: "Zaloguj się z {x}"
|
||||
signinFailed: "Nie udało się zalogować. Wprowadzona nazwa użytkownika lub hasło są nieprawidłowe."
|
||||
tapSecurityKey: "Wybierz swój klucz bezpieczeństwa"
|
||||
or: "Lub"
|
||||
language: "Język"
|
||||
uiLanguage: "Język wyświetlania UI"
|
||||
groupInvited: "Zaproszony(-a) do grupy"
|
||||
aboutX: "O {x}"
|
||||
@ -432,6 +443,7 @@ category: "Kategoria"
|
||||
tags: "Tagi"
|
||||
docSource: "Źródło tego dokumentu"
|
||||
createAccount: "Utwórz konto"
|
||||
existingAccount: "Istniejące konto"
|
||||
regenerate: "Wygeneruj ponownie"
|
||||
fontSize: "Rozmiar czcionki"
|
||||
noFollowRequests: "Nie masz żadnych oczekujących próśb o możliwość obserwacji"
|
||||
@ -453,6 +465,8 @@ showFeaturedNotesInTimeline: "Pokazuj wyróżnione wpisy w osi czasu"
|
||||
objectStorage: "Pamięć obiektowa"
|
||||
useObjectStorage: "Używaj pamięci obiektowej"
|
||||
objectStorageBaseUrl: "Podstawowy URL"
|
||||
objectStorageBucket: "Bucket"
|
||||
objectStorageBucketDesc: "Podaj nazwę „wiadra” używaną przez konfigurowaną usługę."
|
||||
objectStoragePrefix: "Prefiks"
|
||||
objectStoragePrefixDesc: "Pliki będą przechowywane w katalogu z tym prefiksem."
|
||||
objectStorageEndpoint: "Punkt końcowy"
|
||||
@ -499,7 +513,6 @@ deleteAllFilesConfirm: "Czy na pewno chcesz usunąć wszystkie pliki?"
|
||||
removeAllFollowingDescription: "Przestań obserwować wszystkie konta z {host}. Wykonaj to, jeżeli instancja już nie istnieje."
|
||||
userSuspended: "To konto zostało zawieszone."
|
||||
userSilenced: "Ten użytkownik został wyciszony."
|
||||
sidebar: "Pasek boczny"
|
||||
divider: "Rozdzielacz"
|
||||
addItem: "Dodaj element"
|
||||
rooms: "Pokój"
|
||||
@ -519,6 +532,8 @@ disablePlayer: "Zamknij odtwarzacz wideo"
|
||||
expandTweet: "Rozwiń tweet"
|
||||
themeEditor: "Edytor motywu"
|
||||
description: "Opis"
|
||||
describeFile: "dodaj podpis"
|
||||
enterFileDescription: "Wprowadź napis"
|
||||
author: "Autor"
|
||||
leaveConfirm: "Są niezapisane zmiany. Czy chcesz je odrzucić?"
|
||||
manage: "Zarządzanie"
|
||||
@ -540,6 +555,7 @@ pluginTokenRequestedDescription: "Ta wtyczka będzie mogła korzystać z ustawio
|
||||
notificationType: "Rodzaj powiadomień"
|
||||
edit: "Edytuj"
|
||||
useStarForReactionFallback: "Użyj ★ jako zapasowego emoji, gdy emoji reakcji jest nieznane"
|
||||
emailServer: "Serwer poczty e-mail"
|
||||
enableEmail: "Włącz dostarczanie wiadomości e-mail"
|
||||
emailConfigInfo: "Wykorzystywany do potwierdzenia adresu e-mail w trakcie rejestracji, lub gdy zapomnisz hasła"
|
||||
email: "Adres e-mail"
|
||||
@ -552,6 +568,7 @@ smtpPass: "Hasło"
|
||||
emptyToDisableSmtpAuth: "Pozostaw adres e-mail i hasło puste, aby wyłączyć weryfikację SMTP"
|
||||
smtpSecureInfo: "Wyłącz, jeżeli używasz STARTTLS"
|
||||
testEmail: "Przetestuj dostarczanie wiadomości e-mail"
|
||||
wordMute: "Wyciszenie słowa"
|
||||
userSaysSomething: "{name} powiedział(-a) coś"
|
||||
makeActive: "Aktywuj"
|
||||
display: "Wyświetlanie"
|
||||
@ -622,6 +639,7 @@ emailVerified: "Adres e-mail został potwierdzony"
|
||||
noteFavoritesCount: "Liczba polubionych wpisów"
|
||||
pageLikesCount: "Liczba otrzymanych polubień stron"
|
||||
pageLikedCount: "Liczba polubionych stron"
|
||||
reversiCount: "Liczba rozgrywek Reversi"
|
||||
contact: "Kontakt"
|
||||
useSystemFont: "Używaj domyślnej czcionki systemu"
|
||||
experimentalFeatures: "Eksperymentalne funkcje"
|
||||
@ -630,6 +648,7 @@ makeExplorable: "Pokazuj konto na stronie „Eksploruj”"
|
||||
makeExplorableDescription: "Jeżeli wyłączysz tę opcję, Twoje konto nie będzie wyświetlać się w sekcji „Eksploruj”."
|
||||
showGapBetweenNotesInTimeline: "Pokazuj odstęp między wpisami na osi czasu."
|
||||
duplicate: "Duplikuj"
|
||||
left: "Lewo"
|
||||
center: "Wyśsrodkuj"
|
||||
wide: "Szerokie"
|
||||
narrow: "Wąskie"
|
||||
@ -639,26 +658,108 @@ clearCache: "Wyczyść pamięć podręczną"
|
||||
onlineUsersCount: "{n} osób jest online"
|
||||
nUsers: "{n} użytkowników"
|
||||
nNotes: "{n} wpisów"
|
||||
sendErrorReports: "Wyślij raporty o błędach"
|
||||
myTheme: "Mój motyw"
|
||||
backgroundColor: "Tło"
|
||||
accentColor: "Akcent"
|
||||
textColor: "Tekst"
|
||||
saveAs: "Zapisz jako…"
|
||||
advanced: "Zaawansowane"
|
||||
value: "Wartość"
|
||||
createdAt: "Utworzono"
|
||||
updatedAt: "Zaktualizowano"
|
||||
saveConfirm: "Zapisać zmiany?"
|
||||
deleteConfirm: "Na pewno usunąć?"
|
||||
invalidValue: "Nieprawidłowa wartość."
|
||||
registry: "Rejestr"
|
||||
closeAccount: "Zamknij konto"
|
||||
currentVersion: "Bieżąca wersja"
|
||||
latestVersion: "Najnowsza wersja"
|
||||
youAreRunningUpToDateClient: "Korzystasz z najnowszej wersji klienta."
|
||||
newVersionOfClientAvailable: "Nowsza wersja klienta jest dostępna."
|
||||
usageAmount: "Użycie"
|
||||
capacity: "Pojemność"
|
||||
inUse: "Użyto"
|
||||
editCode: "Edytuj kod"
|
||||
apply: "Zastosuj"
|
||||
receiveAnnouncementFromInstance: "Otrzymuj powiadomienia e-mail z tej instancji"
|
||||
emailNotification: "Powiadomienia e-mail"
|
||||
publish: "Publikuj"
|
||||
inChannelSearch: "Szukaj na kanale"
|
||||
useReactionPickerForContextMenu: "Otwórz wybornik reakcji prawym kliknięciem"
|
||||
typingUsers: "{users} pisze(-ą)..."
|
||||
jumpToSpecifiedDate: "Przejdź do określonej daty"
|
||||
showingPastTimeline: "Obecnie wyświetla starą oś czasu"
|
||||
clear: "Wróć"
|
||||
markAllAsRead: "Oznacz wszystkie jako przeczytane"
|
||||
goBack: "Wróć"
|
||||
unlikeConfirm: "Na pewno chcesz usunąć polubienie?"
|
||||
fullView: "Pełny widok"
|
||||
quitFullView: "Opuść pełny widok"
|
||||
addDescription: "Dodaj opis"
|
||||
info: "Informacje"
|
||||
userInfo: "Informacje o użykowniku"
|
||||
unknown: "Nieznane"
|
||||
onlineStatus: "Status online"
|
||||
hideOnlineStatus: "Ukryj status online"
|
||||
hideOnlineStatusDescription: "Ukrywanie statusu online ogranicza wygody niektórych funkcji, tj. wyszukiwanie"
|
||||
online: "Online"
|
||||
active: "Aktywny"
|
||||
offline: "Offline"
|
||||
notRecommended: "Nie zalecane"
|
||||
botProtection: "Zabezpieczenie przed botami"
|
||||
instanceBlocking: "Zablokowane instancje"
|
||||
selectAccount: "Wybierz konto"
|
||||
enabled: "Właczono"
|
||||
disabled: "Wyłączono"
|
||||
quickAction: "Szybkie działania"
|
||||
user: "Użytkownicy"
|
||||
administration: "Zarządzanie"
|
||||
accounts: "Konta"
|
||||
switch: "Przełącz"
|
||||
noMaintainerInformationWarning: "Informacje o administratorze nie są skonfigurowane."
|
||||
noBotProtectionWarning: "Zabezpieczenie przed botami nie jest skonfigurowane."
|
||||
configure: "Skonfiguruj"
|
||||
postToGallery: "Opublikuj w galerii"
|
||||
gallery: "Galeria"
|
||||
recentPosts: "Ostatnie wpisy"
|
||||
popularPosts: "Popularne wpisy"
|
||||
shareWithNote: "Udostępnij z wpisem"
|
||||
ads: "Reklamy"
|
||||
expiration: "Ankieta kończy się"
|
||||
memo: "Notatki"
|
||||
priority: "Priorytet"
|
||||
high: "Wysoki"
|
||||
middle: "Średnie"
|
||||
low: "Niski"
|
||||
emailNotConfiguredWarning: "Nie podano adresu e-mail"
|
||||
ratio: "Stosunek"
|
||||
global: "Globalna"
|
||||
_ad:
|
||||
back: "Wróć"
|
||||
reduceFrequencyOfThisAd: "Pokazuj tę reklamę rzadziej"
|
||||
_forgotPassword:
|
||||
ifNoEmail: "Jeżeli nie podano adresu e-mail podczas rejestracji, skontaktuj się z administratorem zamiast tego."
|
||||
contactAdmin: "Jeżeli Twoja instancja nie obsługuje adresów e-mail, skontaktuj się zamiast tego z administratorem, aby zresetować hasło."
|
||||
_gallery:
|
||||
my: "Moja galeria"
|
||||
liked: "Polubione wpisy"
|
||||
like: "Polub"
|
||||
unlike: "Cofnij polubienie"
|
||||
_email:
|
||||
_follow:
|
||||
title: "Zaobserwował(a) Cię"
|
||||
_receiveFollowRequest:
|
||||
title: "Otrzymano prośbę o możliwość obserwacji"
|
||||
_plugin:
|
||||
install: "Zainstaluj wtyczki"
|
||||
installWarn: "Nie instaluj niezaufanych wtyczek."
|
||||
manage: "Zarządzanie wtyczkami"
|
||||
_registry:
|
||||
scope: "Zakres"
|
||||
key: "Klucz"
|
||||
keys: "Klucz"
|
||||
domain: "Domena"
|
||||
createKey: "Utwórz klucz"
|
||||
_aboutMisskey:
|
||||
about: "Misskey jest oprogramowanie open source rozwijanym przez syuilo od 2014."
|
||||
@ -708,6 +809,7 @@ _mfm:
|
||||
x4Description: "Czyni treść jeszcze większą niż jeszcze większa."
|
||||
blur: "Rozmycie"
|
||||
font: "Czcionka"
|
||||
fontDescription: "Wybiera czcionkę do wyświetlania treści."
|
||||
_reversi:
|
||||
reversi: "Reversi"
|
||||
gameSettings: "Ustawienia gry"
|
||||
@ -756,9 +858,7 @@ _channel:
|
||||
following: "Śledzeni"
|
||||
usersCount: "{n} uczestnicy"
|
||||
notesCount: "{n} wpisy"
|
||||
_sidebar:
|
||||
full: "Pełne"
|
||||
icon: "Awatar"
|
||||
_menuDisplay:
|
||||
hide: "Ukryj"
|
||||
_wordMute:
|
||||
muteWords: "Słowo do wyciszenia"
|
||||
@ -972,16 +1072,21 @@ _profile:
|
||||
username: "Nazwa użytkownika"
|
||||
description: "Opis"
|
||||
youCanIncludeHashtags: "Możesz umieścić hashtagi w swoim opisie."
|
||||
metadata: "Dodatkowe informacje"
|
||||
metadataEdit: "Edytuj dodatkowe informacje"
|
||||
metadataDescription: "Możesz wyświetlać do czterech sekcji dodatkowych informacji na swoim profilu."
|
||||
metadataLabel: "Etykieta"
|
||||
metadataContent: "Treść"
|
||||
changeAvatar: "Zmień awatar"
|
||||
changeBanner: "Zmień baner"
|
||||
_exportOrImport:
|
||||
allNotes: "Wszystkie wpisy"
|
||||
followingList: "Obserwowani"
|
||||
muteList: "Wycisz"
|
||||
blockingList: "Zablokuj"
|
||||
userLists: "Listy"
|
||||
_charts:
|
||||
federationInstancesTotal: "Łącznie sfederowanych instancji"
|
||||
usersTotal: "Łącznie # użytkowników"
|
||||
activeUsers: "Aktywni użytkownicy"
|
||||
_instanceCharts:
|
||||
@ -996,6 +1101,7 @@ _instanceCharts:
|
||||
_timelines:
|
||||
home: "Strona główna"
|
||||
local: "Lokalne"
|
||||
social: "Społeczność"
|
||||
global: "Globalna"
|
||||
_rooms:
|
||||
roomOf: "Pokój {user}"
|
||||
@ -1366,6 +1472,8 @@ _deck:
|
||||
swapRight: "Przesuń w prawo"
|
||||
swapUp: "Zamień z powyższym"
|
||||
swapDown: "Zamień z poniższym"
|
||||
stackLeft: "Przypnij do lewej"
|
||||
popRight: "Odepnij w prawo"
|
||||
profile: "Profil"
|
||||
_columns:
|
||||
main: "Główna"
|
||||
|
@ -6,25 +6,72 @@ notifications: "Notificações"
|
||||
username: "Nome de usuário"
|
||||
password: "Senha"
|
||||
ok: "OK"
|
||||
gotIt: "Entendi"
|
||||
cancel: "Cancelar"
|
||||
enterUsername: "Digite o nome de usuário"
|
||||
renotedBy: "Repostado por {user}"
|
||||
noNotes: "Sem posts"
|
||||
settings: "Configurações"
|
||||
basicSettings: "Configurações básicas"
|
||||
otherSettings: "Outras configurações"
|
||||
profile: "Perfil"
|
||||
timeline: "Timeline"
|
||||
logout: "Sair"
|
||||
users: "Usuários"
|
||||
favorite: "Favoritar"
|
||||
favorites: "Favoritar"
|
||||
showMore: "Ver mais"
|
||||
youGotNewFollower: "Você tem um novo seguidor"
|
||||
followRequestAccepted: "Pedido de seguir aceito"
|
||||
note: "Post"
|
||||
notes: "Posts"
|
||||
enterEmoji: "Inserir emoji"
|
||||
renote: "Repostar"
|
||||
renoted: "Repostado"
|
||||
cantRenote: "Não pode repostar"
|
||||
cantReRenote: "Não pode repostar este repost"
|
||||
pinnedNote: "Post fixado"
|
||||
sensitive: "Conteúdo sensível"
|
||||
mute: "Silenciar"
|
||||
unmute: "Dessilenciar"
|
||||
settingGuide: "Guia de configuração"
|
||||
instances: "Instância"
|
||||
registeredAt: "Registrado em"
|
||||
perHour: "por hora"
|
||||
perDay: "por dia"
|
||||
noUsers: "Sem usuários"
|
||||
messageRead: "Lida"
|
||||
lightThemes: "Tema claro"
|
||||
darkThemes: "Tema escuro"
|
||||
addFile: "Adicionar arquivo"
|
||||
nsfw: "Conteúdo sensível"
|
||||
monthX: "mês de {month}"
|
||||
pinnedNotes: "Post fixado"
|
||||
smtpUser: "Nome de usuário"
|
||||
smtpPass: "Senha"
|
||||
user: "Usuários"
|
||||
_email:
|
||||
_follow:
|
||||
title: "Você tem um novo seguidor"
|
||||
_mfm:
|
||||
search: "Pesquisar"
|
||||
_theme:
|
||||
keys:
|
||||
renote: "Repostar"
|
||||
_sfx:
|
||||
note: "Posts"
|
||||
notification: "Notificações"
|
||||
_widgets:
|
||||
notifications: "Notificações"
|
||||
timeline: "Timeline"
|
||||
_profile:
|
||||
username: "Nome de usuário"
|
||||
_exportOrImport:
|
||||
muteList: "Silenciar"
|
||||
_notification:
|
||||
youWereFollowed: "Você tem um novo seguidor"
|
||||
_types:
|
||||
renote: "Repostar"
|
||||
_deck:
|
||||
_columns:
|
||||
notifications: "Notificações"
|
||||
|
@ -7,6 +7,7 @@ search: "Поиск"
|
||||
notifications: "Уведомления"
|
||||
username: "Имя пользователя"
|
||||
password: "Пароль"
|
||||
forgotPassword: "Пароль забыт"
|
||||
fetchingAsApObject: "Приём с других сайтов"
|
||||
ok: "Окей"
|
||||
gotIt: "Ясно!"
|
||||
@ -278,6 +279,7 @@ emptyDrive: "Диск пуст"
|
||||
emptyFolder: "Папка пуста"
|
||||
unableToDelete: "Удаление невозможно"
|
||||
inputNewFileName: "Введите имя нового файла"
|
||||
inputNewDescription: "Введите новую подпись"
|
||||
inputNewFolderName: "Пожалуйста, введите новое имя папки!"
|
||||
circularReferenceFolder: "Вы пытаетесь переместить папку внутрь себя."
|
||||
hasChildFilesOrFolders: "Эта папка не пуста и не может быть удалена."
|
||||
@ -309,8 +311,8 @@ monthX: "{month} месяц"
|
||||
yearX: "{year} год"
|
||||
pages: "Страницы"
|
||||
integration: "Интеграция"
|
||||
connectSerice: "Соединение"
|
||||
disconnectSerice: "Отключение"
|
||||
connectService: "Подключиться"
|
||||
disconnectService: "Отключиться"
|
||||
enableLocalTimeline: "Включить локальную ленту"
|
||||
enableGlobalTimeline: "Включить глобальную ленту"
|
||||
disablingTimelinesInfo: "У администраторов и модераторов есть доступ ко всем лентам, даже если они отключены."
|
||||
@ -324,6 +326,7 @@ driveCapacityPerRemoteAccount: "Объём диска на одного поль
|
||||
inMb: "В мегабайтах"
|
||||
iconUrl: "Ссылка на аватар"
|
||||
bannerUrl: "Ссылка на изображение в шапке"
|
||||
backgroundImageUrl: "Ссылка на фоновое изображение"
|
||||
basicInfo: "Общая информация"
|
||||
pinnedUsers: "Прикреплённый пользователь"
|
||||
pinnedUsersDescription: "Перечислите по одному имени пользователя в строке. Пользователи, перечисленные здесь, будут привязаны к закладке \"Изучение\"."
|
||||
@ -525,7 +528,6 @@ removeAllFollowing: "Удалить всех подписчиков"
|
||||
removeAllFollowingDescription: "Отменить все подписки с домена {host}? Пожалуйста, применяйте это действие, если инстанс больше не существует."
|
||||
userSuspended: "Эта учётная запись заморожена"
|
||||
userSilenced: "Этот пользователь был заглушен"
|
||||
sidebar: "Боковая панель"
|
||||
divider: "Линия-разделитель"
|
||||
addItem: "Добавить элемент"
|
||||
rooms: "Комната"
|
||||
@ -545,6 +547,8 @@ disablePlayer: "Выключить проигрыватель"
|
||||
expandTweet: "Развернуть твит"
|
||||
themeEditor: "Редактор темы оформления"
|
||||
description: "Описание"
|
||||
describeFile: "Добавить подпись"
|
||||
enterFileDescription: "Введите подпись"
|
||||
author: "Автор"
|
||||
leaveConfirm: "Вы не сохранили изменения. Хотите выйти и потерять их?"
|
||||
manage: "Управление"
|
||||
@ -747,10 +751,23 @@ gallery: "Галерея"
|
||||
recentPosts: "Недавние публикации"
|
||||
popularPosts: "Популярные публикации"
|
||||
shareWithNote: "Поделиться заметкой"
|
||||
ads: "Реклама"
|
||||
expiration: "Опрос длится"
|
||||
memo: "Памятка"
|
||||
priority: "Приоритет"
|
||||
high: "Высокий"
|
||||
middle: "Средне"
|
||||
low: "Низкий"
|
||||
emailNotConfiguredWarning: "Не указан адрес электронной почты"
|
||||
ratio: "Соотношение"
|
||||
global: "Всеобщая"
|
||||
_ad:
|
||||
back: "Выход"
|
||||
reduceFrequencyOfThisAd: "Реже показывать эту рекламу"
|
||||
_forgotPassword:
|
||||
enterEmail: "Введите адрес электронной почты, который ввели при регистрации. На неё будет выслана ссылка для смены пароля."
|
||||
ifNoEmail: "Если вы не ввели свой адрес электронной почты, свяжитесь с администратором ресурса, чтобы сменить пароль."
|
||||
contactAdmin: "Здесь не используются адреса электронной почты, так что свяжитесь с администратором, чтобы поменять пароль."
|
||||
_gallery:
|
||||
my: "Личная"
|
||||
liked: "Понравившееся"
|
||||
@ -893,9 +910,7 @@ _channel:
|
||||
following: "Подписки"
|
||||
usersCount: "Участников: {n}"
|
||||
notesCount: "Заметок: {n}"
|
||||
_sidebar:
|
||||
full: "Полностью"
|
||||
icon: "Только значки"
|
||||
_menuDisplay:
|
||||
hide: "Спрятать"
|
||||
_wordMute:
|
||||
muteWords: "Скрыть слово"
|
||||
|
@ -307,8 +307,6 @@ monthX: "{month}"
|
||||
yearX: "{year}"
|
||||
pages: "Сторінки"
|
||||
integration: "Інтеграція"
|
||||
connectSerice: "Під’єднати"
|
||||
disconnectSerice: "Відключитися"
|
||||
enableLocalTimeline: "Увімкнути локальну стрічку"
|
||||
enableGlobalTimeline: "Увімкнути глобальну стрічку"
|
||||
disablingTimelinesInfo: "Адміністратори та модератори завжди мають доступ до всіх стрічок, навіть якщо вони вимкнуті."
|
||||
@ -519,7 +517,6 @@ removeAllFollowing: "Скасувати всі підписки"
|
||||
removeAllFollowingDescription: "Скасувати підписку на всі акаунти з {host}. Будь ласка, робіть це, якщо інстанс більше не існує."
|
||||
userSuspended: "Обліковий запис заблокований."
|
||||
userSilenced: "Обліковий запис приглушений."
|
||||
sidebar: "Бокова панель"
|
||||
divider: "Розділювач"
|
||||
addItem: "Додати елемент"
|
||||
rooms: "Кімнати"
|
||||
@ -691,6 +688,7 @@ user: "Користувачі"
|
||||
administration: "Управління"
|
||||
expiration: "Опитування закінчується"
|
||||
middle: "Середній"
|
||||
global: "Глобальна"
|
||||
_ad:
|
||||
back: "Назад"
|
||||
_gallery:
|
||||
@ -818,9 +816,7 @@ _channel:
|
||||
following: "Підписки"
|
||||
usersCount: "{n} учасників"
|
||||
notesCount: "{n} дописів"
|
||||
_sidebar:
|
||||
full: "Повна"
|
||||
icon: "Аватар"
|
||||
_menuDisplay:
|
||||
hide: "Сховати"
|
||||
_wordMute:
|
||||
muteWords: "Заглушені слова"
|
||||
|
@ -1,13 +1,13 @@
|
||||
---
|
||||
_lang_: "中文(简体)"
|
||||
headlineMisskey: "通过帖子连接在一起的网络"
|
||||
introMisskey: "欢迎!Misskey是一个开源的、去中心化的“微博客”服务。\n通过编写「帖文」来和大家分享你的以及你周围的事情吧!📡\n通过「回应」功能,可以让你快速地对大家的帖文表达反馈👍\n来探索新的世界吧!🚀"
|
||||
introMisskey: "欢迎!Misskey是一个开源的、去中心化的“微博客”服务。\n通过编写「帖子」来和大家分享你的以及你周围的事情吧!📡\n通过「回应」功能,可以让你快速地对大家的帖子表达反馈👍\n来探索新的世界吧!🚀"
|
||||
monthAndDay: "{month}月 {day}日"
|
||||
search: "搜索"
|
||||
notifications: "通知"
|
||||
username: "用户名"
|
||||
password: "密码"
|
||||
forgotPassword: "忘记密码"
|
||||
forgotPassword: "重置密码"
|
||||
fetchingAsApObject: "联合查询中"
|
||||
ok: "OK"
|
||||
gotIt: "我明白了"
|
||||
@ -63,33 +63,33 @@ import: "导入"
|
||||
export: "导出"
|
||||
files: "文件"
|
||||
download: "下载"
|
||||
driveFileDeleteConfirm: "要删除「{name}」文件吗?附加此文件的帖子也会消失。"
|
||||
driveFileDeleteConfirm: "要删除「{name}」文件吗?附加此文件的帖子也会被删除。"
|
||||
unfollowConfirm: "要取消对{name}的关注吗?"
|
||||
exportRequested: "导出请求已提交。可能需要花一些时间。导出的文件将保存到网盘中。"
|
||||
importRequested: "导入请求已提交。这可能需要花一点时间。"
|
||||
exportRequested: "导出请求已提交,这可能需要花一些时间,导出的文件将保存到网盘中。"
|
||||
importRequested: "导入请求已提交,这可能需要花一点时间。"
|
||||
lists: "列表"
|
||||
noLists: "列表为空"
|
||||
note: "帖子"
|
||||
notes: "帖子"
|
||||
following: "关注中"
|
||||
followers: "关注者"
|
||||
followsYou: "关注了你"
|
||||
followsYou: "正在关注你"
|
||||
createList: "创建列表"
|
||||
manageLists: "管理列表"
|
||||
error: "错误"
|
||||
somethingHappened: "出现了问题"
|
||||
somethingHappened: "出现了一些问题!"
|
||||
retry: "重试"
|
||||
pageLoadError: "页面加载失败。"
|
||||
pageLoadErrorDescription: "这通常是由于网络或浏览器缓存的原因。请清除缓存或等待片刻后重试。"
|
||||
enterListName: "输入列表名称"
|
||||
privacy: "隐私"
|
||||
makeFollowManuallyApprove: "关注者请求需要批准"
|
||||
makeFollowManuallyApprove: "关注者的关注请求需要批准"
|
||||
defaultNoteVisibility: "默认可见性"
|
||||
follow: "关注"
|
||||
followRequest: "关注申请"
|
||||
followRequests: "关注申请"
|
||||
unfollow: "取消关注"
|
||||
followRequestPending: "发送关注申请"
|
||||
followRequestPending: "发送关注请求"
|
||||
enterEmoji: "输入表情符号"
|
||||
renote: "转发"
|
||||
unrenote: "取消转发"
|
||||
@ -106,7 +106,7 @@ add: "添加"
|
||||
reaction: "回应"
|
||||
reactionSettingDescription: "选择您想要置顶的回应。"
|
||||
reactionSettingDescription2: "拖动重新排序,单击删除,点击 + 添加。"
|
||||
rememberNoteVisibility: "记录公开范围"
|
||||
rememberNoteVisibility: "保存上次设置的可见性"
|
||||
attachCancel: "删除附件"
|
||||
markAsSensitive: "标记为敏感内容"
|
||||
unmarkAsSensitive: "取消标记为敏感内容"
|
||||
@ -134,11 +134,11 @@ addEmoji: "添加表情符号"
|
||||
settingGuide: "推荐配置"
|
||||
cacheRemoteFiles: "远程文件缓存"
|
||||
cacheRemoteFilesDescription: "当禁用此设定时远程文件将直接从远程实例载入。禁用后会减小储存空间需求,但是会增加流量,因为缩略图不会被生成。"
|
||||
flagAsBot: "这个账户是Bot"
|
||||
flagAsBot: "这是一个机器人账号"
|
||||
flagAsBotDescription: "如果此帐户由程序控制,请启用此项。启用后,此标志可以帮助其他开发人员防止机器人之间产生无限互动的行为,并让Misskey的内部系统将此帐户识别为机器人。"
|
||||
flagAsCat: "这个账户是Cat"
|
||||
flagAsCatDescription: "如果您想表明此帐户是一只猫,请打开此标志。"
|
||||
autoAcceptFollowed: "自动允许关注"
|
||||
flagAsCat: "这个账户是一只猫"
|
||||
flagAsCatDescription: "如果您想表明此帐户是一只猫,请打开此标志。\n开启后,会在您的头像上出现猫耳朵,并将你的帖子中的「na」替换为「nya」,日文同理。"
|
||||
autoAcceptFollowed: "自动允许关注者的关注"
|
||||
addAccount: "添加账户"
|
||||
loginFailed: "登录失败"
|
||||
showOnRemote: "转到所在实例显示"
|
||||
@ -172,7 +172,7 @@ software: "软件"
|
||||
version: "版本"
|
||||
metadata: "元数据"
|
||||
withNFiles: "{n}个文件"
|
||||
monitor: "监视器"
|
||||
monitor: "服务器状态"
|
||||
jobQueue: "作业队列"
|
||||
cpuAndMemory: "CPU和内存"
|
||||
network: "网络"
|
||||
@ -211,7 +211,7 @@ instanceFollowing: "关注实例"
|
||||
instanceFollowers: "关注实例"
|
||||
instanceUsers: "实例用户"
|
||||
changePassword: "修改密码"
|
||||
security: "安全性"
|
||||
security: "安全"
|
||||
retypedNotMatch: "两次输入不一致!"
|
||||
currentPassword: "现在的密码"
|
||||
newPassword: "新密码"
|
||||
@ -231,18 +231,18 @@ deleteAreYouSure: "要删掉「{x}」吗?"
|
||||
resetAreYouSure: "恢复默认设置?"
|
||||
saved: "已保存"
|
||||
messaging: "聊天"
|
||||
upload: "上传"
|
||||
upload: "本地上传"
|
||||
fromDrive: "从网盘中"
|
||||
fromUrl: "从 URL"
|
||||
uploadFromUrl: "从网址上传"
|
||||
uploadFromUrlDescription: "要上传的文件的URL"
|
||||
uploadFromUrlDescription: "输入文件的URL"
|
||||
uploadFromUrlRequested: "请求上传"
|
||||
uploadFromUrlMayTakeTime: "上传可能需要一些时间完成。"
|
||||
explore: "发现"
|
||||
games: "Misskey游戏"
|
||||
messageRead: "已读"
|
||||
noMoreHistory: "没有更多的历史记录"
|
||||
startMessaging: "开始聊天"
|
||||
startMessaging: "添加聊天"
|
||||
nUsersRead: "{n}人已读"
|
||||
agreeTo: "{0}人同意"
|
||||
tos: "服务条款"
|
||||
@ -260,8 +260,8 @@ themeForLightMode: "在浅色模式下使用的主题"
|
||||
themeForDarkMode: "在深色模式下使用的主题"
|
||||
light: "浅色"
|
||||
dark: "深色"
|
||||
lightThemes: "亮色主题"
|
||||
darkThemes: "暗色主题"
|
||||
lightThemes: "浅色主题"
|
||||
darkThemes: "深色主题"
|
||||
syncDeviceDarkMode: "将深色模式与设备设置同步"
|
||||
drive: "网盘"
|
||||
fileName: "文件名称"
|
||||
@ -275,23 +275,24 @@ createFolder: "创建文件夹"
|
||||
renameFolder: "重命名文件夹"
|
||||
deleteFolder: "删除文件夹"
|
||||
addFile: "添加文件"
|
||||
emptyDrive: "驱动器为空"
|
||||
emptyFolder: "空文件夹"
|
||||
emptyDrive: "网盘中无文件"
|
||||
emptyFolder: "此文件夹中无文件"
|
||||
unableToDelete: "无法删除"
|
||||
inputNewFileName: "请输入新文件名"
|
||||
inputNewFolderName: "请输入新文件名"
|
||||
inputNewDescription: "请输入新标题"
|
||||
inputNewFolderName: "请输入新文件夹名"
|
||||
circularReferenceFolder: "目标文件夹是您要移动的文件夹的子文件夹。"
|
||||
hasChildFilesOrFolders: "此文件夹不为空,无法删除。"
|
||||
hasChildFilesOrFolders: "此文件夹中有文件,无法删除。"
|
||||
copyUrl: "复制链接"
|
||||
rename: "重命名"
|
||||
avatar: "头像"
|
||||
banner: "Banner"
|
||||
banner: "横幅"
|
||||
nsfw: "敏感内容"
|
||||
whenServerDisconnected: "与服务器连接中断时"
|
||||
disconnectedFromServer: "已从服务器断开连接"
|
||||
disconnectedFromServer: "已和服务器断开连接"
|
||||
reload: "重新加载"
|
||||
doNothing: "什么都不做"
|
||||
reloadConfirm: "确定要重新加载吗"
|
||||
doNothing: "关闭弹窗"
|
||||
reloadConfirm: "确定要重新加载吗?"
|
||||
watch: "关注"
|
||||
unwatch: "取消关注"
|
||||
accept: "允许"
|
||||
@ -310,8 +311,8 @@ monthX: "{month}月"
|
||||
yearX: "{year}年"
|
||||
pages: "页面"
|
||||
integration: "关联"
|
||||
connectSerice: "连接"
|
||||
disconnectSerice: "断开连接"
|
||||
connectService: "连接"
|
||||
disconnectService: "断开连接"
|
||||
enableLocalTimeline: "启用本地时间线功能"
|
||||
enableGlobalTimeline: "启用全局时间线"
|
||||
disablingTimelinesInfo: "即使时间线功能被禁用,出于便利性的原因,管理员和数据图表也可以继续使用。"
|
||||
@ -324,13 +325,14 @@ driveCapacityPerLocalAccount: "每个用户的网盘空间"
|
||||
driveCapacityPerRemoteAccount: "每个远程用户的网盘容量"
|
||||
inMb: "以兆字节(MegaByte)为单位"
|
||||
iconUrl: "图标URL"
|
||||
bannerUrl: "Banner URL"
|
||||
bannerUrl: "横幅URL"
|
||||
backgroundImageUrl: "背景图URL"
|
||||
basicInfo: "基本信息"
|
||||
pinnedUsers: "置顶用户"
|
||||
pinnedUsersDescription: "在「发现」页面中使用换行标记想要置顶的用户。"
|
||||
pinnedPages: "固定页面"
|
||||
pinnedPagesDescription: "输入您要固定到实例首页的页面路径,以换行符分隔。"
|
||||
pinnedClipId: "置顶的片段ID"
|
||||
pinnedClipId: "置顶的书签ID"
|
||||
pinnedNotes: "已置顶的帖子"
|
||||
hcaptcha: "hCaptcha"
|
||||
enableHcaptcha: "启用 hCaptcha"
|
||||
@ -348,13 +350,13 @@ antennaSource: "接收来源"
|
||||
antennaKeywords: "包含关键字"
|
||||
antennaExcludeKeywords: "排除关键字"
|
||||
antennaKeywordsDescription: "使用空格分隔会产生AND规范,并且使用换行符分隔会产生OR规范"
|
||||
notifyAntenna: "通知新帖子"
|
||||
notifyAntenna: "开启通知"
|
||||
withFileAntenna: "仅带有附件的帖子"
|
||||
enableServiceworker: "启用ServiceWorker"
|
||||
antennaUsersDescription: "指定用户名,用换行符分隔"
|
||||
caseSensitive: "区分大小写"
|
||||
withReplies: "包括回复"
|
||||
connectedTo: "您的账号已连到接以下社交账号"
|
||||
connectedTo: "您的账号已连到接以下第三方账号"
|
||||
notesAndReplies: "帖子与回复"
|
||||
withFiles: "附件"
|
||||
silence: "禁言"
|
||||
@ -362,8 +364,8 @@ silenceConfirm: "确认要禁言吗?"
|
||||
unsilence: "解除禁言"
|
||||
unsilenceConfirm: "要解除禁言吗?"
|
||||
popularUsers: "热门用户"
|
||||
recentlyUpdatedUsers: "最近投稿用户"
|
||||
recentlyRegisteredUsers: "最近登录用户"
|
||||
recentlyUpdatedUsers: "最近投稿的用户"
|
||||
recentlyRegisteredUsers: "最近登录的用户"
|
||||
recentlyDiscoveredUsers: "最近发现的用户"
|
||||
exploreUsersCount: "有{count}个用户"
|
||||
exploreFediverse: "探索Fediverse"
|
||||
@ -372,9 +374,9 @@ userList: "列表"
|
||||
about: "关于"
|
||||
aboutMisskey: "关于 Misskey"
|
||||
administrator: "管理员"
|
||||
token: "令牌"
|
||||
token: "Token (令牌)"
|
||||
twoStepAuthentication: "两步验证"
|
||||
moderator: "版主"
|
||||
moderator: "监察员"
|
||||
nUsersMentioned: "{n} 被提到"
|
||||
securityKey: "安全密钥"
|
||||
securityKeyName: "密钥名称"
|
||||
@ -416,7 +418,7 @@ noteOf: "{user}的帖子"
|
||||
inviteToGroup: "群组邀请"
|
||||
maxNoteTextLength: "帖子的字数限制"
|
||||
quoteAttached: "已引用"
|
||||
quoteQuestion: "是否将其作为引用附上?"
|
||||
quoteQuestion: "是否引用此链接内容?"
|
||||
noMessagesYet: "现在没有新的聊天"
|
||||
newMessageExists: "新信息"
|
||||
onlyOneFileCanBeAttached: "只能添加一个附件"
|
||||
@ -440,9 +442,9 @@ tapSecurityKey: "轻触硬件安全密钥"
|
||||
or: "或者"
|
||||
language: "语言"
|
||||
uiLanguage: "显示语言"
|
||||
groupInvited: "群组招待"
|
||||
groupInvited: "您有新的群组邀请"
|
||||
aboutX: "关于 {x}"
|
||||
useOsNativeEmojis: "使用OS原生表情符号"
|
||||
useOsNativeEmojis: "使用系统的原生表情符号"
|
||||
youHaveNoGroups: "没有群组"
|
||||
joinOrCreateGroup: "请加入一个现有的群组,或者创建新群组。"
|
||||
noHistory: "没有历史记录"
|
||||
@ -458,7 +460,7 @@ regenerate: "重新生成"
|
||||
fontSize: "字体大小"
|
||||
noFollowRequests: "没有关注申请"
|
||||
openImageInNewTab: "在新标签页中打开图片"
|
||||
dashboard: "Dashboard"
|
||||
dashboard: "管理面板"
|
||||
local: "本地"
|
||||
remote: "远程"
|
||||
total: "总计"
|
||||
@ -490,12 +492,12 @@ objectStorageUseProxy: "使用代理"
|
||||
objectStorageUseProxyDesc: "如果您不使用代理进行API连接,请将其关闭。"
|
||||
objectStorageSetPublicRead: "上传时设置为public-read"
|
||||
serverLogs: "服务器日志"
|
||||
deleteAll: "删除全部"
|
||||
showFixedPostForm: "在时间线顶部显示帖子表单"
|
||||
deleteAll: "全部删除"
|
||||
showFixedPostForm: "在时间线顶部显示发帖框"
|
||||
newNoteRecived: "有新的帖子"
|
||||
sounds: "声音"
|
||||
listen: "听"
|
||||
none: "空"
|
||||
sounds: "提示音"
|
||||
listen: "试听"
|
||||
none: "无"
|
||||
showInPage: "在页面中显示"
|
||||
popout: "弹窗"
|
||||
volume: "音量"
|
||||
@ -507,15 +509,15 @@ recentUsed: "最近使用"
|
||||
install: "安装"
|
||||
uninstall: "卸载"
|
||||
installedApps: "已授权的应用"
|
||||
nothing: "没什么"
|
||||
nothing: "没有"
|
||||
installedDate: "授权日期"
|
||||
lastUsedDate: "最近使用"
|
||||
state: "状态"
|
||||
sort: "排序"
|
||||
ascendingOrder: "升序"
|
||||
descendingOrder: "降序"
|
||||
scratchpad: "便签本"
|
||||
scratchpadDescription: "便签本为AiScript提供了实验环境。您可以编写代码以与Misskey交互,运行它并查看结果。"
|
||||
scratchpad: "AiScript控制台"
|
||||
scratchpadDescription: "AiScript控制台为AiScript提供了实验环境。您可以编写代码以与Misskey交互,运行它并查看结果。"
|
||||
output: "输出"
|
||||
script: "脚本"
|
||||
disablePagesScript: "禁用页面脚本"
|
||||
@ -526,7 +528,7 @@ removeAllFollowing: "取消所有关注"
|
||||
removeAllFollowingDescription: "取消{host}的所有关注者。当实例不存在时执行。"
|
||||
userSuspended: "该用户已被冻结。"
|
||||
userSilenced: "该用户已被禁言。"
|
||||
sidebar: "侧边栏"
|
||||
menu: "菜单"
|
||||
divider: "分割线"
|
||||
addItem: "添加项目"
|
||||
rooms: "房间"
|
||||
@ -543,9 +545,11 @@ poll: "调查问卷"
|
||||
useCw: "隐藏内容"
|
||||
enablePlayer: "打开播放器"
|
||||
disablePlayer: "关闭播放器"
|
||||
expandTweet: "展开贴文"
|
||||
expandTweet: "展开帖子"
|
||||
themeEditor: "主题编辑器"
|
||||
description: "描述"
|
||||
describeFile: "添加标题"
|
||||
enterFileDescription: "输入标题"
|
||||
author: "作者"
|
||||
leaveConfirm: "存在未保存的更改。要放弃更改吗?"
|
||||
manage: "管理"
|
||||
@ -587,10 +591,10 @@ userSaysSomething: "{name}说了什么"
|
||||
makeActive: "启用"
|
||||
display: "显示"
|
||||
copy: "复制"
|
||||
metrics: "指标"
|
||||
overview: "概述"
|
||||
metrics: "服务器监控"
|
||||
overview: "服务器概况"
|
||||
logs: "日志"
|
||||
delayed: "延迟"
|
||||
delayed: "滞后"
|
||||
database: "数据库"
|
||||
channel: "频道"
|
||||
create: "创建"
|
||||
@ -623,17 +627,17 @@ random: "随机"
|
||||
system: "系统"
|
||||
switchUi: "切换界面"
|
||||
desktop: "桌面"
|
||||
clip: "片段"
|
||||
clip: "书签"
|
||||
createNew: "新建"
|
||||
optional: "可选"
|
||||
createNewClip: "新建片段"
|
||||
createNewClip: "新建书签"
|
||||
public: "公开"
|
||||
i18nInfo: "Misskey已经被志愿者们翻译到了各种语言。如果你也有兴趣,可以通过{link}帮助翻译。"
|
||||
manageAccessTokens: "管理 Access Tokens"
|
||||
accountInfo: "帐户信息"
|
||||
notesCount: "贴文数量"
|
||||
notesCount: "帖子数量"
|
||||
repliesCount: "回复数量"
|
||||
renotesCount: "转贴数量"
|
||||
renotesCount: "转帖数量"
|
||||
repliedCount: "回复数"
|
||||
renotedCount: "转发数"
|
||||
followingCount: "正在关注数量"
|
||||
@ -644,9 +648,9 @@ pollVotesCount: "问卷调查的投票数"
|
||||
pollVotedCount: "问卷调查的被投票数"
|
||||
yes: "是"
|
||||
no: "否"
|
||||
driveFilesCount: "磁盘文件数"
|
||||
driveUsage: "磁盘空间用量"
|
||||
noCrawle: "拒绝搜索器的索引"
|
||||
driveFilesCount: "网盘的文件数"
|
||||
driveUsage: "网盘的空间用量"
|
||||
noCrawle: "拒绝搜索引擎的索引"
|
||||
noCrawleDescription: "要求搜索引擎不要收录(索引)您的用户页面,帖子,页面等。"
|
||||
lockedAccountInfo: "即使通过了关注请求,只要您不将帖子可见范围设置成“关注者”,任何人都可以看到您的帖子。"
|
||||
alwaysMarkSensitive: "默认将媒体文件标记为敏感内容"
|
||||
@ -661,7 +665,7 @@ pageLikedCount: "页面被点赞次数"
|
||||
reversiCount: "黑白棋对战次数"
|
||||
contact: "联系人"
|
||||
useSystemFont: "使用系统默认字体"
|
||||
clips: "片段"
|
||||
clips: "书签"
|
||||
experimentalFeatures: "实验性功能"
|
||||
developer: "开发者"
|
||||
makeExplorable: "使账号可见。"
|
||||
@ -693,7 +697,7 @@ saveConfirm: "确定保存?"
|
||||
deleteConfirm: "确定删除?"
|
||||
invalidValue: "无效值。"
|
||||
registry: "注册表"
|
||||
closeAccount: "关闭账户"
|
||||
closeAccount: "永久注销账户"
|
||||
currentVersion: "当前版本"
|
||||
latestVersion: "最新版本"
|
||||
youAreRunningUpToDateClient: "您所使用的客户端已经是最新的。"
|
||||
@ -757,13 +761,17 @@ middle: "中"
|
||||
low: "低"
|
||||
emailNotConfiguredWarning: "电子邮件地址未设置。"
|
||||
ratio: "比率"
|
||||
customCss: "自定义 CSS"
|
||||
customCssWarn: "这些设置必须有相关的基础知识,不当的配置可能导致客户端无法正常使用!"
|
||||
global: "全局"
|
||||
squareAvatars: "显示方形头像图标"
|
||||
_ad:
|
||||
back: "返回"
|
||||
reduceFrequencyOfThisAd: "减少此广告的频率"
|
||||
_forgotPassword:
|
||||
enterEmail: "请输入您用来注册帐户的电子邮件地址。密码重置链接将发送到该地址。"
|
||||
ifNoEmail: "如果您没有使用电子邮件地址注册,请联系管理员。"
|
||||
contactAdmin: "该实例不支持电子邮件。如果您想重设密码,请联系管理员。"
|
||||
enterEmail: "请输入您验证账号时用的电子邮箱地址,密码重置链接将发送至该邮箱上。"
|
||||
ifNoEmail: "如果您没有使用电子邮件地址进行验证,请联系管理员。"
|
||||
contactAdmin: "该实例不支持发送电子邮件。如果您想重设密码,请联系管理员。"
|
||||
_gallery:
|
||||
my: "我的图库"
|
||||
liked: "喜欢的图片"
|
||||
@ -773,7 +781,7 @@ _email:
|
||||
_follow:
|
||||
title: "你有新的关注者"
|
||||
_receiveFollowRequest:
|
||||
title: "收到关注请求"
|
||||
title: "收到了关注请求"
|
||||
_plugin:
|
||||
install: "安装插件"
|
||||
installWarn: "请不要安装不可信的插件。"
|
||||
@ -906,19 +914,20 @@ _channel:
|
||||
following: "正在关注"
|
||||
usersCount: "有{n}人参与"
|
||||
notesCount: "有{n}个帖子"
|
||||
_sidebar:
|
||||
full: "全部"
|
||||
icon: "图标"
|
||||
_menuDisplay:
|
||||
sideFull: "横向"
|
||||
sideIcon: "横向(图标)"
|
||||
top: "顶部"
|
||||
hide: "隐藏"
|
||||
_wordMute:
|
||||
muteWords: "禁用词"
|
||||
muteWordsDescription: "使用空格分隔表示AND逻辑,使用换行符分隔表示OR逻辑。"
|
||||
muteWordsDescription2: "将关键字用斜线括起来表示正则表达式。"
|
||||
softDescription: "隐藏时间线中指定条件的帖文。"
|
||||
hardDescription: "防止将具有指定条件的帖文添加到时间线。 即使您更改条件,未添加的帖文也会被排除在外。"
|
||||
softDescription: "隐藏时间线中指定条件的帖子。"
|
||||
hardDescription: "防止将具有指定条件的帖子添加到时间线。 即使您更改条件,未添加的帖文也会被排除在外。"
|
||||
soft: "软屏蔽"
|
||||
hard: "硬屏蔽"
|
||||
mutedNotes: "被屏蔽的帖文"
|
||||
mutedNotes: "被屏蔽的帖子"
|
||||
_theme:
|
||||
explore: "寻找主题"
|
||||
install: "安装主题"
|
||||
@ -944,8 +953,8 @@ _theme:
|
||||
argument: "参数"
|
||||
basedProp: "基于的属性名称"
|
||||
alpha: "不透明度"
|
||||
darken: "暗色"
|
||||
lighten: "亮色"
|
||||
darken: "深色"
|
||||
lighten: "浅色"
|
||||
inputConstantName: "请输入常量名称"
|
||||
importInfo: "您可以在此处粘贴主题代码,将其导入到编辑器中"
|
||||
deleteConstantConfirm: "确定要删除常量{const}吗?"
|
||||
@ -980,18 +989,18 @@ _theme:
|
||||
cwBg: "CW 按钮背景"
|
||||
cwFg: "CW 按钮文本"
|
||||
cwHoverBg: "CW 按钮背景(悬停)"
|
||||
toastBg: "吐司通知背景"
|
||||
toastFg: "吐司通知文本"
|
||||
toastBg: "Toast通知背景"
|
||||
toastFg: "Toast通知文本"
|
||||
buttonBg: "按钮背景"
|
||||
buttonHoverBg: "按钮背景(悬停)"
|
||||
inputBorder: "输入框边框"
|
||||
listItemHoverBg: "下拉列表项目背景(悬停)"
|
||||
driveFolderBg: "驱动器文件夹背景"
|
||||
driveFolderBg: "网盘的文件夹背景"
|
||||
wallpaperOverlay: "壁纸叠加层"
|
||||
badge: "徽章"
|
||||
messageBg: "聊天背景"
|
||||
accentDarken: "强调色(暗)"
|
||||
accentLighten: "强调色(亮)"
|
||||
accentDarken: "强调色(深)"
|
||||
accentLighten: "强调色(浅)"
|
||||
fgHighlighted: "高亮显示文本"
|
||||
_sfx:
|
||||
note: "帖子"
|
||||
@ -1090,9 +1099,9 @@ _auth:
|
||||
_antennaSources:
|
||||
all: "所有帖子"
|
||||
homeTimeline: "已关注用户的帖子"
|
||||
users: "来自特定用户的帖子"
|
||||
userList: "来自特定清单中的帖子"
|
||||
userGroup: "来自特定组中用户的帖子"
|
||||
users: "来自指定用户的帖子"
|
||||
userList: "来自指定列表中的帖子"
|
||||
userGroup: "来自指定群组中用户的帖子"
|
||||
_weekday:
|
||||
sunday: "星期日"
|
||||
monday: "星期一"
|
||||
@ -1118,7 +1127,7 @@ _widgets:
|
||||
button: "按钮"
|
||||
onlineUsers: "在线用户"
|
||||
jobQueue: "作业队列"
|
||||
serverMetric: "服务器指标"
|
||||
serverMetric: "服务器监控"
|
||||
aiscript: "AiScript控制台"
|
||||
_cw:
|
||||
hide: "隐藏"
|
||||
@ -1131,7 +1140,7 @@ _poll:
|
||||
noMore: "无法再添加更多了"
|
||||
canMultipleVote: "允许多个投票"
|
||||
expiration: "截止时间"
|
||||
infinite: "无限期"
|
||||
infinite: "不限时间"
|
||||
at: "指定日期"
|
||||
after: "指定时间"
|
||||
deadlineDate: "截止日期"
|
||||
@ -1170,7 +1179,7 @@ _postForm:
|
||||
e: "请写下来吧"
|
||||
f: "等待您的发布..."
|
||||
_profile:
|
||||
name: "名称"
|
||||
name: "昵称"
|
||||
username: "用户名"
|
||||
description: "个人简介"
|
||||
youCanIncludeHashtags: "您可以包含一个哈希标签。"
|
||||
@ -1283,7 +1292,7 @@ _rooms:
|
||||
_pages:
|
||||
newPage: "创建页面"
|
||||
editPage: "编辑页面"
|
||||
readPage: "查看源"
|
||||
readPage: "查看页面"
|
||||
created: "页面已创建"
|
||||
updated: "页面已更新"
|
||||
deleted: "该页面已被删除"
|
||||
@ -1596,7 +1605,7 @@ _notification:
|
||||
reaction: "回应"
|
||||
pollVote: "问卷调查被投票"
|
||||
receiveFollowRequest: "收到关注请求"
|
||||
followRequestAccepted: "关注请求已接受"
|
||||
followRequestAccepted: "关注请求已通过"
|
||||
groupInvited: "加入群组邀请"
|
||||
app: "关联应用的通知"
|
||||
_deck:
|
||||
|
@ -1,19 +1,20 @@
|
||||
---
|
||||
_lang_: "繁體中文"
|
||||
headlineMisskey: "貼文連繫網絡"
|
||||
introMisskey: "歡迎! Misskey是一個開源且去中心化的社群網絡。\n通過「貼文」分享周邊新鮮事,並告訴其他人您的想法!📡\n透過「情感」功能,對大家的貼文表達情感!👍\n一起來探索這個新的世界吧!🚀"
|
||||
headlineMisskey: "貼文連繫網路"
|
||||
introMisskey: "歡迎! Misskey是一個開放原始碼且去中心化的社群網路。\n透過「貼文」分享周邊新鮮事,並告訴其他人您的想法!📡\n透過「情感」功能,對大家的貼文表達情感!👍\n一起來探索這個新的世界吧!🚀"
|
||||
monthAndDay: "{month}月 {day}日"
|
||||
search: "搜尋"
|
||||
notifications: "通知"
|
||||
username: "使用者名稱"
|
||||
password: "密碼"
|
||||
forgotPassword: "忘記密碼"
|
||||
fetchingAsApObject: "從聯邦宇宙取得中..."
|
||||
ok: "OK"
|
||||
gotIt: "知道了"
|
||||
cancel: "取消"
|
||||
enterUsername: "輸入使用者名稱"
|
||||
renotedBy: "{user} 轉發了"
|
||||
noNotes: "貼文不可用。"
|
||||
renotedBy: "{user} 轉傳了"
|
||||
noNotes: "無貼文。"
|
||||
noNotifications: "沒有通知"
|
||||
instance: "實例"
|
||||
settings: "設定"
|
||||
@ -46,8 +47,8 @@ deleteAndEdit: "刪除並編輯"
|
||||
deleteAndEditConfirm: "要刪除並再次編輯嗎?此貼文的所有情感、轉發和回覆也將會消失。"
|
||||
addToList: "加入至清單"
|
||||
sendMessage: "發送訊息"
|
||||
copyUsername: "複製用戶名"
|
||||
searchUser: "搜尋用戶"
|
||||
copyUsername: "複製使用者名稱"
|
||||
searchUser: "搜尋使用者"
|
||||
reply: "回覆"
|
||||
loadMore: "載入更多"
|
||||
showMore: "載入更多"
|
||||
@ -92,9 +93,9 @@ followRequestPending: "追隨許可批准中"
|
||||
enterEmoji: "輸入表情符號"
|
||||
renote: "轉發"
|
||||
unrenote: "取消轉發"
|
||||
renoted: "轉發成功"
|
||||
renoted: "轉傳成功"
|
||||
cantRenote: "無法轉發此貼文。"
|
||||
cantReRenote: "無法轉發之前已經轉發過的內容。"
|
||||
cantReRenote: "無法轉傳之前已經轉傳過的內容。"
|
||||
quote: "引用"
|
||||
pinnedNote: "已置頂的貼文"
|
||||
pinned: "置頂"
|
||||
@ -278,6 +279,7 @@ emptyDrive: "雲端硬碟為空"
|
||||
emptyFolder: "資料夾為空"
|
||||
unableToDelete: "無法刪除"
|
||||
inputNewFileName: "輸入檔案名稱"
|
||||
inputNewDescription: "請輸入新標題 "
|
||||
inputNewFolderName: "輸入新資料夾的名稱"
|
||||
circularReferenceFolder: "目標文件夾是您要移動的文件夾的子文件夾。"
|
||||
hasChildFilesOrFolders: "此文件夾不是空的,無法刪除。"
|
||||
@ -309,8 +311,8 @@ monthX: "{month}月"
|
||||
yearX: "{year}年"
|
||||
pages: "頁面"
|
||||
integration: "整合"
|
||||
connectSerice: "連線"
|
||||
disconnectSerice: "中斷連線"
|
||||
connectService: "己連結"
|
||||
disconnectService: "己斷開 "
|
||||
enableLocalTimeline: "開啟本地時間軸"
|
||||
enableGlobalTimeline: "啟用公開時間軸"
|
||||
disablingTimelinesInfo: "即使您關閉了時間線功能,管理員和協調人仍可以繼續使用,以方便您。"
|
||||
@ -324,6 +326,7 @@ driveCapacityPerRemoteAccount: "每個非本地用戶的雲端容量"
|
||||
inMb: "以Mbps為單位"
|
||||
iconUrl: "圖像URL"
|
||||
bannerUrl: "橫幅圖像URL"
|
||||
backgroundImageUrl: "背景圖片的來源網址 "
|
||||
basicInfo: "基本資訊"
|
||||
pinnedUsers: "置頂用戶"
|
||||
pinnedUsersDescription: "在「發現」頁面中使用換行標記想要置頂的使用者。"
|
||||
@ -475,7 +478,9 @@ objectStorage: "Object Storage (物件儲存)"
|
||||
useObjectStorage: "使用Object Storage"
|
||||
objectStorageBaseUrl: "Base URL"
|
||||
objectStorageBucket: "儲存空間(Bucket)"
|
||||
objectStorageBucketDesc: "請指定您正在使用的服務的存儲桶名稱。 "
|
||||
objectStoragePrefix: "前綴"
|
||||
objectStoragePrefixDesc: "它存儲在此前綴目錄下。"
|
||||
objectStorageEndpoint: "端點(Endpoint)"
|
||||
objectStorageEndpointDesc: "如要使用AWS S3,請留空。否則請依照你使用的服務商的說明書進行設定,以'<host>'或 '<host>:<port>'的形式設定端點(Endpoint)。"
|
||||
objectStorageRegion: "地域(Region)"
|
||||
@ -518,7 +523,6 @@ removeAllFollowing: "解除所有追蹤"
|
||||
removeAllFollowingDescription: "解除{host}所有的追蹤。在實例不再存在時執行。"
|
||||
userSuspended: "該使用者已被停用"
|
||||
userSilenced: "該用戶已被禁言。"
|
||||
sidebar: "側邊列"
|
||||
divider: "分割線"
|
||||
addItem: "新增項目"
|
||||
rooms: "房間"
|
||||
@ -538,6 +542,8 @@ disablePlayer: "關閉播放器"
|
||||
expandTweet: "展開推文"
|
||||
themeEditor: "主題編輯器"
|
||||
description: "描述"
|
||||
describeFile: "添加標題 "
|
||||
enterFileDescription: "輸入標題 "
|
||||
author: "作者"
|
||||
leaveConfirm: "有未保存的更改。要放棄嗎?"
|
||||
manage: "管理"
|
||||
@ -731,11 +737,31 @@ switch: "切換"
|
||||
noMaintainerInformationWarning: "尚未設定管理員信息。"
|
||||
noBotProtectionWarning: "尚未設定Bot防護。"
|
||||
configure: "設定"
|
||||
postToGallery: "發佈到相簿"
|
||||
gallery: "相簿"
|
||||
recentPosts: "最新貼文"
|
||||
popularPosts: "熱門的貼文"
|
||||
ads: "廣告"
|
||||
expiration: "期限"
|
||||
memo: "備忘錄"
|
||||
priority: "優先級"
|
||||
high: "高"
|
||||
middle: "中"
|
||||
low: "低"
|
||||
emailNotConfiguredWarning: "沒有設定電子郵件地址"
|
||||
ratio: "%"
|
||||
global: "公開"
|
||||
_ad:
|
||||
back: "返回"
|
||||
reduceFrequencyOfThisAd: "降低此廣告的頻率 "
|
||||
_forgotPassword:
|
||||
enterEmail: "請輸入您的帳戶註冊的電子郵件地址。 密碼重置連結將被發送到該電子郵件地址。"
|
||||
ifNoEmail: "如果您還沒有註冊您的電子郵件地址,請聯繫管理員。 "
|
||||
contactAdmin: "此實例不支持電子郵件,請聯繫您的管理員重置您的密碼。 "
|
||||
_gallery:
|
||||
my: "我的貼文"
|
||||
liked: "喜歡的貼文"
|
||||
like: "讚"
|
||||
unlike: "收回喜歡"
|
||||
_email:
|
||||
_follow:
|
||||
@ -776,6 +802,7 @@ _mfm:
|
||||
url: "URL"
|
||||
urlDescription: "可以展示URL位址。"
|
||||
link: "鏈接"
|
||||
linkDescription: "您可以將特定範圍的文章與 URL 相關聯。 "
|
||||
bold: "粗體"
|
||||
small: "縮小"
|
||||
center: "置中"
|
||||
@ -786,7 +813,9 @@ _mfm:
|
||||
blockMath: "數學公式(方塊)"
|
||||
quote: "引用"
|
||||
emoji: "自訂表情符號"
|
||||
emojiDescription: "您可以通過將自定義表情符號名稱括在冒號中來顯示自定義表情符號。 "
|
||||
search: "搜尋"
|
||||
searchDescription: "您可以顯示所輸入的搜索框。"
|
||||
flip: "翻轉"
|
||||
flipDescription: "將內容上下或左右翻轉。"
|
||||
jelly: "動畫(果凍)"
|
||||
@ -855,9 +884,7 @@ _channel:
|
||||
following: "關注中"
|
||||
usersCount: "有{n}人參與"
|
||||
notesCount: "有{n}個貼文"
|
||||
_sidebar:
|
||||
full: "全部"
|
||||
icon: "大頭貼"
|
||||
_menuDisplay:
|
||||
hide: "隱藏"
|
||||
_wordMute:
|
||||
muteWords: "加入靜音文字"
|
||||
@ -879,17 +906,27 @@ _theme:
|
||||
constant: "常數"
|
||||
defaultValue: "預設值"
|
||||
color: "顏色"
|
||||
refProp: "查看屬性 "
|
||||
key: "按鍵"
|
||||
func: "函数"
|
||||
funcKind: "功能類型"
|
||||
argument: "參數"
|
||||
basedProp: "要基於的屬性的名稱 "
|
||||
alpha: "透明度"
|
||||
darken: "暗度"
|
||||
lighten: "亮度"
|
||||
keys:
|
||||
accent: "重點色彩"
|
||||
bg: "背景"
|
||||
fg: "文本"
|
||||
focus: "聚焦"
|
||||
indicator: "指標"
|
||||
panel: "面板"
|
||||
shadow: "陰影"
|
||||
header: "標題"
|
||||
navBg: "側邊欄的背景 "
|
||||
navFg: "側邊欄的文字"
|
||||
navHoverFg: "側邊欄文字(懸停) "
|
||||
navActive: "側邊欄文本 (活動)"
|
||||
navIndicator: "側邊欄指示符"
|
||||
link: "鏈接"
|
||||
@ -971,6 +1008,7 @@ _tutorial:
|
||||
_2fa:
|
||||
alreadyRegistered: "此設備已經被註冊過了"
|
||||
registerDevice: "註冊裝置"
|
||||
registerKey: "註冊鍵"
|
||||
step1: "首先,在您的設備上安裝二步驗證程式,例如{a}或{b}。"
|
||||
step2: "然後,掃描螢幕上的QR code。"
|
||||
_permissions:
|
||||
@ -1040,6 +1078,7 @@ _widgets:
|
||||
button: "按鈕"
|
||||
onlineUsers: "線上的用戶"
|
||||
jobQueue: "佇列"
|
||||
serverMetric: "服務器指標 "
|
||||
_cw:
|
||||
hide: "隱藏"
|
||||
show: "瀏覽更多"
|
||||
@ -1053,6 +1092,7 @@ _poll:
|
||||
expiration: "期限"
|
||||
infinite: "無期限"
|
||||
at: "結束時間"
|
||||
after: "進度指定 "
|
||||
deadlineDate: "截止日期"
|
||||
deadlineTime: "小時"
|
||||
duration: "時長"
|
||||
@ -1067,6 +1107,7 @@ _poll:
|
||||
remainingSeconds: "{s}秒後截止"
|
||||
_visibility:
|
||||
public: "公開"
|
||||
publicDescription: "發布給所有用戶 "
|
||||
home: "首頁"
|
||||
followers: "追隨者"
|
||||
specified: "指定使用者"
|
||||
@ -1180,6 +1221,7 @@ _rooms:
|
||||
cube: "立方體"
|
||||
tv: "電視"
|
||||
pinguin: "企鵝蠟像"
|
||||
rubik-cube: "魔術方塊"
|
||||
poster-h: "海報(橫向)"
|
||||
poster-v: "海報(直向)"
|
||||
sofa: " 沙發"
|
||||
@ -1242,6 +1284,7 @@ _pages:
|
||||
post: "發佈窗口"
|
||||
_post:
|
||||
text: "内容"
|
||||
attachCanvasImage: "附加相簿圖像 "
|
||||
canvasId: "畫布ID"
|
||||
textInput: "插入字串"
|
||||
_textInput:
|
||||
@ -1266,6 +1309,7 @@ _pages:
|
||||
note: "嵌式貼文"
|
||||
_note:
|
||||
id: "貼文ID"
|
||||
idDescription: "您也可以粘貼筆記 URL 並進行設置。 "
|
||||
detailed: "顯示詳細內容"
|
||||
switch: "開關"
|
||||
_switch:
|
||||
@ -1282,12 +1326,15 @@ _pages:
|
||||
colored: "彩色"
|
||||
action: "按下按鈕後發生的行為"
|
||||
_action:
|
||||
dialog: "顯示對話框 "
|
||||
_dialog:
|
||||
content: "内容"
|
||||
resetRandom: "重設亂數"
|
||||
pushEvent: "發送事件"
|
||||
_pushEvent:
|
||||
event: "事件名稱"
|
||||
message: "按下時顯示的消息 "
|
||||
variable: "要發送的變數"
|
||||
no-variable: "沒有"
|
||||
callAiScript: "調用AiScript"
|
||||
_callAiScript:
|
||||
@ -1296,6 +1343,7 @@ _pages:
|
||||
_radioButton:
|
||||
name: "變數名稱"
|
||||
title: "標題"
|
||||
values: "由換行符分隔的選項"
|
||||
default: "預設值"
|
||||
script:
|
||||
categories:
|
||||
@ -1313,6 +1361,8 @@ _pages:
|
||||
text: "字串"
|
||||
multiLineText: "字串(多行)"
|
||||
textList: "字串串列"
|
||||
_textList:
|
||||
info: "請分開每個換行符 "
|
||||
strLen: "字串長度"
|
||||
_strLen:
|
||||
arg1: "字串"
|
||||
@ -1323,6 +1373,8 @@ _pages:
|
||||
strReplace: "替換字串"
|
||||
_strReplace:
|
||||
arg1: "字串"
|
||||
arg2: "替換前"
|
||||
arg3: "替換後"
|
||||
strReverse: "倒轉字串"
|
||||
_strReverse:
|
||||
arg1: "字串"
|
||||
@ -1389,6 +1441,7 @@ _pages:
|
||||
_if:
|
||||
arg1: "如果"
|
||||
arg2: "如果"
|
||||
arg3: "除此以外 "
|
||||
not: "否"
|
||||
_not:
|
||||
arg1: "否"
|
||||
@ -1399,13 +1452,17 @@ _pages:
|
||||
_rannum:
|
||||
arg1: "下限"
|
||||
arg2: "上限"
|
||||
randomPick: "從列表中隨機選擇 "
|
||||
_randomPick:
|
||||
arg1: "清單"
|
||||
dailyRandom: "隨機(使用者每日變化 )"
|
||||
_dailyRandom:
|
||||
arg1: "機率"
|
||||
dailyRannum: "亂數(使用者每日變化)"
|
||||
_dailyRannum:
|
||||
arg1: "下限"
|
||||
arg2: "上限"
|
||||
dailyRandomPick: "從列表中隨機選擇(使用者每日變化 ) "
|
||||
_dailyRandomPick:
|
||||
arg1: "清單"
|
||||
seedRandom: "隨機抽選種子碼"
|
||||
@ -1444,7 +1501,10 @@ _pages:
|
||||
aiScriptVar: "AiScript的變數"
|
||||
fn: "函数"
|
||||
_fn:
|
||||
slots: "欄位"
|
||||
slots-info: "用換行符分隔每個欄位"
|
||||
arg1: "輸出"
|
||||
for: "重複 "
|
||||
_for:
|
||||
arg1: "重複次數"
|
||||
arg2: "處理"
|
||||
@ -1454,13 +1514,16 @@ _pages:
|
||||
boolean: "標記"
|
||||
array: "清單"
|
||||
stringArray: "字串列表"
|
||||
emptySlot: "空欄位"
|
||||
enviromentVariables: "環境變數"
|
||||
pageVariables: "頁面元素"
|
||||
argVariables: "輸入欄位"
|
||||
_relayStatus:
|
||||
requesting: "等待核准"
|
||||
accepted: "已通過核准"
|
||||
rejected: "已拒絕"
|
||||
_notification:
|
||||
fileUploaded: "上傳檔案成功。"
|
||||
youGotMention: "{name}提及到您"
|
||||
youGotReply: "{name}回覆了您"
|
||||
youGotQuote: "{name}引用了您"
|
||||
|
16
migration/1621479946000-add-note-indexes.ts
Normal file
16
migration/1621479946000-add-note-indexes.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||
|
||||
export class addNoteIndexes1621479946000 implements MigrationInterface {
|
||||
name = 'addNoteIndexes1621479946000'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE INDEX "IDX_NOTE_MENTIONS" ON "note" USING gin ("mentions")`, undefined);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_NOTE_VISIBLE_USER_IDS" ON "note" USING gin ("visibleUserIds")`, undefined);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP INDEX "IDX_NOTE_MENTIONS"`, undefined);
|
||||
await queryRunner.query(`DROP INDEX "IDX_NOTE_VISIBLE_USER_IDS"`, undefined);
|
||||
}
|
||||
|
||||
}
|
13
migration/1622679304522-user-profile-description-length.ts
Normal file
13
migration/1622679304522-user-profile-description-length.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||
|
||||
export class userProfileDescriptionLength1622679304522 implements MigrationInterface {
|
||||
name = 'userProfileDescriptionLength1622679304522';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "description" TYPE character varying(2048)`, undefined);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "description" TYPE character varying(1024)`, undefined);
|
||||
}
|
||||
}
|
12
migration/1622681548499-log-message-length.ts
Normal file
12
migration/1622681548499-log-message-length.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||
|
||||
export class logMessageLength1622681548499 implements MigrationInterface {
|
||||
name = 'logMessageLength1622681548499';
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "log" ALTER COLUMN "message" TYPE character varying(2048)`, undefined);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "log" ALTER COLUMN "message" TYPE character varying(1024)`, undefined);
|
||||
}
|
||||
}
|
190
package.json
190
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
||||
"version": "12.81.0",
|
||||
"version": "12.84.2",
|
||||
"codename": "indigo",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -31,116 +31,114 @@
|
||||
},
|
||||
"resolutions": {
|
||||
"chokidar": "^3.3.1",
|
||||
"constantinople": "^4.0.1",
|
||||
"jsonld/rdf-canonize/node-forge": "0.10.0",
|
||||
"lodash": "^4.17.20"
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-runtime": "7.13.15",
|
||||
"@babel/plugin-transform-runtime": "7.14.5",
|
||||
"@elastic/elasticsearch": "7.11.0",
|
||||
"@koa/cors": "3.1.0",
|
||||
"@koa/multer": "3.0.0",
|
||||
"@koa/router": "9.0.1",
|
||||
"@sentry/browser": "5.29.2",
|
||||
"@sentry/tracing": "5.29.2",
|
||||
"@sinonjs/fake-timers": "7.0.5",
|
||||
"@sinonjs/fake-timers": "7.1.2",
|
||||
"@syuilo/aiscript": "0.11.1",
|
||||
"@types/bcryptjs": "2.4.2",
|
||||
"@types/bull": "3.15.1",
|
||||
"@types/cbor": "5.0.1",
|
||||
"@types/bull": "3.15.2",
|
||||
"@types/cbor": "6.0.0",
|
||||
"@types/dateformat": "3.0.1",
|
||||
"@types/escape-regexp": "0.0.0",
|
||||
"@types/glob": "7.1.3",
|
||||
"@types/gulp": "4.0.8",
|
||||
"@types/gulp-rename": "2.0.0",
|
||||
"@types/is-url": "1.2.28",
|
||||
"@types/js-yaml": "4.0.1",
|
||||
"@types/jsdom": "16.2.10",
|
||||
"@types/jsonld": "1.5.5",
|
||||
"@types/katex": "0.11.0",
|
||||
"@types/koa": "2.13.1",
|
||||
"@types/koa-bodyparser": "4.3.0",
|
||||
"@types/koa-cors": "0.0.0",
|
||||
"@types/koa-favicon": "2.0.19",
|
||||
"@types/glob": "7.1.4",
|
||||
"@types/gulp": "4.0.9",
|
||||
"@types/gulp-rename": "2.0.1",
|
||||
"@types/is-url": "1.2.30",
|
||||
"@types/js-yaml": "4.0.2",
|
||||
"@types/jsdom": "16.2.13",
|
||||
"@types/jsonld": "1.5.6",
|
||||
"@types/katex": "0.11.1",
|
||||
"@types/koa": "2.13.4",
|
||||
"@types/koa-bodyparser": "4.3.2",
|
||||
"@types/koa-cors": "0.0.1",
|
||||
"@types/koa-favicon": "2.0.21",
|
||||
"@types/koa-logger": "3.1.1",
|
||||
"@types/koa-mount": "4.0.0",
|
||||
"@types/koa-send": "4.1.2",
|
||||
"@types/koa-views": "2.0.4",
|
||||
"@types/koa__cors": "3.0.2",
|
||||
"@types/koa__multer": "2.0.2",
|
||||
"@types/koa__router": "8.0.4",
|
||||
"@types/markdown-it": "12.0.1",
|
||||
"@types/matter-js": "0.14.11",
|
||||
"@types/mocha": "8.2.2",
|
||||
"@types/node": "14.14.41",
|
||||
"@types/node-fetch": "2.5.10",
|
||||
"@types/nodemailer": "6.4.1",
|
||||
"@types/koa-send": "4.1.3",
|
||||
"@types/koa-views": "7.0.0",
|
||||
"@types/koa__cors": "3.0.3",
|
||||
"@types/koa__multer": "2.0.3",
|
||||
"@types/koa__router": "8.0.7",
|
||||
"@types/markdown-it": "12.0.3",
|
||||
"@types/matter-js": "0.17.3",
|
||||
"@types/mocha": "8.2.3",
|
||||
"@types/node": "16.3.3",
|
||||
"@types/node-fetch": "2.5.11",
|
||||
"@types/nodemailer": "6.4.4",
|
||||
"@types/nprogress": "0.2.0",
|
||||
"@types/oauth": "0.9.1",
|
||||
"@types/parse5": "6.0.0",
|
||||
"@types/parse5": "6.0.1",
|
||||
"@types/parsimmon": "1.10.6",
|
||||
"@types/portscanner": "2.1.0",
|
||||
"@types/pug": "2.0.4",
|
||||
"@types/portscanner": "2.1.1",
|
||||
"@types/pug": "2.0.5",
|
||||
"@types/punycode": "2.1.0",
|
||||
"@types/qrcode": "1.4.0",
|
||||
"@types/qrcode": "1.4.1",
|
||||
"@types/random-seed": "0.3.3",
|
||||
"@types/ratelimiter": "3.4.1",
|
||||
"@types/redis": "2.8.28",
|
||||
"@types/rename": "1.0.2",
|
||||
"@types/ratelimiter": "3.4.2",
|
||||
"@types/redis": "2.8.31",
|
||||
"@types/rename": "1.0.4",
|
||||
"@types/request-stats": "3.0.0",
|
||||
"@types/rimraf": "3.0.0",
|
||||
"@types/rimraf": "3.0.1",
|
||||
"@types/seedrandom": "2.4.28",
|
||||
"@types/sharp": "0.28.0",
|
||||
"@types/sinonjs__fake-timers": "6.0.2",
|
||||
"@types/speakeasy": "2.0.5",
|
||||
"@types/sharp": "0.28.4",
|
||||
"@types/sinonjs__fake-timers": "6.0.3",
|
||||
"@types/speakeasy": "2.0.6",
|
||||
"@types/throttle-debounce": "2.1.0",
|
||||
"@types/tinycolor2": "1.4.2",
|
||||
"@types/tmp": "0.2.0",
|
||||
"@types/uuid": "8.3.0",
|
||||
"@types/web-push": "3.3.0",
|
||||
"@types/tinycolor2": "1.4.3",
|
||||
"@types/tmp": "0.2.1",
|
||||
"@types/uuid": "8.3.1",
|
||||
"@types/web-push": "3.3.2",
|
||||
"@types/webpack": "5.28.0",
|
||||
"@types/webpack-stream": "3.2.12",
|
||||
"@types/websocket": "1.0.2",
|
||||
"@types/ws": "7.4.1",
|
||||
"@typescript-eslint/parser": "4.22.0",
|
||||
"@vue/compiler-sfc": "3.0.11",
|
||||
"@types/websocket": "1.0.3",
|
||||
"@types/ws": "7.4.6",
|
||||
"@typescript-eslint/parser": "4.28.3",
|
||||
"@vue/compiler-sfc": "3.1.5",
|
||||
"abort-controller": "3.0.0",
|
||||
"apexcharts": "3.26.1",
|
||||
"apexcharts": "3.27.2",
|
||||
"autobind-decorator": "2.4.0",
|
||||
"autosize": "4.0.2",
|
||||
"autosize": "4.0.4",
|
||||
"autwh": "0.1.0",
|
||||
"aws-sdk": "2.892.0",
|
||||
"aws-sdk": "2.948.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
"blurhash": "1.1.3",
|
||||
"broadcast-channel": "3.5.3",
|
||||
"bull": "3.22.3",
|
||||
"broadcast-channel": "3.7.0",
|
||||
"bull": "3.26.0",
|
||||
"cafy": "15.2.1",
|
||||
"cbor": "7.0.5",
|
||||
"cbor": "7.0.6",
|
||||
"chalk": "4.1.1",
|
||||
"chart.js": "2.9.4",
|
||||
"cli-highlight": "2.1.11",
|
||||
"commander": "7.2.0",
|
||||
"concurrently": "6.0.2",
|
||||
"concurrently": "6.2.0",
|
||||
"content-disposition": "0.5.3",
|
||||
"core-js": "3.11.0",
|
||||
"core-js": "3.15.2",
|
||||
"crc-32": "1.2.0",
|
||||
"css-loader": "5.2.4",
|
||||
"cssnano": "5.0.1",
|
||||
"css-loader": "6.0.0",
|
||||
"cssnano": "5.0.6",
|
||||
"dateformat": "4.5.1",
|
||||
"diskusage": "1.1.3",
|
||||
"escape-regexp": "0.0.1",
|
||||
"eslint": "7.25.0",
|
||||
"eslint-plugin-vue": "7.9.0",
|
||||
"eslint": "7.30.0",
|
||||
"eslint-plugin-vue": "7.13.0",
|
||||
"eventemitter3": "4.0.7",
|
||||
"feed": "4.2.2",
|
||||
"file-type": "16.3.0",
|
||||
"file-type": "16.5.1",
|
||||
"fluent-ffmpeg": "2.1.2",
|
||||
"glob": "7.1.6",
|
||||
"glob": "7.1.7",
|
||||
"got": "11.8.2",
|
||||
"gulp": "4.0.2",
|
||||
"gulp-cssnano": "2.1.3",
|
||||
"gulp-rename": "2.0.0",
|
||||
"gulp-replace": "1.1.1",
|
||||
"gulp-replace": "1.1.3",
|
||||
"gulp-terser": "2.0.1",
|
||||
"gulp-tslint": "8.1.4",
|
||||
"hard-source-webpack-plugin": "0.13.1",
|
||||
@ -148,17 +146,17 @@
|
||||
"http-proxy-agent": "4.0.1",
|
||||
"http-signature": "1.3.5",
|
||||
"https-proxy-agent": "5.0.0",
|
||||
"idb-keyval": "5.0.5",
|
||||
"idb-keyval": "5.0.6",
|
||||
"insert-text-at-cursor": "0.3.0",
|
||||
"is-root": "2.1.0",
|
||||
"is-svg": "4.3.1",
|
||||
"js-yaml": "4.1.0",
|
||||
"jsdom": "16.5.3",
|
||||
"jsdom": "16.6.0",
|
||||
"json5": "2.2.0",
|
||||
"json5-loader": "4.0.1",
|
||||
"jsonld": "4.0.1",
|
||||
"jsonld": "5.2.0",
|
||||
"jsrsasign": "8.0.20",
|
||||
"katex": "0.13.3",
|
||||
"katex": "0.13.11",
|
||||
"koa": "2.13.1",
|
||||
"koa-bodyparser": "4.3.0",
|
||||
"koa-favicon": "2.1.0",
|
||||
@ -170,26 +168,27 @@
|
||||
"koa-views": "7.0.1",
|
||||
"langmap": "0.0.16",
|
||||
"lookup-dns-cache": "2.1.0",
|
||||
"markdown-it": "12.0.6",
|
||||
"markdown-it": "12.1.0",
|
||||
"markdown-it-anchor": "7.1.0",
|
||||
"matter-js": "0.17.1",
|
||||
"mfm-js": "0.16.3",
|
||||
"mocha": "8.3.2",
|
||||
"mfm-js": "0.19.0",
|
||||
"misskey-js": "0.0.6",
|
||||
"mocha": "8.4.0",
|
||||
"moji": "0.5.1",
|
||||
"ms": "2.1.3",
|
||||
"multer": "1.4.2",
|
||||
"nested-property": "4.0.0",
|
||||
"node-fetch": "2.6.1",
|
||||
"nodemailer": "6.5.0",
|
||||
"nodemailer": "6.6.3",
|
||||
"object-assign-deep": "0.4.0",
|
||||
"os-utils": "0.0.14",
|
||||
"parse5": "6.0.1",
|
||||
"pg": "8.6.0",
|
||||
"portscanner": "2.2.0",
|
||||
"postcss": "8.2.12",
|
||||
"postcss-loader": "5.2.0",
|
||||
"prismjs": "1.23.0",
|
||||
"probe-image-size": "7.1.0",
|
||||
"postcss": "8.3.5",
|
||||
"postcss-loader": "6.1.1",
|
||||
"prismjs": "1.24.1",
|
||||
"probe-image-size": "7.2.1",
|
||||
"promise-limit": "2.7.0",
|
||||
"promise-sequential": "1.1.1",
|
||||
"pug": "3.0.2",
|
||||
@ -198,7 +197,7 @@
|
||||
"qrcode": "1.4.4",
|
||||
"random-seed": "0.3.0",
|
||||
"ratelimiter": "3.4.1",
|
||||
"re2": "1.15.9",
|
||||
"re2": "1.16.0",
|
||||
"reconnecting-websocket": "4.4.0",
|
||||
"redis": "3.1.2",
|
||||
"redis-lock": "0.1.4",
|
||||
@ -210,48 +209,49 @@
|
||||
"rimraf": "3.0.2",
|
||||
"rndstr": "1.0.0",
|
||||
"s-age": "1.1.2",
|
||||
"sass": "1.32.11",
|
||||
"sass-loader": "11.0.1",
|
||||
"sass": "1.35.2",
|
||||
"sass-loader": "12.1.0",
|
||||
"seedrandom": "3.0.5",
|
||||
"sharp": "0.28.1",
|
||||
"sharp": "0.28.3",
|
||||
"speakeasy": "2.0.0",
|
||||
"stringz": "2.1.0",
|
||||
"style-loader": "2.0.0",
|
||||
"style-loader": "3.1.0",
|
||||
"summaly": "2.4.0",
|
||||
"syslog-pro": "1.0.0",
|
||||
"systeminformation": "5.6.12",
|
||||
"systeminformation": "5.7.7",
|
||||
"syuilo-password-strength": "0.0.1",
|
||||
"textarea-caret": "3.1.0",
|
||||
"three": "0.117.1",
|
||||
"throttle-debounce": "3.0.1",
|
||||
"tinycolor2": "1.4.2",
|
||||
"tmp": "0.2.1",
|
||||
"ts-loader": "9.1.1",
|
||||
"ts-node": "9.1.1",
|
||||
"tsc-alias": "1.2.10",
|
||||
"tsconfig-paths": "3.9.0",
|
||||
"ts-loader": "9.2.3",
|
||||
"ts-node": "10.1.0",
|
||||
"tsc-alias": "1.3.7",
|
||||
"tsconfig-paths": "3.10.1",
|
||||
"tslint": "6.1.3",
|
||||
"tslint-sonarts": "1.9.0",
|
||||
"twemoji-parser": "13.1.0",
|
||||
"typeorm": "0.2.32",
|
||||
"typescript": "4.2.4",
|
||||
"typescript": "4.3.5",
|
||||
"ulid": "2.3.0",
|
||||
"uuid": "8.3.2",
|
||||
"v-debounce": "0.1.2",
|
||||
"vanilla-tilt": "1.7.0",
|
||||
"vue": "3.0.11",
|
||||
"vue": "3.1.5",
|
||||
"vue-color": "2.8.1",
|
||||
"vue-json-pretty": "1.7.1",
|
||||
"vue-loader": "16.1.2",
|
||||
"vue-json-pretty": "1.8.1",
|
||||
"vue-loader": "16.3.1",
|
||||
"vue-prism-editor": "2.0.0-alpha.2",
|
||||
"vue-router": "4.0.5",
|
||||
"vue-style-loader": "4.1.3",
|
||||
"vue-svg-loader": "0.17.0-beta.2",
|
||||
"vuedraggable": "4.0.1",
|
||||
"web-push": "3.4.4",
|
||||
"webpack": "5.35.1",
|
||||
"webpack-cli": "4.6.0",
|
||||
"web-push": "3.4.5",
|
||||
"webpack": "5.45.1",
|
||||
"webpack-cli": "4.7.2",
|
||||
"websocket": "1.0.34",
|
||||
"ws": "7.4.5",
|
||||
"ws": "7.5.3",
|
||||
"xev": "2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -8,6 +8,8 @@ import { unisonReload } from '@client/scripts/unison-reload';
|
||||
type Account = {
|
||||
id: string;
|
||||
token: string;
|
||||
isModerator: boolean;
|
||||
isAdmin: boolean;
|
||||
};
|
||||
|
||||
const data = localStorage.getItem('account');
|
||||
@ -45,7 +47,7 @@ function fetchAccount(token): Promise<Account> {
|
||||
})
|
||||
.then(res => {
|
||||
// When failed to authenticate user
|
||||
if (res.status !== 200 && res.status < 500) {
|
||||
if (res.status >= 400 && res.status < 500) {
|
||||
return signout();
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,8 @@
|
||||
:cy="5 - (Math.cos(angle) * (5 - graduationsPadding))"
|
||||
:r="i % 5 == 0 ? 0.125 : 0.05"
|
||||
:fill="i % 5 == 0 ? majorGraduationColor : minorGraduationColor"
|
||||
:key="i"/>
|
||||
:key="i"
|
||||
/>
|
||||
|
||||
<line
|
||||
:x1="5 - (Math.sin(sAngle) * (sHandLengthRatio * handsTailLength))"
|
||||
@ -13,7 +14,9 @@
|
||||
:x2="5 + (Math.sin(sAngle) * ((sHandLengthRatio * 5) - handsPadding))"
|
||||
:y2="5 - (Math.cos(sAngle) * ((sHandLengthRatio * 5) - handsPadding))"
|
||||
:stroke="sHandColor"
|
||||
stroke-width="0.05"/>
|
||||
:stroke-width="thickness / 2"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
|
||||
<line
|
||||
:x1="5 - (Math.sin(mAngle) * (mHandLengthRatio * handsTailLength))"
|
||||
@ -21,7 +24,9 @@
|
||||
:x2="5 + (Math.sin(mAngle) * ((mHandLengthRatio * 5) - handsPadding))"
|
||||
:y2="5 - (Math.cos(mAngle) * ((mHandLengthRatio * 5) - handsPadding))"
|
||||
:stroke="mHandColor"
|
||||
stroke-width="0.1"/>
|
||||
:stroke-width="thickness"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
|
||||
<line
|
||||
:x1="5 - (Math.sin(hAngle) * (hHandLengthRatio * handsTailLength))"
|
||||
@ -29,16 +34,24 @@
|
||||
:x2="5 + (Math.sin(hAngle) * ((hHandLengthRatio * 5) - handsPadding))"
|
||||
:y2="5 - (Math.cos(hAngle) * ((hHandLengthRatio * 5) - handsPadding))"
|
||||
:stroke="hHandColor"
|
||||
stroke-width="0.1"/>
|
||||
:stroke-width="thickness"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import * as tinycolor from 'tinycolor2';
|
||||
import * as os from '@client/os';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
thickness: {
|
||||
type: Number,
|
||||
default: 0.1
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
now: new Date(),
|
||||
|
@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, h, TransitionGroup } from 'vue';
|
||||
import { defineComponent, h, PropType, TransitionGroup } from 'vue';
|
||||
import MkAd from '@client/components/global/ad.vue';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
items: {
|
||||
type: Array,
|
||||
type: Array as PropType<{ id: string; createdAt: string; _shouldInsertAd_: boolean; }[]>,
|
||||
required: true,
|
||||
},
|
||||
direction: {
|
||||
|
@ -87,6 +87,10 @@ export default defineComponent({
|
||||
text: this.file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
|
||||
icon: this.file.isSensitive ? 'fas fa-eye' : 'fas fa-eye-slash',
|
||||
action: this.toggleSensitive
|
||||
}, {
|
||||
text: this.$ts.describeFile,
|
||||
icon: 'fas fa-i-cursor',
|
||||
action: this.describe
|
||||
}, null, {
|
||||
text: this.$ts.copyUrl,
|
||||
icon: 'fas fa-link',
|
||||
@ -150,6 +154,26 @@ export default defineComponent({
|
||||
});
|
||||
},
|
||||
|
||||
describe() {
|
||||
os.popup(import('@client/components/media-caption.vue'), {
|
||||
title: this.$ts.describeFile,
|
||||
input: {
|
||||
placeholder: this.$ts.inputNewDescription,
|
||||
default: this.file.comment !== null ? this.file.comment : '',
|
||||
},
|
||||
image: this.file
|
||||
}, {
|
||||
done: result => {
|
||||
if (!result || result.canceled) return;
|
||||
let comment = result.result;
|
||||
os.api('drive/files/update', {
|
||||
fileId: this.file.id,
|
||||
comment: comment.length == 0 ? null : comment
|
||||
});
|
||||
}
|
||||
}, 'closed');
|
||||
},
|
||||
|
||||
toggleSensitive() {
|
||||
os.api('drive/files/update', {
|
||||
fileId: this.file.id,
|
||||
|
@ -139,7 +139,7 @@ export default defineComponent({
|
||||
});
|
||||
}
|
||||
|
||||
this.connection = os.stream.useSharedConnection('drive');
|
||||
this.connection = os.stream.useChannel('drive');
|
||||
|
||||
this.connection.on('fileCreated', this.onStreamDriveFileCreated);
|
||||
this.connection.on('fileUpdated', this.onStreamDriveFileUpdated);
|
||||
@ -301,7 +301,7 @@ export default defineComponent({
|
||||
}
|
||||
}).then(({ canceled, result: url }) => {
|
||||
if (canceled) return;
|
||||
os.api('drive/files/upload_from_url', {
|
||||
os.api('drive/files/upload-from-url', {
|
||||
url: url,
|
||||
folderId: this.folder ? this.folder.id : undefined
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<MkModal ref="modal" :manual-showing="manualShowing" :src="src" @click="$refs.modal.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')">
|
||||
<MkModal ref="modal" :manual-showing="manualShowing" :src="src" :front="true" @click="$refs.modal.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')">
|
||||
<MkEmojiPicker :show-pinned="showPinned" :as-reaction-picker="asReactionPicker" @chosen="chosen" ref="picker"/>
|
||||
</MkModal>
|
||||
</template>
|
||||
|
@ -1,7 +1,5 @@
|
||||
<template>
|
||||
<div class="xfbouadm" v-if="meta" :style="{ backgroundImage: `url(${ meta.backgroundImageUrl })` }">
|
||||
|
||||
</div>
|
||||
<div class="xfbouadm" v-if="meta" :style="{ backgroundImage: `url(${ meta.backgroundImageUrl })` }"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -71,7 +71,7 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.connection = os.stream.useSharedConnection('main');
|
||||
this.connection = os.stream.useChannel('main');
|
||||
|
||||
this.connection.on('follow', this.onFollowChange);
|
||||
this.connection.on('unfollow', this.onFollowChange);
|
||||
|
@ -34,6 +34,10 @@
|
||||
<template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template>
|
||||
<option v-for="item in form[item].enum" :value="item.value" :key="item.value">{{ item.label }}</option>
|
||||
</FormSelect>
|
||||
<FormRadios v-else-if="form[item].type === 'radio'" v-model="values[item]">
|
||||
<template #desc><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template>
|
||||
<option v-for="item in form[item].options" :value="item.value" :key="item.value">{{ item.label }}</option>
|
||||
</FormRadios>
|
||||
<FormRange v-else-if="form[item].type === 'range'" v-model:value="values[item]" :min="form[item].mim" :max="form[item].max" :step="form[item].step">
|
||||
<template #label><span v-text="form[item].label || item"></span><span v-if="form[item].required === false"> ({{ $ts.optional }})</span></template>
|
||||
<template v-if="form[item].description" #desc>{{ form[item].description }}</template>
|
||||
@ -56,6 +60,7 @@ import FormSwitch from './form/switch.vue';
|
||||
import FormSelect from './form/select.vue';
|
||||
import FormRange from './form/range.vue';
|
||||
import FormButton from './form/button.vue';
|
||||
import FormRadios from './form/radios.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -67,6 +72,7 @@ export default defineComponent({
|
||||
FormSelect,
|
||||
FormRange,
|
||||
FormButton,
|
||||
FormRadios,
|
||||
},
|
||||
|
||||
props: {
|
||||
|
@ -27,7 +27,10 @@ export default defineComponent({
|
||||
},
|
||||
render() {
|
||||
const label = this.$slots.desc();
|
||||
const options = this.$slots.default();
|
||||
let options = this.$slots.default();
|
||||
|
||||
// なぜかFragmentになることがあるため
|
||||
if (options.length === 1 && options[0].props == null) options = options[0].children;
|
||||
|
||||
return h('div', {
|
||||
class: 'cnklmpwm _formItem'
|
||||
@ -37,7 +40,7 @@ export default defineComponent({
|
||||
}, label),
|
||||
...options.map(option => h('button', {
|
||||
class: '_button _formPanel _formClickable',
|
||||
key: option.props.value,
|
||||
key: option.key,
|
||||
onClick: () => this.value = option.props.value,
|
||||
}, [h('span', {
|
||||
class: ['check', { checked: this.value === option.props.value }],
|
||||
|
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<span class="eiwwqkts _noSelect" :class="{ cat }" :title="acct(user)" v-if="disableLink" v-user-preview="disablePreview ? undefined : user.id" @click="onClick">
|
||||
<span class="eiwwqkts _noSelect" :class="{ cat, square: $store.state.squareAvatars }" :title="acct(user)" v-if="disableLink" v-user-preview="disablePreview ? undefined : user.id" @click="onClick">
|
||||
<img class="inner" :src="url" decoding="async"/>
|
||||
<MkUserOnlineIndicator v-if="showIndicator" class="indicator" :user="user"/>
|
||||
</span>
|
||||
<MkA class="eiwwqkts _noSelect" :class="{ cat }" :to="userPage(user)" :title="acct(user)" :target="target" v-else v-user-preview="disablePreview ? undefined : user.id">
|
||||
<MkA class="eiwwqkts _noSelect" :class="{ cat, square: $store.state.squareAvatars }" :to="userPage(user)" :title="acct(user)" :target="target" v-else v-user-preview="disablePreview ? undefined : user.id">
|
||||
<img class="inner" :src="url" decoding="async"/>
|
||||
<MkUserOnlineIndicator v-if="showIndicator" class="indicator" :user="user"/>
|
||||
</MkA>
|
||||
@ -81,28 +81,6 @@ export default defineComponent({
|
||||
border-radius: 100%;
|
||||
line-height: 16px;
|
||||
|
||||
&.cat {
|
||||
&:before, &:after {
|
||||
background: #df548f;
|
||||
border: solid 4px currentColor;
|
||||
box-sizing: border-box;
|
||||
content: '';
|
||||
display: inline-block;
|
||||
height: 50%;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
&:before {
|
||||
border-radius: 0 75% 75%;
|
||||
transform: rotate(37.5deg) skew(30deg);
|
||||
}
|
||||
|
||||
&:after {
|
||||
border-radius: 75% 0 75% 75%;
|
||||
transform: rotate(-37.5deg) skew(-30deg);
|
||||
}
|
||||
}
|
||||
|
||||
> .inner {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
@ -125,5 +103,35 @@ export default defineComponent({
|
||||
width: 20%;
|
||||
height: 20%;
|
||||
}
|
||||
|
||||
&.square {
|
||||
border-radius: 20%;
|
||||
|
||||
> .inner {
|
||||
border-radius: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
&.cat {
|
||||
&:before, &:after {
|
||||
background: #df548f;
|
||||
border: solid 4px currentColor;
|
||||
box-sizing: border-box;
|
||||
content: '';
|
||||
display: inline-block;
|
||||
height: 50%;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
&:before {
|
||||
border-radius: 0 75% 75%;
|
||||
transform: rotate(37.5deg) skew(30deg);
|
||||
}
|
||||
|
||||
&:after {
|
||||
border-radius: 75% 0 75% 75%;
|
||||
transform: rotate(-37.5deg) skew(-30deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<MkModal ref="modal" @click="$refs.modal.close()" @closed="$emit('closed')">
|
||||
<div class="xubzgfga">
|
||||
<header>{{ image.name }}</header>
|
||||
<img :src="image.url" :alt="image.name" :title="image.name" @click="$refs.modal.close()"/>
|
||||
<img :src="image.url" :alt="image.comment" :title="image.comment" @click="$refs.modal.close()"/>
|
||||
<footer>
|
||||
<span>{{ image.type }}</span>
|
||||
<span>{{ bytes(image.size) }}</span>
|
||||
|
@ -36,7 +36,7 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import MkModal from '@client/components/ui/modal.vue';
|
||||
import { sidebarDef } from '@client/sidebar';
|
||||
import { menuDef } from '@client/menu';
|
||||
import { instanceName } from '@client/config';
|
||||
|
||||
export default defineComponent({
|
||||
@ -48,7 +48,7 @@ export default defineComponent({
|
||||
|
||||
data() {
|
||||
return {
|
||||
menuDef: sidebarDef,
|
||||
menuDef: menuDef,
|
||||
items: [],
|
||||
instanceName,
|
||||
};
|
||||
|
@ -87,8 +87,6 @@ export default defineComponent({
|
||||
> .icon {
|
||||
padding-left: 2px;
|
||||
font-size: .9em;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
238
src/client/components/media-caption.vue
Normal file
238
src/client/components/media-caption.vue
Normal file
@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<MkModal ref="modal" @click="done(true)" @closed="$emit('closed')">
|
||||
<div class="container">
|
||||
<div class="fullwidth top-caption">
|
||||
<div class="mk-dialog">
|
||||
<header v-if="title"><Mfm :text="title"/></header>
|
||||
<textarea autofocus v-model="inputValue" :placeholder="input.placeholder" @keydown="onInputKeydown"></textarea>
|
||||
<div class="buttons" v-if="(showOkButton || showCancelButton)">
|
||||
<MkButton inline @click="ok" primary>{{ $ts.ok }}</MkButton>
|
||||
<MkButton inline @click="cancel" >{{ $ts.cancel }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hdrwpsaf fullwidth">
|
||||
<header>{{ image.name }}</header>
|
||||
<img :src="image.url" :alt="image.comment" :title="image.comment" @click="$refs.modal.close()"/>
|
||||
<footer>
|
||||
<span>{{ image.type }}</span>
|
||||
<span>{{ bytes(image.size) }}</span>
|
||||
<span v-if="image.properties && image.properties.width">{{ number(image.properties.width) }}px × {{ number(image.properties.height) }}px</span>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</MkModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import MkModal from '@client/components/ui/modal.vue';
|
||||
import MkButton from '@client/components/ui/button.vue';
|
||||
import bytes from '@client/filters/bytes';
|
||||
import number from '@client/filters/number';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MkModal,
|
||||
MkButton,
|
||||
},
|
||||
|
||||
props: {
|
||||
image: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
input: {
|
||||
required: true
|
||||
},
|
||||
showOkButton: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showCancelButton: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
cancelableByBgClick: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
},
|
||||
|
||||
emits: ['done', 'closed'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
inputValue: this.input.default ? this.input.default : null
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
document.addEventListener('keydown', this.onKeydown);
|
||||
},
|
||||
|
||||
beforeUnmount() {
|
||||
document.removeEventListener('keydown', this.onKeydown);
|
||||
},
|
||||
|
||||
methods: {
|
||||
bytes,
|
||||
number,
|
||||
|
||||
done(canceled, result?) {
|
||||
this.$emit('done', { canceled, result });
|
||||
this.$refs.modal.close();
|
||||
},
|
||||
|
||||
async ok() {
|
||||
if (!this.showOkButton) return;
|
||||
|
||||
const result = this.inputValue;
|
||||
this.done(false, result);
|
||||
},
|
||||
|
||||
cancel() {
|
||||
this.done(true);
|
||||
},
|
||||
|
||||
onBgClick() {
|
||||
if (this.cancelableByBgClick) {
|
||||
this.cancel();
|
||||
}
|
||||
},
|
||||
|
||||
onKeydown(e) {
|
||||
if (e.which === 27) { // ESC
|
||||
this.cancel();
|
||||
}
|
||||
},
|
||||
|
||||
onInputKeydown(e) {
|
||||
if (e.which === 13) { // Enter
|
||||
if (e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex-direction: row;
|
||||
}
|
||||
@media (max-width: 850px) {
|
||||
.container {
|
||||
flex-direction: column;
|
||||
}
|
||||
.top-caption {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
}
|
||||
.fullwidth {
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
.mk-dialog {
|
||||
position: relative;
|
||||
padding: 32px;
|
||||
min-width: 320px;
|
||||
max-width: 480px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
background: var(--panel);
|
||||
border-radius: var(--radius);
|
||||
margin: auto;
|
||||
|
||||
> header {
|
||||
margin: 0 0 8px 0;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
> .buttons {
|
||||
margin-top: 16px;
|
||||
|
||||
> * {
|
||||
margin: 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
> textarea {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
padding: 0 24px;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
color: var(--fg);
|
||||
font-family: inherit;
|
||||
max-width: 100%;
|
||||
min-width: 100%;
|
||||
min-height: 90px;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
.hdrwpsaf {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
> header,
|
||||
> footer {
|
||||
align-self: center;
|
||||
display: inline-block;
|
||||
padding: 6px 9px;
|
||||
font-size: 90%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
border-radius: 6px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
> header {
|
||||
margin-bottom: 8px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
> img {
|
||||
display: block;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
object-fit: contain;
|
||||
width: 100%;
|
||||
cursor: zoom-out;
|
||||
image-orientation: from-image;
|
||||
}
|
||||
|
||||
> footer {
|
||||
margin-top: 8px;
|
||||
opacity: 0.8;
|
||||
|
||||
> span + span {
|
||||
margin-left: 0.5em;
|
||||
padding-left: 0.5em;
|
||||
border-left: solid 1px rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="qjewsnkg" v-if="hide" @click="hide = false">
|
||||
<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.name"/>
|
||||
<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.comment" :alt="image.comment"/>
|
||||
<div class="text">
|
||||
<div>
|
||||
<b><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b>
|
||||
@ -14,7 +14,7 @@
|
||||
:title="image.name"
|
||||
@click.prevent="onClick"
|
||||
>
|
||||
<ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.name" :title="image.name" :cover="false"/>
|
||||
<ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.comment" :title="image.comment" :cover="false"/>
|
||||
<div class="gif" v-if="image.type === 'image/gif'">GIF</div>
|
||||
</a>
|
||||
<i class="fas fa-eye-slash" @click="hide = true"></i>
|
||||
|
@ -9,7 +9,6 @@
|
||||
<video
|
||||
:poster="video.thumbnailUrl"
|
||||
:title="video.name"
|
||||
crossorigin="anonymous"
|
||||
preload="none"
|
||||
controls
|
||||
>
|
||||
|
@ -109,7 +109,7 @@ export default defineComponent({
|
||||
|
||||
this.readObserver.observe(this.$el);
|
||||
|
||||
this.connection = os.stream.useSharedConnection('main');
|
||||
this.connection = os.stream.useChannel('main');
|
||||
this.connection.on('readAllNotifications', () => this.readObserver.unobserve(this.$el));
|
||||
}
|
||||
},
|
||||
|
@ -12,10 +12,10 @@
|
||||
<XNotification v-else :notification="notification" :with-time="true" :full="true" class="_panel notification" :key="notification.id"/>
|
||||
</XList>
|
||||
|
||||
<button class="_buttonPrimary" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
|
||||
<MkButton primary style="margin: var(--margin) auto;" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
|
||||
<template v-if="!moreFetching">{{ $ts.loadMore }}</template>
|
||||
<template v-if="moreFetching"><MkLoading inline/></template>
|
||||
</button>
|
||||
</MkButton>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
@ -28,12 +28,14 @@ import XList from './date-separated-list.vue';
|
||||
import XNote from './note.vue';
|
||||
import { notificationTypes } from '../../types';
|
||||
import * as os from '@client/os';
|
||||
import MkButton from '@client/components/ui/button.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
XNotification,
|
||||
XList,
|
||||
XNote,
|
||||
MkButton,
|
||||
},
|
||||
|
||||
mixins: [
|
||||
@ -87,7 +89,7 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.connection = os.stream.useSharedConnection('main');
|
||||
this.connection = os.stream.useChannel('main');
|
||||
this.connection.on('notification', this.onNotification);
|
||||
},
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
<p v-if="!readOnly">
|
||||
<span>{{ $t('_poll.totalVotes', { n: total }) }}</span>
|
||||
<span> · </span>
|
||||
<a v-if="!closed && !isVoted" @click="toggleShowResult">{{ showResult ? $ts._poll.vote : $ts._poll.showResult }}</a>
|
||||
@ -31,6 +31,11 @@ export default defineComponent({
|
||||
note: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
readOnly: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@ -65,7 +70,7 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.showResult = this.isVoted;
|
||||
this.showResult = this.readOnly || this.isVoted;
|
||||
|
||||
if (this.note.poll.expiresAt) {
|
||||
const update = () => {
|
||||
@ -83,7 +88,7 @@ export default defineComponent({
|
||||
this.showResult = !this.showResult;
|
||||
},
|
||||
vote(id) {
|
||||
if (this.closed || !this.poll.multiple && this.poll.choices.some(c => c.isVoted)) return;
|
||||
if (this.readOnly || this.closed || !this.poll.multiple && this.poll.choices.some(c => c.isVoted)) return;
|
||||
os.api('notes/polls/vote', {
|
||||
noteId: this.note.id,
|
||||
choice: id
|
||||
|
@ -89,6 +89,27 @@ export default defineComponent({
|
||||
file.name = result;
|
||||
});
|
||||
},
|
||||
|
||||
async describe(file) {
|
||||
os.popup(import("@client/components/media-caption.vue"), {
|
||||
title: this.$ts.describeFile,
|
||||
input: {
|
||||
placeholder: this.$ts.inputNewDescription,
|
||||
default: file.comment !== null ? file.comment : "",
|
||||
},
|
||||
image: file
|
||||
}, {
|
||||
done: result => {
|
||||
if (!result || result.canceled) return;
|
||||
let comment = result.result;
|
||||
os.api('drive/files/update', {
|
||||
fileId: file.id,
|
||||
comment: comment.length == 0 ? null : comment
|
||||
});
|
||||
}
|
||||
}, 'closed');
|
||||
},
|
||||
|
||||
showFileMenu(file, ev: MouseEvent) {
|
||||
if (this.menu) return;
|
||||
this.menu = os.modalMenu([{
|
||||
@ -99,6 +120,10 @@ export default defineComponent({
|
||||
text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
|
||||
icon: file.isSensitive ? 'fas fa-eye-slash' : 'fas fa-eye',
|
||||
action: () => { this.toggleSensitive(file) }
|
||||
}, {
|
||||
text: this.$ts.describeFile,
|
||||
icon: 'fas fa-i-cursor',
|
||||
action: () => { this.describe(file) }
|
||||
}, {
|
||||
text: this.$ts.attachCancel,
|
||||
icon: 'fas fa-times-circle',
|
||||
|
@ -61,7 +61,7 @@ import * as mfm from 'mfm-js';
|
||||
import { host, url } from '@client/config';
|
||||
import { erase, unique } from '../../prelude/array';
|
||||
import { extractMentions } from '@/misc/extract-mentions';
|
||||
import getAcct from '@/misc/acct/render';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
import { formatTimeString } from '@/misc/format-time-string';
|
||||
import { Autocomplete } from '@client/scripts/autocomplete';
|
||||
import { noteVisibilities } from '../../types';
|
||||
|
@ -14,7 +14,7 @@ export default defineComponent({
|
||||
class: 'pxhvhrfw',
|
||||
}, options.map(option => withDirectives(h('button', {
|
||||
class: ['_button', { active: this.value === option.props.value }],
|
||||
key: option.props.value,
|
||||
key: option.key,
|
||||
disabled: this.value === option.props.value,
|
||||
onClick: () => {
|
||||
this.$emit('update:value', option.props.value);
|
||||
|
@ -92,33 +92,33 @@ export default defineComponent({
|
||||
this.query = {
|
||||
antennaId: this.antenna
|
||||
};
|
||||
this.connection = os.stream.connectToChannel('antenna', {
|
||||
this.connection = os.stream.useChannel('antenna', {
|
||||
antennaId: this.antenna
|
||||
});
|
||||
this.connection.on('note', prepend);
|
||||
} else if (this.src == 'home') {
|
||||
endpoint = 'notes/timeline';
|
||||
this.connection = os.stream.useSharedConnection('homeTimeline');
|
||||
this.connection = os.stream.useChannel('homeTimeline');
|
||||
this.connection.on('note', prepend);
|
||||
|
||||
this.connection2 = os.stream.useSharedConnection('main');
|
||||
this.connection2 = os.stream.useChannel('main');
|
||||
this.connection2.on('follow', onChangeFollowing);
|
||||
this.connection2.on('unfollow', onChangeFollowing);
|
||||
} else if (this.src == 'local') {
|
||||
endpoint = 'notes/local-timeline';
|
||||
this.connection = os.stream.useSharedConnection('localTimeline');
|
||||
this.connection = os.stream.useChannel('localTimeline');
|
||||
this.connection.on('note', prepend);
|
||||
} else if (this.src == 'social') {
|
||||
endpoint = 'notes/hybrid-timeline';
|
||||
this.connection = os.stream.useSharedConnection('hybridTimeline');
|
||||
this.connection = os.stream.useChannel('hybridTimeline');
|
||||
this.connection.on('note', prepend);
|
||||
} else if (this.src == 'global') {
|
||||
endpoint = 'notes/global-timeline';
|
||||
this.connection = os.stream.useSharedConnection('globalTimeline');
|
||||
this.connection = os.stream.useChannel('globalTimeline');
|
||||
this.connection.on('note', prepend);
|
||||
} else if (this.src == 'mentions') {
|
||||
endpoint = 'notes/mentions';
|
||||
this.connection = os.stream.useSharedConnection('main');
|
||||
this.connection = os.stream.useChannel('main');
|
||||
this.connection.on('mention', prepend);
|
||||
} else if (this.src == 'directs') {
|
||||
endpoint = 'notes/mentions';
|
||||
@ -130,14 +130,14 @@ export default defineComponent({
|
||||
prepend(note);
|
||||
}
|
||||
};
|
||||
this.connection = os.stream.useSharedConnection('main');
|
||||
this.connection = os.stream.useChannel('main');
|
||||
this.connection.on('mention', onNote);
|
||||
} else if (this.src == 'list') {
|
||||
endpoint = 'notes/user-list-timeline';
|
||||
this.query = {
|
||||
listId: this.list
|
||||
};
|
||||
this.connection = os.stream.connectToChannel('userList', {
|
||||
this.connection = os.stream.useChannel('userList', {
|
||||
listId: this.list
|
||||
});
|
||||
this.connection.on('note', prepend);
|
||||
@ -148,7 +148,7 @@ export default defineComponent({
|
||||
this.query = {
|
||||
channelId: this.channel
|
||||
};
|
||||
this.connection = os.stream.connectToChannel('channel', {
|
||||
this.connection = os.stream.useChannel('channel', {
|
||||
channelId: this.channel
|
||||
});
|
||||
this.connection.on('note', prepend);
|
||||
|
@ -191,6 +191,8 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
> .content {
|
||||
--stickyTop: 0px;
|
||||
|
||||
&.omitted {
|
||||
position: relative;
|
||||
max-height: var(--maxHeight);
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<transition :name="$store.state.animation ? popup ? 'modal-popup' : 'modal' : ''" :duration="$store.state.animation ? popup ? 500 : 300 : 0" appear @after-leave="onClosed" @enter="$emit('opening')" @after-enter="childRendered">
|
||||
<div v-show="manualShowing != null ? manualShowing : showing" class="mk-modal" v-hotkey.global="keymap" :style="{ pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
|
||||
<div v-show="manualShowing != null ? manualShowing : showing" class="qzhlnise" :class="{ front }" v-hotkey.global="keymap" :style="{ pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
|
||||
<div class="bg _modalBg" @click="onBgClick" @contextmenu.prevent.stop="() => {}"></div>
|
||||
<div class="content" :class="{ popup, fixed, top: position === 'top' }" @click.self="onBgClick" ref="content">
|
||||
<slot></slot>
|
||||
@ -41,6 +41,11 @@ export default defineComponent({
|
||||
},
|
||||
position: {
|
||||
required: false
|
||||
},
|
||||
front: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
emits: ['opening', 'click', 'esc', 'close', 'closed'],
|
||||
@ -224,14 +229,14 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
.mk-modal {
|
||||
.qzhlnise {
|
||||
> .bg {
|
||||
z-index: 20000;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
> .content:not(.popup) {
|
||||
position: fixed;
|
||||
z-index: 20000;
|
||||
z-index: 10000;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
@ -263,11 +268,25 @@ export default defineComponent({
|
||||
|
||||
> .content.popup {
|
||||
position: absolute;
|
||||
z-index: 20000;
|
||||
z-index: 10000;
|
||||
|
||||
&.fixed {
|
||||
position: fixed;
|
||||
}
|
||||
}
|
||||
|
||||
&.front {
|
||||
> .bg {
|
||||
z-index: 20000;
|
||||
}
|
||||
|
||||
> .content:not(.popup) {
|
||||
z-index: 20000;
|
||||
}
|
||||
|
||||
> .content.popup {
|
||||
z-index: 20000;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -23,14 +23,17 @@ export default defineComponent({
|
||||
},
|
||||
render() {
|
||||
const label = this.$slots.desc();
|
||||
const options = this.$slots.default();
|
||||
let options = this.$slots.default();
|
||||
|
||||
// なぜかFragmentになることがあるため
|
||||
if (options.length === 1 && options[0].props == null) options = options[0].children;
|
||||
|
||||
return h('div', {
|
||||
class: 'novjtcto'
|
||||
}, [
|
||||
h('div', label),
|
||||
...options.map(option => h(MkRadio, {
|
||||
key: option.props.value,
|
||||
key: option.key,
|
||||
value: option.props.value,
|
||||
modelValue: this.value,
|
||||
'onUpdate:modelValue': value => this.value = value,
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import MkFollowButton from './follow-button.vue';
|
||||
import { userPage } from '../filters/user';
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import MkFollowButton from './follow-button.vue';
|
||||
import { userPage } from '../filters/user';
|
||||
import * as os from '@client/os';
|
||||
|
@ -43,6 +43,7 @@ export default defineComponent({
|
||||
|
||||
props: {
|
||||
widgets: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
edit: {
|
||||
|
@ -6,7 +6,7 @@ export default {
|
||||
|
||||
const header = src.children[0];
|
||||
const currentStickyTop = getComputedStyle(src).getPropertyValue('--stickyTop') || '0px';
|
||||
src.style.setProperty('--stickyTop', `${parseInt(currentStickyTop) + header.offsetHeight}px`);
|
||||
src.style.setProperty('--stickyTop', `calc(${currentStickyTop} + ${header.offsetHeight}px)`);
|
||||
header.style.setProperty('--stickyTop', currentStickyTop);
|
||||
header.style.position = 'sticky';
|
||||
header.style.top = 'var(--stickyTop)';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import getAcct from '@/misc/acct/render';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
import getUserName from '@/misc/get-user-name';
|
||||
import { url } from '@client/config';
|
||||
|
||||
|
@ -34,18 +34,6 @@ console.info(`Misskey v${version}`);
|
||||
window.onerror = null;
|
||||
window.onunhandledrejection = null;
|
||||
|
||||
// 後方互換性のため。
|
||||
// TODO: そのうち消す
|
||||
if ((typeof ColdDeviceStorage.get('lightTheme') === 'string') || (typeof ColdDeviceStorage.get('darkTheme') === 'string')) {
|
||||
ColdDeviceStorage.set('lightTheme', require('@client/themes/l-light.json5'));
|
||||
ColdDeviceStorage.set('darkTheme', require('@client/themes/d-dark.json5'));
|
||||
}
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = 'https://use.fontawesome.com/releases/v5.15.3/css/all.css';
|
||||
document.head.appendChild(link);
|
||||
// TODOここまで
|
||||
|
||||
if (_DEV_) {
|
||||
console.warn('Development mode!!!');
|
||||
|
||||
@ -163,8 +151,6 @@ fetchInstance().then(() => {
|
||||
initializeSw();
|
||||
});
|
||||
|
||||
stream.init($i);
|
||||
|
||||
const app = createApp(await (
|
||||
window.location.search === '?zen' ? import('@client/ui/zen.vue') :
|
||||
!$i ? import('@client/ui/visitor.vue') :
|
||||
@ -296,7 +282,7 @@ if ($i) {
|
||||
}
|
||||
}
|
||||
|
||||
const main = stream.useSharedConnection('main', 'System');
|
||||
const main = stream.useChannel('main', null, 'System');
|
||||
|
||||
// 自分の情報が更新されたとき
|
||||
main.on('meUpdated', i => {
|
||||
@ -358,10 +344,6 @@ if ($i) {
|
||||
sound.play('channel');
|
||||
});
|
||||
|
||||
main.on('readAllAnnouncements', () => {
|
||||
updateAccount({ hasUnreadAnnouncement: false });
|
||||
});
|
||||
|
||||
// トークンが再生成されたとき
|
||||
// このままではMisskeyが利用できないので強制的にサインアウトさせる
|
||||
main.on('myTokenRegenerated', () => {
|
||||
|
@ -1,26 +1,14 @@
|
||||
import { computed, reactive } from 'vue';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { api } from './os';
|
||||
|
||||
// TODO: 他のタブと永続化されたstateを同期
|
||||
|
||||
export type Instance = {
|
||||
emojis: {
|
||||
category: string;
|
||||
}[];
|
||||
ads: {
|
||||
id: string;
|
||||
ratio: number;
|
||||
place: string;
|
||||
url: string;
|
||||
imageUrl: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
const data = localStorage.getItem('instance');
|
||||
|
||||
// TODO: instanceをリアクティブにするかは再考の余地あり
|
||||
|
||||
export const instance: Instance = reactive(data ? JSON.parse(data) : {
|
||||
export const instance: Misskey.entities.InstanceMetadata = reactive(data ? JSON.parse(data) : {
|
||||
// TODO: set default values
|
||||
});
|
||||
|
||||
|
@ -5,7 +5,7 @@ import { i18n } from '@client/i18n';
|
||||
import { $i } from './account';
|
||||
import { unisonReload } from '@client/scripts/unison-reload';
|
||||
|
||||
export const sidebarDef = {
|
||||
export const menuDef = {
|
||||
notifications: {
|
||||
title: 'notifications',
|
||||
icon: 'fas fa-bell',
|
@ -3,16 +3,16 @@
|
||||
import { Component, defineAsyncComponent, markRaw, reactive, Ref, ref } from 'vue';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import Stream from '@client/scripts/stream';
|
||||
import { apiUrl, debug } from '@client/config';
|
||||
import { apiUrl, debug, url } from '@client/config';
|
||||
import MkPostFormDialog from '@client/components/post-form-dialog.vue';
|
||||
import MkWaitingDialog from '@client/components/waiting-dialog.vue';
|
||||
import { resolve } from '@client/router';
|
||||
import { $i } from '@client/account';
|
||||
import { defaultStore } from '@client/store';
|
||||
|
||||
export const stream = markRaw(new Stream());
|
||||
export const stream = markRaw(new Misskey.Stream(url, $i));
|
||||
|
||||
export const pendingApiRequestsCount = ref(0);
|
||||
let apiRequestsCount = 0; // for debug
|
||||
@ -20,7 +20,11 @@ export const apiRequests = ref([]); // for debug
|
||||
|
||||
export const windows = new Map();
|
||||
|
||||
export function api(endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) {
|
||||
const apiClient = new Misskey.api.APIClient({
|
||||
origin: url,
|
||||
});
|
||||
|
||||
export const api = ((endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) => {
|
||||
pendingApiRequestsCount.value++;
|
||||
|
||||
const onFinally = () => {
|
||||
@ -56,7 +60,7 @@ export function api(endpoint: string, data: Record<string, any> = {}, token?: st
|
||||
if (res.status === 200) {
|
||||
resolve(body);
|
||||
if (debug) {
|
||||
log!.res = markRaw(body);
|
||||
log!.res = markRaw(JSON.parse(JSON.stringify(body)));
|
||||
log!.state = 'success';
|
||||
}
|
||||
} else if (res.status === 204) {
|
||||
@ -90,17 +94,15 @@ export function api(endpoint: string, data: Record<string, any> = {}, token?: st
|
||||
promise.then(onFinally, onFinally);
|
||||
|
||||
return promise;
|
||||
}
|
||||
}) as typeof apiClient.request;
|
||||
|
||||
export function apiWithDialog(
|
||||
export const apiWithDialog = ((
|
||||
endpoint: string,
|
||||
data: Record<string, any> = {},
|
||||
token?: string | null | undefined,
|
||||
onSuccess?: (res: any) => void,
|
||||
onFailure?: (e: Error) => void,
|
||||
) {
|
||||
) => {
|
||||
const promise = api(endpoint, data, token);
|
||||
promiseDialog(promise, onSuccess, onFailure ? onFailure : (e) => {
|
||||
promiseDialog(promise, null, (e) => {
|
||||
dialog({
|
||||
type: 'error',
|
||||
text: e.message + '\n' + (e as any).id,
|
||||
@ -108,7 +110,7 @@ export function apiWithDialog(
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
}) as typeof api;
|
||||
|
||||
export function promiseDialog<T extends Promise<any>>(
|
||||
promise: T,
|
||||
|
@ -6,7 +6,7 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import * as os from '@client/os';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
|
||||
export default defineComponent({
|
||||
created() {
|
||||
|
@ -63,7 +63,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import MkButton from '@client/components/ui/button.vue';
|
||||
import MkInput from '@client/components/ui/input.vue';
|
||||
import MkSelect from '@client/components/ui/select.vue';
|
||||
|
@ -90,7 +90,7 @@ export default defineComponent({
|
||||
stats: null,
|
||||
serverInfo: null,
|
||||
connection: null,
|
||||
queueConnection: os.stream.useSharedConnection('queueStats'),
|
||||
queueConnection: os.stream.useChannel('queueStats'),
|
||||
memUsage: 0,
|
||||
chartCpuMem: null,
|
||||
chartNet: null,
|
||||
@ -121,7 +121,7 @@ export default defineComponent({
|
||||
os.api('admin/server-info', {}).then(res => {
|
||||
this.serverInfo = res;
|
||||
|
||||
this.connection = os.stream.useSharedConnection('serverStats');
|
||||
this.connection = os.stream.useChannel('serverStats');
|
||||
this.connection.on('stats', this.onStats);
|
||||
this.connection.on('statsLog', this.onStatsLog);
|
||||
this.connection.send('requestLog', {
|
||||
|
@ -92,6 +92,7 @@ export default defineComponent({
|
||||
version,
|
||||
url,
|
||||
stats: null,
|
||||
meta: null,
|
||||
fetchStats: () => os.api('stats', {}),
|
||||
fetchServerInfo: () => os.api('admin/server-info', {}),
|
||||
fetchJobs: () => os.api('admin/queue/deliver-delayed', {}),
|
||||
|
@ -35,7 +35,7 @@ export default defineComponent({
|
||||
title: this.$ts.jobQueue,
|
||||
icon: 'fas fa-clipboard-list',
|
||||
},
|
||||
connection: os.stream.useSharedConnection('queueStats'),
|
||||
connection: os.stream.useChannel('queueStats'),
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -19,6 +19,11 @@
|
||||
<span>{{ $ts.bannerUrl }}</span>
|
||||
</FormInput>
|
||||
|
||||
<FormInput v-model:value="backgroundImageUrl">
|
||||
<template #prefix><i class="fas fa-link"></i></template>
|
||||
<span>{{ $ts.backgroundImageUrl }}</span>
|
||||
</FormInput>
|
||||
|
||||
<FormInput v-model:value="tosUrl">
|
||||
<template #prefix><i class="fas fa-link"></i></template>
|
||||
<span>{{ $ts.tosUrl }}</span>
|
||||
@ -88,6 +93,7 @@ export default defineComponent({
|
||||
maintainerEmail: null,
|
||||
iconUrl: null,
|
||||
bannerUrl: null,
|
||||
backgroundImageUrl: null,
|
||||
maxNoteTextLength: 0,
|
||||
enableLocalTimeline: false,
|
||||
enableGlobalTimeline: false,
|
||||
@ -106,6 +112,7 @@ export default defineComponent({
|
||||
this.tosUrl = meta.tosUrl;
|
||||
this.iconUrl = meta.iconUrl;
|
||||
this.bannerUrl = meta.bannerUrl;
|
||||
this.backgroundImageUrl = meta.backgroundImageUrl;
|
||||
this.maintainerName = meta.maintainerName;
|
||||
this.maintainerEmail = meta.maintainerEmail;
|
||||
this.maxNoteTextLength = meta.maxNoteTextLength;
|
||||
@ -120,6 +127,7 @@ export default defineComponent({
|
||||
tosUrl: this.tosUrl,
|
||||
iconUrl: this.iconUrl,
|
||||
bannerUrl: this.bannerUrl,
|
||||
backgroundImageUrl: this.backgroundImageUrl,
|
||||
maintainerName: this.maintainerName,
|
||||
maintainerEmail: this.maintainerEmail,
|
||||
maxNoteTextLength: this.maxNoteTextLength,
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineAsyncComponent, defineComponent } from 'vue';
|
||||
import getAcct from '@/misc/acct/render';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
import MkButton from '@client/components/ui/button.vue';
|
||||
import { acct } from '../../filters/user';
|
||||
import * as os from '@client/os';
|
||||
@ -63,7 +63,7 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.connection = os.stream.useSharedConnection('messagingIndex');
|
||||
this.connection = os.stream.useChannel('messagingIndex');
|
||||
|
||||
this.connection.on('message', this.onMessage);
|
||||
this.connection.on('read', this.onRead);
|
||||
|
@ -40,7 +40,7 @@ import { computed, defineComponent } from 'vue';
|
||||
import XList from '@client/components/date-separated-list.vue';
|
||||
import XMessage from './messaging-room.message.vue';
|
||||
import XForm from './messaging-room.form.vue';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import { isBottom, onScrollBottom, scroll } from '@client/scripts/scroll';
|
||||
import * as os from '@client/os';
|
||||
import { popout } from '@client/scripts/popout';
|
||||
@ -141,7 +141,7 @@ const Component = defineComponent({
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
this.connection = os.stream.connectToChannel('messaging', {
|
||||
this.connection = os.stream.useChannel('messaging', {
|
||||
otherparty: this.user ? this.user.id : undefined,
|
||||
group: this.group ? this.group.id : undefined,
|
||||
});
|
||||
|
@ -52,7 +52,7 @@ import MkInput from '@client/components/ui/input.vue';
|
||||
import MkTextarea from '@client/components/ui/textarea.vue';
|
||||
import MkSelect from '@client/components/ui/select.vue';
|
||||
import MkSwitch from '@client/components/ui/switch.vue';
|
||||
import getAcct from '@/misc/acct/render';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
import * as os from '@client/os';
|
||||
|
||||
export default defineComponent({
|
||||
|
@ -350,6 +350,9 @@ export default defineComponent({
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@use "sass:math";
|
||||
|
||||
.xqnhankfuuilcwvhgsopeqncafzsquya {
|
||||
text-align: center;
|
||||
|
||||
@ -388,11 +391,11 @@ export default defineComponent({
|
||||
font-size: 0.8em;
|
||||
|
||||
&:first-child {
|
||||
margin-left: -($gap / 2);
|
||||
margin-left: -(math.div($gap, 2));
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-right: -($gap / 2);
|
||||
margin-right: -(math.div($gap, 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -413,11 +416,11 @@ export default defineComponent({
|
||||
font-size: 12px;
|
||||
|
||||
&:first-child {
|
||||
margin-top: -($gap / 2);
|
||||
margin-top: -(math.div($gap, 2));
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: -($gap / 2);
|
||||
margin-bottom: -(math.div($gap, 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ export default defineComponent({
|
||||
if (this.connection) {
|
||||
this.connection.dispose();
|
||||
}
|
||||
this.connection = os.stream.connectToChannel('gamesReversiGame', {
|
||||
this.connection = os.stream.useChannel('gamesReversiGame', {
|
||||
gameId: this.game.id
|
||||
});
|
||||
this.connection.on('started', this.onStarted);
|
||||
|
@ -92,7 +92,7 @@ export default defineComponent({
|
||||
|
||||
mounted() {
|
||||
if (this.$i) {
|
||||
this.connection = os.stream.useSharedConnection('gamesReversi');
|
||||
this.connection = os.stream.useChannel('gamesReversi');
|
||||
|
||||
this.connection.on('invited', this.onInvited);
|
||||
|
||||
|
@ -52,7 +52,7 @@
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { Room } from '@client/scripts/room/room';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import XPreview from './preview.vue';
|
||||
const storeItems = require('@client/scripts/room/furnitures.json5');
|
||||
import { query as urlQuery } from '../../../prelude/url';
|
||||
|
72
src/client/pages/settings/custom-css.vue
Normal file
72
src/client/pages/settings/custom-css.vue
Normal file
@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<FormBase>
|
||||
<FormInfo warn>{{ $ts.customCssWarn }}</FormInfo>
|
||||
|
||||
<FormTextarea v-model:value="localCustomCss" manual-save tall class="_monospace" style="tab-size: 2;">
|
||||
<span>{{ $ts.local }}</span>
|
||||
</FormTextarea>
|
||||
</FormBase>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import FormTextarea from '@client/components/form/textarea.vue';
|
||||
import FormSelect from '@client/components/form/select.vue';
|
||||
import FormRadios from '@client/components/form/radios.vue';
|
||||
import FormBase from '@client/components/form/base.vue';
|
||||
import FormGroup from '@client/components/form/group.vue';
|
||||
import FormLink from '@client/components/form/link.vue';
|
||||
import FormButton from '@client/components/form/button.vue';
|
||||
import FormInfo from '@client/components/form/info.vue';
|
||||
import * as os from '@client/os';
|
||||
import { ColdDeviceStorage } from '@client/store';
|
||||
import { unisonReload } from '@client/scripts/unison-reload';
|
||||
import * as symbols from '@client/symbols';
|
||||
import { defaultStore } from '@client/store';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
FormTextarea,
|
||||
FormSelect,
|
||||
FormRadios,
|
||||
FormBase,
|
||||
FormGroup,
|
||||
FormLink,
|
||||
FormButton,
|
||||
FormInfo,
|
||||
},
|
||||
|
||||
emits: ['info'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
[symbols.PAGE_INFO]: {
|
||||
title: this.$ts.customCss,
|
||||
icon: 'fas fa-code'
|
||||
},
|
||||
localCustomCss: localStorage.getItem('customCss')
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$emit('info', this[symbols.PAGE_INFO]);
|
||||
|
||||
this.$watch('localCustomCss', this.apply);
|
||||
},
|
||||
|
||||
methods: {
|
||||
async apply() {
|
||||
localStorage.setItem('customCss', this.localCustomCss);
|
||||
|
||||
const { canceled } = await os.dialog({
|
||||
type: 'info',
|
||||
text: this.$ts.reloadToApplySetting,
|
||||
showCancelButton: true
|
||||
});
|
||||
if (canceled) return;
|
||||
|
||||
unisonReload();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
@ -220,6 +220,9 @@ export default defineComponent({
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@use "sass:math";
|
||||
|
||||
.uawsfosz {
|
||||
> div {
|
||||
padding: 24px;
|
||||
@ -227,12 +230,12 @@ export default defineComponent({
|
||||
> .meter {
|
||||
$size: 12px;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border-radius: ($size / 2);
|
||||
border-radius: math.div($size, 2);
|
||||
overflow: hidden;
|
||||
|
||||
> div {
|
||||
height: $size;
|
||||
border-radius: ($size / 2);
|
||||
border-radius: math.div($size, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,7 @@
|
||||
<FormSwitch v-model:value="showGapBetweenNotesInTimeline">{{ $ts.showGapBetweenNotesInTimeline }}</FormSwitch>
|
||||
<FormSwitch v-model:value="loadRawImages">{{ $ts.loadRawImages }}</FormSwitch>
|
||||
<FormSwitch v-model:value="disableShowingAnimatedImages">{{ $ts.disableShowingAnimatedImages }}</FormSwitch>
|
||||
<FormSwitch v-model:value="squareAvatars">{{ $ts.squareAvatars }}</FormSwitch>
|
||||
<FormSwitch v-model:value="useSystemFont">{{ $ts.useSystemFont }}</FormSwitch>
|
||||
<FormSwitch v-model:value="useOsNativeEmojis">{{ $ts.useOsNativeEmojis }}
|
||||
<div><Mfm text="🍮🍦🍭🍩🍰🍫🍬🥞🍪" :key="useOsNativeEmojis"/></div>
|
||||
@ -78,6 +79,8 @@
|
||||
</FormSelect>
|
||||
|
||||
<FormLink to="/settings/deck">{{ $ts.deck }}</FormLink>
|
||||
|
||||
<FormLink to="/settings/custom-css"><template #icon><i class="fas fa-code"></i></template>{{ $ts.customCss }}</FormLink>
|
||||
</FormBase>
|
||||
</template>
|
||||
|
||||
@ -143,6 +146,7 @@ export default defineComponent({
|
||||
instanceTicker: defaultStore.makeGetterSetter('instanceTicker'),
|
||||
enableInfiniteScroll: defaultStore.makeGetterSetter('enableInfiniteScroll'),
|
||||
useReactionPickerForContextMenu: defaultStore.makeGetterSetter('useReactionPickerForContextMenu'),
|
||||
squareAvatars: defaultStore.makeGetterSetter('squareAvatars'),
|
||||
},
|
||||
|
||||
watch: {
|
||||
@ -174,6 +178,10 @@ export default defineComponent({
|
||||
this.reloadAsk();
|
||||
},
|
||||
|
||||
squareAvatars() {
|
||||
this.reloadAsk();
|
||||
},
|
||||
|
||||
showGapBetweenNotesInTimeline() {
|
||||
this.reloadAsk();
|
||||
},
|
||||
|
@ -26,7 +26,7 @@
|
||||
<template #label>{{ $ts.clientSettings }}</template>
|
||||
<FormLink :active="page === 'general'" replace to="/settings/general"><template #icon><i class="fas fa-cogs"></i></template>{{ $ts.general }}</FormLink>
|
||||
<FormLink :active="page === 'theme'" replace to="/settings/theme"><template #icon><i class="fas fa-palette"></i></template>{{ $ts.theme }}</FormLink>
|
||||
<FormLink :active="page === 'sidebar'" replace to="/settings/sidebar"><template #icon><i class="fas fa-list-ul"></i></template>{{ $ts.sidebar }}</FormLink>
|
||||
<FormLink :active="page === 'menu'" replace to="/settings/menu"><template #icon><i class="fas fa-list-ul"></i></template>{{ $ts.menu }}</FormLink>
|
||||
<FormLink :active="page === 'sounds'" replace to="/settings/sounds"><template #icon><i class="fas fa-music"></i></template>{{ $ts.sounds }}</FormLink>
|
||||
<FormLink :active="page === 'plugin'" replace to="/settings/plugin"><template #icon><i class="fas fa-plug"></i></template>{{ $ts.plugins }}</FormLink>
|
||||
</FormGroup>
|
||||
@ -121,8 +121,9 @@ export default defineComponent({
|
||||
case 'theme': return defineAsyncComponent(() => import('./theme.vue'));
|
||||
case 'theme/install': return defineAsyncComponent(() => import('./theme.install.vue'));
|
||||
case 'theme/manage': return defineAsyncComponent(() => import('./theme.manage.vue'));
|
||||
case 'sidebar': return defineAsyncComponent(() => import('./sidebar.vue'));
|
||||
case 'menu': return defineAsyncComponent(() => import('./menu.vue'));
|
||||
case 'sounds': return defineAsyncComponent(() => import('./sounds.vue'));
|
||||
case 'custom-css': return defineAsyncComponent(() => import('./custom-css.vue'));
|
||||
case 'deck': return defineAsyncComponent(() => import('./deck.vue'));
|
||||
case 'plugin': return defineAsyncComponent(() => import('./plugin.vue'));
|
||||
case 'plugin/install': return defineAsyncComponent(() => import('./plugin.install.vue'));
|
||||
|
@ -4,8 +4,8 @@
|
||||
<div class="_formLabel"><i class="fab fa-twitter"></i> Twitter</div>
|
||||
<div class="_formPanel" style="padding: 16px;">
|
||||
<p v-if="integrations.twitter">{{ $ts.connectedTo }}: <a :href="`https://twitter.com/${integrations.twitter.screenName}`" rel="nofollow noopener" target="_blank">@{{ integrations.twitter.screenName }}</a></p>
|
||||
<MkButton v-if="integrations.twitter" @click="disconnectTwitter" danger>{{ $ts.disconnectSerice }}</MkButton>
|
||||
<MkButton v-else @click="connectTwitter" primary>{{ $ts.connectSerice }}</MkButton>
|
||||
<MkButton v-if="integrations.twitter" @click="disconnectTwitter" danger>{{ $ts.disconnectService }}</MkButton>
|
||||
<MkButton v-else @click="connectTwitter" primary>{{ $ts.connectService }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -13,8 +13,8 @@
|
||||
<div class="_formLabel"><i class="fab fa-discord"></i> Discord</div>
|
||||
<div class="_formPanel" style="padding: 16px;">
|
||||
<p v-if="integrations.discord">{{ $ts.connectedTo }}: <a :href="`https://discord.com/users/${integrations.discord.id}`" rel="nofollow noopener" target="_blank">@{{ integrations.discord.username }}#{{ integrations.discord.discriminator }}</a></p>
|
||||
<MkButton v-if="integrations.discord" @click="disconnectDiscord" danger>{{ $ts.disconnectSerice }}</MkButton>
|
||||
<MkButton v-else @click="connectDiscord" primary>{{ $ts.connectSerice }}</MkButton>
|
||||
<MkButton v-if="integrations.discord" @click="disconnectDiscord" danger>{{ $ts.disconnectService }}</MkButton>
|
||||
<MkButton v-else @click="connectDiscord" primary>{{ $ts.connectService }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -22,8 +22,8 @@
|
||||
<div class="_formLabel"><i class="fab fa-github"></i> GitHub</div>
|
||||
<div class="_formPanel" style="padding: 16px;">
|
||||
<p v-if="integrations.github">{{ $ts.connectedTo }}: <a :href="`https://github.com/${integrations.github.login}`" rel="nofollow noopener" target="_blank">@{{ integrations.github.login }}</a></p>
|
||||
<MkButton v-if="integrations.github" @click="disconnectGithub" danger>{{ $ts.disconnectSerice }}</MkButton>
|
||||
<MkButton v-else @click="connectGithub" primary>{{ $ts.connectSerice }}</MkButton>
|
||||
<MkButton v-if="integrations.github" @click="disconnectGithub" danger>{{ $ts.disconnectService }}</MkButton>
|
||||
<MkButton v-else @click="connectGithub" primary>{{ $ts.connectService }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
</FormBase>
|
||||
|
@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<FormBase>
|
||||
<FormTextarea v-model:value="items" tall>
|
||||
<span>{{ $ts.sidebar }}</span>
|
||||
<FormTextarea v-model:value="items" tall manual-save>
|
||||
<span>{{ $ts.menu }}</span>
|
||||
<template #desc><button class="_textButton" @click="addItem">{{ $ts.addItem }}</button></template>
|
||||
</FormTextarea>
|
||||
|
||||
<FormRadios v-model="sidebarDisplay">
|
||||
<FormRadios v-model="menuDisplay">
|
||||
<template #desc>{{ $ts.display }}</template>
|
||||
<option value="full">{{ $ts._sidebar.full }}</option>
|
||||
<option value="icon">{{ $ts._sidebar.icon }}</option>
|
||||
<!-- <MkRadio v-model="sidebarDisplay" value="hide" disabled>{{ $ts._sidebar.hide }}</MkRadio>--> <!-- TODO: サイドバーを完全に隠せるようにすると、別途ハンバーガーボタンのようなものをUIに表示する必要があり面倒 -->
|
||||
<option value="sideFull">{{ $ts._menuDisplay.sideFull }}</option>
|
||||
<option value="sideIcon">{{ $ts._menuDisplay.sideIcon }}</option>
|
||||
<option value="top">{{ $ts._menuDisplay.top }}</option>
|
||||
<!-- <MkRadio v-model="menuDisplay" value="hide" disabled>{{ $ts._menuDisplay.hide }}</MkRadio>--> <!-- TODO: サイドバーを完全に隠せるようにすると、別途ハンバーガーボタンのようなものをUIに表示する必要があり面倒 -->
|
||||
</FormRadios>
|
||||
|
||||
<FormButton @click="save()" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
|
||||
<FormButton @click="reset()" danger><i class="fas fa-redo"></i> {{ $ts.default }}</FormButton>
|
||||
</FormBase>
|
||||
</template>
|
||||
@ -26,9 +26,10 @@ import FormBase from '@client/components/form/base.vue';
|
||||
import FormGroup from '@client/components/form/group.vue';
|
||||
import FormButton from '@client/components/form/button.vue';
|
||||
import * as os from '@client/os';
|
||||
import { sidebarDef } from '@client/sidebar';
|
||||
import { menuDef } from '@client/menu';
|
||||
import { defaultStore } from '@client/store';
|
||||
import * as symbols from '@client/symbols';
|
||||
import { unisonReload } from '@client/scripts/unison-reload';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -43,11 +44,11 @@ export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
[symbols.PAGE_INFO]: {
|
||||
title: this.$ts.sidebar,
|
||||
title: this.$ts.menu,
|
||||
icon: 'fas fa-list-ul'
|
||||
},
|
||||
menuDef: sidebarDef,
|
||||
items: '',
|
||||
menuDef: menuDef,
|
||||
items: defaultStore.state.menu.join('\n'),
|
||||
}
|
||||
},
|
||||
|
||||
@ -56,11 +57,17 @@ export default defineComponent({
|
||||
return this.items.trim().split('\n').filter(x => x.trim() !== '');
|
||||
},
|
||||
|
||||
sidebarDisplay: defaultStore.makeGetterSetter('sidebarDisplay')
|
||||
menuDisplay: defaultStore.makeGetterSetter('menuDisplay')
|
||||
},
|
||||
|
||||
created() {
|
||||
this.items = this.$store.state.menu.join('\n');
|
||||
watch: {
|
||||
menuDisplay() {
|
||||
this.reloadAsk();
|
||||
},
|
||||
|
||||
items() {
|
||||
this.save();
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
@ -84,7 +91,6 @@ export default defineComponent({
|
||||
});
|
||||
if (canceled) return;
|
||||
this.items = [...this.splited, item].join('\n');
|
||||
this.save();
|
||||
},
|
||||
|
||||
save() {
|
||||
@ -95,7 +101,6 @@ export default defineComponent({
|
||||
reset() {
|
||||
this.$store.reset('menu');
|
||||
this.items = this.$store.state.menu.join('\n');
|
||||
this.reloadAsk();
|
||||
},
|
||||
|
||||
async reloadAsk() {
|
||||
@ -106,7 +111,7 @@ export default defineComponent({
|
||||
});
|
||||
if (canceled) return;
|
||||
|
||||
location.reload();
|
||||
unisonReload();
|
||||
}
|
||||
},
|
||||
});
|
@ -71,7 +71,7 @@
|
||||
<FormButton primary v-else @click="wallpaper = null">{{ $ts.removeWallpaper }}</FormButton>
|
||||
|
||||
<FormGroup>
|
||||
<FormLink to="https://assets.msky.cafe/theme/list" external><template #icon><i class="fas fa-globe"></i></template>{{ $ts._theme.explore }}</FormLink>
|
||||
<FormLink to="https://assets.misskey.io/theme/list" external><template #icon><i class="fas fa-globe"></i></template>{{ $ts._theme.explore }}</FormLink>
|
||||
<FormLink to="/settings/theme/install"><template #icon><i class="fas fa-download"></i></template>{{ $ts._theme.install }}</FormLink>
|
||||
</FormGroup>
|
||||
|
||||
|
@ -234,7 +234,7 @@ import MkRemoteCaution from '@client/components/remote-caution.vue';
|
||||
import MkTab from '@client/components/tab.vue';
|
||||
import MkInfo from '@client/components/ui/info.vue';
|
||||
import Progress from '@client/scripts/loading';
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import { getScrollPosition } from '@client/scripts/scroll';
|
||||
import { getUserMenu } from '@client/scripts/get-user-menu';
|
||||
import number from '../../filters/number';
|
||||
|
@ -1,10 +1,22 @@
|
||||
<template>
|
||||
<div class="civpbkhh">
|
||||
<div v-for="note in notes" class="note">
|
||||
<div class="content _panel">
|
||||
{{ note.text }}
|
||||
<div class="scrollbox" ref="scroll" v-bind:class="{ scroll: isScrolling }">
|
||||
<div v-for="note in notes" class="note">
|
||||
<div class="content _panel">
|
||||
<div class="body">
|
||||
<MkA class="reply" v-if="note.replyId" :to="`/notes/${note.replyId}`"><i class="fas fa-reply"></i></MkA>
|
||||
<Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i" :custom-emojis="note.emojis"/>
|
||||
<MkA class="rp" v-if="note.renoteId" :to="`/notes/${note.renoteId}`">RN: ...</MkA>
|
||||
</div>
|
||||
<div v-if="note.files.length > 0" class="richcontent">
|
||||
<XMediaList :media-list="note.files"/>
|
||||
</div>
|
||||
<div v-if="note.poll">
|
||||
<XPoll :note="note" :readOnly="true" />
|
||||
</div>
|
||||
</div>
|
||||
<XReactionsViewer :note="note" ref="reactionsViewer"/>
|
||||
</div>
|
||||
<XReactionsViewer :note="note" ref="reactionsViewer"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -12,16 +24,21 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import XReactionsViewer from '@client/components/reactions-viewer.vue';
|
||||
import XMediaList from '@client/components/media-list.vue';
|
||||
import XPoll from '@client/components/poll.vue';
|
||||
import * as os from '@client/os';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
XReactionsViewer
|
||||
XReactionsViewer,
|
||||
XMediaList,
|
||||
XPoll
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
notes: [],
|
||||
isScrolling: false,
|
||||
}
|
||||
},
|
||||
|
||||
@ -29,22 +46,53 @@ export default defineComponent({
|
||||
os.api('notes/featured').then(notes => {
|
||||
this.notes = notes;
|
||||
});
|
||||
},
|
||||
|
||||
updated() {
|
||||
if (this.$refs.scroll.clientHeight > window.innerHeight) {
|
||||
this.isScrolling = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@keyframes scroll {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
5% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
75% {
|
||||
transform: translate3d(0, calc(-100% + 90vh), 0);
|
||||
}
|
||||
90% {
|
||||
transform: translate3d(0, calc(-100% + 90vh), 0);
|
||||
}
|
||||
}
|
||||
|
||||
.civpbkhh {
|
||||
text-align: right;
|
||||
|
||||
> .note {
|
||||
margin: 16px 0 16px auto;
|
||||
> .scrollbox {
|
||||
&.scroll {
|
||||
animation: scroll 45s linear infinite;
|
||||
}
|
||||
|
||||
> .content {
|
||||
padding: 16px;
|
||||
margin: 0 0 0 auto;
|
||||
max-width: max-content;
|
||||
border-radius: 16px;
|
||||
> .note {
|
||||
margin: 16px 0 16px auto;
|
||||
|
||||
> .content {
|
||||
padding: 16px;
|
||||
margin: 0 0 0 auto;
|
||||
max-width: max-content;
|
||||
border-radius: 16px;
|
||||
|
||||
> .richcontent {
|
||||
min-width: 250px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import { host as localHost } from '@client/config';
|
||||
|
||||
export async function genSearchQuery(v: any, q: string) {
|
||||
|
@ -3,6 +3,11 @@ import * as url from '../../prelude/url';
|
||||
|
||||
export function getStaticImageUrl(baseUrl: string): string {
|
||||
const u = new URL(baseUrl);
|
||||
if (u.href.startsWith(`${instanceUrl}/proxy/`)) {
|
||||
// もう既にproxyっぽそうだったらsearchParams付けるだけ
|
||||
u.searchParams.set('static', '1');
|
||||
return u.href;
|
||||
}
|
||||
const dummy = `${u.host}${u.pathname}`; // 拡張子がないとキャッシュしてくれないCDNがあるので
|
||||
return `${instanceUrl}/proxy/${dummy}?${url.query({
|
||||
url: u.href,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { i18n } from '@client/i18n';
|
||||
import copyToClipboard from '@client/scripts/copy-to-clipboard';
|
||||
import { host } from '@client/config';
|
||||
import getAcct from '@/misc/acct/render';
|
||||
import { getAcct } from '@/misc/acct';
|
||||
import * as os from '@client/os';
|
||||
import { userActions } from '@client/store';
|
||||
import { router } from '@client/router';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import parseAcct from '@/misc/acct/parse';
|
||||
import { parseAcct } from '@/misc/acct';
|
||||
import { i18n } from '@client/i18n';
|
||||
import * as os from '@client/os';
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as os from '@client/os';
|
||||
import { i18n } from '@client/i18n';
|
||||
import { defaultStore } from '@client/store';
|
||||
|
||||
export function selectFile(src: any, label: string | null, multiple = false) {
|
||||
return new Promise((res, rej) => {
|
||||
@ -8,7 +9,7 @@ export function selectFile(src: any, label: string | null, multiple = false) {
|
||||
input.type = 'file';
|
||||
input.multiple = multiple;
|
||||
input.onchange = () => {
|
||||
const promises = Array.from(input.files).map(file => os.upload(file));
|
||||
const promises = Array.from(input.files).map(file => os.upload(file, defaultStore.state.uploadFolder));
|
||||
|
||||
Promise.all(promises).then(driveFiles => {
|
||||
res(multiple ? driveFiles : driveFiles[0]);
|
||||
@ -47,7 +48,7 @@ export function selectFile(src: any, label: string | null, multiple = false) {
|
||||
|
||||
const marker = Math.random().toString(); // TODO: UUIDとか使う
|
||||
|
||||
const connection = os.stream.useSharedConnection('main');
|
||||
const connection = os.stream.useChannel('main');
|
||||
connection.on('urlUploadFinished', data => {
|
||||
if (data.marker === marker) {
|
||||
res(multiple ? [data.file] : data.file);
|
||||
@ -55,8 +56,9 @@ export function selectFile(src: any, label: string | null, multiple = false) {
|
||||
}
|
||||
});
|
||||
|
||||
os.api('drive/files/upload_from_url', {
|
||||
os.api('drive/files/upload-from-url', {
|
||||
url: url,
|
||||
folderId: defaultStore.state.uploadFolder,
|
||||
marker
|
||||
});
|
||||
|
||||
|
@ -7,8 +7,9 @@ export class StickySidebar {
|
||||
private isTop = false;
|
||||
private isBottom = false;
|
||||
private offsetTop: number;
|
||||
private globalHeaderHeight: number = 59;
|
||||
|
||||
constructor(container: StickySidebar['container'], marginTop = 0) {
|
||||
constructor(container: StickySidebar['container'], marginTop = 0, globalHeaderHeight = 0) {
|
||||
this.container = container;
|
||||
this.el = this.container.children[0] as HTMLElement;
|
||||
this.el.style.position = 'sticky';
|
||||
@ -16,30 +17,31 @@ export class StickySidebar {
|
||||
this.container.prepend(this.spacer);
|
||||
this.marginTop = marginTop;
|
||||
this.offsetTop = this.container.getBoundingClientRect().top;
|
||||
this.globalHeaderHeight = globalHeaderHeight;
|
||||
}
|
||||
|
||||
public calc(scrollTop: number) {
|
||||
if (scrollTop > this.lastScrollTop) { // downscroll
|
||||
const overflow = Math.max(0, (this.el.clientHeight + this.marginTop) - window.innerHeight);
|
||||
const overflow = Math.max(0, this.globalHeaderHeight + (this.el.clientHeight + this.marginTop) - window.innerHeight);
|
||||
this.el.style.bottom = null;
|
||||
this.el.style.top = `${-overflow + this.marginTop}px`;
|
||||
this.el.style.top = `${-overflow + this.marginTop + this.globalHeaderHeight}px`;
|
||||
|
||||
this.isBottom = (scrollTop + window.innerHeight) >= (this.el.offsetTop + this.el.clientHeight);
|
||||
|
||||
if (this.isTop) {
|
||||
this.isTop = false;
|
||||
this.spacer.style.marginTop = `${Math.max(0, this.lastScrollTop + this.marginTop - this.offsetTop)}px`;
|
||||
this.spacer.style.marginTop = `${Math.max(0, this.globalHeaderHeight + this.lastScrollTop + this.marginTop - this.offsetTop)}px`;
|
||||
}
|
||||
} else { // upscroll
|
||||
const overflow = (this.el.clientHeight + this.marginTop) - window.innerHeight;
|
||||
const overflow = this.globalHeaderHeight + (this.el.clientHeight + this.marginTop) - window.innerHeight;
|
||||
this.el.style.top = null;
|
||||
this.el.style.bottom = `${-overflow}px`;
|
||||
|
||||
this.isTop = scrollTop <= this.el.offsetTop;
|
||||
this.isTop = scrollTop + this.marginTop + this.globalHeaderHeight <= this.el.offsetTop;
|
||||
|
||||
if (this.isBottom) {
|
||||
this.isBottom = false;
|
||||
this.spacer.style.marginTop = `${this.lastScrollTop + this.marginTop - this.offsetTop - overflow}px`;
|
||||
this.spacer.style.marginTop = `${this.globalHeaderHeight + this.lastScrollTop + this.marginTop - this.offsetTop - overflow}px`;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,312 +0,0 @@
|
||||
import autobind from 'autobind-decorator';
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import ReconnectingWebsocket from 'reconnecting-websocket';
|
||||
import { markRaw } from 'vue';
|
||||
import { debug, wsUrl } from '@client/config';
|
||||
import { query as urlQuery } from '../../prelude/url';
|
||||
|
||||
/**
|
||||
* Misskey stream connection
|
||||
*/
|
||||
export default class Stream extends EventEmitter {
|
||||
private stream: ReconnectingWebsocket;
|
||||
public state: 'initializing' | 'reconnecting' | 'connected' = 'initializing';
|
||||
private sharedConnectionPools: Pool[] = [];
|
||||
private sharedConnections: SharedConnection[] = [];
|
||||
private nonSharedConnections: NonSharedConnection[] = [];
|
||||
|
||||
@autobind
|
||||
public init(user): void {
|
||||
const query = urlQuery({
|
||||
i: user?.token,
|
||||
_t: Date.now(),
|
||||
});
|
||||
|
||||
this.stream = new ReconnectingWebsocket(`${wsUrl}?${query}`, '', { minReconnectionDelay: 1 }); // https://github.com/pladaria/reconnecting-websocket/issues/91
|
||||
this.stream.addEventListener('open', this.onOpen);
|
||||
this.stream.addEventListener('close', this.onClose);
|
||||
this.stream.addEventListener('message', this.onMessage);
|
||||
}
|
||||
|
||||
@autobind
|
||||
public useSharedConnection(channel: string, name?: string): SharedConnection {
|
||||
let pool = this.sharedConnectionPools.find(p => p.channel === channel);
|
||||
|
||||
if (pool == null) {
|
||||
pool = new Pool(this, channel);
|
||||
this.sharedConnectionPools.push(pool);
|
||||
}
|
||||
|
||||
const connection = markRaw(new SharedConnection(this, channel, pool, name));
|
||||
this.sharedConnections.push(connection);
|
||||
return connection;
|
||||
}
|
||||
|
||||
@autobind
|
||||
public removeSharedConnection(connection: SharedConnection) {
|
||||
this.sharedConnections = this.sharedConnections.filter(c => c !== connection);
|
||||
}
|
||||
|
||||
@autobind
|
||||
public removeSharedConnectionPool(pool: Pool) {
|
||||
this.sharedConnectionPools = this.sharedConnectionPools.filter(p => p !== pool);
|
||||
}
|
||||
|
||||
@autobind
|
||||
public connectToChannel(channel: string, params?: any): NonSharedConnection {
|
||||
const connection = markRaw(new NonSharedConnection(this, channel, params));
|
||||
this.nonSharedConnections.push(connection);
|
||||
return connection;
|
||||
}
|
||||
|
||||
@autobind
|
||||
public disconnectToChannel(connection: NonSharedConnection) {
|
||||
this.nonSharedConnections = this.nonSharedConnections.filter(c => c !== connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback of when open connection
|
||||
*/
|
||||
@autobind
|
||||
private onOpen() {
|
||||
const isReconnect = this.state === 'reconnecting';
|
||||
|
||||
this.state = 'connected';
|
||||
this.emit('_connected_');
|
||||
|
||||
// チャンネル再接続
|
||||
if (isReconnect) {
|
||||
for (const p of this.sharedConnectionPools)
|
||||
p.connect();
|
||||
for (const c of this.nonSharedConnections)
|
||||
c.connect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback of when close connection
|
||||
*/
|
||||
@autobind
|
||||
private onClose() {
|
||||
if (this.state === 'connected') {
|
||||
this.state = 'reconnecting';
|
||||
this.emit('_disconnected_');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback of when received a message from connection
|
||||
*/
|
||||
@autobind
|
||||
private onMessage(message) {
|
||||
const { type, body } = JSON.parse(message.data);
|
||||
|
||||
if (type === 'channel') {
|
||||
const id = body.id;
|
||||
|
||||
let connections: Connection[];
|
||||
|
||||
connections = this.sharedConnections.filter(c => c.id === id);
|
||||
|
||||
if (connections.length === 0) {
|
||||
connections = [this.nonSharedConnections.find(c => c.id === id)];
|
||||
}
|
||||
|
||||
for (const c of connections.filter(c => c != null)) {
|
||||
c.emit(body.type, Object.freeze(body.body));
|
||||
if (debug) c.inCount++;
|
||||
}
|
||||
} else {
|
||||
this.emit(type, Object.freeze(body));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to connection
|
||||
*/
|
||||
@autobind
|
||||
public send(typeOrPayload, payload?) {
|
||||
const data = payload === undefined ? typeOrPayload : {
|
||||
type: typeOrPayload,
|
||||
body: payload
|
||||
};
|
||||
|
||||
this.stream.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Close this connection
|
||||
*/
|
||||
@autobind
|
||||
public close() {
|
||||
this.stream.removeEventListener('open', this.onOpen);
|
||||
this.stream.removeEventListener('message', this.onMessage);
|
||||
}
|
||||
}
|
||||
|
||||
let idCounter = 0;
|
||||
|
||||
class Pool {
|
||||
public channel: string;
|
||||
public id: string;
|
||||
protected stream: Stream;
|
||||
public users = 0;
|
||||
private disposeTimerId: any;
|
||||
private isConnected = false;
|
||||
|
||||
constructor(stream: Stream, channel: string) {
|
||||
this.channel = channel;
|
||||
this.stream = stream;
|
||||
|
||||
this.id = (++idCounter).toString();
|
||||
|
||||
this.stream.on('_disconnected_', this.onStreamDisconnected);
|
||||
}
|
||||
|
||||
@autobind
|
||||
private onStreamDisconnected() {
|
||||
this.isConnected = false;
|
||||
}
|
||||
|
||||
@autobind
|
||||
public inc() {
|
||||
if (this.users === 0 && !this.isConnected) {
|
||||
this.connect();
|
||||
}
|
||||
|
||||
this.users++;
|
||||
|
||||
// タイマー解除
|
||||
if (this.disposeTimerId) {
|
||||
clearTimeout(this.disposeTimerId);
|
||||
this.disposeTimerId = null;
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
public dec() {
|
||||
this.users--;
|
||||
|
||||
// そのコネクションの利用者が誰もいなくなったら
|
||||
if (this.users === 0) {
|
||||
// また直ぐに再利用される可能性があるので、一定時間待ち、
|
||||
// 新たな利用者が現れなければコネクションを切断する
|
||||
this.disposeTimerId = setTimeout(() => {
|
||||
this.disconnect();
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
public connect() {
|
||||
if (this.isConnected) return;
|
||||
this.isConnected = true;
|
||||
this.stream.send('connect', {
|
||||
channel: this.channel,
|
||||
id: this.id
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
private disconnect() {
|
||||
this.stream.off('_disconnected_', this.onStreamDisconnected);
|
||||
this.stream.send('disconnect', { id: this.id });
|
||||
this.stream.removeSharedConnectionPool(this);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Connection extends EventEmitter {
|
||||
public channel: string;
|
||||
protected stream: Stream;
|
||||
public abstract id: string;
|
||||
|
||||
public name?: string; // for debug
|
||||
public inCount: number = 0; // for debug
|
||||
public outCount: number = 0; // for debug
|
||||
|
||||
constructor(stream: Stream, channel: string, name?: string) {
|
||||
super();
|
||||
|
||||
this.stream = stream;
|
||||
this.channel = channel;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@autobind
|
||||
public send(id: string, typeOrPayload, payload?) {
|
||||
const type = payload === undefined ? typeOrPayload.type : typeOrPayload;
|
||||
const body = payload === undefined ? typeOrPayload.body : payload;
|
||||
|
||||
this.stream.send('ch', {
|
||||
id: id,
|
||||
type: type,
|
||||
body: body
|
||||
});
|
||||
|
||||
if (debug) this.outCount++;
|
||||
}
|
||||
|
||||
public abstract dispose(): void;
|
||||
}
|
||||
|
||||
class SharedConnection extends Connection {
|
||||
private pool: Pool;
|
||||
|
||||
public get id(): string {
|
||||
return this.pool.id;
|
||||
}
|
||||
|
||||
constructor(stream: Stream, channel: string, pool: Pool, name?: string) {
|
||||
super(stream, channel, name);
|
||||
|
||||
this.pool = pool;
|
||||
this.pool.inc();
|
||||
}
|
||||
|
||||
@autobind
|
||||
public send(typeOrPayload, payload?) {
|
||||
super.send(this.pool.id, typeOrPayload, payload);
|
||||
}
|
||||
|
||||
@autobind
|
||||
public dispose() {
|
||||
this.pool.dec();
|
||||
this.removeAllListeners();
|
||||
this.stream.removeSharedConnection(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NonSharedConnection extends Connection {
|
||||
public id: string;
|
||||
protected params: any;
|
||||
|
||||
constructor(stream: Stream, channel: string, params?: any) {
|
||||
super(stream, channel);
|
||||
|
||||
this.params = params;
|
||||
this.id = (++idCounter).toString();
|
||||
|
||||
this.connect();
|
||||
}
|
||||
|
||||
@autobind
|
||||
public connect() {
|
||||
this.stream.send('connect', {
|
||||
channel: this.channel,
|
||||
id: this.id,
|
||||
params: this.params
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
public send(typeOrPayload, payload?) {
|
||||
super.send(this.id, typeOrPayload, payload);
|
||||
}
|
||||
|
||||
@autobind
|
||||
public dispose() {
|
||||
this.removeAllListeners();
|
||||
this.stream.send('disconnect', { id: this.id });
|
||||
this.stream.disconnectToChannel(this);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user