diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 8165654fc..f29f2195d 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -58,7 +58,7 @@ common: friday: "金曜日" saturday: "土曜日" reactions: - like: "ええやん" + like: "いいね" love: "しゅき" laugh: "笑" hmm: "ふぅ~む" @@ -84,6 +84,7 @@ common: my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" i-like-sushi: "私は(プリンよりむしろ)寿司が好き" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" + use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" verified-user: "公式アカウント" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" reversi: @@ -754,6 +755,7 @@ desktop/views/components/ui.header.account.vue: lists: "リスト" follow-requests: "フォロー申請" customize: "ホームのカスタマイズ" + admin: "管理" settings: "設定" signout: "サインアウト" dark: "闇に飲まれる" @@ -818,18 +820,24 @@ desktop/views/pages/admin/admin.unverify-user.vue: unverify-user: "ユーザーの公式アカウント解除" unverify: "公式アカウントを解除する" unverified: "公式アカウントを解除しました" -desktop/views/pages/admin/admin.notes-chart.vue: - title: "投稿" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.users-chart.vue: - title: "ユーザー" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.drive-chart.vue: - title: "ドライブ" - local: "ローカル" - remote: "リモート" +desktop/views/pages/admin/admin.chart.vue: + title: "チャート" + per-day: "1日ごと" + per-hour: "1時間ごと" + notes: "投稿" + users: "ユーザー" + drive: "ドライブ" + charts: + notes: "投稿の増減 (統合)" + local-notes: "投稿の増減 (ローカル)" + remote-notes: "投稿の増減 (リモート)" + notes-total: "投稿の累計" + users: "ユーザーの増減" + users-total: "ユーザーの累計" + drive: "ドライブ使用量の増減" + drive-total: "ドライブ使用量の累計" + drive-files: "ドライブのファイル数の増減" + drive-files-total: "ドライブのファイル数の累計" desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "メディア投稿のみ" is-media-view: "メディアビュー" @@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue: game: "ゲーム" darkmode: "ダークモード" settings: "設定" + admin: "管理" about: "Misskeyについて" mobile/views/components/user-timeline.vue: no-notes: "このユーザーは投稿していないようです。" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index de656dfb0..94fcb2483 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -58,7 +58,7 @@ common: friday: "金曜日" saturday: "土曜日" reactions: - like: "ええやん" + like: "いいね" love: "Lieben" laugh: "Lachen" hmm: "Hmm...?" @@ -84,6 +84,7 @@ common: my-token-regenerated: "Dein Token wurde generiert. Du wirst jetzt abgemeldet." i-like-sushi: "私は(プリンよりむしろ)寿司が好き" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" + use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" verified-user: "公式アカウント" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" reversi: @@ -754,6 +755,7 @@ desktop/views/components/ui.header.account.vue: lists: "Listen" follow-requests: "フォロー申請" customize: "ホームのカスタマイズ" + admin: "管理" settings: "Einstellungen" signout: "Ausloggen" dark: "Verdunkeln" @@ -818,18 +820,24 @@ desktop/views/pages/admin/admin.unverify-user.vue: unverify-user: "ユーザーの公式アカウント解除" unverify: "公式アカウントを解除する" unverified: "公式アカウントを解除しました" -desktop/views/pages/admin/admin.notes-chart.vue: - title: "投稿" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.users-chart.vue: - title: "ユーザー" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.drive-chart.vue: - title: "ドライブ" - local: "ローカル" - remote: "リモート" +desktop/views/pages/admin/admin.chart.vue: + title: "チャート" + per-day: "1日ごと" + per-hour: "1時間ごと" + notes: "投稿" + users: "ユーザー" + drive: "ドライブ" + charts: + notes: "投稿の増減 (統合)" + local-notes: "投稿の増減 (ローカル)" + remote-notes: "投稿の増減 (リモート)" + notes-total: "投稿の累計" + users: "ユーザーの増減" + users-total: "ユーザーの累計" + drive: "ドライブ使用量の増減" + drive-total: "ドライブ使用量の累計" + drive-files: "ドライブのファイル数の増減" + drive-files-total: "ドライブのファイル数の累計" desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "メディア投稿のみ" is-media-view: "メディアビュー" @@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue: game: "ゲーム" darkmode: "ダークモード" settings: "設定" + admin: "管理" about: "Misskeyについて" mobile/views/components/user-timeline.vue: no-notes: "このユーザーは投稿していないようです。" diff --git a/locales/en-US.yml b/locales/en-US.yml index b65a03bfa..1a9a7325d 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -84,6 +84,7 @@ common: my-token-regenerated: "Your token has been regenerated, so you will be signed out." i-like-sushi: "I prefer sushi rather than pudding" show-reversi-board-labels: "Show row and column labels in Reversi" + use-contrast-reversi-stones: "Make the stone color clear" verified-user: "Verified account" disable-animated-mfm: "Disable animated texts in a post" reversi: @@ -754,6 +755,7 @@ desktop/views/components/ui.header.account.vue: lists: "Lists" follow-requests: "Follow requests" customize: "Customize home layout" + admin: "Admin" settings: "Settings" signout: "Sign out" dark: "Submerge in dark" @@ -818,18 +820,24 @@ desktop/views/pages/admin/admin.unverify-user.vue: unverify-user: "User account unverification settings" unverify: "Unverify account" unverified: "The account is now being unverified" -desktop/views/pages/admin/admin.notes-chart.vue: - title: "Posts" - local: "Local" - remote: "Remote" -desktop/views/pages/admin/admin.users-chart.vue: - title: "Users" - local: "Local" - remote: "Remote" -desktop/views/pages/admin/admin.drive-chart.vue: - title: "Drive" - local: "Local" - remote: "Remote" +desktop/views/pages/admin/admin.chart.vue: + title: "Chart" + per-day: "per Day" + per-hour: "per Hour" + notes: "Posts" + users: "Users" + drive: "Media storage" + charts: + notes: "The number of posts: increase/decrease (All)" + local-notes: "The number of posts: increase/decrease (Local)" + remote-notes: "The number of posts: increase/decrease (Global)" + notes-total: "The number of posts: cumulative total" + users: "The number of users: increase/decrease" + users-total: "The number of users: cumulative total" + drive: "Capacity used as the storage: increase/decrease" + drive-total: "Capacity used as the storage: cumulative total" + drive-files: "The number of files on the storage: increase/decrease" + drive-files-total: "The number of files on the storage: cumulative total" desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "Only media posts" is-media-view: "Media view" @@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue: game: "Games" darkmode: "Dark theme" settings: "Settings" + admin: "Admin" about: "About Misskey" mobile/views/components/user-timeline.vue: no-notes: "It seems this user hasn't posted anything yet." diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 599e05b7c..38ed898cd 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -58,7 +58,7 @@ common: friday: "Viernes" saturday: "Sábado" reactions: - like: "ええやん" + like: "いいね" love: "amor" laugh: "risa" hmm: "hmm" @@ -84,6 +84,7 @@ common: my-token-regenerated: "Tu token se ha regenerado vas a ser desconectado." i-like-sushi: "Prefiero sushi a pudín" show-reversi-board-labels: "Mostrar etiquetas de filas y columnas en Reversi" + use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" verified-user: "公式アカウント" disable-animated-mfm: "Desactivar texto animado en una publicación" reversi: @@ -754,6 +755,7 @@ desktop/views/components/ui.header.account.vue: lists: "リスト" follow-requests: "フォロー申請" customize: "ホームのカスタマイズ" + admin: "管理" settings: "設定" signout: "サインアウト" dark: "闇に飲まれる" @@ -818,18 +820,24 @@ desktop/views/pages/admin/admin.unverify-user.vue: unverify-user: "ユーザーの公式アカウント解除" unverify: "公式アカウントを解除する" unverified: "公式アカウントを解除しました" -desktop/views/pages/admin/admin.notes-chart.vue: - title: "投稿" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.users-chart.vue: - title: "ユーザー" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.drive-chart.vue: - title: "ドライブ" - local: "ローカル" - remote: "リモート" +desktop/views/pages/admin/admin.chart.vue: + title: "チャート" + per-day: "1日ごと" + per-hour: "1時間ごと" + notes: "投稿" + users: "ユーザー" + drive: "ドライブ" + charts: + notes: "投稿の増減 (統合)" + local-notes: "投稿の増減 (ローカル)" + remote-notes: "投稿の増減 (リモート)" + notes-total: "投稿の累計" + users: "ユーザーの増減" + users-total: "ユーザーの累計" + drive: "ドライブ使用量の増減" + drive-total: "ドライブ使用量の累計" + drive-files: "ドライブのファイル数の増減" + drive-files-total: "ドライブのファイル数の累計" desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "メディア投稿のみ" is-media-view: "メディアビュー" @@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue: game: "ゲーム" darkmode: "ダークモード" settings: "設定" + admin: "管理" about: "Misskeyについて" mobile/views/components/user-timeline.vue: no-notes: "このユーザーは投稿していないようです。" diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 9e979700d..4e7ff713a 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -58,10 +58,10 @@ common: friday: "Vendredi" saturday: "Samedi" reactions: - like: "ええやん" + like: "J'aime" love: "Adore" laugh: "Rire" - hmm: "Hmm ... ?" + hmm: "Hmm … ?" surprise: "Wow" congrats: "Félicitations !" angry: "En colère" @@ -69,10 +69,10 @@ common: rip: "RIP" pudding: "Pudding" note-placeholders: - a: "Que faites vous maintenant ?" + a: "Que faites-vous maintenant ?" b: "Quoi de neuf ?" c: "Qu'avez-vous en tête ?" - d: "Voulez-vous exprimer quelque chose ?" + d: "Désirez-vous publier quelques mots ?" e: "Écrivez ici" f: "En attente de vos écrits" search: "Recherche" @@ -84,6 +84,7 @@ common: my-token-regenerated: "Votre token vient d'être généré, vous allez maintenant être déconnecté." i-like-sushi: "Je préfère les sushis plutôt que le pudding" show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi" + use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" verified-user: "Compte vérifié" disable-animated-mfm: "Désactiver les textes animés dans les publications" reversi: @@ -230,7 +231,7 @@ common/views/components/connect-failed.troubleshooter.vue: flush: "Vider le cache" set-version: "Choisissez une version" common/views/components/messaging.vue: - search-user: "Trouver un·e utilisateur·rice" + search-user: "Trouver un·e utilisateur·trice" you: "Vous" no-history: "Pas d'historique" common/views/components/messaging-room.vue: @@ -378,7 +379,7 @@ common/views/widgets/tips.vue: tips-line3: "Vous pouvez glisser et déposer des fichiers sur la fenêtre de la note" tips-line4: "Vous pouvez coller des images à partir du presse-papier sur la fenêtre de la note" tips-line5: "Vous pouvez téléverser des fichiers sur le Drive en faisant un glisser-déposer" - tips-line6: "ドライブでファイルをドラッグしてフォルダ移動できます" + tips-line6: "Vous pouvez déplacer un dossier en le glissant dans le Drive" tips-line7: "ドライブでフォルダをドラッグしてフォルダ移動できます" tips-line8: "Vous pouvez personnaliser l'Accueil via les paramètres" tips-line9: "Misskey est sous licence AGPLv3" @@ -512,7 +513,7 @@ desktop/views/components/following.vue: empty: "Vous ne suivez aucun compte." desktop/views/components/friends-maker.vue: title: "Utilisateurs recommandés :" - empty: "Impossible de trouver des utilisateurs à recommander." + empty: "Impossible de trouver des utilisateurs·trices à recommander." fetching: "Chargement" refresh: "Plus" close: "Fermer" @@ -629,7 +630,7 @@ desktop/views/components/settings.vue: circle-icons: "Utiliser des icônes circulaires" gradient-window-header: "Utiliser les dégradés sur la barre de titre de la fenêtre" post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" - suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" + suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie" show-reply-target: "Afficher les réponses" show-my-renotes: "Afficher mes republications dans le fil" show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" @@ -754,6 +755,7 @@ desktop/views/components/ui.header.account.vue: lists: "Listes" follow-requests: "Demandes de suivi" customize: "Personnaliser l'Accueil" + admin: "Admin" settings: "Réglages" signout: "Déconnexion" dark: "Fall in dark" @@ -791,12 +793,12 @@ desktop/views/components/window.vue: popout: "ポップアウト" close: "Fermer" desktop/views/pages/admin/admin.vue: - dashboard: "ダッシュボード" + dashboard: "Tableau de bord" drive: "Drive" users: "Utilisateur·rice·s" update: "Mises à jour" desktop/views/pages/admin/admin.dashboard.vue: - dashboard: "ダッシュボード" + dashboard: "Tableau de bord" all-users: "Tou·te·s les utilisateur·rice·s" original-users: "Utilisateur·rice·s sur cette instance" all-notes: "Toutes les publications" @@ -811,25 +813,31 @@ desktop/views/pages/admin/admin.unsuspend-user.vue: unsuspend: "Suspension levée" unsuspended: "La suspension de l’utilisateur·rice a été levée avec succès" desktop/views/pages/admin/admin.verify-user.vue: - verify-user: "ユーザーの公式アカウント設定" + verify-user: "Paramètres de vérification du compte utilisateur" verify: "Vérification du compte" verified: "Le compte a été vérifié" desktop/views/pages/admin/admin.unverify-user.vue: unverify-user: "ユーザーの公式アカウント解除" - unverify: "公式アカウントを解除する" + unverify: "Ôter la vérification du compte" unverified: "公式アカウントを解除しました" -desktop/views/pages/admin/admin.notes-chart.vue: - title: "投稿" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.users-chart.vue: - title: "ユーザー" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.drive-chart.vue: - title: "ドライブ" - local: "ローカル" - remote: "リモート" +desktop/views/pages/admin/admin.chart.vue: + title: "Graphs" + per-day: "par jour" + per-hour: "par heure" + notes: "Notes" + users: "Utilisateurs·trices" + drive: "Drive" + charts: + notes: "投稿の増減 (統合)" + local-notes: "投稿の増減 (ローカル)" + remote-notes: "投稿の増減 (リモート)" + notes-total: "Total des notes" + users: "ユーザーの増減" + users-total: "Nombre total d’utilisateurs·trices" + drive: "ドライブ使用量の増減" + drive-total: "ドライブ使用量の累計" + drive-files: "ドライブのファイル数の増減" + drive-files-total: "ドライブのファイル数の累計" desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "Les publications médias uniquement" is-media-view: "Vue média" @@ -977,7 +985,7 @@ mobile/views/components/follow-button.vue: follow-request: "Demande d'abonnement" mobile/views/components/friends-maker.vue: title: "Abonnez-vous aux utilisateurs" - empty: "Impossible de trouver des utilisateurs à recommander." + empty: "Impossible de trouver des utilisateurs·trices à recommander." fetching: "Chargement" refresh: "Voir plus" close: "Fermer" @@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue: game: "Jeux" darkmode: "Mode nuit" settings: "Réglages" + admin: "管理" about: "À propose de Misskey" mobile/views/components/user-timeline.vue: no-notes: "Cette utilisateur semble n'avoir rien poster pour le moment" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 8165654fc..f29f2195d 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -58,7 +58,7 @@ common: friday: "金曜日" saturday: "土曜日" reactions: - like: "ええやん" + like: "いいね" love: "しゅき" laugh: "笑" hmm: "ふぅ~む" @@ -84,6 +84,7 @@ common: my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" i-like-sushi: "私は(プリンよりむしろ)寿司が好き" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" + use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" verified-user: "公式アカウント" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" reversi: @@ -754,6 +755,7 @@ desktop/views/components/ui.header.account.vue: lists: "リスト" follow-requests: "フォロー申請" customize: "ホームのカスタマイズ" + admin: "管理" settings: "設定" signout: "サインアウト" dark: "闇に飲まれる" @@ -818,18 +820,24 @@ desktop/views/pages/admin/admin.unverify-user.vue: unverify-user: "ユーザーの公式アカウント解除" unverify: "公式アカウントを解除する" unverified: "公式アカウントを解除しました" -desktop/views/pages/admin/admin.notes-chart.vue: - title: "投稿" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.users-chart.vue: - title: "ユーザー" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.drive-chart.vue: - title: "ドライブ" - local: "ローカル" - remote: "リモート" +desktop/views/pages/admin/admin.chart.vue: + title: "チャート" + per-day: "1日ごと" + per-hour: "1時間ごと" + notes: "投稿" + users: "ユーザー" + drive: "ドライブ" + charts: + notes: "投稿の増減 (統合)" + local-notes: "投稿の増減 (ローカル)" + remote-notes: "投稿の増減 (リモート)" + notes-total: "投稿の累計" + users: "ユーザーの増減" + users-total: "ユーザーの累計" + drive: "ドライブ使用量の増減" + drive-total: "ドライブ使用量の累計" + drive-files: "ドライブのファイル数の増減" + drive-files-total: "ドライブのファイル数の累計" desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "メディア投稿のみ" is-media-view: "メディアビュー" @@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue: game: "ゲーム" darkmode: "ダークモード" settings: "設定" + admin: "管理" about: "Misskeyについて" mobile/views/components/user-timeline.vue: no-notes: "このユーザーは投稿していないようです。" diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index 85da28c99..845217ef5 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -84,6 +84,7 @@ common: my-token-regenerated: "あんさんのトークンが更新されたらしいわ。すまんがとりあえずサインアウトすんで。" i-like-sushi: "寿司(のほうがプリンよりむしろ)ウマい、タコ焼きはあらへんけど。" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示や!" + use-contrast-reversi-stones: "リバーシのアイコンにコントラストをつけんで!" verified-user: "アメちゃん付きアカウント" disable-animated-mfm: "投稿内のちょろちょろ動いてんのを止める" reversi: @@ -190,17 +191,17 @@ common/views/components/games/reversi/reversi.index.vue: common/views/components/games/reversi/reversi.room.vue: settings-of-the-game: "ゲームの設定" choose-map: "マップを選択" - random: "ランダム" + random: "いんじゃんほい" black-or-white: "先手/後手" - black-is: "{}が黒" + black-is: "{}が黒や" rules: "ルール" - is-llotheo: "石の少ない方が勝ち(ロセオ)" + is-llotheo: "石の少ない方が勝ちや!(ロセオ)" looped-map: "ループマップ" - can-put-everywhere: "どこでも置けるモード" + can-put-everywhere: "どこに置いてもええモード" settings-of-the-bot: "Botの設定" - this-game-is-started-soon: "ゲームは数秒後に開始されます" - waiting-for-other: "相手の準備が完了するのを待っています" - waiting-for-me: "あなたの準備が完了するのを待っています" + this-game-is-started-soon: "ゲームは数秒後に開始されんで" + waiting-for-other: "相手の準備が完了すんのを待ってんで" + waiting-for-me: "あんさんの準備が完了すんのを待ってんで" waiting-for-both: "準備中" cancel: "やめとくわ" ready: "準備完了" @@ -754,6 +755,7 @@ desktop/views/components/ui.header.account.vue: lists: "リスト" follow-requests: "フォロー申請" customize: "ホームのカスタマイズ" + admin: "管理" settings: "設定" signout: "サインアウト" dark: "闇に飲まれる" @@ -818,18 +820,24 @@ desktop/views/pages/admin/admin.unverify-user.vue: unverify-user: "ユーザーの公式アカウント解除" unverify: "公式アカウントを解除する" unverified: "公式アカウントを解除しました" -desktop/views/pages/admin/admin.notes-chart.vue: - title: "投稿" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.users-chart.vue: - title: "ユーザー" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.drive-chart.vue: - title: "ドライブ" - local: "ローカル" - remote: "リモート" +desktop/views/pages/admin/admin.chart.vue: + title: "チャート" + per-day: "1日ごと" + per-hour: "1時間ごと" + notes: "投稿" + users: "ユーザー" + drive: "ドライブ" + charts: + notes: "投稿の増減 (統合)" + local-notes: "投稿の増減 (ローカル)" + remote-notes: "投稿の増減 (リモート)" + notes-total: "投稿の累計" + users: "ユーザーの増減" + users-total: "ユーザーの累計" + drive: "ドライブ使用量の増減" + drive-total: "ドライブ使用量の累計" + drive-files: "ドライブのファイル数の増減" + drive-files-total: "ドライブのファイル数の累計" desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "メディア投稿のみ" is-media-view: "メディアビュー" @@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue: game: "ゲーム" darkmode: "ダークモード" settings: "設定" + admin: "管理" about: "Misskeyについて" mobile/views/components/user-timeline.vue: no-notes: "このユーザーは投稿していないようです。" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index b00d268c9..e33bf3e4f 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -58,7 +58,7 @@ common: friday: "금요일" saturday: "토요일" reactions: - like: "ええやん" + like: "いいね" love: "좋아" laugh: "크크" hmm: "음..." @@ -84,6 +84,7 @@ common: my-token-regenerated: "당신의 토큰이 업데이트되어 있기 때문에 로그 아웃합니다." i-like-sushi: "나는(푸딩보다 오히려)스시가 좋아" show-reversi-board-labels: "리버시 보드의 행과 열 레이블을 표시" + use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" verified-user: "公式アカウント" disable-animated-mfm: "게시물의 문자 애니메이션을 비활성화 할" reversi: @@ -754,6 +755,7 @@ desktop/views/components/ui.header.account.vue: lists: "リスト" follow-requests: "フォロー申請" customize: "ホームのカスタマイズ" + admin: "管理" settings: "設定" signout: "サインアウト" dark: "闇に飲まれる" @@ -818,18 +820,24 @@ desktop/views/pages/admin/admin.unverify-user.vue: unverify-user: "ユーザーの公式アカウント解除" unverify: "公式アカウントを解除する" unverified: "公式アカウントを解除しました" -desktop/views/pages/admin/admin.notes-chart.vue: - title: "投稿" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.users-chart.vue: - title: "ユーザー" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.drive-chart.vue: - title: "ドライブ" - local: "ローカル" - remote: "リモート" +desktop/views/pages/admin/admin.chart.vue: + title: "チャート" + per-day: "1日ごと" + per-hour: "1時間ごと" + notes: "投稿" + users: "ユーザー" + drive: "ドライブ" + charts: + notes: "投稿の増減 (統合)" + local-notes: "投稿の増減 (ローカル)" + remote-notes: "投稿の増減 (リモート)" + notes-total: "投稿の累計" + users: "ユーザーの増減" + users-total: "ユーザーの累計" + drive: "ドライブ使用量の増減" + drive-total: "ドライブ使用量の累計" + drive-files: "ドライブのファイル数の増減" + drive-files-total: "ドライブのファイル数の累計" desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "メディア投稿のみ" is-media-view: "メディアビュー" @@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue: game: "ゲーム" darkmode: "ダークモード" settings: "設定" + admin: "管理" about: "Misskeyについて" mobile/views/components/user-timeline.vue: no-notes: "このユーザーは投稿していないようです。" diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index c620c4bbd..6ba495802 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -58,7 +58,7 @@ common: friday: "Piątek" saturday: "Sobota" reactions: - like: "ええやん" + like: "いいね" love: "Kocham" laugh: "Śmieszne" hmm: "Hmm…?" @@ -84,6 +84,7 @@ common: my-token-regenerated: "Twój token został wygenerowany. Zostaniesz wylogowany." i-like-sushi: "Wolę sushi od puddingu" show-reversi-board-labels: "Pokazuj podpisy wierszy i kolumn w Reversi" + use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" verified-user: "公式アカウント" disable-animated-mfm: "Wyłącz animowany tekst we wpisach" reversi: @@ -754,6 +755,7 @@ desktop/views/components/ui.header.account.vue: lists: "Listy" follow-requests: "Prośby o śledzenie" customize: "Dostosuj stronę główną" + admin: "管理" settings: "Ustawienia" signout: "Wyloguj się" dark: "Sprowadź ciemność" @@ -818,18 +820,24 @@ desktop/views/pages/admin/admin.unverify-user.vue: unverify-user: "ユーザーの公式アカウント解除" unverify: "公式アカウントを解除する" unverified: "公式アカウントを解除しました" -desktop/views/pages/admin/admin.notes-chart.vue: - title: "投稿" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.users-chart.vue: - title: "ユーザー" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.drive-chart.vue: - title: "ドライブ" - local: "ローカル" - remote: "リモート" +desktop/views/pages/admin/admin.chart.vue: + title: "チャート" + per-day: "1日ごと" + per-hour: "1時間ごと" + notes: "投稿" + users: "ユーザー" + drive: "ドライブ" + charts: + notes: "投稿の増減 (統合)" + local-notes: "投稿の増減 (ローカル)" + remote-notes: "投稿の増減 (リモート)" + notes-total: "投稿の累計" + users: "ユーザーの増減" + users-total: "ユーザーの累計" + drive: "ドライブ使用量の増減" + drive-total: "ドライブ使用量の累計" + drive-files: "ドライブのファイル数の増減" + drive-files-total: "ドライブのファイル数の累計" desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "Tylko wpisy z zawartością multimedialną" is-media-view: "Widok multimediów" @@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue: game: "Gry" darkmode: "Tryb ciemny" settings: "Ustawienia" + admin: "管理" about: "O Misskey" mobile/views/components/user-timeline.vue: no-notes: "Wygląda na to, że ten użytkownik nie opublikował jeszcze niczego" diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml index 029016a59..758c82a05 100644 --- a/locales/pt-PT.yml +++ b/locales/pt-PT.yml @@ -58,7 +58,7 @@ common: friday: "sexta" saturday: "sábado" reactions: - like: "Legal..." + like: "いいね" love: "Amei" laugh: "Riso" hmm: "Hmm...?" @@ -84,6 +84,7 @@ common: my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" i-like-sushi: "Eu prefiro sushi a pudim" show-reversi-board-labels: "Mostrar etiquetas de colunas e linhas no Reversi" + use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" verified-user: "Conta verificada" disable-animated-mfm: "Desativar texto animado nas publicações" reversi: @@ -754,6 +755,7 @@ desktop/views/components/ui.header.account.vue: lists: "リスト" follow-requests: "フォロー申請" customize: "ホームのカスタマイズ" + admin: "管理" settings: "設定" signout: "サインアウト" dark: "闇に飲まれる" @@ -818,18 +820,24 @@ desktop/views/pages/admin/admin.unverify-user.vue: unverify-user: "ユーザーの公式アカウント解除" unverify: "公式アカウントを解除する" unverified: "公式アカウントを解除しました" -desktop/views/pages/admin/admin.notes-chart.vue: - title: "投稿" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.users-chart.vue: - title: "ユーザー" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.drive-chart.vue: - title: "ドライブ" - local: "ローカル" - remote: "リモート" +desktop/views/pages/admin/admin.chart.vue: + title: "チャート" + per-day: "1日ごと" + per-hour: "1時間ごと" + notes: "投稿" + users: "ユーザー" + drive: "ドライブ" + charts: + notes: "投稿の増減 (統合)" + local-notes: "投稿の増減 (ローカル)" + remote-notes: "投稿の増減 (リモート)" + notes-total: "投稿の累計" + users: "ユーザーの増減" + users-total: "ユーザーの累計" + drive: "ドライブ使用量の増減" + drive-total: "ドライブ使用量の累計" + drive-files: "ドライブのファイル数の増減" + drive-files-total: "ドライブのファイル数の累計" desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "メディア投稿のみ" is-media-view: "メディアビュー" @@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue: game: "ゲーム" darkmode: "ダークモード" settings: "設定" + admin: "管理" about: "Misskeyについて" mobile/views/components/user-timeline.vue: no-notes: "このユーザーは投稿していないようです。" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index 9eef17f79..8e26329a7 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -58,7 +58,7 @@ common: friday: "金曜日" saturday: "土曜日" reactions: - like: "ええやん" + like: "いいね" love: "しゅき" laugh: "笑" hmm: "ふぅ~む" @@ -84,6 +84,7 @@ common: my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" i-like-sushi: "私は(プリンよりむしろ)寿司が好き" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" + use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" verified-user: "公式アカウント" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" reversi: @@ -754,6 +755,7 @@ desktop/views/components/ui.header.account.vue: lists: "リスト" follow-requests: "フォロー申請" customize: "ホームのカスタマイズ" + admin: "管理" settings: "設定" signout: "サインアウト" dark: "闇に飲まれる" @@ -818,18 +820,24 @@ desktop/views/pages/admin/admin.unverify-user.vue: unverify-user: "ユーザーの公式アカウント解除" unverify: "公式アカウントを解除する" unverified: "公式アカウントを解除しました" -desktop/views/pages/admin/admin.notes-chart.vue: - title: "投稿" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.users-chart.vue: - title: "ユーザー" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.drive-chart.vue: - title: "ドライブ" - local: "ローカル" - remote: "リモート" +desktop/views/pages/admin/admin.chart.vue: + title: "チャート" + per-day: "1日ごと" + per-hour: "1時間ごと" + notes: "投稿" + users: "ユーザー" + drive: "ドライブ" + charts: + notes: "投稿の増減 (統合)" + local-notes: "投稿の増減 (ローカル)" + remote-notes: "投稿の増減 (リモート)" + notes-total: "投稿の累計" + users: "ユーザーの増減" + users-total: "ユーザーの累計" + drive: "ドライブ使用量の増減" + drive-total: "ドライブ使用量の累計" + drive-files: "ドライブのファイル数の増減" + drive-files-total: "ドライブのファイル数の累計" desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "メディア投稿のみ" is-media-view: "メディアビュー" @@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue: game: "ゲーム" darkmode: "ダークモード" settings: "設定" + admin: "管理" about: "Misskeyについて" mobile/views/components/user-timeline.vue: no-notes: "このユーザーは投稿していないようです。" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 8ce97a5b4..c807102d9 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -58,7 +58,7 @@ common: friday: "金曜日" saturday: "土曜日" reactions: - like: "ええやん" + like: "いいね" love: "しゅき" laugh: "笑" hmm: "ふぅ~む" @@ -84,6 +84,7 @@ common: my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" i-like-sushi: "私は(プリンよりむしろ)寿司が好き" show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" + use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" verified-user: "公式アカウント" disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" reversi: @@ -754,6 +755,7 @@ desktop/views/components/ui.header.account.vue: lists: "リスト" follow-requests: "フォロー申請" customize: "ホームのカスタマイズ" + admin: "管理" settings: "設定" signout: "サインアウト" dark: "闇に飲まれる" @@ -818,18 +820,24 @@ desktop/views/pages/admin/admin.unverify-user.vue: unverify-user: "ユーザーの公式アカウント解除" unverify: "公式アカウントを解除する" unverified: "公式アカウントを解除しました" -desktop/views/pages/admin/admin.notes-chart.vue: - title: "投稿" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.users-chart.vue: - title: "ユーザー" - local: "ローカル" - remote: "リモート" -desktop/views/pages/admin/admin.drive-chart.vue: - title: "ドライブ" - local: "ローカル" - remote: "リモート" +desktop/views/pages/admin/admin.chart.vue: + title: "チャート" + per-day: "1日ごと" + per-hour: "1時間ごと" + notes: "投稿" + users: "ユーザー" + drive: "ドライブ" + charts: + notes: "投稿の増減 (統合)" + local-notes: "投稿の増減 (ローカル)" + remote-notes: "投稿の増減 (リモート)" + notes-total: "投稿の累計" + users: "ユーザーの増減" + users-total: "ユーザーの累計" + drive: "ドライブ使用量の増減" + drive-total: "ドライブ使用量の累計" + drive-files: "ドライブのファイル数の増減" + drive-files-total: "ドライブのファイル数の累計" desktop/views/pages/deck/deck.tl-column.vue: is-media-only: "メディア投稿のみ" is-media-view: "メディアビュー" @@ -1044,6 +1052,7 @@ mobile/views/components/ui.nav.vue: game: "ゲーム" darkmode: "ダークモード" settings: "設定" + admin: "管理" about: "Misskeyについて" mobile/views/components/user-timeline.vue: no-notes: "このユーザーは投稿していないようです。" diff --git a/package.json b/package.json index f859120de..32cafda27 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "misskey", "author": "syuilo ", - "version": "8.8.0", - "clientVersion": "1.0.8842", + "version": "8.9.0", + "clientVersion": "1.0.8950", "codename": "nighthike", "main": "./built/index.js", "private": true, @@ -60,7 +60,7 @@ "@types/mocha": "5.2.3", "@types/mongodb": "3.1.4", "@types/ms": "0.7.30", - "@types/node": "10.7.1", + "@types/node": "10.9.1", "@types/portscanner": "2.1.0", "@types/pug": "2.0.4", "@types/qrcode": "1.2.0", @@ -70,14 +70,14 @@ "@types/request-promise-native": "1.0.15", "@types/rimraf": "2.0.2", "@types/seedrandom": "2.4.27", - "@types/sharp": "0.17.9", + "@types/sharp": "0.17.10", "@types/showdown": "1.7.5", "@types/single-line-log": "1.1.0", "@types/speakeasy": "2.0.2", "@types/systeminformation": "3.23.0", "@types/tmp": "0.0.33", "@types/uuid": "3.4.3", - "@types/webpack": "4.4.10", + "@types/webpack": "4.4.11", "@types/webpack-stream": "3.2.10", "@types/websocket": "0.0.39", "@types/ws": "6.0.0", @@ -210,7 +210,7 @@ "vue": "2.5.17", "vue-chartjs": "3.4.0", "vue-cropperjs": "2.2.1", - "vue-js-modal": "1.3.18", + "vue-js-modal": "1.3.19", "vue-json-tree-view": "2.1.4", "vue-loader": "15.4.0", "vue-router": "3.0.1", diff --git a/src/client/app/desktop/script.ts b/src/client/app/desktop/script.ts index 8dc048219..7f4a2d0b0 100644 --- a/src/client/app/desktop/script.ts +++ b/src/client/app/desktop/script.ts @@ -94,7 +94,7 @@ init(async (launch) => { /** * Init Notification */ - if ('Notification' in window) { + if ('Notification' in window && os.store.getters.isSignedIn) { // 許可を得ていなかったらリクエスト if ((Notification as any).permission == 'default') { await Notification.requestPermission(); diff --git a/src/client/app/desktop/views/pages/admin/admin.chart.vue b/src/client/app/desktop/views/pages/admin/admin.chart.vue index 89e61d4c7..4310ce03d 100644 --- a/src/client/app/desktop/views/pages/admin/admin.chart.vue +++ b/src/client/app/desktop/views/pages/admin/admin.chart.vue @@ -55,10 +55,10 @@ export default Vue.extend({ case 'local-notes': return this.notesChart('local'); case 'remote-notes': return this.notesChart('remote'); case 'notes-total': return this.notesTotalChart(); - case 'drive': return this.driveChart(false); - case 'drive-total': return this.driveChart(true); - case 'drive-files': return this.driveFilesChart(false); - case 'drive-files-total': return this.driveFilesChart(true); + case 'drive': return this.driveChart(); + case 'drive-total': return this.driveTotalChart(); + case 'drive-files': return this.driveFilesChart(); + case 'drive-files-total': return this.driveFilesTotalChart(); } }, stats(): any[] { @@ -81,7 +81,7 @@ export default Vue.extend({ normal: type == 'local' ? x.notes.local.diffs.normal : type == 'remote' ? x.notes.remote.diffs.normal : x.notes.local.diffs.normal + x.notes.remote.diffs.normal, reply: type == 'local' ? x.notes.local.diffs.reply : type == 'remote' ? x.notes.remote.diffs.reply : x.notes.local.diffs.reply + x.notes.remote.diffs.reply, renote: type == 'local' ? x.notes.local.diffs.renote : type == 'remote' ? x.notes.remote.diffs.renote : x.notes.local.diffs.renote + x.notes.remote.diffs.renote, - all: type == 'local' ? x.notes.local.diff : type == 'remote' ? x.notes.remote.diff : x.notes.local.diff + x.notes.remote.diff + all: type == 'local' ? (x.notes.local.inc + -x.notes.local.dec) : type == 'remote' ? (x.notes.remote.inc + -x.notes.remote.dec) : (x.notes.local.inc + -x.notes.local.dec) + (x.notes.remote.inc + -x.notes.remote.dec) })); return [{ @@ -152,7 +152,7 @@ export default Vue.extend({ return [{ datasets: [{ - label: 'Notes', + label: 'Combined', fill: false, borderColor: '#555', borderWidth: 2, @@ -161,7 +161,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteCount + x.localCount })) }, { - label: 'Remote Notes', + label: 'Remote', fill: true, backgroundColor: 'rgba(65, 221, 222, 0.1)', borderColor: '#41ddde', @@ -170,7 +170,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteCount })) }, { - label: 'Local Notes', + label: 'Local', fill: true, backgroundColor: 'rgba(246, 88, 79, 0.1)', borderColor: '#f6584f', @@ -203,13 +203,13 @@ export default Vue.extend({ usersChart(total: boolean): any { const data = this.stats.slice().reverse().map(x => ({ date: new Date(x.date), - localCount: total ? x.users.local.total : x.users.local.diff, - remoteCount: total ? x.users.remote.total : x.users.remote.diff + localCount: total ? x.users.local.total : (x.users.local.inc + -x.users.local.dec), + remoteCount: total ? x.users.remote.total : (x.users.remote.inc + -x.users.remote.dec) })); return [{ datasets: [{ - label: 'Users', + label: 'Combined', fill: false, borderColor: '#555', borderWidth: 2, @@ -218,7 +218,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteCount + x.localCount })) }, { - label: 'Remote Users', + label: 'Remote', fill: true, backgroundColor: 'rgba(65, 221, 222, 0.1)', borderColor: '#41ddde', @@ -227,7 +227,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteCount })) }, { - label: 'Local Users', + label: 'Local', fill: true, backgroundColor: 'rgba(246, 88, 79, 0.1)', borderColor: '#f6584f', @@ -257,16 +257,93 @@ export default Vue.extend({ }]; }, - driveChart(total: boolean): any { + driveChart(): any { const data = this.stats.slice().reverse().map(x => ({ date: new Date(x.date), - localSize: total ? x.drive.local.totalSize : x.drive.local.diffSize, - remoteSize: total ? x.drive.remote.totalSize : x.drive.remote.diffSize + localInc: x.drive.local.incSize, + localDec: -x.drive.local.decSize, + remoteInc: x.drive.remote.incSize, + remoteDec: -x.drive.remote.decSize, })); return [{ datasets: [{ - label: 'Drive Usage', + label: 'All', + fill: false, + borderColor: '#555', + borderWidth: 2, + borderDash: [4, 4], + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.localInc + x.localDec + x.remoteInc + x.remoteDec })) + }, { + label: 'Remote +', + fill: true, + backgroundColor: 'rgba(65, 221, 222, 0.1)', + borderColor: '#41ddde', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.remoteInc })) + }, { + label: 'Remote -', + fill: true, + backgroundColor: 'rgba(65, 221, 222, 0.1)', + borderColor: '#41ddde', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.remoteDec })) + }, { + label: 'Local +', + fill: true, + backgroundColor: 'rgba(246, 88, 79, 0.1)', + borderColor: '#f6584f', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.localInc })) + }, { + label: 'Local -', + fill: true, + backgroundColor: 'rgba(246, 88, 79, 0.1)', + borderColor: '#f6584f', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.localDec })) + }] + }, { + scales: { + yAxes: [{ + ticks: { + callback: value => { + return Vue.filter('bytes')(value); + } + } + }] + }, + tooltips: { + callbacks: { + label: (tooltipItem, data) => { + const label = data.datasets[tooltipItem.datasetIndex].label || ''; + return `${label}: ${Vue.filter('bytes')(tooltipItem.yLabel)}`; + } + } + } + }]; + }, + + driveTotalChart(): any { + const data = this.stats.slice().reverse().map(x => ({ + date: new Date(x.date), + localSize: x.drive.local.totalSize, + remoteSize: x.drive.remote.totalSize + })); + + return [{ + datasets: [{ + label: 'Combined', fill: false, borderColor: '#555', borderWidth: 2, @@ -275,7 +352,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteSize + x.localSize })) }, { - label: 'Remote Drive Usage', + label: 'Remote', fill: true, backgroundColor: 'rgba(65, 221, 222, 0.1)', borderColor: '#41ddde', @@ -284,7 +361,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteSize })) }, { - label: 'Local Drive Usage', + label: 'Local', fill: true, backgroundColor: 'rgba(246, 88, 79, 0.1)', borderColor: '#f6584f', @@ -314,25 +391,102 @@ export default Vue.extend({ }]; }, - driveFilesChart(total: boolean): any { + driveFilesChart(): any { const data = this.stats.slice().reverse().map(x => ({ date: new Date(x.date), - localCount: total ? x.drive.local.totalCount : x.drive.local.diffCount, - remoteCount: total ? x.drive.remote.totalCount : x.drive.remote.diffCount + localInc: x.drive.local.incCount, + localDec: -x.drive.local.decCount, + remoteInc: x.drive.remote.incCount, + remoteDec: -x.drive.remote.decCount })); return [{ datasets: [{ - label: 'Drive Files', + label: 'All', fill: false, borderColor: '#555', borderWidth: 2, borderDash: [4, 4], pointBackgroundColor: '#fff', lineTension: 0, - data: data.map(x => ({ t: x.date, y: x.remoteCount + x.localCount })) + data: data.map(x => ({ t: x.date, y: x.localInc + x.localDec + x.remoteInc + x.remoteDec })) }, { - label: 'Remote Drive Files', + label: 'Remote +', + fill: true, + backgroundColor: 'rgba(65, 221, 222, 0.1)', + borderColor: '#41ddde', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.remoteInc })) + }, { + label: 'Remote -', + fill: true, + backgroundColor: 'rgba(65, 221, 222, 0.1)', + borderColor: '#41ddde', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.remoteDec })) + }, { + label: 'Local +', + fill: true, + backgroundColor: 'rgba(246, 88, 79, 0.1)', + borderColor: '#f6584f', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.localInc })) + }, { + label: 'Local -', + fill: true, + backgroundColor: 'rgba(246, 88, 79, 0.1)', + borderColor: '#f6584f', + borderWidth: 2, + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.localDec })) + }] + }, { + scales: { + yAxes: [{ + ticks: { + callback: value => { + return Vue.filter('number')(value); + } + } + }] + }, + tooltips: { + callbacks: { + label: (tooltipItem, data) => { + const label = data.datasets[tooltipItem.datasetIndex].label || ''; + return `${label}: ${Vue.filter('number')(tooltipItem.yLabel)}`; + } + } + } + }]; + }, + + driveFilesTotalChart(): any { + const data = this.stats.slice().reverse().map(x => ({ + date: new Date(x.date), + localCount: x.drive.local.totalCount, + remoteCount: x.drive.remote.totalCount, + })); + + return [{ + datasets: [{ + label: 'Combined', + fill: false, + borderColor: '#555', + borderWidth: 2, + borderDash: [4, 4], + pointBackgroundColor: '#fff', + lineTension: 0, + data: data.map(x => ({ t: x.date, y: x.localCount + x.remoteCount })) + }, { + label: 'Remote', fill: true, backgroundColor: 'rgba(65, 221, 222, 0.1)', borderColor: '#41ddde', @@ -341,7 +495,7 @@ export default Vue.extend({ lineTension: 0, data: data.map(x => ({ t: x.date, y: x.remoteCount })) }, { - label: 'Local Drive Files', + label: 'Local', fill: true, backgroundColor: 'rgba(246, 88, 79, 0.1)', borderColor: '#f6584f', diff --git a/src/models/stats.ts b/src/models/stats.ts index c481c3196..3041d3852 100644 --- a/src/models/stats.ts +++ b/src/models/stats.ts @@ -8,8 +8,14 @@ export default Stats; export interface IStats { _id: mongo.ObjectID; + /** + * 集計日時 + */ date: Date; + /** + * 集計期間 + */ span: 'day' | 'hour'; /** @@ -18,26 +24,36 @@ export interface IStats { users: { local: { /** - * この日時点での、ローカルのユーザーの総計 + * 集計期間時点での、全ユーザー数 (ローカル) */ total: number; /** - * ローカルのユーザー数の前日比 + * 増加したユーザー数 (ローカル) */ - diff: number; + inc: number; + + /** + * 減少したユーザー数 (ローカル) + */ + dec: number; }; remote: { /** - * この日時点での、リモートのユーザーの総計 + * 集計期間時点での、全ユーザー数 (リモート) */ total: number; /** - * リモートのユーザー数の前日比 + * 増加したユーザー数 (リモート) */ - diff: number; + inc: number; + + /** + * 減少したユーザー数 (リモート) + */ + dec: number; }; }; @@ -47,28 +63,33 @@ export interface IStats { notes: { local: { /** - * この日時点での、ローカルの投稿の総計 + * 集計期間時点での、全投稿数 (ローカル) */ total: number; /** - * ローカルの投稿数の前日比 + * 増加した投稿数 (ローカル) */ - diff: number; + inc: number; + + /** + * 減少した投稿数 (ローカル) + */ + dec: number; diffs: { /** - * ローカルの通常の投稿数の前日比 + * 通常の投稿数の差分 (ローカル) */ normal: number; /** - * ローカルのリプライの投稿数の前日比 + * リプライの投稿数の差分 (ローカル) */ reply: number; /** - * ローカルのRenoteの投稿数の前日比 + * Renoteの投稿数の差分 (ローカル) */ renote: number; }; @@ -76,28 +97,33 @@ export interface IStats { remote: { /** - * この日時点での、リモートの投稿の総計 + * 集計期間時点での、全投稿数 (リモート) */ total: number; /** - * リモートの投稿数の前日比 + * 増加した投稿数 (リモート) */ - diff: number; + inc: number; + + /** + * 減少した投稿数 (リモート) + */ + dec: number; diffs: { /** - * リモートの通常の投稿数の前日比 + * 通常の投稿数の差分 (リモート) */ normal: number; /** - * リモートのリプライの投稿数の前日比 + * リプライの投稿数の差分 (リモート) */ reply: number; /** - * リモートのRenoteの投稿数の前日比 + * Renoteの投稿数の差分 (リモート) */ renote: number; }; @@ -110,46 +136,66 @@ export interface IStats { drive: { local: { /** - * この日時点での、ローカルのドライブファイル数の総計 + * 集計期間時点での、全ドライブファイル数 (ローカル) */ totalCount: number; /** - * この日時点での、ローカルのドライブファイルサイズの総計 + * 集計期間時点での、全ドライブファイルの合計サイズ (ローカル) */ totalSize: number; /** - * ローカルのドライブファイル数の前日比 + * 増加したドライブファイル数 (ローカル) */ - diffCount: number; + incCount: number; /** - * ローカルのドライブファイルサイズの前日比 + * 増加したドライブ使用量 (ローカル) */ - diffSize: number; + incSize: number; + + /** + * 減少したドライブファイル数 (ローカル) + */ + decCount: number; + + /** + * 減少したドライブ使用量 (ローカル) + */ + decSize: number; }; remote: { /** - * この日時点での、リモートのドライブファイル数の総計 + * 集計期間時点での、全ドライブファイル数 (リモート) */ totalCount: number; /** - * この日時点での、リモートのドライブファイルサイズの総計 + * 集計期間時点での、全ドライブファイルの合計サイズ (リモート) */ totalSize: number; /** - * リモートのドライブファイル数の前日比 + * 増加したドライブファイル数 (リモート) */ - diffCount: number; + incCount: number; /** - * リモートのドライブファイルサイズの前日比 + * 増加したドライブ使用量 (リモート) */ - diffSize: number; + incSize: number; + + /** + * 減少したドライブファイル数 (リモート) + */ + decCount: number; + + /** + * 減少したドライブ使用量 (リモート) + */ + decSize: number; }; }; } diff --git a/src/remote/activitypub/models/note.ts b/src/remote/activitypub/models/note.ts index 02bce6fec..1dfeebfdf 100644 --- a/src/remote/activitypub/models/note.ts +++ b/src/remote/activitypub/models/note.ts @@ -131,5 +131,7 @@ export async function resolveNote(value: string | IObject, resolver?: Resolver): //#endregion // リモートサーバーからフェッチしてきて登録 - return await createNote(value, resolver); + // ここでuriの代わりに添付されてきたNote Objectが指定されていると、サーバーフェッチを経ずにノートが生成されるが + // 添付されてきたNote Objectは偽装されている可能性があるため、常にuriを指定してサーバーフェッチを行う。 + return await createNote(uri, resolver); } diff --git a/src/server/api/endpoints/chart.ts b/src/server/api/endpoints/chart.ts index da3476f06..514bacaa8 100644 --- a/src/server/api/endpoints/chart.ts +++ b/src/server/api/endpoints/chart.ts @@ -2,6 +2,31 @@ import Stats, { IStats } from '../../../models/stats'; type Omit = Pick>; +function migrateStats(stats: IStats[]) { + stats.forEach(stat => { + const isOldData = stat.users.local.inc == null; + + if (!isOldData) return; + + stat.users.local.inc = (stat as any).users.local.diff; + stat.users.local.dec = 0; + stat.users.remote.inc = (stat as any).users.remote.diff; + stat.users.remote.dec = 0; + stat.notes.local.inc = (stat as any).notes.local.diff; + stat.notes.local.dec = 0; + stat.notes.remote.inc = (stat as any).notes.remote.diff; + stat.notes.remote.dec = 0; + stat.drive.local.incCount = (stat as any).drive.local.diffCount; + stat.drive.local.decCount = 0; + stat.drive.local.incSize = (stat as any).drive.local.diffSize; + stat.drive.local.decSize = 0; + stat.drive.remote.incCount = (stat as any).drive.remote.diffCount; + stat.drive.remote.decCount = 0; + stat.drive.remote.incSize = (stat as any).drive.remote.diffSize; + stat.drive.remote.decSize = 0; + }); +} + export const meta = { }; @@ -44,6 +69,10 @@ export default (params: any) => new Promise(async (res, rej) => { }), ]); + // 後方互換性のため + migrateStats(statsPerDay); + migrateStats(statsPerHour); + const format = (src: IStats[], span: 'day' | 'hour') => { const chart: Array, 'span'>> = []; @@ -70,17 +99,20 @@ export default (params: any) => new Promise(async (res, rej) => { users: { local: { total: mostRecent.users.local.total, - diff: 0 + inc: 0, + dec: 0 }, remote: { total: mostRecent.users.remote.total, - diff: 0 + inc: 0, + dec: 0 } }, notes: { local: { total: mostRecent.notes.local.total, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -89,7 +121,8 @@ export default (params: any) => new Promise(async (res, rej) => { }, remote: { total: mostRecent.notes.remote.total, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -101,14 +134,18 @@ export default (params: any) => new Promise(async (res, rej) => { local: { totalCount: mostRecent.drive.local.totalCount, totalSize: mostRecent.drive.local.totalSize, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 }, remote: { totalCount: mostRecent.drive.remote.totalCount, totalSize: mostRecent.drive.remote.totalSize, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 } } }); @@ -118,17 +155,20 @@ export default (params: any) => new Promise(async (res, rej) => { users: { local: { total: 0, - diff: 0 + inc: 0, + dec: 0 }, remote: { total: 0, - diff: 0 + inc: 0, + dec: 0 } }, notes: { local: { total: 0, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -137,7 +177,8 @@ export default (params: any) => new Promise(async (res, rej) => { }, remote: { total: 0, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -149,14 +190,18 @@ export default (params: any) => new Promise(async (res, rej) => { local: { totalCount: 0, totalSize: 0, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 }, remote: { totalCount: 0, totalSize: 0, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 } } }); diff --git a/src/services/update-chart.ts b/src/services/update-chart.ts index 0a0f58bb9..1f8da6be9 100644 --- a/src/services/update-chart.ts +++ b/src/services/update-chart.ts @@ -48,17 +48,20 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise { users: { local: { total: mostRecentStats.users.local.total, - diff: 0 + inc: 0, + dec: 0 }, remote: { total: mostRecentStats.users.remote.total, - diff: 0 + inc: 0, + dec: 0 } }, notes: { local: { total: mostRecentStats.notes.local.total, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -67,7 +70,8 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise { }, remote: { total: mostRecentStats.notes.remote.total, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -79,14 +83,18 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise { local: { totalCount: mostRecentStats.drive.local.totalCount, totalSize: mostRecentStats.drive.local.totalSize, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 }, remote: { totalCount: mostRecentStats.drive.remote.totalCount, totalSize: mostRecentStats.drive.remote.totalSize, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 } } }; @@ -105,17 +113,20 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise { users: { local: { total: 0, - diff: 0 + inc: 0, + dec: 0 }, remote: { total: 0, - diff: 0 + inc: 0, + dec: 0 } }, notes: { local: { total: 0, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -124,7 +135,8 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise { }, remote: { total: 0, - diff: 0, + inc: 0, + dec: 0, diffs: { normal: 0, reply: 0, @@ -136,14 +148,18 @@ async function getCurrentStats(span: 'day' | 'hour'): Promise { local: { totalCount: 0, totalSize: 0, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 }, remote: { totalCount: 0, totalSize: 0, - diffCount: 0, - diffSize: 0 + incCount: 0, + incSize: 0, + decCount: 0, + decSize: 0 } } }; @@ -174,46 +190,56 @@ function update(inc: any) { } export async function updateUserStats(user: IUser, isAdditional: boolean) { - const amount = isAdditional ? 1 : -1; const origin = isLocalUser(user) ? 'local' : 'remote'; const inc = {} as any; - inc[`users.${origin}.total`] = amount; - inc[`users.${origin}.diff`] = amount; + inc[`users.${origin}.total`] = isAdditional ? 1 : -1; + if (isAdditional) { + inc[`users.${origin}.inc`] = 1; + } else { + inc[`users.${origin}.dec`] = 1; + } await update(inc); } export async function updateNoteStats(note: INote, isAdditional: boolean) { - const amount = isAdditional ? 1 : -1; const origin = isLocalUser(note._user) ? 'local' : 'remote'; const inc = {} as any; - inc[`notes.${origin}.total`] = amount; - inc[`notes.${origin}.diff`] = amount; + inc[`notes.${origin}.total`] = isAdditional ? 1 : -1; + + if (isAdditional) { + inc[`notes.${origin}.inc`] = 1; + } else { + inc[`notes.${origin}.dec`] = 1; + } if (note.replyId != null) { - inc[`notes.${origin}.diffs.reply`] = amount; + inc[`notes.${origin}.diffs.reply`] = isAdditional ? 1 : -1; } else if (note.renoteId != null) { - inc[`notes.${origin}.diffs.renote`] = amount; + inc[`notes.${origin}.diffs.renote`] = isAdditional ? 1 : -1; } else { - inc[`notes.${origin}.diffs.normal`] = amount; + inc[`notes.${origin}.diffs.normal`] = isAdditional ? 1 : -1; } await update(inc); } export async function updateDriveStats(file: IDriveFile, isAdditional: boolean) { - const amount = isAdditional ? 1 : -1; - const size = isAdditional ? file.length : -file.length; const origin = isLocalUser(file.metadata._user) ? 'local' : 'remote'; const inc = {} as any; - inc[`drive.${origin}.totalCount`] = amount; - inc[`drive.${origin}.diffCount`] = amount; - inc[`drive.${origin}.totalSize`] = size; - inc[`drive.${origin}.diffSize`] = size; + inc[`drive.${origin}.totalCount`] = isAdditional ? 1 : -1; + inc[`drive.${origin}.totalSize`] = isAdditional ? file.length : -file.length; + if (isAdditional) { + inc[`drive.${origin}.incCount`] = 1; + inc[`drive.${origin}.incSize`] = file.length; + } else { + inc[`drive.${origin}.decCount`] = 1; + inc[`drive.${origin}.decSize`] = file.length; + } await update(inc); }