Merge branch 'develop'

This commit is contained in:
syuilo 2019-06-16 16:09:04 +09:00
commit 5cc1aab530
No known key found for this signature in database
GPG key ID: BDC4C49D06AB9D69
28 changed files with 184 additions and 113 deletions

View file

@ -17,6 +17,17 @@ npm i -g ts-node
npm run migrate npm run migrate
``` ```
11.21.0 (2019/06/16)
--------------------
### ✨Improvements
* Unicode 12.0 の絵文字に対応
* 閉鎖しているホストにはAP deliverしないように
* image以外はproxyしないように
### 🐛Fixes
* サムネイル生成でエラーになるとファイルのアップロードに失敗する問題を修正
* オートコンプリートにアニメーション停止が効かない問題を修正
11.20.4 (2019/06/13) 11.20.4 (2019/06/13)
-------------------- --------------------
### 🐛Fixes ### 🐛Fixes

View file

@ -94,9 +94,20 @@ common:
follow-users-to-make-your-timeline: "Poznámky sledujících se zobrazí ve vaší časové ose" follow-users-to-make-your-timeline: "Poznámky sledujících se zobrazí ve vaší časové ose"
explore: "Najít uživatele" explore: "Najít uživatele"
post-form: post-form:
attach-location-information: "Přidat informace o lokaci"
hide-contents: "Schovat obsah"
reply-placeholder: "Odpovědět na tento příspěvek"
quote-placeholder: "Citovat tento příspěvek"
submit: "Odeslat" submit: "Odeslat"
reply: "Odpovědět" reply: "Odpovědět"
renote: "Renotovat" renote: "Renotovat"
attach-media-from-local: "Uplodovat soubor z vašeho zařízení"
insert-a-kao: "v('ω')v"
create-poll: "Vytvořit anketu"
text-remain: "zbývá ještě {} znaků"
recent-tags: "Nejnovější"
visibility: "Viditelnost"
geolocation-alert: "Vaše zařízení nedalo k dispozici lokaci"
error: "Chyba" error: "Chyba"
enter-username: "Zadejte své uživatelské jméno" enter-username: "Zadejte své uživatelské jméno"
add-visible-user: "Přidat uživatele" add-visible-user: "Přidat uživatele"
@ -316,7 +327,10 @@ auth/views/form.vue:
accept: "Povolit přístup" accept: "Povolit přístup"
auth/views/index.vue: auth/views/index.vue:
loading: "Načítám..." loading: "Načítám..."
denied-paragraph: "Tato aplikace nebude mít přístup k Vašemu účtu."
already-authorized: "Tato aplikace byla již autorizována." already-authorized: "Tato aplikace byla již autorizována."
callback-url: "Zpátky do aplikace."
please-go-back: "Prosím vraťte se zpátky do aplikace."
error: "Taková relace neexistuje." error: "Taková relace neexistuje."
sign-in: "Prosím přihlaste se." sign-in: "Prosím přihlaste se."
common/views/pages/explore.vue: common/views/pages/explore.vue:
@ -366,20 +380,25 @@ common/views/components/games/reversi/reversi.room.vue:
waiting-for-both: "Připravuji" waiting-for-both: "Připravuji"
cancel: "Zrušit" cancel: "Zrušit"
ready: "Připraveno" ready: "Připraveno"
cancel-ready: "Pokračovat v přípravě"
common/views/components/connect-failed.vue: common/views/components/connect-failed.vue:
title: "Nelze se připojit k serveru" title: "Nelze se připojit k serveru"
description: "Nastal problém s Vaším připojením k internetu, nebo server není dostupný nebo zrovna probíhá údržba. Prosím {zkuste to znova} za pár minut." description: "Nastal problém s Vaším připojením k internetu, nebo server není dostupný nebo zrovna probíhá údržba. Prosím {zkuste to znova} za pár minut."
thanks: "Děkujeme že jste použili Misskey." thanks: "Děkujeme že jste použili Misskey."
common/views/components/connect-failed.troubleshooter.vue: common/views/components/connect-failed.troubleshooter.vue:
title: "Poradce při potížích"
network: "Síťové připojení" network: "Síťové připojení"
checking-network: "Prověřit síťové připojení" checking-network: "Prověřit síťové připojení"
internet: "Připojení k internetu" internet: "Připojení k internetu"
checking-internet: "Ověřuji připojení k internetu." checking-internet: "Ověřuji připojení k internetu."
server: "Připojení k serveru" server: "Připojení k serveru"
checking-server: "Spojuji se se serverem"
no-network-desc: "Ujistěte se že jste připojeni k Internetu." no-network-desc: "Ujistěte se že jste připojeni k Internetu."
no-internet: "Nejste připojeni k internetu" no-internet: "Nejste připojeni k internetu"
no-internet-desc: "Jste připojen k síti, ale zdá se že stále chybí připojení k Internetu. Prosím zkontrolujte Vaše připojení k Internetu." no-internet-desc: "Jste připojen k síti, ale zdá se že stále chybí připojení k Internetu. Prosím zkontrolujte Vaše připojení k Internetu."
no-server: "Nelze se připojit k serveru Misskey" no-server: "Nelze se připojit k serveru Misskey"
success: "Úspěšně se podařilo spojit s Misskey serverem"
flush: "Vyčistit mezipaměť"
common/views/components/media-banner.vue: common/views/components/media-banner.vue:
sensitive: "Choulostivý obsah" sensitive: "Choulostivý obsah"
click-to-show: "Klikněte pro zobrazení" click-to-show: "Klikněte pro zobrazení"
@ -403,8 +422,10 @@ common/views/components/theme.vue:
find-more-theme: "Najít další vzhledy" find-more-theme: "Najít další vzhledy"
theme-name: "Jméno vzhledu" theme-name: "Jméno vzhledu"
preview-created-theme: "Náhled" preview-created-theme: "Náhled"
invalid-theme: "Vzhled není validní"
already-installed: "Tento vzhled je již nainstalován." already-installed: "Tento vzhled je již nainstalován."
saved: "Uloženo" saved: "Uloženo"
manage-themes: "Správa vzhledů"
builtin-themes: "Standardní vzhledy" builtin-themes: "Standardní vzhledy"
my-themes: "Moje vzhledy" my-themes: "Moje vzhledy"
installed-themes: "Nainstalované vzhledy" installed-themes: "Nainstalované vzhledy"
@ -415,6 +436,7 @@ common/views/components/theme.vue:
desc: "Popis" desc: "Popis"
export: "Exportovat" export: "Exportovat"
import: "Importovat" import: "Importovat"
import-by-code: "nebo zkopírujte kód"
theme-name-required: "Jméno vzhledu je povinné" theme-name-required: "Jméno vzhledu je povinné"
common/views/components/cw-button.vue: common/views/components/cw-button.vue:
hide: "Skrýt" hide: "Skrýt"
@ -487,10 +509,13 @@ common/views/components/poll-editor.vue:
remove: "Odstranit tuto možnost" remove: "Odstranit tuto možnost"
add: "+ Přidat možnost" add: "+ Přidat možnost"
destroy: "Zahodit dotazník" destroy: "Zahodit dotazník"
multiple: "Více odpovědí je povoleno"
expiration: "Termín" expiration: "Termín"
infinite: "Nekonečne" infinite: "Nekonečne"
at: "Výběr data a času" at: "Výběr data a času"
no-more: "Více už přidat nemůžete"
deadline-date: "Termín ukončení" deadline-date: "Termín ukončení"
deadline-time: "Doba trvání"
interval: "Trvání" interval: "Trvání"
second: "Sekunda" second: "Sekunda"
minute: "Minuta" minute: "Minuta"
@ -498,6 +523,7 @@ common/views/components/poll-editor.vue:
day: "Ne" day: "Ne"
common/views/components/reaction-picker.vue: common/views/components/reaction-picker.vue:
choose-reaction: "Vyberte svoji reakci" choose-reaction: "Vyberte svoji reakci"
input-reaction-placeholder: "nebo vložte Emoji"
common/views/components/emoji-picker.vue: common/views/components/emoji-picker.vue:
custom-emoji: "Emoji" custom-emoji: "Emoji"
people: "Lidé" people: "Lidé"
@ -511,6 +537,7 @@ common/views/components/emoji-picker.vue:
common/views/components/signin.vue: common/views/components/signin.vue:
username: "Přezdívka" username: "Přezdívka"
password: "Heslo" password: "Heslo"
token: "Token"
signing-in: "Přihlašování..." signing-in: "Přihlašování..."
or: "Nebo" or: "Nebo"
signin-with-twitter: "Přihlásit se pomocí účtu Twitter" signin-with-twitter: "Přihlásit se pomocí účtu Twitter"
@ -538,6 +565,7 @@ common/views/components/signup.vue:
password-matched: "OK" password-matched: "OK"
password-not-matched: "Neshodují se" password-not-matched: "Neshodují se"
recaptcha: "Potvrzení" recaptcha: "Potvrzení"
tos: "Podmínky užívání"
create: "Vytvořit účet" create: "Vytvořit účet"
some-error: "Pokus o vytvoření účtu selhal. Prosím zkuste to znovu." some-error: "Pokus o vytvoření účtu selhal. Prosím zkuste to znovu."
common/views/components/special-message.vue: common/views/components/special-message.vue:
@ -576,6 +604,7 @@ common/views/components/visibility-chooser.vue:
home: "Domů" home: "Domů"
specified-desc: "Poslat pouze zmíněným uživatelům" specified-desc: "Poslat pouze zmíněným uživatelům"
local-public: "Veřejná (pouze místní)" local-public: "Veřejná (pouze místní)"
local-public-desc: "Nepublikovat na vzdálených serverech"
local-home: "Domovská (pouze místní)" local-home: "Domovská (pouze místní)"
local-followers: "Pro sledující (pouze místní)" local-followers: "Pro sledující (pouze místní)"
common/views/components/trends.vue: common/views/components/trends.vue:
@ -585,6 +614,8 @@ common/views/components/language-settings.vue:
title: "Zobrazit jazyky" title: "Zobrazit jazyky"
pick-language: "Zvolte jazyk" pick-language: "Zvolte jazyk"
recommended: "Doporučené" recommended: "Doporučené"
auto: "Automaticky"
specify-language: "Vyberte jazyk"
info: "Pro aktivování změn musíte znovu načíst stránky." info: "Pro aktivování změn musíte znovu načíst stránky."
common/views/components/profile-editor.vue: common/views/components/profile-editor.vue:
title: "Profil" title: "Profil"
@ -611,6 +642,7 @@ common/views/components/profile-editor.vue:
email-not-verified: "Váš email není potvrzen. Prosím zkontrolujte si svou schránku." email-not-verified: "Váš email není potvrzen. Prosím zkontrolujte si svou schránku."
export: "Exportovat" export: "Exportovat"
import: "Importovat" import: "Importovat"
export-and-import: "Import / Export"
export-targets: export-targets:
following-list: "Seznam sledujících" following-list: "Seznam sledujících"
mute-list: "Seznam ztlumených uživatelů" mute-list: "Seznam ztlumených uživatelů"
@ -630,19 +662,31 @@ common/views/components/user-list-editor.vue:
add-user: "Přidat uživatele" add-user: "Přidat uživatele"
common/views/components/user-group-editor.vue: common/views/components/user-group-editor.vue:
users: "Členové" users: "Členové"
rename: "Přejmenovat skupinu"
delete: "Odstranit skupinu"
transfer: "Přesunout skupinu" transfer: "Přesunout skupinu"
transfer-are-you-sure: "Jste si jistí že chcete přidat @$2 do skupiny: $1?"
transferred: "Skupina přesunuta" transferred: "Skupina přesunuta"
remove-user: "Odebrat uživatele z této skupiny"
delete-are-you-sure: "Jste si jistí že chcete smazat skupinu \"$1\"?"
deleted: "Smazáno" deleted: "Smazáno"
invite: "Pozvat" invite: "Pozvat"
invited: "Pozvánka byla úspěšně odeslána"
common/views/components/user-lists.vue: common/views/components/user-lists.vue:
user-lists: "Seznamy" user-lists: "Seznamy"
create-list: "Vytvořit seznam"
list-name: "Název seznamu" list-name: "Název seznamu"
common/views/components/user-groups.vue: common/views/components/user-groups.vue:
user-groups: "Skupiny" user-groups: "Skupiny"
create-group: "Vytvořit skupinu"
group-name: "Název skupiny"
owned-groups: "Moje skupiny"
invites: "Pozvat" invites: "Pozvat"
reject-invite: "Odmítnout" reject-invite: "Odmítnout"
common/views/widgets/broadcast.vue: common/views/widgets/broadcast.vue:
fetching: "Načítám" fetching: "Načítám"
no-broadcasts: "Žádná nová oznámení"
have-a-nice-day: "Přejeme Vám příjemný den!"
next: "Další" next: "Další"
common/views/widgets/calendar.vue: common/views/widgets/calendar.vue:
year: "Rok {}" year: "Rok {}"
@ -800,6 +844,7 @@ desktop/views/components/renote-form-window.vue:
desktop/views/components/settings.2fa.vue: desktop/views/components/settings.2fa.vue:
detail: "Více…" detail: "Více…"
url: "https://www.google.cz/landing/2step/" url: "https://www.google.cz/landing/2step/"
token: "Token"
common/views/components/media-image.vue: common/views/components/media-image.vue:
click-to-show: "Klikněte pro zobrazení" click-to-show: "Klikněte pro zobrazení"
common/views/components/api-settings.vue: common/views/components/api-settings.vue:

View file

@ -1761,8 +1761,7 @@ pages:
_divide: _divide:
arg1: "A" arg1: "A"
arg2: "B" arg2: "B"
remind: "÷ Tomo" _mod:
_remind:
arg1: "A" arg1: "A"
arg2: "B" arg2: "B"
eq: "A og B er ens" eq: "A og B er ens"

View file

@ -1857,8 +1857,8 @@ pages:
_divide: _divide:
arg1: "A" arg1: "A"
arg2: "B" arg2: "B"
remind: "÷ Remaindering" mod: "÷ Remaindering"
_remind: _mod:
arg1: "A" arg1: "A"
arg2: "B" arg2: "B"
eq: "A and B are equal" eq: "A and B are equal"

View file

@ -12,7 +12,7 @@ common:
rich-contents: "Notes" rich-contents: "Notes"
rich-contents-desc: "Partagez vos idées, les événements et les sujets qui vous tiennent à cœur ainsi que tout autre chose que vous souhaitez partager avec les autres. Si vous le désirez, vous pouvez décorer vos messages en utilisant une syntaxe différente ou en y joignant des sondages et des fichiers, tels que les photos ou les vidéos que vous aimez." rich-contents-desc: "Partagez vos idées, les événements et les sujets qui vous tiennent à cœur ainsi que tout autre chose que vous souhaitez partager avec les autres. Si vous le désirez, vous pouvez décorer vos messages en utilisant une syntaxe différente ou en y joignant des sondages et des fichiers, tels que les photos ou les vidéos que vous aimez."
reaction: "Réactions" reaction: "Réactions"
reaction-desc: "Une manière simple d'exprimer vos émotions. Misskey peut attacher diverses réactions aux publications des autres utilisateurs. Si vous essayez les réactions sur Misskey, vous ne pourrez plus retourner sur une autre plateforme de réseaux sociaux n'offrant que des « J'aime »." reaction-desc: "Une manière simple d'exprimer vos émotions. Misskey peut attacher diverses réactions aux publications des autres utilisateur·rice·s. Si vous essayez les réactions sur Misskey, vous ne pourrez plus retourner sur une autre plateforme de réseaux sociaux n'offrant que des « J'aime »."
ui: "Interface" ui: "Interface"
ui-desc: "Aucune interface graphique ne peut plaire à tout le monde. Par conséquent, Misskey possède une interface utilisateur hautement personnalisable selon vos goûts. Vous pouvez rendre votre page d'accueil originale en modifiant la mise en page de votre fil et en déplaçant les widgets que vous pouvez facilement ajuster pour vous approprier cet espace." ui-desc: "Aucune interface graphique ne peut plaire à tout le monde. Par conséquent, Misskey possède une interface utilisateur hautement personnalisable selon vos goûts. Vous pouvez rendre votre page d'accueil originale en modifiant la mise en page de votre fil et en déplaçant les widgets que vous pouvez facilement ajuster pour vous approprier cet espace."
drive: "Drive" drive: "Drive"
@ -89,8 +89,8 @@ common:
"write:reactions": "Gérer vos réactions" "write:reactions": "Gérer vos réactions"
"write:votes": "Vote" "write:votes": "Vote"
empty-timeline-info: empty-timeline-info:
follow-users-to-make-your-timeline: "Les utilisateurs suivants afficheront leurs publications sur votre fil." follow-users-to-make-your-timeline: "Les utilisateur·rice·s suivant·e·s afficheront leurs publications sur votre fil."
explore: "Trouver des utilisateurs" explore: "Trouver des utilisateur·rice·s"
post-form: post-form:
attach-location-information: "Joindre des informations de localisation" attach-location-information: "Joindre des informations de localisation"
hide-contents: "Masquer les contenus" hide-contents: "Masquer les contenus"
@ -148,13 +148,13 @@ common:
public: "Public" public: "Public"
home: "Principal" home: "Principal"
home-desc: "Publier sur le fil principal uniquement" home-desc: "Publier sur le fil principal uniquement"
followers: "Abonnés" followers: "Abonné·e·s"
followers-desc: "Publier à vos abonnés uniquement" followers-desc: "Publier à vos abonné·e·s uniquement"
specified: "Direct" specified: "Direct"
specified-desc: "Publier uniquement aux utilisateurs mentionnés" specified-desc: "Publier uniquement aux utilisateur·rice·s mentionné·e·s"
local-public: "Local (Public)" local-public: "Local (Public)"
local-home: "Accueil (local uniquement)" local-home: "Accueil (local uniquement)"
local-followers: "Local (Abonnés)" local-followers: "Abonné·e·s (Local uniquement)"
note-placeholders: note-placeholders:
a: "Que faites-vous maintenant ?" a: "Que faites-vous maintenant ?"
b: "Quoi de neuf ?" b: "Quoi de neuf ?"
@ -314,7 +314,7 @@ common:
version: "Version" version: "Version"
broadcast: "Diffusion" broadcast: "Diffusion"
notifications: "Notifications" notifications: "Notifications"
users: "Utilisateurs recommandés" users: "Utilisateur·rice·s recommandé·e·s"
polls: "Sondages" polls: "Sondages"
post-form: "Champs de publication" post-form: "Champs de publication"
server: "Infos sur le serveur" server: "Infos sur le serveur"
@ -342,13 +342,13 @@ auth/views/index.vue:
sign-in: "Veuillez vous connecter" sign-in: "Veuillez vous connecter"
common/views/pages/explore.vue: common/views/pages/explore.vue:
pinned-users: "Utilisateur·rice·s épinglé·e·s" pinned-users: "Utilisateur·rice·s épinglé·e·s"
popular-users: "Utilisateurs populaires" popular-users: "Utilisateur·rice·s populaires"
recently-updated-users: "Utilisateurs actifs récemment" recently-updated-users: "Utilisateur·rice·s actif·ve·s récemment"
recently-registered-users: "Les nouveaux inscrits" recently-registered-users: "Les nouveaux inscrits"
popular-tags: "Mots-clés populaires" popular-tags: "Mots-clés populaires"
federated: "Du Fédiverse" federated: "Du Fédiverse"
explore: "Explorer {host}" explore: "Explorer {host}"
users-info: "Actuellement, {users} utilisateurs se sont inscrit ici" users-info: "Actuellement, {users} utilisateur·rice·s se sont inscrit ici"
common/views/components/url-preview.vue: common/views/components/url-preview.vue:
enable-player: "Activer la lecture" enable-player: "Activer la lecture"
disable-player: "Fermer le lecteur" disable-player: "Fermer le lecteur"
@ -653,13 +653,13 @@ common/views/components/visibility-chooser.vue:
followers: "Abonné·e·s" followers: "Abonné·e·s"
followers-desc: "Publier à vos abonné·e·s uniquement" followers-desc: "Publier à vos abonné·e·s uniquement"
specified: "Direct" specified: "Direct"
specified-desc: "Publier uniquement aux utilisateurs mentionnés" specified-desc: "Publier uniquement aux utilisateur·rice·s mentionné·e·s"
local-public: "Local (Public)" local-public: "Local (Public)"
local-public-desc: "Ne pas publier pour les distants" local-public-desc: "Ne pas publier pour les distants"
local-home: "Accueil (local uniquement)" local-home: "Accueil (local uniquement)"
local-followers: "Local (Abonnés)" local-followers: "Abonné·e·s (Local uniquement)"
common/views/components/trends.vue: common/views/components/trends.vue:
count: "{} utilisateurs mentionnés" count: "{} utilisateur·rice·s mentionné·e·s"
empty: "Aucune tendance" empty: "Aucune tendance"
common/views/components/language-settings.vue: common/views/components/language-settings.vue:
title: "Langue " title: "Langue "
@ -897,7 +897,7 @@ desktop/views/components/media-video.vue:
sensitive: "Le contenu est NSFW" sensitive: "Le contenu est NSFW"
click-to-show: "Cliquer pour afficher" click-to-show: "Cliquer pour afficher"
desktop/views/components/followers-window.vue: desktop/views/components/followers-window.vue:
followers: "{} abonné·e·s" followers: "Abonné·e·s de {}"
desktop/views/components/followers.vue: desktop/views/components/followers.vue:
empty: "Il semble que vous navez pas encore dabonné·e·s." empty: "Il semble que vous navez pas encore dabonné·e·s."
desktop/views/components/following-window.vue: desktop/views/components/following-window.vue:
@ -1224,7 +1224,7 @@ admin/views/charts.vue:
per-hour: "par heure" per-hour: "par heure"
federation: "Fédération" federation: "Fédération"
notes: "Publications" notes: "Publications"
users: "Utilisateurs" users: "Utilisateur·rice·s"
drive: "Lecteur" drive: "Lecteur"
network: "Réseau" network: "Réseau"
charts: charts:
@ -1234,8 +1234,8 @@ admin/views/charts.vue:
local-notes: "Nombre des publications : augmentation/diminution (Local)" local-notes: "Nombre des publications : augmentation/diminution (Local)"
remote-notes: "Nombre de publications : augmentation/diminution (distants)" remote-notes: "Nombre de publications : augmentation/diminution (distants)"
notes-total: "Total des notes" notes-total: "Total des notes"
users: "Nombre dutilisateurs : augmentation/diminution" users: "Nombre dutilisateur·rice·s : augmentation/diminution"
users-total: "Nombre total des utilisateurs" users-total: "Nombre total des utilisateur·rice·s"
active-users: "Utilisateur·rice·s actif·ve·s" active-users: "Utilisateur·rice·s actif·ve·s"
drive: "Capacité utilisée comme stockage : augmentation/diminution" drive: "Capacité utilisée comme stockage : augmentation/diminution"
drive-total: "Utilisation totale du lecteur" drive-total: "Utilisation totale du lecteur"
@ -1266,6 +1266,7 @@ admin/views/drive.vue:
unmark-as-sensitive: "Ne pas marquer comme sensible" unmark-as-sensitive: "Ne pas marquer comme sensible"
marked-as-sensitive: "Marqué comme sensible" marked-as-sensitive: "Marqué comme sensible"
unmarked-as-sensitive: "Marqué comme non sensible" unmarked-as-sensitive: "Marqué comme non sensible"
clean-remote-files: "Nettoyer le cache des fichiers distants"
clean-up: "Nettoyage" clean-up: "Nettoyage"
admin/views/users.vue: admin/views/users.vue:
operation: "Actions" operation: "Actions"
@ -1374,7 +1375,7 @@ admin/views/federation.vue:
lastCommunicatedAtAsc: "La date et l'heure des interactions plus anciennes" lastCommunicatedAtAsc: "La date et l'heure des interactions plus anciennes"
lastCommunicatedAtDesc: "La date et l'heure des nouvelles interactions" lastCommunicatedAtDesc: "La date et l'heure des nouvelles interactions"
notesDesc: "Description des notes" notesDesc: "Description des notes"
usersAsc: "Peu d'abonnés" usersAsc: "Peu d'abonné·e·s"
followingAsc: "Les moins suivies" followingAsc: "Les moins suivies"
followingDesc: "Ayant le plus d'abonné·e·s" followingDesc: "Ayant le plus d'abonné·e·s"
followersAsc: "Ayant le moins d'abonné·e·s" followersAsc: "Ayant le moins d'abonné·e·s"
@ -1389,7 +1390,7 @@ admin/views/federation.vue:
charts: "Graphs" charts: "Graphs"
chart-srcs: chart-srcs:
requests: "Requêtes" requests: "Requêtes"
users: "Nombre dutilisateurs·trices : augmentation/diminution" users: "Nombre dutilisateur·trice·s : augmentation/diminution"
users-total: "Nombre total des utilisateur·rice·s" users-total: "Nombre total des utilisateur·rice·s"
notes: "Augmentation/diminution du nombre des notes" notes: "Augmentation/diminution du nombre des notes"
notes-total: "Nombre total des notes" notes-total: "Nombre total des notes"
@ -1431,7 +1432,7 @@ desktop/views/pages/user-list.users.vue:
desktop/views/pages/user/user.followers-you-know.vue: desktop/views/pages/user/user.followers-you-know.vue:
title: "Abonné·e·s que vous connaissez" title: "Abonné·e·s que vous connaissez"
loading: "Chargement en cours" loading: "Chargement en cours"
no-users: "Aucun abonné connu" no-users: "Aucun·e abonné·e connu·e"
desktop/views/pages/user/user.friends.vue: desktop/views/pages/user/user.friends.vue:
title: "Mentions fréquentes" title: "Mentions fréquentes"
loading: "Chargement en cours" loading: "Chargement en cours"
@ -1646,7 +1647,7 @@ deck/deck.user-column.vue:
follows-you: "Vous suit" follows-you: "Vous suit"
posts: "Notes" posts: "Notes"
following: "Suit" following: "Suit"
followers: "Abonnés" followers: "Abonné·e·s"
images: "Images" images: "Images"
activity: "Activité" activity: "Activité"
timeline: "Fil dactualité" timeline: "Fil dactualité"
@ -1688,6 +1689,7 @@ pages:
view-source: "Afficher la source" view-source: "Afficher la source"
view-page: "Afficher la page" view-page: "Afficher la page"
like: "Bien" like: "Bien"
liked-pages: "Pages favorites"
my-pages: "Mes pages" my-pages: "Mes pages"
inspector: "Inspecteur" inspector: "Inspecteur"
content: "Bloc de page" content: "Bloc de page"
@ -1801,7 +1803,7 @@ pages:
_divide: _divide:
arg1: "A" arg1: "A"
arg2: "B" arg2: "B"
_remind: _mod:
arg1: "A" arg1: "A"
arg2: "B" arg2: "B"
eq: "A et B sont équivalents" eq: "A et B sont équivalents"

View file

@ -2060,8 +2060,8 @@ pages:
_divide: _divide:
arg1: "A" arg1: "A"
arg2: "B" arg2: "B"
remind: "÷ 割った余り" mod: "÷ 割った余り"
_remind: _mod:
arg1: "A" arg1: "A"
arg2: "B" arg2: "B"
eq: "AとBが同じ" eq: "AとBが同じ"

View file

@ -1857,8 +1857,8 @@ pages:
_divide: _divide:
arg1: "A" arg1: "A"
arg2: "B" arg2: "B"
remind: "÷ 나눈 나머지" mod: "÷ 나눈 나머지"
_remind: _mod:
arg1: "A" arg1: "A"
arg2: "B" arg2: "B"
eq: "A와 B가 동일" eq: "A와 B가 동일"

View file

@ -1857,8 +1857,8 @@ pages:
_divide: _divide:
arg1: "A" arg1: "A"
arg2: "B" arg2: "B"
remind: "÷ 取模" mod: "÷ 取模"
_remind: _mod:
arg1: "A" arg1: "A"
arg2: "B" arg2: "B"
eq: "A和B相等" eq: "A和B相等"

View file

@ -1,7 +1,7 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "11.20.4", "version": "11.21.0",
"codename": "daybreak", "codename": "daybreak",
"repository": { "repository": {
"type": "git", "type": "git",
@ -99,7 +99,7 @@
"@types/websocket": "0.0.40", "@types/websocket": "0.0.40",
"@types/ws": "6.0.1", "@types/ws": "6.0.1",
"animejs": "3.0.1", "animejs": "3.0.1",
"apexcharts": "3.7.1", "apexcharts": "3.8.0",
"autobind-decorator": "2.4.0", "autobind-decorator": "2.4.0",
"autosize": "4.0.2", "autosize": "4.0.2",
"autwh": "0.1.0", "autwh": "0.1.0",
@ -165,11 +165,11 @@
"loader-utils": "1.2.3", "loader-utils": "1.2.3",
"lolex": "3.1.0", "lolex": "3.1.0",
"lookup-dns-cache": "2.1.0", "lookup-dns-cache": "2.1.0",
"minio": "7.0.8", "minio": "7.0.10",
"mocha": "6.1.4", "mocha": "6.1.4",
"moji": "0.5.1", "moji": "0.5.1",
"moment": "2.24.0", "moment": "2.24.0",
"ms": "2.1.1", "ms": "2.1.2",
"nested-property": "0.0.7", "nested-property": "0.0.7",
"node-fetch": "2.6.0", "node-fetch": "2.6.0",
"nodemailer": "6.2.1", "nodemailer": "6.2.1",
@ -215,7 +215,7 @@
"stylus": "0.54.5", "stylus": "0.54.5",
"stylus-loader": "3.0.2", "stylus-loader": "3.0.2",
"summaly": "2.2.0", "summaly": "2.2.0",
"systeminformation": "4.1.6", "systeminformation": "4.11.1",
"syuilo-password-strength": "0.0.1", "syuilo-password-strength": "0.0.1",
"terser-webpack-plugin": "1.3.0", "terser-webpack-plugin": "1.3.0",
"textarea-caret": "3.1.0", "textarea-caret": "3.1.0",
@ -255,8 +255,8 @@
"vuex": "3.1.1", "vuex": "3.1.1",
"vuex-persistedstate": "2.5.4", "vuex-persistedstate": "2.5.4",
"web-push": "3.3.5", "web-push": "3.3.5",
"webpack": "4.33.0", "webpack": "4.34.0",
"webpack-cli": "3.3.2", "webpack-cli": "3.3.4",
"websocket": "1.0.28", "websocket": "1.0.28",
"ws": "7.0.0", "ws": "7.0.0",
"xev": "2.0.1" "xev": "2.0.1"

View file

@ -16,7 +16,7 @@
</ol> </ol>
<ol class="emojis" ref="suggests" v-if="emojis.length > 0"> <ol class="emojis" ref="suggests" v-if="emojis.length > 0">
<li v-for="emoji in emojis" @click="complete(type, emoji.emoji)" @keydown="onKeydown" tabindex="-1"> <li v-for="emoji in emojis" @click="complete(type, emoji.emoji)" @keydown="onKeydown" tabindex="-1">
<span class="emoji" v-if="emoji.isCustomEmoji"><img :src="emoji.url" :alt="emoji.emoji"/></span> <span class="emoji" v-if="emoji.isCustomEmoji"><img :src="$store.state.device.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url" :alt="emoji.emoji"/></span>
<span class="emoji" v-else-if="!useOsDefaultEmojis"><img :src="emoji.url" :alt="emoji.emoji"/></span> <span class="emoji" v-else-if="!useOsDefaultEmojis"><img :src="emoji.url" :alt="emoji.emoji"/></span>
<span class="emoji" v-else>{{ emoji.emoji }}</span> <span class="emoji" v-else>{{ emoji.emoji }}</span>
<span class="name" v-html="emoji.name.replace(q, `<b>${q}</b>`)"></span> <span class="name" v-html="emoji.name.replace(q, `<b>${q}</b>`)"></span>
@ -31,6 +31,7 @@ import Vue from 'vue';
import * as emojilib from 'emojilib'; import * as emojilib from 'emojilib';
import contains from '../../../common/scripts/contains'; import contains from '../../../common/scripts/contains';
import { twemojiBase } from '../../../../../misc/twemoji-base'; import { twemojiBase } from '../../../../../misc/twemoji-base';
import { getStaticImageUrl } from '../../../common/scripts/get-static-image-url';
type EmojiDef = { type EmojiDef = {
emoji: string; emoji: string;
@ -78,6 +79,7 @@ export default Vue.extend({
data() { data() {
return { return {
getStaticImageUrl,
fetching: true, fetching: true,
users: [], users: [],
hashtags: [], hashtags: [],

View file

@ -257,7 +257,7 @@ export default class Reversi {
public get winner(): Color | null { public get winner(): Color | null {
return this.isEnded ? return this.isEnded ?
this.blackCount == this.whiteCount ? null : this.blackCount == this.whiteCount ? null :
this.opts.isLlotheo === this.blackCount > this.whiteCount ? WHITE : BLACK : this.opts.isLlotheo === this.blackCount > this.whiteCount ? WHITE : BLACK :
undefined as never; undefined as never;
} }
} }

View file

@ -161,7 +161,7 @@ export class ASEvaluator {
subtract: (a: number, b: number) => a - b, subtract: (a: number, b: number) => a - b,
multiply: (a: number, b: number) => a * b, multiply: (a: number, b: number) => a * b,
divide: (a: number, b: number) => a / b, divide: (a: number, b: number) => a / b,
remind: (a: number, b: number) => a % b, mod: (a: number, b: number) => a % b,
strLen: (a: string) => a.length, strLen: (a: string) => a.length,
strPick: (a: string, b: number) => a[b - 1], strPick: (a: string, b: number) => a[b - 1],
strReplace: (a: string, b: string, c: string) => a.split(b).join(c), strReplace: (a: string, b: string, c: string) => a.split(b).join(c),

View file

@ -58,7 +58,7 @@ export const funcDefs: Record<string, { in: any[]; out: any; category: string; i
subtract: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faMinus, }, subtract: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faMinus, },
multiply: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faTimes, }, multiply: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faTimes, },
divide: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, }, divide: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
remind: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, }, mod: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
eq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faEquals, }, eq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faEquals, },
notEq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faNotEqual, }, notEq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faNotEqual, },
gt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: faGreaterThan, }, gt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: faGreaterThan, },

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
export const twemojiBase = 'https://cdn.jsdelivr.net/npm/twemoji@11.3.0'; export const twemojiBase = 'https://cdn.jsdelivr.net/npm/twemoji@12.0.1';
// https://cdn.jsdelivr.net/npm/twemoji@11.3.0 // https://cdn.jsdelivr.net/npm/twemoji@12.0.1
// https://cdnjs.cloudflare.com/ajax/libs/twemoji/11.3.0 // https://cdnjs.cloudflare.com/ajax/libs/twemoji/12.0.1
// https://twemoji.maxcdn.com // https://twemoji.maxcdn.com

View file

@ -8,7 +8,7 @@ export type PackedMessagingMessage = SchemaType<typeof packedMessagingMessageSch
@EntityRepository(MessagingMessage) @EntityRepository(MessagingMessage)
export class MessagingMessageRepository extends Repository<MessagingMessage> { export class MessagingMessageRepository extends Repository<MessagingMessage> {
public isValidText(text: string): boolean { public validateText(text: string): boolean {
return text.trim().length <= 1000 && text.trim() != ''; return text.trim().length <= 1000 && text.trim() != '';
} }

View file

@ -1,3 +1,4 @@
import $ from 'cafy';
import { EntityRepository, Repository, In } from 'typeorm'; import { EntityRepository, Repository, In } from 'typeorm';
import { User, ILocalUser, IRemoteUser } from '../entities/user'; import { User, ILocalUser, IRemoteUser } from '../entities/user';
import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserGroupJoinings } from '..'; import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserGroupJoinings } from '..';
@ -231,29 +232,13 @@ export class UserRepository extends Repository<User> {
} }
//#region Validators //#region Validators
public validateUsername(username: string, remote = false): boolean { public validateLocalUsername = $.str.match(/^\w{1,20}$/);
return typeof username == 'string' && (remote ? /^\w([\w-]*\w)?$/ : /^\w{1,20}$/).test(username); public validateRemoteUsername = $.str.match(/^\w([\w-]*\w)?$/);
} public validatePassword = $.str.min(1);
public validateName = $.str.min(1).max(50);
public validatePassword(password: string): boolean { public validateDescription = $.str.min(1).max(500);
return typeof password == 'string' && password != ''; public validateLocation = $.str.min(1).max(50);
} public validateBirthday = $.str.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/);
public isValidName(name?: string): boolean {
return name === null || (typeof name == 'string' && name.length < 50 && name.trim() != '');
}
public isValidDescription(description: string): boolean {
return typeof description == 'string' && description.length < 500 && description.trim() != '';
}
public isValidLocation(location: string): boolean {
return typeof location == 'string' && location.length < 50 && location.trim() != '';
}
public isValidBirthday(birthday: string): boolean {
return typeof birthday == 'string' && /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.test(birthday);
}
//#endregion //#endregion
} }

View file

@ -53,12 +53,14 @@ function validatePerson(x: any, uri: string) {
return new Error('invalid person: inbox is not a string'); return new Error('invalid person: inbox is not a string');
} }
if (!Users.validateUsername(x.preferredUsername, true)) { if (!Users.validateRemoteUsername.ok(x.preferredUsername)) {
return new Error('invalid person: invalid username'); return new Error('invalid person: invalid username');
} }
if (!Users.isValidName(x.name == '' ? null : x.name)) { if (x.name != null && x.name != '') {
return new Error('invalid person: invalid name'); if (!Users.validateName.ok(x.name)) {
return new Error('invalid person: invalid name');
}
} }
if (typeof x.id !== 'string') { if (typeof x.id !== 'string') {

View file

@ -9,7 +9,7 @@ import config from '../../config';
import { ILocalUser } from '../../models/entities/user'; import { ILocalUser } from '../../models/entities/user';
import { publishApLogStream } from '../../services/stream'; import { publishApLogStream } from '../../services/stream';
import { apLogger } from './logger'; import { apLogger } from './logger';
import { UserKeypairs } from '../../models'; import { UserKeypairs, Instances } from '../../models';
import { fetchMeta } from '../../misc/fetch-meta'; import { fetchMeta } from '../../misc/fetch-meta';
import { toPuny } from '../../misc/convert-host'; import { toPuny } from '../../misc/convert-host';
import { ensure } from '../../prelude/ensure'; import { ensure } from '../../prelude/ensure';
@ -17,15 +17,30 @@ import { ensure } from '../../prelude/ensure';
export const logger = apLogger.createSubLogger('deliver'); export const logger = apLogger.createSubLogger('deliver');
export default async (user: ILocalUser, url: string, object: any) => { export default async (user: ILocalUser, url: string, object: any) => {
logger.info(`--> ${url}`);
const timeout = 10 * 1000; const timeout = 10 * 1000;
const { protocol, host, hostname, port, pathname, search } = new URL(url); const { protocol, host, hostname, port, pathname, search } = new URL(url);
// ブロックしてたら中断 // ブロックしてたら中断
const meta = await fetchMeta(); const meta = await fetchMeta();
if (meta.blockedHosts.includes(toPuny(host))) return; if (meta.blockedHosts.includes(toPuny(host))) {
logger.info(`skip (blocked) ${url}`);
return;
}
// closedなら中断
const closedHosts = await Instances.find({
where: {
isMarkedAsClosed: true
},
cache: 60 * 1000
});
if (closedHosts.map(x => x.host).includes(toPuny(host))) {
logger.info(`skip (closed) ${url}`);
return;
}
logger.info(`--> ${url}`);
const data = JSON.stringify(object); const data = JSON.stringify(object);

View file

@ -29,14 +29,14 @@ export const meta = {
params: { params: {
name: { name: {
validator: $.optional.nullable.str.pipe(Users.isValidName), validator: $.optional.nullable.use(Users.validateName),
desc: { desc: {
'ja-JP': '名前(ハンドルネームやニックネーム)' 'ja-JP': '名前(ハンドルネームやニックネーム)'
} }
}, },
description: { description: {
validator: $.optional.nullable.str.pipe(Users.isValidDescription), validator: $.optional.nullable.use(Users.validateDescription),
desc: { desc: {
'ja-JP': 'アカウントの説明や自己紹介' 'ja-JP': 'アカウントの説明や自己紹介'
} }
@ -50,14 +50,14 @@ export const meta = {
}, },
location: { location: {
validator: $.optional.nullable.str.pipe(Users.isValidLocation), validator: $.optional.nullable.use(Users.validateLocation),
desc: { desc: {
'ja-JP': '住んでいる地域、所在' 'ja-JP': '住んでいる地域、所在'
} }
}, },
birthday: { birthday: {
validator: $.optional.nullable.str.pipe(Users.isValidBirthday), validator: $.optional.nullable.use(Users.validateBirthday),
desc: { desc: {
'ja-JP': '誕生日 (YYYY-MM-DD形式)' 'ja-JP': '誕生日 (YYYY-MM-DD形式)'
} }

View file

@ -44,7 +44,7 @@ export const meta = {
}, },
text: { text: {
validator: $.optional.str.pipe(MessagingMessages.isValidText) validator: $.optional.str.pipe(MessagingMessages.validateText)
}, },
fileId: { fileId: {

View file

@ -9,7 +9,7 @@ export const meta = {
params: { params: {
username: { username: {
validator: $.str.pipe(Users.validateUsername) validator: $.use(Users.validateLocalUsername)
} }
} }
}; };

View file

@ -66,7 +66,7 @@ export const meta = {
}; };
export default define(meta, async (ps, me) => { export default define(meta, async (ps, me) => {
const isUsername = Users.validateUsername(ps.query.replace('@', ''), !ps.localOnly); const isUsername = ps.localOnly ? Users.validateLocalUsername.ok(ps.query.replace('@', '')) : Users.validateRemoteUsername.ok(ps.query.replace('@', ''));
let users: User[] = []; let users: User[] = [];

View file

@ -58,13 +58,13 @@ export default async (ctx: Koa.BaseContext) => {
} }
// Validate username // Validate username
if (!Users.validateUsername(username)) { if (!Users.validateLocalUsername.ok(username)) {
ctx.status = 400; ctx.status = 400;
return; return;
} }
// Validate password // Validate password
if (!Users.validatePassword(password)) { if (!Users.validatePassword.ok(password)) {
ctx.status = 400; ctx.status = 400;
return; return;
} }

View file

@ -17,6 +17,8 @@ export async function proxyMedia(ctx: Koa.BaseContext) {
const [type, ext] = await detectMine(path); const [type, ext] = await detectMine(path);
if (!type.startsWith('image/')) throw 403;
let image: IImage; let image: IImage;
if ('static' in ctx.query && ['image/png', 'image/gif'].includes(type)) { if ('static' in ctx.query && ['image/png', 'image/gif'].includes(type)) {

View file

@ -36,7 +36,7 @@ module.exports = async (ctx: Koa.BaseContext) => {
ctx.body = summary; ctx.body = summary;
} catch (e) { } catch (e) {
logger.error(`Failed to get preview of ${ctx.query.url}: ${e}`); logger.warn(`Failed to get preview of ${ctx.query.url}: ${e}`);
ctx.status = 200; ctx.status = 200;
ctx.set('Cache-Control', 'max-age=86400, immutable'); ctx.set('Cache-Control', 'max-age=86400, immutable');
ctx.body = '{}'; ctx.body = '{}';

View file

@ -149,18 +149,22 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
if (generateWeb) { if (generateWeb) {
logger.info(`creating web image`); logger.info(`creating web image`);
if (['image/jpeg'].includes(type)) { try {
webpublic = await convertToJpeg(path, 2048, 2048); if (['image/jpeg'].includes(type)) {
} else if (['image/webp'].includes(type)) { webpublic = await convertToJpeg(path, 2048, 2048);
webpublic = await convertToWebp(path, 2048, 2048); } else if (['image/webp'].includes(type)) {
} else if (['image/png'].includes(type)) { webpublic = await convertToWebp(path, 2048, 2048);
webpublic = await convertToPng(path, 2048, 2048); } else if (['image/png'].includes(type)) {
} else if (['image/apng', 'image/vnd.mozilla.apng'].includes(type)) { webpublic = await convertToPng(path, 2048, 2048);
webpublic = await convertToApng(path); } else if (['image/apng', 'image/vnd.mozilla.apng'].includes(type)) {
} else if (['image/gif'].includes(type)) { webpublic = await convertToApng(path);
webpublic = await convertToGif(path); } else if (['image/gif'].includes(type)) {
} else { webpublic = await convertToGif(path);
logger.info(`web image not created (not an image)`); } else {
logger.info(`web image not created (not an image)`);
}
} catch (e) {
logger.warn(`web image not created (an error occured)`, e);
} }
} else { } else {
logger.info(`web image not created (from remote)`); logger.info(`web image not created (from remote)`);
@ -170,18 +174,22 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
// #region thumbnail // #region thumbnail
let thumbnail: IImage | null = null; let thumbnail: IImage | null = null;
if (['image/jpeg', 'image/webp'].includes(type)) { try {
thumbnail = await convertToJpeg(path, 498, 280); if (['image/jpeg', 'image/webp'].includes(type)) {
} else if (['image/png'].includes(type)) { thumbnail = await convertToJpeg(path, 498, 280);
thumbnail = await convertToPng(path, 498, 280); } else if (['image/png'].includes(type)) {
} else if (['image/gif'].includes(type)) { thumbnail = await convertToPng(path, 498, 280);
thumbnail = await convertToGif(path); } else if (['image/gif'].includes(type)) {
} else if (type.startsWith('video/')) { thumbnail = await convertToGif(path);
try { } else if (type.startsWith('video/')) {
thumbnail = await GenerateVideoThumbnail(path); try {
} catch (e) { thumbnail = await GenerateVideoThumbnail(path);
logger.error(`GenerateVideoThumbnail failed: ${e}`); } catch (e) {
logger.error(`GenerateVideoThumbnail failed: ${e}`);
}
} }
} catch (e) {
logger.warn(`thumbnail not created (an error occured)`, e);
} }
// #endregion thumbnail // #endregion thumbnail

View file

@ -90,7 +90,7 @@ export default class Logger {
} }
} }
public warn(message: string, data?: Record<string, any> | null, important = false): void { // 実行を継続できるが改善すべき状況で使う public warn(message: string, data?: Record<string, any> | null, important = false): void { // 実行を継続できるが改善すべき状況で使う
this.log('warning', message, data, important); this.log('warning', message, data, important);
} }