Compare commits
127 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e701ef9e0 | ||
|
|
3d6fb661bb | ||
|
|
fc372496da | ||
|
|
ad7258fe9c | ||
|
|
bd707cb2a8 | ||
|
|
1839b5f205 | ||
|
|
02b47f963c | ||
|
|
f8a7f9378a | ||
|
|
65cb253be4 | ||
|
|
a12356b24b | ||
|
|
6a67ad7f93 | ||
|
|
140a7f0b1c | ||
|
|
00159bc6b5 | ||
|
|
9542260103 | ||
|
|
72074578df | ||
|
|
3b4750a988 | ||
|
|
aeec5f0163 | ||
|
|
9c94d8c8d6 | ||
|
|
581712a2c8 | ||
|
|
b25b51aaca | ||
|
|
fb97e13a61 | ||
|
|
36e154fdb2 | ||
|
|
ca273a24b4 | ||
|
|
d828bf2889 | ||
|
|
87efccef18 | ||
|
|
e0bf522e7f | ||
|
|
5b1cd3bd3c | ||
|
|
f00489196d | ||
|
|
dd53bf7e51 | ||
|
|
35a6da26d2 | ||
|
|
c8c8748a0b | ||
|
|
46d0065a90 | ||
|
|
990b0180a8 | ||
|
|
f3bfb72251 | ||
|
|
0358a7edc6 | ||
|
|
37f99fca04 | ||
|
|
50dfc8ab82 | ||
|
|
c70c739b0c | ||
|
|
5918285326 | ||
|
|
b1dead1186 | ||
|
|
3e36e132c3 | ||
|
|
fa8d1809e7 | ||
|
|
e12b668d04 | ||
|
|
e5506f7d8c | ||
|
|
b1ac7e5cb3 | ||
|
|
ffd164a5f3 | ||
|
|
cb27414026 | ||
|
|
e320912f33 | ||
|
|
d23aaae698 | ||
|
|
120c0fe848 | ||
|
|
34857b9520 | ||
|
|
a87dcece4c | ||
|
|
01e2479004 | ||
|
|
0fd63fe091 | ||
|
|
cc98801c67 | ||
|
|
2724d74108 | ||
|
|
6d0c0d3a5f | ||
|
|
15f8f63317 | ||
|
|
d970d65968 | ||
|
|
04d359691b | ||
|
|
bfc519944a | ||
|
|
9f69fd14a2 | ||
|
|
85058787b2 | ||
|
|
ec851623e0 | ||
|
|
e05429a3ec | ||
|
|
f651c41816 | ||
|
|
6b88d99ae2 | ||
|
|
814469cdca | ||
|
|
536bf8f141 | ||
|
|
6a27290815 | ||
|
|
7dde3465e2 | ||
|
|
0206a4ac83 | ||
|
|
380f5a972c | ||
|
|
407467a236 | ||
|
|
bcfa9e18bf | ||
|
|
69b730e91a | ||
|
|
6c6c003d68 | ||
|
|
fd652b70d6 | ||
|
|
804a5ab6a8 | ||
|
|
d984a1aa19 | ||
|
|
e05b5a6ab8 | ||
|
|
3ff84db421 | ||
|
|
74ca73ecb4 | ||
|
|
37032f68ae | ||
|
|
21d3605737 | ||
|
|
0a7c1caf43 | ||
|
|
24b57335fa | ||
|
|
9f981d875a | ||
|
|
6dcc3800e0 | ||
|
|
44e9be5a1c | ||
|
|
6a8c560d21 | ||
|
|
0afe8c6b34 | ||
|
|
0f5d7f52a0 | ||
|
|
aaaefa0ee2 | ||
|
|
276929bc7e | ||
|
|
32882f1397 | ||
|
|
7dc380c485 | ||
|
|
49aaa9a5d3 | ||
|
|
84462eb3f2 | ||
|
|
91709ca979 | ||
|
|
9ece71e652 | ||
|
|
4e93f6c6ff | ||
|
|
ad9f1fb7c7 | ||
|
|
abaeea6d8b | ||
|
|
8efbcc4c6b | ||
|
|
8ef31cab8c | ||
|
|
37ae53e55c | ||
|
|
d01f06bdf4 | ||
|
|
0d4a8d118a | ||
|
|
7e6ec83b1f | ||
|
|
9eb515cfae | ||
|
|
d0da019a21 | ||
|
|
57a13c9ad3 | ||
|
|
7f39100634 | ||
|
|
9ab96ef39a | ||
|
|
ed21d797a6 | ||
|
|
15960746bb | ||
|
|
e0f1e3ca71 | ||
|
|
51d0524182 | ||
|
|
16801aa5c4 | ||
|
|
cd23f66834 | ||
|
|
cc5d2b2875 | ||
|
|
94ef03db9e | ||
|
|
038bd100b2 | ||
|
|
3b5c3f086a | ||
|
|
a136715111 | ||
|
|
daa22d68fa |
@@ -164,3 +164,6 @@ drive:
|
||||
# external: true
|
||||
# engine: http://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}
|
||||
# timeout: 300000
|
||||
|
||||
# Max allowed note text length in charactors
|
||||
maxNoteTextLength: 1000
|
||||
|
||||
@@ -11,7 +11,7 @@ branches:
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- 10.1.0
|
||||
- 11.0.0
|
||||
|
||||
env:
|
||||
- CXX=g++-4.8 NODE_ENV=production
|
||||
|
||||
@@ -13,7 +13,3 @@ redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
pass: ''
|
||||
elasticsearch:
|
||||
host: localhost
|
||||
port: 9200
|
||||
pass: ''
|
||||
|
||||
@@ -13,7 +13,3 @@ redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
pass: ''
|
||||
elasticsearch:
|
||||
host: localhost
|
||||
port: 9200
|
||||
pass: ''
|
||||
|
||||
20
Dockerfile
20
Dockerfile
@@ -1,16 +1,26 @@
|
||||
FROM alpine:edge AS base
|
||||
FROM alpine:3.8 AS base
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
RUN apk add --no-cache nodejs nodejs-npm
|
||||
RUN apk add vips fftw --update-cache --repository https://dl-3.alpinelinux.org/alpine/edge/testing/
|
||||
RUN apk add --no-cache nodejs nodejs-npm zlib
|
||||
WORKDIR /misskey
|
||||
COPY . ./
|
||||
|
||||
FROM base AS builder
|
||||
|
||||
RUN apk add --no-cache gcc g++ python autoconf automake file make nasm
|
||||
RUN apk add vips-dev fftw-dev --update-cache --repository https://dl-3.alpinelinux.org/alpine/edge/testing/
|
||||
RUN apk add --no-cache \
|
||||
gcc \
|
||||
g++ \
|
||||
libc-dev \
|
||||
python \
|
||||
autoconf \
|
||||
automake \
|
||||
file \
|
||||
make \
|
||||
nasm \
|
||||
pkgconfig \
|
||||
libtool \
|
||||
zlib-dev
|
||||
RUN npm install \
|
||||
&& npm install -g node-gyp \
|
||||
&& node-gyp configure \
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
[![][travis-badge]][travis-link]
|
||||
[![][dependencies-badge]][dependencies-link]
|
||||
[](http://makeapullrequest.com) [](https://greenkeeper.io/)
|
||||
[](http://makeapullrequest.com)
|
||||
|
||||
**Sophisticated microblogging platform, evolving forever.**
|
||||
|
||||
|
||||
38
appveyor.yml
Normal file
38
appveyor.yml
Normal file
@@ -0,0 +1,38 @@
|
||||
# appveyor file
|
||||
# http://www.appveyor.com/docs/appveyor-yml
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- nodejs_version: 11.0.0
|
||||
|
||||
platform:
|
||||
- x64
|
||||
- Any CPU
|
||||
|
||||
build: off
|
||||
|
||||
install:
|
||||
# Get the latest stable version of Node.js or io.js
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
|
||||
# Update node-gyp
|
||||
# 必須! node-gyp のバージョンを上げないと、ネイティブモジュールのコンパイルに失敗します
|
||||
- npm install -g node-gyp
|
||||
|
||||
- npm install
|
||||
|
||||
init:
|
||||
# git clone の際の改行を変換しないようにします
|
||||
- git config --global core.autocrlf false
|
||||
|
||||
before_test:
|
||||
# 設定ファイルを配置
|
||||
- cp ./.travis/default.yml ./.config
|
||||
- cp ./.travis/test.yml ./.config
|
||||
|
||||
- npm run build
|
||||
|
||||
test_script:
|
||||
- node --version
|
||||
- npm --version
|
||||
- npm test
|
||||
@@ -6,7 +6,7 @@ services:
|
||||
restart: always
|
||||
links:
|
||||
- mongo
|
||||
- redis
|
||||
# - redis
|
||||
# - es
|
||||
ports:
|
||||
- "127.0.0.1:3000:3000"
|
||||
@@ -14,18 +14,18 @@ services:
|
||||
- internal_network
|
||||
- external_network
|
||||
|
||||
redis:
|
||||
restart: always
|
||||
image: redis:4.0-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
# redis:
|
||||
# restart: always
|
||||
# image: redis:4.0-alpine
|
||||
# networks:
|
||||
# - internal_network
|
||||
### Uncomment to enable Redis persistance
|
||||
# volumes:
|
||||
# - ./redis:/data
|
||||
## volumes:
|
||||
## - ./redis:/data
|
||||
|
||||
mongo:
|
||||
restart: always
|
||||
image: mongo:4.1-bionic
|
||||
image: mongo:4.1
|
||||
networks:
|
||||
- internal_network
|
||||
environment:
|
||||
|
||||
@@ -7,23 +7,29 @@ This guide describes how to install and setup Misskey with Docker.
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
*1.* Make configuration files
|
||||
*1.* Download Misskey
|
||||
----------------------------------------------------------------
|
||||
1. `git clone -b master git://github.com/syuilo/misskey.git` Clone Misskey repository's master branch.
|
||||
2. `cd misskey` Move to misskey directory.
|
||||
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest) tag.
|
||||
|
||||
*2.* Make configuration files
|
||||
----------------------------------------------------------------
|
||||
1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`.
|
||||
2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` Copy the `.config/mongo_initdb_example.js` and rename it to `mongo_initdb.js`.
|
||||
2. Edit `default.yml` and `mongo_initdb.js`.
|
||||
|
||||
*2.* Configure Docker
|
||||
*3.* Configure Docker
|
||||
----------------------------------------------------------------
|
||||
Edit `docker-compose.yml`.
|
||||
|
||||
*3.* Build Misskey
|
||||
*4.* Build Misskey
|
||||
----------------------------------------------------------------
|
||||
Build misskey with the following:
|
||||
|
||||
`docker-compose build`
|
||||
|
||||
*4.* That is it.
|
||||
*5.* That is it.
|
||||
----------------------------------------------------------------
|
||||
Well done! Now, you have an environment that run to Misskey.
|
||||
|
||||
|
||||
@@ -7,23 +7,29 @@ Dockerを使ったMisskey構築方法
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
*1.* 設定ファイルを作成する
|
||||
*1.* Misskeyのダウンロード
|
||||
----------------------------------------------------------------
|
||||
1. `git clone -b master git://github.com/syuilo/misskey.git` masterブランチからMisskeyレポジトリをクローン
|
||||
2. `cd misskey` misskeyディレクトリに移動
|
||||
3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認
|
||||
|
||||
*2.* 設定ファイルを作成する
|
||||
----------------------------------------------------------------
|
||||
1. `cp .config/example.yml .config/default.yml` `.config/example.yml`をコピーし名前を`default.yml`にする
|
||||
2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` `.config/mongo_initdb_example.js`をコピーし名前を`mongo_initdb.js`にする
|
||||
3. `default.yml`と`mongo_initdb.js`を編集する
|
||||
|
||||
*2.* Dockerの設定
|
||||
*3.* Dockerの設定
|
||||
----------------------------------------------------------------
|
||||
`docker-compose.yml`を編集してください。
|
||||
|
||||
*3.* Misskeyのビルド
|
||||
*4.* Misskeyのビルド
|
||||
----------------------------------------------------------------
|
||||
次のコマンドでMisskeyをビルドしてください:
|
||||
|
||||
`docker-compose build`
|
||||
|
||||
*4.* 以上です!
|
||||
*5.* 以上です!
|
||||
----------------------------------------------------------------
|
||||
お疲れ様でした。これでMisskeyを動かす準備は整いました。
|
||||
|
||||
@@ -45,4 +51,4 @@ Dockerを使ったMisskey構築方法
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
なにかお困りのことがありましたらお気軽にご連絡ください。
|
||||
なにかお困りのことがありましたらお気軽にご連絡ください。
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "{}年前"
|
||||
month-and-day: "{month}月 {day}日"
|
||||
trash: "ゴミ箱"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "日"
|
||||
monday: "月"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "チャート"
|
||||
per-day: "1日ごと"
|
||||
per-hour: "1時間ごと"
|
||||
federation: "フェデレーション"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
drive: "ドライブ"
|
||||
network: "ネットワーク"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減 (統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "決定"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "使用中"
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
banner: "バナー"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "名前を変更"
|
||||
rename-folder: "フォルダ名の変更"
|
||||
input-new-folder-name: "新しいフォルダ名を入力してください"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "検索"
|
||||
load-more: "もっと読み込む"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "通知"
|
||||
apps: "アプリ"
|
||||
mute: "ミュート"
|
||||
drive: "ドライブ"
|
||||
security: "セキュリティ"
|
||||
signin: "サインイン履歴"
|
||||
password: "パスワード"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "設定が完了しました!"
|
||||
failed: "設定に失敗しました。トークンに誤りがないかご確認ください。"
|
||||
info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。"
|
||||
desktop/views/components/settings.api.vue:
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "連携しているアプリケーションはありません"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "中"
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "ミュートしているユーザーはいません"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "さん"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "プロフィール"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
lists: "リスト"
|
||||
follow-requests: "フォロー申請"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "閉じる"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "ユーザー"
|
||||
update: "更新"
|
||||
announcements: "お知らせ"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "他を見る"
|
||||
no-one: "いません!"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "ドライブ"
|
||||
used: "使用中"
|
||||
folder-count: "フォルダ"
|
||||
count-separator: "、"
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "メッセージ"
|
||||
follow-requests: "フォロー申請"
|
||||
search: "検索"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
user-lists: "リスト"
|
||||
widgets: "ウィジェット"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "リスト"
|
||||
enter-list-name: "リスト名を入力してください"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "ドライブ"
|
||||
more: "もっと見る"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めましょう"
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "vor {} Jahr{0:en}"
|
||||
month-and-day: "{day}/{month}"
|
||||
trash: "Papierkorb"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "So"
|
||||
monday: "Mo"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "チャート"
|
||||
per-day: "1日ごと"
|
||||
per-hour: "1時間ごと"
|
||||
federation: "フェデレーション"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
drive: "ドライブ"
|
||||
network: "Netzwerk"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減 (統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "OK"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "benutzt"
|
||||
drive: "Speicher"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "Avatar"
|
||||
banner: "Banner"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "Umbenennen"
|
||||
rename-folder: "Ordner umbenennen"
|
||||
input-new-folder-name: "Namen für neuen Ordner eingeben"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "Laufwerk"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "Suchen"
|
||||
load-more: "Mehr laden"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "Mitteilungen"
|
||||
apps: "In App öffnen"
|
||||
mute: "Stummschalten"
|
||||
drive: "Dateien vom Drive anfügen"
|
||||
security: "Sicherheit"
|
||||
signin: "サインイン履歴"
|
||||
password: "Passwort"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "設定が完了しました!"
|
||||
failed: "設定に失敗しました。トークンに誤りがないかご確認ください。"
|
||||
info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。"
|
||||
desktop/views/components/settings.api.vue:
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "Bitte Passwort eingeben"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "連携しているアプリケーションはありません"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "中"
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "ミュートしているユーザーはいません"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "さん"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "Dein Profil"
|
||||
drive: "Speicher"
|
||||
favorites: "Favoriten"
|
||||
lists: "Listen"
|
||||
follow-requests: "フォロー申請"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "閉じる"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "ユーザー"
|
||||
update: "更新"
|
||||
announcements: "お知らせ"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "他を見る"
|
||||
no-one: "いません!"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "ドライブ"
|
||||
used: "使用中"
|
||||
folder-count: "フォルダ"
|
||||
count-separator: "、"
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "メッセージ"
|
||||
follow-requests: "フォロー申請"
|
||||
search: "検索"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
user-lists: "リスト"
|
||||
widgets: "ウィジェット"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "リスト"
|
||||
enter-list-name: "リスト名を入力してください"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "ドライブ"
|
||||
more: "Mehr laden"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めましょう"
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "{}year(s) ago"
|
||||
month-and-day: "{month}/{day}"
|
||||
trash: "Trash"
|
||||
drive: "Drive"
|
||||
weekday-short:
|
||||
sunday: "S"
|
||||
monday: "M"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "Charts"
|
||||
per-day: "per Day"
|
||||
per-hour: "per Hour"
|
||||
federation: "Federation"
|
||||
notes: "Posts"
|
||||
users: "Users"
|
||||
drive: "Drive"
|
||||
network: "Network"
|
||||
charts:
|
||||
federation-instances: "The number of instances: increase/decrease"
|
||||
federation-instances-total: "Total number of instances"
|
||||
notes: "The number of posts: increase/decrease (Combined)"
|
||||
local-notes: "The number of posts: increase/decrease (Local)"
|
||||
remote-notes: "The number of posts: increase/decrease (Remote)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "OK"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "used"
|
||||
drive: "Media storage"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "Avatar"
|
||||
banner: "Banner"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "Rename"
|
||||
rename-folder: "Rename folder"
|
||||
input-new-folder-name: "Enter new name"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "Media storage"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "Search"
|
||||
load-more: "Load more"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "Notification"
|
||||
apps: "Apps"
|
||||
mute: "Mute"
|
||||
drive: "Drive"
|
||||
security: "Security"
|
||||
signin: "Sign in history"
|
||||
password: "Password"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "Settings saved!"
|
||||
failed: "Failed to setup. Please ensure that the token is correct."
|
||||
info: "From the next time you sign in to Misskey, the token displayed on your device will be necessary too, as well as the password."
|
||||
desktop/views/components/settings.api.vue:
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "To access the API, set this token as the key 'i' of request parameters."
|
||||
caution: "Do not enter this token to any apps nor tell this token to others otherwise your account may get compromised."
|
||||
regeneration-of-token: "If your token gets leaked, you can regenerate it."
|
||||
regenerate-token: "Regenerate the token"
|
||||
token: "Token:"
|
||||
enter-password: "Please enter the password"
|
||||
enter-password: "Enter the password"
|
||||
console:
|
||||
title: 'API console'
|
||||
endpoint: 'Endpoint'
|
||||
parameter: 'Parameters'
|
||||
send: 'Send'
|
||||
sending: 'Sending'
|
||||
response: 'Result'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "No linked applications"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "Max"
|
||||
in-use: "In use"
|
||||
stats: "Statistics"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "No muted users"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "-san"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "Your profile"
|
||||
drive: "Media storage"
|
||||
favorites: "Favorites"
|
||||
lists: "Lists"
|
||||
follow-requests: "Follow requests"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "Close"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "Dashboard"
|
||||
drive: "Drive"
|
||||
users: "Users"
|
||||
update: "Updates"
|
||||
announcements: "Announcements"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "refresh"
|
||||
no-one: "Anyone!"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "Media storage"
|
||||
used: "used"
|
||||
folder-count: "Folder(s)"
|
||||
count-separator: ", "
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "Messages"
|
||||
follow-requests: "Follow requests"
|
||||
search: "Search"
|
||||
drive: "Drive"
|
||||
favorites: "Favorites"
|
||||
user-lists: "Lists"
|
||||
widgets: "Widgets"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "Lists"
|
||||
enter-list-name: "Enter a name of the list to make"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "Drive"
|
||||
more: "Load more"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "Your account is now ready! 📦"
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "Hace {} año(s)"
|
||||
month-and-day: "{day} de {month}"
|
||||
trash: "Papelera"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "domingo"
|
||||
monday: "lunes"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "Gráficos"
|
||||
per-day: "por día"
|
||||
per-hour: "por hora"
|
||||
federation: "フェデレーション"
|
||||
notes: "Publicaciones"
|
||||
users: "Usuarios"
|
||||
drive: "Unidad"
|
||||
network: "ネットワーク"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "Número de publicaciones: aumentar/disminuir (Combinado)"
|
||||
local-notes: "Número de publicaciones: aumentar/disminuir (Local)"
|
||||
remote-notes: "Número de publicaciones: aumentar/disminuir (Remoto)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "OK"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "usado"
|
||||
drive: "Disco"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "Avatar"
|
||||
banner: "Banner"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "Renombrar"
|
||||
rename-folder: "Renombrar carpeta"
|
||||
input-new-folder-name: "Escribe el nombre nuevo"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "Disco"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "Buscar"
|
||||
load-more: "Cargar más"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "Notificación"
|
||||
apps: "Aplicaciones"
|
||||
mute: "Silenciar"
|
||||
drive: "Disco"
|
||||
security: "Seguridad"
|
||||
signin: "Historial de inicios de sesión"
|
||||
password: "Contraseña"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "¡Configuraciones guardadas!"
|
||||
failed: "Error al configurar. Por favor asegúrate de que el token es correcto."
|
||||
info: "Desde ahora, ingresa el token que se muestra en tu dispositivo adicionalmente a tu contraseña cuando inicies sesión en Misskey"
|
||||
desktop/views/components/settings.api.vue:
|
||||
intro: "Para acceder al API, configura este token como la letra \"i\" de los parámetros requeridos."
|
||||
caution: "Por favor no muestres este token a otros (no lo ingreses en otro lugar que no sea aquí). De otra forma, tu cuenta puede llegar a ser comprometida."
|
||||
regeneration-of-token: "En el caso no deseado de que este token lo tenga otra persona, puedes regenerarlo."
|
||||
regenerate-token: "Regenerar el token"
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "Por favor ingresa tu contraseña"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "No hay aplicaciones asociadas"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "Max"
|
||||
in-use: "en uso."
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "No hay usuarios silenciados"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "-san"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "Tu perfil"
|
||||
drive: "Unidad"
|
||||
favorites: "Favoritos"
|
||||
lists: "Listas"
|
||||
follow-requests: "Solicitudes de seguimiento"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "閉じる"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "ユーザー"
|
||||
update: "更新"
|
||||
announcements: "お知らせ"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "他を見る"
|
||||
no-one: "いません!"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "ドライブ"
|
||||
used: "使用中"
|
||||
folder-count: "フォルダ"
|
||||
count-separator: "、"
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "メッセージ"
|
||||
follow-requests: "フォロー申請"
|
||||
search: "検索"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
user-lists: "リスト"
|
||||
widgets: "ウィジェット"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "リスト"
|
||||
enter-list-name: "リスト名を入力してください"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "ドライブ"
|
||||
more: "もっと見る"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めましょう"
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "Il y a {} an·s"
|
||||
month-and-day: "{month} mois/{day} jour"
|
||||
trash: "Corbeille"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "D"
|
||||
monday: "L"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "Graphiques"
|
||||
per-day: "par jour"
|
||||
per-hour: "par heure"
|
||||
federation: "フェデレーション"
|
||||
notes: "Publications"
|
||||
users: "Utilisateurs"
|
||||
drive: "Drive"
|
||||
network: "Réseau"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減 (統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "OK"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "utilisé"
|
||||
drive: "Drive"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "Avatar"
|
||||
banner: "Bannière"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "Renommer"
|
||||
rename-folder: "Renommer le dossier"
|
||||
input-new-folder-name: "Entrer un nouveau nom"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "Drive"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "Rechercher"
|
||||
load-more: "Afficher plus"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "Notification"
|
||||
apps: "Applications"
|
||||
mute: "Mettre en sourdine"
|
||||
drive: "Drive"
|
||||
security: "Sécurité"
|
||||
signin: "Historique de connexion"
|
||||
password: "Mot de Passe"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "L'operation a été complétée avec succès!"
|
||||
failed: "L'operation a échoué. Veuillez vous assurer que le token a été entrer correctement."
|
||||
info: "À partir de maintenant, à chaque fois que vous vous connecter entrez votre mot de passe ainsi que le token généré sur votre appareil."
|
||||
desktop/views/components/settings.api.vue:
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "Si votre jeton est compromis, vous pouvez le régénérer."
|
||||
regenerate-token: "Regenerer le token"
|
||||
token: "Jeton :"
|
||||
enter-password: "Veuillez entrer le mot de passe"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "Aucune application autorisée"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "Maximum"
|
||||
in-use: "en cours d’utilisation"
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "Aucun utilisateurs mis en sourdine"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "M."
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "Votre profil"
|
||||
drive: "Drive"
|
||||
favorites: "Favorites"
|
||||
lists: "Listes"
|
||||
follow-requests: "Demandes de suivi"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "Fermer"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "Tableau de bord"
|
||||
drive: "Drive"
|
||||
users: "Utilisateur·rice·s"
|
||||
update: "Mises à jour"
|
||||
announcements: "お知らせ"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "Afficher d'autres"
|
||||
no-one: "Personne"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "Drive"
|
||||
used: "utilisé"
|
||||
folder-count: "Dossier(s)"
|
||||
count-separator: ", "
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "Messages"
|
||||
follow-requests: "Demandes d'abonnement"
|
||||
search: "Rechercher"
|
||||
drive: "Drive"
|
||||
favorites: "Favoris"
|
||||
user-lists: "Listes"
|
||||
widgets: "Modules"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "Listes"
|
||||
enter-list-name: "Nom de la liste"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "Drive"
|
||||
more: "Afficher plus ..."
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "Votre compte est prêt ! 📦"
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "{}年前"
|
||||
month-and-day: "{month}月 {day}日"
|
||||
trash: "ゴミ箱"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "日"
|
||||
monday: "月"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "チャート"
|
||||
per-day: "1日ごと"
|
||||
per-hour: "1時間ごと"
|
||||
federation: "フェデレーション"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
drive: "ドライブ"
|
||||
network: "ネットワーク"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減 (統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "決定"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "使用中"
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
banner: "バナー"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "名前を変更"
|
||||
rename-folder: "フォルダ名の変更"
|
||||
input-new-folder-name: "新しいフォルダ名を入力してください"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "検索"
|
||||
load-more: "もっと読み込む"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "通知"
|
||||
apps: "アプリ"
|
||||
mute: "ミュート"
|
||||
drive: "ドライブ"
|
||||
security: "セキュリティ"
|
||||
signin: "サインイン履歴"
|
||||
password: "パスワード"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "設定が完了しました!"
|
||||
failed: "設定に失敗しました。トークンに誤りがないかご確認ください。"
|
||||
info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。"
|
||||
desktop/views/components/settings.api.vue:
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "連携しているアプリケーションはありません"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "中"
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "ミュートしているユーザーはいません"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "さん"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "プロフィール"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
lists: "リスト"
|
||||
follow-requests: "フォロー申請"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "閉じる"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "ユーザー"
|
||||
update: "更新"
|
||||
announcements: "お知らせ"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "他を見る"
|
||||
no-one: "いません!"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "ドライブ"
|
||||
used: "使用中"
|
||||
folder-count: "フォルダ"
|
||||
count-separator: "、"
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "メッセージ"
|
||||
follow-requests: "フォロー申請"
|
||||
search: "検索"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
user-lists: "リスト"
|
||||
widgets: "ウィジェット"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "リスト"
|
||||
enter-list-name: "リスト名を入力してください"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "ドライブ"
|
||||
more: "もっと見る"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めましょう"
|
||||
|
||||
@@ -64,6 +64,7 @@ common:
|
||||
month-and-day: "{month}月 {day}日"
|
||||
|
||||
trash: "ゴミ箱"
|
||||
drive: "ドライブ"
|
||||
|
||||
weekday-short:
|
||||
sunday: "日"
|
||||
@@ -601,11 +602,14 @@ desktop/views/components/charts.vue:
|
||||
title: "チャート"
|
||||
per-day: "1日ごと"
|
||||
per-hour: "1時間ごと"
|
||||
federation: "フェデレーション"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
drive: "ドライブ"
|
||||
network: "ネットワーク"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減 (統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -639,7 +643,6 @@ desktop/views/components/crop-window.vue:
|
||||
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "使用中"
|
||||
drive: "ドライブ"
|
||||
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
@@ -672,9 +675,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename-folder: "フォルダ名の変更"
|
||||
input-new-folder-name: "新しいフォルダ名を入力してください"
|
||||
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "ドライブ"
|
||||
|
||||
desktop/views/components/drive.vue:
|
||||
search: "検索"
|
||||
load-more: "もっと読み込む"
|
||||
@@ -833,7 +833,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "通知"
|
||||
apps: "アプリ"
|
||||
mute: "ミュート"
|
||||
drive: "ドライブ"
|
||||
security: "セキュリティ"
|
||||
signin: "サインイン履歴"
|
||||
password: "パスワード"
|
||||
@@ -951,20 +950,28 @@ desktop/views/components/settings.2fa.vue:
|
||||
failed: "設定に失敗しました。トークンに誤りがないかご確認ください。"
|
||||
info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。"
|
||||
|
||||
desktop/views/components/settings.api.vue:
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "連携しているアプリケーションはありません"
|
||||
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "中"
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "ミュートしているユーザーはいません"
|
||||
@@ -1005,7 +1012,6 @@ desktop/views/components/ui.header.vue:
|
||||
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "プロフィール"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
lists: "リスト"
|
||||
follow-requests: "フォロー申請"
|
||||
@@ -1060,7 +1066,6 @@ desktop/views/components/window.vue:
|
||||
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "ユーザー"
|
||||
update: "更新"
|
||||
announcements: "お知らせ"
|
||||
@@ -1248,7 +1253,6 @@ desktop/views/widgets/users.vue:
|
||||
no-one: "いません!"
|
||||
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "ドライブ"
|
||||
used: "使用中"
|
||||
folder-count: "フォルダ"
|
||||
count-separator: "、"
|
||||
@@ -1372,7 +1376,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "メッセージ"
|
||||
follow-requests: "フォロー申請"
|
||||
search: "検索"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
user-lists: "リスト"
|
||||
widgets: "ウィジェット"
|
||||
@@ -1400,7 +1403,6 @@ mobile/views/pages/user-lists.vue:
|
||||
enter-list-name: "リスト名を入力してください"
|
||||
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "ドライブ"
|
||||
more: "もっと見る"
|
||||
|
||||
mobile/views/pages/signup.vue:
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "{}年前"
|
||||
month-and-day: "{month}月 {day}日"
|
||||
trash: "ゴミ箱"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "日"
|
||||
monday: "月"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "チャート"
|
||||
per-day: "1日ごと"
|
||||
per-hour: "1時間ごと"
|
||||
federation: "フェデレーション"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
drive: "ドライブ"
|
||||
network: "ネットワーク"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減(統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "そうする"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "使うとる"
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
banner: "バナー"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "名前を変えるで"
|
||||
rename-folder: "フォルダ名を変えるで"
|
||||
input-new-folder-name: "新しいフォルダ名を入力してや"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "検索"
|
||||
load-more: "もっとあらへんのか!"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "通知"
|
||||
apps: "アプリ"
|
||||
mute: "ミュート"
|
||||
drive: "ドライブ"
|
||||
security: "守護神セキュリティ"
|
||||
signin: "こんな感じでサインインしたらしいで"
|
||||
password: "パスワード"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "設定が完了したで!"
|
||||
failed: "なんか設定に失敗したで。トークンを間違えとらんか確認してや。"
|
||||
info: "次のサインインからは、パスワードに加えてデバイスに出とるトークンを入力してな。"
|
||||
desktop/views/components/settings.api.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」っちゅうキーでパラメータに付加してリクエストしてや。"
|
||||
caution: "アカウントを不正利用されるかも知れんから、このトークンは第三者に教えたらあかんで(アプリなどにも入力しんといてな)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたとかその可能性があったらトークンを再生成できるで。"
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "トークン:"
|
||||
enter-password: "パスワードを入力してや"
|
||||
token: "Token:"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "連携しているアプリケーションはあらへんで"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "中"
|
||||
in-use: "使用中"
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使うとる"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "ミュートしているユーザーはおらんで"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "はん"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "プロフィール"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
lists: "リスト"
|
||||
follow-requests: "フォロー許してくれや!言うてみる"
|
||||
@@ -936,10 +943,9 @@ desktop/views/components/window.vue:
|
||||
close: "さいなら"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "ユーザー"
|
||||
update: "更新"
|
||||
announcements: "お知らせ"
|
||||
announcements: "知っといてや"
|
||||
hashtags: "ハッシュタグ"
|
||||
desktop/views/pages/admin/admin.dashboard.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
@@ -968,7 +974,7 @@ desktop/views/pages/admin/admin.unverify-user.vue:
|
||||
unverify: "公式アカウントにはさせへんで"
|
||||
unverified: "公式アカウントを解除したで"
|
||||
desktop/views/pages/admin/admin.announcements.vue:
|
||||
announcements: "お知らせ"
|
||||
announcements: "知っといてや"
|
||||
desktop/views/pages/admin/admin.hashtags.vue:
|
||||
hided-tags: "Hidden Tags"
|
||||
desktop/views/pages/deck/deck.tl-column.vue:
|
||||
@@ -980,10 +986,10 @@ desktop/views/pages/deck/deck.user-column.vue:
|
||||
following: "フォロー"
|
||||
followers: "フォロワー"
|
||||
images: "画像"
|
||||
activity: "アクティビティ"
|
||||
activity: "やっとること"
|
||||
timeline: "タイムライン"
|
||||
pinned-notes: "ピン留めされた投稿"
|
||||
push-to-a-list: "リストに追加"
|
||||
pinned-notes: "ピン留めしはった投稿"
|
||||
push-to-a-list: "リストに入れたる"
|
||||
desktop/views/pages/stats/stats.vue:
|
||||
all-users: "全てのユーザー"
|
||||
original-users: "ここの人らだけ"
|
||||
@@ -1036,7 +1042,7 @@ desktop/views/pages/user/user.friends.vue:
|
||||
no-users: "よう話すツレは居らん"
|
||||
desktop/views/pages/user/user.vue:
|
||||
is-suspended: "このユーザーはあかんわ。凍結されとる。"
|
||||
last-used-at: "最終アクセス"
|
||||
last-used-at: "最後いつ来はった?"
|
||||
desktop/views/pages/user/user.photos.vue:
|
||||
title: "写真"
|
||||
loading: "読み込んどります"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "他を見る"
|
||||
no-one: "おらん!"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "ドライブ"
|
||||
used: "使うとる"
|
||||
folder-count: "フォルダ"
|
||||
count-separator: "、"
|
||||
@@ -1119,8 +1124,8 @@ mobile/views/components/drive.file-detail.vue:
|
||||
hash: "ハッシュ(md5)"
|
||||
exif: "EXIF"
|
||||
nsfw: "ちょっと見せられへんわ"
|
||||
mark-as-sensitive: "閲覧注意に設定"
|
||||
unmark-as-sensitive: "閲覧注意を解除"
|
||||
mark-as-sensitive: "見たらあかん感じにしとく"
|
||||
unmark-as-sensitive: "やっぱ見せたるわ"
|
||||
mobile/views/components/media-image.vue:
|
||||
sensitive: "見たらあかんで"
|
||||
click-to-show: "押してみ、見せたるわ"
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "メッセージ"
|
||||
follow-requests: "フォロー許してくれや!言うてみる"
|
||||
search: "検索"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
user-lists: "リスト"
|
||||
widgets: "ウィジェット"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "リスト"
|
||||
enter-list-name: "リスト名を入力してや"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "ドライブ"
|
||||
more: "もっとあるやろ!"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めようや"
|
||||
@@ -1316,7 +1319,7 @@ mobile/views/pages/settings.vue:
|
||||
signout: "さいなら"
|
||||
sound: "サウンド"
|
||||
enable-sounds: "サウンド鳴らす"
|
||||
mark-as-read-all-unread-notes: "すべての投稿を既読にする"
|
||||
mark-as-read-all-unread-notes: "全部もう読んだわ"
|
||||
mobile/views/pages/user.vue:
|
||||
follows-you: "フォローされとるで"
|
||||
following: "フォロー"
|
||||
@@ -1373,27 +1376,27 @@ dev/views/index.vue:
|
||||
manage-apps: "アプリの管理"
|
||||
dev/views/apps.vue:
|
||||
manage-apps: "アプリを管理"
|
||||
create-app: "アプリ作成"
|
||||
app-missing: "アプリなし"
|
||||
create-app: "アプリ作る"
|
||||
app-missing: "アプリあらへん"
|
||||
dev/views/new-app.vue:
|
||||
create-app: "アプリケーションの作成"
|
||||
app-name: "アプリケーション名"
|
||||
app-name-desc: "あなたのアプリの名称。"
|
||||
app-name-ex: "ex) Misskey for iOS"
|
||||
app-overview: "アプリの概要"
|
||||
app-desc: "あなたのアプリの簡単な説明や紹介。"
|
||||
app-desc-ex: "ex) Misskey iOSクライアント。"
|
||||
callback-url: "コールバックURL (オプション)"
|
||||
callback-url-desc: "ユーザーが認証フォームで認証した際にリダイレクトするURLを設定できます。"
|
||||
create-app: "アプリケーション作る"
|
||||
app-name: "アプリケーションの名前"
|
||||
app-name-desc: "あんたのアプリの名前。"
|
||||
app-name-ex: "ex) 関西ミスキー保安協会"
|
||||
app-overview: "このアプリどんなん?"
|
||||
app-desc: "あんたのアプリどんなんか教えて"
|
||||
app-desc-ex: "ex) 関西人なら誰でも口ずさめるこのCMがついにMisskeyへ。"
|
||||
callback-url: "コールバックURL (無くてもええで)"
|
||||
callback-url-desc: "ユーザーが認証フォームで認証した後どこに連れてくかを設定できるで"
|
||||
authority: "権限"
|
||||
authority-desc: "ここで要求した機能だけがAPIからアクセスできます。"
|
||||
authority-warning: "アプリ作成後も変更できますが、新たな権限を付与する場合、その時点で関連付けられているユーザーキーはすべて無効になります。"
|
||||
account-read: "アカウントの情報を見る。"
|
||||
account-write: "アカウントの情報を操作する。"
|
||||
note-write: "投稿する。"
|
||||
reaction-write: "リアクションしたりリアクションをキャンセルする。"
|
||||
following-write: "フォローしたりフォロー解除する。"
|
||||
drive-read: "ドライブを見る。"
|
||||
drive-write: "ドライブを操作する。"
|
||||
notification-read: "通知を見る。"
|
||||
notification-write: "通知を操作する。"
|
||||
authority-desc: "ここにチェックした機能しかAPIからアクセスできひんから気ぃつけてな"
|
||||
authority-warning: "アプリ作った後でも変えれるけど、新しいやつ追加したらそん時関連付いてるユーザーキーは全部ほかされるで。"
|
||||
account-read: "アカウントの情報見せて"
|
||||
account-write: "アカウントの情報いじらせて"
|
||||
note-write: "投稿させて"
|
||||
reaction-write: "リアクションしたりそれをキャンセルさせて"
|
||||
following-write: "フォローとかフォロー解除させて"
|
||||
drive-read: "ドライブ見せて"
|
||||
drive-write: "ドライブいじらせて"
|
||||
notification-read: "通知見せて"
|
||||
notification-write: "通知いじらせて"
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "{}년전"
|
||||
month-and-day: "{month}월 {day}일"
|
||||
trash: "휴지통"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "일"
|
||||
monday: "월"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "チャート"
|
||||
per-day: "1日ごと"
|
||||
per-hour: "1時間ごと"
|
||||
federation: "フェデレーション"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
drive: "ドライブ"
|
||||
network: "ネットワーク"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減 (統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "決定"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "使用中"
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
banner: "バナー"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "名前を変更"
|
||||
rename-folder: "フォルダ名の変更"
|
||||
input-new-folder-name: "新しいフォルダ名を入力してください"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "検索"
|
||||
load-more: "もっと読み込む"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "通知"
|
||||
apps: "アプリ"
|
||||
mute: "ミュート"
|
||||
drive: "ドライブ"
|
||||
security: "セキュリティ"
|
||||
signin: "サインイン履歴"
|
||||
password: "パスワード"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "設定が完了しました!"
|
||||
failed: "設定に失敗しました。トークンに誤りがないかご確認ください。"
|
||||
info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。"
|
||||
desktop/views/components/settings.api.vue:
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "連携しているアプリケーションはありません"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "中"
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "ミュートしているユーザーはいません"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "さん"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "プロフィール"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
lists: "リスト"
|
||||
follow-requests: "フォロー申請"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "閉じる"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "ユーザー"
|
||||
update: "更新"
|
||||
announcements: "お知らせ"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "他を見る"
|
||||
no-one: "いません!"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "ドライブ"
|
||||
used: "使用中"
|
||||
folder-count: "フォルダ"
|
||||
count-separator: "、"
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "メッセージ"
|
||||
follow-requests: "フォロー申請"
|
||||
search: "検索"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
user-lists: "リスト"
|
||||
widgets: "ウィジェット"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "リスト"
|
||||
enter-list-name: "リスト名を入力してください"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "ドライブ"
|
||||
more: "もっと見る"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めましょう"
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "{}jaar geleden"
|
||||
month-and-day: "{month}月 {day}日"
|
||||
trash: "ゴミ箱"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "Z"
|
||||
monday: "M"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "チャート"
|
||||
per-day: "1日ごと"
|
||||
per-hour: "1時間ごと"
|
||||
federation: "フェデレーション"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
drive: "ドライブ"
|
||||
network: "ネットワーク"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減 (統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "Oké"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "gebruikt"
|
||||
drive: "Drive"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "Gebruikersafbeelding"
|
||||
banner: "Omslagfoto"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "Naam wijzigen"
|
||||
rename-folder: "Mapnaam wijzigen"
|
||||
input-new-folder-name: "Voer een nieuwe naam in"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "Drive"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "Zoeken"
|
||||
load-more: "Meer laden"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "Melding"
|
||||
apps: "Apps"
|
||||
mute: "Dempen"
|
||||
drive: "Drive"
|
||||
security: "Beveiliging"
|
||||
signin: "Inloggeschiedenis"
|
||||
password: "Wachtwoord"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "Instellen voltooid!"
|
||||
failed: "Instellen mislukt. Zorg ervoor dat de sleutel juist is."
|
||||
info: "Vanaf nu moet je ook de op je apparaat getoonde sleutel tonen bij het inloggen op Misskey."
|
||||
desktop/views/components/settings.api.vue:
|
||||
intro: "Als je toegang wilt tot de API, stel deze sleutel dan in als 'i' bij de verzoekparameters."
|
||||
caution: "Laat deze sleutel niet zien aan derde partijen (en voer hem nergens anders in dan hier), anders kan je account gehackt worden."
|
||||
regeneration-of-token: "Mocht deze sleutel tóch uitlekken, dan kun je hem opnieuw genereren."
|
||||
regenerate-token: "Sleutel opnieuw genereren"
|
||||
token: "Sleutel:"
|
||||
enter-password: "Voer je wachtwoord in"
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "連携しているアプリケーションはありません"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "中"
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "Geen gedempte gebruikers"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "さん"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "Je profiel"
|
||||
drive: "Drive"
|
||||
favorites: "Favorieten"
|
||||
lists: "Lijsten"
|
||||
follow-requests: "フォロー申請"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "Sluiten"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "ユーザー"
|
||||
update: "更新"
|
||||
announcements: "お知らせ"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "Anderen tonen"
|
||||
no-one: "Niemand"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "Drive"
|
||||
used: "gebruikt"
|
||||
folder-count: "Map(pen)"
|
||||
count-separator: ", "
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "Gesprekken"
|
||||
follow-requests: "フォロー申請"
|
||||
search: "Zoeken"
|
||||
drive: "Drive"
|
||||
favorites: "お気に入り"
|
||||
user-lists: "リスト"
|
||||
widgets: "ウィジェット"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "リスト"
|
||||
enter-list-name: "リスト名を入力してください"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "Drive"
|
||||
more: "もっと見る"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めましょう"
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "{} år siden"
|
||||
month-and-day: "{day}/{month}"
|
||||
trash: "Papirkurv"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "S"
|
||||
monday: "M"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "Diagrammer"
|
||||
per-day: "per dag"
|
||||
per-hour: "1時間ごと"
|
||||
federation: "フェデレーション"
|
||||
notes: "Innlegg"
|
||||
users: "Brukere"
|
||||
drive: "Disk"
|
||||
network: "ネットワーク"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減 (統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "Ok"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "brukt"
|
||||
drive: "Disk"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "Avatar"
|
||||
banner: "Banner"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "Endre navn"
|
||||
rename-folder: "フォルダ名の変更"
|
||||
input-new-folder-name: "新しいフォルダ名を入力してください"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "Disk"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "Søk"
|
||||
load-more: "もっと読み込む"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "Notifikasjon"
|
||||
apps: "Apper"
|
||||
mute: "Demp"
|
||||
drive: "Disk"
|
||||
security: "セキュリティ"
|
||||
signin: "サインイン履歴"
|
||||
password: "Passord"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "設定が完了しました!"
|
||||
failed: "設定に失敗しました。トークンに誤りがないかご確認ください。"
|
||||
info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。"
|
||||
desktop/views/components/settings.api.vue:
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "連携しているアプリケーションはありません"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "Maks"
|
||||
in-use: "I bruk"
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "ミュートしているユーザーはいません"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "-san"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "プロフィール"
|
||||
drive: "Disk"
|
||||
favorites: "Favoritter"
|
||||
lists: "Lister"
|
||||
follow-requests: "フォロー申請"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "Lukk"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "Disk"
|
||||
users: "Brukere"
|
||||
update: "Oppdater"
|
||||
announcements: "お知らせ"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "Oppdater"
|
||||
no-one: "Ingen"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "Disk"
|
||||
used: "brukt"
|
||||
folder-count: "Mappe(r)"
|
||||
count-separator: ","
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "Meldinger"
|
||||
follow-requests: "フォロー申請"
|
||||
search: "Søk"
|
||||
drive: "Disk"
|
||||
favorites: "Favoritter"
|
||||
user-lists: "Lister"
|
||||
widgets: "ウィジェット"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "Lister"
|
||||
enter-list-name: "リスト名を入力してください"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "Disk"
|
||||
more: "Vis mer"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めましょう"
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "{} lat temu"
|
||||
month-and-day: "{month}-{day}"
|
||||
trash: "Kosz"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "N"
|
||||
monday: "Pn"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "チャート"
|
||||
per-day: "1日ごと"
|
||||
per-hour: "1時間ごと"
|
||||
federation: "フェデレーション"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
drive: "ドライブ"
|
||||
network: "ネットワーク"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減 (統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "OK"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "wykorzystane"
|
||||
drive: "Dysk"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "Awatar"
|
||||
banner: "Baner"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "Zmień nazwę"
|
||||
rename-folder: "Zmień nazwę katalogu"
|
||||
input-new-folder-name: "Wprowadź nową nazwę"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "Dysk"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "Szukaj"
|
||||
load-more: "Załaduj więcej"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "Powiadomienia"
|
||||
apps: "Aplikacje"
|
||||
mute: "Wyciszanie"
|
||||
drive: "Dysk"
|
||||
security: "Bezpieczeństwo"
|
||||
signin: "Historia logowań"
|
||||
password: "Hasło"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "Pomyślnie ukończono konfigurację!"
|
||||
failed: "Nie udało się skonfigurować uwierzytelniania dwuetapowego, upewnij się że wprowadziłeś prawidłowy token."
|
||||
info: "Od teraz, wprowadzaj token wyświetlany na urządzeniu przy każdym logowaniu do Misskey."
|
||||
desktop/views/components/settings.api.vue:
|
||||
intro: "Aby uzyskać dostęp do API, ustaw ten token jako klucz 'i' parametrów żądań."
|
||||
caution: "Nie pokazuj tego tokenu osobom trzecim (nie wprowadzaj go nigdzie indziej), aby konto nie trafiło w niepowołane ręce."
|
||||
regeneration-of-token: "W przypadku wycieku tokenu, możesz wygenerować nowy."
|
||||
regenerate-token: "Wygeneruj nowy token"
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "Wprowadź hasło"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "Brak zautoryzowanych aplikacji"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "Maksymalnie"
|
||||
in-use: " w użyciu."
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "Brak wyciszonych użytkowników"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "さん"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "Twój profil"
|
||||
drive: "Dysk"
|
||||
favorites: "Ulubione"
|
||||
lists: "Listy"
|
||||
follow-requests: "Prośby o śledzenie"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "Zamknij"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "ユーザー"
|
||||
update: "更新"
|
||||
announcements: "お知らせ"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "Pokaż innych"
|
||||
no-one: "Pusto"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "Dysk"
|
||||
used: "użyto"
|
||||
folder-count: "Katalog(i)"
|
||||
count-separator: ", "
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "Wiadomości"
|
||||
follow-requests: "Prośby o śledzenie"
|
||||
search: "Szukaj"
|
||||
drive: "Dysk"
|
||||
favorites: "Ulubione"
|
||||
user-lists: "Listy"
|
||||
widgets: "Widżety"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "Listy"
|
||||
enter-list-name: "Wprowadź nazwę listy"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "Dysk"
|
||||
more: "Załaduj więcej"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "Rozpocznijmy! 📦"
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "{} ano(s) atrás"
|
||||
month-and-day: "{day}/{month}"
|
||||
trash: "Lixo"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "Dom"
|
||||
monday: "Seg"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "チャート"
|
||||
per-day: "1日ごと"
|
||||
per-hour: "1時間ごと"
|
||||
federation: "フェデレーション"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
drive: "ドライブ"
|
||||
network: "ネットワーク"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減 (統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "決定"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "使用中"
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
banner: "バナー"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "名前を変更"
|
||||
rename-folder: "フォルダ名の変更"
|
||||
input-new-folder-name: "新しいフォルダ名を入力してください"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "検索"
|
||||
load-more: "もっと読み込む"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "通知"
|
||||
apps: "アプリ"
|
||||
mute: "ミュート"
|
||||
drive: "ドライブ"
|
||||
security: "セキュリティ"
|
||||
signin: "サインイン履歴"
|
||||
password: "パスワード"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "設定が完了しました!"
|
||||
failed: "設定に失敗しました。トークンに誤りがないかご確認ください。"
|
||||
info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。"
|
||||
desktop/views/components/settings.api.vue:
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "連携しているアプリケーションはありません"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "中"
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "ミュートしているユーザーはいません"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "さん"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "プロフィール"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
lists: "リスト"
|
||||
follow-requests: "フォロー申請"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "閉じる"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "Usuários"
|
||||
update: "Actualizações"
|
||||
announcements: "お知らせ"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "他を見る"
|
||||
no-one: "いません!"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "ドライブ"
|
||||
used: "使用中"
|
||||
folder-count: "フォルダ"
|
||||
count-separator: "、"
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "メッセージ"
|
||||
follow-requests: "フォロー申請"
|
||||
search: "検索"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
user-lists: "リスト"
|
||||
widgets: "ウィジェット"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "リスト"
|
||||
enter-list-name: "リスト名を入力してください"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "ドライブ"
|
||||
more: "もっと見る"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めましょう"
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "{}年前"
|
||||
month-and-day: "{month}月 {day}日"
|
||||
trash: "ゴミ箱"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "日"
|
||||
monday: "月"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "チャート"
|
||||
per-day: "1日ごと"
|
||||
per-hour: "1時間ごと"
|
||||
federation: "フェデレーション"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
drive: "ドライブ"
|
||||
network: "ネットワーク"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減 (統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "決定"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "使用中"
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
banner: "バナー"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "名前を変更"
|
||||
rename-folder: "フォルダ名の変更"
|
||||
input-new-folder-name: "新しいフォルダ名を入力してください"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "検索"
|
||||
load-more: "もっと読み込む"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "通知"
|
||||
apps: "アプリ"
|
||||
mute: "ミュート"
|
||||
drive: "ドライブ"
|
||||
security: "セキュリティ"
|
||||
signin: "サインイン履歴"
|
||||
password: "パスワード"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "設定が完了しました!"
|
||||
failed: "設定に失敗しました。トークンに誤りがないかご確認ください。"
|
||||
info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。"
|
||||
desktop/views/components/settings.api.vue:
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "連携しているアプリケーションはありません"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "中"
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "ミュートしているユーザーはいません"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "さん"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "プロフィール"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
lists: "リスト"
|
||||
follow-requests: "フォロー申請"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "閉じる"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "ユーザー"
|
||||
update: "更新"
|
||||
announcements: "お知らせ"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "他を見る"
|
||||
no-one: "いません!"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "ドライブ"
|
||||
used: "使用中"
|
||||
folder-count: "フォルダ"
|
||||
count-separator: "、"
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "メッセージ"
|
||||
follow-requests: "フォロー申請"
|
||||
search: "検索"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
user-lists: "リスト"
|
||||
widgets: "ウィジェット"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "リスト"
|
||||
enter-list-name: "リスト名を入力してください"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "ドライブ"
|
||||
more: "もっと見る"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めましょう"
|
||||
|
||||
@@ -62,6 +62,7 @@ common:
|
||||
years_ago: "{}年前"
|
||||
month-and-day: "{month}月 {day}日"
|
||||
trash: "ゴミ箱"
|
||||
drive: "ドライブ"
|
||||
weekday-short:
|
||||
sunday: "日"
|
||||
monday: "月"
|
||||
@@ -541,11 +542,14 @@ desktop/views/components/charts.vue:
|
||||
title: "チャート"
|
||||
per-day: "1日ごと"
|
||||
per-hour: "1時間ごと"
|
||||
federation: "フェデレーション"
|
||||
notes: "投稿"
|
||||
users: "ユーザー"
|
||||
drive: "ドライブ"
|
||||
network: "ネットワーク"
|
||||
charts:
|
||||
federation-instances: "インスタンスの増減"
|
||||
federation-instances-total: "インスタンスの積算"
|
||||
notes: "投稿の増減 (統合)"
|
||||
local-notes: "投稿の増減 (ローカル)"
|
||||
remote-notes: "投稿の増減 (リモート)"
|
||||
@@ -575,7 +579,6 @@ desktop/views/components/crop-window.vue:
|
||||
ok: "決定"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "使用中"
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
banner: "バナー"
|
||||
@@ -605,8 +608,6 @@ desktop/views/components/drive.folder.vue:
|
||||
rename: "名前を変更"
|
||||
rename-folder: "フォルダ名の変更"
|
||||
input-new-folder-name: "新しいフォルダ名を入力してください"
|
||||
desktop/views/components/drive.nav-folder.vue:
|
||||
drive: "ドライブ"
|
||||
desktop/views/components/drive.vue:
|
||||
search: "検索"
|
||||
load-more: "もっと読み込む"
|
||||
@@ -741,7 +742,6 @@ desktop/views/components/settings.vue:
|
||||
notification: "通知"
|
||||
apps: "アプリ"
|
||||
mute: "ミュート"
|
||||
drive: "ドライブ"
|
||||
security: "セキュリティ"
|
||||
signin: "サインイン履歴"
|
||||
password: "パスワード"
|
||||
@@ -847,18 +847,26 @@ desktop/views/components/settings.2fa.vue:
|
||||
success: "設定が完了しました!"
|
||||
failed: "設定に失敗しました。トークンに誤りがないかご確認ください。"
|
||||
info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。"
|
||||
desktop/views/components/settings.api.vue:
|
||||
common/views/components/api-settings.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regenerate-token: "トークンを再生成"
|
||||
token: "Token:"
|
||||
enter-password: "パスワードを入力してください"
|
||||
console:
|
||||
title: 'APIコンソール'
|
||||
endpoint: 'エンドポイント'
|
||||
parameter: 'パラメータ'
|
||||
send: '送信'
|
||||
sending: '応答待ち'
|
||||
response: '結果'
|
||||
desktop/views/components/settings.apps.vue:
|
||||
no-apps: "連携しているアプリケーションはありません"
|
||||
desktop/views/components/settings.drive.vue:
|
||||
max: "中"
|
||||
common/views/components/drive-settings.vue:
|
||||
max: "容量"
|
||||
in-use: "使用中"
|
||||
stats: "統計"
|
||||
desktop/views/components/settings.mute.vue:
|
||||
no-users: "ミュートしているユーザーはいません"
|
||||
desktop/views/components/settings.password.vue:
|
||||
@@ -892,7 +900,6 @@ desktop/views/components/ui.header.vue:
|
||||
adjective: "さん"
|
||||
desktop/views/components/ui.header.account.vue:
|
||||
profile: "プロフィール"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
lists: "リスト"
|
||||
follow-requests: "フォロー申請"
|
||||
@@ -936,7 +943,6 @@ desktop/views/components/window.vue:
|
||||
close: "閉じる"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "ユーザー"
|
||||
update: "更新"
|
||||
announcements: "お知らせ"
|
||||
@@ -1089,7 +1095,6 @@ desktop/views/widgets/users.vue:
|
||||
refresh: "他を見る"
|
||||
no-one: "いません!"
|
||||
mobile/views/components/drive.vue:
|
||||
drive: "ドライブ"
|
||||
used: "使用中"
|
||||
folder-count: "フォルダ"
|
||||
count-separator: "、"
|
||||
@@ -1193,7 +1198,6 @@ mobile/views/components/ui.nav.vue:
|
||||
messaging: "メッセージ"
|
||||
follow-requests: "フォロー申請"
|
||||
search: "検索"
|
||||
drive: "ドライブ"
|
||||
favorites: "お気に入り"
|
||||
user-lists: "リスト"
|
||||
widgets: "ウィジェット"
|
||||
@@ -1216,7 +1220,6 @@ mobile/views/pages/user-lists.vue:
|
||||
title: "リスト"
|
||||
enter-list-name: "リスト名を入力してください"
|
||||
mobile/views/pages/drive.vue:
|
||||
drive: "ドライブ"
|
||||
more: "もっと見る"
|
||||
mobile/views/pages/signup.vue:
|
||||
lets-start: "📦 始めましょう"
|
||||
|
||||
17352
package-lock.json
generated
Normal file
17352
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
package.json
24
package.json
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <i@syuilo.com>",
|
||||
"version": "10.30.3",
|
||||
"clientVersion": "1.0.11045",
|
||||
"version": "10.33.0",
|
||||
"clientVersion": "1.0.11172",
|
||||
"codename": "nighthike",
|
||||
"main": "./built/index.js",
|
||||
"private": true,
|
||||
@@ -58,7 +58,7 @@
|
||||
"@types/koa__cors": "2.2.3",
|
||||
"@types/minio": "7.0.0",
|
||||
"@types/mkdirp": "0.5.2",
|
||||
"@types/mocha": "5.2.3",
|
||||
"@types/mocha": "5.2.5",
|
||||
"@types/mongodb": "3.1.12",
|
||||
"@types/ms": "0.7.30",
|
||||
"@types/node": "10.12.0",
|
||||
@@ -84,7 +84,7 @@
|
||||
"@types/websocket": "0.0.40",
|
||||
"@types/ws": "6.0.1",
|
||||
"animejs": "2.2.0",
|
||||
"apexcharts": "2.1.5",
|
||||
"apexcharts": "2.1.6",
|
||||
"autobind-decorator": "2.1.0",
|
||||
"autosize": "4.0.2",
|
||||
"autwh": "0.1.0",
|
||||
@@ -104,15 +104,13 @@
|
||||
"deep-equal": "1.0.1",
|
||||
"deepcopy": "0.6.3",
|
||||
"diskusage": "0.2.5",
|
||||
"dompurify": "1.0.5",
|
||||
"double-ended-queue": "2.1.0-0",
|
||||
"elasticsearch": "15.1.1",
|
||||
"emojilib": "2.3.0",
|
||||
"escape-regexp": "0.0.1",
|
||||
"eslint": "5.0.1",
|
||||
"eslint": "5.7.0",
|
||||
"eslint-plugin-vue": "4.7.1",
|
||||
"eventemitter3": "3.1.0",
|
||||
"exif-js": "2.3.0",
|
||||
"file-loader": "2.0.0",
|
||||
"file-type": "10.1.0",
|
||||
"fuckadblock": "3.2.1",
|
||||
@@ -131,8 +129,7 @@
|
||||
"gulp-uglify": "3.0.1",
|
||||
"gulp-util": "3.0.8",
|
||||
"hard-source-webpack-plugin": "0.12.0",
|
||||
"highlight.js": "9.12.0",
|
||||
"html-minifier": "3.5.20",
|
||||
"html-minifier": "3.5.21",
|
||||
"http-signature": "1.2.0",
|
||||
"insert-text-at-cursor": "0.1.1",
|
||||
"is-root": "2.0.0",
|
||||
@@ -141,7 +138,7 @@
|
||||
"jsdom": "12.2.0",
|
||||
"json5": "2.1.0",
|
||||
"json5-loader": "1.0.1",
|
||||
"koa": "2.5.1",
|
||||
"koa": "2.6.1",
|
||||
"koa-bodyparser": "4.2.1",
|
||||
"koa-compress": "3.0.0",
|
||||
"koa-favicon": "2.0.1",
|
||||
@@ -154,7 +151,6 @@
|
||||
"koa-slow": "2.1.0",
|
||||
"koa-views": "6.1.4",
|
||||
"loader-utils": "1.1.0",
|
||||
"lodash.assign": "4.2.0",
|
||||
"mecab-async": "0.1.2",
|
||||
"merge-options": "1.0.1",
|
||||
"minio": "7.0.1",
|
||||
@@ -205,10 +201,10 @@
|
||||
"textarea-caret": "3.1.0",
|
||||
"tinycolor2": "1.4.1",
|
||||
"tmp": "0.0.33",
|
||||
"ts-loader": "4.4.1",
|
||||
"ts-loader": "5.2.2",
|
||||
"ts-node": "7.0.1",
|
||||
"tslint": "5.10.0",
|
||||
"typescript": "2.9.2",
|
||||
"typescript": "3.1.3",
|
||||
"typescript-eslint-parser": "20.0.0",
|
||||
"uglify-es": "3.3.9",
|
||||
"url-loader": "1.1.2",
|
||||
@@ -233,7 +229,7 @@
|
||||
"vuex-persistedstate": "2.5.4",
|
||||
"web-push": "3.3.3",
|
||||
"webfinger.js": "2.6.6",
|
||||
"webpack": "4.22.0",
|
||||
"webpack": "4.23.1",
|
||||
"webpack-cli": "3.1.2",
|
||||
"websocket": "1.0.28",
|
||||
"ws": "6.1.0",
|
||||
|
||||
66
src/chart/federation.ts
Normal file
66
src/chart/federation.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import autobind from 'autobind-decorator';
|
||||
import Chart, { Obj } from '.';
|
||||
import Instance from '../models/instance';
|
||||
|
||||
/**
|
||||
* フェデレーションに関するチャート
|
||||
*/
|
||||
type FederationLog = {
|
||||
instance: {
|
||||
/**
|
||||
* インスタンス数の合計
|
||||
*/
|
||||
total: number;
|
||||
|
||||
/**
|
||||
* 増加インスタンス数
|
||||
*/
|
||||
inc: number;
|
||||
|
||||
/**
|
||||
* 減少インスタンス数
|
||||
*/
|
||||
dec: number;
|
||||
};
|
||||
};
|
||||
|
||||
class FederationChart extends Chart<FederationLog> {
|
||||
constructor() {
|
||||
super('federation');
|
||||
}
|
||||
|
||||
@autobind
|
||||
protected async getTemplate(init: boolean, latest?: FederationLog): Promise<FederationLog> {
|
||||
const [total] = init ? await Promise.all([
|
||||
Instance.count({})
|
||||
]) : [
|
||||
latest ? latest.instance.total : 0
|
||||
];
|
||||
|
||||
return {
|
||||
instance: {
|
||||
total: total,
|
||||
inc: 0,
|
||||
dec: 0
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@autobind
|
||||
public async update(isAdditional: boolean) {
|
||||
const update: Obj = {};
|
||||
|
||||
update.total = isAdditional ? 1 : -1;
|
||||
if (isAdditional) {
|
||||
update.inc = 1;
|
||||
} else {
|
||||
update.dec = 1;
|
||||
}
|
||||
|
||||
await this.inc({
|
||||
instance: update
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new FederationChart();
|
||||
@@ -20,7 +20,6 @@ type ArrayValue<T> = {
|
||||
|
||||
type Span = 'day' | 'hour';
|
||||
|
||||
//#region Chart Core
|
||||
type Log<T extends Obj> = {
|
||||
_id: mongo.ObjectID;
|
||||
|
||||
@@ -87,13 +86,33 @@ export default abstract class Chart<T> {
|
||||
}
|
||||
|
||||
@autobind
|
||||
private async getCurrentLog(span: Span, group?: any): Promise<Log<T>> {
|
||||
private getCurrentDate(): [number, number, number, number] {
|
||||
const now = new Date();
|
||||
|
||||
const y = now.getFullYear();
|
||||
const m = now.getMonth();
|
||||
const d = now.getDate();
|
||||
const h = now.getHours();
|
||||
|
||||
return [y, m, d, h];
|
||||
}
|
||||
|
||||
@autobind
|
||||
private getLatestLog(span: Span, group?: any): Promise<Log<T>> {
|
||||
return this.collection.findOne({
|
||||
group: group,
|
||||
span: span
|
||||
}, {
|
||||
sort: {
|
||||
date: -1
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
private async getCurrentLog(span: Span, group?: any): Promise<Log<T>> {
|
||||
const [y, m, d, h] = this.getCurrentDate();
|
||||
|
||||
const current =
|
||||
span == 'day' ? new Date(y, m, d) :
|
||||
span == 'hour' ? new Date(y, m, d, h) :
|
||||
@@ -106,53 +125,55 @@ export default abstract class Chart<T> {
|
||||
date: current
|
||||
});
|
||||
|
||||
if (currentLog) {
|
||||
// ログがあればそれを返して終了
|
||||
if (currentLog != null) {
|
||||
return currentLog;
|
||||
}
|
||||
|
||||
let log: Log<T>;
|
||||
let data: T;
|
||||
|
||||
// 集計期間が変わってから、初めてのチャート更新なら
|
||||
// 最も最近のログを持ってくる
|
||||
// * 例えば集計期間が「日」である場合で考えると、
|
||||
// * 昨日何もチャートを更新するような出来事がなかった場合は、
|
||||
// * ログがそもそも作られずドキュメントが存在しないということがあり得るため、
|
||||
// * 「昨日の」と決め打ちせずに「もっとも最近の」とします
|
||||
const latest = await this.collection.findOne({
|
||||
group: group,
|
||||
span: span
|
||||
}, {
|
||||
sort: {
|
||||
date: -1
|
||||
}
|
||||
});
|
||||
const latest = await this.getLatestLog(span, group);
|
||||
|
||||
if (latest) {
|
||||
// 現在のログを初期挿入
|
||||
const data = await this.getTemplate(false, latest.data);
|
||||
|
||||
const log = await this.collection.insert({
|
||||
group: group,
|
||||
span: span,
|
||||
date: current,
|
||||
data: data
|
||||
});
|
||||
|
||||
return log;
|
||||
if (latest != null) {
|
||||
// 空ログデータを作成
|
||||
data = await this.getTemplate(false, latest.data);
|
||||
} else {
|
||||
// ログが存在しなかったら
|
||||
// * Misskeyインスタンスを建てて初めてのチャート更新時など
|
||||
// (Misskeyインスタンスを建てて初めてのチャート更新時など
|
||||
// または何らかの理由でチャートコレクションを抹消した場合)
|
||||
|
||||
// 空のログを作成
|
||||
const data = await this.getTemplate(true, null, group);
|
||||
// 初期ログデータを作成
|
||||
data = await this.getTemplate(true, null, group);
|
||||
}
|
||||
|
||||
const log = await this.collection.insert({
|
||||
try {
|
||||
// 新規ログ挿入
|
||||
log = await this.collection.insert({
|
||||
group: group,
|
||||
span: span,
|
||||
date: current,
|
||||
data: data
|
||||
});
|
||||
|
||||
return log;
|
||||
} catch (e) {
|
||||
// 11000 is duplicate key error
|
||||
// 並列動作している他のチャートエンジンプロセスと処理が重なる場合がある
|
||||
// その場合は再度最も新しいログを持ってくる
|
||||
if (e.code === 11000) {
|
||||
log = await this.getLatestLog(span, group);
|
||||
} else {
|
||||
console.error(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
@autobind
|
||||
@@ -173,6 +194,7 @@ export default abstract class Chart<T> {
|
||||
};
|
||||
}
|
||||
|
||||
// ログ更新
|
||||
this.collection.update({
|
||||
_id: log._id
|
||||
}, query);
|
||||
@@ -200,16 +222,14 @@ export default abstract class Chart<T> {
|
||||
public async getChart(span: Span, range: number, group?: any): Promise<ArrayValue<T>> {
|
||||
const promisedChart: Promise<T>[] = [];
|
||||
|
||||
const now = new Date();
|
||||
const y = now.getFullYear();
|
||||
const m = now.getMonth();
|
||||
const d = now.getDate();
|
||||
const h = now.getHours();
|
||||
const [y, m, d, h] = this.getCurrentDate();
|
||||
|
||||
const gt =
|
||||
span == 'day' ? new Date(y, m, d - range) :
|
||||
span == 'hour' ? new Date(y, m, d, h - range) : null;
|
||||
span == 'hour' ? new Date(y, m, d, h - range) :
|
||||
null;
|
||||
|
||||
// ログ取得
|
||||
const logs = await this.collection.find({
|
||||
group: group,
|
||||
span: span,
|
||||
@@ -225,6 +245,7 @@ export default abstract class Chart<T> {
|
||||
}
|
||||
});
|
||||
|
||||
// 整形
|
||||
for (let i = (range - 1); i >= 0; i--) {
|
||||
const current =
|
||||
span == 'day' ? new Date(y, m, d - i) :
|
||||
@@ -235,7 +256,8 @@ export default abstract class Chart<T> {
|
||||
|
||||
if (log) {
|
||||
promisedChart.unshift(Promise.resolve(log.data));
|
||||
} else { // 隙間埋め
|
||||
} else {
|
||||
// 隙間埋め
|
||||
const latest = logs.find(l => l.date.getTime() < current.getTime());
|
||||
promisedChart.unshift(this.getTemplate(false, latest ? latest.data : null));
|
||||
}
|
||||
@@ -282,4 +304,3 @@ export default abstract class Chart<T> {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
72
src/client/app/common/views/components/api-settings.vue
Normal file
72
src/client/app/common/views/components/api-settings.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<ui-card>
|
||||
<div slot="title">%fa:key% API</div>
|
||||
|
||||
<section class="fit-top">
|
||||
<ui-input :value="$store.state.i.token" readonly>
|
||||
<span>%i18n:@token%</span>
|
||||
</ui-input>
|
||||
<p>%i18n:@intro%</p>
|
||||
<ui-info warn>%i18n:@caution%</ui-info>
|
||||
<p>%i18n:@regeneration-of-token%</p>
|
||||
<ui-button @click="regenerateToken">%fa:sync-alt% %i18n:@regenerate-token%</ui-button>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<header>%fa:terminal% %i18n:@console.title%</header>
|
||||
<ui-input v-model="endpoint">
|
||||
<span>%i18n:@console.endpoint%</span>
|
||||
</ui-input>
|
||||
<ui-textarea v-model="body">
|
||||
<span>%i18n:@console.parameter% (JSON or JSON5)</span>
|
||||
</ui-textarea>
|
||||
<ui-button @click="send" :disabled="sending">
|
||||
<template v-if="sending">%i18n:@console.sending%</template>
|
||||
<template v-else>%fa:paper-plane% %i18n:@console.send%</template>
|
||||
</ui-button>
|
||||
<ui-textarea v-if="res" v-model="res" readonly tall>
|
||||
<span>%i18n:@console.response%</span>
|
||||
</ui-textarea>
|
||||
</section>
|
||||
</ui-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import * as JSON5 from 'json5';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
return {
|
||||
endpoint: '',
|
||||
body: '{}',
|
||||
res: null,
|
||||
sending: false
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
regenerateToken() {
|
||||
(this as any).apis.input({
|
||||
title: '%i18n:@enter-password%',
|
||||
type: 'password'
|
||||
}).then(password => {
|
||||
(this as any).api('i/regenerate_token', {
|
||||
password: password
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
send() {
|
||||
this.sending = true;
|
||||
(this as any).api(this.endpoint, JSON5.parse(this.body)).then(res => {
|
||||
this.sending = false;
|
||||
this.res = JSON5.stringify(res, null, 2);
|
||||
}, err => {
|
||||
this.sending = false;
|
||||
this.res = JSON5.stringify(err, null, 2);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
171
src/client/app/common/views/components/drive-settings.vue
Normal file
171
src/client/app/common/views/components/drive-settings.vue
Normal file
@@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<ui-card>
|
||||
<div slot="title">%fa:cloud% %i18n:common.drive%</div>
|
||||
|
||||
<section v-if="!fetching" class="juakhbxthdewydyreaphkepoxgxvfogn">
|
||||
<div class="meter"><div :style="meterStyle"></div></div>
|
||||
<p>%i18n:@max%: <b>{{ capacity | bytes }}</b> %i18n:@in-use%: <b>{{ usage | bytes }}</b></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<header>%i18n:@stats%</header>
|
||||
<div ref="chart" style="margin-bottom: -16px; color: #000;"></div>
|
||||
</section>
|
||||
</ui-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import * as tinycolor from 'tinycolor2';
|
||||
import * as ApexCharts from 'apexcharts';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
return {
|
||||
fetching: true,
|
||||
usage: null,
|
||||
capacity: null
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
meterStyle(): any {
|
||||
return {
|
||||
width: `${this.usage / this.capacity * 100}%`,
|
||||
background: tinycolor({
|
||||
h: 180 - (this.usage / this.capacity * 180),
|
||||
s: 0.7,
|
||||
l: 0.5
|
||||
})
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
(this as any).api('drive').then(info => {
|
||||
this.capacity = info.capacity;
|
||||
this.usage = info.usage;
|
||||
this.fetching = false;
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.renderChart();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
renderChart() {
|
||||
(this as any).api('charts/user/drive', {
|
||||
userId: this.$store.state.i.id,
|
||||
span: 'day',
|
||||
limit: 21
|
||||
}).then(stats => {
|
||||
const addition = [];
|
||||
const deletion = [];
|
||||
|
||||
const now = new Date();
|
||||
const y = now.getFullYear();
|
||||
const m = now.getMonth();
|
||||
const d = now.getDate();
|
||||
|
||||
for (let i = 0; i < 21; i++) {
|
||||
const x = new Date(y, m, d - i);
|
||||
addition.push([
|
||||
x,
|
||||
stats.incSize[i]
|
||||
]);
|
||||
deletion.push([
|
||||
x,
|
||||
-stats.decSize[i]
|
||||
]);
|
||||
}
|
||||
|
||||
const chart = new ApexCharts(this.$refs.chart, {
|
||||
chart: {
|
||||
type: 'bar',
|
||||
stacked: true,
|
||||
height: 150,
|
||||
zoom: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
columnWidth: '90%',
|
||||
endingShape: 'rounded'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
clipMarkers: false,
|
||||
borderColor: 'rgba(0, 0, 0, 0.1)'
|
||||
},
|
||||
tooltip: {
|
||||
shared: true,
|
||||
intersect: false
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
},
|
||||
series: [{
|
||||
name: 'Additions',
|
||||
data: addition
|
||||
}, {
|
||||
name: 'Deletions',
|
||||
data: deletion
|
||||
}],
|
||||
xaxis: {
|
||||
type: 'datetime',
|
||||
labels: {
|
||||
style: {
|
||||
colors: tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--text')).toRgbString()
|
||||
}
|
||||
},
|
||||
axisBorder: {
|
||||
color: 'rgba(0, 0, 0, 0.1)'
|
||||
},
|
||||
axisTicks: {
|
||||
color: 'rgba(0, 0, 0, 0.1)'
|
||||
},
|
||||
crosshairs: {
|
||||
width: 1,
|
||||
opacity: 1
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
formatter: v => Vue.filter('bytes')(v, 0),
|
||||
style: {
|
||||
color: tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--text')).toRgbString()
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
chart.render();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.juakhbxthdewydyreaphkepoxgxvfogn
|
||||
> .meter
|
||||
$size = 12px
|
||||
|
||||
margin-bottom 16px
|
||||
background rgba(0, 0, 0, 0.1)
|
||||
border-radius ($size / 2)
|
||||
overflow hidden
|
||||
|
||||
> div
|
||||
height $size
|
||||
border-radius ($size / 2)
|
||||
|
||||
> p
|
||||
margin 0
|
||||
|
||||
</style>
|
||||
@@ -1,5 +1,7 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
import apiSettings from './api-settings.vue';
|
||||
import driveSettings from './drive-settings.vue';
|
||||
import profileEditor from './profile-editor.vue';
|
||||
import noteSkeleton from './note-skeleton.vue';
|
||||
import theme from './theme.vue';
|
||||
@@ -43,9 +45,12 @@ import uiTextarea from './ui/textarea.vue';
|
||||
import uiSwitch from './ui/switch.vue';
|
||||
import uiRadio from './ui/radio.vue';
|
||||
import uiSelect from './ui/select.vue';
|
||||
import uiInfo from './ui/info.vue';
|
||||
import formButton from './ui/form/button.vue';
|
||||
import formRadio from './ui/form/radio.vue';
|
||||
|
||||
Vue.component('mk-api-settings', apiSettings);
|
||||
Vue.component('mk-drive-settings', driveSettings);
|
||||
Vue.component('mk-profile-editor', profileEditor);
|
||||
Vue.component('mk-note-skeleton', noteSkeleton);
|
||||
Vue.component('mk-theme', theme);
|
||||
@@ -89,5 +94,6 @@ Vue.component('ui-textarea', uiTextarea);
|
||||
Vue.component('ui-switch', uiSwitch);
|
||||
Vue.component('ui-radio', uiRadio);
|
||||
Vue.component('ui-select', uiSelect);
|
||||
Vue.component('ui-info', uiInfo);
|
||||
Vue.component('form-button', formButton);
|
||||
Vue.component('form-radio', formRadio);
|
||||
|
||||
33
src/client/app/common/views/components/ui/info.vue
Normal file
33
src/client/app/common/views/components/ui/info.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<div class="ymxyweixqwsxauxldgpvecjepnwxbylu" :class="{ warn }">
|
||||
<i v-if="warn">%fa:exclamation-triangle%</i>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
warn: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.ymxyweixqwsxauxldgpvecjepnwxbylu
|
||||
margin 16px 0
|
||||
padding 16px
|
||||
font-size 90%
|
||||
|
||||
> i
|
||||
margin-right 4px
|
||||
|
||||
&.warn
|
||||
background var(--infoWarnBg)
|
||||
color var(--infoWarnFg)
|
||||
</style>
|
||||
@@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div class="ui-textarea" :class="{ focused, filled }">
|
||||
<div class="ui-textarea" :class="{ focused, filled, tall }">
|
||||
<div class="input">
|
||||
<span class="label" ref="label"><slot></slot></span>
|
||||
<textarea ref="input"
|
||||
:value="value"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
:pattern="pattern"
|
||||
:autocomplete="autocomplete"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false">
|
||||
</textarea>
|
||||
:value="value"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
:pattern="pattern"
|
||||
:autocomplete="autocomplete"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
></textarea>
|
||||
</div>
|
||||
<div class="text"><slot name="text"></slot></div>
|
||||
</div>
|
||||
@@ -41,7 +41,12 @@ export default Vue.extend({
|
||||
autocomplete: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
tall: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -66,6 +71,9 @@ export default Vue.extend({
|
||||
root(fill)
|
||||
margin 42px 0 32px 0
|
||||
|
||||
&:last-child
|
||||
margin-bottom 0
|
||||
|
||||
> .input
|
||||
padding 12px
|
||||
|
||||
@@ -157,6 +165,11 @@ root(fill)
|
||||
left 0 !important
|
||||
transform scale(0.75)
|
||||
|
||||
&.tall
|
||||
> .input
|
||||
> textarea
|
||||
min-height 200px
|
||||
|
||||
.ui-textarea.fill
|
||||
root(true)
|
||||
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
<header>
|
||||
<b>%i18n:@title%:</b>
|
||||
<select v-model="chartType">
|
||||
<optgroup label="%i18n:@federation%">
|
||||
<option value="federation-instances">%i18n:@charts.federation-instances%</option>
|
||||
<option value="federation-instances-total">%i18n:@charts.federation-instances-total%</option>
|
||||
</optgroup>
|
||||
<optgroup label="%i18n:@users%">
|
||||
<option value="users">%i18n:@charts.users%</option>
|
||||
<option value="users-total">%i18n:@charts.users-total%</option>
|
||||
@@ -79,6 +83,8 @@ export default Vue.extend({
|
||||
data(): any {
|
||||
if (this.chart == null) return null;
|
||||
switch (this.chartType) {
|
||||
case 'federation-instances': return this.federationInstancesChart(false);
|
||||
case 'federation-instances-total': return this.federationInstancesChart(true);
|
||||
case 'users': return this.usersChart(false);
|
||||
case 'users-total': return this.usersChart(true);
|
||||
case 'notes': return this.notesChart('combined');
|
||||
@@ -109,11 +115,13 @@ export default Vue.extend({
|
||||
this.now = new Date();
|
||||
|
||||
const [perHour, perDay] = await Promise.all([Promise.all([
|
||||
(this as any).api('charts/federation', { limit: limit, span: 'hour' }),
|
||||
(this as any).api('charts/users', { limit: limit, span: 'hour' }),
|
||||
(this as any).api('charts/notes', { limit: limit, span: 'hour' }),
|
||||
(this as any).api('charts/drive', { limit: limit, span: 'hour' }),
|
||||
(this as any).api('charts/network', { limit: limit, span: 'hour' })
|
||||
]), Promise.all([
|
||||
(this as any).api('charts/federation', { limit: limit, span: 'day' }),
|
||||
(this as any).api('charts/users', { limit: limit, span: 'day' }),
|
||||
(this as any).api('charts/notes', { limit: limit, span: 'day' }),
|
||||
(this as any).api('charts/drive', { limit: limit, span: 'day' }),
|
||||
@@ -122,16 +130,18 @@ export default Vue.extend({
|
||||
|
||||
const chart = {
|
||||
perHour: {
|
||||
users: perHour[0],
|
||||
notes: perHour[1],
|
||||
drive: perHour[2],
|
||||
network: perHour[3]
|
||||
federation: perHour[0],
|
||||
users: perHour[1],
|
||||
notes: perHour[2],
|
||||
drive: perHour[3],
|
||||
network: perHour[4]
|
||||
},
|
||||
perDay: {
|
||||
users: perDay[0],
|
||||
notes: perDay[1],
|
||||
drive: perDay[2],
|
||||
network: perDay[3]
|
||||
federation: perDay[0],
|
||||
users: perDay[1],
|
||||
notes: perDay[2],
|
||||
drive: perDay[3],
|
||||
network: perDay[4]
|
||||
}
|
||||
};
|
||||
|
||||
@@ -156,6 +166,23 @@ export default Vue.extend({
|
||||
return arr.map((v, i) => ({ t: this.getDate(i).getTime(), y: v }));
|
||||
},
|
||||
|
||||
federationInstancesChart(total: boolean): any {
|
||||
return [{
|
||||
datasets: [{
|
||||
label: 'Instances',
|
||||
fill: true,
|
||||
backgroundColor: rgba(colors.localPlus),
|
||||
borderColor: colors.localPlus,
|
||||
borderWidth: 2,
|
||||
pointBackgroundColor: '#fff',
|
||||
lineTension: 0,
|
||||
data: this.format(total
|
||||
? this.stats.federation.instance.total
|
||||
: sum(this.stats.federation.instance.inc, negate(this.stats.federation.instance.dec)))
|
||||
}]
|
||||
}];
|
||||
},
|
||||
|
||||
notesChart(type: string): any {
|
||||
return [{
|
||||
datasets: [{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<mk-window ref="window" @closed="destroyDom" width="800px" height="500px" :popout-url="popout">
|
||||
<template slot="header">
|
||||
<p v-if="usage" :class="$style.info"><b>{{ usage.toFixed(1) }}%</b> %i18n:@used%</p>
|
||||
<span :class="$style.title">%fa:cloud%%i18n:@drive%</span>
|
||||
<span :class="$style.title">%fa:cloud%%i18n:common.drive%</span>
|
||||
</template>
|
||||
<mk-drive :class="$style.browser" multiple :init-folder="folder" ref="browser"/>
|
||||
</mk-window>
|
||||
|
||||
@@ -67,12 +67,12 @@ export default Vue.extend({
|
||||
text: '%i18n:@contextmenu.rename%',
|
||||
icon: '%fa:i-cursor%',
|
||||
action: this.rename
|
||||
}/*, null, {
|
||||
}, null, {
|
||||
type: 'item',
|
||||
text: '%i18n:common.delete%',
|
||||
icon: '%fa:R trash-alt%',
|
||||
action: this.deleteFolder
|
||||
}*/], {
|
||||
}], {
|
||||
closed: () => {
|
||||
this.isContextmenuShowing = false;
|
||||
}
|
||||
@@ -207,7 +207,9 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
deleteFolder() {
|
||||
alert('not implemented yet');
|
||||
(this as any).api('drive/folders/delete', {
|
||||
folderId: this.folder.id
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
@drop.stop="onDrop"
|
||||
>
|
||||
<template v-if="folder == null">%fa:cloud%</template>
|
||||
<span>{{ folder == null ? '%i18n:@drive%' : folder.name }}</span>
|
||||
<span>{{ folder == null ? '%i18n:common.drive%' : folder.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ export default Vue.extend({
|
||||
hierarchyFolders: [],
|
||||
selectedFiles: [],
|
||||
uploadings: [],
|
||||
connection: null
|
||||
connection: null,
|
||||
|
||||
/**
|
||||
* ドロップされようとしているか
|
||||
@@ -122,6 +122,7 @@ export default Vue.extend({
|
||||
this.connection.on('fileDeleted', this.onStreamDriveFileDeleted);
|
||||
this.connection.on('folderCreated', this.onStreamDriveFolderCreated);
|
||||
this.connection.on('folderUpdated', this.onStreamDriveFolderUpdated);
|
||||
this.connection.on('folderDeleted', this.onStreamDriveFolderDeleted);
|
||||
|
||||
if (this.initFolder) {
|
||||
this.move(this.initFolder);
|
||||
@@ -182,6 +183,10 @@ export default Vue.extend({
|
||||
}
|
||||
},
|
||||
|
||||
onStreamDriveFolderDeleted(folderId) {
|
||||
this.removeFolder(folderId);
|
||||
},
|
||||
|
||||
onChangeUploaderUploads(uploads) {
|
||||
this.uploadings = uploads;
|
||||
},
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<span v-if="visibility === 'specified'">%fa:envelope%</span>
|
||||
<span v-if="visibility === 'private'">%fa:lock%</span>
|
||||
</button>
|
||||
<p class="text-count" :class="{ over: this.trimmedLength(text) > 1000 }">{{ 1000 - this.trimmedLength(text) }}</p>
|
||||
<p class="text-count" :class="{ over: this.trimmedLength(text) > this.maxNoteTextLength }">{{ this.maxNoteTextLength - this.trimmedLength(text) }}</p>
|
||||
<button :class="{ posting }" class="submit" :disabled="!canPost" @click="post">
|
||||
{{ posting ? '%i18n:@posting%' : submitText }}<mk-ellipsis v-if="posting"/>
|
||||
</button>
|
||||
@@ -107,10 +107,17 @@ export default Vue.extend({
|
||||
visibleUsers: [],
|
||||
autocomplete: null,
|
||||
draghover: false,
|
||||
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]')
|
||||
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'),
|
||||
maxNoteTextLength: 1000
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
(this as any).os.getMeta().then(meta => {
|
||||
this.maxNoteTextLength = meta.maxNoteTextLength;
|
||||
});
|
||||
},
|
||||
|
||||
computed: {
|
||||
draftId(): string {
|
||||
return this.renote
|
||||
@@ -149,7 +156,7 @@ export default Vue.extend({
|
||||
canPost(): boolean {
|
||||
return !this.posting &&
|
||||
(1 <= this.text.length || 1 <= this.files.length || this.poll || this.renote) &&
|
||||
(length(this.text.trim()) <= 1000);
|
||||
(length(this.text.trim()) <= this.maxNoteTextLength);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="2fa">
|
||||
<p>%i18n:@intro%<a href="%i18n:@url%" target="_blank">%i18n:@detail%</a></p>
|
||||
<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:@caution%</p></div>
|
||||
<p style="margin-top:0;">%i18n:@intro%<a href="%i18n:@url%" target="_blank">%i18n:@detail%</a></p>
|
||||
<ui-info warn>%i18n:@caution%</ui-info>
|
||||
<p v-if="!data && !$store.state.i.twoFactorEnabled"><ui-button @click="register">%i18n:@register%</ui-button></p>
|
||||
<template v-if="$store.state.i.twoFactorEnabled">
|
||||
<p>%i18n:@already-registered%</p>
|
||||
@@ -72,9 +72,3 @@ export default Vue.extend({
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.2fa
|
||||
color #4a535a
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
<template>
|
||||
<div class="root api">
|
||||
<ui-input :value="$store.state.i.token" readonly>
|
||||
<span>%i18n:@token%</span>
|
||||
</ui-input>
|
||||
<p>%i18n:@intro%</p>
|
||||
<div class="ui info warn"><p>%fa:exclamation-triangle%%i18n:@caution%</p></div>
|
||||
<p>%i18n:@regeneration-of-token%</p>
|
||||
<ui-button @click="regenerateToken">%i18n:@regenerate-token%</ui-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
methods: {
|
||||
regenerateToken() {
|
||||
(this as any).apis.input({
|
||||
title: '%i18n:@enter-password%',
|
||||
type: 'password'
|
||||
}).then(password => {
|
||||
(this as any).api('i/regenerate_token', {
|
||||
password: password
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.root.api
|
||||
code
|
||||
display inline-block
|
||||
padding 4px 6px
|
||||
color #555
|
||||
background #eee
|
||||
border-radius 2px
|
||||
</style>
|
||||
@@ -1,34 +0,0 @@
|
||||
<template>
|
||||
<div class="root">
|
||||
<template v-if="!fetching">
|
||||
<p><b>{{ capacity | bytes }}</b>%i18n:@max%<b>{{ usage | bytes }}</b>%i18n:@in-use%</p>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
return {
|
||||
fetching: true,
|
||||
usage: null,
|
||||
capacity: null
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
(this as any).api('drive').then(info => {
|
||||
this.capacity = info.capacity;
|
||||
this.usage = info.usage;
|
||||
this.fetching = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.root
|
||||
> p
|
||||
> b
|
||||
margin 0 8px
|
||||
</style>
|
||||
@@ -5,7 +5,7 @@
|
||||
<p :class="{ active: page == 'theme' }" @mousedown="page = 'theme'">%fa:palette .fw%%i18n:@theme%</p>
|
||||
<p :class="{ active: page == 'web' }" @mousedown="page = 'web'">%fa:desktop .fw%Web</p>
|
||||
<p :class="{ active: page == 'notification' }" @mousedown="page = 'notification'">%fa:R bell .fw%%i18n:@notification%</p>
|
||||
<p :class="{ active: page == 'drive' }" @mousedown="page = 'drive'">%fa:cloud .fw%%i18n:@drive%</p>
|
||||
<p :class="{ active: page == 'drive' }" @mousedown="page = 'drive'">%fa:cloud .fw%%i18n:common.drive%</p>
|
||||
<p :class="{ active: page == 'hashtags' }" @mousedown="page = 'hashtags'">%fa:hashtag .fw%%i18n:@tags%</p>
|
||||
<p :class="{ active: page == 'mute' }" @mousedown="page = 'mute'">%fa:ban .fw%%i18n:@mute%</p>
|
||||
<p :class="{ active: page == 'apps' }" @mousedown="page = 'apps'">%fa:puzzle-piece .fw%%i18n:@apps%</p>
|
||||
@@ -189,12 +189,9 @@
|
||||
</section>
|
||||
</ui-card>
|
||||
|
||||
<ui-card class="drive" v-show="page == 'drive'">
|
||||
<div slot="title">%fa:cloud% %i18n:@drive%</div>
|
||||
<section>
|
||||
<x-drive/>
|
||||
</section>
|
||||
</ui-card>
|
||||
<div class="drive" v-if="page == 'drive'">
|
||||
<mk-drive-settings/>
|
||||
</div>
|
||||
|
||||
<ui-card class="hashtags" v-show="page == 'hashtags'">
|
||||
<div slot="title">%fa:hashtag% %i18n:@tags%</div>
|
||||
@@ -238,12 +235,9 @@
|
||||
</section>
|
||||
</ui-card>
|
||||
|
||||
<ui-card class="api" v-show="page == 'api'">
|
||||
<div slot="title">%fa:key% API</div>
|
||||
<section class="fit-top">
|
||||
<x-api/>
|
||||
</section>
|
||||
</ui-card>
|
||||
<div class="api" v-show="page == 'api'">
|
||||
<mk-api-settings/>
|
||||
</div>
|
||||
|
||||
<ui-card class="other" v-show="page == 'other'">
|
||||
<div slot="title">%fa:info-circle% %i18n:@about%</div>
|
||||
@@ -298,10 +292,8 @@ import Vue from 'vue';
|
||||
import XMute from './settings.mute.vue';
|
||||
import XPassword from './settings.password.vue';
|
||||
import X2fa from './settings.2fa.vue';
|
||||
import XApi from './settings.api.vue';
|
||||
import XApps from './settings.apps.vue';
|
||||
import XSignins from './settings.signins.vue';
|
||||
import XDrive from './settings.drive.vue';
|
||||
import XTags from './settings.tags.vue';
|
||||
import { url, langs, version } from '../../../config';
|
||||
import checkForUpdate from '../../../common/scripts/check-for-update';
|
||||
@@ -311,10 +303,8 @@ export default Vue.extend({
|
||||
XMute,
|
||||
XPassword,
|
||||
X2fa,
|
||||
XApi,
|
||||
XApps,
|
||||
XSignins,
|
||||
XDrive,
|
||||
XTags
|
||||
},
|
||||
props: {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<router-link :to="`/@${ $store.state.i.username }`">%fa:user%<span>%i18n:@profile%</span>%fa:angle-right%</router-link>
|
||||
</li>
|
||||
<li @click="drive">
|
||||
<p>%fa:cloud%<span>%i18n:@drive%</span>%fa:angle-right%</p>
|
||||
<p>%fa:cloud%<span>%i18n:common.drive%</span>%fa:angle-right%</p>
|
||||
</li>
|
||||
<li>
|
||||
<router-link to="/i/favorites">%fa:star%<span>%i18n:@favorites%</span>%fa:angle-right%</router-link>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<li v-if="this.$store.state.i && this.$store.state.i.isAdmin"
|
||||
@click="nav('hashtags')" :class="{ active: page == 'hashtags' }">%fa:hashtag .fw%%i18n:@hashtags%</li>
|
||||
|
||||
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:@drive%</li> -->
|
||||
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:common.drive%</li> -->
|
||||
<!-- <li @click="nav('update')" :class="{ active: page == 'update' }">%i18n:@update%</li> -->
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
@@ -159,8 +159,8 @@ export default Vue.extend({
|
||||
}
|
||||
//#endregion
|
||||
|
||||
// タブが非表示またはスクロール位置が最上部ではないならタイトルで通知
|
||||
if (document.hidden || !this.isScrollTop()) {
|
||||
// タブが非表示ならタイトルで通知
|
||||
if (document.hidden) {
|
||||
this.$store.commit('pushBehindNote', note);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
:src="file.url"
|
||||
:alt="file.name"
|
||||
:title="file.name"
|
||||
@load="onImageLoaded"
|
||||
:style="style">
|
||||
<template v-if="kind != 'image'">%fa:file%</template>
|
||||
<footer v-if="kind == 'image' && file.properties && file.properties.width && file.properties.height">
|
||||
@@ -46,14 +45,6 @@
|
||||
<ui-button @click="del">%fa:trash-alt R% %i18n:@delete%</ui-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="exif" v-show="exif">
|
||||
<div>
|
||||
<p>
|
||||
%fa:camera%%i18n:@exif%
|
||||
</p>
|
||||
<pre ref="exif" class="json">{{ exif ? JSON.stringify(exif, null, 2) : '' }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hash">
|
||||
<div>
|
||||
<p>
|
||||
@@ -67,8 +58,6 @@
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import * as EXIF from 'exif-js';
|
||||
import * as hljs from 'highlight.js';
|
||||
import { gcd } from '../../../../../prelude/math';
|
||||
|
||||
export default Vue.extend({
|
||||
@@ -139,15 +128,6 @@ export default Vue.extend({
|
||||
|
||||
showCreatedAt() {
|
||||
alert(new Date(this.file.createdAt).toLocaleString());
|
||||
},
|
||||
|
||||
onImageLoaded() {
|
||||
const self = this;
|
||||
EXIF.getData(this.$refs.img, function(this: any) {
|
||||
const allMetaData = EXIF.getAllTags(this);
|
||||
self.exif = allMetaData;
|
||||
hljs.highlightBlock(self.$refs.exif);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -256,34 +236,4 @@ export default Vue.extend({
|
||||
border-radius 2px
|
||||
background #f5f5f5
|
||||
|
||||
> .exif
|
||||
padding 14px
|
||||
border-top solid 1px var(--faceDivider)
|
||||
|
||||
> div
|
||||
max-width 500px
|
||||
margin 0 auto
|
||||
|
||||
> p
|
||||
display block
|
||||
margin 0
|
||||
padding 0
|
||||
color var(--text)
|
||||
font-size 0.9em
|
||||
|
||||
> [data-fa]
|
||||
margin-right 4px
|
||||
|
||||
> pre
|
||||
display block
|
||||
width 100%
|
||||
margin 6px 0 0 0
|
||||
padding 8px
|
||||
height 128px
|
||||
overflow auto
|
||||
font-size 0.9em
|
||||
border solid 1px #dfdfdf
|
||||
border-radius 2px
|
||||
background #f5f5f5
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="kmmwchoexgckptowjmjgfsygeltxfeqs">
|
||||
<nav ref="nav">
|
||||
<a @click.prevent="goRoot()" href="/i/drive">%fa:cloud%%i18n:@drive%</a>
|
||||
<a @click.prevent="goRoot()" href="/i/drive">%fa:cloud%%i18n:common.drive%</a>
|
||||
<template v-for="folder in hierarchyFolders">
|
||||
<span :key="folder.id + '>'">%fa:angle-right%</span>
|
||||
<a :key="folder.id" @click.prevent="cd(folder)" :href="`/i/drive/folder/${folder.id}`">{{ folder.name }}</a>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<header>
|
||||
<button class="cancel" @click="cancel">%fa:times%</button>
|
||||
<div>
|
||||
<span class="text-count" :class="{ over: trimmedLength(text) > 1000 }">{{ 1000 - trimmedLength(text) }}</span>
|
||||
<span class="text-count" :class="{ over: trimmedLength(text) > this.maxNoteTextLength }">{{ this.maxNoteTextLength - trimmedLength(text) }}</span>
|
||||
<span class="geo" v-if="geo">%fa:map-marker-alt%</span>
|
||||
<button class="submit" :disabled="!canPost" @click="post">{{ submitText }}</button>
|
||||
</div>
|
||||
@@ -102,10 +102,17 @@ export default Vue.extend({
|
||||
visibleUsers: [],
|
||||
useCw: false,
|
||||
cw: null,
|
||||
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]')
|
||||
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'),
|
||||
maxNoteTextLength: 1000
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
(this as any).os.getMeta().then(meta => {
|
||||
this.maxNoteTextLength = meta.maxNoteTextLength;
|
||||
});
|
||||
},
|
||||
|
||||
computed: {
|
||||
draftId(): string {
|
||||
return this.renote
|
||||
@@ -144,7 +151,7 @@ export default Vue.extend({
|
||||
canPost(): boolean {
|
||||
return !this.posting &&
|
||||
(1 <= this.text.length || 1 <= this.files.length || this.poll || this.renote) &&
|
||||
(this.text.trim().length <= 1000);
|
||||
(this.text.trim().length <= this.maxNoteTextLength);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<li><router-link to="/i/widgets" :data-active="$route.name == 'widgets'">%fa:R calendar-alt%%i18n:@widgets%%fa:angle-right%</router-link></li>
|
||||
<li><router-link to="/i/favorites" :data-active="$route.name == 'favorites'">%fa:star%%i18n:@favorites%%fa:angle-right%</router-link></li>
|
||||
<li><router-link to="/i/lists" :data-active="$route.name == 'user-lists'">%fa:list%%i18n:@user-lists%%fa:angle-right%</router-link></li>
|
||||
<li><router-link to="/i/drive" :data-active="$route.name == 'drive'">%fa:cloud%%i18n:@drive%%fa:angle-right%</router-link></li>
|
||||
<li><router-link to="/i/drive" :data-active="$route.name == 'drive'">%fa:cloud%%i18n:common.drive%%fa:angle-right%</router-link></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a @click="search">%fa:search%%i18n:@search%%fa:angle-right%</a></li>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<span slot="header">
|
||||
<template v-if="folder"><span style="margin-right:4px;">%fa:R folder-open%</span>{{ folder.name }}</template>
|
||||
<template v-if="file"><mk-file-type-icon data-icon :type="file.type" style="margin-right:4px;"/>{{ file.name }}</template>
|
||||
<template v-if="!folder && !file"><span style="margin-right:4px;">%fa:cloud%</span>%i18n:@drive%</template>
|
||||
<template v-if="!folder && !file"><span style="margin-right:4px;">%fa:cloud%</span>%i18n:common.drive%</template>
|
||||
</span>
|
||||
<template slot="func"><button @click="fn">%fa:ellipsis-h%</button></template>
|
||||
<mk-drive
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
<ui-switch v-model="iLikeSushi">%i18n:common.i-like-sushi%</ui-switch>
|
||||
<ui-switch v-model="disableAnimatedMfm">%i18n:common.disable-animated-mfm%</ui-switch>
|
||||
<ui-switch v-model="alwaysShowNsfw">%i18n:common.always-show-nsfw% (%i18n:common.this-setting-is-this-device-only%)</ui-switch>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<ui-switch v-model="games_reversi_showBoardLabels">%i18n:common.show-reversi-board-labels%</ui-switch>
|
||||
<ui-switch v-model="games_reversi_useContrastStones">%i18n:common.use-contrast-reversi-stones%</ui-switch>
|
||||
</section>
|
||||
@@ -80,6 +83,8 @@
|
||||
</section>
|
||||
</ui-card>
|
||||
|
||||
<mk-drive-settings/>
|
||||
|
||||
<ui-card>
|
||||
<div slot="title">%fa:volume-up% %i18n:@sound%</div>
|
||||
|
||||
@@ -118,6 +123,8 @@
|
||||
</section>
|
||||
</ui-card>
|
||||
|
||||
<mk-api-settings />
|
||||
|
||||
<ui-card>
|
||||
<div slot="title">%fa:sync-alt% %i18n:@update%</div>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
faceClearButtonHover: 'rgba(0, 0, 0, 0.1)',
|
||||
faceClearButtonActive: 'rgba(0, 0, 0, 0.2)',
|
||||
popupBg: ':lighten<5<$secondary',
|
||||
popupFg: '#d6dce2',
|
||||
popupFg: '$text',
|
||||
|
||||
subNoteBg: 'rgba(0, 0, 0, 0.18)',
|
||||
subNoteText: ':alpha<0.7<$text',
|
||||
@@ -131,6 +131,9 @@
|
||||
remoteInfoBg: '#42321c',
|
||||
remoteInfoFg: '#ffbd3e',
|
||||
|
||||
infoWarnBg: '#42321c',
|
||||
infoWarnFg: '#ffbd3e',
|
||||
|
||||
messagingRoomBg: '@bg',
|
||||
messagingRoomInfo: '#fff',
|
||||
messagingRoomDateDividerLine: 'rgba(255, 255, 255, 0.1)',
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
faceClearButtonHover: 'rgba(0, 0, 0, 0.025)',
|
||||
faceClearButtonActive: 'rgba(0, 0, 0, 0.05)',
|
||||
popupBg: ':lighten<5<$secondary',
|
||||
popupFg: '#586069',
|
||||
popupFg: '$text',
|
||||
|
||||
subNoteBg: 'rgba(0, 0, 0, 0.01)',
|
||||
subNoteText: ':alpha<0.7<$text',
|
||||
@@ -131,6 +131,9 @@
|
||||
remoteInfoBg: '#fff0db',
|
||||
remoteInfoFg: '#573c08',
|
||||
|
||||
infoWarnBg: '#fff0db',
|
||||
infoWarnFg: '#573c08',
|
||||
|
||||
messagingRoomBg: '#fff',
|
||||
messagingRoomInfo: '#000',
|
||||
messagingRoomDateDividerLine: 'rgba(0, 0, 0, 0.1)',
|
||||
|
||||
@@ -49,6 +49,8 @@ export default function load() {
|
||||
if (config.localDriveCapacityMb == null) config.localDriveCapacityMb = 256;
|
||||
if (config.remoteDriveCapacityMb == null) config.remoteDriveCapacityMb = 8;
|
||||
|
||||
if (config.maxNoteTextLength == null) config.maxNoteTextLength = 1000;
|
||||
|
||||
if (config.name == null) config.name = 'Misskey';
|
||||
|
||||
return Object.assign(config, mixin);
|
||||
|
||||
@@ -103,6 +103,8 @@ export type Source = {
|
||||
engine: string;
|
||||
timeout: number;
|
||||
};
|
||||
|
||||
maxNoteTextLength?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
35
src/models/instance.ts
Normal file
35
src/models/instance.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import * as mongo from 'mongodb';
|
||||
import db from '../db/mongodb';
|
||||
|
||||
const Instance = db.get<IInstance>('instances');
|
||||
Instance.createIndex('host', { unique: true });
|
||||
export default Instance;
|
||||
|
||||
export interface IInstance {
|
||||
_id: mongo.ObjectID;
|
||||
|
||||
/**
|
||||
* ホスト
|
||||
*/
|
||||
host: string;
|
||||
|
||||
/**
|
||||
* このインスタンスを捕捉した日時
|
||||
*/
|
||||
caughtAt: Date;
|
||||
|
||||
/**
|
||||
* このインスタンスのシステム (MastodonとかMisskeyとかPleromaとか)
|
||||
*/
|
||||
system: string;
|
||||
|
||||
/**
|
||||
* このインスタンスのユーザー数
|
||||
*/
|
||||
usersCount: number;
|
||||
|
||||
/**
|
||||
* このインスタンスから受け取った投稿数
|
||||
*/
|
||||
notesCount: number;
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import NoteReaction from './note-reaction';
|
||||
import Favorite, { deleteFavorite } from './favorite';
|
||||
import Notification, { deleteNotification } from './notification';
|
||||
import Following from './following';
|
||||
import config from '../config';
|
||||
|
||||
const Note = db.get<INote>('notes');
|
||||
Note.createIndex('uri', { sparse: true, unique: true });
|
||||
@@ -21,15 +22,15 @@ Note.createIndex('userId');
|
||||
Note.createIndex('mentions');
|
||||
Note.createIndex('visibleUserIds');
|
||||
Note.createIndex('tagsLower');
|
||||
Note.createIndex('_user.host');
|
||||
Note.createIndex('_files._id');
|
||||
Note.createIndex('_files.contentType');
|
||||
Note.createIndex({
|
||||
createdAt: -1
|
||||
});
|
||||
Note.createIndex({ createdAt: -1 });
|
||||
Note.createIndex({ score: -1 }, { sparse: true });
|
||||
export default Note;
|
||||
|
||||
export function isValidText(text: string): boolean {
|
||||
return length(text.trim()) <= 1000 && text.trim() != '';
|
||||
return length(text.trim()) <= config.maxNoteTextLength && text.trim() != '';
|
||||
}
|
||||
|
||||
export function isValidCw(text: string): boolean {
|
||||
@@ -84,8 +85,14 @@ export type INote = {
|
||||
heading: number;
|
||||
speed: number;
|
||||
};
|
||||
|
||||
uri: string;
|
||||
|
||||
/**
|
||||
* 人気の投稿度合いを表すスコア
|
||||
*/
|
||||
score: number;
|
||||
|
||||
// 非正規化
|
||||
_reply?: {
|
||||
userId: mongo.ObjectID;
|
||||
@@ -297,6 +304,7 @@ export const pack = async (
|
||||
delete _note.prev;
|
||||
delete _note.next;
|
||||
delete _note.tagsLower;
|
||||
delete _note.score;
|
||||
delete _note._user;
|
||||
delete _note._reply;
|
||||
delete _note._renote;
|
||||
|
||||
@@ -13,6 +13,8 @@ import htmlToMFM from '../../../mfm/html-to-mfm';
|
||||
import usersChart from '../../../chart/users';
|
||||
import { URL } from 'url';
|
||||
import { resolveNote } from './note';
|
||||
import registerInstance from '../../../services/register-instance';
|
||||
import Instance from '../../../models/instance';
|
||||
|
||||
const log = debug('misskey:activitypub');
|
||||
|
||||
@@ -173,6 +175,18 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<IU
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Register host
|
||||
registerInstance(host).then(i => {
|
||||
Instance.update({ _id: i._id }, {
|
||||
$inc: {
|
||||
usersCount: 1
|
||||
}
|
||||
});
|
||||
|
||||
// TODO
|
||||
//perInstanceChart.newUser();
|
||||
});
|
||||
|
||||
//#region Increment users count
|
||||
Meta.update({}, {
|
||||
$inc: {
|
||||
@@ -214,6 +228,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<IU
|
||||
//#endregion
|
||||
|
||||
await updateFeatured(user._id).catch(err => console.log(err));
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,15 @@ export default (endpoint: string, user: IUser, app: IApp, data: any, file?: any)
|
||||
console.warn(`SLOW API CALL DETECTED: ${ep.name} (${time}ms)`);
|
||||
}
|
||||
} catch (e) {
|
||||
rej(e);
|
||||
if (e.name == 'INVALID_PARAM') {
|
||||
rej({
|
||||
code: e.name,
|
||||
param: e.param,
|
||||
reason: e.message
|
||||
});
|
||||
} else {
|
||||
rej(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export const meta = {
|
||||
|
||||
export default (params: any) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
const stats = await driveChart.getChart(ps.span as any, ps.limit);
|
||||
|
||||
|
||||
33
src/server/api/endpoints/charts/federation.ts
Normal file
33
src/server/api/endpoints/charts/federation.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import $ from 'cafy';
|
||||
import getParams from '../../get-params';
|
||||
import federationChart from '../../../../chart/federation';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
'ja-JP': 'フェデレーションのチャートを取得します。'
|
||||
},
|
||||
|
||||
params: {
|
||||
span: $.str.or(['day', 'hour']).note({
|
||||
desc: {
|
||||
'ja-JP': '集計のスパン (day または hour)'
|
||||
}
|
||||
}),
|
||||
|
||||
limit: $.num.optional.range(1, 100).note({
|
||||
default: 30,
|
||||
desc: {
|
||||
'ja-JP': '最大数。例えば 30 を指定したとすると、スパンが"day"の場合は30日分のデータが、スパンが"hour"の場合は30時間分のデータが返ります。'
|
||||
}
|
||||
}),
|
||||
}
|
||||
};
|
||||
|
||||
export default (params: any) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
const stats = await federationChart.getChart(ps.span as any, ps.limit);
|
||||
|
||||
res(stats);
|
||||
});
|
||||
@@ -31,7 +31,7 @@ export const meta = {
|
||||
|
||||
export default (params: any) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
const stats = await hashtagChart.getChart(ps.span as any, ps.limit, ps.tag);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export const meta = {
|
||||
|
||||
export default (params: any) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
const stats = await networkChart.getChart(ps.span as any, ps.limit);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export const meta = {
|
||||
|
||||
export default (params: any) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
const stats = await notesChart.getChart(ps.span as any, ps.limit);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ export const meta = {
|
||||
|
||||
export default (params: any) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
const stats = await perUserDriveChart.getChart(ps.span as any, ps.limit, ps.userId);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ export const meta = {
|
||||
|
||||
export default (params: any) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
const stats = await perUserFollowingChart.getChart(ps.span as any, ps.limit, ps.userId);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ export const meta = {
|
||||
|
||||
export default (params: any) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
const stats = await perUserNotesChart.getChart(ps.span as any, ps.limit, ps.userId);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ export const meta = {
|
||||
|
||||
export default (params: any) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
const stats = await perUserReactionsChart.getChart(ps.span as any, ps.limit, ps.userId);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export const meta = {
|
||||
|
||||
export default (params: any) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
const stats = await usersChart.getChart(ps.span as any, ps.limit);
|
||||
|
||||
|
||||
@@ -2,8 +2,11 @@ import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
||||
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
|
||||
import { publishDriveStream } from '../../../../../stream';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
import getParams from '../../../get-params';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
|
||||
desc: {
|
||||
'ja-JP': 'ドライブのフォルダを作成します。',
|
||||
'en-US': 'Create a folder of drive.'
|
||||
@@ -11,25 +14,37 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-write'
|
||||
kind: 'drive-write',
|
||||
|
||||
params: {
|
||||
name: $.str.optional.pipe(isValidFolderName).note({
|
||||
default: 'Untitled',
|
||||
desc: {
|
||||
'ja-JP': 'フォルダ名',
|
||||
'en-US': 'Folder name'
|
||||
}
|
||||
}),
|
||||
|
||||
parentId: $.type(ID).optional.nullable.note({
|
||||
desc: {
|
||||
'ja-JP': '親フォルダID',
|
||||
'en-US': 'Parent folder ID'
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'name' parameter
|
||||
const [name = '無題のフォルダー', nameErr] = $.str.optional.pipe(isValidFolderName).get(params.name);
|
||||
if (nameErr) return rej('invalid name param');
|
||||
|
||||
// Get 'parentId' parameter
|
||||
const [parentId = null, parentIdErr] = $.type(ID).optional.nullable.get(params.parentId);
|
||||
if (parentIdErr) return rej('invalid parentId param');
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
// If the parent folder is specified
|
||||
let parent = null;
|
||||
if (parentId) {
|
||||
if (ps.parentId) {
|
||||
// Fetch parent folder
|
||||
parent = await DriveFolder
|
||||
.findOne({
|
||||
_id: parentId,
|
||||
_id: ps.parentId,
|
||||
userId: user._id
|
||||
});
|
||||
|
||||
@@ -41,7 +56,7 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||
// Create folder
|
||||
const folder = await DriveFolder.insert({
|
||||
createdAt: new Date(),
|
||||
name: name,
|
||||
name: ps.name,
|
||||
parentId: parent !== null ? parent._id : null,
|
||||
userId: user._id
|
||||
});
|
||||
|
||||
60
src/server/api/endpoints/drive/folders/delete.ts
Normal file
60
src/server/api/endpoints/drive/folders/delete.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
||||
import DriveFolder from '../../../../../models/drive-folder';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
import getParams from '../../../get-params';
|
||||
import { publishDriveStream } from '../../../../../stream';
|
||||
import DriveFile from '../../../../../models/drive-file';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
|
||||
desc: {
|
||||
'ja-JP': '指定したドライブのフォルダを削除します。',
|
||||
'en-US': 'Delete specified folder of drive.'
|
||||
},
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-write',
|
||||
|
||||
params: {
|
||||
folderId: $.type(ID).note({
|
||||
desc: {
|
||||
'ja-JP': '対象のフォルダID',
|
||||
'en-US': 'Target folder ID'
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
// Get folder
|
||||
const folder = await DriveFolder
|
||||
.findOne({
|
||||
_id: ps.folderId,
|
||||
userId: user._id
|
||||
});
|
||||
|
||||
if (folder === null) {
|
||||
return rej('folder-not-found');
|
||||
}
|
||||
|
||||
const [childFoldersCount, childFilesCount] = await Promise.all([
|
||||
DriveFolder.count({ parentId: folder._id }),
|
||||
DriveFile.count({ 'metadata.folderId': folder._id })
|
||||
]);
|
||||
|
||||
if (childFoldersCount !== 0 || childFilesCount !== 0) {
|
||||
return rej('has-child-contents');
|
||||
}
|
||||
|
||||
await DriveFolder.remove({ _id: folder._id });
|
||||
|
||||
// Publish folderCreated event
|
||||
publishDriveStream(user._id, 'folderDeleted', folder._id);
|
||||
|
||||
res();
|
||||
});
|
||||
@@ -1,26 +1,38 @@
|
||||
import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
||||
import DriveFolder, { pack } from '../../../../../models/drive-folder';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
import getParams from '../../../get-params';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
|
||||
desc: {
|
||||
'ja-JP': '指定したドライブのフォルダの情報を取得します。'
|
||||
'ja-JP': '指定したドライブのフォルダの情報を取得します。',
|
||||
'en-US': 'Get specified folder of drive.'
|
||||
},
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-read'
|
||||
kind: 'drive-read',
|
||||
|
||||
params: {
|
||||
folderId: $.type(ID).note({
|
||||
desc: {
|
||||
'ja-JP': '対象のフォルダID',
|
||||
'en-US': 'Target folder ID'
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'folderId' parameter
|
||||
const [folderId, folderIdErr] = $.type(ID).get(params.folderId);
|
||||
if (folderIdErr) return rej('invalid folderId param');
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
// Get folder
|
||||
const folder = await DriveFolder
|
||||
.findOne({
|
||||
_id: folderId,
|
||||
_id: ps.folderId,
|
||||
userId: user._id
|
||||
});
|
||||
|
||||
|
||||
@@ -2,8 +2,11 @@ import $ from 'cafy'; import ID from '../../../../../misc/cafy-id';
|
||||
import DriveFolder, { isValidFolderName, pack } from '../../../../../models/drive-folder';
|
||||
import { publishDriveStream } from '../../../../../stream';
|
||||
import { ILocalUser } from '../../../../../models/user';
|
||||
import getParams from '../../../get-params';
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
|
||||
desc: {
|
||||
'ja-JP': '指定したドライブのフォルダの情報を更新します。',
|
||||
'en-US': 'Update specified folder of drive.'
|
||||
@@ -11,18 +14,40 @@ export const meta = {
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'drive-write'
|
||||
kind: 'drive-write',
|
||||
|
||||
params: {
|
||||
folderId: $.type(ID).note({
|
||||
desc: {
|
||||
'ja-JP': '対象のフォルダID',
|
||||
'en-US': 'Target folder ID'
|
||||
}
|
||||
}),
|
||||
|
||||
name: $.str.optional.pipe(isValidFolderName).note({
|
||||
desc: {
|
||||
'ja-JP': 'フォルダ名',
|
||||
'en-US': 'Folder name'
|
||||
}
|
||||
}),
|
||||
|
||||
parentId: $.type(ID).optional.nullable.note({
|
||||
desc: {
|
||||
'ja-JP': '親フォルダID',
|
||||
'en-US': 'Parent folder ID'
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
// Get 'folderId' parameter
|
||||
const [folderId, folderIdErr] = $.type(ID).get(params.folderId);
|
||||
if (folderIdErr) return rej('invalid folderId param');
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
// Fetch folder
|
||||
const folder = await DriveFolder
|
||||
.findOne({
|
||||
_id: folderId,
|
||||
_id: ps.folderId,
|
||||
userId: user._id
|
||||
});
|
||||
|
||||
@@ -30,22 +55,16 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
||||
return rej('folder-not-found');
|
||||
}
|
||||
|
||||
// Get 'name' parameter
|
||||
const [name, nameErr] = $.str.optional.pipe(isValidFolderName).get(params.name);
|
||||
if (nameErr) return rej('invalid name param');
|
||||
if (name) folder.name = name;
|
||||
if (ps.name) folder.name = ps.name;
|
||||
|
||||
// Get 'parentId' parameter
|
||||
const [parentId, parentIdErr] = $.type(ID).optional.nullable.get(params.parentId);
|
||||
if (parentIdErr) return rej('invalid parentId param');
|
||||
if (parentId !== undefined) {
|
||||
if (parentId === null) {
|
||||
if (ps.parentId !== undefined) {
|
||||
if (ps.parentId === null) {
|
||||
folder.parentId = null;
|
||||
} else {
|
||||
// Get parent folder
|
||||
const parent = await DriveFolder
|
||||
.findOne({
|
||||
_id: parentId,
|
||||
_id: ps.parentId,
|
||||
userId: user._id
|
||||
});
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ export const meta = {
|
||||
|
||||
export default (params: any) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
const hashtags = await Hashtag
|
||||
.find({
|
||||
|
||||
@@ -26,7 +26,7 @@ export const meta = {
|
||||
|
||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
const message = await Message.findOne({
|
||||
_id: ps.messageId,
|
||||
|
||||
@@ -49,6 +49,7 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
|
||||
swPublickey: config.sw ? config.sw.public_key : null,
|
||||
hidedTags: (me && me.isAdmin) ? meta.hidedTags : undefined,
|
||||
bannerUrl: meta.bannerUrl,
|
||||
maxNoteTextLength: config.maxNoteTextLength,
|
||||
|
||||
features: {
|
||||
registration: !meta.disableRegistration,
|
||||
|
||||
@@ -56,7 +56,7 @@ export const meta = {
|
||||
|
||||
export default (params: any) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
// Check if both of sinceId and untilId is specified
|
||||
if (ps.sinceId && ps.untilId) {
|
||||
|
||||
49
src/server/api/endpoints/notes/featured.ts
Normal file
49
src/server/api/endpoints/notes/featured.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import $ from 'cafy';
|
||||
import Note from '../../../../models/note';
|
||||
import { packMany } from '../../../../models/note';
|
||||
import { ILocalUser } from '../../../../models/user';
|
||||
import getParams from '../../get-params';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
'ja-JP': 'Featuredな投稿を取得します。',
|
||||
'en-US': 'Get featured notes.'
|
||||
},
|
||||
|
||||
requireCredential: false,
|
||||
|
||||
params: {
|
||||
limit: $.num.optional.range(1, 30).note({
|
||||
default: 10,
|
||||
desc: {
|
||||
'ja-JP': '最大数'
|
||||
}
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
export default async (params: any, user: ILocalUser) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
|
||||
const day = 1000 * 60 * 60 * 24;
|
||||
|
||||
const notes = await Note
|
||||
.find({
|
||||
createdAt: {
|
||||
$gt: new Date(Date.now() - day)
|
||||
},
|
||||
deletedAt: null,
|
||||
visibility: { $in: ['public', 'home'] }
|
||||
}, {
|
||||
limit: ps.limit,
|
||||
sort: {
|
||||
score: -1
|
||||
},
|
||||
hint: {
|
||||
score: -1
|
||||
}
|
||||
});
|
||||
|
||||
return await packMany(notes, user);
|
||||
};
|
||||
@@ -36,7 +36,7 @@ export const meta = {
|
||||
|
||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
// Check if both of sinceId and untilId is specified
|
||||
if (ps.sinceId && ps.untilId) {
|
||||
|
||||
@@ -111,7 +111,7 @@ export const meta = {
|
||||
|
||||
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
if (ps.includeUserUsernames != null) {
|
||||
const ids = erase(null, await Promise.all(ps.includeUserUsernames.map(async (username) => {
|
||||
|
||||
@@ -32,7 +32,7 @@ export const meta = {
|
||||
|
||||
export default (params: any, user: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
// Fetch the list
|
||||
const userList = await UserList.findOne({
|
||||
|
||||
@@ -110,7 +110,7 @@ export const meta = {
|
||||
|
||||
export default (params: any, me: ILocalUser) => new Promise(async (res, rej) => {
|
||||
const [ps, psErr] = getParams(meta, params);
|
||||
if (psErr) throw psErr;
|
||||
if (psErr) return rej(psErr);
|
||||
|
||||
if (ps.userId === undefined && ps.username === undefined) {
|
||||
return rej('userId or username is required');
|
||||
|
||||
@@ -12,7 +12,9 @@ export default function <T extends Defs>(defs: T, params: any): [{
|
||||
Object.keys(defs.params).some(k => {
|
||||
const [v, e] = defs.params[k].get(params[k]);
|
||||
if (e) {
|
||||
err = e;
|
||||
err = new Error(e.message);
|
||||
err.name = 'INVALID_PARAM';
|
||||
(err as any).param = k;
|
||||
return true;
|
||||
} else {
|
||||
if (v === undefined && defs.params[k].data.default) {
|
||||
|
||||
@@ -28,6 +28,8 @@ import perUserNotesChart from '../../chart/per-user-notes';
|
||||
|
||||
import { erase, unique } from '../../prelude/array';
|
||||
import insertNoteUnread from './unread';
|
||||
import registerInstance from '../register-instance';
|
||||
import Instance from '../../models/instance';
|
||||
|
||||
type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
|
||||
|
||||
@@ -170,6 +172,20 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
|
||||
notesChart.update(note, true);
|
||||
perUserNotesChart.update(user, note, true);
|
||||
|
||||
// Register host
|
||||
if (isRemoteUser(user)) {
|
||||
registerInstance(user.host).then(i => {
|
||||
Instance.update({ _id: i._id }, {
|
||||
$inc: {
|
||||
notesCount: 1
|
||||
}
|
||||
});
|
||||
|
||||
// TODO
|
||||
//perInstanceChart.newNote();
|
||||
});
|
||||
}
|
||||
|
||||
// ハッシュタグ登録
|
||||
tags.map(tag => registerHashtag(user, tag));
|
||||
|
||||
@@ -298,7 +314,8 @@ async function renderActivity(data: Option, note: INote) {
|
||||
function incRenoteCount(renote: INote) {
|
||||
Note.update({ _id: renote._id }, {
|
||||
$inc: {
|
||||
renoteCount: 1
|
||||
renoteCount: 1,
|
||||
score: 1
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -551,8 +568,7 @@ function saveQuote(renote: INote, note: INote) {
|
||||
Note.update({ _id: renote._id }, {
|
||||
$push: {
|
||||
_quoteIds: note._id
|
||||
},
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -36,12 +36,12 @@ export default async (user: IUser, note: INote, reaction: string) => new Promise
|
||||
|
||||
res();
|
||||
|
||||
const inc: {[key: string]: number} = {};
|
||||
inc[`reactionCounts.${reaction}`] = 1;
|
||||
|
||||
// Increment reactions count
|
||||
await Note.update({ _id: note._id }, {
|
||||
$inc: inc
|
||||
$inc: {
|
||||
[`reactionCounts.${reaction}`]: 1,
|
||||
score: 1
|
||||
}
|
||||
});
|
||||
|
||||
perUserReactionsChart.update(user, note);
|
||||
|
||||
22
src/services/register-instance.ts
Normal file
22
src/services/register-instance.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import Instance, { IInstance } from '../models/instance';
|
||||
import federationChart from '../chart/federation';
|
||||
|
||||
export default async function(host: string): Promise<IInstance> {
|
||||
if (host == null) return null;
|
||||
|
||||
const index = await Instance.findOne({ host });
|
||||
|
||||
if (index == null) {
|
||||
const i = await Instance.insert({
|
||||
host,
|
||||
caughtAt: new Date(),
|
||||
system: null // TODO
|
||||
});
|
||||
|
||||
federationChart.update(true);
|
||||
|
||||
return i;
|
||||
} else {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user