Merge branch 'develop'

This commit is contained in:
syuilo 2020-03-22 10:59:27 +09:00
commit 7f0084a7ed
41 changed files with 1698 additions and 164 deletions

View file

@ -1,6 +1,33 @@
ChangeLog
=========
12.22.0 (2020/02/23)
-------------------
### ✨Improvements
* Web UI のデザインを大幅に変更
* 通知のポップアップ表示を廃止
* リモートユーザーであっても投稿数、フォロー・フォロワー数を表示
* リモートユーザーであるという警告を投稿ページでも表示
* ユーザー名のサジェストをアクティブであるユーザー順に表示
* 通知音の音量スライダーなど、スライダーへのデザイン適用
* リアクション設定機能を刷新
* 同じホットキーが連続で発動しないように
* 同じノートを何回リノートしても一回として数えるように
* ElasticSearch で認証ができるように
### 🐛Fixes
* ユーザー名を設定していないユーザーのノートページのタイトルが「のノート」になる問題を修正
* ソーシャルアカウントでの連携ログインができない問題を修正
* アプリ認証画面でログインしたときに正常に遷移できない問題を修正
* オブジェクトストレージでS3のvirtual-host形式のサポートなど
* GIF 画像のバッジの色合いを修正
* ートのテキストがMFMの使い方によってははみ出る問題を修正
* ダークテーマ利用時にセレクトが使いにくくなる問題を修正
* ボリュームを0にしてもサウンドが鳴動している問題を修正
* 検索窓のスタイルが適用されていなかった問題を修正
12.21.0 (2020/02/23)
-------------------
### ✨Improvements

View file

@ -89,6 +89,9 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><img src="https://avatars1.githubusercontent.com/u/30769358?s=460&v=4" alt="mei23" width="100"></td>
<td><img src="https://avatars2.githubusercontent.com/u/20679825?s=460&v=4" alt="acid-chicken" width="100"></td>
<td><img src="https://avatars2.githubusercontent.com/u/6533808?s=460&v=4" alt="rinsuki" width="100"></td>
<td><img src="https://avatars0.githubusercontent.com/u/7973572?s=460&v=4" alt="tamaina" width="100"></td>
<td><img src="https://avatars1.githubusercontent.com/u/7106976?s=460&v=4" alt="Xeltica" width="100"></td>
<td><img src="https://avatars1.githubusercontent.com/u/17376330?s=460&v=4" alt="u1-liquid" width="100"></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/syuilo">@syuilo</a></td>
@ -96,6 +99,9 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td align="center"><a href="https://github.com/mei23">@mei23</a></td>
<td align="center"><a href="https://github.com/acid-chicken">@acid-chicken</a></td>
<td align="center"><a href="https://github.com/rinsuki">@rinsuki</a></td>
<td align="center"><a href="https://github.com/tamaina">@tamaina</a></td>
<td align="center"><a href="https://github.com/Xeltica">@Xeltica</a></td>
<td align="center"><a href="https://github.com/u1-liquid">@u1-liquid</a></td>
</tr>
</table>

View file

@ -49,63 +49,649 @@ import: "Importieren"
export: "Exportieren"
files: "Dateien"
download: "Download"
driveFileDeleteConfirm: "Möchtest du die Datei \"{name}\" löschen? Die zugehörige Notiz wird ebenso verschwinden."
unfollowConfirm: "Möchtest du {name} nicht mehr folgen?"
lists: "Listen"
noLists: "Keine Liste!"
note: "Noten"
note: "Notiz"
notes: "Notizen"
following: "Folgen"
followers: "Folgende"
followsYou: "Folgt dir"
createList: "Liste erstellen"
manageLists: "Liste verwalten"
error: "Ein Problem ist aufgetreten"
retry: "Wiederholen"
enterListName: "Listennamen eingeben"
privacy: "Privatsphäre"
makeFollowManuallyApprove: "Folgeanfragen benötigen Bestätigung"
defaultNoteVisibility: "Die Standardsichtbarkeit"
follow: "Folgen"
followRequest: "Follower-Anfragen"
followRequests: "Follower-Anfragen"
unfollow: "Nicht mehr folgen"
followRequestPending: "Ausstehend"
enterEmoji: "Gib ein Emoji ein"
renote: "Renote"
unrenote: "Renote zurücknehmen"
quote: "Zitieren"
pinnedNote: "Angepinnte Notiz"
you: "Du"
clickToShow: "Klicke zum den Inhalt anzusehen"
sensitive: "Dieser Inhalt ist NSFW"
add: "Hinzufügen"
reaction: "Reaktionen"
reactionSettingDescription: "Weisen Sie Ihre lieblings reaktionen zu, die Sie in den Reaktionenswähler stecken möchten."
rememberNoteVisibility: "Notizsichtbarkeit merken"
renameFile: "Datei umbenennen"
attachCancel: "Anhängen abbrechen"
markAsSensitive: "Als sensitiv markieren"
unmarkAsSensitive: "Markierung als sensitiv zurücknehmen"
enterFileName: "Dateinamen eingeben"
mute: "Stummschalten"
unmute: "Stummschaltung aufheben"
block: "Blockieren"
unblock: "Blockierung aufheben"
suspend: "Sperren"
unsuspend: "Sperrung aufheben"
blockConfirm: "Möchtest du diesen Account wirklich blockieren?"
unblockConfirm: "Möchtest du diese Blockierung wirklich aufheben?"
suspendConfirm: "Möchtest du diesen Account wirklich sperren?"
unsuspendConfirm: "Möchtest du die Sperrung dieses Accounts wirklich aufheben?"
selectList: "Wähle eine Liste aus"
customEmojis: "Benutzerdefinierte Emojis"
emojiName: "Emojiname"
emojiUrl: "Emoji-URL"
addEmoji: "Emoji hinzufügen"
flagAsBot: "Als Bot markieren"
flagAsCat: "Als Katze markieren"
autoAcceptFollowed: "Folgeanfragen automatisch akzeptieren"
addAcount: "Benutzerkonto hinzufügen"
loginFailed: "Login fehlgeschlagen"
general: "Allgemein"
wallpaper: "Hintergrund"
removeWallpaper: "Hintergrund entfernen"
searchWith: "Suche: {q}"
youHaveNoLists: "Du hast keine Listen"
followConfirm: "Möchtest du {name} wirklich folgen?"
selectUser: "Benutzer wählen"
recipient: "Empfänger"
annotation: "Anmerkung"
federation: "Föderation"
instances: "Instanz"
latestStatus: "Neuester Status"
storageUsage: "Speicherplatzverbrauch"
charts: "Charts"
perHour: "Pro Stunde"
perDay: "Pro Tag"
blockThisInstance: "Diese Instanz blockieren"
version: "Version"
metadata: "Metadaten"
withNFiles: "{n} Datei(en)"
jobQueue: "Job-Warteschlange"
cpuAndMemory: "CPU und Arbeitsspeicher"
network: "Netzwerk"
disk: "Festplatte"
instanceInfo: "Instanzinformationen"
statistics: "Statistiken"
clearQueue: "Warteschlange leeren"
clearQueueConfirmTitle: "Möchtest du die Warteschlange wirklich leeren?"
clearQueueConfirmText: "Jegliche Notizen, die sich noch in der Warteschlange befinden, werden hierdurch nicht föderiert. Diese Aktion wird normalerweise NICHT benötigt."
clearCachedFiles: "Cache leeren"
blockedInstances: "Blockierte Instanzen"
blockedInstancesDescription: "Gib den Hostnamen der Instanz an, die blockiert werden soll. Blockierte Instanzen können nicht mehr mit dieser kommunizieren."
muteAndBlock: "Stummgeschaltet / Blockiert"
mutedUsers: "Stummgestellte Benutzer"
blockedUsers: "Blockierte Benutzer"
noUsers: "Keine Benutzer"
editProfile: "Profil bearbeiten"
noteDeleteConfirm: "Möchtest du diese Notiz wirklich löschen?"
pinLimitExceeded: "Du kannst nicht noch mehr Notizen anpinnen."
intro: "Misskey Installation abgeschlossen! Lass uns nun ein Administratorkonto erstellen."
done: "Fertig"
processing: "In Bearbeitung"
preview: "Vorschau"
default: "Standard"
noCustomEmojis: "Es existieren keine Emojis"
noJobs: "Es gibt keine Jobs"
federating: "Föderiert"
blocked: "Blockiert"
suspended: "Gesperrt"
all: "Alles"
changePassword: "Passwort ändern"
security: "Sicherheit"
retypedNotMatch: "Eingaben stimmen nicht überein."
currentPassword: "Momentanes Passwort"
newPassword: "Neues Passwort"
newPasswordRetype: "Neues Passwort (wiederholen)"
attachFile: "Datei anhängen"
more: "Mehr!"
featured: "Hervorgehoben"
usernameOrUserId: "Benutzername oder Benutzer-ID"
noSuchUser: "Benutzer nicht gefunden"
announcements: "Ankündigungen"
imageUrl: "Bild-URL"
remove: "Löschen"
removed: "Erfolgreich gelöscht"
removeAreYouSure: "Möchtest du \"{x}\" wirklich löschen?"
saved: "Gespeichert"
messaging: "Nachrichten"
upload: "Hochladen"
fromDrive: "Aus Drive"
fromUrl: "Von einer URL"
explore: "Erkunden"
games: "Misskey Spiele"
messageRead: "Gelesen"
recentUsedEmojis: "Kürzlich genutzte Emojis"
noMoreHistory: "Kein weiterer Verlauf vorhanden"
nUsersRead: "Von {n} gelesen"
agreeTo: "Ich stimme {0} zu"
tos: "Nutzungsbedingungen"
start: "Anfangen"
home: "Startseite"
activity: "Aktivität"
images: "Bilder"
birthday: "Geburtstag"
yearsOld: "{age} Jahre alt"
registeredDate: "Registierdatum"
location: "Ort"
theme: "Farbthemen"
lightThemes: "Helle Farbthemen"
darkThemes: "Dunkle Farbthemen"
drive: "Drive"
selectFile: "Datei auswählen"
selectFiles: "Dateien auswählen"
renameFolder: "Ordner umbenennen"
createFolder: "Ordner erstellen"
deleteFolder: "Ordner löschen"
addFile: "Datei hinzufügen"
emptyDrive: "Drive ist leer"
emptyFolder: "Der Ordner ist leer"
copyUrl: "URL kopieren"
rename: "Umbenennen"
avatar: "Profilbild"
banner: "Banner"
nsfw: "Dieser Inhalt ist NSFW"
disconnectedFromServer: "Verbindung zum Server wurde getrennt"
reload: "Aktualisieren"
doNothing: "Ignorieren"
watch: "Beobachten"
unwatch: "Nicht mehr beobachten"
accept: "Akzeptieren"
reject: "Ablehnen"
instanceName: "Name der Instanz"
instanceDescription: "Beschreibung der Instanz"
maintainerName: "Betreiber"
maintainerEmail: "Betreiberemail"
tosUrl: "URL der Nutzungsbedingungen"
thisYear: "Dieses Jahr"
thisMonth: "Dieser Monat"
today: "Heute"
pages: "Seiten"
integration: "Integration"
connectSerice: "Verbinden"
disconnectSerice: "Trennen"
registration: "Registrieren"
enableRegistration: "Registration neuer Benutzer erlauben"
invite: "Einladen"
driveCapacityPerLocalAccount: "Drivekapazität pro lokales Benutzerkonto"
inMb: "In Megabytes"
iconUrl: "Icon-URL"
bannerUrl: "Banner-URL"
basicInfo: "Basisdaten"
pinnedUsers: "Angepinnte Benutzer"
pinnedUsersDescription: "Gib einen Benutzernamen pro Zeile ein. Diese werden im \"Erkunden\" Tab angezeigt."
recaptcha: "reCAPTCHA"
enableRecaptcha: "reCAPTCHA aktivieren"
antennas: "Antennen"
manageAntennas: "Antennen verwalten"
name: "Name"
antennaSource: "Antennenquelle"
antennaKeywords: "Schlüsselwörter, die beobachtet werden sollen"
antennaExcludeKeywords: "Schlüsselwörter, die ignoriert werden sollen"
antennaKeywordsDescription: "Mit Leerzeichen für eine \"UND\"-Verknüpfung trennen, durch Zeilenumbrüche für eine \"ODER\"-Verknüpfung trennen."
serviceworker: "ServiceWorker"
enableServiceworker: "ServiceWorker aktivieren"
antennaUsersDescription: "Benutzernamen getrennt durch Zeilenumbrüche angeben"
caseSensitive: "Groß-/Kleinschreibung unterscheiden"
withReplies: "Antworten beinhalten"
connectedTo: "Mit folgenden Benutzerkonten verknüpft"
notesAndReplies: "Notizen und Antworten"
withFiles: "Dateien beinhalten"
popularUsers: "Beliebte Benutzer"
recentlyUpdatedUsers: "Vor kurzem aktive Benutzer"
recentlyRegisteredUsers: "Vor kurzem registrierte Benutzer"
recentlyDiscoveredUsers: "Vor kurzem gefundene Benutzer"
exploreUsersCount: "Es gibt {count} Benutzer"
exploreFediverse: "Das Fediverse erkunden"
userList: "Listen"
aboutMisskey: "Über Misskey"
resetPassword: "Passwort zurücksetzen"
newPasswordIs: "Das neue Passwort ist \"{password}\""
posted: "Gesendet"
autoReloadWhenDisconnected: "Automatisch aktualisieren wenn die Serververbindung getrennt wird"
autoNoteWatch: "Notiz automatisch beobachten"
autoNoteWatchDescription: "Werde über Notizen, auf die du reagiert oder geantwortet hast, informiert"
reduceUiAnimation: "Animationen der Benutzeroberfläche reduzieren"
share: "Teilen"
notFound: "Nicht gefunden"
notFoundDescription: "Es konnte keine Seite unter dieser URL gefunden werden."
uploadFolder: "Standardordner für Uploads"
cacheClear: "Cache leeren"
markAsReadAllNotifications: "Alle Benachrichtigungen als gelesen markieren"
markAsReadAllUnreadNotes: "Alle Notizen als gelesen markieren"
invites: "Einladen"
title: "Betreff"
text: "Text"
enable: "Aktivieren"
next: "Weiter"
retype: "Erneut eingeben"
noteOf: "Notiz von {user}"
inviteToGroup: "Zu Gruppe einladen"
maxNoteTextLength: "Maximale Länge von Notizen"
useOsNativeEmojis: "Eingebaute Emojis des Betriebssystems benutzen"
noGroups: "Keine Gruppen vorhanden"
joinOrCreateGroup: "Lass dich zu einer Gruppe einladen oder erstelle deine eigene."
noHistory: "Kein Verlauf"
disableAnimatedMfm: "MFM, die Animationen enthalten, deaktivieren"
category: "Kategorie"
tags: "Schlagwörter"
createAccount: "Benutzerkonto erstellen"
existingAcount: "Bestehendes Benutzerkonto"
regenerate: "Regenerieren"
fontSize: "Schriftgröße"
noFollowRequests: "Du hast keine Follow-Anfragen"
openImageInNewTab: "Bilder in neuem Tab öffnen"
dashboard: "Dashboard"
local: "Lokal"
total: "Gesamt"
weekOverWeekChanges: "Wöchentlich"
dayOverDayChanges: "Täglich"
accessibility: "Barrierefreiheit"
clinetSettings: "Client-Einstellungen"
accountSettings: "Benutzerkontoeinstellungen"
promotion: "Hervorgehoben"
promote: "Hervorheben"
numberOfDays: "Anzahl der Tage"
hideThisNote: "Diese Notiz verstecken"
serverLogs: "Serverprotokolle"
deleteAll: "Alle löschen"
sounds: "Töne"
listen: "Anhören"
none: "Keine"
volume: "Lautstärke"
details: "Details"
chooseEmoji: "Wähle ein Emoji"
_sfx:
note: "Notizen"
noteMy: "Meine Notizen"
notification: "Benachrichtigungen"
chat: "Nachrichten"
chatBg: "Nachrichten (Hintergrund)"
antenna: "Antennen"
_ago:
unknown: "Unbekannt"
future: "Zukunft"
justNow: "Gerade eben"
secondsAgo: "vor {n} Sekunde(n)"
minutesAgo: "vor {n} Minute(n)"
hoursAgo: "vor {n} Stunde(n)"
daysAgo: "vor {n} Tag(en)"
weeksAgo: "vor {n} Woche(n)"
monthsAgo: "vor {n} Monat(en)"
yearsAgo: "vor {n} Jahr(en)"
_time:
second: "Sekunde"
minute: "Minute"
hour: "Stunde"
_permissions:
"read:messaging": "Nachrichten lesen"
"write:messaging": "Nachrichten schicken oder löschen"
"read:reactions": "Reaktionen sehen"
"write:reactions": "Reaktionen hinzufügen und bearbeiten"
_weekday:
sunday: "Sonntag"
monday: "Montag"
tuesday: "Dienstag"
wednesday: "Mittwoch"
thursday: "Donnerstag"
friday: "Freitag"
saturday: "Samstag"
_widgets:
memo: "Memo"
notifications: "Benachrichtigungen"
timeline: "Zeitleiste"
calendar: "Kalender"
trends: "Trends"
clock: "Uhr"
rss: "RSS-Reader"
activity: "Aktivität"
photos: "Fotos"
_cw:
hide: "Ausblenden"
show: "Zeige mehr"
chars: "{count} Zeichen"
files: "{count} Dateien"
poll: "Umfrage"
_poll:
noOnlyOneChoice: "Mindestens zwei Antwortmöglichkeiten werden benötigt."
choiceN: "Auswahl {n}"
noMore: "Du kannst keine weiteren Auswahlen hinzufügen"
canMultipleVote: "Mehrfachantworten erlauben"
expiration: "Abstimmung endet am"
infinite: "Nie"
at: "Beenden am..."
after: "Beenden nach..."
deadlineDate: "Enddatum"
deadlineTime: "Stunde"
duration: "Laufzeit"
votesCount: "{n} Stimmen"
totalVotes: "Insgesamt {n} Stimmen"
vote: "Abstimmen"
showResult: "Ergebnis anzeigen"
voted: "Abgestimmt"
closed: "Beendet"
remainingDays: "{d} Tage {h} Stunden verbleibend"
remainingHours: "{h} Stunden {m} Minuten verbleibend"
remainingMinutes: "{m} Minuten {s} Sekunden verbleibend"
remainingSeconds: "{s} Sekunden verbleibend"
_visibility:
public: "Öffentlich"
publicDescription: "Deine Notiz wird global sichtbar sein"
home: "Startseite"
followers: "Folgende"
followersDescription: "Nur für Follower sichtbar"
specified: "Direkt"
specifiedDescription: "Nur für erwähnte Benutzer sichtbar"
localOnly: "Nur Lokal"
_postForm:
replyPlaceholder: "Dieser Notiz antworten..."
quotePlaceholder: "Diese Notiz zitieren..."
_placeholders:
a: "Was machst du momentan?"
b: "Was ist um dich herum los?"
c: "Was geht dir durch den Kopf?"
d: "Was möchtest du sagen?"
e: "Fang an zu schreiben..."
f: "Ich warte darauf, dass du schreibst..."
_profile:
name: "Name"
username: "Benutzername"
description: "Über mich"
youCanIncludeHashtags: "Du kannst auch Hashtags in deiner Beschreibung verwenden."
metadata: "Andere Informationen"
metadataLabel: "Name"
metadataContent: "Inhalt"
_exportOrImport:
allNotes: "Alle Notizen"
followingList: "Folgen"
muteList: "Stummschalten"
blockingList: "Blockieren"
userLists: "Listen"
_charts:
federationInstancesIncDec: "Unterschied in der Anzahl von förderierenden Instanzen"
federationInstancesTotal: "Anzahl aller föderierenden Instanzen"
usersIncDec: "Unterschied in der Anzahl von Benutzern"
usersTotal: "Anzahl aller Benutzer"
activeUsers: "Aktive Benutzer"
notesIncDec: "Unterschied in der Anzahl von Notizen"
localNotesIncDec: "Unterschied in der Anzahl von lokalen Notizen"
notesTotal: "Anzahl aller Notizen"
filesIncDec: "Unterschied in der Anzahl von Dateien"
filesTotal: "Anzahl aller Dateien"
storageUsageIncDec: "Unterschied in der Höhe der Speichernutzung"
storageUsageTotal: "Gesamte Speichernutzung"
_instanceCharts:
requests: "Anfragen"
users: "Unterschied in der Anzahl von Benutzern"
usersTotal: "Anzahl aller Benutzer"
notes: "Unterschied in der Anzahl von Notizen"
notesTotal: "Anzahl aller Notizen"
ff: "Unterschied in der Anzahl von Followern"
ffTotal: "Gesamtanzahl der Follower"
cacheSize: "Unterschied in der Größe des Caches"
cacheSizeTotal: "Gesamtgröße des Caches"
files: "Unterschied in der Anzahl der Dateien"
filesTotal: "Gesamtanzahl der Dateien"
_timelines:
home: "Startseite"
local: "Lokal"
global: "Global"
_pages:
content: "Inhalt"
more-details: "Mehr Informationen"
title: "Titel"
url: "Seiten-URL"
summary: "Zusammenfassung"
alignCenter: "Mittig ausrichten"
hide-title-when-pinned: "Seitentitel wenn angepinnt ausblenden"
font: "Schriftart"
fontSerif: "Serif"
fontSansSerif: "Sans Serif"
chooseBlock: "Block hinzufügen"
selectType: "Wähle einen Typ"
enterVariableName: "Gib einen Namen für deine Variable ein"
the-variable-name-is-already-used: "Der Variablenname wird bereits verwendet"
content-blocks: "Inhalt"
input-blocks: "Eingabe"
special-blocks: "Speziell"
post-from-post-form: "Diesen Inhalt senden"
posted-from-post-form: "Erfolgreich gesendet!"
blocks:
text: "Text"
textarea: "Textfeld"
section: "Abschnitt"
image: "Bilder"
button: "Knopf"
if: "Falls"
_if:
variable: "Variable"
post: "Neue Notiz anfertigen"
_post:
text: "Inhalt"
textInput: "Texteingabe"
_textInput:
text: "Titel"
default: "Standardwert"
textareaInput: "Eingabe des mehrzeiligen Textfelds"
_textareaInput:
text: "Titel"
default: "Standardwert"
numberInput: "Nummereingabe"
_numberInput:
text: "Titel"
default: "Standardwert"
switch: "Fallunterscheidung"
_switch:
text: "Titel"
default: "Standardwert"
counter: "Zähler"
_counter:
text: "Titel"
inc: "Erhöhen um"
_button:
text: "Titel"
colored: "Farbig"
action: "Aktion, die beim Knopfdruck ausgeführt werden soll"
_action:
dialog: "Zeige ein Dialogfenster"
_dialog:
content: "Inhalt"
resetRandom: "Setze den Zufallswert zurück"
pushEvent: "Sende ein Event"
_pushEvent:
event: "Eventname"
message: "Nachricht, die bei Aktivierung gezeigt werden soll"
variable: "Variable, die gesendet werden soll"
no-variable: "Keine"
radioButton: "Optionsfeld"
_radioButton:
title: "Titel"
values: "Auswahlmöglichkeiten (getrennt durch Zeilenumbrüche)"
default: "Standardwert"
script:
categories:
logical: "Logische Operationen"
operation: "Berechnungen"
comparison: "Vergleiche"
random: "Zufällig"
value: "Werte"
fn: "Funktionen"
text: "Textoperationen"
convert: "Konvertierung"
list: "Listen"
blocks:
text: "Text"
multiLineText: "Text (Mehrzeilig)"
textList: "Textliste"
_textList:
info: "Trenne jeden Eintrag mit einem Zeilenumbruch"
strLen: "Textlänge"
_strLen:
arg1: "Text"
strPick: "Zeichen extrahieren"
_strPick:
arg1: "Text"
arg2: "Zeichenposition"
strReplace: "Textersetzung"
_strReplace:
arg1: "Text"
arg2: "Zu ersetzender Text"
arg3: "Ersetzen mit"
strReverse: "Text umkehren"
_strReverse:
arg1: "Text"
join: "Text zusammenfügen"
_join:
arg1: "Listen"
arg2: "Trennzeichen"
add: "Addieren"
_add:
arg1: "A"
arg2: "B"
subtract: "Subtrahieren"
_subtract:
arg1: "A"
arg2: "B"
multiply: "Multiplizieren"
_multiply:
arg1: "A"
arg2: "B"
divide: "Teilen"
_divide:
arg1: "A"
arg2: "B"
mod: "Rest"
_mod:
arg1: "A"
arg2: "B"
round: "Runden"
_round:
arg1: "Nummer"
eq: "A und B sind gleich"
_eq:
arg1: "A"
arg2: "B"
notEq: "A und B sind nicht gleich"
_notEq:
arg1: "A"
arg2: "B"
and: "A UND B"
_and:
arg1: "A"
arg2: "B"
or: "A ODER B"
_or:
arg1: "A"
arg2: "B"
lt: "< A ist kleiner als B"
_lt:
arg1: "A"
arg2: "B"
gt: "> A ist größer als B"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A ist kleiner als oder gleich B"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A ist größer als oder gleich B"
_gtEq:
arg1: "A"
arg2: "B"
if: "Kondition"
_if:
arg1: "Falls"
arg2: "Wenn wahr"
arg3: "Sonst"
not: "NICHT"
_not:
arg1: "NICHT"
random: "Zufällig"
_random:
arg1: "Warscheinlichkeit"
rannum: "Zufallsnummer"
_rannum:
arg1: "Minimum"
arg2: "Maximum"
randomPick: "Zufallswahl aus Liste"
_randomPick:
arg1: "Listen"
dailyRandom: "Zufallswahl (Läuft für einen Tag)"
_dailyRandom:
arg1: "Warscheinlichkeit"
dailyRannum: "Zufallsnummer (Läuft für einen Tag)"
_dailyRannum:
arg1: "Minimum"
arg2: "Maximum"
dailyRandomPick: "Zufallswahl aus Liste (Läuft für einen Tag)"
_dailyRandomPick:
arg1: "Listen"
seedRandom: "Zufällig (mit Startwert / Seed)"
_seedRandom:
arg1: "Startwert / Seed"
arg2: "Warscheinlichkeit"
seedRannum: "Zufallsnummer (mit Startwert / Seed)"
_seedRannum:
arg1: "Startwert / Seed"
arg2: "Minimum"
arg3: "Maximum"
seedRandomPick: "Zufallswahl aus Liste (mit Startwert / Seed)"
_seedRandomPick:
arg1: "Startwert / Seed"
arg2: "Listen"
DRPWPM: "Zufallswahl aus gewichteter Liste (Läuft für einen Tag)"
_DRPWPM:
arg1: "Textliste"
pick: "Aus einer Liste wählen"
_pick:
arg1: "Listen"
arg2: "Position"
listLen: "Listenlänge abrufen"
_listLen:
arg1: "Listen"
number: "Nummer"
stringToNumber: "Text zu Nummer"
_stringToNumber:
arg1: "Text"
numberToString: "Nummer zu Text"
_numberToString:
arg1: "Nummer"
splitStrByLine: "Text nach Zeilenumbrüchen aufteilen"
_splitStrByLine:
arg1: "Text"
fn: "Funktionen"
_fn:
arg1: "Ausgabe"
for: "Wiederholen"
_for:
arg1: "Anzahl der Wiederholungen"
arg2: "Aktion"
types:
string: "Text"
number: "Nummer"
array: "Listen"
stringArray: "Textliste"
enviromentVariables: "Umgebungsvariable"
pageVariables: "Seitenelement"

View file

@ -1,6 +1,6 @@
---
_lang_: "English"
introMisskey: "Welcome! Misskey is an open source and also decentralized microblogging service.\nWrite the \"notes\" to share what is happening now, or send out your own words to everyone 📡\nWith the \"reactions\", you can add your feelings to everyone's notes faster than anyone 👍\nLet's explore the new world 🚀"
introMisskey: "Welcome! Misskey is an open source, and also a decentralized microblogging service.\nCreate \"notes\" to share what is happening now, or to share it with everyone around you 📡\nWith \"reactions\", you can also quickly express your feelings about everyone's notes 👍\nLet's explore a new world 🚀"
monthAndDay: "{month}/{day}"
search: "Search"
notifications: "Notifications"
@ -84,7 +84,7 @@ clickToShow: "Click to show"
sensitive: "NSFW"
add: "Add"
reaction: "Reaction"
reactionSettingDescription: "Customize reaction picker emojis (separated by line breaks)"
reactionSettingDescription: "Assign your favorite reactions which want to pin in reaction picker."
rememberNoteVisibility: "Remember note visibility settings"
renameFile: "Rename file"
attachCancel: "Remove attachment"
@ -168,6 +168,7 @@ intro: "Installation of Misskey has been finished! Please create an admin user."
done: "Done"
processing: "Processing"
preview: "Preview"
default: "Default"
noCustomEmojis: "There are no emojis"
customEmojisOfRemote: "Emojis from other instances"
noJobs: "There are no jobs"
@ -331,7 +332,7 @@ unregister: "Unregister"
passwordLessLogin: "Set up password-less login"
resetPassword: "Reset password"
newPasswordIs: "The new password is \"{password}\""
post: "Notes"
post: "Post"
posted: "Posted!"
autoReloadWhenDisconnected: "Auto reload when disconnected with server"
autoNoteWatch: "Watch note automatically"
@ -422,15 +423,28 @@ hideThisNote: "Hide this note"
showFeaturedNotesInTimeline: "Show Featured notes in Timeline"
objectStorage: "Object Storage"
useObjectStorage: "Use object storage"
objectStorageBaseUrl: "Base URL"
objectStorageBaseUrlDesc: "URL prefix used for construct URL to object (media) referencing. Specify its URL if you are using a CDN or Proxy, otherwise specify the address that publicly accessible according to the guide of service that you're going to use. i.g 'https://<bucket>.s3.amazonaws.com' for AWS S3, and 'https://storage.googleapis.com/<bucket>' for GCS."
objectStorageBucket: "Bucket"
objectStorageBucketDesc: "Please specify the bucket name used on configured service."
objectStoragePrefix: "Prefix"
objectStoragePrefixDesc: "Files will stored under the directory of this prefix."
objectStorageEndpoint: "Endpoint"
objectStorageEndpointDesc: "Leave this empty if you are using AWS S3, otherwise specify the endpoint as '<host>' or '<host>:<port>' according to the guide of service that you're going to use."
objectStorageRegion: "Region"
objectStorageRegionDesc: "Specify a region like 'xx-east-1'. If your service does not have distinction about regions, leave it blank or fill with 'us-east-1'."
objectStorageUseSSL: "Use SSL"
objectStorageUseSSLDesc: "Turn off this if you are not going to use HTTPS for API connection"
serverLogs: "Server logs"
deleteAll: "Delete all"
showFixedPostForm: "Display the posting form at the top of the timeline"
newNoteRecived: "You've got a new note"
useNotificationsPopup: "Display notification list in popup"
sounds: "Sounds"
listen: "Listen"
none: "None"
volume: "Volume"
details: "Details"
chooseEmoji: "Choose an emoji"
_sfx:
note: "New note"
noteMy: "My note"
@ -458,11 +472,11 @@ _tutorial:
title: "How to use Misskey"
step1_1: "Welcome!"
step1_2: "This page is called \"timeline\". It shows chronologically ordered \"notes\" of people who you \"follow\"."
step1_3: "Your timeline is currently empty, since you have not posed any notes or followed anyone yet."
step1_3: "Your timeline is currently empty, since you have not posted any notes or followed anyone yet."
step2_1: "Let's finish setting up your profile before writing a note or following anyone."
step2_2: "Providing some information about who you are will make it easier for others to follow you back."
step3_1: "Finished setting up your profile?"
step3_2: "The next step is to post a note. You can do this by pressing a pencil icon on the screen."
step3_2: "The next step is to post a note. You can do this by pressing the pencil icon on the screen."
step3_3: "Fill in the modal and press the button on the right top to post."
step3_4: "Have nothing to say? Try \"just setting up my msky\"!"
step4_1: "Finished posting your first note?"
@ -473,7 +487,7 @@ _tutorial:
step5_4: "If the other user has a lock icon next to their name, that user will have to manually approve your follow request."
step6_1: "Now you will be able to see other users' notes on your timeline."
step6_2: "You can also put \"reactions\" on other people's notes to quickly respond."
step6_3: "To attach a \"reaction\", press \"+\" mark on other user's note and choose an emoji you'd like to react with."
step6_3: "To attach a \"reaction\", press the \"+\" mark on another user's note and choose an emoji you'd like to react with."
step7_1: "Congratulations! You have now finished Misskey's basic tutorial."
step7_2: "If you would like to learn more about Misskey, try the {help} section."
step7_3: "Good luck and have fun! 🚀"

View file

@ -84,7 +84,7 @@ clickToShow: "Click para ver"
sensitive: "Marcado como sensible"
add: "Añadir"
reaction: "Reacción"
reactionSettingDescription: "Elegir las reacciones mostradas en el seleccionador de reacciones, separadas por una nueva linea"
reactionSettingDescription: "Asigne sus reacción favoritas que desean anclar en el selector de reacciones."
rememberNoteVisibility: "Recordar visibilidad"
renameFile: "Renombrar archivo"
attachCancel: "Quitar adjunto"
@ -168,6 +168,7 @@ intro: "¡La instalación de Misskey ha terminado! Crea el usuario administrador
done: "Terminado"
processing: "Procesando"
preview: "Vista previa"
default: "Predeterminado"
noCustomEmojis: "No hay emojis personalizados"
customEmojisOfRemote: "Emojis remotos"
noJobs: "No hay trabajos"
@ -422,15 +423,28 @@ hideThisNote: "Ocultar esta nota"
showFeaturedNotesInTimeline: "Mostrar notas destacadas en la línea de tiempo"
objectStorage: "Almacenamiento de objetos"
useObjectStorage: "Usar almacenamiento de objetos"
objectStorageBaseUrl: "Base URL"
objectStorageBaseUrlDesc: "Prefijo de URL utilizado para construir URL para hacer referencia a objetos (medios). Especifique su URL si está utilizando un CDN o Proxy; de lo contrario, especifique la dirección a la que se puede acceder públicamente de acuerdo con la guía de servicio que va a utilizar. i.g 'https://<bucket>.s3.amazonaws.com' para AWS S3 y 'https://storage.googleapis.com/<bucket>' para GCS."
objectStorageBucket: "Bucket"
objectStorageBucketDesc: "Especifique el nombre del depósito utilizado en el servicio configurado."
objectStoragePrefix: "Prefix"
objectStoragePrefixDesc: "Los archivos se almacenarán en el directorio de este prefijo."
objectStorageEndpoint: "Endpoint"
objectStorageEndpointDesc: "Deje esto en blanco si está utilizando AWS S3; de lo contrario, especifique el punto final como '<host>' o '<host>: <port>' de acuerdo con la guía de servicio que va a utilizar."
objectStorageRegion: "Region"
objectStorageRegionDesc: "Especifique una región como 'xx-east-1'. Si su servicio no tiene distinción sobre regiones, déjelo en blanco o complete con 'us-east-1'."
objectStorageUseSSL: "Usar SSL"
objectStorageUseSSLDesc: "Desactive esto si no va a usar HTTPS para la conexión API"
serverLogs: "Registros del servidor"
deleteAll: "Eliminar todos"
showFixedPostForm: "Mostrar el formulario de las entradas encima de la línea de tiempo"
newNoteRecived: "Tienes una nota nuevo"
useNotificationsPopup: "Mostrar lista de notificaciones en ventana emergente"
sounds: "Sonidos"
listen: "Escuchar"
none: "Ninguna"
volume: "Volumen"
details: "Detalles"
chooseEmoji: "Elije un emoji"
_sfx:
note: "Notas"
noteMy: "Nota (a mí mismo)"

View file

@ -40,9 +40,9 @@ sendMessage: "Envoyer un message"
copyUsername: "Copier le nom d'utilisateur"
reply: "Répondre"
loadMore: "Voir plus"
youGotNewFollower: "Vous a suivi"
receiveFollowRequest: "Demande de suivi reçue"
followRequestAccepted: "Suivre la demande acceptée"
youGotNewFollower: "Vous a abonnés"
receiveFollowRequest: "Demande de abonnés reçue"
followRequestAccepted: "L'abonne la demande acceptée"
mentions: "Mentions"
directNotes: "Messages directs"
importAndExport: "Import et export"
@ -51,7 +51,7 @@ export: "Exporter"
files: "Fichier·s"
download: "Télécharger"
driveFileDeleteConfirm: "Êtes-vous sûr·e de vouloir supprimer le fichier \"{name}\" ? Les notes avec ce fichier joint seront aussi supprimées."
unfollowConfirm: "Êtes-vous sûr·e ne plus vouloir suivre {name} ?"
unfollowConfirm: "Êtes-vous sûr·de ne plus vouloir abonne {name} ?"
exportRequested: "Vous avez demandé une exportation. Cela pourrait prendre un peu de temps. Une fois l'exportation terminée, le fichier résultant sera ajouté dans le Drive."
importRequested: "Vous avez initié un import. Cela pourrait prendre un peu de temps."
lists: "Listes"
@ -84,7 +84,7 @@ clickToShow: "Cliquer pour afficher"
sensitive: "Contenu sensible"
add: "Ajouter"
reaction: "Réactions"
reactionSettingDescription: "Personnaliser les émojis à afficher dans le sélecteur de réactions, délimités par les sauts de ligne."
reactionSettingDescription: "Attribuez vos réactions préférées qui souhaitent épingler le sélecteur de réaction."
rememberNoteVisibility: "Se souvenir de la visibilité des notes"
renameFile: "Renommer le ficher"
attachCancel: "Enlever le fichier attaché"
@ -119,9 +119,9 @@ wallpaper: "Arrière plan"
removeWallpaper: "Supprimer l'arrière plan"
searchWith: "Recherche : {q}"
youHaveNoLists: "Vous n'avez aucune liste"
followConfirm: "Désirez-vous suivre {name} ?"
followConfirm: "Désirez-vous abonne {name} ?"
proxyAccount: "Compte proxy"
proxyAccountDescription: "Un compte proxy se comporte, dans certaines conditions, comme un·e abonné·e distant pour les utilisateurs d'autres instances.\nExemple : quand un·e utilisateur·rice distant·e est ajouté·e à une liste, ses notes ne serait pas visibles sur l'instance si personne ne le·la suit. Le compte proxy va donc le·la suivre pour que ses notes soient acheminées."
proxyAccountDescription: "Un compte proxy se comporte, dans certaines conditions, comme un·e abonné·e distant pour les utilisateurs d'autres instances.\nExemple : quand un·e utilisateur·rice distant·e est ajouté·e à une liste, ses notes ne serait pas visibles sur l'instance si personne ne le·la abonné. Le compte proxy va donc le·la abonne pour que ses notes soient acheminées."
host: "Hôte"
selectUser: "Sélectionner un·e utilisateur·rice"
recipient: "Correspondant·e"
@ -168,6 +168,7 @@ intro: "L'installation de Misskey est terminée! Créons le compte administrateu
done: "Terminé"
processing: "Traitement en cours"
preview: "Prévisualisation"
default: "Par défaut"
noCustomEmojis: "Il a pas démoji"
customEmojisOfRemote: "Émojis l'instance distante"
noJobs: "Il n'y a aucune tâche planifiée"
@ -312,11 +313,11 @@ userList: "Listes"
about: "Informations"
aboutMisskey: "À propos de Misskey"
aboutMisskeyText: "Misskey est un logiciel open source, développé par syuilo depuis 2014."
misskeyMembers: "Il est développé et maintenu par les membres répertoriés ici:"
misskeyMembers: "Il est développé et maintenu par les membres listés ci-dessous :"
misskeySource: "Le code source est disponible ici:"
misskeyTranslation: "Aidez-nous avec votre contribution à traduire Misskey:"
misskeyDonate: "Vous pouvez contribuer au développement de Misskey en faisant un don ici:"
morePatrons: "Nous apprécions vraiment le soutien de nombreux autres les soutiens non répertoriés ici. Merci beaucoup à tous! 🥰"
morePatrons: "Nous apprécions vraiment le soutien de nombreuses autres personnes non mentionnées ici. Merci à toutes et à tous ! 🥰"
patrons: "Supporteurs"
administrator: "Administrateur"
token: "Jeton"
@ -331,7 +332,7 @@ unregister: "Se désinscrire"
passwordLessLogin: "Connectez-vous sans mot de passe"
resetPassword: "Réinitialiser mot de passe"
newPasswordIs: "Votre nouveau mot de passe est \"{password}\""
post: "Notes"
post: "Publier"
posted: "Publié !"
autoReloadWhenDisconnected: "Rechargement automatique lorsque le serveur se déconnecte"
autoNoteWatch: "Surveiller automatique pour les notes"
@ -404,7 +405,7 @@ createAccount: "Créer compte"
existingAcount: "Comptes existants"
regenerate: "Régénérer"
fontSize: "Taille de la police"
noFollowRequests: "Vous n'avez aucune demandes d'abonnement en attente"
noFollowRequests: "Vous navez aucune demande dabonnement en attente"
openImageInNewTab: "Ouvrir l'image dans un nouvel onglet"
dashboard: "Tableau de bord"
local: "Local"
@ -419,18 +420,31 @@ promotion: "Promu"
promote: "Promouvoir"
numberOfDays: "Nombre de jours"
hideThisNote: "Masquer cette note"
showFeaturedNotesInTimeline: "Afficher les notes en vedette dans Fil d'actualité"
showFeaturedNotesInTimeline: "Afficher les notes en vedette dans fil d'actualité"
objectStorage: "Stockage d'objets"
useObjectStorage: "Utiliser le stockage d'objets"
objectStorageBaseUrl: "Base URL"
objectStorageBaseUrlDesc: "Préfixe d'URL utilisé pour construire l'URL vers le référencement d'objet (média). Spécifiez son URL si vous utilisez un CDN ou un proxy, sinon spécifiez l'adresse accessible au public selon le guide de service que vous allez utiliser. i.g 'https://<bucket>.s3.amazonaws.com' pour AWS S3 et 'https://storage.googleapis.com/<bucket>' pour GCS."
objectStorageBucket: "Bucket"
objectStorageBucketDesc: "Veuillez spécifier le nom du compartiment utilisé sur le service configuré."
objectStoragePrefix: "Prefix"
objectStoragePrefixDesc: "Les fichiers seront stockés sous le répertoire de ce préfixe."
objectStorageEndpoint: "Endpoint"
objectStorageEndpointDesc: "Laissez ce champ vide si vous utilisez AWS S3, sinon spécifiez le point de terminaison comme '<host>' ou '<host>: <port>' selon le guide de service que vous allez utiliser."
objectStorageRegion: "Region"
objectStorageRegionDesc: "Spécifiez une région comme 'xx-east-1'. Si votre service ne fait pas de distinction entre les régions, laissez-le vide ou remplissez 'us-east-1'."
objectStorageUseSSL: "Utiliser SSL"
objectStorageUseSSLDesc: "Désactivez-le si vous n'utilisez pas HTTPS pour la connexion API"
serverLogs: "Journaux serveur"
deleteAll: "Supprimer tout"
showFixedPostForm: "Afficher le formulaire en haut du fil d'actualité"
newNoteRecived: "Vous avez un nouveau note"
useNotificationsPopup: "Afficher la liste des notifications dans une fenêtre contextuelle"
newNoteRecived: "Vous avez une nouvelle note"
sounds: "Sons"
listen: "Écouter"
none: "Rien"
volume: "Volume"
details: "Détails"
chooseEmoji: "Choisissez des emojis"
_sfx:
note: "Nouvelle note"
noteMy: "Ma note"
@ -457,16 +471,26 @@ _time:
_tutorial:
title: "Comment utiliser Misskey"
step1_1: "Bienvenue,"
step1_2: "Cette page est appelée \"timeline\". Elle montre les \"notes\" des personnes que vous \"suivez\" dans l'ordre chronologique."
step1_3: "Vous n'avez pas encore posté de notes ou ne suivez personne, vous ne devriez donc rien voir dans la chronologie."
step2_1: "Finissons de créer votre profil avant d'écrire une note ou de suivre quelqu'un."
step2_2: "En fournissant quelques informations sur vous, il sera plus facile pour les autres de vous suivre."
step1_2: "Cette page est appelée \"fil d'actualité\". Elle montre les \"notes\" des personnes que vous \"abonne\" dans l'ordre chronologique."
step1_3: "Vous n'avez pas encore publier de notes et personne n'est encore abonnements, vous ne devriez donc rien voir dans fil d'actualité."
step2_1: "Finissons de créer votre profil avant d'écrire une note ou de abonne quelqu'un."
step2_2: "En fournissant quelques informations sur vous, il sera plus facile pour les autres de vous abonne."
step3_1: "Vous avez fini de créer votre profil ?"
step3_2: "Létape suivante consiste à créer une note. Vous pouvez commencer en cliquant sur licône crayon sur lécran."
step3_3: "Remplissez le cadran et cliquez sur le bouton en haut à droite pour envoyer."
step3_4: "Vous n'avez rien à dire ? Essayez de dire \"J'ai commencé à utiliser Misskey\"."
step4_1: "Avez-vous posté votre première notes ?"
step4_2: "Votre première note est maintenant affichée sur votre timeline."
step4_2: "Votre première note est maintenant affiché sur votre fil d'actualité."
step5_1: "Ensuite, abonnons-nous d'autres personnes et rendre la fil d'actualité en savoir plus vivante."
step5_2: "{featured} affiche les notes en tendance sur cette instance. {explore} vous permet de trouver les utilisateur·rice·s en tendance. Essayez de vous abonner aux gens que vous aimez !"
step5_3: "Pour abonne un utilisateur, cliquez sur l'icône de l'utilisateur pour afficher la page de l'utilisateur et appuyez sur le bouton \"Abonnement\"."
step5_4: "Selon l'utilisateur, il peut s'écouler un certain temps avant que la abonner ne soit approuvé."
step6_1: "Si vous voyez la notes d'un autre utilisateur sur fil d'actualité, c'était réussi."
step6_2: "Vous pouvez ajouter des \"réactions\" aux notes des autres afin de pouvoir facilement dire votre émotion."
step6_3: "Pour ajouter une réaction, cliquez sur la marque \"+\" sur la note et sélectionnez la réaction souhaitée."
step7_1: "Tu as bien travaillé ! Ceci conclut l'explication de l'utilisation de base de Misskey."
step7_2: "Pour plus d'informations sur Misskey, voir {help}."
step7_3: "Alors, profitez de Misskey 🚀"
_2fa:
alreadyRegistered: "Cette étape à déjà été complétée"
registerDevice: "Sinscrire l'appareil"

View file

@ -35,6 +35,8 @@ unpin: "ピン留め解除"
copyContent: "内容をコピー"
copyLink: "リンクをコピー"
delete: "削除"
deleteAndEdit: "削除して編集"
deleteAndEditConfirm: "このートを削除してもう一度編集しますかこのートへのリアクション、Renote、返信も全て削除されます。"
addToList: "リストに追加"
sendMessage: "メッセージを送信"
copyUsername: "ユーザー名をコピー"
@ -86,7 +88,6 @@ add: "追加"
reaction: "リアクション"
reactionSettingDescription: "リアクションピッカーに表示するリアクションを設定します。"
rememberNoteVisibility: "公開範囲を記憶する"
renameFile: "ファイル名を変更"
attachCancel: "添付取り消し"
markAsSensitive: "閲覧注意にする"
unmarkAsSensitive: "閲覧注意を解除する"
@ -116,6 +117,7 @@ loginFailed: "ログインに失敗しました"
showOnRemote: "リモートで表示"
general: "全般"
wallpaper: "壁紙"
setWallpaper: "壁紙を設定"
removeWallpaper: "壁紙を削除"
searchWith: "検索: {q}"
youHaveNoLists: "リストがありません"
@ -204,10 +206,13 @@ messaging: "チャット"
upload: "アップロード"
fromDrive: "ドライブから"
fromUrl: "URLから"
uploadFromUrl: "URLアップロード"
uploadFromUrlDescription: "アップロードしたいファイルのURL"
uploadFromUrlRequested: "アップロードをリクエストしました"
uploadFromUrlMayTakeTime: "アップロードが完了するまで時間がかかる場合があります。"
explore: "みつける"
games: "Misskey Games"
messageRead: "既読"
recentUsedEmojis: "最近使用した絵文字"
noMoreHistory: "これより過去の履歴はありません"
startMessaging: "チャットを開始"
nUsersRead: "{n}人が読みました"
@ -223,17 +228,30 @@ yearsOld: "{age}歳"
registeredDate: "登録日"
location: "場所"
theme: "テーマ"
themeForLightMode: "ライトモードで使うテーマ"
themeForDarkMode: "ダークモードで使うテーマ"
light: "ライト"
dark: "ダーク"
lightThemes: "明るいテーマ"
darkThemes: "暗いテーマ"
syncDeviceDarkMode: "デバイスのダークモードと同期する"
drive: "ドライブ"
fileName: "ファイル名"
selectFile: "ファイルを選択"
selectFiles: "ファイルを選択"
renameFolder: "フォルダー名を変更"
renameFile: "ファイル名を変更"
folderName: "フォルダー名"
createFolder: "フォルダーを作成"
renameFolder: "フォルダー名を変更"
deleteFolder: "フォルダーを削除"
addFile: "ファイルを追加"
emptyDrive: "ドライブは空です"
emptyFolder: "フォルダーは空です"
unableToDelete: "削除できません"
inputNewFileName: "新しいファイル名を入力してください"
inputNewFolderName: "新しいフォルダ名を入力してください"
circularReferenceFolder: "移動先のフォルダーは、移動するフォルダーのサブフォルダーです。"
hasChildFilesOrFolders: "このフォルダは空でないため、削除できません。"
copyUrl: "URLをコピー"
rename: "名前を変更"
avatar: "アイコン"
@ -387,13 +405,14 @@ strongPassword: "強いパスワード"
passwordMatched: "一致しました"
passwordNotMatched: "一致していません"
signinWith: "{x}でログイン"
signinFailed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
tapSecurityKey: "セキュリティーキーにタッチ"
or: "もしくは"
uiLanguage: "UIの表示言語"
groupInvited: "グループに招待されました"
aboutX: "{x}について"
useOsNativeEmojis: "OSネイティブの絵文字を使用"
noGroups: "グループがありません"
youHaveNoGroups: "グループがありません"
joinOrCreateGroup: "既存のグループに招待してもらうか、新しくグループを作成してください。"
noHistory: "履歴はありません"
disableAnimatedMfm: "動きのあるMFMを無効にする"
@ -445,6 +464,8 @@ none: "なし"
volume: "音量"
details: "詳細"
chooseEmoji: "絵文字を選択"
unableToProcess: "操作を完了できません"
recentUsed: "最近使用"
_sfx:
note: "ノート"
@ -671,45 +692,39 @@ _pages:
newPage: "ページの作成"
editPage: "ページの編集"
readPage: "ソースを表示中"
page-created: "ページを作成しました"
page-updated: "ページを更新しました"
name-already-exists: "指定されたページURLは既に存在しています"
title-invalid-name: "不正なページURLです"
text-invalid-name: "空白でないか確認してください"
created: "ページを作成しました"
updated: "ページを更新しました"
deleted: "ページを削除しました"
nameAlreadyExists: "指定されたページURLは既に存在しています"
invalidNameTitle: "不正なページURLです"
invalidNameText: "空白でないか確認してください"
editThisPage: "このページを編集"
viewSource: "ソースを表示"
viewPage: "ページを見る"
like: "いいね"
unlike: "いいね解除"
liked-pages: "いいねしたページ"
my-pages: "自分のページ"
my: "自分のページ"
liked: "いいねしたページ"
inspector: "インスペクター"
content: "ページブロック"
variables: "変数"
variables-info: "変数を使うことで動的なページを作成できます。テキスト内で <b>{ 変数名 }</b> と書くとそこに変数の値を埋め込めます。例えば <b>Hello { thing } world!</b> というテキストで、変数(thing)の値が <b>ai</b> だった場合、テキストは <b>Hello ai world!</b> になります。"
variables-info2: "変数の評価(値を算出すること)は上から下に行われるので、ある変数の中で自分より下の変数を参照することはできません。例えば上から <b>A、B、C</b> と3つの変数を定義したとき、<b>C</b>の中で<b>A</b>や<b>B</b>を参照することはできますが、<b>A</b>の中で<b>B</b>や<b>C</b>を参照することはできません。"
variables-info3: "ユーザーからの入力を受け取るには、ページに「ユーザー入力」ブロックを設置し、「変数名」に入力を格納したい変数名を設定します(変数は自動で作成されます)。その変数を使ってユーザー入力に応じた動作を行えます。"
variables-info4: "関数を使うと、値の算出処理を再利用可能な形にまとめることができます。関数を作るには、「関数」タイプの変数を作成します。関数にはスロット(引数)を設定することができ、スロットの値は関数内で変数として利用可能です。また、AiScript標準で関数を引数に取る関数(高階関数と呼ばれます)も存在します。関数は予め定義しておくほかに、このような高階関数のスロットに即席でセットすることもできます。"
more-details: "詳しい説明"
title: "タイトル"
url: "ページURL"
summary: "ページの要約"
alignCenter: "中央寄せ"
hide-title-when-pinned: "ピン留めされているときにタイトルを非表示"
hideTitleWhenPinned: "ピン留めされているときにタイトルを非表示"
font: "フォント"
fontSerif: "セリフ"
fontSansSerif: "サンセリフ"
set-eye-catching-image: "アイキャッチ画像を設定"
remove-eye-catching-image: "アイキャッチ画像を削除"
eyeCatchingImageSet: "アイキャッチ画像を設定"
eyeCatchingImageRemove: "アイキャッチ画像を削除"
chooseBlock: "ブロックを追加"
selectType: "種類を選択"
enterVariableName: "変数名を決めてください"
the-variable-name-is-already-used: "その変数名は既に使われています"
content-blocks: "コンテンツ"
input-blocks: "入力"
special-blocks: "特殊"
post-from-post-form: "この内容を投稿"
posted-from-post-form: "投稿しました"
variableNameIsAlreadyUsed: "その変数名は既に使われています"
contentBlocks: "コンテンツ"
inputBlocks: "入力"
specialBlocks: "特殊"
blocks:
text: "テキスト"
textarea: "テキストエリア"

View file

@ -84,7 +84,7 @@ clickToShow: "클릭하여 보기"
sensitive: "열람주의"
add: "추가"
reaction: "리액션"
reactionSettingDescription: "리액션 선택창에 표시할 리액션을 줄바꿈으로 구분해 설정합니다."
reactionSettingDescription: "리액션 선택 상자에 표시할 리액션을 설정합니다."
rememberNoteVisibility: "공개 범위를 기억하기"
renameFile: "파일 이름 변경"
attachCancel: "첨부 취소"
@ -168,6 +168,7 @@ intro: "Misskey의 설치가 완료되었습니다! 관리자 계정을 생성
done: "완료"
processing: "처리중"
preview: "미리보기"
default: "기본값"
noCustomEmojis: "이모지가 없습니다"
customEmojisOfRemote: "다른 인스턴스들의 이모지"
noJobs: "작업이 없습니다"
@ -422,15 +423,28 @@ hideThisNote: "이 노트를 숨기기"
showFeaturedNotesInTimeline: "타임라인에 추천 노트를 표시"
objectStorage: "오브젝트 스토리지"
useObjectStorage: "오브젝트 스토리지를 사용"
objectStorageBaseUrl: "Base URL"
objectStorageBaseUrlDesc: "오브젝트 (미디어) 참조 URL 을 만들 때 사용되는 URL입니다. CDN 또는 프록시를 사용하는 경우 그 URL을 지정하고, 그 외의 경우 사용할 서비스의 가이드에 따라 공개적으로 액세스 할 수 있는 주소를 지정해 주세요. 예를 들어, AWS S3의 경우 'https://<bucket>.s3.amazonaws.com', GCS등의 경우 'https://storage.googleapis.com/<bucket>' 와 같이 지정합니다."
objectStorageBucket: "Bucket"
objectStorageBucketDesc: "사용 서비스의 bucket명을 지정해주세요."
objectStoragePrefix: "Prefix"
objectStoragePrefixDesc: "이 Prefix 의 디렉토리 아래에 파일이 저장됩니다."
objectStorageEndpoint: "Endpoint"
objectStorageEndpointDesc: "AWS S3의 경우 공란, 다른 서비스의 경우 각 서비스의 가이드에 맞게 endpoint를 설정해주세요. '<host>' 혹은 '<host>:<port>' 와 같이 지정합니다."
objectStorageRegion: "Region"
objectStorageRegionDesc: "'xx-east-1'와 같이 region을 지정해주세요. 사용하는 서비스에 region 개념이 없는 경우, 비워 두거나 'us-east-1'으로 설정해 주세요."
objectStorageUseSSL: "SSL 사용"
objectStorageUseSSLDesc: "API 호출시 HTTPS 를 사용하지 않는 경우 OFF 로 설정해 주세요"
serverLogs: "서버 로그"
deleteAll: "모두 삭제"
showFixedPostForm: "타임라인 상단에 글 작성란을 표시"
newNoteRecived: "새 노트가 있습니다"
useNotificationsPopup: "알림 목록을 팝업으로 표시"
sounds: "소리"
listen: "듣기"
none: "없음"
volume: "음량"
details: "자세히"
chooseEmoji: "이모지 선택"
_sfx:
note: "새 노트"
noteMy: "내 노트"

View file

@ -11,7 +11,7 @@ ok: "OK"
gotIt: "我明白了"
cancel: "取消"
enterUsername: "输入用户名"
renotedBy: "由 {user} 转"
renotedBy: "由 {user} 转"
noNotes: "没有投稿"
noNotifications: "无通知"
instance: "实例"
@ -84,7 +84,7 @@ clickToShow: "点击以显示"
sensitive: "阅读注意"
add: "添加"
reaction: "反应"
reactionSettingDescription: "快速选择回应中的自定义表情符号,以换行符分隔。"
reactionSettingDescription: "选择您想要固定在反应选择器中的反应。"
rememberNoteVisibility: "记录公开范围"
renameFile: "重命名文件"
attachCancel: "删除附件"
@ -168,6 +168,7 @@ intro: "Misskey的部署结束啦填写管理员账号吧"
done: "完成"
processing: "处理中"
preview: "预览"
default: "默认"
noCustomEmojis: "无自定义Emoji"
customEmojisOfRemote: "远程Emoji"
noJobs: "没有任务"
@ -239,6 +240,8 @@ avatar: "头像"
banner: "Banner"
nsfw: "阅读注意"
disconnectedFromServer: "已从服务器断开连接"
reload: "重新加载"
doNothing: "什么都不做"
reloadConfirm: "确定要重新加载吗"
watch: "关注"
unwatch: "取消关注"
@ -280,11 +283,19 @@ enableRecaptcha: "启用 reCAPTCHA\n(请注意, 此功能在中国大陆不可
recaptchaSiteKey: "网站密钥"
recaptchaSecretKey: "reCAPTCHA 密钥"
antennas: "天线"
manageAntennas: "天线管理"
name: "名称"
antennaSource: "接收来源"
antennaKeywords: "包含关键字"
antennaExcludeKeywords: "排除关键字"
antennaKeywordsDescription: "使用空格分隔会产生AND规范并且使用换行符分隔会产生OR规范"
notifyAntenna: "通知新帖子"
withFileAntenna: "仅带有附件的帖子"
serviceworker: "ServiceWorker"
enableServiceworker: "启用ServiceWorker"
antennaUsersDescription: "指定用户名,用换行符分隔"
caseSensitive: "区分大小写"
withReplies: "包括回复"
connectedTo: "您的账号已连到接以下社交账号"
notesAndReplies: "帖子与回复"
withFiles: "附件"
@ -405,21 +416,42 @@ dayOverDayChanges: "与前一日相比"
accessibility: "辅助功能"
clinetSettings: "客户端设置"
accountSettings: "账户设置"
promotion: "推广"
promote: "推广"
numberOfDays: "天数"
hideThisNote: "隐藏这条帖子"
showFeaturedNotesInTimeline: "在时间上显示热门推荐"
showFeaturedNotesInTimeline: "在时间线上显示热门推荐"
objectStorage: "对象存储"
useObjectStorage: "使用对象存储"
objectStorageBaseUrl: "基本网址"
objectStorageBaseUrlDesc: "供参考的URL。如果使用CDN或Proxy则其URL为S3\"https://<bucket>.s3.amazonaws.com\"、GCS等\"https://storage-googleapis.proxy.ustclug.org/<bucket>\"。"
objectStorageBucket: "存储桶"
objectStorageBucketDesc: "请指定使用的对象存储服务的存储桶名称。"
objectStoragePrefix: "前缀"
objectStoragePrefixDesc: "它将存储在此前缀的目录下。"
objectStorageEndpoint: "端点"
objectStorageEndpointDesc: "S3默认情况下为空否则请为每个服务指定端点。 指定为“<host>”或“<host>:<port>”。"
objectStorageRegion: "可用区"
objectStorageRegionDesc: "指定一个可用区例如“xx-east-1”。 如果您的对象存储服务没有可用区概念请将其留空或填写“us-east-1”。"
objectStorageUseSSL: "使用SSL"
objectStorageUseSSLDesc: "如果不使用https进行API连接请关闭。"
serverLogs: "服务器日志"
deleteAll: "删除全部"
showFixedPostForm: "在时间线顶部显示帖子表单"
newNoteRecived: "有新的帖子"
useNotificationsPopup: "在弹出窗口中显示通知列表"
sounds: "声音"
listen: "听"
none: "空"
volume: "音量"
details: "详情"
chooseEmoji: "选择表情符号"
_sfx:
note: "帖子"
noteMy: "我的笔记"
notification: "通知"
chat: "聊天"
chatBg: "聊天背景"
antenna: "天线接收"
_ago:
unknown: "未知"
future: "未来"
@ -449,11 +481,25 @@ _tutorial:
step3_4: "不知道说些什么好吗那就写下「Misskey我来啦」这样的话吧。"
step4_1: "将你的话语发布出去了吗?"
step4_2: "太棒了!现在你可以在你的时间线中看到你刚刚发布的帖子了。"
step5_1: "接下来,关注其他人来使时间线更生动吧。"
step5_2: "{featured}将向您展示热门趋势的帖子。 {explore}将让您找到热门用户。 尝试关注您喜欢的人!"
step5_3: "要关注其他用户,请单击他的头像,然后在他的个人资料上按下“关注”按钮。"
step5_4: "如果用户的名称旁边有锁定图标,则该用户需要手动批准您的关注请求。"
step6_1: "现在,您将可以在时间线上看到其他用户的帖子。"
step6_2: "您还可以在其他人的帖子上进行「反应」,以快速做出简单回复。"
step6_3: "在他人的贴子上按下「+」图标,即可选择想要的表情来进行「反应」。"
step7_1: "对Misskey基本操作的简单介绍到此结束了。 辛苦了!"
step7_2: "如果你想了解更多有关Misskey的信息请参见{help}。"
step7_3: "接下来享受Misskey带来的乐趣吧🚀"
_2fa:
alreadyRegistered: "此设备已被注册"
registerDevice: "注册设备"
registerKey: "注册密钥"
step1: "首先,在您的设备上安装二步验证应用程序,例如{a}或{b}。"
step2: "然后,扫描屏幕上显示的二维码。"
step3: "输入您的应用提供的动态口令以完成设置。"
step4: "从现在开始,任何登录操作都将要求您提供动态口令。"
securityKeyInfo: "您可以设置使用支持FIDO2的硬件安全密钥、指纹或设备上的PIN来保护您的登录过程。"
_permissions:
"read:account": "查看账户信息"
"write:account": "更改帐户信息"
@ -465,8 +511,11 @@ _permissions:
"write:favorites": "编辑收藏夹"
"read:following": "查看关注信息"
"write:following": "关注/取消关注"
"read:messaging": "查看消息"
"write:messaging": "撰写或删除消息"
"read:mutes": "查看屏蔽列表"
"write:mutes": "编辑屏蔽列表"
"write:notes": "撰写或删除帖子"
"read:notifications": "查看通知"
"write:notifications": "管理通知"
"read:reactions": "查看回应"
@ -479,10 +528,14 @@ _permissions:
"read:user-groups": "查看用户组"
"write:user-groups": "操作用户组"
_auth:
shareAccess: "您要授权允许“{name}”访问您的帐户吗?"
permissionAsk: "这个应用程序需要以下权限"
_antennaSources:
all: "所有帖子"
homeTimeline: "已关注用户的帖子"
users: "来自特定用户的帖子"
userList: "来自特定清单中的帖子"
userGroup: "来自特定组中用户的帖子"
_weekday:
sunday: "星期日"
monday: "星期一"
@ -531,6 +584,7 @@ _poll:
remainingSeconds: "{s}秒后截止"
_visibility:
public: "公开"
publicDescription: "您的帖子将出现在全局时间线上"
home: "首页"
homeDescription: "仅发送至首页的时间线"
followers: "关注者"
@ -569,7 +623,13 @@ _charts:
usersTotal: "用户总数"
activeUsers: "活跃用户数"
notesIncDec: "帖子:增加/减少"
localNotesIncDec: "本地帖子量增减"
remoteNotesIncDec: "远程帖子量增减"
notesTotal: "帖子总数"
filesIncDec: "文件总数增减"
filesTotal: "合计文件总数"
storageUsageIncDec: "存储空间用量增减"
storageUsageTotal: "合计存储空间用量"
_instanceCharts:
requests: "请求"
users: "用户数量:增加/减少"
@ -579,6 +639,9 @@ _instanceCharts:
ff: "关注/被关注:数量变化"
ffTotal: "关注/被关注:总数"
cacheSize: "缓存大小:增加/减少"
cacheSizeTotal: "合计缓存大小"
files: "文件总数增减"
filesTotal: "合计文件总数"
_timelines:
home: "首页"
local: "本地"

View file

@ -1,2 +1,391 @@
---
_lang_: "中文(繁体)"
monthAndDay: "{month}月 {day}日"
search: "搜尋"
notifications: "通知"
username: "用戶名"
password: "密碼"
fetchingAsApObject: "從Fediverse尋找中..."
ok: "OK"
gotIt: "知道了"
cancel: "取消"
enterUsername: "輸入用戶名"
renotedBy: "由{user}轉發"
noNotes: "沒有筆記"
noNotifications: "沒有通知"
settings: "設定"
profile: "個人檔案"
timeline: "時間軸"
noAccountDescription: "此用戶還沒有自我介紹"
login: "登入"
loggingIn: "登入中"
logout: "登出"
signup: "註冊"
uploading: "上傳中"
save: "保存"
users: "用戶"
addUser: "新增用戶"
favorite: "收藏"
favorites: "收藏"
unfavorite: "取消收藏"
pin: "置頂"
unpin: "取消置頂"
copyContent: "複製內容"
copyLink: "複製連結"
delete: "刪除"
addToList: "添加至清單"
sendMessage: "發送訊息"
copyUsername: "複製用戶名"
reply: "回覆"
loadMore: "載入更多"
youGotNewFollower: "您有新的追隨者"
receiveFollowRequest: "收到追隨請求"
followRequestAccepted: "追隨請求已接受"
mentions: "提及"
importAndExport: "匯入 / 匯出"
import: "匯入"
export: "匯出"
files: "檔案"
download: "下載"
driveFileDeleteConfirm: "確定要刪除檔案「{name}」嗎?附加此檔案的筆記也會跟著不見。"
unfollowConfirm: "確定要取消對{name}的追隨嗎?"
exportRequested: "已請求匯出。這可能會花一點時間。結束後檔案將會被放到雲端裡。"
importRequested: "已請求匯入。這可能會花一點時間"
lists: "清單"
noLists: "沒有清單"
note: "筆記"
notes: "筆記"
following: "關注中"
followers: "追隨者"
followsYou: "追隨你的人"
createList: "建立清單"
manageLists: "管理清單"
error: "發生錯誤"
retry: "重試"
enterListName: "輸入清單名稱"
privacy: "隱私"
makeFollowManuallyApprove: "手動審核追隨請求"
defaultNoteVisibility: "預設的筆記隱私權"
follow: "追隨"
followRequest: "追隨請求"
followRequests: "追隨請求"
unfollow: "取消追隨"
followRequestPending: "追隨許可批准中"
enterEmoji: "輸入表情符號"
renote: "轉發筆記"
unrenote: "取消轉發筆記"
quote: "引用"
pinnedNote: "已置頂筆記"
you: "您"
clickToShow: "點擊查看"
sensitive: "敏感內容"
add: "新增"
reaction: "反應"
rememberNoteVisibility: "記住筆記隱私設定"
renameFile: "重新命名檔案"
attachCancel: "移除附件"
markAsSensitive: "標記為敏感內容"
unmarkAsSensitive: "取消標記為敏感內容"
enterFileName: "請輸入檔案名稱"
mute: "禁言"
unmute: "解除禁言"
block: "封鎖"
unblock: "解除封鎖"
suspend: "凍結"
unsuspend: "解凍"
blockConfirm: "確定要封鎖此用戶?"
unblockConfirm: "確定解除封鎖此用戶?"
suspendConfirm: "確定凍結此帳號?"
unsuspendConfirm: "確定解凍此帳號?"
selectList: "選擇清單"
customEmojis: "自訂表情符號"
emojiName: "表情符號名稱"
emojiUrl: "表情符號URL"
addEmoji: "新增表情符號"
flagAsBot: "此帳戶是Bot"
flagAsCat: "此帳戶是Cat"
autoAcceptFollowed: "自動許可關注"
addAcount: "新增帳戶"
loginFailed: "登入失敗"
general: "一般"
wallpaper: "壁紙"
removeWallpaper: "移除壁紙"
searchWith: "搜尋: {q}"
youHaveNoLists: "你沒有任何清單"
followConfirm: "你真的要關注{name}嗎?"
host: "主機"
selectUser: "選擇用戶"
recipient: "收件人"
annotation: "註解"
federation: "整合"
latestStatus: "最後狀態"
storageUsage: "已使用容量"
charts: "圖表"
perHour: "每小時"
perDay: "每日"
operations: "操作"
software: "軟體"
version: "版本"
withNFiles: "{n}個檔案"
monitor: "監視器"
network: "網路"
statistics: "統計"
clearQueue: "清除佇列"
clearQueueConfirmTitle: "確定要清除佇列嗎?"
clearCachedFiles: "清除快取資料"
muteAndBlock: "禁言 / 封鎖"
mutedUsers: "已禁言用戶"
blockedUsers: "已封鎖用戶"
noUsers: "無用戶"
editProfile: "編輯個人檔案"
noteDeleteConfirm: "確定刪除此筆記嗎?"
pinLimitExceeded: "不能再置頂更多筆記了"
intro: "Misskey安裝作業完成請創立管理員用戶"
done: "完成"
processing: "處理中"
preview: "預覽"
noCustomEmojis: "沒有表情符號"
federating: "整合檢索中"
blocked: "已封鎖"
suspended: "已凍結"
all: "全部"
subscribing: "訂閱中"
notResponding: "沒有回應"
changePassword: "修改密碼"
security: "安全性"
retypedNotMatch: "不相符的輸入內容"
currentPassword: "現在的密碼"
newPassword: "新的密碼"
newPasswordRetype: "新的密碼(再輸入一次)"
attachFile: "添加附件"
more: "更多!"
featured: "精選"
usernameOrUserId: "用戶名或用戶ID"
noSuchUser: "用戶不存在"
announcements: "公告"
imageUrl: "圖片URL"
remove: "刪除"
removed: "成功移除"
removeAreYouSure: "確定要刪掉「{x}」嗎?"
saved: "已保存"
messaging: "傳送訊息"
upload: "上傳"
fromDrive: "從雲端"
fromUrl: "從URL"
explore: "探索"
games: "Misskey 遊戲"
messageRead: "已讀"
recentUsedEmojis: "最近使用的表情符號"
noMoreHistory: "沒有更多歷史紀錄"
startMessaging: "開始傳送訊息"
nUsersRead: "{n}人已讀"
tos: "使用條款"
start: "開始"
home: "首頁"
activity: "動態"
birthday: "生日"
yearsOld: "{age}歲"
registeredDate: "註冊日期"
location: "位置"
theme: "外觀主題"
lightThemes: "明亮主題"
darkThemes: "灰暗主題"
drive: "雲端硬碟"
selectFile: "選擇檔案"
selectFiles: "選擇檔案"
renameFolder: "重新命名資料夾"
createFolder: "新增資料夾"
deleteFolder: "刪除資料夾"
addFile: "添加檔案"
emptyDrive: "雲端硬碟為空"
emptyFolder: "空的資料夾"
copyUrl: "複製URL"
rename: "重新命名"
avatar: "頭像"
banner: "橫幅"
nsfw: "敏感內容"
disconnectedFromServer: "與伺服器中斷連線"
reload: "重新載入"
doNothing: "無視"
reloadConfirm: "確定要重新嘗試嗎?"
watch: "關注"
unwatch: "取消關注"
accept: "接受"
reject: "拒絕"
maintainerName: "管理員名稱"
maintainerEmail: "管理員信箱"
tosUrl: "服務條款URL"
thisYear: "今年"
thisMonth: "本月"
today: "本日"
dayX: "{day}天"
monthX: "{month}月"
yearX: "{year}年"
pages: "頁面"
connectSerice: "連線"
disconnectSerice: "中斷連線"
enableLocalTimeline: "開啟本地時間軸"
enableGlobalTimeline: "開啟全球時間軸"
registration: "註冊"
enableRegistration: "開啟新用戶註冊"
invite: "邀請"
proxyRemoteFiles: "代理遠程檔案"
driveCapacityPerLocalAccount: "每個本地用戶的雲端容量"
inMb: "以Mbps為單位"
iconUrl: "圖像URL"
bannerUrl: "橫幅圖片URL"
basicInfo: "基本資訊"
pinnedUsers: "置頂用戶"
recaptcha: "reCAPTCHA"
enableRecaptcha: "啟用 reCAPTCHA"
recaptchaSiteKey: "網站金鑰"
recaptchaSecretKey: "金鑰"
name: "名稱"
serviceworker: "ServiceWorker"
enableServiceworker: "開啟 ServiceWorker"
caseSensitive: "區分大小寫"
notesAndReplies: "貼文與回覆"
withFiles: "附件"
silence: "禁言"
silenceConfirm: "確定要禁言此用戶嗎?"
unsilenceConfirm: "確定要解除禁言嗎?"
popularUsers: "熱門用戶"
recentlyUpdatedUsers: "最近發文的用戶"
recentlyRegisteredUsers: "新加入用戶"
recentlyDiscoveredUsers: "最近發現的用戶"
userList: "清單"
passwordLessLogin: "設置無密碼登入"
resetPassword: "重置密碼"
newPasswordIs: "新密碼為「{password}」"
post: "投稿"
posted: "投稿完成"
autoReloadWhenDisconnected: "和伺服器斷線時自動重新載入"
autoNoteWatch: "自動關注筆記"
autoNoteWatchDescription: "收到反應或回覆過的筆記的通知"
reduceUiAnimation: "減少介面的動態視覺"
share: "分享"
notFound: "找不到"
notFoundDescription: "找不到與指定URL回應的頁面"
uploadFolder: "預設上傳資料夾"
cacheClear: "清除暫存"
markAsReadAllNotifications: "標記所有通知為已讀"
markAsReadAllUnreadNotes: "標記所有筆記為已讀"
markAsReadAllTalkMessages: "標記所有訊息為已讀"
help: "幫助"
inputMessageHere: "在此輸入訊息"
close: "關閉"
group: "群組"
groups: "群組"
createGroup: "創建群組"
joinedGroups: "群組成員"
invites: "邀請"
groupName: "群組名稱"
members: "成員"
transfer: "轉讓"
messagingWithUser: "傳送訊息給其他用戶"
messagingWithGroup: "發送訊息至群組"
title: "標題"
text: "文字"
enable: "啟用"
next: "下一步"
retype: "重新輸入"
noteOf: "{user}的筆記"
inviteToGroup: "邀請至群組"
maxNoteTextLength: "筆記的字數限制"
quoteAttached: "引用"
quoteQuestion: "是否要引用?"
noMessagesYet: "沒有訊息"
newMessageExists: "有新的訊息"
onlyOneFileCanBeAttached: "只能添加一個附件"
signinRequired: "請先登入"
invitationCode: "邀請碼"
checking: "確認中"
available: "可用的"
unavailable: "不可用的"
usernameInvalidFormat: "可使用大小寫英文字母、數字和底線"
tooShort: "過短"
none: "無"
volume: "音量"
details: "詳細資訊"
_sfx:
note: "筆記"
noteMy: "我的筆記"
notification: "通知"
chat: "傳送訊息"
_ago:
unknown: "未知"
future: "未來"
justNow: "剛剛"
secondsAgo: "{n}秒前"
minutesAgo: "{n}分鐘前"
hoursAgo: "{n}小時前"
daysAgo: "{n}天前"
weeksAgo: "{n}周前"
monthsAgo: "{n}個月前"
yearsAgo: "{n}年前"
_time:
second: "秒"
minute: "分鐘"
hour: "小時"
day: "天"
_tutorial:
title: "Misskey使用方法"
step1_1: "歡迎!"
step1_2: "此為「時間軸」頁面,它會按照時間順序顯示你「追隨」的人的「筆記」"
step1_3: "由於你沒有發布任何筆記,也沒有追隨任何人,所以你的時間軸目前是空的。"
step2_1: "在發文或追隨其他人之前先讓我們設定一下個人資料吧。"
step2_2: "提供一些關於自己的資訊來讓其他人更有追隨你的意願。"
step3_1: "個人資料都打理好了嗎?"
step3_2: "下一步讓我們來試試看發個文,按一下畫面上的鉛筆圖示來開始"
step3_3: "輸入完內容後,按視窗右上角的按鈕來發文"
step3_4: "不知道該寫什麼內容嗎試試看「開始使用Misskey了」如何。"
step4_1: "筆記發出去了嗎?"
step4_2: "如果你的筆記有顯示在時間軸上,就代表已經發文成功。"
step5_1: "現在試試看追隨其他人來讓你的時間軸變得更生動吧。"
step5_3: "想要追隨其他人,只要點擊他們的頭像並按「追隨」即可。"
step5_4: "如果使用者的名字旁有鎖頭的圖示,代表他們需要手動核准你的追隨請求。"
step6_1: "現在你可以在時間軸上看到其他用戶的貼文"
step6_2: "你也可以在其他人的貼文上進行「反應」來表達簡單的回覆。"
step6_3: "在他人的貼文按下「+」的圖示即可選擇想要的表情符號來進行「反應」。"
step7_1: "以上為Misskey的基本操作說明教學在此告一段落。辛苦了。"
step7_2: "歡迎到{help}來瞭解更多Misskey相關介紹。"
_widgets:
notifications: "通知"
timeline: "時間軸"
activity: "動態"
_cw:
show: "載入更多"
_poll:
deadlineTime: "小時"
_visibility:
home: "首頁"
followers: "追隨者"
_profile:
name: "名稱"
username: "用戶名"
_exportOrImport:
followingList: "關注中"
muteList: "禁言"
blockingList: "封鎖"
userLists: "清單"
_timelines:
home: "首頁"
_pages:
script:
categories:
list: "清單"
blocks:
_join:
arg1: "清單"
_randomPick:
arg1: "清單"
_dailyRandomPick:
arg1: "清單"
_seedRandomPick:
arg2: "清單"
_pick:
arg1: "清單"
_listLen:
arg1: "清單"
types:
array: "清單"

View file

@ -1,7 +1,7 @@
{
"name": "misskey",
"author": "syuilo <syuilotan@yahoo.co.jp>",
"version": "12.22.0",
"version": "12.23.0",
"codename": "indigo",
"repository": {
"type": "git",

View file

@ -164,6 +164,7 @@ import { v4 as uuid } from 'uuid';
import i18n from './i18n';
import { host, instanceName } from './config';
import { search } from './scripts/search';
import { isDeviceDarkmode } from './scripts/is-device-darkmode';
import MkToast from './components/toast.vue';
const DESKTOP_THRESHOLD = 1100;
@ -224,6 +225,10 @@ export default Vue.extend({
},
created() {
if (this.$store.state.device.syncDeviceDarkMode) {
this.$store.commit('device/set', { key: 'darkMode', value: isDeviceDarkmode() });
}
if (this.$store.getters.isSignedIn) {
this.connection = this.$root.stream.useSharedConnection('main');
this.connection.on('notification', this.onNotification);

View file

@ -139,9 +139,9 @@ export default Vue.extend({
rename() {
this.$root.dialog({
title: this.$t('contextmenu.rename-file'),
title: this.$t('renameFile'),
input: {
placeholder: this.$t('contextmenu.input-new-file-name'),
placeholder: this.$t('inputNewFileName'),
default: this.file.name,
allowEmpty: false
}

View file

@ -137,14 +137,14 @@ export default Vue.extend({
switch (err) {
case 'detected-circular-definition':
this.$root.dialog({
title: this.$t('unable-to-process'),
text: this.$t('circular-reference-detected')
title: this.$t('unableToProcess'),
text: this.$t('circularReferenceFolder')
});
break;
default:
this.$root.dialog({
type: 'error',
text: this.$t('unhandled-error')
text: this.$t('error')
});
}
});
@ -177,9 +177,9 @@ export default Vue.extend({
rename() {
this.$root.dialog({
title: this.$t('contextmenu.rename-folder'),
title: this.$t('renameFolder'),
input: {
placeholder: this.$t('contextmenu.input-new-folder-name'),
placeholder: this.$t('inputNewFolderName'),
default: this.folder.name
}
}).then(({ canceled, result: name }) => {
@ -206,14 +206,14 @@ export default Vue.extend({
case 'b0fc8a17-963c-405d-bfbc-859a487295e1':
this.$root.dialog({
type: 'error',
title: this.$t('unable-to-delete'),
text: this.$t('has-child-files-or-folders')
title: this.$t('unableToDelete'),
text: this.$t('hasChildFilesOrFolders')
});
break;
default:
this.$root.dialog({
type: 'error',
text: this.$t('unable-to-delete')
text: this.$t('unableToDelete')
});
}
});

View file

@ -263,14 +263,14 @@ export default Vue.extend({
switch (err) {
case 'detected-circular-definition':
this.$root.dialog({
title: this.$t('unable-to-process'),
text: this.$t('circular-reference-detected')
title: this.$t('unableToProcess'),
text: this.$t('circularReferenceFolder')
});
break;
default:
this.$root.dialog({
type: 'error',
text: this.$t('unhandled-error')
text: this.$t('error')
});
}
});
@ -284,9 +284,9 @@ export default Vue.extend({
urlUpload() {
this.$root.dialog({
title: this.$t('url-upload'),
title: this.$t('uploadFromUrl'),
input: {
placeholder: this.$t('url-of-file')
placeholder: this.$t('uploadFromUrlDescription')
}
}).then(({ canceled, result: url }) => {
if (canceled) return;
@ -296,17 +296,17 @@ export default Vue.extend({
});
this.$root.dialog({
title: this.$t('url-upload-requested'),
text: this.$t('may-take-time')
title: this.$t('uploadFromUrlRequested'),
text: this.$t('uploadFromUrlMayTakeTime')
});
});
},
createFolder() {
this.$root.dialog({
title: this.$t('create-folder'),
title: this.$t('createFolder'),
input: {
placeholder: this.$t('folder-name')
placeholder: this.$t('folderName')
}
}).then(({ canceled, result: name }) => {
if (canceled) return;
@ -321,9 +321,9 @@ export default Vue.extend({
renameFolder(folder) {
this.$root.dialog({
title: this.$t('contextmenu.rename-folder'),
title: this.$t('renameFolder'),
input: {
placeholder: this.$t('contextmenu.input-new-folder-name'),
placeholder: this.$t('inputNewFolderName'),
default: folder.name
}
}).then(({ canceled, result: name }) => {
@ -349,14 +349,14 @@ export default Vue.extend({
case 'b0fc8a17-963c-405d-bfbc-859a487295e1':
this.$root.dialog({
type: 'error',
title: this.$t('unable-to-delete'),
text: this.$t('has-child-files-or-folders')
title: this.$t('unableToDelete'),
text: this.$t('hasChildFilesOrFolders')
});
break;
default:
this.$root.dialog({
type: 'error',
text: this.$t('unable-to-delete')
text: this.$t('unableToDelete')
});
}
});

View file

@ -2,12 +2,11 @@
<x-popup :source="source" ref="popup" @closed="() => { $emit('closed'); destroyDom(); }">
<div class="omfetrab">
<header>
<button v-for="category in categories"
<button v-for="(category, i) in categories"
class="_button"
:title="category.text"
@click="go(category)"
:class="{ active: category.isActive }"
:key="category.text"
:key="i"
>
<fa :icon="category.icon" fixed-width/>
</button>
@ -15,7 +14,7 @@
<div class="emojis">
<template v-if="categories[0].isActive">
<header class="category"><fa :icon="faHistory" fixed-width/> {{ $t('recentUsedEmojis') }}</header>
<header class="category"><fa :icon="faHistory" fixed-width/> {{ $t('recentUsed') }}</header>
<div class="list">
<button v-for="(emoji, i) in ($store.state.device.recentEmojis || [])"
class="_button"
@ -27,9 +26,10 @@
<img v-else :src="$store.state.device.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
</button>
</div>
<header class="category"><fa :icon="faAsterisk" fixed-width/> {{ $t('customEmojis') }}</header>
</template>
<header class="category"><fa :icon="categories.find(x => x.isActive).icon" fixed-width/> {{ categories.find(x => x.isActive).text }}</header>
<template v-if="categories.find(x => x.isActive).name">
<div class="list">
<button v-for="emoji in emojilist.filter(e => e.category === categories.find(x => x.isActive).name)"
@ -92,47 +92,38 @@ export default Vue.extend({
customEmojis: {},
faGlobe, faHistory,
categories: [{
text: this.$t('customEmoji'),
icon: faAsterisk,
isActive: true
}, {
name: 'people',
text: this.$t('people'),
icon: faLaugh,
isActive: false
}, {
name: 'animals_and_nature',
text: this.$t('animals-and-nature'),
icon: faLeaf,
isActive: false
}, {
name: 'food_and_drink',
text: this.$t('food-and-drink'),
icon: faUtensils,
isActive: false
}, {
name: 'activity',
text: this.$t('activity'),
icon: faFutbol,
isActive: false
}, {
name: 'travel_and_places',
text: this.$t('travel-and-places'),
icon: faCity,
isActive: false
}, {
name: 'objects',
text: this.$t('objects'),
icon: faDice,
isActive: false
}, {
name: 'symbols',
text: this.$t('symbols'),
icon: faHeart,
isActive: false
}, {
name: 'flags',
text: this.$t('flags'),
icon: faFlag,
isActive: false
}]

View file

@ -86,7 +86,7 @@
<script lang="ts">
import Vue from 'vue';
import { faBolt, faTimes, faBullhorn, faStar, faLink, faExternalLinkSquareAlt, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faQuoteRight, faInfoCircle } from '@fortawesome/free-solid-svg-icons';
import { faCopy, faTrashAlt, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons';
import { faCopy, faTrashAlt, faEdit, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons';
import { parse } from '../../mfm/parse';
import { sum, unique } from '../../prelude/array';
import i18n from '../i18n';
@ -142,7 +142,7 @@ export default Vue.extend({
replies: [],
showContent: false,
hideThisNote: false,
faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan
faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan
};
},
@ -460,6 +460,22 @@ export default Vue.extend({
});
},
delEdit() {
this.$root.dialog({
type: 'warning',
text: this.$t('deleteAndEditConfirm'),
showCancelButton: true
}).then(({ canceled }) => {
if (canceled) return;
this.$root.api('notes/delete', {
noteId: this.appearNote.id
});
this.$root.post({ initialNote: this.appearNote, renote: this.appearNote.renote, reply: this.appearNote.reply });
});
},
toggleFavorite(favorite: boolean) {
this.$root.api(favorite ? 'notes/favorites/create' : 'notes/favorites/delete', {
noteId: this.appearNote.id
@ -547,6 +563,11 @@ export default Vue.extend({
),
...(this.appearNote.userId == this.$store.state.i.id ? [
null,
{
icon: faEdit,
text: this.$t('deleteAndEdit'),
action: this.delEdit
},
{
icon: faTrashAlt,
text: this.$t('delete'),

View file

@ -300,6 +300,7 @@ export default Vue.extend({
});
}
this.visibility = init.visibility;
this.localOnly = init.localOnly;
this.quoteId = init.renote ? init.renote.id : null;
}

View file

@ -155,7 +155,7 @@ export default Vue.extend({
if (err === null) return;
this.$root.dialog({
type: 'error',
text: this.$t('login-failed')
text: this.$t('signinFailed')
});
this.signing = false;
});
@ -176,7 +176,7 @@ export default Vue.extend({
}).catch(() => {
this.$root.dialog({
type: 'error',
text: this.$t('login-failed')
text: this.$t('signinFailed')
});
this.challengeData = null;
this.totpLogin = false;

View file

@ -18,7 +18,7 @@ import PostFormDialog from './components/post-form-dialog.vue';
import Dialog from './components/dialog.vue';
import Menu from './components/menu.vue';
import { router } from './router';
import { applyTheme, lightTheme } from './theme';
import { applyTheme, lightTheme, builtinThemes } from './theme';
Vue.use(Vuex);
Vue.use(VueHotkey);
@ -163,6 +163,12 @@ os.init(async () => {
isMobile: isMobile
};
},
watch: {
'$store.state.device.darkMode'() {
const themes = builtinThemes.concat(this.$store.state.device.themes);
applyTheme(themes.find(x => x.id === (this.$store.state.device.darkMode ? this.$store.state.device.darkTheme : this.$store.state.device.lightTheme)));
}
},
methods: {
api: os.api,
signout: os.signout,

View file

@ -14,6 +14,8 @@
<li><mk-link url="https://github.com/acid-chicken" class="at">@acid-chicken</mk-link></li>
<li><mk-link url="https://github.com/tamaina" class="at">@tamaina</mk-link></li>
<li><mk-link url="https://github.com/rinsuki" class="at">@rinsuki</mk-link></li>
<li><mk-link url="https://github.com/Xeltica" class="at">@Xeltica</mk-link></li>
<li><mk-link url="https://github.com/u1-liquid" class="at">@u1-liquid</mk-link></li>
</ul>
<div style="margin-top: 1em;">📦 {{ $t('misskeySource') }}</div>
<mk-url url="https://github.com/syuilo/misskey"/>

View file

@ -61,7 +61,7 @@ export default Vue.extend({
this.$root.dialog({
type: 'error',
text: this.$t('some-error')
text: this.$t('error')
});
});
}

View file

@ -345,6 +345,20 @@ export default Vue.extend({
},
methods: {
invite() {
this.$root.api('admin/invite').then(x => {
this.$root.dialog({
type: 'info',
text: x.code
});
}).catch(e => {
this.$root.dialog({
type: 'error',
text: e
});
});
},
addPinUser() {
this.$root.new(MkUserSelect, {}).$once('selected', user => {
this.pinnedUsers = this.pinnedUsers.trim();

View file

@ -113,7 +113,7 @@ export default Vue.extend({
if (items[0].kind == 'file') {
this.$root.dialog({
type: 'error',
text: this.$t('only-one-file-attached')
text: this.$t('onlyOneFileCanBeAttached')
});
}
}
@ -138,7 +138,7 @@ export default Vue.extend({
e.preventDefault();
this.$root.dialog({
type: 'error',
text: this.$t('only-one-file-attached')
text: this.$t('onlyOneFileCanBeAttached')
});
return;
}

View file

@ -145,7 +145,7 @@ export default Vue.extend({
if (groups1.length === 0 && groups2.length === 0) {
this.$root.dialog({
type: 'warning',
title: this.$t('noGroups'),
title: this.$t('youHaveNoGroups'),
text: this.$t('joinOrCreateGroup'),
});
return;

View file

@ -69,7 +69,7 @@ export default Vue.extend({
async add() {
const { canceled, result: type } = await this.$root.dialog({
type: null,
title: this.$t('choose-block'),
title: this.$t('_pages.chooseBlock'),
select: {
groupedItems: this.getPageBlockList()
},

View file

@ -80,7 +80,7 @@ export default Vue.extend({
async add() {
const { canceled, result: type } = await this.$root.dialog({
type: null,
title: this.$t('choose-block'),
title: this.$t('_pages.chooseBlock'),
select: {
groupedItems: this.getPageBlockList()
},

View file

@ -212,7 +212,7 @@ export default Vue.extend({
async changeType() {
const { canceled, result: type } = await this.$root.dialog({
type: null,
title: this.$t('select-type'),
title: this.$t('_pages.selectType'),
select: {
groupedItems: this.getScriptBlockList(this.getExpectedType ? this.getExpectedType() : null)
},

View file

@ -2,7 +2,7 @@
<div>
<div class="gwbmwxkm _panel">
<header>
<div class="title"><fa :icon="faStickyNote"/> {{ readonly ? $t('readPage') : pageId ? $t('editPage') : $t('newPage') }}</div>
<div class="title"><fa :icon="faStickyNote"/> {{ readonly ? $t('_pages.readPage') : pageId ? $t('_pages.editPage') : $t('_pages.newPage') }}</div>
<div class="buttons">
<button class="_button" @click="del()" v-if="!readonly"><fa :icon="faTrashAlt"/></button>
<button class="_button" @click="() => showOptions = !showOptions"><fa :icon="faCog"/></button>
@ -11,37 +11,37 @@
</header>
<section>
<router-link class="view" v-if="pageId" :to="`/@${ author.username }/pages/${ currentName }`"><fa :icon="faExternalLinkSquareAlt"/> {{ $t('view-page') }}</router-link>
<router-link class="view" v-if="pageId" :to="`/@${ author.username }/pages/${ currentName }`"><fa :icon="faExternalLinkSquareAlt"/> {{ $t('_pages.viewPage') }}</router-link>
<mk-input v-model="title">
<span>{{ $t('title') }}</span>
<span>{{ $t('_pages.title') }}</span>
</mk-input>
<template v-if="showOptions">
<mk-input v-model="summary">
<span>{{ $t('summary') }}</span>
<span>{{ $t('_pages.summary') }}</span>
</mk-input>
<mk-input v-model="name">
<template #prefix>{{ url }}/@{{ author.username }}/pages/</template>
<span>{{ $t('url') }}</span>
<span>{{ $t('_pages.url') }}</span>
</mk-input>
<mk-switch v-model="alignCenter">{{ $t('alignCenter') }}</mk-switch>
<mk-switch v-model="alignCenter">{{ $t('_pages.alignCenter') }}</mk-switch>
<mk-select v-model="font">
<template #label>{{ $t('font') }}</template>
<option value="serif">{{ $t('fontSerif') }}</option>
<option value="sans-serif">{{ $t('fontSansSerif') }}</option>
<template #label>{{ $t('_pages.font') }}</template>
<option value="serif">{{ $t('_pages.fontSerif') }}</option>
<option value="sans-serif">{{ $t('_pages.fontSansSerif') }}</option>
</mk-select>
<mk-switch v-model="hideTitleWhenPinned">{{ $t('hide-title-when-pinned') }}</mk-switch>
<mk-switch v-model="hideTitleWhenPinned">{{ $t('_pages.hideTitleWhenPinned') }}</mk-switch>
<div class="eyeCatch">
<mk-button v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage()"><fa :icon="faPlus"/> {{ $t('set-eye-catching-image') }}</mk-button>
<mk-button v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage()"><fa :icon="faPlus"/> {{ $t('_pages.eyeCatchingImageSet') }}</mk-button>
<div v-else-if="eyeCatchingImage">
<img :src="eyeCatchingImage.url" :alt="eyeCatchingImage.name"/>
<mk-button @click="removeEyeCatchingImage()" v-if="!readonly"><fa :icon="faTrashAlt"/> {{ $t('remove-eye-catching-image') }}</mk-button>
<mk-button @click="removeEyeCatchingImage()" v-if="!readonly"><fa :icon="faTrashAlt"/> {{ $t('_pages.eyeCatchingImageRemove') }}</mk-button>
</div>
</div>
</template>
@ -53,7 +53,7 @@
</div>
<mk-container :body-togglable="true">
<template #header><fa :icon="faMagic"/> {{ $t('variables') }}</template>
<template #header><fa :icon="faMagic"/> {{ $t('_pages.variables') }}</template>
<div class="qmuvgica">
<x-draggable tag="div" class="variables" v-show="variables.length > 0" :list="variables" handle=".drag-handle" :group="{ name: 'variables' }" animation="150" swap-threshold="0.5">
<x-variable v-for="variable in variables"
@ -70,22 +70,14 @@
</x-draggable>
<mk-button @click="addVariable()" class="add" v-if="!readonly"><fa :icon="faPlus"/></mk-button>
<x-info><span v-html="$t('variables-info')"></span><a @click="() => moreDetails = true" style="display:block;">{{ $t('more-details') }}</a></x-info>
<template v-if="moreDetails">
<x-info><span v-html="$t('variables-info2')"></span></x-info>
<x-info><span v-html="$t('variables-info3')"></span></x-info>
<x-info><span v-html="$t('variables-info4')"></span></x-info>
</template>
</div>
</mk-container>
<mk-container :body-togglable="true" :expanded="false">
<template #header><fa :icon="faCode"/> {{ $t('inspector') }}</template>
<template #header><fa :icon="faCode"/> {{ $t('_pages.inspector') }}</template>
<div style="padding:0 32px 32px 32px;">
<mk-textarea :value="JSON.stringify(content, null, 2)" readonly tall>{{ $t('content') }}</mk-textarea>
<mk-textarea :value="JSON.stringify(variables, null, 2)" readonly tall>{{ $t('variables') }}</mk-textarea>
<mk-textarea :value="JSON.stringify(content, null, 2)" readonly tall>{{ $t('_pages.content') }}</mk-textarea>
<mk-textarea :value="JSON.stringify(variables, null, 2)" readonly tall>{{ $t('_pages.variables') }}</mk-textarea>
</div>
</mk-container>
</div>
@ -152,7 +144,6 @@ export default Vue.extend({
variables: [],
aiScript: null,
showOptions: false,
moreDetails: false,
url,
faPlus, faICursor, faSave, faStickyNote, faMagic, faCog, faTrashAlt, faExternalLinkSquareAlt, faCode
};
@ -243,14 +234,14 @@ export default Vue.extend({
if (err.info.param == 'name') {
this.$root.dialog({
type: 'error',
title: this.$t('title-invalid-name'),
text: this.$t('text-invalid-name')
title: this.$t('_pages.invalidNameTitle'),
text: this.$t('_pages.invalidNameText')
});
}
} else if (err.code == 'NAME_ALREADY_EXISTS') {
this.$root.dialog({
type: 'error',
text: this.$t('name-already-exists')
text: this.$t('_pages.nameAlreadyExists')
});
}
};
@ -262,7 +253,7 @@ export default Vue.extend({
this.currentName = this.name.trim();
this.$root.dialog({
type: 'success',
text: this.$t('page-updated')
text: this.$t('_pages.updated')
});
}).catch(onError);
} else {
@ -272,7 +263,7 @@ export default Vue.extend({
this.currentName = this.name.trim();
this.$root.dialog({
type: 'success',
text: this.$t('page-created')
text: this.$t('_pages.created')
});
this.$router.push(`/my/pages/edit/${this.pageId}`);
}).catch(onError);
@ -282,7 +273,7 @@ export default Vue.extend({
del() {
this.$root.dialog({
type: 'warning',
text: this.$t('are-you-sure-delete'),
text: this.$t('removeAreYouSure', { x: this.title.trim() }),
showCancelButton: true
}).then(({ canceled }) => {
if (canceled) return;
@ -291,7 +282,7 @@ export default Vue.extend({
}).then(() => {
this.$root.dialog({
type: 'success',
text: this.$t('page-deleted')
text: this.$t('_pages.deleted')
});
this.$router.push(`/my/pages`);
});
@ -301,7 +292,7 @@ export default Vue.extend({
async add() {
const { canceled, result: type } = await this.$root.dialog({
type: null,
title: this.$t('chooseBlock'),
title: this.$t('_pages.chooseBlock'),
select: {
groupedItems: this.getPageBlockList()
},
@ -315,7 +306,7 @@ export default Vue.extend({
async addVariable() {
let { canceled, result: name } = await this.$root.dialog({
title: this.$t('enterVariableName'),
title: this.$t('_pages.enterVariableName'),
input: {
type: 'text',
},
@ -328,7 +319,7 @@ export default Vue.extend({
if (this.aiScript.isUsedName(name)) {
this.$root.dialog({
type: 'error',
text: this.$t('the-variable-name-is-already-used')
text: this.$t('_pages.variableNameIsAlreadyUsed')
});
return;
}
@ -348,7 +339,7 @@ export default Vue.extend({
getPageBlockList() {
return [{
label: this.$t('content-blocks'),
label: this.$t('_pages.contentBlocks'),
items: [
{ value: 'section', text: this.$t('_pages.blocks.section') },
{ value: 'text', text: this.$t('_pages.blocks.text') },
@ -356,7 +347,7 @@ export default Vue.extend({
{ value: 'textarea', text: this.$t('_pages.blocks.textarea') },
]
}, {
label: this.$t('input-blocks'),
label: this.$t('_pages.inputBlocks'),
items: [
{ value: 'button', text: this.$t('_pages.blocks.button') },
{ value: 'radioButton', text: this.$t('_pages.blocks.radioButton') },
@ -367,7 +358,7 @@ export default Vue.extend({
{ value: 'counter', text: this.$t('_pages.blocks.counter') }
]
}, {
label: this.$t('special-blocks'),
label: this.$t('_pages.specialBlocks'),
items: [
{ value: 'if', text: this.$t('_pages.blocks.if') },
{ value: 'post', text: this.$t('_pages.blocks.post') }

View file

@ -1,7 +1,7 @@
<template>
<div>
<mk-container :body-togglable="true">
<template #header><fa :icon="faEdit" fixed-width/>{{ $t('my-pages') }}</template>
<template #header><fa :icon="faEdit" fixed-width/>{{ $t('_pages.my') }}</template>
<div class="rknalgpo my">
<mk-button class="new" @click="create()"><fa :icon="faPlus"/></mk-button>
<mk-pagination :pagination="myPagesPagination" #default="{items}">
@ -11,7 +11,7 @@
</mk-container>
<mk-container :body-togglable="true">
<template #header><fa :icon="faHeart" fixed-width/>{{ $t('liked-pages') }}</template>
<template #header><fa :icon="faHeart" fixed-width/>{{ $t('_pages.liked') }}</template>
<div class="rknalgpo">
<mk-pagination :pagination="likedPagesPagination" #default="{items}">
<mk-page-preview v-for="like in items" class="ckltabjg" :page="like.page" :key="like.page.id"/>

View file

@ -8,7 +8,7 @@
<section class="_card">
<div class="_title"><fa :icon="faMusic"/> {{ $t('sounds') }}</div>
<div class="_content">
<mk-range v-model="sfxVolume" min="0" max="1" step="0.1">
<mk-range v-model="sfxVolume" :min="0" :max="1" :step="0.1">
<fa slot="icon" :icon="volumeIcon"/>
<span slot="title">{{ $t('volume') }}</span>
</mk-range>

View file

@ -2,8 +2,30 @@
<section class="rfqxtzch _card">
<div class="_title"><fa :icon="faPalette"/> {{ $t('theme') }}</div>
<div class="_content">
<mk-select v-model="theme" :placeholder="$t('theme')">
<template #label>{{ $t('theme') }}</template>
<div class="darkMode" :class="{ disabled: syncDeviceDarkMode }">
<div class="toggleWrapper">
<input type="checkbox" class="dn" id="dn" v-model="darkMode" :disabled="syncDeviceDarkMode"/>
<label for="dn" class="toggle">
<span class="before">{{ $t('light') }}</span>
<span class="after">{{ $t('dark') }}</span>
<span class="toggle__handler">
<span class="crater crater--1"></span>
<span class="crater crater--2"></span>
<span class="crater crater--3"></span>
</span>
<span class="star star--1"></span>
<span class="star star--2"></span>
<span class="star star--3"></span>
<span class="star star--4"></span>
<span class="star star--5"></span>
<span class="star star--6"></span>
</label>
</div>
</div>
</div>
<div class="_content">
<mk-select v-model="lightTheme">
<template #label>{{ $t('themeForLightMode') }}</template>
<optgroup :label="$t('lightThemes')">
<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
</optgroup>
@ -11,6 +33,18 @@
<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
</optgroup>
</mk-select>
<mk-select v-model="darkTheme">
<template #label>{{ $t('themeForDarkMode') }}</template>
<optgroup :label="$t('darkThemes')">
<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
</optgroup>
<optgroup :label="$t('lightThemes')">
<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
</optgroup>
</mk-select>
</div>
<div class="_content">
<mk-switch v-model="syncDeviceDarkMode">{{ $t('syncDeviceDarkMode') }}</mk-switch>
</div>
<div class="_content">
<mk-button primary v-if="wallpaper == null" @click="setWallpaper">{{ $t('setWallpaper') }}</mk-button>
@ -25,9 +59,11 @@ import { faPalette } from '@fortawesome/free-solid-svg-icons';
import MkInput from '../../components/ui/input.vue';
import MkButton from '../../components/ui/button.vue';
import MkSelect from '../../components/ui/select.vue';
import MkSwitch from '../../components/ui/switch.vue';
import i18n from '../../i18n';
import { Theme, builtinThemes, applyTheme } from '../../theme';
import { selectFile } from '../../scripts/select-file';
import { isDeviceDarkmode } from '../../scripts/is-device-darkmode';
export default Vue.extend({
i18n,
@ -36,6 +72,7 @@ export default Vue.extend({
MkInput,
MkButton,
MkSelect,
MkSwitch,
},
data() {
@ -62,15 +99,44 @@ export default Vue.extend({
return this.themes.filter(t => t.base == 'light' || t.kind == 'light');
},
theme: {
get() { return this.$store.state.device.theme; },
set(value) { this.$store.commit('device/set', { key: 'theme', value }); }
darkTheme: {
get() { return this.$store.state.device.darkTheme; },
set(value) { this.$store.commit('device/set', { key: 'darkTheme', value }); }
},
lightTheme: {
get() { return this.$store.state.device.lightTheme; },
set(value) { this.$store.commit('device/set', { key: 'lightTheme', value }); }
},
darkMode: {
get() { return this.$store.state.device.darkMode; },
set(value) { this.$store.commit('device/set', { key: 'darkMode', value }); }
},
syncDeviceDarkMode: {
get() { return this.$store.state.device.syncDeviceDarkMode; },
set(value) { this.$store.commit('device/set', { key: 'syncDeviceDarkMode', value }); }
},
},
watch: {
theme() {
applyTheme(this.themes.find(x => x.id === this.theme));
darkTheme() {
if (this.$store.state.device.darkMode) {
applyTheme(this.themes.find(x => x.id === this.darkTheme));
}
},
lightTheme() {
if (!this.$store.state.device.darkMode) {
applyTheme(this.themes.find(x => x.id === this.lightTheme));
}
},
syncDeviceDarkMode() {
if (this.$store.state.device.syncDeviceDarkMode) {
this.$store.commit('device/set', { key: 'darkMode', value: isDeviceDarkmode() });
}
},
wallpaper() {
@ -92,3 +158,230 @@ export default Vue.extend({
}
});
</script>
<style lang="scss" scoped>
.rfqxtzch {
> ._content {
> .darkMode {
position: relative;
padding: 32px 0;
&.disabled {
opacity: 0.7;
&, * {
cursor: not-allowed !important;
}
}
.toggleWrapper {
position: absolute;
top: 50%;
left: 50%;
overflow: hidden;
padding: 0 200px;
transform: translate3d(-50%, -50%, 0);
input {
position: absolute;
left: -99em;
}
}
.toggle {
cursor: pointer;
display: inline-block;
position: relative;
width: 90px;
height: 50px;
background-color: #83D8FF;
border-radius: 90px - 6;
transition: background-color 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95) !important;
> .before, > .after {
position: absolute;
top: 15px;
font-size: 18px;
transition: color 1s ease;
}
> .before {
left: -70px;
color: var(--accent);
}
> .after {
right: -68px;
color: var(--fg);
}
}
.toggle__handler {
display: inline-block;
position: relative;
z-index: 1;
top: 3px;
left: 3px;
width: 50px - 6;
height: 50px - 6;
background-color: #FFCF96;
border-radius: 50px;
box-shadow: 0 2px 6px rgba(0,0,0,.3);
transition: all 400ms cubic-bezier(0.68, -0.55, 0.265, 1.55) !important;
transform: rotate(-45deg);
.crater {
position: absolute;
background-color: #E8CDA5;
opacity: 0;
transition: opacity 200ms ease-in-out !important;
border-radius: 100%;
}
.crater--1 {
top: 18px;
left: 10px;
width: 4px;
height: 4px;
}
.crater--2 {
top: 28px;
left: 22px;
width: 6px;
height: 6px;
}
.crater--3 {
top: 10px;
left: 25px;
width: 8px;
height: 8px;
}
}
.star {
position: absolute;
background-color: #ffffff;
transition: all 300ms cubic-bezier(0.445, 0.05, 0.55, 0.95) !important;
border-radius: 50%;
}
.star--1 {
top: 10px;
left: 35px;
z-index: 0;
width: 30px;
height: 3px;
}
.star--2 {
top: 18px;
left: 28px;
z-index: 1;
width: 30px;
height: 3px;
}
.star--3 {
top: 27px;
left: 40px;
z-index: 0;
width: 30px;
height: 3px;
}
.star--4,
.star--5,
.star--6 {
opacity: 0;
transition: all 300ms 0 cubic-bezier(0.445, 0.05, 0.55, 0.95) !important;
}
.star--4 {
top: 16px;
left: 11px;
z-index: 0;
width: 2px;
height: 2px;
transform: translate3d(3px,0,0);
}
.star--5 {
top: 32px;
left: 17px;
z-index: 0;
width: 3px;
height: 3px;
transform: translate3d(3px,0,0);
}
.star--6 {
top: 36px;
left: 28px;
z-index: 0;
width: 2px;
height: 2px;
transform: translate3d(3px,0,0);
}
input:checked {
+ .toggle {
background-color: #749DD6;
> .before {
color: var(--fg);
}
> .after {
color: var(--accent);
}
.toggle__handler {
background-color: #FFE5B5;
transform: translate3d(40px, 0, 0) rotate(0);
.crater { opacity: 1; }
}
.star--1 {
width: 2px;
height: 2px;
}
.star--2 {
width: 4px;
height: 4px;
transform: translate3d(-5px, 0, 0);
}
.star--3 {
width: 2px;
height: 2px;
transform: translate3d(-7px, 0, 0);
}
.star--4,
.star--5,
.star--6 {
opacity: 1;
transform: translate3d(0,0,0);
}
.star--4 {
transition: all 300ms 200ms cubic-bezier(0.445, 0.05, 0.55, 0.95) !important;
}
.star--5 {
transition: all 300ms 300ms cubic-bezier(0.445, 0.05, 0.55, 0.95) !important;
}
.star--6 {
transition: all 300ms 400ms cubic-bezier(0.445, 0.05, 0.55, 0.95) !important;
}
}
}
}
}
}
</style>

View file

@ -0,0 +1,3 @@
export function isDeviceDarkmode() {
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
}

View file

@ -35,7 +35,10 @@ const defaultDeviceSettings = {
accounts: [],
recentEmojis: [],
themes: [],
theme: 'light',
darkTheme: '8c539dc1-0fab-4d47-9194-39c508e9bfe1',
lightTheme: '4eea646f-7afa-4645-83e9-83af0333cd37',
darkMode: false,
syncDeviceDarkMode: true,
animation: true,
animatedMfm: true,
imageNewTab: false,

View file

@ -13,8 +13,8 @@ export const lightTheme: Theme = require('./themes/_light.json5');
export const darkTheme: Theme = require('./themes/_dark.json5');
export const builtinThemes = [
lightTheme,
darkTheme,
require('./themes/white.json5'),
require('./themes/black.json5'),
require('./themes/lavender.json5'),
require('./themes/halloween.json5'),
require('./themes/garden.json5'),
@ -44,7 +44,7 @@ export function applyTheme(theme: Theme, persist = true) {
const _theme = JSON.parse(JSON.stringify(theme));
if (_theme.base) {
const base = [lightTheme, darkTheme].find(x => x.id == _theme.base);
const base = [lightTheme, darkTheme].find(x => x.id === _theme.base);
_theme.props = Object.assign({}, base.props, _theme.props);
}

View file

@ -0,0 +1,14 @@
{
id: '8c539dc1-0fab-4d47-9194-39c508e9bfe1',
name: 'Black',
author: 'syuilo',
desc: 'Basic dark theme',
base: 'dark',
props: {
divider: '#2d2d2d',
messageBg: '#1d1d1d',
},
}

View file

@ -0,0 +1,13 @@
{
id: '4eea646f-7afa-4645-83e9-83af0333cd37',
name: 'White',
author: 'syuilo',
desc: 'Basic light theme',
base: 'light',
props: {
messageBg: '#dedede',
},
}

10
src/docs/pages.ja-JP.md Normal file
View file

@ -0,0 +1,10 @@
# Pages
## 変数
変数を使うことで動的なページを作成できます。テキスト内で <b>{ 変数名 }</b> と書くとそこに変数の値を埋め込めます。例えば <b>Hello { thing } world!</b> というテキストで、変数(thing)の値が <b>ai</b> だった場合、テキストは <b>Hello ai world!</b> になります。
変数の評価(値を算出すること)は上から下に行われるので、ある変数の中で自分より下の変数を参照することはできません。例えば上から <b>A、B、C</b> と3つの変数を定義したとき、<b>C</b>の中で<b>A</b><b>B</b>を参照することはできますが、<b>A</b>の中で<b>B</b><b>C</b>を参照することはできません。
ユーザーからの入力を受け取るには、ページに「ユーザー入力」ブロックを設置し、「変数名」に入力を格納したい変数名を設定します(変数は自動で作成されます)。その変数を使ってユーザー入力に応じた動作を行えます。
関数を使うと、値の算出処理を再利用可能な形にまとめることができます。関数を作るには、「関数」タイプの変数を作成します。関数にはスロット(引数)を設定することができ、スロットの値は関数内で変数として利用可能です。また、AiScript標準で関数を引数に取る関数(高階関数と呼ばれます)も存在します。関数は予め定義しておくほかに、このような高階関数のスロットに即席でセットすることもできます。

View file

@ -5,7 +5,17 @@ const dateTimeIntervals = {
};
export function dateUTC(time: number[]): Date {
return new Date(Date.UTC(...time));
const d = time.length === 2 ? Date.UTC(time[0], time[1])
: time.length === 3 ? Date.UTC(time[0], time[1], time[2])
: time.length === 4 ? Date.UTC(time[0], time[1], time[2], time[3])
: time.length === 5 ? Date.UTC(time[0], time[1], time[2], time[3], time[4])
: time.length === 6 ? Date.UTC(time[0], time[1], time[2], time[3], time[4], time[5])
: time.length === 7 ? Date.UTC(time[0], time[1], time[2], time[3], time[4], time[5], time[6])
: null;
if (!d) throw 'wrong number of arguments';
return new Date(d);
}
export function isTimeSame(a: Date, b: Date): boolean {

View file

@ -72,6 +72,7 @@ export default define(meta, async (ps, me) => {
q.andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' })
}
q.andWhere('user.updatedAt IS NOT NULL');
q.orderBy('user.updatedAt', 'DESC');
const users = await q.take(ps.limit!).skip(ps.offset).getMany();
@ -82,6 +83,7 @@ export default define(meta, async (ps, me) => {
.where('user.host IS NULL')
.andWhere('user.isSuspended = FALSE')
.andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' })
.andWhere('user.updatedAt IS NOT NULL')
.orderBy('user.updatedAt', 'DESC')
.take(ps.limit!)
.skip(ps.offset)
@ -92,6 +94,7 @@ export default define(meta, async (ps, me) => {
.where('user.host IS NOT NULL')
.andWhere('user.isSuspended = FALSE')
.andWhere('user.usernameLower like :username', { username: ps.username.toLowerCase() + '%' })
.andWhere('user.updatedAt IS NOT NULL')
.orderBy('user.updatedAt', 'DESC')
.take(ps.limit! - users.length)
.getMany();

View file

@ -74,6 +74,7 @@ export default define(meta, async (ps, me) => {
.where('user.host IS NULL')
.andWhere('user.isSuspended = FALSE')
.andWhere('user.usernameLower like :username', { username: ps.query.replace('@', '').toLowerCase() + '%' })
.andWhere('user.updatedAt IS NOT NULL')
.orderBy('user.updatedAt', 'DESC')
.take(ps.limit!)
.skip(ps.offset)
@ -84,6 +85,7 @@ export default define(meta, async (ps, me) => {
.where('user.host IS NOT NULL')
.andWhere('user.isSuspended = FALSE')
.andWhere('user.usernameLower like :username', { username: ps.query.replace('@', '').toLowerCase() + '%' })
.andWhere('user.updatedAt IS NOT NULL')
.orderBy('user.updatedAt', 'DESC')
.take(ps.limit! - users.length)
.getMany();